Example #1
0
 def __init__(self, task_settings, user_settings, make=True):
     # =====================================================================
     # IMPORT task_settings, user_settings, and SessionPathCreator params
     # =====================================================================
     ts = {
         i: task_settings.__dict__[i]
         for i in [x for x in dir(task_settings) if "__" not in x]
     }
     self.__dict__.update(ts)
     us = {
         i: user_settings.__dict__[i]
         for i in [x for x in dir(user_settings) if "__" not in x]
     }
     self.__dict__.update(us)
     self = iotasks.deserialize_pybpod_user_settings(self)
     spc = SessionPathCreator(self.PYBPOD_SUBJECTS[0],
                              protocol=self.PYBPOD_PROTOCOL,
                              make=make)
     self.__dict__.update(spc.__dict__)
     # =====================================================================
     # SAVE SETTINGS FILE AND TASK CODE
     # =====================================================================
     iotasks.save_session_settings(self)
     iotasks.copy_task_code(self)
     iotasks.save_task_code(self)
Example #2
0
 def __init__(self, task_settings, user_settings):
     # =====================================================================
     # IMPORT task_settings, user_settings, and SessionPathCreator params
     # =====================================================================
     ts = {
         i: task_settings.__dict__[i] for i in [x for x in dir(task_settings) if "__" not in x]
     }
     self.__dict__.update(ts)
     us = {
         i: user_settings.__dict__[i] for i in [x for x in dir(user_settings) if "__" not in x]
     }
     self.__dict__.update(us)
     self = iotasks.deserialize_pybpod_user_settings(self)
     spc = SessionPathCreator(self.PYBPOD_SUBJECTS[0], protocol=self.PYBPOD_PROTOCOL, make=True)
     self.__dict__.update(spc.__dict__)
     # =====================================================================
     # OSC CLIENT
     # =====================================================================
     self.OSC_CLIENT_PORT = 7110
     self.OSC_CLIENT_IP = "127.0.0.1"
     self.OSC_CLIENT = udp_client.SimpleUDPClient(self.OSC_CLIENT_IP, self.OSC_CLIENT_PORT)
     # =====================================================================
     # SAVE SETTINGS FILE AND TASK CODE
     # =====================================================================
     iotasks.save_session_settings(self)
     iotasks.copy_task_code(self)
     iotasks.save_task_code(self)
Example #3
0
    def __init__(self, task_settings, user_settings):
        # =====================================================================
        # IMPORT task_settings, user_settings, and SessionPathCreator params
        # =====================================================================
        ts = {
            i: task_settings.__dict__[i]
            for i in [x for x in dir(task_settings) if '__' not in x]
        }
        self.__dict__.update(ts)
        us = {
            i: user_settings.__dict__[i]
            for i in [x for x in dir(user_settings) if '__' not in x]
        }
        self.__dict__.update(us)
        self = iotasks.deserialize_pybpod_user_settings(self)
        spc = SessionPathCreator(self.IBLRIG_FOLDER,
                                 self.IBLRIG_DATA_FOLDER,
                                 self.PYBPOD_SUBJECTS[0],
                                 protocol=self.PYBPOD_PROTOCOL,
                                 board=self.PYBPOD_BOARD,
                                 make=True)
        self.__dict__.update(spc.__dict__)

        # =====================================================================
        # OSC CLIENT
        # =====================================================================
        self.OSC_CLIENT_PORT = 7110
        self.OSC_CLIENT_IP = '127.0.0.1'
        self.OSC_CLIENT = udp_client.SimpleUDPClient(self.OSC_CLIENT_IP,
                                                     self.OSC_CLIENT_PORT)
        # # =====================================================================
        # # PREVIOUS DATA FILES
        # # =====================================================================
        # self.LAST_TRIAL_DATA = iotasks.load_data(self.PREVIOUS_SESSION_PATH)
        # self.LAST_SETTINGS_DATA = iotasks.load_settings(
        #     self.PREVIOUS_SESSION_PATH)
        # # =====================================================================
        # # ADAPTIVE STUFF
        # # =====================================================================
        # self.CALIB_FUNC = adaptive.init_calib_func(self)
        # self.CALIB_FUNC_RANGE = adaptive.init_calib_func_range(self)
        # self.REWARD_VALVE_TIME = adaptive.init_reward_valve_time(self)

        # # =====================================================================
        # # RUN VISUAL STIM
        # # =====================================================================
        self.VISUAL_STIMULUS_TYPE = 'screen_calibration'
        # bonsai.start_visual_stim(self)
        # =====================================================================
        # SAVE SETTINGS FILE AND TASK CODE
        # =====================================================================
        iotasks.save_session_settings(self)
        iotasks.copy_task_code(self)
        iotasks.save_task_code(self)
        self.display_logs()
