From 5486334e8e5306f93436f4f4ad6efdffa9e30ae7 Mon Sep 17 00:00:00 2001 From: Robert Ennis Date: Wed, 27 Mar 2024 21:15:20 +0100 Subject: [PATCH] move stream loading routines into their respective constructor. streams need to load last to have access to all the filled attrs of their parent recording --- .gitignore | 1 + .../neon_recording/neon_recording.py | 42 ++++--------------- .../neon_recording/stream/gaze_stream.py | 22 +++++++++- .../neon_recording/stream/imu/imu_stream.py | 8 +++- .../neon_recording/stream/stream.py | 8 ++-- .../neon_recording/stream/video_stream.py | 31 ++++++++------ 6 files changed, 61 insertions(+), 51 deletions(-) diff --git a/.gitignore b/.gitignore index fcdea1d..9011cfb 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ test_data/ .vscode/ *.mp4 dev/ +guide # Created by https://www.toptal.com/developers/gitignore/api/python,visualstudiocode,macos,windows,linux,pycharm # Edit at https://www.toptal.com/developers/gitignore?templates=python,visualstudiocode,macos,windows,linux,pycharm diff --git a/src/pupil_labs/neon_recording/neon_recording.py b/src/pupil_labs/neon_recording/neon_recording.py index a166155..b6462a4 100644 --- a/src/pupil_labs/neon_recording/neon_recording.py +++ b/src/pupil_labs/neon_recording/neon_recording.py @@ -129,16 +129,9 @@ def _load_calib_bin(self): ) def __init__(self, rec_dir_in: pathlib.Path | str): - self._streams = { - "gaze": GazeStream("gaze", self), - "imu": IMUStream("imu", self), - "scene": VideoStream("scene", self), - "eye": VideoStream("eye", self), - } - self._calib_bin_loaded = False - log.info(f"NeonRecording: Loading recording from: {rec_dir_in}") + log.info(f"NeonRecording: Loading recording from {rec_dir_in}") if isinstance(rec_dir_in, str): self._rec_dir = pathlib.Path(rec_dir_in) else: @@ -175,31 +168,6 @@ def __init__(self, rec_dir_in: pathlib.Path | str): self._wearer["uuid"] = wearer_data["uuid"] self._wearer["name"] = wearer_data["name"] - # load up raw times, in case useful at some point - log.info("NeonRecording: Loading raw time (ns) files") - self._gaze_ps1_raw_time_ns = np.fromfile( - str(self._rec_dir / "gaze ps1.time"), dtype=" None: + def _load(self) -> None: + log.info("NeonRecording: Loading gaze data") + # we use gaze_200hz from cloud for the rec gaze stream # ts, raw = self._load_ts_and_data(rec_dir, 'gaze ps1') gaze_200hz_ts, gaze_200hz_raw = self._load_ts_and_data("gaze_200hz") gaze_200hz_ts_rel = gaze_200hz_ts - self._recording._start_ts + # load up raw timestamps in original ns format, + # in case useful at some point + log.debug("NeonRecording: Loading raw gaze timestamps (ns)") + self._gaze_ps1_raw_time_ns = np.fromfile( + str(self._recording._rec_dir / "gaze ps1.time"), dtype=" None: + def _load(self): + log.info("NeonRecording: Loading IMU data") + imu_rec = IMURecording( self._recording._rec_dir / "extimu ps1.raw", self._recording._start_ts ) diff --git a/src/pupil_labs/neon_recording/stream/stream.py b/src/pupil_labs/neon_recording/stream/stream.py index c997582..e96cae5 100644 --- a/src/pupil_labs/neon_recording/stream/stream.py +++ b/src/pupil_labs/neon_recording/stream/stream.py @@ -48,7 +48,7 @@ def ts_rel(self): return self._ts_rel @abc.abstractmethod - def _load(self, file_name: Optional[str] = None) -> None: + def _load(self): pass @abc.abstractmethod @@ -104,11 +104,11 @@ def sample(self, tstamps, method=InterpolationMethod.NEAREST): return self._sample_linear_interp(sorted_tses) else: return ValueError( - "Only LINEAR, NEAREST, and INSERT_ORDER methods are supported." + "Only LINEAR and NEAREST methods are supported." ) def _sample_nearest_rob(self, sorted_tses): - log.debug("NeonRecording: Sampling nearest timestamps.") + log.debug("NeonRecording: Sampling timestamps with nearest neighbor method.") closest_idxs = [ np.argmin(np.abs(self._ts - curr_ts)) if not self._ts_oob(curr_ts) else None @@ -125,7 +125,7 @@ def _sample_nearest_rob(self, sorted_tses): # https://stackoverflow.com/questions/2566412/find-nearest-value-in-numpy-array def _sample_nearest(self, sorted_tses): # uggcf://jjj.lbhghor.pbz/jngpu?i=FRKKRF5i59b - log.debug("NeonRecording: Sampling nearest timestamps.") + log.debug("NeonRecording: Sampling timestamps with nearest neighbor method.") closest_idxs = np.searchsorted(self._ts, sorted_tses, side="right") for i, ts in enumerate(sorted_tses): diff --git a/src/pupil_labs/neon_recording/stream/video_stream.py b/src/pupil_labs/neon_recording/stream/video_stream.py index 4215c45..9eee1a9 100644 --- a/src/pupil_labs/neon_recording/stream/video_stream.py +++ b/src/pupil_labs/neon_recording/stream/video_stream.py @@ -12,6 +12,14 @@ class VideoStream(Stream): + def __init__(self, name, file_name, recording): + super().__init__(name, recording) + self._file_name = file_name + self._width = None + self._height = None + + self._load() + @property def width(self): return self._width @@ -33,20 +41,19 @@ def _sample_linear_interp(self, sorted_ts): "NeonRecording: Video streams only support nearest neighbor interpolation." ) - def _load(self, file_name: Optional[str] = None) -> None: - if file_name is not None: - container, ts = self._load_video(file_name) + def _load(self): + log.info(f"NeonRecording: Loading video: {self._file_name}.") + + container, ts = self._load_video(self._file_name) - self._backing_data = container.streams.video[0] - self._data = self._backing_data.frames - self._ts = ts - setattr(self._data, "ts", self._ts) - self._ts_rel = self._ts - self._recording._start_ts + self._backing_data = container.streams.video[0] + self._data = self._backing_data.frames + self._ts = ts + setattr(self._data, "ts", self._ts) + self._ts_rel = self._ts - self._recording._start_ts - self._width = self._data[0].width - self._height = self._data[0].height - else: - raise ValueError("Filename must be provided when loading a VideoStream.") + self._width = self._data[0].width + self._height = self._data[0].height def _load_video(self, video_name: str): log.debug(