trialStimStartFrames = d['trialStimStartFrame'][:trialEndFrames.size] trialRewardDirection = d['trialRewardDir'][:trialEndFrames.size] trialResponse = d['trialResponse'][:trialEndFrames.size] deltaWheel = d['deltaWheelPos'][:] trialOpenLoopFrames = d['trialOpenLoopFrames'][:] trialResponseFrames = d['trialResponseFrame'][:] trialMaskOnset = d['trialMaskOnset'][:] maskContrast = d['trialMaskContrast'][:] preStimFrames = trialStimStartFrames-trialStartFrames if 'trialStimStartFrame' in d else np.array([d['preStimFrames'][:]]*trialStartFrames.size) trialStartFrames += preStimFrames nogo = d['trialTargetFrames'][:-1]==0 ignoreTrials = ignore_trials(d) postTrialFrames = 0 if d['postRewardTargetFrames'][()]>0 else 1 #make sure we have at least one frame after the reward data = list(zip(trialRewardDirection, trialResponse, trialStartFrames, trialStimStartFrame, trialResponseFrame, trialEndFrames, trialMaskOnset, maskContrast)) index = range(len(trialResponse)) df = pd.DataFrame(data, index=index, columns=['rewDir', 'resp', 'trialStart', 'stimStart', 'respFrame', 'endFrame', 'soa', 'mask']) fig, ax = plt.subplots() # turnRightTrials == stim presented on L, turn right - viceversa for turnLeftTrials - or for orientation, turn right nogoTrials = []
def session(data, ignoreRepeats=True, printValues=True): d = data def count(resp, direction): return len(trialResponse[(trialResponse == resp) & (trialRewardDirection == direction) & (trialTargetFrames != 0)]) trialResponse = d['trialResponse'][:] trialRewardDirection = d['trialRewardDir'][:len(trialResponse)] trialTargetFrames = d['trialTargetFrames'][:len(trialResponse)] trialMaskContrast = d['trialMaskContrast'][:len(trialResponse)] trialRewards = 0 for trial in trialResponse: if trial == 1: trialRewards += 1 if ignoreRepeats == True: trialResponseOG = trialResponse if 'trialRepeat' in d.keys(): prevTrialIncorrect = d['trialRepeat'][:len(trialResponse)] else: prevTrialIncorrect = np.concatenate( ([False], trialResponseOG[:-1] < 1)) trialResponse = trialResponseOG[prevTrialIncorrect == False] trialRewardDirection = trialRewardDirection[prevTrialIncorrect == False] trialTargetFrames = trialTargetFrames[prevTrialIncorrect == False] trialMaskContrast = trialMaskContrast[prevTrialIncorrect == False] print('Repeats: ' + (str((len(trialResponseOG) - len(trialResponse)))) + '/' + str(len(trialResponseOG))) print((round(len(trialResponseOG) - len(trialResponse)) / len(trialResponseOG))) elif ignoreRepeats == False: trialResponse = d['trialResponse'][:] #nogo_turn(d, ignoreRepeats=False, returnArray=False)[0] print('Trials: ' + (str(len(trialResponse)))) else: pass ignoreTrials = ignore_trials(d) ignoreBooleanMask = np.zeros(len(trialResponse), dtype=bool) for i, m in enumerate(ignoreBooleanMask): if i in ignoreTrials: ignoreBooleanMask[i] = True trialResponse = trialResponse[ ignoreBooleanMask == False] # potentially poor wording, but this is using the boolean mask trialRewardDirection = trialRewardDirection[ignoreBooleanMask == False] trialTargetFrames = trialTargetFrames[ignoreBooleanMask == False] trialMaskContrast = trialMaskContrast[ignoreBooleanMask == False] #how to use this indexing rightTurnTotal = sum( (trialRewardDirection == 1) & (trialTargetFrames != 0)) #left stim leftTurnTotal = sum( (trialRewardDirection == -1) & (trialTargetFrames != 0)) #right stim nogoTotal = sum((trialTargetFrames == 0) & (trialMaskContrast == 0)) # count(response, reward direction) where -1 is turn left rightTurnCorr, leftTurnCorr = count(1, 1), count(1, -1) rightTurnIncorrect, leftTurnIncorrect = count(-1, 1), count(-1, -1) rightNoResp, leftNoResp = count(0, 1), count(0, -1) nogoCorr = len( trialResponse[(trialResponse == 1) & (trialTargetFrames == 0) & (trialMaskContrast == 0)]) nogoMove = len( trialResponse[(trialResponse == -1) & (trialTargetFrames == 0) & (trialMaskContrast == 0)]) respTotal = len( trialResponse[(trialResponse != 0) & (trialTargetFrames > 0)]) # response of GO trials totalCorrect = len( trialResponse[trialResponse == 1]) # this includes nogos total = len(trialResponse) trialRewards2 = 0 for trial in trialResponse: if trial == 1: trialRewards2 += 1 print('Counted rewards: ' + str(trialRewards2)) print("Rewards this session: " + str(trialRewards)) cell_texts = dict() for i, (num, denom, title) in enumerate( zip([ rightTurnCorr, rightTurnIncorrect, rightNoResp, leftTurnCorr, leftTurnIncorrect, leftNoResp, nogoCorr, (leftTurnCorr + rightTurnCorr), totalCorrect ], [ rightTurnTotal, rightTurnTotal, rightTurnTotal, leftTurnTotal, leftTurnTotal, leftTurnTotal, nogoTotal, respTotal, total ], [ 'Turn R % Correct:', 'Turn R % Incorre:', 'Turn R % No Resp:', 'L % Correct:', 'L % Incorre:', 'L % No Resp:', 'NoGo Corr:', 'Total Correct, given Response:', 'Total Correct (incl nogos):' ])): if printValues == True: print(str(title) + ' ' + str(round(num / denom, 2))) else: val = (round(num / denom, 2)) cell_texts.update({title: val}) return cell_texts
def plot_soa(data, ignoreNoRespAfter=None, showNogo=True): matplotlib.rcParams['pdf.fonttype'] = 42 d = data end = ignore_after( d, ignoreNoRespAfter)[0] if ignoreNoRespAfter is not None else len( d['trialResponse'][:]) ignore = ignore_trials(d) # ignore trials with early movement ignoring = np.full(end, 0) for i, _ in enumerate(ignoring): if i in ignore: ignoring[i] = 1 # bring in and clean relevant variables trialResponse = d['trialResponse'][:end][ignoring == 0] trialRewardDirection = d['trialRewardDir'][:end][ignoring == 0] trialTargetFrames = d['trialTargetFrames'][:end][ignoring == 0] trialMaskContrast = d['trialMaskContrast'][:end][ignoring == 0] trialMaskPosition = d['trialMaskPos'][:end][ignoring == 0] trialType = d['trialType'][:end][ignoring == 0] trialStimStart = d['trialStimStartFrame'][:end][ignoring == 0] trialRespFrame = d['trialResponseFrame'][:end][ignoring == 0] deltaWheel = d['deltaWheelPos'][:] framerate = int(np.round(1 / np.median(d['frameIntervals'][:]))) maskOnset = d['maskOnset'][()] * 1000 / framerate trialMaskOnset = d['trialMaskOnset'][:end][ignoring == 0] * (1000 / framerate) # create new, simpler array for mask position trialMaskArray = np.full(len(trialMaskPosition), 0) # used later to filter trials for i, t in enumerate(trialMaskPosition): if 480 in t: trialMaskArray[i] = 1 # mask lateral (overlapping target) elif 270 in t: trialMaskArray[i] = 2 # mask center else: trialMaskArray[i] = 0 # filter and count target only trials (no mask) # these are independent from mask postition and thus outside of loop below targetOnlyVal = maskOnset[-1] + round(np.mean( np.diff(maskOnset))) # assigns evenly-spaced value from soas for i, (mask, trial) in enumerate(zip( trialMaskOnset, trialTargetFrames)): # filters target-Only trials if trial > 0 and mask == 0: trialMaskOnset[i] = targetOnlyVal targetOnlyHit = [[], []] # [left turning], [right turning] targetOnlyResp = [[], []] targetOnlyTotals = [[], []] for i, side in enumerate([-1, 1]): # [L turning], [R turning] for (typ, rew, resp) in zip(trialType, trialRewardDirection, trialResponse): if typ == 'targetOnly': if rew == side: targetOnlyTotals[i].append(1) if resp == 1: targetOnlyHit[i].append(1) if resp != 0: targetOnlyResp[i].append(1) def total(var): return list(map(sum, var)) targetOnlyHit = total(targetOnlyHit) targetOnlyResp = total(targetOnlyResp) targetOnlyTotals = total(targetOnlyTotals) ### PLOTTING for mask, j in zip(['mask lateral', 'mask center'], [1, 2]): # depending on mask position, filter and count trial resps # [turn L] , [turn R] hits = [[], []] misses = [[], []] noResps = [[], []] for i, direction in enumerate([-1, 1]): directionResponses = [ trialResponse[(trialRewardDirection == direction) & (trialMaskArray == j) & (trialMaskOnset == soa)] for soa in np.unique(maskOnset) ] hits[i].append([np.sum(drs == 1) for drs in directionResponses]) misses[i].append([np.sum(drs == -1) for drs in directionResponses]) noResps[i].append([np.sum(drs == 0) for drs in directionResponses]) hits = np.squeeze(np.array(hits)) misses = np.squeeze(np.array(misses)) noResps = np.squeeze(np.array(noResps)) totalTrials = hits + misses + noResps respOnly = hits + misses # mask only -- mask only center and side maskOnlyTurns = [[], []] # 1st is indices, 2nd is turning dir for i, (t, pos, start, end) in enumerate( zip(trialType, trialMaskArray, trialStimStart, trialRespFrame)): if t == 'maskOnly' and pos == j: wheel = (np.cumsum(deltaWheel[start:end])[-1]) maskOnlyTurns[0].append(i) maskOnlyTurns[1].append((wheel / abs(wheel)).astype(int)) ## add catch? after this loop? maskOnlyTotal = len(trialResponse[(trialMaskContrast > 0) & (trialTargetFrames == 0)]) maskOnlyR = maskOnlyTurns[1].count(1) maskOnlyL = maskOnlyTurns[1].count(-1) maskOnlyMove = len(maskOnlyTurns) for title in (['Response Rate', 'Fraction Correct Given Response']): fig, ax = plt.subplots() if mask == 'mask lateral': plt.suptitle('Mask Overlaps target') elif mask == 'mask center': plt.suptitle('Mask Center Screen (non-overlapping)') if title == 'Response Rate': ax.plot(maskOnset, respOnly[0] / totalTrials[0], 'bo-', lw=3, alpha=.7) # left turning ax.plot(maskOnset, respOnly[1] / totalTrials[1], 'ro-', lw=3, alpha=.7) # right turning #plot mask only for given mask position ax.plot(5, (maskOnlyR / maskOnlyTotal), 'ro') ax.plot(5, (maskOnlyL / maskOnlyTotal), 'bo') ax.plot(5, ((maskOnlyTotal - maskOnlyCorr) / maskOnlyTotal), 'ko') ax.plot(targetOnlyVal, targetOnlyResp[0] / targetOnlyTotals[0], 'bo') ax.plot(targetOnlyVal, targetOnlyResp[1] / targetOnlyTotals[1], 'ro') ### add catch trials to resp rate?? ### add catch counts as text at top denom = totalTrials elif title == 'Fraction Correct Given Response': ax.plot(maskOnset, hits[0] / respOnly[0], 'bo-', lw=3, alpha=.7) # left turning ax.plot(maskOnset, hits[1] / respOnly[1], 'ro-', lw=3, alpha=.7) # right turning ax.plot(targetOnlyVal, targetOnlyHit[0] / targetOnlyResp[0], 'bo') ax.plot(targetOnlyVal, targetOnlyHit[1] / targetOnlyResp[1], 'ro') denom = respOnly for x, Ltrials, Rtrials in zip( maskOnset, denom[0], denom[1]): #denom[0]==L, denom[1]==R for y, n, clr in zip((1.03, 1.08), [Rtrials, Ltrials], 'rb'): fig.text(x, y, str(n), transform=ax.transData, color=clr, fontsize=10, ha='center', va='bottom') formatFigure(fig, ax, xLabel='Mask Onset From Target Onset (ms)', yLabel=title) ax.set_title(str(d).split('_')[-3:-1], fontdict={'fontsize': 10}, pad=10) xticks = np.append(maskOnset, targetOnlyVal) xticks = np.insert(xticks, 0, 5) xticklabels = list(np.round(xticks).astype(int)) xticklabels[0] = 'Mask Only' xticklabels[-1] = 'Target Only' # if title=='Response Rate': # # add catch label to plot # x = 0 # xticks = np.concatenate((x,xticks)) # xticklabels = lbl+xticklabels ax.set_xticks(xticks) ax.set_xticklabels(xticklabels) ax.set_xlim([0, xticks[-1] + 5]) ax.set_ylim([0, 1.1]) ax.spines['right'].set_visible(False) ax.spines['top'].set_visible(False) ax.tick_params(direction='out', top=False, right=False) if title == 'Response Rate': ax.xaxis.set_label_coords(0.5, -0.08)
def makeWheelPlot(data, returnData=False, responseFilter=[-1,0,1], ignoreRepeats=True, framesToShowBeforeStart=60, mask=False, maskOnly=False): #Clean up inputs if needed #if response filter is an int, make it a list if type(responseFilter) is int: responseFilter = [responseFilter] d = data frameRate = d['frameRate'][()] trialEndFrames = d['trialEndFrame'][:] trialStartFrames = d['trialStartFrame'][:trialEndFrames.size] trialRewardDirection = d['trialRewardDir'][:trialEndFrames.size] trialResponse = d['trialResponse'][:trialEndFrames.size] deltaWheel = d['deltaWheelPos'][:] preStimFrames = d['trialStimStartFrame'][:trialEndFrames.size]-trialStartFrames if 'trialStimStartFrame' in d else np.array([d['preStimFrames'][:]]*trialStartFrames.size) trialStartFrames += preStimFrames if 'trialOpenLoopFrames' in d.keys(): openLoopFrames = d['trialOpenLoopFrames'][:] elif 'openLoopFrames' in d.keys(): openLoopFrames = d['openLoopFrames'][:] else: raise ValueError if 'rewardFrames' in d.keys(): rewardFrames = d['rewardFrames'][:] elif 'responseFrames' in d.keys(): responseTrials = np.where(trialResponse!= 0)[0] rewardFrames = d['responseFrames'][:][trialResponse[responseTrials]>0] else: rewardFrames = d['trialResponseFrame'][:len(trialResponse)] rewardFrames = rewardFrames[trialResponse>0] nogo = d['trialTargetFrames'][:-1]==0 # alters the necessary variables to exclude any trials that are an incorrect repeat #(i.e, a repeated trial after an incorrect choice). If there are no repeats, it passes if ignoreRepeats == True: if 'trialRepeat' in d.keys(): prevTrialIncorrect = d['trialRepeat'][:len(trialResponse)] subtitle = ['repeats ignored'] elif 'incorrectTrialRepeats' in d and d['incorrectTrialRepeats'][()] > 0: prevTrialIncorrect = np.concatenate(([False],trialResponse[:-1]<1)) trialResponse = trialResponse[prevTrialIncorrect==False] trialStartFrames = trialStartFrames[prevTrialIncorrect==False] trialEndFrames = trialEndFrames[prevTrialIncorrect==False] trialRewardDirection = trialRewardDirection[prevTrialIncorrect==False] nogo = nogo[prevTrialIncorrect==False] subtitle = ['repeats ignored'] elif 'incorrectTrialRepeats' in d and d['incorrectTrialRepeats'][()] == 0: subtitle= ['no repeated trials'] else: subtitle = ['repeats incl'] ignoreTrials = ignore_trials(d) postTrialFrames = 0 if d['postRewardTargetFrames'][()]>0 else 1 #make sure we have at least one frame after the reward fig, ax = plt.subplots() # turnRightTrials == stim presented on L, turn right - viceversa for turnLeftTrials - or for orientation, turn right nogoTrials = [] turnRightTrials = [] turnLeftTrials = [] maxTrialFrames = max(trialEndFrames-trialStartFrames+framesToShowBeforeStart+postTrialFrames) #??? why trialTime = (np.arange(maxTrialFrames)-framesToShowBeforeStart)/frameRate # evenly-spaced array of times for x-axis for i, (trialStart, trialEnd, rewardDirection, resp) in enumerate(zip( trialStartFrames, trialEndFrames, trialRewardDirection, trialResponse)): if i>0 and i<len(trialStartFrames): if i in ignoreTrials: pass else: if resp in responseFilter: #get wheel position trace for this trial! trialWheel = np.cumsum(deltaWheel[ trialStart-framesToShowBeforeStart:trialStart-framesToShowBeforeStart + maxTrialFrames ]) trialWheel -= trialWheel[0] trialreward = np.where((rewardFrames>trialStart)&(rewardFrames<=trialEnd))[0] rewardFrame = rewardFrames[trialreward[0]]-trialStart+framesToShowBeforeStart if len(trialreward)>0 else None if nogo[i]: ax.plot(trialTime[:trialWheel.size], trialWheel, 'g', alpha=0.2) # plotting no-go trials if rewardFrame is not None: ax.plot(trialTime[rewardFrame], trialWheel[rewardFrame], 'go') nogoTrials.append(trialWheel) elif rewardDirection>0: ax.plot(trialTime[:trialWheel.size], trialWheel, 'r', alpha=0.2) #plotting right turning if rewardFrame is not None: ax.plot(trialTime[rewardFrame], trialWheel[rewardFrame], 'ro') turnRightTrials.append(trialWheel) elif rewardDirection<0: ax.plot(trialTime[:trialWheel.size], trialWheel, 'b', alpha=0.2) # plotting left turning if rewardFrame is not None: ax.plot(trialTime[rewardFrame], trialWheel[rewardFrame], 'bo') turnLeftTrials.append(trialWheel) turnRightTrials = pd.DataFrame(turnRightTrials).fillna(np.nan).values turnLeftTrials = pd.DataFrame(turnLeftTrials).fillna(np.nan).values nogoTrials = pd.DataFrame(nogoTrials).fillna(np.nan).values ax.plot(trialTime[:turnRightTrials.shape[1]], np.nanmean(turnRightTrials,0), 'r', linewidth=3) ax.plot(trialTime[:turnLeftTrials.shape[1]], np.nanmean(turnLeftTrials, 0), 'b', linewidth=3) ax.plot(trialTime[:nogoTrials.shape[1]], np.nanmean(nogoTrials,0), 'k', linewidth=3) ax.plot([trialTime[framesToShowBeforeStart+openLoopFrames]]*2, ax.get_ylim(), 'k--') name_date = str(data).split('_') formatFigure(fig, ax, xLabel='Time from stimulus onset (s)', yLabel='Wheel Position (pix)', title=name_date[-3:-1] + subtitle) plt.tight_layout()