1010from .pupil import *
1111
1212def generate_pupil_data (event_onsets , fs = 1000 , pad = 5000 , baseline_lowpass = 0.2 ,
13+ scale_signal = (0 ,1 ), scale_evoked = (0.2 ,0.05 ),
1314 evoked_response_perc = 0.02 , response_fluct_sd = 1 ,
1415 prf_npar = (10.35 ,0 ), prf_tmax = (917.0 ,0 ),
15- prop_spurious_events = 0.2 , noise_amp = 0.0005 ):
16+ num_spurious_events = 0 , noise_amp = 0.01 ):
1617 """
1718 Generate artificial pupil data as a sum of slow baseline-fluctuations
1819 on which event-evoked responses are "riding".
@@ -30,16 +31,12 @@ def generate_pupil_data(event_onsets, fs=1000, pad=5000, baseline_lowpass=0.2,
3031 baseline_lowpass: float
3132 cutoff for the lowpass-filter that defines the baseline
3233 (highest allowed frequency in the baseline fluctuations)
33-
34- evoked_response_perc: float
35- amplitude of the pupil-response as proportion of the baseline
36-
37- response_fluct_sd: float
38- How much do the amplitudes of the individual events fluctuate?
39- This is determined by drawing each individual pupil-response to
40- a single event from a (positive) normal distribution with mean as determined
41- by `evoked_response_perc` and sd `response_fluct_sd` (in units of
42- `evoked_response_perc`).
34+ scale_signal: (float,float)
35+ scale of the final signal (mean and SD); default is (0,1), i.e.,
36+ Z-scored data
37+ scale_evoked: (float,float)
38+ amplitude of the pupil-response (mean and SD) in Z-score units;
39+ responses<0 will be set to zero (truncated)
4340 prf_npar: tuple (float,float)
4441 (mean,std) of the npar parameter from :py:func:`pypillometry.pupil.pupil_kernel()`.
4542 If the std is exactly zero, then the mean is used for all pupil-responses.
@@ -48,13 +45,12 @@ def generate_pupil_data(event_onsets, fs=1000, pad=5000, baseline_lowpass=0.2,
4845 (mean,std) of the tmax parameter from :py:func:`pypillometry.pupil.pupil_kernel()`.
4946 If the std is exactly zero, then the mean is used for all pupil-responses.
5047 If the std is positive, tmax is taken i.i.d. from ~ normal(mean,std) for each event.
51- prop_spurious_events: float
52- Add random events to the pupil signal. `prop_spurious_events` is expressed
53- as proportion of the number of real events.
54-
48+ num_spurious_events: float
49+ Add random events to the pupil signal. These are placed at random locations
50+ throughout the dataset.
5551 noise_amp: float
5652 Amplitude of random gaussian noise that sits on top of the simulated signal.
57- Expressed in units of mean baseline pupil diameter.
53+ Expressed in SD- units before scaling up the signal
5854
5955
6056 Returns
@@ -96,14 +92,15 @@ def generate_pupil_data(event_onsets, fs=1000, pad=5000, baseline_lowpass=0.2,
9692 # create baseline-signal
9793 slack = int (0.50 * n ) # add slack to avoid edge effects of the filter
9894 x0 = butter_lowpass_filter (np .random .rand (n + slack ), baseline_lowpass , fs , 2 )[slack :(n + slack )]
99- x0 = x0 * 1000 + 5000 # scale it up to a scale as usually obtained from eyetracker
100-
95+ x0 = (x0 - np .mean (x0 ))/ np .std (x0 ) # Z-score
10196
10297 ### real events regressor
10398 ## scaling
10499 event_ix = (np .array (event_onsets )/ 1000. * fs ).astype (int )
105100 #a, b = (myclip_a - my_mean) / my_std, (myclip_b - my_mean) / my_std
106- delta_weights = stats .truncnorm .rvs (- 1 / response_fluct_sd ,np .inf , loc = 1 , scale = response_fluct_sd , size = event_ix .size )
101+ a = (0 - scale_evoked [0 ])/ scale_evoked [1 ]
102+ b = np .inf
103+ delta_weights = stats .truncnorm .rvs (a ,b , loc = scale_evoked [0 ], scale = scale_evoked [1 ], size = event_ix .size )
107104 x1 = np .zeros_like (sy )
108105
109106 for i ,ev in enumerate (event_onsets ):
@@ -113,9 +110,9 @@ def generate_pupil_data(event_onsets, fs=1000, pad=5000, baseline_lowpass=0.2,
113110
114111 ## spurious events regressor
115112
116- sp_event_ix = np .random .randint (low = 0 ,high = np .ceil ((T - maxdur - pad )/ 1000. * fs ),size = int ( nevents * prop_spurious_events ))
113+ sp_event_ix = np .random .randint (low = 0 ,high = np .ceil ((T - maxdur - pad )/ 1000. * fs ),size = int ( num_spurious_events ))
117114 sp_events = tx [ sp_event_ix ]
118- n_sp_events = sp_events . size
115+ n_sp_events = num_spurious_events
119116
120117 ## npar
121118 if prf_npar [1 ]== 0 : # deterministic parameter
@@ -131,20 +128,19 @@ def generate_pupil_data(event_onsets, fs=1000, pad=5000, baseline_lowpass=0.2,
131128
132129
133130 ## scaling
134- sp_delta_weights = stats .truncnorm .rvs (- 1 / response_fluct_sd , np . inf , loc = 1 , scale = response_fluct_sd , size = sp_event_ix .size )
131+ sp_delta_weights = stats .truncnorm .rvs (a , b , loc = scale_evoked [ 0 ] , scale = scale_evoked [ 1 ] , size = sp_event_ix .size )
135132 x2 = np .zeros_like (sy )
136133
137134 for i ,ev in enumerate (sp_events ):
138135 # create kernel and delta-functions for events
139136 kernel = pupil_kernel (duration = maxdur ,fs = fs ,npar = npars [i ], tmax = tmaxs [i ])
140137 x2 [sp_event_ix [i ]:(sp_event_ix [i ]+ kernel .size )]= x2 [sp_event_ix [i ]:(sp_event_ix [i ]+ kernel .size )]+ kernel * sp_delta_weights [i ]
141138
142- amp = np .mean (x0 )* evoked_response_perc # mean amplitude for the evoked response
143- noise = noise_amp * np .mean (x0 )* np .random .randn (n )
144-
145- sy = x0 + amp * x1 + amp * x2 + noise
139+ sy = x0 + x1 + x2 + noise_amp * np .random .randn (n )
140+ sy = (sy * scale_signal [1 ])+ scale_signal [0 ] # scale to desired range
141+ x0s = (x0 * scale_signal [1 ])+ scale_signal [0 ]
146142
147- return (tx ,sy ,x0 ,delta_weights )
143+ return (tx ,sy ,x0s ,delta_weights )
148144
149145
150146def get_dataset (ntrials = 100 , isi = 2000 , rtdist = (1000 ,500 ),fs = 1000 ,pad = 5000 , ** kwargs ):
0 commit comments