diff options
Diffstat (limited to 'src/argaze.test/GazeFeatures.py')
-rw-r--r-- | src/argaze.test/GazeFeatures.py | 358 |
1 files changed, 174 insertions, 184 deletions
diff --git a/src/argaze.test/GazeFeatures.py b/src/argaze.test/GazeFeatures.py index b41c7c7..035c76a 100644 --- a/src/argaze.test/GazeFeatures.py +++ b/src/argaze.test/GazeFeatures.py @@ -29,79 +29,79 @@ def random_gaze_positions(size, frame_dimension: tuple[float, float] = (1, 1)): for i in range(0, size): # Edit gaze position - random_gaze_position = GazeFeatures.GazePosition((random.random() * frame_dimension[0], random.random() * frame_dimension[1])) + random_gaze_position = GazeFeatures.GazePosition((random.random() * frame_dimension[0], random.random() * frame_dimension[1]), precision=5) - # Store gaze position - ts_gaze_positions[time.time()] = random_gaze_position + # Timestamp gaze position + random_gaze_position.timestamp = time.time() + + # Store timestamped gaze position + ts_gaze_positions.append(random_gaze_position) return ts_gaze_positions -@dataclass(frozen=True) class TestFixation(GazeFeatures.Fixation): """Define basic fixation class for test.""" - def __post_init__(self): + def __init__(self, positions: GazeFeatures.TimeStampedGazePositions = (), finished: bool = False, message: str = None, **kwargs): + + super().__init__(positions, finished, message, **kwargs) - super().__post_init__() + if positions: - points = self.positions.values() - points_x, points_y = [p[0] for p in points], [p[1] for p in points] - points_array = numpy.column_stack([points_x, points_y]) - centroid_array = numpy.array([numpy.mean(points_x), numpy.mean(points_y)]) + positions_array = numpy.asarray(self.values()) + centroid = numpy.mean(positions_array, axis=0) - # Update frozen focus attribute using centroid - object.__setattr__(self, 'focus', (centroid_array[0], centroid_array[1])) + # Update focus attribute using centroid + self.focus = (centroid[0], centroid[1]) -@dataclass(frozen=True) class TestSaccade(GazeFeatures.Saccade): """Define basic saccade for test.""" - def __post_init__(self): - super().__post_init__() + def __init__(self, positions: GazeFeatures.TimeStampedGazePositions = (), finished: bool = False, message: str = None, **kwargs): + + super().__init__(positions, finished, message, **kwargs) class TestGazePositionClass(unittest.TestCase): """Test GazePosition class.""" - + def test_new(self): """Test GazePosition creation.""" # Check empty GazePosition - empty_gaze_position = GazeFeatures.GazePosition() + empty_gaze_position = GazeFeatures.GazePosition(message="empty for test") - self.assertEqual(empty_gaze_position.value, (0, 0)) - self.assertEqual(empty_gaze_position[0], 0) - self.assertEqual(empty_gaze_position[1], 0) - - for v in empty_gaze_position: - self.assertEqual(v, 0) - - self.assertEqual(empty_gaze_position.precision, 0.) - self.assertEqual(len(empty_gaze_position), 2) - self.assertEqual(empty_gaze_position.valid, True) - self.assertEqual(numpy.array(empty_gaze_position).shape, (2,)) + self.assertEqual(empty_gaze_position, ()) + self.assertEqual(empty_gaze_position, ()) + self.assertEqual(empty_gaze_position.precision, None) + self.assertEqual(empty_gaze_position.message, "empty for test") + self.assertEqual(len(empty_gaze_position), 0) + self.assertEqual(bool(empty_gaze_position), False) + self.assertEqual(numpy.array(empty_gaze_position).shape, (0,)) # Check integer GazePosition int_gaze_position = GazeFeatures.GazePosition((123, 456), precision=55) - self.assertEqual(int_gaze_position.value, (123, 456)) + self.assertEqual(int_gaze_position, (123, 456)) self.assertEqual(int_gaze_position[0], 123) self.assertEqual(int_gaze_position[1], 456) + self.assertEqual(int_gaze_position, (123, 456)) self.assertEqual(int_gaze_position.precision, 55) self.assertEqual(len(int_gaze_position), 2) - self.assertEqual(int_gaze_position.valid, True) - self.assertEqual(numpy.array(empty_gaze_position).shape, (2,)) + self.assertEqual(bool(int_gaze_position), True) + self.assertEqual(numpy.array(int_gaze_position).shape, (2,)) # Check float GazePosition float_gaze_position = GazeFeatures.GazePosition((1.23, 4.56), precision=5.5) - self.assertEqual(float_gaze_position.value, (1.23, 4.56)) + self.assertEqual(float_gaze_position, (1.23, 4.56)) self.assertEqual(float_gaze_position[0], 1.23) self.assertEqual(float_gaze_position[1], 4.56) + self.assertEqual(float_gaze_position, (1.23, 4.56)) self.assertEqual(float_gaze_position.precision, 5.5) self.assertEqual(len(float_gaze_position), 2) - self.assertEqual(float_gaze_position.valid, True) - self.assertEqual(numpy.array(empty_gaze_position).shape, (2,)) - + self.assertEqual(bool(float_gaze_position), True) + self.assertEqual(numpy.array(float_gaze_position).shape, (2,)) + def test_properties(self): """Test GazePosition properties cannot be modified after creation.""" @@ -110,11 +110,29 @@ class TestGazePositionClass(unittest.TestCase): # Check that gaze position value setting fails with self.assertRaises(AttributeError): - gaze_position.value = (123, 456) + gaze_position.value = (12, 34) + # WARNING: gaze_position = (12, 34) is possible !!!! + # How to prevent this? - self.assertNotEqual(gaze_position.value, (123, 456)) - self.assertEqual(gaze_position.value, (0, 0)) + self.assertNotEqual(gaze_position, (12, 34)) + self.assertEqual(gaze_position, ()) + # Check that gaze position precision setting fails + with self.assertRaises(AttributeError): + + gaze_position.precision = 5 + + self.assertNotEqual(gaze_position.precision, 5) + self.assertEqual(gaze_position.precision, None) + + # Check that gaze position message setting fails + with self.assertRaises(AttributeError): + + gaze_position.message = "later setting" + + self.assertNotEqual(gaze_position.message, "later setting") + self.assertEqual(gaze_position.message, None) + def test_overlapping(self): """Test GazePosition overlap method.""" @@ -133,83 +151,80 @@ class TestGazePositionClass(unittest.TestCase): self.assertFalse(gaze_position_C.overlap(gaze_position_A)) self.assertFalse(gaze_position_C.overlap(gaze_position_B)) - + def test___repr__(self): """Test GazePosition string representation.""" # Check empty GazePosition representation - self.assertEqual(repr(GazeFeatures.GazePosition()), "{\"value\": [0, 0], \"precision\": 0.0}") + self.assertEqual(repr(GazeFeatures.GazePosition()), "{\"value\": [], \"timestamp\": NaN}") -class TestUnvalidGazePositionClass(unittest.TestCase): - """Test UnvalidGazePosition class.""" + # Check GazePosition representation + self.assertEqual(repr(GazeFeatures.GazePosition((12, 345), precision=50, message="ok")), \ + "{\"value\": [12, 345], \"precision\": 50, \"message\": \"ok\", \"timestamp\": NaN}") +class TestTimeStampedGazePositionsClass(unittest.TestCase): + """Test TimeStampedGazePositions class.""" + def test_new(self): - """Test UnvalidGazePosition creation.""" - - import math - - unvalid_gaze_position = GazeFeatures.UnvalidGazePosition() - - self.assertEqual(unvalid_gaze_position.value, (None, None)) - self.assertEqual(unvalid_gaze_position.precision, None) - self.assertEqual(unvalid_gaze_position.valid, False) + """Test TimeStampedGazePositions creation.""" - def test___repr__(self): - """Test UnvalidGazePosition string representation.""" - - self.assertEqual(repr(GazeFeatures.UnvalidGazePosition()), "{\"message\": null, \"value\": [null, null], \"precision\": null}") + empty_gaze_position = GazeFeatures.GazePosition() + empty_gaze_position.timestamp = 100 -class TestTimeStampedGazePositionsClass(unittest.TestCase): - """Test TimeStampedGazePositions class.""" + gaze_position_with_message = GazeFeatures.GazePosition((12, 345), message="second position") + gaze_position_with_message.timestamp = 200 - def test___setitem__(self): - """Test __setitem__ method.""" + dict_gaze_position = {"timestamp": 300, "value": (0, 0), "precision": 0.} - ts_gaze_positions = GazeFeatures.TimeStampedGazePositions() - ts_gaze_positions[0] = GazeFeatures.GazePosition() - ts_gaze_positions[1] = GazeFeatures.UnvalidGazePosition() - ts_gaze_positions[2] = {"value": (0, 0), "precision": 0.} + ts_gaze_positions = GazeFeatures.TimeStampedGazePositions([empty_gaze_position, gaze_position_with_message, dict_gaze_position]) - # Check GazePosition is correctly stored and accessible as a GazePosition + # Check first GazePosition is correctly stored and accessible as a GazePosition self.assertIsInstance(ts_gaze_positions[0], GazeFeatures.GazePosition) - self.assertEqual(ts_gaze_positions[0].valid, True) + self.assertEqual(bool(ts_gaze_positions[0]), False) + self.assertEqual(ts_gaze_positions[0].timestamp, 100) - # Check UnvalidGazePosition is correctly stored and accessible as a UnvalidGazePosition - self.assertIsInstance(ts_gaze_positions[1], GazeFeatures.UnvalidGazePosition) - self.assertEqual(ts_gaze_positions[1].valid, False) + # Check second GazePosition is correctly stored and accessible as a GazePosition + self.assertIsInstance(ts_gaze_positions[1], GazeFeatures.GazePosition) + self.assertEqual(bool(ts_gaze_positions[1]), True) + self.assertEqual(ts_gaze_positions[1].timestamp, 200) - # Check dict with "value" and "precision" keys is correctly stored and accessible as a GazePosition + # Check third GazePosition from dict is correctly stored and accessible as a GazePosition self.assertIsInstance(ts_gaze_positions[2], GazeFeatures.GazePosition) - self.assertEqual(ts_gaze_positions[2].valid, True) + self.assertEqual(bool(ts_gaze_positions[2]), True) + self.assertEqual(ts_gaze_positions[2].timestamp, 300) # Check that bad data type insertion fails - with self.assertRaises(AssertionError): + with self.assertRaises(TypeError): - ts_gaze_positions[3] = "This string is not a gaze position value." + ts_gaze_positions.append("This string is not a gaze position value.") # Check that dict with bad keys insertion fails - with self.assertRaises(AssertionError): + with self.assertRaises(TypeError): - ts_gaze_positions[4] = {"bad_key": (0, 0), "precision": 0.} + ts_gaze_positions.append({"bad_key": (0, 0), "precision": 0.}) # Check final lenght self.assertEqual(len(ts_gaze_positions), 3) - + def test___repr__(self): """Test inherited string representation.""" ts_gaze_positions = GazeFeatures.TimeStampedGazePositions() - self.assertEqual(repr(GazeFeatures.TimeStampedGazePositions()), "{}") + self.assertEqual(repr(GazeFeatures.TimeStampedGazePositions()), "[]") - ts_gaze_positions[0] = GazeFeatures.GazePosition() - - self.assertEqual(repr(ts_gaze_positions), "{\"0\": {\"value\": [0, 0], \"precision\": 0.0}}") + empty_gaze_position = GazeFeatures.GazePosition() + empty_gaze_position.timestamp = 100 + ts_gaze_positions.append(empty_gaze_position) - ts_gaze_positions[0] = GazeFeatures.UnvalidGazePosition() + self.assertEqual(repr(ts_gaze_positions), "[{\"value\": [], \"timestamp\": 100}]") - self.assertEqual(repr(ts_gaze_positions), "{\"0\": {\"message\": null, \"value\": [null, null], \"precision\": null}}") + full_gaze_position = GazeFeatures.GazePosition((12, 345), precision=50, message="ok") + full_gaze_position.timestamp = 200 + ts_gaze_positions[0] = full_gaze_position + self.assertEqual(repr(ts_gaze_positions), "[{\"value\": [12, 345], \"precision\": 50, \"message\": \"ok\", \"timestamp\": 200}]") + def test_from_dataframe(self): """Test from_dataframe classmethod.""" @@ -226,13 +241,13 @@ class TestTimeStampedGazePositionsClass(unittest.TestCase): # Check first gaze position is correctly stored and accessible as a GazePosition self.assertIsInstance(ts_gaze_positions[0], GazeFeatures.GazePosition) - self.assertEqual(ts_gaze_positions[0].precision, 0) - self.assertEqual(ts_gaze_positions[0].valid, True) + self.assertEqual(ts_gaze_positions[0].precision, None) + self.assertEqual(bool(ts_gaze_positions[0]), True) - # Check third gaze position is correctly stored and accessible as a UnvalidGazePosition - self.assertIsInstance(ts_gaze_positions[2], GazeFeatures.UnvalidGazePosition) + # Check third gaze position is correctly stored and accessible as a GazePosition + self.assertIsInstance(ts_gaze_positions[2], GazeFeatures.GazePosition) self.assertEqual(ts_gaze_positions[2].precision, None) - self.assertEqual(ts_gaze_positions[2].valid, False) + self.assertEqual(bool(ts_gaze_positions[2]), False) data = {'Specific timestamp label': [0, 1, 2, 3, 4], 'Specific gaze position x label': [0, 10, numpy.nan, 30, 40], @@ -249,12 +264,12 @@ class TestTimeStampedGazePositionsClass(unittest.TestCase): # Check first gaze position is correctly stored and accessible as a GazePosition self.assertIsInstance(ts_gaze_positions[0], GazeFeatures.GazePosition) self.assertEqual(ts_gaze_positions[0].precision, 15) - self.assertEqual(ts_gaze_positions[0].valid, True) + self.assertEqual(bool(ts_gaze_positions[0]), True) - # Check third gaze position is correctly stored and accessible as a UnvalidGazePosition - self.assertIsInstance(ts_gaze_positions[2], GazeFeatures.UnvalidGazePosition) - self.assertEqual(ts_gaze_positions[2].precision, None) - self.assertEqual(ts_gaze_positions[2].valid, False) + # Check third gaze position is correctly stored and accessible as a GazePosition + self.assertIsInstance(ts_gaze_positions[2], GazeFeatures.GazePosition) + self.assertEqual(numpy.isnan(ts_gaze_positions[2].precision), True) + self.assertEqual(bool(ts_gaze_positions[2]), False) def test_as_dataframe(self): """Test inherited as_dataframe method.""" @@ -265,27 +280,33 @@ class TestTimeStampedGazePositionsClass(unittest.TestCase): self.assertEqual(ts_gaze_positions_dataframe.index.name, "timestamp") self.assertEqual(ts_gaze_positions_dataframe.index.size, 10) - self.assertEqual(ts_gaze_positions_dataframe.columns.size, 2) + self.assertEqual(ts_gaze_positions_dataframe.columns.size, 3) self.assertEqual(ts_gaze_positions_dataframe.columns[0], "value") self.assertEqual(ts_gaze_positions_dataframe.columns[1], "precision") + self.assertEqual(ts_gaze_positions_dataframe.columns[2], "message") self.assertEqual(ts_gaze_positions_dataframe["value"].dtype, 'object') - self.assertEqual(ts_gaze_positions_dataframe["precision"].dtype, 'float64') + self.assertEqual(ts_gaze_positions_dataframe["precision"].dtype, 'int64') + self.assertEqual(ts_gaze_positions_dataframe["message"].dtype, 'O') # Python object type - # Check unvalid position conversion - ts_gaze_positions = GazeFeatures.TimeStampedGazePositions() - ts_gaze_positions[0] = GazeFeatures.UnvalidGazePosition() + # Check empty position conversion + empty_gaze_position = GazeFeatures.GazePosition() + empty_gaze_position.timestamp = 100 + + ts_gaze_positions = GazeFeatures.TimeStampedGazePositions([empty_gaze_position]) ts_gaze_positions_dataframe = ts_gaze_positions.as_dataframe() self.assertEqual(ts_gaze_positions_dataframe.index.name, "timestamp") self.assertEqual(ts_gaze_positions_dataframe.index.size, 1) - self.assertEqual(ts_gaze_positions_dataframe.columns.size, 2) + self.assertEqual(ts_gaze_positions_dataframe.columns.size, 3) self.assertEqual(ts_gaze_positions_dataframe.columns[0], "value") self.assertEqual(ts_gaze_positions_dataframe.columns[1], "precision") + self.assertEqual(ts_gaze_positions_dataframe.columns[2], "message") self.assertEqual(ts_gaze_positions_dataframe["value"].dtype, 'object') self.assertEqual(ts_gaze_positions_dataframe["precision"].dtype, 'O') # Python object type + self.assertEqual(ts_gaze_positions_dataframe["message"].dtype, 'O') # Python object type class TestGazeMovementClass(unittest.TestCase): """Test GazeMovement class.""" @@ -296,10 +317,10 @@ class TestGazeMovementClass(unittest.TestCase): abstract_gaze_movement = GazeFeatures.GazeMovement(random_gaze_positions(0)) # Check abstract GazeMovement - self.assertEqual(len(abstract_gaze_movement.positions), 0) - self.assertEqual(abstract_gaze_movement.duration, -1) - self.assertEqual(abstract_gaze_movement.amplitude, -1) - self.assertEqual(abstract_gaze_movement.valid, False) + self.assertEqual(len(abstract_gaze_movement), 0) + self.assertEqual(abstract_gaze_movement.duration, 0) + self.assertEqual(abstract_gaze_movement.amplitude, 0) + self.assertEqual(bool(abstract_gaze_movement), False) self.assertEqual(abstract_gaze_movement.finished, False) def test_finish(self): @@ -320,25 +341,22 @@ class TestGazeMovementClass(unittest.TestCase): self.assertEqual(abstract_gaze_movement.finished, True) self.assertEqual(abstract_gaze_movement_ref.finished, True) -class TestUnvalidGazeMovementClass(unittest.TestCase): - """Test UnvalidGazeMovement class.""" - - def test_new(self): - """Test UnvalidGazeMovement creation.""" + def test_message(self): + """Test GazeMovement creation with message only.""" - unvalid_gaze_movement = GazeFeatures.UnvalidGazeMovement('test') + gaze_movement = GazeFeatures.GazeMovement(message='test') - # Check UnvalidGazeMovement - self.assertEqual(len(unvalid_gaze_movement.positions), 0) - self.assertEqual(unvalid_gaze_movement.duration, -1) - self.assertEqual(unvalid_gaze_movement.amplitude, -1) - self.assertEqual(unvalid_gaze_movement.valid, False) - self.assertEqual(unvalid_gaze_movement.finished, False) - self.assertEqual(unvalid_gaze_movement.message, 'test') + # Check GazeMovement + self.assertEqual(len(gaze_movement), 0) + self.assertEqual(gaze_movement.duration, 0) + self.assertEqual(gaze_movement.amplitude, 0) + self.assertEqual(bool(gaze_movement), False) + self.assertEqual(gaze_movement.finished, False) + self.assertEqual(gaze_movement.message, 'test') class TestScanStepClass(unittest.TestCase): """Test ScanStep class.""" - + def test_new(self): """Test ScanStep creation.""" @@ -351,7 +369,7 @@ class TestScanStepClass(unittest.TestCase): self.assertEqual(scan_step.first_fixation, fixation) self.assertEqual(scan_step.last_saccade, saccade) self.assertGreater(scan_step.duration, 0) - + def build_scan_path(size, frame_dimension: tuple[float, float] = (1, 1)): """Build scan path""" @@ -359,19 +377,17 @@ def build_scan_path(size, frame_dimension: tuple[float, float] = (1, 1)): for i in range(size): - fixation = TestFixation(random_gaze_positions(10, frame_dimension)) - ts, _ = fixation.positions.first - scan_path.append_fixation(ts, fixation) + fixation = TestFixation(random_gaze_positions(10, frame_dimension), timestamp=i) + scan_path.append_fixation(fixation) - saccade = TestSaccade(random_gaze_positions(2, frame_dimension)) - ts, _ = saccade.positions.first - scan_path.append_saccade(ts, saccade) + saccade = TestSaccade(random_gaze_positions(2, frame_dimension), timestamp=i+1) + scan_path.append_saccade(saccade) return scan_path class TestScanPathClass(unittest.TestCase): """Test ScanPath class.""" - + def test_new(self): """Test ScanPath creation.""" @@ -380,7 +396,7 @@ class TestScanPathClass(unittest.TestCase): self.assertEqual(len(scan_path), 0) self.assertEqual(scan_path.duration, 0) - + def test_append(self): """Test ScanPath append methods.""" @@ -388,9 +404,7 @@ class TestScanPathClass(unittest.TestCase): # Append a saccade that should be ignored saccade = TestSaccade(random_gaze_positions(2)) - ts, _ = saccade.positions.first - - new_step = scan_path.append_saccade(ts, saccade) + new_step = scan_path.append_saccade(saccade) # Check that no scan step have been created yet self.assertEqual(len(scan_path), 0) @@ -399,9 +413,7 @@ class TestScanPathClass(unittest.TestCase): # Append first fixation fixation_A = TestFixation(random_gaze_positions(10)) - ts, _ = fixation_A.positions.first - - new_step = scan_path.append_fixation(ts, fixation_A) + new_step = scan_path.append_fixation(fixation_A) # Check that no scan step have been created yet self.assertEqual(len(scan_path), 0) @@ -410,9 +422,7 @@ class TestScanPathClass(unittest.TestCase): # Append consecutive saccade saccade_A = TestSaccade(random_gaze_positions(2)) - ts, _ = saccade_A.positions.first - - new_step_A = scan_path.append_saccade(ts, saccade_A) + new_step_A = scan_path.append_saccade(saccade_A) # Check that new scan step have been created self.assertEqual(len(scan_path), 1) @@ -423,9 +433,7 @@ class TestScanPathClass(unittest.TestCase): # Append 2 consecutive fixations then a saccade fixation_B1 = TestFixation(random_gaze_positions(10)) - ts, _ = fixation_B1.positions.first - - new_step = scan_path.append_fixation(ts, fixation_B1) + new_step = scan_path.append_fixation(fixation_B1) # Check that no scan step have been created yet self.assertEqual(len(scan_path), 1) @@ -433,9 +441,7 @@ class TestScanPathClass(unittest.TestCase): self.assertEqual(new_step, None) fixation_B2 = TestFixation(random_gaze_positions(10)) - ts, _ = fixation_B2.positions.first - - new_step = scan_path.append_fixation(ts, fixation_B2) + new_step = scan_path.append_fixation(fixation_B2) # Check that no scan step have been created yet self.assertEqual(len(scan_path), 1) @@ -443,9 +449,7 @@ class TestScanPathClass(unittest.TestCase): self.assertEqual(new_step, None) saccade_B = TestSaccade(random_gaze_positions(2)) - ts, _ = saccade_B.positions.first - - new_step_B = scan_path.append_saccade(ts, saccade_B) + new_step_B = scan_path.append_saccade(saccade_B) # Check that new scan step have been created self.assertEqual(len(scan_path), 2) @@ -456,19 +460,19 @@ class TestScanPathClass(unittest.TestCase): class TestAOIScanStepClass(unittest.TestCase): """Test AOIScanStep class.""" - + def test_new(self): """Test AOIScanStep creation.""" movements = GazeFeatures.TimeStampedGazeMovements() fixation = TestFixation(random_gaze_positions(10)) - ts, _ = fixation.positions.first - movements[ts] = fixation + ts = fixation[0].timestamp + movements.append(fixation) saccade = TestSaccade(random_gaze_positions(2)) - ts, _ = saccade.positions.first - movements[ts] = saccade + ts = saccade[0].timestamp + movements.append(saccade) aoi_scan_step = GazeFeatures.AOIScanStep(movements, 'Test') @@ -478,19 +482,19 @@ class TestAOIScanStepClass(unittest.TestCase): self.assertEqual(aoi_scan_step.first_fixation, fixation) self.assertEqual(aoi_scan_step.last_saccade, saccade) self.assertGreater(aoi_scan_step.duration, 0) - + def test_error(self): """Test AOIScanStep creation error.""" movements = GazeFeatures.TimeStampedGazeMovements() saccade = TestSaccade(random_gaze_positions(2)) - ts, _ = saccade.positions.first - movements[ts] = saccade + ts = saccade[0].timestamp + movements.append(saccade) fixation = TestFixation(random_gaze_positions(10)) - ts, _ = fixation.positions.first - movements[ts] = fixation + ts = fixation[0].timestamp + movements.append(fixation) # Check that aoi scan step creation fail with self.assertRaises(GazeFeatures.AOIScanStepError): @@ -505,21 +509,19 @@ def build_aoi_scan_path(expected_aoi, aoi_path): # Append a hidden last step to allow last given step creation aoi_path.append(aoi_path[-2]) - for aoi in aoi_path: + for i, aoi in enumerate(aoi_path): - fixation = TestFixation(random_gaze_positions(10)) - ts, _ = fixation.positions.first - aoi_scan_path.append_fixation(ts, fixation, aoi) + fixation = TestFixation(random_gaze_positions(10), timestamp=i) + aoi_scan_path.append_fixation(fixation, aoi) - saccade = TestSaccade(random_gaze_positions(2)) - ts, _ = saccade.positions.first - aoi_scan_path.append_saccade(ts, saccade) + saccade = TestSaccade(random_gaze_positions(2), timestamp=i+1) + aoi_scan_path.append_saccade(saccade) return aoi_scan_path class TestAOIScanPathClass(unittest.TestCase): """Test AOIScanPath class.""" - + def test_new(self): """Test AOIScanPath creation.""" @@ -527,7 +529,7 @@ class TestAOIScanPathClass(unittest.TestCase): aoi_scan_path = GazeFeatures.AOIScanPath() self.assertEqual(len(aoi_scan_path), 0) - + def test_append(self): """Test AOIScanPath append methods.""" @@ -535,9 +537,7 @@ class TestAOIScanPathClass(unittest.TestCase): # Append fixation on A aoi fixation_A = TestFixation(random_gaze_positions(10)) - ts, _ = fixation_A.positions.first - - new_step = aoi_scan_path.append_fixation(ts, fixation_A, 'Foo') + new_step = aoi_scan_path.append_fixation(fixation_A, 'Foo') # Check that no aoi scan step have been created yet self.assertEqual(len(aoi_scan_path), 0) @@ -546,9 +546,7 @@ class TestAOIScanPathClass(unittest.TestCase): # Append saccade saccade_A = TestSaccade(random_gaze_positions(2)) - ts, _ = saccade_A.positions.first - - new_step = aoi_scan_path.append_saccade(ts, saccade_A) + new_step = aoi_scan_path.append_saccade(saccade_A) # Check that no aoi scan step have been created yet self.assertEqual(len(aoi_scan_path), 0) @@ -557,9 +555,7 @@ class TestAOIScanPathClass(unittest.TestCase): # Append fixation on B aoi fixation_B = TestFixation(random_gaze_positions(10)) - ts, _ = fixation_B.positions.first - - new_step_A = aoi_scan_path.append_fixation(ts, fixation_B, 'Bar') + new_step_A = aoi_scan_path.append_fixation(fixation_B, 'Bar') # Check a first aoi scan step have been created once a new fixation is appened self.assertEqual(len(aoi_scan_path), 1) @@ -568,14 +564,11 @@ class TestAOIScanPathClass(unittest.TestCase): self.assertEqual(new_step_A.aoi, 'Foo') self.assertEqual(new_step_A.letter, 'A') - first_ts, _ = fixation_A.positions.first - last_ts, _ = saccade_A.positions.last - - self.assertEqual(new_step_A.duration, last_ts - first_ts) + self.assertEqual(new_step_A.duration, saccade_A[-1].timestamp - fixation_A[0].timestamp) # Check letter affectation self.assertEqual(aoi_scan_path.get_letter_aoi('A'), 'Foo') - + def test_append_error(self): """Test AOIScanPath append error.""" @@ -583,9 +576,7 @@ class TestAOIScanPathClass(unittest.TestCase): # Append fixation on A aoi fixation = TestFixation(random_gaze_positions(10)) - ts, _ = fixation.positions.first - - new_step = aoi_scan_path.append_fixation(ts, fixation, 'Foo') + new_step = aoi_scan_path.append_fixation(fixation, 'Foo') # Check that no aoi scan step have been created yet self.assertEqual(len(aoi_scan_path), 0) @@ -593,18 +584,17 @@ class TestAOIScanPathClass(unittest.TestCase): # Append fixation on B aoi fixation = TestFixation(random_gaze_positions(10)) - ts, _ = fixation.positions.first # Check that aoi scan step creation fail when fixation is appened after another fixation with self.assertRaises(GazeFeatures.AOIScanStepError): - new_step = aoi_scan_path.append_fixation(ts, fixation, 'Bar') + new_step = aoi_scan_path.append_fixation(fixation, 'Bar') # Check that unexpected aoi scan step creation fail with self.assertRaises(GazeFeatures.AOIScanStepError): - new_step = aoi_scan_path.append_fixation(ts, fixation, 'Shu') - + new_step = aoi_scan_path.append_fixation(fixation, 'Shu') + def test_letter_index_and_string_reprentation(self): """Test AOIScanPath letter index and string representation feature.""" @@ -633,7 +623,7 @@ class TestAOIScanPathClass(unittest.TestCase): # Check letter sequence representation self.assertEqual(aoi_scan_path.letter_sequence, 'ABCA') - + def test_transition_matrix(self): """Test AOIScanPath transition matrix feature.""" @@ -652,7 +642,7 @@ class TestAOIScanPathClass(unittest.TestCase): self.assertEqual(aoi_scan_path.transition_matrix['Shu']['Foo'], 0) self.assertEqual(aoi_scan_path.transition_matrix['Shu']['Bar'], 1) - + def test_transition_matrix(self): """Test AOIScanPath fixations count feature.""" |