-
FakePupilData(andFakeGazeData?) -
find a good way to implement units so that we don't constantly get confused by mm/cm etc.s
-
plot_timeseries should rename show_onsets to show_events (and accept True/False in addition to "none", "line", "both")
-
merge_mask should take eye= and variables=
-
make blink-detection better by also using x-y data (implement an EyeData.blinks_detect() function that uses both gaze and pupil)
Porting all things from old PupilData to either GenericEyeData (for functions that operate on all variables) or PupilData for pupil-specific functions.
-
scale()andunscale()are now inGenericEyeDataand can be called on any variable- they use dicts to store separate scaling parameters for each variable/eye
-
get_intervals()is now inGenericEyeData(only depends on events) -
sub_slice()is now inGenericEyeData(operates on all variables simultaneously) -
pupil_lowpass_filter()is now inPupilData -
pupil_smooth_window() -
downsample()- implement inGenericEyeData -
merge_eyes()- implement inGenericEyeDatato combine left/right eyes into a single variable- perhaps implement regression merging?
- blinks
- make the
blinksfield a property so that the blinkmask can be kept in sync -
pupil_blinks_detect()- or can this be also for gaze? Will definitely need different algorithms. So should stick with different names -
blinks_merge()- for is aPupilDatamethod but if there will be blinks in the gaze data at some point, the wholeblinkfunctionality should be moved toGenericEyeData - make a "mask" field for the
EyeDataDictthat is a dict of boolean arrays that can be used to mask out parts of the data for blinks/interpolation? -
pupil_blinks_interpolate()- merge with Mahot function and make one an option for the other
- make the
- baseline/response estimation
-
pupil_estimate_baseline() -
pupil_estimate_response()
-
- statistics per events
- some more general interval processing
- plotting
- rework ERPD class: make it use the EyeDataDict but so that each entry is a 2D np.array that stores all the windows for a given event (have to match all dims)
- multiple inheritance scheme:
GenericEyeDataimplements bookkeeping, history, etc like nowPupilDatainherits fromGenericEyeDataand implements pupil-specific methods working on theEyeDataDictfieldsleft_pupilandright_pupiletcGazeDatainherits fromGenericEyeDataand implements gaze-specific methods working on theEyeDataDictfieldsleft_xandright_yetcEyeDatainherits fromPupilDataandGazeDataand implements methods that work on both pupil and gaze data (e.g., the correction of the pupil by foreshortening)- the beauty of it is that they all work on the
self.datafield which isEyeDataDict, just assuming different fields are present - the plotting could mirror that approach: separate
GazePlotterandPupilPlotterthat are then merged in aEyePlotterclass that inherits both - then it the interface would simply be
d.plotting.plot_xx()for all three classes - what about the events? can they go into the
GenericEyeDataclass?
- Problem with the scheme: When
EyeDatainherits from both classes, it is not clear whether a given function belongs to the gaze- or the pupil-data (this is even worse for the plotting functions)- one solution would be consistent naming of the methods but that kind of defeats the whole purpose of the inheritance
- another solution would be to have
EyeDatanot inherit but keep copies of thePupilDataandGazeDataobjects and delegate the calls to them. But that is even worse. - consistent naming having "pupil" or "gaze" go first so that TAB-completion works:
- scale()/unscale() - scale can be moved to generic, featuring an "eyes" and "variables" argument that specifies which timeseries should be scaled;
- pupil_lowpass_filter()
- pupil_smooth_window()
- pupil_downsample() - or can this be for everything? - yeah, think so
- pupil_estimate_baseline()
- pupil_estimate_response()
- pupil_blinks_detect() - or can this be also for gaze? Will definitely need different algorithms. So should stick with different names
- pupil_blinks_merge()
- pupil_blinks_interpolate() - merge with Mahot function and make one an option for the other; remove plotting from Mahot function but add a function to the
PupilPlotterthat can visualize this - pupil_stat_per_event() - should this be based on the
get_intervals()function instead? yeah! Then it can beget_stat_per_interval()and it can accepteyeandvariableas arguments to determine which timeseries should be used; but then it has to be implemented in both child classes; perhaps implement at theGenericEyeDatalevel and then add a thin wrapper on the child classes that calls the generic function preventing it from using the wrong arguments - get_erpd() should also be reworked: based on the
get_intervals()function and allow to select variables and eyes; has to be called something else likeEyeDataSegmentsor so? Then get_segments() can return one segment-object per eye and variable for further processing- or I build another class that works like
EyeDataDictbut with the segments
- or I build another class that works like
- what about the
FakePupilData? The difference is that it has additional timeseries corresponding to the simulated components of the signal; I can inherit fromPupilDataand implement those on top pretty easily; but I need also aFakePupilPlotterthat can visualize those components- as long as I am clever about implementing the other methods, I can just send a "sim" variable into as 'variable' name so that I don't need to completely reimplement them
pintpackage: for unit conversionloggingmodule for logging and potentially for the history?- use
pytestinstead ofunittest - use a separate
PlotHandlerclass, member of PupilData?- that would enable to use
d.plotting.plot_blinks()and everything could be implemented inplottingwhich would be aPlotHandler - the
selfcould be stored in theobj.plottingobject in the constructor (self.plotting.obj = self) - or
obj.plotting.plot()could usesuper()to get at theselfof thePupilDataobject
- that would enable to use
- it seems best to drop the old
PupilDataclass and implement everything asEyeDatawith theEyeDataDictfor the data- what happens if someone only has x/y data or only pupil data?
- would be nice if those would be somehow separate and only implement a subset of methods
- Migrate from Travis CI to GitHub Actions to run tests
- Tests exist but are possible out of date.
- Is efficiency/ code optimization an issue at all?
- One could add type annotations
- Installation instructions: move the
pip install pypillometryto the top. This is what most users will want. - We could help publishing on conda-forge.
- Consider using logging instead of writing own logging functions for verbose prints.
- Code duplication (example:
def objective) - Possible discussion point: functional programming vs. object-oriented programming (many methods could be just functions and the class could be a Python dataclass)
- pros of using methods: implicit type checking
- pros of using functions: many methods are without side-effects but bundling them with attributes makes them stateful and maybe more difficult to test
- the history attribute is created in a surprising and hard to read way
- keephistory decorator is used for debugging/logging
- let's discuss what you mean with extend class structure and we can discuss strategies and pros and cons
- why is PupilArray needed instead of a standard data structure?
- lots of scrolling is needed to get an understanding of the class/functions