Source code for ibllib.qc.task_extractors

import logging

import numpy as np

from one.alf.spec import is_session_path
import one.alf.io as alfio


_logger = logging.getLogger('ibllib')

REQUIRED_FIELDS = [
    'choice',
    'contrastLeft',
    'contrastRight',
    'correct',
    'errorCueTrigger_times',
    'errorCue_times',
    'feedbackType',
    'feedback_times',
    'firstMovement_times',
    'goCueTrigger_times',
    'goCue_times',
    'intervals',
    'itiIn_times',
    'phase',
    'position',
    'probabilityLeft',
    'quiescence',
    'response_times',
    'rewardVolume',
    'stimFreezeTrigger_times',
    'stimFreeze_times',
    'stimOffTrigger_times',
    'stimOff_times',
    'stimOnTrigger_times',
    'stimOn_times',
    'valveOpen_times',
    'wheelMoves_intervals',
    'wheelMoves_peakAmplitude',
    'wheelMoves_peakVelocity_times',
    'wheel_position',
    'wheel_timestamps',
]


[docs] class TaskQCExtractor: def __init__(self, session_path): """ A class for holding the task data required to perform task quality control. :param session_path: a valid session path """ if not is_session_path(session_path): raise ValueError('Invalid session path') self.session_path = session_path self.log = _logger self.data = None self.settings = None self.raw_data = None self.frame_ttls = self.audio_ttls = self.bpod_ttls = None self.wheel_encoding = None
[docs] @staticmethod def rename_data(data): """Rename the extracted data dict for use with TaskQC Splits 'feedback_times' to 'errorCue_times' and 'valveOpen_times'. NB: The data is not copied before making changes :param data: A dict of task data returned by the task extractors :return: the same dict after modifying the keys """ # Expand trials dataframe into key value pairs trials_table = data.pop('table', None) if trials_table is not None: data = {**data, **alfio.AlfBunch.from_df(trials_table)} correct = data['feedbackType'] > 0 # get valve_time and errorCue_times from feedback_times if 'errorCue_times' not in data: data['errorCue_times'] = data['feedback_times'].copy() data['errorCue_times'][correct] = np.nan if 'valveOpen_times' not in data: data['valveOpen_times'] = data['feedback_times'].copy() data['valveOpen_times'][~correct] = np.nan data['correct'] = correct diff_fields = list(set(REQUIRED_FIELDS).difference(set(data.keys()))) for miss_field in diff_fields: data[miss_field] = None if miss_field.startswith('wheel') else data['feedback_times'] * np.nan if len(diff_fields): _logger.warning(f'QC extractor, missing fields filled with NaNs: {diff_fields}') return data