Example #4
0
    def __init__(self, task_settings, user_settings):
        # =====================================================================
        # IMPORT task_settings, user_settings, and SessionPathCreator params
        # =====================================================================
        ts = {
            i: task_settings.__dict__[i]
            for i in [x for x in dir(task_settings) if '__' not in x]
        }
        self.__dict__.update(ts)
        us = {
            i: user_settings.__dict__[i]
            for i in [x for x in dir(user_settings) if '__' not in x]
        }
        self.__dict__.update(us)
        self = iotasks.deserialize_pybpod_user_settings(self)
        spc = SessionPathCreator(self.IBLRIG_FOLDER,
                                 self.IBLRIG_DATA_FOLDER,
                                 self.PYBPOD_SUBJECTS[0],
                                 protocol=self.PYBPOD_PROTOCOL,
                                 board=self.PYBPOD_BOARD,
                                 make=True)
        self.__dict__.update(spc.__dict__)
        # =====================================================================
        # OSC CLIENT
        # =====================================================================
        self.OSC_CLIENT_PORT = 7110
        self.OSC_CLIENT_IP = '127.0.0.1'
        self.OSC_CLIENT = udp_client.SimpleUDPClient(self.OSC_CLIENT_IP,
                                                     self.OSC_CLIENT_PORT)
        # =====================================================================
        # frame2TTL
        # =====================================================================
        self.F2TTL_GET_AND_SET_THRESHOLDS = frame2TTL.get_and_set_thresholds(
            self)
        # =====================================================================
        # ROTARY ENCODER
        # =====================================================================
        self.ALL_THRESHOLDS = self.STIM_POSITIONS
        self.ROTARY_ENCODER = MyRotaryEncoder(self.ALL_THRESHOLDS,
                                              self.STIM_GAIN,
                                              self.COM['ROTARY_ENCODER'])
        # =====================================================================
        # SOUNDS
        # =====================================================================
        self.SOUND_SAMPLE_FREQ = sound.sound_sample_freq(self.SOFT_SOUND)

        self.GO_TONE_DURATION = float(self.GO_TONE_DURATION)
        self.GO_TONE_FREQUENCY = int(self.GO_TONE_FREQUENCY)
        self.GO_TONE_AMPLITUDE = float(self.GO_TONE_AMPLITUDE)

        self.SD = sound.configure_sounddevice(
            output=self.SOFT_SOUND, samplerate=self.SOUND_SAMPLE_FREQ)

        self.SOUND_BOARD_BPOD_PORT = 'Serial3'
        self.GO_TONE_IDX = 2
        self.GO_TONE = None
        self = sound.init_sounds(self, noise=False)
        if self.SOFT_SOUND is None:
            sound.configure_sound_card(sounds=[self.GO_TONE],
                                       indexes=[self.GO_TONE_IDX],
                                       sample_rate=self.SOUND_SAMPLE_FREQ)
        self.OUT_STOP_SOUND = ('SoftCode',
                               0) if self.SOFT_SOUND else ('Serial3', ord('X'))
        self.OUT_TONE = ('SoftCode', 1) if self.SOFT_SOUND else ('Serial3', 5)
        # =====================================================================
        # RUN VISUAL STIM
        # =====================================================================
        bonsai.start_visual_stim(self)
        # =====================================================================
        # SAVE SETTINGS FILE AND TASK CODE
        # =====================================================================
        iotasks.save_session_settings(self)
        iotasks.copy_task_code(self)
        iotasks.save_task_code(self)

        self.bad_stim_count = 0
        self.bad_tone_count = 0
    def __init__(self, task_settings, user_settings, debug=False, fmake=True):
        self.DEBUG = debug
        make = True
        self.IBLRIG_FOLDER = 'C:\\iblrig'
        self.IBLRIG_DATA_FOLDER = None  # ..\\iblrig_data if None
        # =====================================================================
        # IMPORT task_settings, user_settings, and SessionPathCreator params
        # =====================================================================
        ts = {i: task_settings.__dict__[i]
              for i in [x for x in dir(task_settings) if '__' not in x]}
        self.__dict__.update(ts)
        us = {i: user_settings.__dict__[i]
              for i in [x for x in dir(user_settings) if '__' not in x]}
        self.__dict__.update(us)
        self = iotasks.deserialize_pybpod_user_settings(self)
        spc = SessionPathCreator(self.PYBPOD_SUBJECTS[0],
                                 protocol=self.PYBPOD_PROTOCOL,
                                 make=make)
        self.__dict__.update(spc.__dict__)
        # =====================================================================
        # SETTINGS
        # =====================================================================
        self.RECORD_SOUND = True
        self.RECORD_AMBIENT_SENSOR_DATA = True
        self.RECORD_VIDEO = True
        self.OPEN_CAMERA_VIEW = True  # Always True if RECORD_VIDEO is True

        self.NTRIALS = 2000  # Number of trials for the current session
        self.USE_AUTOMATIC_STOPPING_CRITERIONS = True  # Weather to check for the Automatic stopping criterions or not  # noqa
        self.REPEAT_ON_ERROR = False  # not used
        self.INTERACTIVE_DELAY = 0.0
        self.RESPONSE_WINDOW = 60
        self.ITI_CORRECT = 1
        self.ITI_ERROR = 2
        self.CONTRAST_SET = [1., 0.25, 0.125, 0.0625, 0.]  # Full contrast set
        self.CONTRAST_SET_PROBABILITY_TYPE = 'biased'
        self.STIM_FREQ = 0.10  # Probably constant - NOT IN USE
        self.STIM_ANGLE = 0.  # Vertical orientation of Gabor patch
        self.STIM_SIGMA = 7.  # (azimuth_degree) Size of Gabor patch
        self.STIM_GAIN = 4.  # (azimuth_degree/mm) Gain of the RE
        # =====================================================================
        # SUBJECT
        # =====================================================================
        # self.SUBJECT_WEIGHT = self.ask_subject_weight()
        self.POOP_COUNT = False
        self.SUBJECT_DISENGAGED_TRIGGERED = False
        self.SUBJECT_DISENGAGED_TRIALNUM = None
        # =====================================================================
        # OSC CLIENT
        # =====================================================================
        self.OSC_CLIENT_PORT = 7110
        self.OSC_CLIENT_IP = '127.0.0.1'
        self.OSC_CLIENT = udp_client.SimpleUDPClient(self.OSC_CLIENT_IP,
                                                     self.OSC_CLIENT_PORT)
        # =====================================================================
        # PREVIOUS DATA FILES
        # =====================================================================
        self.LAST_TRIAL_DATA = iotasks.load_data(self.PREVIOUS_SESSION_PATH)
        self.LAST_SETTINGS_DATA = iotasks.load_settings(
            self.PREVIOUS_SESSION_PATH)
        bonsai.start_mic_recording(self)
        self.IS_MOCK = user_input.ask_is_mock()  # Change to False if mock has its own task
        # Get preloaded session num (the num in the filename!)
        if self.IS_MOCK:
            self.SESSION_ORDER = None
            self.SESSION_IDX = None
            self.PRELOADED_SESSION_NUM = 'mock'
        else:
            (
                self.SESSION_ORDER,
                self.SESSION_IDX
            ) = iotasks.load_session_order_idx(self.LAST_SETTINGS_DATA)
            self.SESSION_IDX = user_input.ask_confirm_session_idx(self.SESSION_IDX)
            self.PRELOADED_SESSION_NUM = self.SESSION_ORDER[self.SESSION_IDX]
        # Load session from file
        (
            self.POSITIONS,
            self.CONTRASTS,
            self.QUIESCENT_PERIOD,
            self.STIM_PHASE,
            self.LEN_BLOCKS,
        ) = iotasks.load_ephys_session_pcqs(self.PRELOADED_SESSION_NUM)
        # =====================================================================
        # ADAPTIVE STUFF
        # =====================================================================
        self.AUTOMATIC_CALIBRATION = True
        self.CALIBRATION_VALUE = 0.067
        self.REWARD_AMOUNT = 1.5
        self.REWARD_TYPE = 'Water 10% Sucrose'

        self.CALIB_FUNC = None
        if self.AUTOMATIC_CALIBRATION:
            self.CALIB_FUNC = adaptive.init_calib_func()
        self.CALIB_FUNC_RANGE = adaptive.init_calib_func_range()
        self.REWARD_VALVE_TIME = adaptive.init_reward_valve_time(self)

        # =====================================================================
        # ROTARY ENCODER
        # =====================================================================
        self.STIM_POSITIONS = [-35, 35]  # All possible positions (deg)
        self.QUIESCENCE_THRESHOLDS = [-2, 2]  # degree
        self.ALL_THRESHOLDS = (self.STIM_POSITIONS +
                               self.QUIESCENCE_THRESHOLDS)
        self.ROTARY_ENCODER = MyRotaryEncoder(self.ALL_THRESHOLDS,
                                              self.STIM_GAIN,
                                              self.PARAMS['COM_ROTARY_ENCODER'])
        # =====================================================================
        # frame2TTL
        # =====================================================================
        self.F2TTL_GET_AND_SET_THRESHOLDS = frame2TTL.get_and_set_thresholds()
        # =====================================================================
        # SOUNDS
        # =====================================================================
        self.SOFT_SOUND = None
        self.SOUND_SAMPLE_FREQ = sound.sound_sample_freq(self.SOFT_SOUND)
        self.SOUND_BOARD_BPOD_PORT = 'Serial3'
        self.WHITE_NOISE_DURATION = float(0.5)
        self.WHITE_NOISE_AMPLITUDE = float(0.05)
        self.GO_TONE_DURATION = float(0.1)
        self.GO_TONE_FREQUENCY = int(5000)
        self.GO_TONE_AMPLITUDE = float(0.0151)  # 0.0151 for 70.0 dB SPL CCU

        self.SD = sound.configure_sounddevice(
            output=self.SOFT_SOUND, samplerate=self.SOUND_SAMPLE_FREQ)
        # Create sounds and output actions of state machine
        self.GO_TONE = sound.make_sound(
            rate=self.SOUND_SAMPLE_FREQ, frequency=self.GO_TONE_FREQUENCY,
            duration=self.GO_TONE_DURATION, amplitude=self.GO_TONE_AMPLITUDE,
            fade=0.01, chans='stereo')
        self.WHITE_NOISE = sound.make_sound(
            rate=self.SOUND_SAMPLE_FREQ, frequency=-1,
            duration=self.WHITE_NOISE_DURATION,
            amplitude=self.WHITE_NOISE_AMPLITUDE, fade=0.01, chans='stereo')
        self.GO_TONE_IDX = 2
        self.WHITE_NOISE_IDX = 3
        sound.configure_sound_card(
            sounds=[self.GO_TONE, self.WHITE_NOISE],
            indexes=[self.GO_TONE_IDX, self.WHITE_NOISE_IDX],
            sample_rate=self.SOUND_SAMPLE_FREQ)
        self.OUT_TONE = ('SoftCode', 1) if self.SOFT_SOUND else ('Serial3', 6)
        self.OUT_NOISE = ('SoftCode', 2) if self.SOFT_SOUND else ('Serial3', 7)
        self.OUT_STOP_SOUND = (
            'SoftCode', 0) if self.SOFT_SOUND else ('Serial3', ord('X'))
        # =====================================================================
        # PROBES + WEIGHT
        # =====================================================================
        form_data = -1
        while form_data == -1:
            form_data = user_input.session_form(mouse_name=self.SUBJECT_NAME)
        self.SUBJECT_WEIGHT = user_input.get_form_subject_weight(form_data)
        self.PROBE_DATA = user_input.get_form_probe_data(form_data)
        # =====================================================================
        # VISUAL STIM
        # =====================================================================
        self.SYNC_SQUARE_X = 1.33
        self.SYNC_SQUARE_Y = -1.03
        self.USE_VISUAL_STIMULUS = True  # Run the visual stim in bonsai
        self.BONSAI_EDITOR = False  # Open the Bonsai editor of visual stim
        bonsai.start_visual_stim(self)
        # =====================================================================
        # SAVE SETTINGS FILE AND TASK CODE
        # =====================================================================
        if not self.DEBUG:
            iotasks.save_session_settings(self)
            iotasks.copy_task_code(self)
            iotasks.save_task_code(self)
            self.bpod_lights(0)

        self.display_logs()
