aboutsummaryrefslogtreecommitdiff
path: root/src/argaze.test/GazeFeatures.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/argaze.test/GazeFeatures.py')
-rw-r--r--src/argaze.test/GazeFeatures.py358
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."""