diff options
-rw-r--r-- | src/argaze/TobiiGlassesPro2/TobiiEntities.py | 91 | ||||
-rw-r--r-- | src/argaze/utils/explore_tobii_sdcard.py | 9 |
2 files changed, 80 insertions, 20 deletions
diff --git a/src/argaze/TobiiGlassesPro2/TobiiEntities.py b/src/argaze/TobiiGlassesPro2/TobiiEntities.py index e243a5a..a16700d 100644 --- a/src/argaze/TobiiGlassesPro2/TobiiEntities.py +++ b/src/argaze/TobiiGlassesPro2/TobiiEntities.py @@ -4,6 +4,9 @@ import datetime import json import gzip import os + +from argaze.DataAnalysis import TimeStampedData + import cv2 as cv TOBII_DATETIME_FORMAT = '%Y-%m-%dT%H:%M:%S+%f' @@ -18,9 +21,61 @@ TOBII_RECORDINGS_DIRNAME = "recordings" TOBII_RECORD_FILENAME = "recording.json" TOBII_SEGMENTS_DIRNAME = "segments" -TOBII_SEGMENT_FILENAME = "segment.json" +TOBII_SEGMENT_INFO_FILENAME = "segment.json" TOBII_SEGMENT_VIDEO_FILENAME = "fullstream.mp4" -TOBII_SEGMENT_LIVEDATA_FILENAME = "livedata.json.gz" +TOBII_SEGMENT_DATA_FILENAME = "livedata.json.gz" + +class TobiiSegmentData: + """Handle Tobii Glasses Pro 2 segment data file.""" + + def __init__(self, segment_data_path): + """Load segment data from segment directory.""" + + self.__segment_data_path = segment_data_path + self.__ts_start = 0 + + def get_path(self): + return self.__segment_data_path + + def load(self): + + ts_data_dict = {} + + # define a decoder function + def decode(json_item): + + # accept only valid data (e.g. with status value equal to 0) + if json_item.pop('s', -1) == 0: + + # convert timestamp into ms + ts = json_item.pop('ts') / 1000.0 + + # keep first timestamp to offset all timestamps + if self.__ts_start == 0: + self.__ts_start = ts + + ts -= self.__ts_start + + # ignore negative timestamp + if ts < 0: + return + + # concatenate keys to get data signature + data_signature = '-'.join(json_item.keys()) + + # append a timestamped data buffer to store all data with same signature + if data_signature not in ts_data_dict.keys(): + ts_data_dict[data_signature] = TimeStampedData.TimeStampedData() + + # store data into the dedicated timestamped data buffer + ts_data_dict[data_signature][ts] = json_item + + # start loading + with gzip.open(self.__segment_data_path) as f: + for item in f: + json.loads(item.decode('utf-8'), object_hook=decode) + + return ts_data_dict class TobiiSegmentVideo: """Handle Tobii Glasses Pro 2 segment video file.""" @@ -30,11 +85,11 @@ class TobiiSegmentVideo: self.__segment_video_path = segment_video_path - cap = cv.VideoCapture(self.__segment_video_path) + video = cv.VideoCapture(self.__segment_video_path) - self.__width = int(cap.get(cv.CAP_PROP_FRAME_WIDTH)) - self.__height = int(cap.get(cv.CAP_PROP_FRAME_HEIGHT)) - self.__fps = int(cap.get(cv.CAP_PROP_FPS)) + self.__width = int(video.get(cv.CAP_PROP_FRAME_WIDTH)) + self.__height = int(video.get(cv.CAP_PROP_FRAME_HEIGHT)) + self.__fps = int(video.get(cv.CAP_PROP_FPS)) def get_path(self): return self.__segment_video_path @@ -49,7 +104,7 @@ class TobiiSegmentVideo: return self.__fps class TobiiSegment: - """Handle Tobii Glasses Pro 2 segment info, data and video.""" + """Handle Tobii Glasses Pro 2 segment info.""" def __init__(self, segment_path): """Load segment info from segment directory.""" @@ -57,16 +112,16 @@ class TobiiSegment: self.__segment_id = os.path.basename(segment_path) self.__segment_path = segment_path - with open(os.path.join(self.__segment_path, TOBII_SEGMENT_FILENAME)) as f: + with open(os.path.join(self.__segment_path, TOBII_SEGMENT_INFO_FILENAME)) as f: try: item = json.load(f) except: - raise RuntimeError(f'JSON fails to load {self.__segment_path}/{TOBII_SEGMENT_FILENAME}') + raise RuntimeError(f'JSON fails to load {self.__segment_path}/{TOBII_SEGMENT_INFO_FILENAME}') self.__length_us = int(item["seg_length_us"]) self.__calibrated = bool(item["seg_calibrated"]) - self.__time_start = datetime.datetime.strptime(item["seg_t_start"], TOBII_DATETIME_FORMAT) - self.__time_stop = datetime.datetime.strptime(item["seg_t_stop"], TOBII_DATETIME_FORMAT) + self.__start_date = datetime.datetime.strptime(item["seg_t_start"], TOBII_DATETIME_FORMAT) + self.__stop_date = datetime.datetime.strptime(item["seg_t_stop"], TOBII_DATETIME_FORMAT) def get_path(self): return self.__segment_path @@ -77,18 +132,18 @@ class TobiiSegment: def get_length_us(self): return self.__length_us - def get_live_data_filepath(self): - return os.path.join(self.__segment_path, self.__segment_id) + def get_start_date(self): + return self.__start_date - def get_start_date_time(self): - return self.__time_start - - def get_stop_date_time(self): - return self.__time_stop + def get_stop_date(self): + return self.__stop_date def is_calibrated(self): return self.__calibrated + def get_data(self): + return TobiiSegmentData(os.path.join(self.__segment_path, TOBII_SEGMENT_DATA_FILENAME)) + def get_video(self): return TobiiSegmentVideo(os.path.join(self.__segment_path, TOBII_SEGMENT_VIDEO_FILENAME)) diff --git a/src/argaze/utils/explore_tobii_sdcard.py b/src/argaze/utils/explore_tobii_sdcard.py index 7fd9032..0f0b01a 100644 --- a/src/argaze/utils/explore_tobii_sdcard.py +++ b/src/argaze/utils/explore_tobii_sdcard.py @@ -52,8 +52,13 @@ def main(): tobii_segment_video = tobii_segment.get_video() print(f'Video width: {tobii_segment_video.get_width()}, height: {tobii_segment_video.get_height()}, fps: {tobii_segment_video.get_fps()}') - #tobii_segment_data = tobii_segment.get_data() - #print(f'Data width: {tobii_segment_data.get_width()}, height: {tobii_segment_data.get_height()}, fps: {tobii_segment_data.get_fps()}') + tobii_segment_data = tobii_segment.get_data() + + data = tobii_segment_data.load() + + for key in data.keys(): + print(f'{key}: {len(data[key])} items') + print(f'{key} first item: {data[key].popitem()} items') if __name__ == '__main__': |