aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/argaze/ArFeatures.py19
-rw-r--r--src/argaze/GazeFeatures.py45
2 files changed, 58 insertions, 6 deletions
diff --git a/src/argaze/ArFeatures.py b/src/argaze/ArFeatures.py
index cb1b2f6..2e278ea 100644
--- a/src/argaze/ArFeatures.py
+++ b/src/argaze/ArFeatures.py
@@ -607,14 +607,21 @@ class ArFrame():
gaze_position_calibrator_value = frame_data.pop('gaze_position_calibrator')
- gaze_position_calibrator_module_path, gaze_position_calibrator_parameters = gaze_position_calibrator_value.popitem()
+ # str: relative path to file
+ if type(gaze_position_calibrator_value) == str:
- # Prepend argaze.GazeAnalysis path when a single name is provided
- if len(gaze_position_calibrator_module_path.split('.')) == 1:
- gaze_position_calibrator_module_path = f'argaze.GazeAnalysis.{gaze_position_calibrator_module_path}'
+ filepath = os.path.join(working_directory, gaze_position_calibrator_value)
+ file_format = filepath.split('.')[-1]
+
+ # JSON file format
+ if file_format == 'json':
+
+ new_gaze_position_calibrator = GazeFeatures.GazePositionCalibrator.from_json(filepath)
+
+ # dict:
+ else:
- gaze_position_calibrator_module = importlib.import_module(gaze_position_calibrator_module_path)
- new_gaze_position_calibrator = gaze_position_calibrator_module.GazePositionCalibrator(**gaze_position_calibrator_parameters)
+ new_gaze_position_calibrator = GazePositionCalibrator.from_dict(gaze_position_calibrator_value)
except KeyError:
diff --git a/src/argaze/GazeFeatures.py b/src/argaze/GazeFeatures.py
index eddd01d..46e9f17 100644
--- a/src/argaze/GazeFeatures.py
+++ b/src/argaze/GazeFeatures.py
@@ -12,6 +12,7 @@ from dataclasses import dataclass, field
import math
import ast
import json
+import importlib
from inspect import getmembers
from argaze import DataStructures
@@ -208,10 +209,54 @@ class GazePositionCalibrationFailed(Exception):
super().__init__(message)
+GazePositionCalibratorType = TypeVar('GazePositionCalibrator', bound="GazePositionCalibrator")
+# Type definition for type annotation convenience
+
@dataclass
class GazePositionCalibrator():
"""Abstract class to define what should provide a gaze position calibrator algorithm."""
+ @classmethod
+ def from_dict(self, calibrator_data: dict) -> GazePositionCalibratorType:
+ """Load gaze position calibrator from dictionary.
+
+ Parameters:
+ calibrator_data: dictionary with class name and attributes to load
+ """
+ gaze_position_calibrator_module_path, gaze_position_calibrator_parameters = calibrator_data.popitem()
+
+ # Prepend argaze.GazeAnalysis path when a single name is provided
+ if len(gaze_position_calibrator_module_path.split('.')) == 1:
+ gaze_position_calibrator_module_path = f'argaze.GazeAnalysis.{gaze_position_calibrator_module_path}'
+
+ gaze_position_calibrator_module = importlib.import_module(gaze_position_calibrator_module_path)
+ return gaze_position_calibrator_module.GazePositionCalibrator(**gaze_position_calibrator_parameters)
+
+ @classmethod
+ def from_json(self, json_filepath: str) -> GazePositionCalibratorType:
+ """Load calibrator from .json file."""
+
+ # Remember file path to ease rewriting
+ self.__json_filepath = json_filepath
+
+ # Open file
+ with open(self.__json_filepath) as calibration_file:
+
+ return GazePositionCalibrator.from_dict(json.load(calibration_file))
+
+ def to_json(self, json_filepath: str = None):
+ """Save calibrator into .json file."""
+
+ # Remember file path to ease rewriting
+ if json_filepath is not None:
+
+ self.__json_filepath = json_filepath
+
+ # Open file
+ with open(self.__json_filepath, 'w', encoding='utf-8') as calibration_file:
+
+ json.dump({DataStructures.module_path(self):DataStructures.JsonEncoder().default(self)}, calibration_file, ensure_ascii=False, indent=4)
+
def store(self, timestamp: int|float, observed_gaze_position: GazePosition, expected_gaze_position: GazePosition):
"""Store observed and expected gaze positions.