Code Repository
Deep learning-based pupil model predicts time and wavelength dependent light responses
This repository provides the official implementation of a deep learning-based temporal pupil light response model proposed in the article "Deep learning-based pupil model predicts time and wavelength-dependent light responses" authored by Babak Zandi and Tran Quoc Khanh from the Technical University of Darmstadt.
Pupil light response models aim to predict the pupil diameter in millimetres using a light spectrum or derived photometric quantities. State-of-the-art pupil models can only calculate a static diameter at an equilibrium state with the luminance as a main dependent parameter [1]. A recent work showed that such L- and M-cone based pupil models have prediction errors of up to 1.21 mm, mainly caused by the missing time dependence of current pupil functions and the lack of integrating the contribution of the intrinsically photosensitive ganglion cells [2].
We developed the first concept of a pupil model, which can predict the temporal pupil diameter up to 300 seconds for chromatic ( = 450 nm, = 530 nm, = 610 nm, = 660 nm) and polychromatic spectra (~2000 K, ~5000 K, ~10 000 K) at ~100 cd/m2. The differential equation of Fan & Yao [3] was combined with the Watson & Yellot model [1] and feed-forward neural networks to reconstruct the temporal pupil diameter caused by sustained light stimuli. For this, light metrics such as the luminance and a respective CIExy-2° chromaticity coordinate of a light stimulus are used as features to predict model parameters of a base-function. Next, the predicted model parameters can be fed into the basis-function, which finally describes the corresponding temporal pupil light response with a mean absolute error of less than 0.1 mm. Our approach is data-driven through the integration of neural networks. Compared to existing approaches, we can predict the pupil diameter's time course from light metrics for the first time. Furthermore, the modelling approach is flexible, allowing a continuous improvement of the model. Currently, the prediction space is limited, but the model quality can be enhanced with additional data due to the integration of neural networks. We are currently working on a pupil light response database to train the model for more light stimuli. Further details are explained in our publication [4]. In the future, it is conceivable that further input parameters will be added to the model in order to integrate cognitive parameters that could influence pupil diameter.
📧 Correspondence: zandi@lichttechnik.tu-darmstadt.de
Google Scholar Profile: Babak Zandi
Twitter: @BkZandi
This repository contains the neural network models in the folder Python/A03_Models/FF
, which were trained with an intrasubject TrainData_Individual_Subject.csv
and intersubject TrainData_Many_Subject.csv
pupil light response dataset. The combined model itself is implemented as in the function NNCombinedModel.m
using Mathworks Matlab. The function predicts the temporal pupil diameter from three different light metrics variants as input parameters:
- Variant 1: Luminance, CIExy-2° coordinates.
- Variant 2: α-opic radiance values of the L-cones , M-cones, S-cone and ipRGCs.
- Variant 3: Luminance, CIExy-2°and melanopic radiance.
The neural networks can be trained optionally again with the individual input parameter variants using the Python/Main.py
file with the argument --Variant
which defines the model's input value combination. We already uploaded the trained models to this repository. Therefore we recommend this new training step only if you need to train your own models based on your custom datasets. The following command trains the neural network with the TrainData_Many_Subject.csv
dataset using the respective hyperparameters from our article:
- Variant 1:
python Main.py --Variant 1
- Variant 2:
python Main.py --Variant 2
- Variant 3:
python Main.py --Variant 3
Before running the training command, you have to make the following new folders Python/A04_Results_Training/01_Plots/
and Python/A04_Results_Training/02_Data/
in which the training results will be logged. The checkpoint-models will be saved in the folder Python/A02_Models/FF
. To train the model with the TrainData_Individual_Subject.csv
dataset you need to change the line pd.read_csv('A00_Data/TrainData_Many_Subject.csv')
to pd.read_csv('A00_Data/TrainData_Individual_Subject.csv')
in the file Python/A01_Functions/ReadData.py
. The programming code of the neural networks can be found in Python/A02_Networks/FeedForward.py
.
For implementing the neural networks, we have used PyTorch with the amazing pytorch_lightning
framework. The demo code in this repository requires Python 3, PyTorch 1.4+, PyTorch Lightning 0.7+, Numpy, Pandas and Mathworks Matlab.
The combined model is structured so that the neural networks determine the respective model parameters of the base-function from light metrics with Variant 1
, Variant 2
or Variant 3
(see Figure). The model parameters are used in Fan & Yao's differential equation for the phasic pupil diameter and in a polynomial equation to describe the tonic response. We use the Watson & Yellot model to calculate the pupil's starting point with which the solution of the differential equation is calculated with an ode45
solver. In the Watson & Yellot model, the adaptation stimulus' luminance should be used, which is usually presented in pupil light response investigations before the main stimulus. Finally, the phasic and tonic pupil response is combined with two masking functions, resulting in the reconstructed temporal pupil diameter.
The function for predicting the model parameters from the light metrics is implemented in the Python file Python/CalcParam.py
. The function has the following arguments:
--Condition
: Definition of which neural networks should be used to predict the base-function's model parameters. The conditionSingle
employs the neural networks which were trained with the intrasubject dataTrainData_Individual_Subject.csv
. The valueMulti
uses the neural networks which were trained with the intersubject dataTrainData_Many_Subject.csv
.--Variant
: The number of the used input variant.
The respective light metrics need to be defined as additional arguments, which differ depending on the Variant
. Thus, the following calls with double
values are possible:
Variant 1 (Luminance L
, CIExy-2° chromaticity coordinates Fx
and Fx
)
python CalcParam.py --Condition Single --Variant 1 --L doubleValue --Fx doubleValue --Fy doubleValue
Variant 2 (α-opic radiance values of the L-cones Lcone
, M-cones Mcone
, S-cone Scone
and ipRGCs Mel
)
python CalcParam.py --Condition Single --Variant 2 --Lcone doubleValue --Mcone doubleValue --Scone doubleValue --Mel doubleValue`
Variant 3: (Luminance L
, CIExy-2° chromaticity coordinates Fx
and Fy
)
python CalcParam.py --Condition Single --Variant 3 --L doubleValue --Fx doubleValue --Fy doubleValue --Mel doubleValue
After the calling CalcParam.py
, the model parameters are saved in the file Python/output.csv
. Note that the values double
must be given normalised. The normalisation is already done in the file Functions/NNCombinedModel.m
. We recommend calling the entire model from Matlab, as it is described in the section Getting Started.
The combined model can be run via the Matlab script Functions/NNCombinedModel.m
. Before the script can be used, a valid path to your Python executable must be provided since the function Python/CalcParam.py
is called from the Matlab environment. For this, change this line of code python_path = '/Users/papillon/opt/anaconda3/envs/ML/bin/python3';
, which is located in the Functions/NNCombinedModel.m
file in line 4. Demo codes of how to call the function for the different stimulus values are available in the Main.m
file. Note, that the input parameters are restricted to those used in the Main.m
file, as the model is currently not at a state for predicting model parameters beyond the training data. For instance, to predict the pupil light response from the single observer caused by LED spectra with a peak wavelength of 450 nm, 530 nm, 610 nm, 660 nm, 2000 K, 5000 K and 10000 K, you can use the following code snippet in Mathworks Matlab:
% Set the plot preferences (optional)
set(groot, 'DefaultLineLineWidth', 1);
set(groot, 'DefaultAxesLineWidth', 1);
set(groot, 'DefaultAxesFontName', 'CMU Serif');
set(groot, 'DefaultAxesFontSize', 14);
set(groot, 'DefaultAxesFontWeight', 'normal');
set(groot, 'DefaultAxesXMinorTick', 'on');
set(groot, 'DefaultAxesXGrid', 'on');
set(groot, 'DefaultAxesYGrid', 'on');
set(groot, 'DefaultAxesGridLineStyle', ':');
set(groot, 'DefaultAxesUnits', 'normalized');
set(groot, 'DefaultAxesOuterPosition',[0, 0, 1, 1]);
set(groot, 'DefaultFigureUnits', 'inches');
set(groot, 'DefaultFigurePaperPositionMode', 'manual');
set(groot, 'DefaultFigurePosition', [0.1, 11, 8.5, 4.5]);
set(groot, 'DefaultFigurePaperUnits', 'inches');
set(groot, 'DefaultFigurePaperPosition', [0.1, 11, 8.5, 4.5]);
% 0. Load data, add all essential folder to path
clc; clear; load("Data");
addpath("Data");
addpath("Functions");
addpath("Python");
% 1. Predict & Plot PLR from model with neural network - Single subject (Variant 1): L, CIExy-2°
% Light conditions in each col: '450nm'; '530nm'; '610nm'; '660nm'; '2000K'; '5000K'; '10000K'
Luminance = [99.73; 100.12; 100.16; 99.97; 100.17; 100.10; 99.83];
CIE_x = [0.15811; 0.18661; 0.67903; 0.71701; 0.53305; 0.34538; 0.28549];
CIE_y = [0.02006; 0.73928; 0.32039; 0.27995; 0.42288; 0.34976; 0.2769];
hparam.Condition = 'Single';
hparam.Variant = 1;
% Light conditino #1
Index = 1;
hparam.Stimuli = [Luminance(Index), CIE_x(Index), CIE_y(Index)];
[out, Predicted1] = NNCombinedModel(hparam);
% Light conditino #2
Index = 2;
hparam.Stimuli = [Luminance(Index), CIE_x(Index), CIE_y(Index)];
[out, Predicted2] = NNCombinedModel(hparam);
% Light conditino #3
Index = 3;
hparam.Stimuli = [Luminance(Index), CIE_x(Index), CIE_y(Index)];
[out, Predicted3] = NNCombinedModel(hparam);
% Light conditino #4
Index = 4;
hparam.Stimuli = [Luminance(Index), CIE_x(Index), CIE_y(Index)];
[out, Predicted4] = NNCombinedModel(hparam);
% Light conditino #5
Index = 5;
hparam.Stimuli = [Luminance(Index), CIE_x(Index), CIE_y(Index)];
[out, Predicted5] = NNCombinedModel(hparam);
% Light conditino #6
Index = 6;
hparam.Stimuli = [Luminance(Index), CIE_x(Index), CIE_y(Index)];
[out, Predicted6] = NNCombinedModel(hparam);
% Light conditino #7
Index = 7;
hparam.Stimuli = [Luminance(Index), CIE_x(Index), CIE_y(Index)];
[out, Predicted7] = NNCombinedModel(hparam);
% Plot predicted PLR against measured PLR
figure;
t = tiledlayout(3,3, 'Padding',"none", "TileSpacing","normal");
set(gcf, 'Position', [0.1, 11, 14, 8]);
t.Padding = "none";
t.TileSpacing = "compact";
LinewidthModel = 1;
ax1 = nexttile;
plot(linspace(0, 300, 30001)', Pupillendaten_Wide_OneSubject.Spektrum450nm.Median, 'k'); hold on;
plot(Predicted1.Time, Predicted1.CombinedModel, 'b', 'LineWidth', LinewidthModel);
xlabel('Time in seconds'); ylabel('PD in mm'); title({'Intrasubject (450 nm)' 'L, CIExy 2°'})
legend({'Measured PD', 'Predicted PD'},'Location','northwest','NumColumns', 2)
ax2 = nexttile;
plot(linspace(0, 300, 30001)', Pupillendaten_Wide_OneSubject.Spektrum530nm.Median, 'k'); hold on;
plot(Predicted2.Time, Predicted2.CombinedModel, 'b', 'LineWidth', LinewidthModel);
xlabel('Time in seconds'); ylabel('PD in mm'); title({'Intrasubject (530 nm)' 'L, CIExy 2°'})
ax3 = nexttile;
plot(linspace(0, 300, 30001)', Pupillendaten_Wide_OneSubject.Spektrum610nm.Median, 'k'); hold on;
plot(Predicted3.Time, Predicted3.CombinedModel, 'b', 'LineWidth', LinewidthModel);
xlabel('Time in seconds'); ylabel('PD in mm'); title({'Intrasubject (610 nm)' 'L, CIExy 2°'})
ax4 = nexttile;
plot(linspace(0, 300, 30001)', Pupillendaten_Wide_OneSubject.Spektrum660nm.Median, 'k'); hold on;
plot(Predicted4.Time, Predicted4.CombinedModel, 'b', 'LineWidth', LinewidthModel);
xlabel('Time in seconds'); ylabel('PD in mm'); title({'Intrasubject (660 nm)' 'L, CIExy 2°'})
ax5 = nexttile;
plot(linspace(0, 300, 30001)', Pupillendaten_Wide_OneSubject.CCT2000K.Median, 'k'); hold on;
plot(Predicted5.Time, Predicted5.CombinedModel, 'b', 'LineWidth', LinewidthModel);
xlabel('Time in seconds'); ylabel('PD in mm'); title({'Intrasubject (2000 K)' 'L, CIExy 2°'})
ax6 = nexttile;
plot(linspace(0, 300, 30001)', Pupillendaten_Wide_OneSubject.CCT5000K.Median, 'k'); hold on;
plot(Predicted6.Time, Predicted6.CombinedModel, 'b', 'LineWidth', LinewidthModel);
xlabel('Time in seconds'); ylabel('PD in mm'); title({'Intrasubject (5000 K)' 'L, CIExy 2°'})
ax7 = nexttile;
plot(linspace(0, 300, 30001)', Pupillendaten_Wide_OneSubject.CCT10000K.Median, 'k'); hold on;
plot(Predicted7.Time, Predicted7.CombinedModel, 'b', 'LineWidth', LinewidthModel);
xlabel('Time in seconds'); ylabel('PD in mm'); title({'Intrasubject (10 000 K)' 'L, CIExy 2°'})
set(ax1, 'YLim', [1, 5], 'XLim', [0, 300]); grid(ax1, 'off');
set(ax2, 'YLim', [1, 5], 'XLim', [0, 300]); grid(ax1, 'off');
set(ax3, 'YLim', [1, 5], 'XLim', [0, 300]); grid(ax1, 'off');
set(ax4, 'YLim', [1, 5], 'XLim', [0, 300]); grid(ax1, 'off');
set(ax5, 'YLim', [1, 5], 'XLim', [0, 300]); grid(ax1, 'off');
set(ax6, 'YLim', [1, 5], 'XLim', [0, 300]); grid(ax1, 'off');
set(ax7, 'YLim', [1, 5], 'XLim', [0, 300]); grid(ax1, 'off');
In addition to the combined model, we provide a graphical user interface that can adjust the base function's model parameters freely without the neural networks. We used the GUI to fit the base function to our measured pupil data and to create the training data for the neural networks. The GUI can be started via the file GUI/PupilModel_FittingParam.mlapp
from Matlab. In the GUI, the measured pupil data for the respective light stimuli are stored and the model parameters can be freely adjusted.
For the interested readership, we highly recommend to check out the Matlab implementation of the time-independent classical L- and M-cone based pupil models. The models were implemented by William Wheatley & Manuel Spitschan based on the publication from Watson & Yellot [1]:
https://github.com/spitschan/WatsonYellott2012_PupilSize
An analysis of the prediction errors of such classical L- and M-cone based pupil models was performed in the following publication:
Zandi, B., Klabes, J. & Khanh, T.Q. Prediction accuracy of L- and M-cone based human pupil light models. Sci Rep 10, 10988 (2020). https://doi.org/10.1038/s41598-020-67593-3
Please consider to cite our work if you find this repository or our results useful for your research:
Zandi, B., Khanh, T.Q. Deep learning-based pupil model predicts time and spectral dependent light responses. Sci Rep 11, 841 (2021). https://doi.org/10.1038/s41598-020-79908-5
@article{Zandi2021,
author = {Zandi, Babak and Khanh, Tran Quoc},
doi = {10.1038/s41598-020-79908-5},
issn = {2045-2322},
journal = {Scientific Reports},
number = {1},
pages = {841},
title = {{Deep learning-based pupil model predicts time and spectral dependent light responses}},
url = {https://doi.org/10.1038/s41598-020-79908-5},
volume = {11},
year = {2021}}
[1]: Watson, A. B. & Yellott, J. I. A unified formula for light-adapted pupil size. J. Vis. 12, 1–16 (2012).
[2]: Zandi, B., Klabes, J. & Khanh, T.Q. Prediction accuracy of L- and M-cone based human pupil light models. Sci Rep 10, 10988 (2020). https://doi.org/10.1038/s41598-020-67593-3
[3]: Xiaofei Fan & Gang Yao. Modeling Transient Pupillary Light Reflex Induced by a Short Light Flash. IEEE Trans. Biomed. Eng. 58, 36–42 (2011).
[4]: Zandi, B., Khanh, T.Q. Deep learning-based pupil model predicts time and spectral dependent light responses. Sci Rep 11, 841 (2021). https://doi.org/10.1038/s41598-020-79908-5
This work is licensed under a Creative Commons Attribution 4.0 International License. The code is licensed under .