This file was created from the following Jupyter-notebook: pipes.ipynb
Interactive version: Binder badge

Pipeline-based processing in pypillometry

[4]:
%load_ext autoreload
%autoreload 2
import sys
sys.path.insert(0,"..")
import pypillometry as pp

The autoreload extension is already loaded. To reload it, use:
  %reload_ext autoreload

pypillometry implements a pipeline-like approach where each operation executed on a PupilData-object returns a copy of the (modified) object. This enables the “chaining” of commands as follows:

[5]:
# load a small example dataset
d=pp.get_example_data("rlmw_002_short")
d=d.pupil_blinks_detect()\
    .blinks_merge()\
    .pupil_lowpass_filter(3)\
    .downsample(50)
/home/mmi041/Dropbox/work/projects/pupil/pypillometry/docs/../pypillometry/signal/baseline.py:144: RuntimeWarning: Mean of empty slice
  y2=np.nanmean(y_padded.reshape(-1,R), axis=1)

This command loads a data-file (test.pd), applies a 3Hz low-pass filter to it, downsamples the signal to 50 Hz, detects blinks in the signal and merges short, successive blinks together. The final result of this processing-pipeline is stored in object d.

Here, for better visibility, we put each operation in a separate line. For that to work, we need to tell Python that the line has not yet ended at the end of the statement which we achieve by putting a backslash \ at the end of each (non-final) line.

We can get a useful summary of the dataset and the operations applied to it by simply printing it:

[6]:
print(d)
EyeData(test short, 212.3KiB):
 n                   : 2047
 sampling_rate       : 50
 data                : ['left_x', 'left_y', 'left_pupil', 'right_x', 'right_y', 'right_pupil']
 nevents             : 40
 screen_limits       : ((0, 1280), (0, 1024))
 physical_screen_size: (30, 20)
 screen_eye_distance : not set
 duration_minutes    : 0.6823333333333333
 start_min           : 0.00015
 end_min             : 0.6820666666666667
 parameters          : {}
 glimpse             : EyeDataDict(vars=6,n=2047,shape=(2047,)):
  left_x (float64): 656.5500000000001, 656.14, 654.0400000000001, 652.0199999999999, 650.4...
  left_y (float64): 597.54, 591.5, 588.3899999999999, 593.7800000000001, 598.3199999999999...
  left_pupil (float64): 1128.8869458721226, 1133.8058182761888, 1139.7069289167484, 1146.4462392731034, 1153.8027812522362...
  right_x (float64): 775.56, 777.14, 777.08, 776.99, 778.72...
  right_y (float64): 597.31, 601.3, 600.48, 595.3399999999999, 595.1...
  right_pupil (float64): 954.2414624419623, 958.9101375371407, 963.632119267214, 968.2405296620748, 972.6750179976658...

 eyes                : ['left', 'right']
 nblinks             : {'left_pupil': 11, 'right_pupil': 11}
 blinks              : {'left': 11 intervals, 2154.55 +/- 3588.46, [460.00, 13460.00], 'right': 11 intervals, 1005.45 +/- 718.34, [320.00, 3080.00]}
 params              : {}
 History:
 *
 └ fill_time_discontinuities()
  └ reset_time()
   └ pupil_blinks_detect()
    └ blinks_merge()
     └ pupil_lowpass_filter(3)
      └ downsample(50)

We see that sampling rate, number of datapoints and more is automatically printed along with the history of all operations applied to the dataset. This information can also be retrieved separately and in a form useful for further processing the function summary() which returns the information in the form of a dict:

[7]:
d.summary()
[7]:
{'name': 'test short',
 'n': 2047,
 'sampling_rate': 50,
 'data': ['left_x',
  'left_y',
  'left_pupil',
  'right_x',
  'right_y',
  'right_pupil'],
 'nevents': 40,
 'screen_limits': ((0, 1280), (0, 1024)),
 'physical_screen_size': (30, 20),
 'screen_eye_distance': 'not set',
 'duration_minutes': 0.6823333333333333,
 'start_min': 0.00015,
 'end_min': 0.6820666666666667,
 'parameters': '{}',
 'glimpse': 'EyeDataDict(vars=6,n=2047,shape=(2047,)): \n  left_x (float64): 656.5500000000001, 656.14, 654.0400000000001, 652.0199999999999, 650.4...\n  left_y (float64): 597.54, 591.5, 588.3899999999999, 593.7800000000001, 598.3199999999999...\n  left_pupil (float64): 1128.8869458721226, 1133.8058182761888, 1139.7069289167484, 1146.4462392731034, 1153.8027812522362...\n  right_x (float64): 775.56, 777.14, 777.08, 776.99, 778.72...\n  right_y (float64): 597.31, 601.3, 600.48, 595.3399999999999, 595.1...\n  right_pupil (float64): 954.2414624419623, 958.9101375371407, 963.632119267214, 968.2405296620748, 972.6750179976658...\n',
 'eyes': ['left', 'right'],
 'nblinks': {'left_pupil': 11, 'right_pupil': 11},
 'blinks': {'left': 11 intervals, 2154.55 +/- 3588.46, [460.00, 13460.00],
  'right': 11 intervals, 1005.45 +/- 718.34, [320.00, 3080.00]},
 'params': '{}'}

The history is internally stored in PupilData’s history member and can be applied to another object for convenience. That way, a pipeline can be developed on a single dataset and later be transferred to a whole folder of other (similar) datasets.

This file was created from the following Jupyter-notebook: pipes.ipynb
Interactive version: Binder badge