Example #6
0
    def __init__(self, task_settings, user_settings, debug=False, fmake=True):
        self.DEBUG = debug
        make = False if not fmake else ["video"]
        # =====================================================================
        # IMPORT task_settings, user_settings, and SessionPathCreator params
        # =====================================================================
        ts = {
            i: task_settings.__dict__[i]
            for i in [x for x in dir(task_settings) if "__" not in x]
        }
        self.__dict__.update(ts)
        us = {
            i: user_settings.__dict__[i]
            for i in [x for x in dir(user_settings) if "__" not in x]
        }
        self.__dict__.update(us)
        self = iotasks.deserialize_pybpod_user_settings(self)
        spc = SessionPathCreator(self.PYBPOD_SUBJECTS[0],
                                 protocol=self.PYBPOD_PROTOCOL,
                                 make=make)
        self.__dict__.update(spc.__dict__)
        # =====================================================================
        # SUBJECT
        # =====================================================================
        self.SUBJECT_WEIGHT = user.ask_subject_weight(self.PYBPOD_SUBJECTS[0])
        # =====================================================================
        # OSC CLIENT
        # =====================================================================
        self.OSC_CLIENT_PORT = 7110
        self.OSC_CLIENT_IP = "127.0.0.1"
        self.OSC_CLIENT = udp_client.SimpleUDPClient(self.OSC_CLIENT_IP,
                                                     self.OSC_CLIENT_PORT)
        # =====================================================================
        # frame2TTL
        # =====================================================================
        self.F2TTL_GET_AND_SET_THRESHOLDS = frame2TTL.get_and_set_thresholds()
        # =====================================================================
        # ADAPTIVE STUFF
        # =====================================================================
        self.CALIB_FUNC = None
        if self.AUTOMATIC_CALIBRATION:
            self.CALIB_FUNC = adaptive.init_calib_func()
        self.CALIB_FUNC_RANGE = adaptive.init_calib_func_range()
        self.REWARD_VALVE_TIME = adaptive.init_reward_valve_time(self)
        self.STIM_GAIN = 8.0
        # =====================================================================
        # ROTARY ENCODER
        # =====================================================================
        self.ALL_THRESHOLDS = self.STIM_POSITIONS
        self.ROTARY_ENCODER = MyRotaryEncoder(
            self.ALL_THRESHOLDS, self.STIM_GAIN,
            self.PARAMS["COM_ROTARY_ENCODER"])
        # =====================================================================
        # SOUNDS
        # =====================================================================
        self.SOFT_SOUND = None if "ephys" in self.PYBPOD_BOARD else self.SOFT_SOUND
        self.SOUND_SAMPLE_FREQ = sound.sound_sample_freq(self.SOFT_SOUND)

        self.GO_TONE_DURATION = float(self.GO_TONE_DURATION)
        self.GO_TONE_FREQUENCY = int(self.GO_TONE_FREQUENCY)
        self.GO_TONE_AMPLITUDE = float(self.GO_TONE_AMPLITUDE)

        self.SD = sound.configure_sounddevice(
            output=self.SOFT_SOUND, samplerate=self.SOUND_SAMPLE_FREQ)

        self.SOUND_BOARD_BPOD_PORT = "Serial3"
        self.GO_TONE_IDX = 2
        self.GO_TONE = None
        self = sound.init_sounds(self, noise=False)
        if self.SOFT_SOUND is None:
            sound.configure_sound_card(
                sounds=[self.GO_TONE],
                indexes=[self.GO_TONE_IDX],
                sample_rate=self.SOUND_SAMPLE_FREQ,
            )
        self.OUT_STOP_SOUND = (("SoftCode", 0) if self.SOFT_SOUND else
                               ("Serial3", ord("X")))
        self.OUT_TONE = ("SoftCode", 1) if self.SOFT_SOUND else ("Serial3", 5)
        # =====================================================================
        # RUN VISUAL STIM
        # =====================================================================
        bonsai.start_visual_stim(self)
        # =====================================================================
        # SAVE SETTINGS FILE AND TASK CODE
        # =====================================================================
        if not self.DEBUG:
            iotasks.save_session_settings(self)
            iotasks.copy_task_code(self)
            iotasks.save_task_code(self)
            iotasks.copy_video_code(self)
            iotasks.save_video_code(self)
            self.bpod_lights(0)
