def _extract(self): choice = Choice( self.session_path).extract(bpod_trials=self.bpod_trials, settings=self.settings, save=False)[0] f2TTL = [ raw.get_port_events(tr, name="BNC1") for tr in self.bpod_trials ] stimOn_times = np.array([]) stimOff_times = np.array([]) stimFreeze_times = np.array([]) for tr in f2TTL: if tr and len(tr) == 2: stimOn_times = np.append(stimOn_times, tr[0]) stimOff_times = np.append(stimOff_times, tr[-1]) stimFreeze_times = np.append(stimFreeze_times, np.nan) elif tr and len(tr) >= 3: stimOn_times = np.append(stimOn_times, tr[0]) stimOff_times = np.append(stimOff_times, tr[-1]) stimFreeze_times = np.append(stimFreeze_times, tr[-2]) else: stimOn_times = np.append(stimOn_times, np.nan) stimOff_times = np.append(stimOff_times, np.nan) stimFreeze_times = np.append(stimFreeze_times, np.nan) # In no_go trials no stimFreeze happens jsut stim Off stimFreeze_times[choice == 0] = np.nan # Check for trigger times # 2nd order criteria: # stimOn -> Closest one to stimOnTrigger? # stimOff -> Closest one to stimOffTrigger? # stimFreeze -> Closest one to stimFreezeTrigger? return stimOn_times, stimOff_times, stimFreeze_times
def _extract(self): go_cue_times = np.zeros([ len(self.bpod_trials), ]) for ind, tr in enumerate(self.bpod_trials): if raw.get_port_events(tr, 'BNC2'): bnchigh = tr['behavior_data']['Events timestamps'].get( 'BNC2High', None) if bnchigh: go_cue_times[ind] = bnchigh[0] continue bnclow = tr['behavior_data']['Events timestamps'].get( 'BNC2Low', None) if bnclow: go_cue_times[ind] = bnclow[0] - 0.1 continue go_cue_times[ind] = np.nan else: go_cue_times[ind] = np.nan nmissing = np.sum(np.isnan(go_cue_times)) # Check if all stim_syncs have failed to be detected if np.all(np.isnan(go_cue_times)): _logger.warning( f'{self.session_path}: Missing ALL !! BNC2 TTLs ({nmissing} trials)' ) # Check if any stim_sync has failed be detected for every trial elif np.any(np.isnan(go_cue_times)): _logger.warning( f'{self.session_path}: Missing BNC2 TTLs on {nmissing} trials') return go_cue_times
def get_stimOn_times_ge5(session_path, data=False): """ Find first and last stim_sync pulse of the trial. stimOn_times should be the first after the stim_on state. (Stim updates are in BNC1High and BNC1Low - frame2TTL device) Check that all trials have frame changes. Find length of stim_on_state [start, stop]. If either check fails the HW device failed to detect the stim_sync square change Substitute that trial's missing or incorrect value with a NaN. return stimOn_times """ if not data: data = raw.load_data(session_path) # Get all stim_sync events detected stim_sync_all = [ raw.get_port_events(tr['behavior_data']['Events timestamps'], 'BNC1') for tr in data ] stim_sync_all = [np.array(x) for x in stim_sync_all] # Get the stim_on_state that triggers the onset of the stim stim_on_state = np.array([ tr['behavior_data']['States timestamps']['stim_on'][0] for tr in data ]) stimOn_times = np.array([]) for sync, on, off in zip(stim_sync_all, stim_on_state[:, 0], stim_on_state[:, 1]): pulse = sync[np.where(np.bitwise_and((sync > on), (sync <= off)))] if pulse.size == 0: stimOn_times = np.append(stimOn_times, np.nan) else: stimOn_times = np.append(stimOn_times, pulse) nmissing = np.sum(np.isnan(stimOn_times)) # Check if all stim_syncs have failed to be detected if np.all(np.isnan(stimOn_times)): logger_.error( f'{session_path}: Missing ALL BNC1 stimulus ({nmissing} trials') # Check if any stim_sync has failed be detected for every trial if np.any(np.isnan(stimOn_times)): logger_.warning( f'{session_path}: Missing BNC1 stimulus on {nmissing} trials') return stimOn_times
def _extract(self): """ Find the stim sync pulses of each trial. There should be exactly three TTLs per trial. stimCenter_times should be the third TTL pulse. (Stim updates are in BNC1High and BNC1Low - frame2TTL device) """ # Get all stim_sync events detected ttls = [raw.get_port_events(tr, 'BNC1') for tr in self.bpod_trials] stim_center_triggers, _ = StimCenterTriggerTimes( self.session_path).extract(self.bpod_trials, self.settings) # StimCenter times stim_center_times = np.full(stim_center_triggers.shape, np.nan) for i, (sync, last) in enumerate(zip(ttls, stim_center_triggers)): """We expect there to be 3 pulses per trial; if this is the case, stim center will be the third pulse. If any pulses are missing, we can only be confident of the correct one if exactly one pulse occurs after the stim center trigger""" if len(sync) == 3 or (len(sync) > 0 and sum(pulse > last for pulse in sync) == 1): stim_center_times[i] = sync[-1] return stim_center_times
sma.add_state(state_name='start', state_timer=2, output_actions=[('SoftCode', 1)], state_change_conditions={'Tup': 'listen'}) sma.add_state(state_name='listen', state_timer=25, output_actions=[], state_change_conditions={'Tup': 'exit'}) # Send state machine description to Bpod device bpod.send_state_machine(sma) # Run state machine bpod.run_state_machine(sma) # Locks until state machine 'exit' is reached data = bpod.session.current_trial.export() BNC1 = raw.get_port_events(data['Events timestamps'], name='BNC1') # print(BNC1, flush=True) # print(BNC1, flush=True) # print(len(BNC1), flush=True) if len(BNC1) == 1000: log.info("PASS 1000 pulses detected") sys.stdout.flush() else: log.error(f"FAILED to detect 1000 pulses: {len(BNC1)} != 1000") sys.stdout.flush() with open(bpod_data_file, 'a') as f: f.write(json.dumps(BNC1)) f.write('\n') with open(bpod_data_lengths_file, 'a') as f: f.write(json.dumps(len(BNC1))) f.write('\n')
def _extract(self): # Extract all trials... # Get all stim_sync events detected ttls = [raw.get_port_events(tr, 'BNC1') for tr in self.bpod_trials] # Report missing events n_missing = sum(len(pulses) != 3 for pulses in ttls) # Check if all stim syncs have failed to be detected if n_missing == len(ttls): _logger.error( f'{self.session_path}: Missing ALL BNC1 TTLs ({n_missing} trials)' ) elif n_missing > 0: # Check if any stim_sync has failed be detected for every trial _logger.warning( f'{self.session_path}: Missing BNC1 TTLs on {n_missing} trial(s)' ) # Extract datasets common to trainingChoiceWorld training = [ ContrastLR, FeedbackTimes, Intervals, GoCueTimes, StimOnTriggerTimes ] out, _ = run_extractor_classes(training, session_path=self.session_path, save=False, bpod_trials=self.bpod_trials, settings=self.settings) # GoCueTriggerTimes is the same event as StimOnTriggerTimes out['goCueTrigger_times'] = out['stimOnTrigger_times'].copy() # StimOn times stimOn_times = np.full(out['stimOnTrigger_times'].shape, np.nan) stim_center_triggers, _ = (StimCenterTriggerTimes( self.session_path).extract(self.bpod_trials, self.settings)) for i, (sync, last) in enumerate(zip(ttls, stim_center_triggers)): """We expect there to be 3 pulses per trial; if this is the case, stim on will be the second pulse. If 1 pulse is missing, we can only be confident of the correct one if both pulses occur before the stim center trigger""" if len(sync) == 3 or (len(sync) == 2 and sum(pulse < last for pulse in sync) == 2): stimOn_times[i] = sync[1] out['stimOn_times'] = stimOn_times # RewardVolume trial_volume = [x['reward_amount'] for x in self.bpod_trials] out['rewardVolume'] = np.array(trial_volume).astype(np.float64) # StimOffTrigger times (not saved) stimOffTriggers, _ = (StimOffTriggerTimes(self.session_path).extract( self.bpod_trials, self.settings)) # StimOff times """ There should be exactly three TTLs per trial. stimOff_times should be the first TTL pulse. If 1 or more pulses are missing, we can not be confident of assigning the correct one. """ out['stimOff_times'] = np.array([ sync[0] if len(sync) == 3 else np.nan for sync, off in zip(ttls[1:], stimOffTriggers) ]) # FeedbackType is always positive out['feedbackType'] = np.ones(len(out['feedback_times']), dtype=np.int8) # NB: We lose the last trial because the stim off event occurs at trial_num + 1 n_trials = out['stimOff_times'].size return [out[k][:n_trials] for k in self.var_names]
) sma.add_state( state_name="listen", state_timer=25, output_actions=[], state_change_conditions={"Tup": "exit"}, ) # Send state machine description to Bpod device bpod.send_state_machine(sma) # Run state machine if not bpod.run_state_machine(sma): # Locks until state machine 'exit' is reached break data = bpod.session.current_trial.export() BNC1 = raw.get_port_events(data["Events timestamps"], name="BNC1") # print(BNC1, flush=True) # print(BNC1, flush=True) # print(len(BNC1), flush=True) if len(BNC1) == 1000: log.info("PASS 1000 pulses detected") sys.stdout.flush() else: log.error(f"FAILED to detect 1000 pulses: {len(BNC1)} != 1000") sys.stdout.flush() with open(bpod_data_file, "a") as f: f.write(json.dumps(BNC1)) f.write("\n") f.flush() with open(bpod_data_lengths_file, "a") as f: f.write(json.dumps(len(BNC1)))