AllenInstitute / AllenSDK

code for reading and processing Allen Institute for Brain Science data
https://allensdk.readthedocs.io/en/latest/
Other
333 stars 149 forks source link

Add is_sham_change to VBN stimulus_presentations table #2643

Open corbennett opened 1 year ago

corbennett commented 1 year ago

Describe the use case that is addressed by this feature. Currently, it's difficult to find which stimuli were the sham-changes in catch trials from the VBN session stimulus_presentations table. There is a column called is_change which indicates which stimuli were the change stimuli during go trials. It would be very helpful to add an analogous column called `is_sham_change' to indicate which stimuli where the sham-changes during catch trials.

Do you want to work on this issue? I'm happy to provide prototype code that accomplishes this.

aamster commented 1 year ago

@corbennett can you please describe what is a sham change? How is it derived? We should be able to write code for it.

corbennett commented 1 year ago

Some of the trials in the change detection task are 'catch' trials. This means that the image doesn't actually change, but we monitor for licks to estimate the mouse's false alarm rate. These 'sham-changes' occur with the same timing statistics as the real changes. Here's some code to get these:

This first bit is just to merge the stimulus_presentations table and the trials table for a session. Note that most of this code will be unnecessary after https://github.com/AllenInstitute/AllenSDK/issues/2563 is addressed:

trials = session.trials   #get trials table
stim_presentations = session.stimulus_presentations #get stim presentations table
trial_start_times = trials['start_time'] #get the start times for every behavior trial
stim_presentation_starts = stim_presentations.start_time #and the start times for every stim presentation

#Assign every stim to a trial based on when it was shown
stim_trial_assignments = np.searchsorted(trial_start_times, stim_presentation_starts) - 1
stim_presentations['behavior_trial_id'] = stim_trial_assignments

#Clean up result
#First don't assign trials to stims that occurred outside the behavior
stim_presentations.loc[stim_presentations.start_time>trials.iloc[-1]['stop_time'], 'behavior_trial_id'] = np.nan

#Second copy the trial assignments from the active block to the passive block
stim_presentations.loc[stim_presentations.stimulus_block==5, 'behavior_trial_id'] = stim_presentations[stim_presentations.active]['behavior_trial_id'].values

#Now users can merge the two tables with the following line:
stim_trials = stim_presentations.merge(trials, left_on='behavior_trial_id', right_index=True, how='left')

Now that the tables are merged, we can make our new column:

catch_frames = stim_trials[stim_trials['catch']==True]['change_frame'].unique()
stim_trials['is_sham_change'] = False
catch_flashes = stim_trials[stim_trials['start_frame'].isin(catch_frames)].index.values
stim_trials.loc[catch_flashes, 'is_sham_change'] = True
stim_trials.loc[stim_trials.stimulus_block==5, 'is_sham_change'] = stim_trials[stim_trials.active]['is_sham_change'].values #copy to the passive block