Example #7
0
    def __init__(self, task_settings, user_settings, debug=False, fmake=True):
        self.DEBUG = debug
        make = True
        # =====================================================================
        # IMPORT task_settings, user_settings, and SessionPathCreator params
        # =====================================================================
        ts = {
            i: task_settings.__dict__[i]
            for i in [x for x in dir(task_settings) if "__" not in x]
        }
        self.__dict__.update(ts)
        us = {
            i: user_settings.__dict__[i]
            for i in [x for x in dir(user_settings) if "__" not in x]
        }
        self.__dict__.update(us)
        self = iotasks.deserialize_pybpod_user_settings(self)
        # Pretend to run a new ephys session
        spc = ph.SessionPathCreator(
            self.PYBPOD_SUBJECTS[0],
            protocol="_iblrig_tasks_ephysChoiceWorld",
            make=False,
        )  # don't make any folders
        # Get previous session folder i.e. the ephys session that just ran
        self.CORRESPONDING_EPHYS_SESSION = spc.PREVIOUS_SESSION_PATH
        # Load its metadata
        self.CORRESPONDING_EPHYS_SETTINGS_DATA = iotasks.load_settings(
            self.CORRESPONDING_EPHYS_SESSION
        )
        if self.CORRESPONDING_EPHYS_SETTINGS_DATA is None:
            self.CORRESPONDING_EPHYS_SETTINGS_DATA = {}
        # Get the vis stim file for an ephys session for the replay later
        self.VISUAL_STIMULUS_FILE_EPHYS = spc.VISUAL_STIMULUS_FILE
        # Patch the dict if no IS_MOCK key is found
        if "IS_MOCK" not in self.CORRESPONDING_EPHYS_SETTINGS_DATA.keys():
            self.CORRESPONDING_EPHYS_SETTINGS_DATA.update({"IS_MOCK": False})
        # run spc normally
        spc = ph.SessionPathCreator(
            self.PYBPOD_SUBJECTS[0], protocol=self.PYBPOD_PROTOCOL, make=make
        )
        self.__dict__.update(spc.__dict__)
        # =====================================================================
        # SETTINGS
        # =====================================================================
        self.RECORD_SOUND = True
        self.RECORD_AMBIENT_SENSOR_DATA = True
        self.RECORD_VIDEO = True
        self.OPEN_CAMERA_VIEW = True  # Always True if RECORD_VIDEO is True

        self.NTRIALS = 300  # Number of trials for the current session
        self.USE_AUTOMATIC_STOPPING_CRITERIONS = None  # Weather to check for the Automatic stopping criterions or not  # noqa
        self.REPEAT_ON_ERROR = False  # not used
        self.INTERACTIVE_DELAY = 0.0
        self.RESPONSE_WINDOW = 60
        self.ITI_CORRECT = 1
        self.ITI_ERROR = 2
        self.CONTRAST_SET = [1.0, 0.25, 0.125, 0.0625, 0.0]  # Full contrast set
        self.CONTRAST_SET_PROBABILITY_TYPE = "biased"
        self.STIM_FREQ = 0.10  # Probably constant - NOT IN USE
        self.STIM_ANGLE = 0.0  # Vertical orientation of Gabor patch
        self.STIM_SIGMA = 7.0  # (azimuth_degree) Size of Gabor patch
        self.STIM_GAIN = 4.0  # (azimuth_degree/mm) Gain of the RE
        # =====================================================================
        # SUBJECT
        # =====================================================================
        # self.SUBJECT_WEIGHT = self.ask_subject_weight()
        self.POOP_COUNT = True
        self.SUBJECT_DISENGAGED_TRIGGERED = False
        self.SUBJECT_DISENGAGED_TRIALNUM = None
        # =====================================================================
        # OSC CLIENT
        # =====================================================================
        self.OSC_CLIENT_IP = "127.0.0.1"
        self.OSC_CLIENT_PORT = 7110
        self.OSC_CLIENT = udp_client.SimpleUDPClient(
            self.OSC_CLIENT_IP, self.OSC_CLIENT_PORT
        )
        # =====================================================================
        # PREVIOUS DATA FILES
        # =====================================================================
        # Not used
        self.LAST_TRIAL_DATA = None  # iotasks.load_data(self.PREVIOUS_SESSION_PATH)
        self.LAST_SETTINGS_DATA = (
            None  # iotasks.load_settings(self.PREVIOUS_SESSION_PATH)
        )
        # Change to False if mock has its own task
        self.IS_MOCK = self.CORRESPONDING_EPHYS_SETTINGS_DATA["IS_MOCK"]
        # Get pregenerated session num (the num in the filename! from corresponding ephys sesison)
        self.SESSION_ORDER = self.CORRESPONDING_EPHYS_SETTINGS_DATA["SESSION_ORDER"]
        self.SESSION_IDX = self.CORRESPONDING_EPHYS_SETTINGS_DATA["SESSION_IDX"]
        self.PREGENERATED_SESSION_NUM = self.CORRESPONDING_EPHYS_SETTINGS_DATA[
            "PREGENERATED_SESSION_NUM"
        ]
        # Load session from file
        (self.STIM_DELAYS, self.STIM_IDS,) = iotasks.load_passive_session_delays_ids(
            self.PREGENERATED_SESSION_NUM
        )
        self.QUIESCENT_PERIOD = None
        self.LEN_BLOCKS = None
        (
            self.POSITIONS,
            self.CONTRASTS,
            self.STIM_PHASE,
        ) = iotasks.load_passive_session_pcs(self.PREGENERATED_SESSION_NUM)
        # =====================================================================
        # ADAPTIVE STUFF
        # =====================================================================
        self.AUTOMATIC_CALIBRATION = True
        self.CALIBRATION_VALUE = 0.067
        self.REWARD_AMOUNT = 1.5
        self.REWARD_TYPE = None

        self.CALIB_FUNC = None
        if self.AUTOMATIC_CALIBRATION:
            self.CALIB_FUNC = adaptive.init_calib_func()
        self.CALIB_FUNC_RANGE = adaptive.init_calib_func_range()
        self.REWARD_VALVE_TIME = adaptive.init_reward_valve_time(self)

        # =====================================================================
        # ROTARY ENCODER
        # =====================================================================
        self.STIM_POSITIONS = [-35, 35]  # All possible positions (deg)
        self.QUIESCENCE_THRESHOLDS = [-2, 2]  # degree
        self.ALL_THRESHOLDS = self.STIM_POSITIONS + self.QUIESCENCE_THRESHOLDS
        self.ROTARY_ENCODER = None
        # =====================================================================
        # frame2TTL
        # =====================================================================
        self.F2TTL_GET_AND_SET_THRESHOLDS = None
        # =====================================================================
        # SOUNDS
        # =====================================================================
        self.SOFT_SOUND = None
        self.SOUND_SAMPLE_FREQ = sound.sound_sample_freq(self.SOFT_SOUND)
        self.SOUND_BOARD_BPOD_PORT = "Serial3"
        self.WHITE_NOISE_DURATION = float(0.5)
        self.WHITE_NOISE_AMPLITUDE = float(0.05)
        self.GO_TONE_DURATION = float(0.1)
        self.GO_TONE_FREQUENCY = int(5000)
        self.GO_TONE_AMPLITUDE = float(0.0151)  # 0.0151 for 70.0 dB SPL CCU

        self.SD = sound.configure_sounddevice(
            output=self.SOFT_SOUND, samplerate=self.SOUND_SAMPLE_FREQ
        )
        # Create sounds and output actions of state machine
        self.GO_TONE = sound.make_sound(
            rate=self.SOUND_SAMPLE_FREQ,
            frequency=self.GO_TONE_FREQUENCY,
            duration=self.GO_TONE_DURATION,
            amplitude=self.GO_TONE_AMPLITUDE,
            fade=0.01,
            chans="stereo",
        )
        self.WHITE_NOISE = sound.make_sound(
            rate=self.SOUND_SAMPLE_FREQ,
            frequency=-1,
            duration=self.WHITE_NOISE_DURATION,
            amplitude=self.WHITE_NOISE_AMPLITUDE,
            fade=0.01,
            chans="stereo",
        )
        self.GO_TONE_IDX = 2
        self.WHITE_NOISE_IDX = 3
        sound.configure_sound_card(
            sounds=[self.GO_TONE, self.WHITE_NOISE],
            indexes=[self.GO_TONE_IDX, self.WHITE_NOISE_IDX],
            sample_rate=self.SOUND_SAMPLE_FREQ,
        )
        self.OUT_TONE = ("SoftCode", 1) if self.SOFT_SOUND else ("Serial3", 6)
        self.OUT_NOISE = ("SoftCode", 2) if self.SOFT_SOUND else ("Serial3", 7)
        self.OUT_STOP_SOUND = (
            ("SoftCode", 0) if self.SOFT_SOUND else ("Serial3", ord("X"))
        )
        # =====================================================================
        # PROBES + WEIGHT
        # =====================================================================
        # form_data = -1
        # while form_data == -1:
        #     form_data = user_input.session_form(mouse_name=self.SUBJECT_NAME)
        self.SUBJECT_WEIGHT = None
        self.PROBE_DATA = None
        # =====================================================================
        # VISUAL STIM
        # =====================================================================
        self.SYNC_SQUARE_X = 1.33
        self.SYNC_SQUARE_Y = -1.03
        self.USE_VISUAL_STIMULUS = True  # Run the visual stim in bonsai
        self.BONSAI_EDITOR = False  # Open the Bonsai editor of visual stim
        # =====================================================================
        # SAVE SETTINGS FILE AND TASK CODE
        # =====================================================================
        if not self.DEBUG:
            iotasks.save_session_settings(self)
            iotasks.copy_task_code(self)
            iotasks.save_task_code(self)
            self.bpod_lights(0)

        self.display_logs()
    def __init__(self, task_settings, user_settings, debug=False, fmake=True):
        self.DEBUG = debug
        make = False if not fmake else ['video']
        # =====================================================================
        # IMPORT task_settings, user_settings, and SessionPathCreator params
        # =====================================================================
        ts = {
            i: task_settings.__dict__[i]
            for i in [x for x in dir(task_settings) if '__' not in x]
        }
        self.__dict__.update(ts)
        us = {
            i: user_settings.__dict__[i]
            for i in [x for x in dir(user_settings) if '__' not in x]
        }
        self.__dict__.update(us)
        self = iotasks.deserialize_pybpod_user_settings(self)
        spc = SessionPathCreator(self.PYBPOD_SUBJECTS[0],
                                 protocol=self.PYBPOD_PROTOCOL,
                                 make=make)
        self.__dict__.update(spc.__dict__)

        # =====================================================================
        # SUBJECT
        # =====================================================================
        self.SUBJECT_WEIGHT = user.ask_subject_weight(self.PYBPOD_SUBJECTS[0])
        self.SUBJECT_DISENGAGED_TRIGGERED = False
        self.SUBJECT_DISENGAGED_TRIALNUM = None
        # =====================================================================
        # OSC CLIENT
        # =====================================================================
        self.OSC_CLIENT_PORT = 7110
        self.OSC_CLIENT_IP = '127.0.0.1'
        self.OSC_CLIENT = udp_client.SimpleUDPClient(self.OSC_CLIENT_IP,
                                                     self.OSC_CLIENT_PORT)
        # =====================================================================
        # PREVIOUS DATA FILES
        # =====================================================================
        self.LAST_TRIAL_DATA = iotasks.load_data(self.PREVIOUS_SESSION_PATH)
        self.LAST_SETTINGS_DATA = iotasks.load_settings(
            self.PREVIOUS_SESSION_PATH)
        # =====================================================================
        # ADAPTIVE STUFF
        # =====================================================================
        self.AR_MIN_VALUE = 1.5 if 'Sucrose' in self.REWARD_TYPE else 2.0
        self.REWARD_AMOUNT = adaptive.init_reward_amount(self)
        self.CALIB_FUNC = None
        if self.AUTOMATIC_CALIBRATION:
            self.CALIB_FUNC = adaptive.init_calib_func()
        self.CALIB_FUNC_RANGE = adaptive.init_calib_func_range()
        self.REWARD_VALVE_TIME = adaptive.init_reward_valve_time(self)
        self.STIM_GAIN = adaptive.init_stim_gain(self)
        self.IMPULSIVE_CONTROL = 'OFF'
        self = adaptive.impulsive_control(self)
        # =====================================================================
        # frame2TTL
        # =====================================================================
        self.F2TTL_GET_AND_SET_THRESHOLDS = frame2TTL.get_and_set_thresholds()
        # =====================================================================
        # ROTARY ENCODER
        # =====================================================================
        self.ALL_THRESHOLDS = (self.STIM_POSITIONS +
                               self.QUIESCENCE_THRESHOLDS)
        self.ROTARY_ENCODER = MyRotaryEncoder(
            self.ALL_THRESHOLDS, self.STIM_GAIN,
            self.PARAMS['COM_ROTARY_ENCODER'])
        # =====================================================================
        # SOUNDS
        # =====================================================================
        self.SOFT_SOUND = None if 'ephys' in self._BOARD else self.SOFT_SOUND
        self.SOUND_SAMPLE_FREQ = sound.sound_sample_freq(self.SOFT_SOUND)

        self.WHITE_NOISE_DURATION = float(self.WHITE_NOISE_DURATION)
        self.WHITE_NOISE_AMPLITUDE = float(self.WHITE_NOISE_AMPLITUDE)
        self.GO_TONE_DURATION = float(self.GO_TONE_DURATION)
        self.GO_TONE_FREQUENCY = int(self.GO_TONE_FREQUENCY)
        self.GO_TONE_AMPLITUDE = float(self.GO_TONE_AMPLITUDE)

        self.SD = sound.configure_sounddevice(
            output=self.SOFT_SOUND, samplerate=self.SOUND_SAMPLE_FREQ)
        # Create sounds and output actions of state machine
        self.SOUND_BOARD_BPOD_PORT = 'Serial3'
        self.GO_TONE = None
        self.WHITE_NOISE = None
        self.GO_TONE_IDX = 2
        self.WHITE_NOISE_IDX = 3
        self = sound.init_sounds(self)  # sets GO_TONE and WHITE_NOISE
        if self.SOFT_SOUND is None:
            sound.configure_sound_card(
                sounds=[self.GO_TONE, self.WHITE_NOISE],
                indexes=[self.GO_TONE_IDX, self.WHITE_NOISE_IDX],
                sample_rate=self.SOUND_SAMPLE_FREQ)
        self.OUT_STOP_SOUND = ('SoftCode',
                               0) if self.SOFT_SOUND else ('Serial3', ord('X'))
        self.OUT_TONE = ('SoftCode', 1) if self.SOFT_SOUND else ('Serial3', 6)
        self.OUT_NOISE = ('SoftCode', 2) if self.SOFT_SOUND else ('Serial3', 7)
        # =====================================================================
        # RUN VISUAL STIM
        # =====================================================================
        bonsai.start_visual_stim(self)
        # =====================================================================
        # SAVE SETTINGS FILE AND TASK CODE
        # =====================================================================
        if not self.DEBUG:
            iotasks.save_session_settings(self)
            iotasks.copy_task_code(self)
            iotasks.save_task_code(self)
            iotasks.copy_video_code(self)
            iotasks.save_video_code(self)
            self.bpod_lights(0)

        self.display_logs()
    def __init__(self, task_settings, user_settings):
        # =====================================================================
        # IMPORT task_settings, user_settings, and SessionPathCreator params
        # =====================================================================
        ts = {
            i: task_settings.__dict__[i]
            for i in [x for x in dir(task_settings) if '__' not in x]
        }
        self.__dict__.update(ts)
        us = {
            i: user_settings.__dict__[i]
            for i in [x for x in dir(user_settings) if '__' not in x]
        }
        self.__dict__.update(us)
        self = iotasks.deserialize_pybpod_user_settings(self)
        spc = SessionPathCreator(self.PYBPOD_SUBJECTS[0],
                                 protocol=self.PYBPOD_PROTOCOL,
                                 make=True)
        self.__dict__.update(spc.__dict__)

        # =====================================================================
        # OSC CLIENT
        # =====================================================================
        self.OSC_CLIENT_PORT = 7110
        self.OSC_CLIENT_IP = '127.0.0.1'
        self.OSC_CLIENT = udp_client.SimpleUDPClient(self.OSC_CLIENT_IP,
                                                     self.OSC_CLIENT_PORT)
        # =====================================================================
        # frame2TTL
        # =====================================================================
        self.F2TTL_GET_AND_SET_THRESHOLDS = frame2TTL.get_and_set_thresholds()
        # =====================================================================
        # PROBES + WEIGHT
        # =====================================================================
        self.FORM_DATA = user_input.session_form(mouse_name=self.SUBJECT_NAME)
        self.PROBE_DATA = user_input.get_form_probe_data(self.FORM_DATA)
        self.SUBJECT_WEIGHT = user_input.get_form_subject_weight(
            self.FORM_DATA)
        # =====================================================================
        # VISUAL STIM
        # =====================================================================
        self.VISUAL_STIMULUS_FILE = None
        self.SCREEN_DIMENSIONS = {'width': 20, 'height': 15}  # cm
        self.SCREEN_EXTRINSICS = {
            'rotation': (0, 0, 0),
            'translation': (0, 0, -8)
        }
        self.SCREEN_VISUAL_SPAN_X = np.rad2deg(
            math.atan(self.SCREEN_DIMENSIONS['width'] / 2 /
                      abs(self.SCREEN_EXTRINSICS['translation'][2]))) * 2
        self.SCREEN_VISUAL_SPAN_Y = np.rad2deg(
            math.atan(self.SCREEN_DIMENSIONS['height'] / 2 /
                      abs(self.SCREEN_EXTRINSICS['translation'][2]))) * 2
        self.VISUAL_STIMULI = {
            0: 'SPACER',
            1: 'receptive_field_mapping',
            2: 'orientation-direction_selectivity',
            3: 'contrast_reversal',
            4: 'task_stimuli',
            5: 'spontaneous_activity',
        }
        self.STIM_ORDER = [0, 5, 0, 2, 0, 1, 0, 3, 0, 4, 0, 5, 0, 2, 0]

        self.VISUAL_STIM_0 = {
            'ttl_num':
            16,
            'ttl_frame_nums': [
                1, 2, 4, 8, 16, 32, 64, 128, 192, 224, 240, 248, 252, 254, 255,
                256
            ],
            'delay_around':
            4  # seconds
        }
        self.VISUAL_STIM_1 = {
            'ttl_num': None,
            'stim_shape': 'square',
            'stim_npatches': 15 * 15,
            'patch_dva': 8,
            'dva_mat': make_square_dvamat(size=15, dva=8),
            'stim_data_file_name': '_iblrig_RFMapStim.raw.bin',
            'stim_file_shape': [15, 15, 'nframes'],
            'stim_on_time': 0.2,  # seconds
            'polarity_start': -1,
            'polarity_end': +1
        }
        self.VISUAL_STIM_2 = {
            'ttl_num': 320,
            'stim_directions_rad': {
                1: 3 * np.pi / 2,
                2: 5 * np.pi / 4,
                3: 1 * np.pi / 1,
                4: 3 * np.pi / 4,
                5: 1 * np.pi / 2,
                6: 1 * np.pi / 4,
                7: 0 * np.pi / 2,
                8: 7 * np.pi / 4,
            },
            'stim_sequence': [1, 2, 3, 4, 5, 6, 7, 8] * 20,
            'stim_tf': 2,  # Hz
            'stim_cpd': 0.05,  # spatial freq, cycles per degree
            'stim_on_time': 2,  # seconds
            'stim_off_time': 1,  # seconds
            'polarity_start': +1,
            'polarity_end': -1,
        }
        self.VISUAL_STIM_3 = {
            'ttl_num': 180,
            'stim_shape': 'square',
            'stim_npatches': 15 * 15,
            'patch_dva': 25,
            'dva_mat': make_square_dvamat(size=15, dva=25),
            'stim_patch_contrasts': {
                1: checkerboard((15, 15)) * 255,
                2: np.abs(checkerboard((15, 15)) - 1) * 255
            },
            'stim_sequence': [1, 2] * 90,
            'stim_on_time': 1,  # seconds
            'stim_off_time': 0,  # seconds
            'polarity_start': +1,
            'polarity_end': -1,
        }
        self.VISUAL_STIM_4 = {
            'ttl_num': 400,
            'stim_spatial_freq': 0.1,  # cyc/º
            'sigma': 7**2,  # dva
            'elevation': 0,
            'orientation': 0,
            'phase': 0,
            'stim_on_time': 2,  # seconds
            'stim_off_time': 1,  # seconds
            'stim_azimuth_set': [-35, 35],
            'stim_contrast_set': [1.0, 0.5, 0.25, 0.125, 0.0625],
            'stim_file':
            'iblrig/visual_stim/ephys_certification/04_ContrastSelectivityTaskStim/stims.csv',
            'stim_file_columns': ('azimuth', 'contrast'),
            'polarity_start': +1,
            'polarity_end': -1,
        }
        # =====================================================================
        # SAVE SETTINGS FILE AND TASK CODE
        # =====================================================================
        iotasks.copy_task_code(self)
        iotasks.save_task_code(self)
        iotasks.save_session_settings(self)
