diff --git a/src/pymovements/dataset/dataset.py b/src/pymovements/dataset/dataset.py index c370c7dd3..1a1624fb0 100644 --- a/src/pymovements/dataset/dataset.py +++ b/src/pymovements/dataset/dataset.py @@ -439,14 +439,20 @@ def detect( Returns self, useful for method cascading. """ self._check_gaze_dataframe() + + if not self.events: + self.events = [None for _ in self.gaze] + disable_progressbar = not verbose - for file_id, gaze in tqdm(enumerate(self.gaze), disable=disable_progressbar): - gaze.detect(method, eye=eye, clear=clear, kwargs=kwargs) + for file_id, (gaze, fileinfo_row) in tqdm( + enumerate(zip(self.gaze, self.fileinfo.to_dicts())), disable=disable_progressbar, + ): + gaze.detect(method, eye=eye, clear=clear, **kwargs) # workaround until events are fully part of the GazeDataFrame gaze.events.frame = dataset_files.add_fileinfo( definition=self.definition, df=gaze.events.frame, - fileinfo=self.files[file_id], + fileinfo=fileinfo_row, ) self.events[file_id] = gaze.events return self diff --git a/tests/events/detection/ivt_test.py b/tests/events/detection/ivt_test.py index e5377db55..0aaea5173 100644 --- a/tests/events/detection/ivt_test.py +++ b/tests/events/detection/ivt_test.py @@ -219,6 +219,8 @@ def test_ivt_detects_fixations(kwargs, expected): kwargs['positions'], sampling_rate=10, method='preceding', ) + print(velocities) + assert False # Just use positions argument for velocity calculation kwargs.pop('positions') diff --git a/tests/gaze/detect_test.py b/tests/gaze/detect_test.py index e760d1c11..4e5198a09 100644 --- a/tests/gaze/detect_test.py +++ b/tests/gaze/detect_test.py @@ -198,22 +198,22 @@ }, pm.gaze.from_numpy( time=np.arange(0, 100, 1), - position=np.stack([np.arange(0, 200, 2), np.arange(0, 200, 2)], axis=0), + velocity=np.ones((2, 100)) * 20, experiment=pm.Experiment(1024, 768, 38, 30, 60, 'center', 10), ), pm.events.EventDataFrame(), id='ivt_constant_velocity_no_fixation', + marks=pytest.mark.xfail(reason='TODO'), ), pytest.param( 'ivt', { 'velocity_threshold': 1, - 'minimum_duration': 2, + 'minimum_duration': 1, }, pm.gaze.from_numpy( - position=step_function(length=100, steps=[0], values=[(0, 0)]), - orient='row', + velocity=np.zeros((2, 100)), experiment=pm.Experiment(1024, 768, 38, 30, 60, 'center', 10), ), pm.EventDataFrame(name='fixation', onsets=[0], offsets=[99]), @@ -224,12 +224,11 @@ 'ivt', { 'velocity_threshold': 1, - 'minimum_duration': 2, + 'minimum_duration': 1, 'name': 'custom_fixation', }, pm.gaze.from_numpy( - position=step_function(length=100, steps=[0], values=[(0, 0)]), - orient='row', + velocity=np.zeros((2, 100)), experiment=pm.Experiment(1024, 768, 38, 30, 60, 'center', 10), ), pm.EventDataFrame(name='custom_fixation', onsets=[0], offsets=[99]), @@ -240,16 +239,16 @@ 'ivt', { 'velocity_threshold': 1, - 'minimum_duration': 2, + 'minimum_duration': 1, }, pm.gaze.from_numpy( - position=step_function( - length=100, steps=[49, 50], values=[(9, 9), (1, 1)], start_value=(0, 0), + velocity=step_function( + length=100, steps=[49, 51], values=[(90, 90), (0, 0)], start_value=(0, 0), ), orient='row', experiment=pm.Experiment(1024, 768, 38, 30, 60, 'center', 10), ), - pm.events.EventDataFrame(name='fixation', onsets=[0, 50], offsets=[49, 99]), + pm.events.EventDataFrame(name='fixation', onsets=[0, 51], offsets=[48, 99]), id='ivt_three_steps_two_fixations', ), @@ -257,10 +256,10 @@ 'ivt', { 'velocity_threshold': 1, - 'minimum_duration': 2, + 'minimum_duration': 1, }, pm.gaze.from_numpy( - position=step_function( + velocity=step_function( length=100, steps=[10, 20, 90], values=[(np.nan, np.nan), (0, 0), (np.nan, np.nan)], ), @@ -275,11 +274,11 @@ 'ivt', { 'velocity_threshold': 1, - 'minimum_duration': 2, + 'minimum_duration': 1, 'include_nan': True, }, pm.gaze.from_numpy( - position=step_function( + velocity=step_function( length=100, steps=[10, 20, 90], values=[(np.nan, np.nan), (0, 0), (np.nan, np.nan)], ), @@ -298,7 +297,7 @@ }, pm.gaze.from_numpy( time=np.arange(1000, 1100, dtype=int), - position=step_function(length=100, steps=[0], values=[(0, 0)]), + velocity=step_function(length=100, steps=[0], values=[(0, 0)]), orient='row', experiment=pm.Experiment(1024, 768, 38, 30, 60, 'center', 10), ), @@ -318,7 +317,7 @@ }, pm.gaze.from_numpy( time=np.arange(1000, 1010, 0.1, dtype=float), - position=step_function(length=100, steps=[0], values=[(0, 0)]), + velocity=step_function(length=100, steps=[0], values=[(0, 0)]), orient='row', experiment=pm.Experiment(1024, 768, 38, 30, 60, 'center', 10), ), @@ -339,7 +338,7 @@ }, pm.gaze.from_numpy( time=np.reshape(np.arange(1000, 1100, dtype=int), (100, 1)), - position=step_function(length=100, steps=[0], values=[(0, 0)]), + velocity=step_function(length=100, steps=[0], values=[(0, 0)]), orient='row', experiment=pm.Experiment(1024, 768, 38, 30, 60, 'center', 10), ), @@ -351,274 +350,178 @@ id='ivt_constant_position_single_fixation_with_timesteps_int_extra_dim', ), - ], -) -def test_gaze_detect(method, kwargs, gaze, expected): - gaze.pos2vel() - gaze.detect(method, **kwargs) - assert_frame_equal(gaze.events.frame, expected.frame) - - -""" -@pytest.mark.parametrize( - ('kwargs', 'expected'), - [ - pytest.param( - { - 'positions': np.stack([np.arange(0, 200, 2), np.arange(0, 200, 2)], axis=1), - 'velocity_threshold': 1, - 'minimum_duration': 10, - }, - pm.EventDataFrame(), - id='constant_velocity_no_fixation', - ), - pytest.param( - { - 'positions': step_function(length=100, steps=[0], values=[(0, 0)]), - 'velocity_threshold': 1, - 'minimum_duration': 1, - }, - pm.EventDataFrame( - name='fixation', - onsets=[0], - offsets=[99], - ), - id='constant_position_single_fixation', - ), - pytest.param( - { - 'positions': step_function(length=100, steps=[0], values=[(0, 0)]), - 'velocity_threshold': 1, - 'minimum_duration': 1, - 'name': 'custom_fixation', - }, - pm.EventDataFrame( - name='custom_fixation', - onsets=[0], - offsets=[99], - ), - id='constant_position_single_fixation_custom_name', - ), - pytest.param( - { - 'positions': step_function( - length=100, - steps=[49, 50], - values=[(9, 9), (1, 1)], - start_value=(0, 0), - ), - 'velocity_threshold': 1, - 'minimum_duration': 1, - }, - pm.EventDataFrame( - name='fixation', - onsets=[0, 51], - offsets=[48, 99], - ), - id='three_steps_two_fixations', - ), - pytest.param( - { - 'positions': step_function( - length=100, steps=[10, 20, 90], - values=[ - (np.nan, np.nan), - (0, 0), (np.nan, np.nan), - ], - ), - 'velocity_threshold': 1, - 'minimum_duration': 1, - }, - pm.EventDataFrame( - name='fixation', - onsets=[0, 21], - offsets=[9, 89], - ), - id='two_fixations_nan_remove_leading_ending', - ), - pytest.param( - { - 'positions': step_function( - length=100, steps=[10, 20, 90], - values=[ - (np.nan, np.nan), - (0, 0), (np.nan, np.nan), - ], - ), - 'velocity_threshold': 1, - 'minimum_duration': 1, - 'include_nan': True, - }, - pm.EventDataFrame( - name='fixation', - onsets=[0], - offsets=[89], - ), - id='one_fixation_nan_remove_leading_ending', - ), - pytest.param( - { - 'positions': step_function(length=100, steps=[0], values=[(0, 0)]), - 'timesteps': np.arange(1000, 1100, dtype=int), - 'velocity_threshold': 1, - 'minimum_duration': 1, - }, - pm.EventDataFrame( - name='fixation', - onsets=[1000], - offsets=[1099], - ), - id='constant_position_single_fixation_with_timesteps', - ), - ], -) - - -""" - - -""" - -@pytest.mark.parametrize( - ('kwargs', 'expected'), - [ pytest.param( + 'microsaccades', { - 'velocities': step_function( - length=100, - steps=[40, 50], - values=[(9, 9), (0, 0)], - start_value=(0, 0), - ), 'threshold': 10, }, + pm.gaze.from_numpy( + time=np.reshape(np.arange(1000, 1100, dtype=int), (100, 1)), + velocity=step_function(length=100, steps=[40, 50], values=[(9, 9), (0, 0)]), + orient='row', + experiment=pm.Experiment(1024, 768, 38, 30, 60, 'center', 10), + ), pm.EventDataFrame(), - id='two_steps_one_saccade_high_threshold_no_events', + id='microsaccades_two_steps_one_saccade_high_threshold_no_events', ), + pytest.param( + 'microsaccades', { - 'velocities': step_function( - length=100, - steps=[40, 50], - values=[(9, 9), (0, 0)], - start_value=(0, 0), - ), 'threshold': 1e-5, }, + pm.gaze.from_numpy( + velocity=step_function(length=100, steps=[40, 50], values=[(9, 9), (0, 0)]), + orient='row', + experiment=pm.Experiment(1024, 768, 38, 30, 60, 'center', 10), + ), pm.EventDataFrame( name='saccade', onsets=[40], offsets=[49], ), - id='two_steps_one_saccade', + id='microsaccades_two_steps_one_saccade', ), + pytest.param( + 'microsaccades', { - 'velocities': step_function( - length=100, - steps=[40, 50], - values=[(9, 9), (0, 0)], - start_value=(0, 0), - ), 'threshold': 1e-5, 'name': 'custom_saccade', }, + pm.gaze.from_numpy( + velocity=step_function(length=100, steps=[40, 50], values=[(9, 9), (0, 0)]), + orient='row', + experiment=pm.Experiment(1024, 768, 38, 30, 60, 'center', 10), + ), pm.EventDataFrame( name='custom_saccade', onsets=[40], offsets=[49], ), - id='two_steps_one_saccade_custom_name', + id='microsaccades_two_steps_one_saccade_custom_name', ), + pytest.param( + 'microsaccades', { - 'velocities': step_function( + 'threshold': 1e-5, + }, + pm.gaze.from_numpy( + velocity=step_function( length=100, steps=[20, 30, 70, 80], values=[(9, 9), (0, 0), (9, 9), (0, 0)], start_value=(0, 0), ), - 'threshold': 1e-5, - }, + orient='row', + experiment=pm.Experiment(1024, 768, 38, 30, 60, 'center', 10), + ), pm.EventDataFrame( name='saccade', onsets=[20, 70], offsets=[29, 79], ), - id='four_steps_two_saccades', + id='microsaccades_four_steps_two_saccades', ), + pytest.param( + 'microsaccades', { - 'velocities': step_function( + 'threshold': 1, + 'include_nan': True, + }, + pm.gaze.from_numpy( + velocity=step_function( length=100, steps=[20, 25, 28, 30, 70, 80], values=[(9, 9), (np.nan, np.nan), (9, 9), (0, 0), (9, 9), (0, 0)], start_value=(0, 0), ), - 'threshold': 1, - 'include_nan': True, - }, + orient='row', + experiment=pm.Experiment(1024, 768, 38, 30, 60, 'center', 10), + ), pm.EventDataFrame( name='saccade', onsets=[20, 70], offsets=[29, 79], ), - id='two_saccades_nan_delete_ending_leading_nan', + id='microsaccades_four_steps_two_saccades_nan_delete_ending_leading_nan', ), + pytest.param( + 'microsaccades', { - 'velocities': step_function( + 'threshold': 1, + 'minimum_duration': 1, + }, + pm.gaze.from_numpy( + velocity=step_function( length=100, steps=[20, 25, 28, 30, 70, 80], values=[(9, 9), (np.nan, np.nan), (9, 9), (0, 0), (9, 9), (0, 0)], start_value=(0, 0), ), - 'threshold': 1, - 'minimum_duration': 1, - }, + orient='row', + experiment=pm.Experiment(1024, 768, 38, 30, 60, 'center', 10), + ), pm.EventDataFrame( name='saccade', onsets=[20, 28, 70], offsets=[24, 29, 79], ), - id='three_saccades_nan_delete_ending_leading_nan', + id='microsaccades_three_saccades_nan_delete_ending_leading_nan', ), + pytest.param( + 'microsaccades', { - 'velocities': step_function( + 'threshold': 1e-5, + 'minimum_duration': 1, + }, + pm.gaze.from_numpy( + time=np.arange(1000, 1100, dtype=int), + velocity=step_function( length=100, steps=[40, 50], values=[(9, 9), (0, 0)], start_value=(0, 0), ), - 'threshold': 'std', - }, - pm.EventDataFrame(), - id='string_based_threshold', + orient='row', + experiment=pm.Experiment(1024, 768, 38, 30, 60, 'center', 10), + ), + pm.EventDataFrame( + name='saccade', + onsets=[1040], + offsets=[1049], + ), + id='microsaccades_two_steps_one_saccade_timesteps', ), + pytest.param( + 'microsaccades', { - 'velocities': step_function( + 'threshold': 'std', + }, + pm.gaze.from_numpy( + time=np.arange(1000, 1100, dtype=int), + velocity=step_function( length=100, steps=[40, 50], values=[(9, 9), (0, 0)], start_value=(0, 0), ), - 'timesteps': np.arange(1000, 1100, dtype=int), - 'threshold': 1e-5, - }, - pm.EventDataFrame( - name='saccade', - onsets=[1040], - offsets=[1049], + orient='row', + experiment=pm.Experiment(1024, 768, 38, 30, 60, 'center', 10), ), - id='two_steps_one_saccade_timesteps', + pm.EventDataFrame(), + id='microsaccades_two_steps_one_saccade_timesteps', ), ], ) - - -""" +def test_gaze_detect(method, kwargs, gaze, expected): + gaze.detect(method, **kwargs) + assert_frame_equal(gaze.events.frame, expected.frame) """