Source code for gazelib.conversion.icl.gazelibfixtures.common

# -*- coding: utf-8 -*-
import gazelib
from os import path
from gazelib.conversion import utils


[docs]def convert(gazedata_file_path, experiment_config_file_path, trial_config_id): ''' Parameters: gazedata_file_path: string experiment_config_file_path: string trial_config_id: 'mid' or 'shift' Return: CommonV1 object ''' # Known values participant_number = 'Akseli' was_calibrated = True # Read the files gdfp = gazedata_file_path # short alias ecfp = experiment_config_file_path gd = gazelib.io.load_csv_as_dictlist(gdfp) ec = gazelib.io.load_json(ecfp) # Convert configuration to object expconf = utils.ExperimentConfiguration(ec) trialconf = expconf.get_trial_configuration(trial_config_id) # Return with a gazelib-common-v1 Object. c = gazelib.containers.CommonV1() # Build environment constants participant_number = str(participant_number) c.add_environment('gazelib/gaze/head_id', participant_number) trial_config_id = str(trial_config_id) c.add_environment('icl/gaze/trial_configuration_id', trial_config_id) source_files = [gazedata_file_path, experiment_config_file_path] source_files = list(map(path.basename, source_files)) c.add_environment('gazelib/general/source_files', source_files) assert isinstance(was_calibrated, bool) c.add_environment('icl/gaze/tracker_successfully_calibrated', was_calibrated) c.add_environment('gazelib/gaze/eyetracker/manufacturer', 'Tobii') c.add_environment('gazelib/gaze/eyetracker/model', 'TX300') c.add_environment('gazelib/gaze/tracked_display_size', { "physical_mm": { "width": 510.0, "height": 288.0 }, "resolution_px": { "width": 1024, "height": 768 } }) # Build timeline def get_microseconds(tet_time): '''Takes in time in microseconds''' # tet_time might be string, hence int() return int(tet_time) global_time = get_microseconds(gd[0]['TETTime']) # Reference point in microseconds global_time_micros = global_time def convert_to_relative(tet_time): '''Convert to relative times, ints in microseconds''' return int(tet_time) - global_time_micros def get_relative_time(gazepoint): '''Convert gazepoint's TETTime to CommonV1 compliant relative time''' return convert_to_relative(gazepoint['TETTime']) timeline = list(map(get_relative_time, gd)) c.set_time_reference(global_time) c.add_timeline('eyetracker', timeline) # Build streams def tobii_validity_to_confidency(validity): '''Take in integer validity, return float confidence''' validity = int(validity) if validity == 0: return 1.0 if validity == 1: return 0.8 if validity == 2: return 0.5 if validity == 3: return 0.1 if validity == 4: return 0.0 raise Exception('Invalid Tobii validity: ' + str(validity)) left_confidency = [] right_confidency = [] left_eye_x_relative_stream = [] left_eye_y_relative_stream = [] left_eye_pupil_mm_stream = [] right_eye_x_relative_stream = [] right_eye_y_relative_stream = [] right_eye_pupil_mm_stream = [] def convert_x(x): '''X's already in relative units but may be strings''' x = float(x) if x == -1.0: return None return x def convert_y(y): '''Y's already in relative units but may be strings''' y = float(y) if y == -1.0: return None return y def convert_pupil(pupil_diam): d = float(pupil_diam) if d == -1.0: return None return d for gazepoint in gd: l_validity = gazepoint['ValidityLeftEye'] r_validity = gazepoint['ValidityRightEye'] l_confidency = tobii_validity_to_confidency(l_validity) r_confidency = tobii_validity_to_confidency(r_validity) left_confidency.append(l_confidency) right_confidency.append(r_confidency) left_eye_x_relative = convert_x(gazepoint['XGazePosLeftEye']) left_eye_y_relative = convert_y(gazepoint['YGazePosLeftEye']) left_eye_pupil_mm = convert_pupil(gazepoint['LeftEyePupilDiameter']) right_eye_x_relative = convert_x(gazepoint['XGazePosRightEye']) right_eye_y_relative = convert_y(gazepoint['YGazePosRightEye']) right_eye_pupil_mm = convert_pupil(gazepoint['RightEyePupilDiameter']) left_eye_x_relative_stream.append(left_eye_x_relative) left_eye_y_relative_stream.append(left_eye_y_relative) left_eye_pupil_mm_stream.append(left_eye_pupil_mm) right_eye_x_relative_stream.append(right_eye_x_relative) right_eye_y_relative_stream.append(right_eye_y_relative) right_eye_pupil_mm_stream.append(right_eye_pupil_mm) c.add_stream('gazelib/gaze/left_eye_x_relative', 'eyetracker', left_eye_x_relative_stream) c.add_stream('gazelib/gaze/left_eye_y_relative', 'eyetracker', left_eye_y_relative_stream) c.add_stream('gazelib/gaze/left_eye_pupil_mm', 'eyetracker', left_eye_pupil_mm_stream) c.add_stream('gazelib/gaze/right_eye_x_relative', 'eyetracker', right_eye_x_relative_stream) c.add_stream('gazelib/gaze/right_eye_y_relative', 'eyetracker', right_eye_y_relative_stream) c.add_stream('gazelib/gaze/right_eye_pupil_mm', 'eyetracker', right_eye_pupil_mm_stream) # Build events ####### # ICL experiment period tags ####### def value_converter(r): tag = r['tag'] # Skip nones if tag == '': raise ValueError() if tag == 'Wait': return 'icl/experiment/reaction/period/wait' if tag == 'Target' or tag == 'midbox': return 'icl/experiment/reaction/period/target' raise utils.ConversionException('Unexpected tag value: ' + str(tag)) def time_converter(r): return get_relative_time(r) tag_ranges = utils.split_to_ranges_at_change_in_value(gd, value_converter, time_converter) for tag in tag_ranges: c.add_event([tag['value']], tag['start'], tag['end']) ######### # Trials ########## def value_converter(r): if r['trialnumber'] == '': raise ValueError() return int(r['trialnumber']) def time_converter(r): return get_relative_time(r) ranges = utils.split_to_ranges_at_change_in_value(gd, value_converter, time_converter) for r in ranges: extra = { 'icl/experiment/reaction/trial/sequence_number': r['value'] } c.add_event(['icl/experiment/reaction/trial'], r['start'], r['end'], extra=extra) ################## # Image stimuli i.e. UserDefined_1 & Aoi ################## def value_converter(r): # Split when at least one of the two changes if r['stim'] == '' or r['aoi'] == '': raise ValueError() return r['stim'] + '-' + r['aoi'] ranges = utils.split_to_ranges_at_change_in_value(gd, value_converter, time_converter) for r in ranges: original_row = r['first'] image_index = int(original_row['stim']) aoi_index = int(original_row['aoi']) extra = { 'original_area_of_interest_index': aoi_index, 'original_image_index': image_index, 'icl/stimulus/image/filename': trialconf.get_image_name(image_index), 'icl/stimulus/image/rectangle': trialconf.get_aoi_rectangle(aoi_index) } c.add_event(['icl/stimulus', 'icl/stimulus/image'], r['start'], r['end'], extra=extra) return c