Example #10
0
    def __init__(self, task_settings, user_settings, debug=False, fmake=True):
        self.DEBUG = debug
        # =====================================================================
        # IMPORT task_settings, user_settings, and SessionPathCreator params
        # =====================================================================
        ts = {
            i: task_settings.__dict__[i]
            for i in [x for x in dir(task_settings) if "__" not in x]
        }
        self.__dict__.update(ts)
        us = {
            i: user_settings.__dict__[i]
            for i in [x for x in dir(user_settings) if "__" not in x]
        }
        self.__dict__.update(us)
        self = iotasks.deserialize_pybpod_user_settings(self)
        if not fmake:
            make = False
        elif fmake and "ephys" in self.PYBPOD_BOARD:
            make = True  # True makes only raw_behavior_data folder
        else:
            make = ["video"]  # besides behavior which folders to creae
        spc = SessionPathCreator(self.PYBPOD_SUBJECTS[0],
                                 protocol=self.PYBPOD_PROTOCOL,
                                 make=make)
        self.__dict__.update(spc.__dict__)

        # =====================================================================
        # DELAY SESSION INITIATION BY
        # =====================================================================
        self.SESSION_START_DELAY_SEC = 0
        # =====================================================================
        # frame2TTL
        # =====================================================================
        self.F2TTL_GET_AND_SET_THRESHOLDS = frame2TTL.get_and_set_thresholds()
        # =====================================================================
        # SUBJECT
        # =====================================================================
        self.SUBJECT_WEIGHT = user.ask_subject_weight(self.PYBPOD_SUBJECTS[0])
        self.SUBJECT_DISENGAGED_TRIGGERED = False
        self.SUBJECT_DISENGAGED_TRIALNUM = None
        # =====================================================================
        # OSC CLIENT
        # =====================================================================
        self.OSC_CLIENT_PORT = 7110
        self.OSC_CLIENT_IP = "127.0.0.1"
        self.OSC_CLIENT = udp_client.SimpleUDPClient(self.OSC_CLIENT_IP,
                                                     self.OSC_CLIENT_PORT)
        # =====================================================================
        # PREVIOUS DATA FILES
        # =====================================================================
        self.LAST_TRIAL_DATA = iotasks.load_data(self.PREVIOUS_SESSION_PATH)
        self.LAST_SETTINGS_DATA = iotasks.load_settings(
            self.PREVIOUS_SESSION_PATH)
        # =====================================================================
        # ADAPTIVE STUFF
        # =====================================================================
        self.CALIB_FUNC = None
        if self.AUTOMATIC_CALIBRATION:
            self.CALIB_FUNC = adaptive.init_calib_func()
        self.CALIB_FUNC_RANGE = adaptive.init_calib_func_range()
        self.REWARD_VALVE_TIME = adaptive.init_reward_valve_time(self)

        # =====================================================================
        # ROTARY ENCODER
        # =====================================================================
        self.ALL_THRESHOLDS = self.STIM_POSITIONS + self.QUIESCENCE_THRESHOLDS
        self.ROTARY_ENCODER = MyRotaryEncoder(
            self.ALL_THRESHOLDS, self.STIM_GAIN,
            self.PARAMS["COM_ROTARY_ENCODER"])
        # =====================================================================
        # SOUNDS
        # =====================================================================
        self.SOFT_SOUND = None if "ephys" in self.PYBPOD_BOARD else self.SOFT_SOUND
        self.SOUND_SAMPLE_FREQ = sound.sound_sample_freq(self.SOFT_SOUND)

        self.WHITE_NOISE_DURATION = float(self.WHITE_NOISE_DURATION)
        self.WHITE_NOISE_AMPLITUDE = float(self.WHITE_NOISE_AMPLITUDE)
        self.GO_TONE_DURATION = float(self.GO_TONE_DURATION)
        self.GO_TONE_FREQUENCY = int(self.GO_TONE_FREQUENCY)
        self.GO_TONE_AMPLITUDE = float(self.GO_TONE_AMPLITUDE)

        self.SD = sound.configure_sounddevice(
            output=self.SOFT_SOUND, samplerate=self.SOUND_SAMPLE_FREQ)
        # Create sounds and output actions of state machine
        self.GO_TONE = None
        self.WHITE_NOISE = None
        self = sound.init_sounds(self)  # sets GO_TONE and WHITE_NOISE
        # SoundCard config params
        self.SOUND_BOARD_BPOD_PORT = "Serial3"
        self.GO_TONE_IDX = 2
        self.WHITE_NOISE_IDX = 3
        if self.SOFT_SOUND is None:
            sound.configure_sound_card(
                sounds=[self.GO_TONE, self.WHITE_NOISE],
                indexes=[self.GO_TONE_IDX, self.WHITE_NOISE_IDX],
                sample_rate=self.SOUND_SAMPLE_FREQ,
            )

        self.OUT_TONE = ("SoftCode", 1) if self.SOFT_SOUND else ("Serial3", 6)
        self.OUT_NOISE = ("SoftCode", 2) if self.SOFT_SOUND else ("Serial3", 7)
        self.OUT_STOP_SOUND = (("SoftCode", 0) if self.SOFT_SOUND else
                               ("Serial3", ord("X")))

        # =====================================================================
        # SAVE SETTINGS FILE AND TASK CODE
        # =====================================================================
        if not self.DEBUG:
            iotasks.save_session_settings(self)
            iotasks.copy_task_code(self)
            iotasks.save_task_code(self)
            if "ephys" not in self.PYBPOD_BOARD:
                iotasks.copy_video_code(self)
                iotasks.save_video_code(self)
            self.bpod_lights(0)

        self.display_logs()
Example #11
0
    def __init__(self, task_settings, user_settings):
        # =====================================================================
        # IMPORT task_settings, user_settings, and SessionPathCreator params
        # =====================================================================
        ts = {
            i: task_settings.__dict__[i]
            for i in [x for x in dir(task_settings) if "__" not in x]
        }
        self.__dict__.update(ts)
        us = {
            i: user_settings.__dict__[i]
            for i in [x for x in dir(user_settings) if "__" not in x]
        }
        self.__dict__.update(us)
        self = iotasks.deserialize_pybpod_user_settings(self)
        spc = SessionPathCreator(
            self.PYBPOD_SUBJECTS[0], protocol=self.PYBPOD_PROTOCOL, make=True
        )
        self.__dict__.update(spc.__dict__)

        # =====================================================================
        # OSC CLIENT
        # =====================================================================
        self.OSC_CLIENT_PORT = 7110
        self.OSC_CLIENT_IP = "127.0.0.1"
        self.OSC_CLIENT = udp_client.SimpleUDPClient(
            self.OSC_CLIENT_IP, self.OSC_CLIENT_PORT
        )
        # =====================================================================
        # frame2TTL
        # =====================================================================
        self.F2TTL_GET_AND_SET_THRESHOLDS = frame2TTL.get_and_set_thresholds()
        # =====================================================================
        # PROBES + WEIGHT
        # =====================================================================
        self.FORM_DATA = user_input.session_form(mouse_name=self.SUBJECT_NAME)
        self.PROBE_DATA = user_input.get_form_probe_data(self.FORM_DATA)
        self.SUBJECT_WEIGHT = user_input.get_form_subject_weight(self.FORM_DATA)
        # =====================================================================
        # VISUAL STIM
        # =====================================================================
        self.VISUAL_STIMULUS_FILE = None
        self.SCREEN_DIMENSIONS = {"width": 20, "height": 15}  # cm
        self.SCREEN_EXTRINSICS = {"rotation": (0, 0, 0), "translation": (0, 0, -8)}
        self.SCREEN_VISUAL_SPAN_X = (
            np.rad2deg(
                math.atan(
                    self.SCREEN_DIMENSIONS["width"]
                    / 2
                    / abs(self.SCREEN_EXTRINSICS["translation"][2])
                )
            )
            * 2
        )
        self.SCREEN_VISUAL_SPAN_Y = (
            np.rad2deg(
                math.atan(
                    self.SCREEN_DIMENSIONS["height"]
                    / 2
                    / abs(self.SCREEN_EXTRINSICS["translation"][2])
                )
            )
            * 2
        )
        self.VISUAL_STIMULI = {
            0: "SPACER",
            1: "receptive_field_mapping",
            2: "orientation-direction_selectivity",
            3: "contrast_reversal",
            4: "task_stimuli",
            5: "spontaneous_activity",
        }
        self.STIM_ORDER = [0, 5, 0, 2, 0, 1, 0, 3, 0, 4, 0, 5, 0, 2, 0]

        self.VISUAL_STIM_0 = {
            "ttl_num": 16,
            "ttl_frame_nums": [
                1,
                2,
                4,
                8,
                16,
                32,
                64,
                128,
                192,
                224,
                240,
                248,
                252,
                254,
                255,
                256,
            ],
            "delay_around": 4,  # seconds
        }
        self.VISUAL_STIM_1 = {
            "ttl_num": None,
            "stim_shape": "square",
            "stim_npatches": 15 * 15,
            "patch_dva": 8,
            "dva_mat": make_square_dvamat(size=15, dva=8),
            "stim_data_file_name": "_iblrig_RFMapStim.raw.bin",
            "stim_file_shape": [15, 15, "nframes"],
            "stim_on_time": 0.2,  # seconds
            "polarity_start": -1,
            "polarity_end": +1,
        }
        self.VISUAL_STIM_2 = {
            "ttl_num": 320,
            "stim_directions_rad": {
                1: 3 * np.pi / 2,
                2: 5 * np.pi / 4,
                3: 1 * np.pi / 1,
                4: 3 * np.pi / 4,
                5: 1 * np.pi / 2,
                6: 1 * np.pi / 4,
                7: 0 * np.pi / 2,
                8: 7 * np.pi / 4,
            },
            "stim_sequence": [1, 2, 3, 4, 5, 6, 7, 8] * 20,
            "stim_tf": 2,  # Hz
            "stim_cpd": 0.05,  # spatial freq, cycles per degree
            "stim_on_time": 2,  # seconds
            "stim_off_time": 1,  # seconds
            "polarity_start": +1,
            "polarity_end": -1,
        }
        self.VISUAL_STIM_3 = {
            "ttl_num": 180,
            "stim_shape": "square",
            "stim_npatches": 15 * 15,
            "patch_dva": 25,
            "dva_mat": make_square_dvamat(size=15, dva=25),
            "stim_patch_contrasts": {
                1: checkerboard((15, 15)) * 255,
                2: np.abs(checkerboard((15, 15)) - 1) * 255,
            },
            "stim_sequence": [1, 2] * 90,
            "stim_on_time": 1,  # seconds
            "stim_off_time": 0,  # seconds
            "polarity_start": +1,
            "polarity_end": -1,
        }
        self.VISUAL_STIM_4 = {
            "ttl_num": 400,
            "stim_spatial_freq": 0.1,  # cyc/º
            "sigma": 7 ** 2,  # dva
            "elevation": 0,
            "orientation": 0,
            "phase": 0,
            "stim_on_time": 2,  # seconds
            "stim_off_time": 1,  # seconds
            "stim_azimuth_set": [-35, 35],
            "stim_contrast_set": [1.0, 0.5, 0.25, 0.125, 0.0625],
            "stim_file":
                "iblrig/visual_stim/ephys_certification/04_ContrastSelectivityTaskStim/stims.csv",
            "stim_file_columns": ("azimuth", "contrast"),
            "polarity_start": +1,
            "polarity_end": -1,
        }
        # =====================================================================
        # SAVE SETTINGS FILE AND TASK CODE
        # =====================================================================
        iotasks.copy_task_code(self)
        iotasks.save_task_code(self)
        iotasks.save_session_settings(self)