""" Module to analyze GLMs of widefield Ca2+ data Lucas Pinto 2020, lucas.pinto@northwestern.edu """ #!/usr/bin/env python # Libraries import numpy as np import scipy as sp import matplotlib.pyplot as plt import lp_utils as utils import deepdish as dd import analyzeBehavior as behav import mat73 from scipy.io import loadmat import pingouin as pg import pandas as pd import copy wf_params = { 'glm_comp_file' : '/Users/lpinto/Dropbox/PintoEtAl2020_subtrial_inact/data/dffGLM_autoregr_model_comp_time.mat', 'glm_summ_file' : '/Users/lpinto/Dropbox/PintoEtAl2020_subtrial_inact/data/glmSummary_ROI_corr_autoRegr_time.mat', 'glm_eg_file' : '/Users/lpinto/Dropbox/PintoEtAl2020_subtrial_inact/data/dffGLM_time_ridge_ROI_autoRegr_ai3_20170201.mat', 'mouse_eg_id' : 1, 'areaList' : ['V1','mV2','PPC','RSC','mM2','aM2','M1'], 'area_eg_idx_autoregr' : [0, 3, 4, 6], 'area_eg_idx_glm' : [0, 7, 10, 13], 'trial_idx_glm' : range(933,983) } # ============================================================================== # load widefield model data def load_glm(wf_params=wf_params): """ glm = load_glm(wf_params=wf_params) takes optional wf_params dictionary, returns dictionary with GLM summary, comparison and single examples loaded from .mat files """ glm = dict() glm['comp'] = loadmat(wf_params['glm_comp_file'], struct_as_record=True, squeeze_me=True) summ = loadmat(wf_params['glm_summ_file'], struct_as_record=False, squeeze_me=True) glm['summ'] = summ['glmSumm'] eg = mat73.loadmat(wf_params['glm_eg_file']) glm['eg'] = dict() glm['eg']['y'] = eg['dffFit']['bestpred_y'][:-2] glm['eg']['yhat'] = eg['dffFit']['bestpred_yhat'][:-2] glm['eg']['ROIlbl'] = utils.wf_ROIlbl_translate(eg['dffFit']['ROIlbl'][:-2]) return glm # ============================================================================== # summarize glm results def summarize_glm(glm=None): """ glm_summ = summarize_glm(glm=None) takes glm dictionary (will load if None), returns dictionary with summary analysis of model performance and auto-regressive parameters """ if glm is None: glm = load_glm() # set up glm_summ = dict() mouse_names = utils.get_mouse_name(glm['comp']['recls']) glm_summ['mice'] = np.unique(mouse_names) num_mice = len(glm_summ['mice']) glm_summ['model_names'] = glm['comp']['model_names'] num_models = len(glm['comp']['model_names']) glm_summ['areaList'] = wf_params['areaList'] num_areas = len(glm_summ['areaList']) accuracy = glm['comp']['accuracy'][:,:-2,:].flatten() glm_summ['accuracy_mice'] = np.zeros((num_mice,num_areas,num_models)) glm_areas = utils.wf_ROIlbl_translate(glm['summ'].ROIlbl[0:-2]) # compare accuracy area_mat = np.stack([np.stack([glm_areas]*len(mouse_names),axis=0)]*num_models,axis=2).flatten() mouse_mat = np.stack([np.stack([mouse_names]*num_areas*2,axis=1)]*num_models,axis=2)[:,:,:,0].flatten() for iMouse, mouse in enumerate(glm_summ['mice']): for iArea, area in enumerate(glm_summ['areaList']): is_area = area_mat == area is_mouse = mouse_mat == mouse this_mat = accuracy[np.logical_and(is_area,is_mouse)] this_mat = np.reshape(this_mat,(np.sum(np.array(mouse_names) == mouse),2,num_models)) glm_summ['accuracy_mice'][iMouse,iArea,:] = np.mean(np.mean(this_mat,axis=0),axis=0) # remove just correlations model from analysis, irrelevant here is_valid = np.zeros((num_mice,num_areas,num_models)) == 0 is_valid[:,:,1] = False glm_summ['accuracy_mice'] = glm_summ['accuracy_mice'][is_valid].reshape(num_mice,num_areas,num_models-1) glm_summ['model_names'] = ['Task','Task + auto-regr.','Task + corr + auto-regr.'] num_models = len(glm_summ['model_names']) glm_summ['accuracy_mean'] = np.mean(glm_summ['accuracy_mice'],axis=0) glm_summ['accuracy_sem'] = np.std(glm_summ['accuracy_mice'],axis=0,ddof=1) / np.sqrt(num_mice) # stats # 2-way ANOVA with RM table = pd.DataFrame({'area' : np.repeat(range(num_areas), num_mice*num_models), 'mouse': np.tile(np.repeat(range(num_mice), num_models), num_areas), 'model': np.tile(range(num_models), num_mice*num_areas), 'acc' : glm_summ['accuracy_mice'].flatten()}) glm_summ['accuracy_anova_table'] = pg.rm_anova(dv='acc', within=['area','model'],subject='mouse',data=table) glm_summ['accuracy_posthoc_pvals'] = pg.pairwise_tukey(data=table,dv='acc',between='model') # timescales and towers glm_summ = analyze_timescales(glm,glm_summ) glm_summ = analyze_tower_weights(glm,glm_summ) return glm_summ # ============================================================================== # analyze autogressive coefficients def analyze_timescales(glm,glm_summ): # extract relevant predictors num_mice = len(glm_summ['mice']) num_areas = len(glm_summ['areaList']) glm_areas = utils.wf_ROIlbl_translate(glm['summ'].ROIlbl[0:-2]) ispred_idx = np.array([glm['summ'].predLbls[iPred].find('auto') \ for iPred in range(np.size(glm['summ'].predLbls))])==0 num_lags = np.sum(ispred_idx) weights = glm['summ'].weights[:-2,ispred_idx,:] glm_summ['acorr_weights'] = np.zeros((num_areas,num_lags,num_mice)) glm_summ['taus'] = np.zeros((num_areas,num_mice)) glm_summ['acorr_lags'] = np.arange(0,num_lags*.1,.1) glm_summ['acorr_xaxis'] = np.arange(0,num_lags*.1-.1,.01) glm_summ['acorr_fit_mice'] = np.zeros((num_areas,np.size(glm_summ['acorr_xaxis']),num_mice)) glm_summ['acorr_fit_r2'] = np.zeros((num_areas,num_mice)) # average over areas, normalize and fit exponentials for iArea, area in enumerate(glm_summ['areaList']): is_area = np.array(glm_areas) == area glm_summ['acorr_weights'][iArea,:,:] = np.mean(weights[is_area,:,:],axis=0) for iMouse in range(num_mice): glm_summ['acorr_weights'][iArea,:,iMouse] = glm_summ['acorr_weights'][iArea,:,iMouse] \ / glm_summ['acorr_weights'][iArea,0,iMouse] fit , _ = sp.optimize.curve_fit(exp_decay, glm_summ['acorr_lags'], \ glm_summ['acorr_weights'][iArea,:,iMouse], maxfev=4000, bounds=[0.01, 1]) glm_summ['taus'][iArea,iMouse] = fit[0] glm_summ['acorr_fit_mice'][iArea,:,iMouse] = exp_decay(glm_summ['acorr_xaxis'],*fit) glm_summ['acorr_fit_r2'][iArea,iMouse] = utils.fit_rsquare(glm_summ['acorr_weights'][iArea,:,iMouse], \ exp_decay(glm_summ['acorr_lags'],*fit)) # one-way ANOVA with RM for taus table = pd.DataFrame({'area' : np.repeat(range(num_areas), num_mice), 'mouse': np.tile(range(num_mice), num_areas), 'tau' : glm_summ['taus'].flatten()}) glm_summ['taus_anova_table'] = pg.rm_anova(dv='tau', within='area',subject='mouse',data=table) glm_summ['taus_anova_pval'] = glm_summ['taus_anova_table']['p-unc'].to_numpy() # avg fit glm_summ['acorr_weights_mean'] = np.mean(glm_summ['acorr_weights'],axis=2) glm_summ['acorr_weights_sem'] = np.std(glm_summ['acorr_weights'],axis=2,ddof=1) / np.sqrt(num_mice) glm_summ['acorr_fit_pred'] = np.zeros((num_areas,np.size(glm_summ['acorr_xaxis']))) for iArea in range(num_areas): fit , _ = sp.optimize.curve_fit(exp_decay, glm_summ['acorr_lags'], \ glm_summ['acorr_weights_mean'][iArea,:], maxfev=4000, bounds=[0.01, 1]) glm_summ['acorr_fit_pred'][iArea,:] = exp_decay(glm_summ['acorr_xaxis'],*fit) return glm_summ # ============================================================================== # analyze model coefficients related to towers def analyze_tower_weights(glm,glm_summ,smooth_w=3): """ glm_summ = analyze_tower_weights(glm,glm_summ,smooth_w=3) analyzes contralateral and \delta tower weights for each area called by summarize_glm. smooth_w is number of datapoints in sigma of a gaussian window for smoothing coefficients over lags """ # extract relevant predictors towL_idx = np.array([glm['summ'].predLbls[iPred].find('tow_L') \ for iPred in range(np.size(glm['summ'].predLbls))])==0 towR_idx = np.array([glm['summ'].predLbls[iPred].find('tow_R') \ for iPred in range(np.size(glm['summ'].predLbls))])==0 delta_idx = np.array([glm['summ'].predLbls[iPred].find('Delta') \ for iPred in range(np.size(glm['summ'].predLbls))])>0 towL_weights = glm['summ'].weights[:-2,towL_idx,:] towR_weights = glm['summ'].weights[:-2,towR_idx,:] delta_weights = glm['summ'].weights[:-2,delta_idx,:] # combine in ipsi and contra ROIlbl = glm['summ'].ROIlbl[0:-2] glm_areas = np.unique(utils.wf_ROIlbl_translate(ROIlbl)) isR = np.array([ROIlbl[iROI].find('-R') for iROI in range(len(ROIlbl))])>0 isL = ~isR hemR_towL_weights = towL_weights[isR,:,:] hemR_towR_weights = towR_weights[isR,:,:] hemL_towL_weights = towL_weights[isL,:,:] hemL_towR_weights = towR_weights[isL,:,:] contraDelta_weights = delta_weights[isL,:,:] # since \Delta = R - L, contra is always left hemisphere ipsiDelta_weights = delta_weights[isR,:,:] # since \Delta = R - L, ipsi is always right hemisphere # initialize vars num_lags_tow = np.sum(towL_idx) num_lags_delta = np.sum(delta_idx) dt = glm['summ'].glmCfg.timeBins[1] - glm['summ'].glmCfg.timeBins[0] num_mice = len(glm_summ['mice']) num_areas = len(glm_areas) glm_summ['tower_taxis'] = np.arange(0,num_lags_tow*dt,dt) glm_summ['delta_taxis'] = np.arange(0,num_lags_delta*dt,dt) glm_summ['contraTow_weights'] = np.zeros((num_areas,num_lags_tow,num_mice)) glm_summ['ipsiTow_weights'] = np.zeros((num_areas,num_lags_tow,num_mice)) glm_summ['contraTow_peakTime'] = np.zeros((num_areas,num_mice)) glm_summ['ipsiTow_peakTime'] = np.zeros((num_areas,num_mice)) glm_summ['contraDelta_weights'] = np.zeros((num_areas,num_lags_delta,num_mice)) glm_summ['ipsiDelta_weights'] = np.zeros((num_areas,num_lags_delta,num_mice)) glm_summ['contraDelta_peakTime'] = np.zeros((num_areas,num_mice)) glm_summ['ipsiDelta_peakTime'] = np.zeros((num_areas,num_mice)) # baseline subtract, normalize, smooth, measure time of peak coefficient value for iArea, area in enumerate(glm_summ['areaList']): is_area = np.array(glm_areas) == area for iMouse in range(num_mice): thisw_hRtR = hemR_towR_weights[is_area,:,iMouse][0] thisw_hRtL = hemR_towL_weights[is_area,:,iMouse][0] thisw_hLtR = hemL_towR_weights[is_area,:,iMouse][0] thisw_hLtL = hemL_towL_weights[is_area,:,iMouse][0] this_contra = sp.ndimage.gaussian_filter1d((thisw_hLtR + thisw_hRtL)/2,smooth_w) this_ipsi = sp.ndimage.gaussian_filter1d((thisw_hLtL + thisw_hRtR)/2,smooth_w) this_contra = this_contra - np.min(this_contra) this_contra = this_contra / np.max(this_contra) this_ipsi = this_ipsi - np.min(this_ipsi) this_ipsi = this_ipsi / np.max(this_ipsi) glm_summ['contraTow_weights'][iArea,:,iMouse] = this_contra glm_summ['contraTow_peakTime'][iArea,iMouse] = glm_summ['tower_taxis'][this_contra==np.max(this_contra)] glm_summ['ipsiTow_weights'][iArea,:,iMouse] = this_ipsi glm_summ['ipsiTow_peakTime'][iArea,iMouse] = glm_summ['tower_taxis'][this_ipsi==np.max(this_ipsi)] thisw = contraDelta_weights[is_area,:,iMouse][0] thisw = sp.ndimage.gaussian_filter1d(thisw,smooth_w) thisw = thisw - np.min(thisw) thisw = thisw / np.max(thisw) glm_summ['contraDelta_weights'][iArea,:,iMouse] = thisw glm_summ['contraDelta_peakTime'][iArea,iMouse] = glm_summ['delta_taxis'][thisw==np.max(thisw)] thisw = ipsiDelta_weights[is_area,:,iMouse][0] thisw = sp.ndimage.gaussian_filter1d(thisw,smooth_w) thisw = thisw - np.min(thisw) thisw = thisw / np.max(thisw) glm_summ['ipsiDelta_weights'][iArea,:,iMouse] = thisw glm_summ['ipsiDelta_peakTime'][iArea,iMouse] = glm_summ['delta_taxis'][thisw==np.max(thisw)] # one-way ANOVA with RM for peaks table = pd.DataFrame({'area' : np.repeat(range(num_areas), num_mice), 'mouse': np.tile(range(num_mice), num_areas), 'contraTow_peakTime' : glm_summ['contraTow_peakTime'].flatten()}) glm_summ['contraTow_peakTime_anova_table'] = pg.rm_anova(dv='contraTow_peakTime', within='area',subject='mouse',data=table) glm_summ['contraTow_peakTime_anova_pval'] = glm_summ['contraTow_peakTime_anova_table']['p-unc'].to_numpy() table = pd.DataFrame({'area' : np.repeat(range(num_areas), num_mice), 'mouse': np.tile(range(num_mice), num_areas), 'ipsiTow_peakTime' : glm_summ['ipsiTow_peakTime'].flatten()}) glm_summ['ipsiTow_peakTime_anova_table'] = pg.rm_anova(dv='ipsiTow_peakTime', within='area',subject='mouse',data=table) glm_summ['ipsiTow_peakTime_anova_pval'] = glm_summ['ipsiTow_peakTime_anova_table']['p-unc'].to_numpy() table = pd.DataFrame({'area' : np.repeat(range(num_areas), num_mice), 'mouse': np.tile(range(num_mice), num_areas), 'contraDelta_peakTime' : glm_summ['contraDelta_peakTime'].flatten()}) glm_summ['contraDelta_peakTime_anova_table'] = pg.rm_anova(dv='contraDelta_peakTime', within='area',subject='mouse',data=table) glm_summ['contraDelta_peakTime_anova_pval'] = glm_summ['contraDelta_peakTime_anova_table']['p-unc'].to_numpy() table = pd.DataFrame({'area' : np.repeat(range(num_areas), num_mice), 'mouse': np.tile(range(num_mice), num_areas), 'ipsiDelta_peakTime' : glm_summ['ipsiDelta_peakTime'].flatten()}) glm_summ['ipsiDelta_peakTime_anova_table'] = pg.rm_anova(dv='ipsiDelta_peakTime', within='area',subject='mouse',data=table) glm_summ['ipsiDelta_peakTime_anova_pval'] = glm_summ['ipsiDelta_peakTime_anova_table']['p-unc'].to_numpy() return glm_summ # ============================================================================== # plot model coefficients related to towers def plot_tower_weights(glm_summ,plot_median=True): """ fig = plot_tower_weights(glm_summ,plot_median=True) plots contralateral and \delta tower weights and analysis thereof for each area glm_summ is output of summarize_glm, fig is fig handle plot_median is boolean to show median rather than mean across mice """ fig = plt.figure(figsize=(5,6.5)) cl = utils.getAreaColors(glm_summ['areaList']) nareas = len(glm_summ['areaList']) nmice = np.size(glm_summ['contraTow_peakTime'],axis=1) # plot contralateral tower weights by time plot_what = 'contraTow_weights' taxis = glm_summ['tower_taxis'] for iArea in range(nareas): ax = fig.add_subplot(4,4,iArea+1) thism = np.mean(glm_summ[plot_what][iArea,:,:],axis=1) thiss = np.std(glm_summ[plot_what][iArea,:,:],axis=1,ddof=1) / np.sqrt(nmice-1) ax.fill_between(taxis,thism-thiss,thism+thiss,color=[.7,.7,.7,.5]) ax.plot(taxis,thism,color=cl[iArea],lw=1.5) ax.set_xticks(np.arange(0,2.5,.5)) ax.set_yticks(np.arange(0,1.25,.25)) ax.set_xlim([0,2]) ax.set_ylim([0,1]) if iArea == 4: ax.set_xlabel('Lag (s)') ax.set_ylabel('Norm. contra tower coeff.') ax = utils.applyPlotDefaults(ax) # plot peaks per area / mouse ax = fig.add_subplot(4,4,8) plot_what = 'contraTow_peakTime' jitter = np.random.uniform(size=(nmice))*0.05-0.025 for iArea in range(nareas): this_peak = glm_summ[plot_what][iArea,:] ax.bar(iArea,np.mean(this_peak),color=cl[iArea]) ax.errorbar(iArea,np.mean(this_peak),np.std(this_peak,ddof=1)/np.sqrt(nmice-1),color=cl[iArea]) ax.plot(iArea+jitter,this_peak,marker='.',c=[.6,.6,.6,.5], ls='None') ax.set_xticks(np.arange(nareas)) ax.set_xticklabels(glm_summ['areaList'],rotation=90) ax.set_yticks(np.arange(0,2.5,.5)) ax.set_xlim([-.5,iArea+.5]) ax.set_ylim([0,2.05]) ax.set_ylabel('Time of peak (s)') # print ANOVA p (bins) plt.text(0,2.2,'p = {:.2f}'.format(glm_summ['contraTow_peakTime_anova_pval'][0]),fontsize=8,color='k') ax = utils.applyPlotDefaults(ax) # plot contralateral \Delta tower weights by time plot_what = 'contraDelta_weights' taxis = glm_summ['delta_taxis'] for iArea in range(nareas): ax = fig.add_subplot(4,4,iArea+2+nareas) thism = np.mean(glm_summ[plot_what][iArea,:,:],axis=1) thiss = np.std(glm_summ[plot_what][iArea,:,:],axis=1,ddof=1) / np.sqrt(nmice-1) ax.fill_between(taxis,thism-thiss,thism+thiss,color=[.7,.7,.7,.5]) ax.plot(taxis,thism,color=cl[iArea],lw=1.5) ax.set_xticks(np.arange(0,2.5,.5)) ax.set_yticks(np.arange(0,1.25,.25)) ax.set_xlim([0,2]) ax.set_ylim([0,1]) if iArea == 4: ax.set_xlabel('Lag (s)') ax.set_ylabel('Norm. \u0394 towers coeff.') ax = utils.applyPlotDefaults(ax) # plot peaks per area / mouse ax = fig.add_subplot(4,4,16) plot_what = 'contraDelta_peakTime' jitter = np.random.uniform(size=(nmice))*0.05-0.025 for iArea in range(nareas): this_peak = glm_summ[plot_what][iArea,:] if plot_median: thism = np.median(this_peak) thiss = sp.stats.iqr(this_peak) else: thism = np.mean(this_peak) thiss = np.std(this_peak,ddof=1)/np.sqrt(nmice-1) ax.bar(iArea,thism,color=cl[iArea]) ax.errorbar(iArea,thism,thiss,color=cl[iArea]) ax.plot(iArea+jitter,this_peak,marker='.',c=[.6,.6,.6,.5], ls='None') ax.set_xticks(np.arange(nareas)) ax.set_xticklabels(glm_summ['areaList'],rotation=90) ax.set_yticks(np.arange(0,2.5,.5)) ax.set_xlim([-.5,iArea+.5]) ax.set_ylim([0,2.05]) ax.set_ylabel('Time of peak (s)') # print ANOVA p (bins) plt.text(0,2.2,'p = {:.2f}'.format(glm_summ['contraDelta_peakTime_anova_pval'][0]),fontsize=8,color='k') ax = utils.applyPlotDefaults(ax) fig.subplots_adjust(left=.1, bottom=.25, right=.95, top=.75, wspace=.75, hspace=.75) return fig # ============================================================================== # plot glm timescales def plot_glm_timescales(glm_summ,glm,plot_median=True,wf_params=wf_params): """ fig, figdata = plot_glm_timescales(glm_summ,glm,plot_median=True) takes glm and glm_summ dictionaries, plots data summary and examples with emphasis on timescales plot_median is boolean to show median rather than mean across mice returns figure handle fig and source data dictionary figdata """ colors = utils.getAreaColors(glm_summ['areaList']) num_areas = len(glm_summ['areaList']) fig = plt.figure(figsize=(5,4.5)) figdata = dict() # plot model performance ax = fig.add_subplot(2,4,5) acc = glm_summ['accuracy_mice'][:,:,-1].flatten() ax.hist(acc,bins=np.arange(0,1.05,.05),color=[.5,.5,.5]) ax.set_xticks(np.arange(0,1.25,.25)) ax.set_xlabel('Cross-val. accuracy (avg. r)') ax.set_ylabel('Num. observations\n(Mice * ROI)') ax = utils.applyPlotDefaults(ax) figdata['glm_xval_accuracy_corrcoeff'] = acc # plot example model predictions area_eg_idx = wf_params['area_eg_idx_glm'] data_points = wf_params['trial_idx_glm'] xaxis = np.arange(0,len(data_points)*.1,.1) subplot = [2, 6, 10, 14] figdata['glm_examples_xaxis'] = xaxis figdata['glm_examples_xaxis_label'] = 'Time from trial start (s)' figdata['glm_examples_yaxis_label'] = '\DeltaF/F (z-score)' figdata['glm_examples_areaLabels'] = list() figdata['glm_examples_data'] = list() figdata['glm_examples_prediction'] = list() for iEg in range(len(area_eg_idx)): ax = fig.add_subplot(4,4,subplot[iEg]) if iEg == len(area_eg_idx): data_points = data_points + 38 # hack: M1 is misaligned due to some NaN in this file thisy = sp.ndimage.gaussian_filter1d(glm['eg']['y'][area_eg_idx[iEg]][data_points], 1) figdata['glm_examples_data'].append(thisy) ax.plot(xaxis,thisy,linestyle='-',linewidth=.75,color=[.3, .3, .3],label='Data') thisy = sp.ndimage.gaussian_filter1d(glm['eg']['yhat'][area_eg_idx[iEg]][data_points], 1) figdata['glm_examples_prediction'].append(thisy) thiscl = utils.getAreaColors([glm['eg']['ROIlbl'][area_eg_idx[iEg]]]) ax.plot(xaxis,thisy,linestyle='-',linewidth=1,color=thiscl[0],label='Prediction') ax.set_xticks(range(0,6,1)) ax.set_title(glm['eg']['ROIlbl'][area_eg_idx[iEg]]) if iEg == 2: ax.set_xlabel('Time from trial start (s)') if iEg == 3: ax.set_ylabel('Df/f (z-score)') utils.applyPlotDefaults(ax) figdata['glm_examples_areaLabels'].append(glm['eg']['ROIlbl'][area_eg_idx[iEg]]) # plot example exponential fits # subplot = [4, 5, 11, 12] subplot = [3, 7, 11, 15] area_eg_idx = wf_params['area_eg_idx_autoregr'] figdata['expfit_examples_xaxis'] = -(np.flip(glm_summ['acorr_lags']+.1)) figdata['expfit_examples_xaxis_label'] = 'Lag (s)' figdata['expfit_examples_yaxis_label'] = 'Norm. auto-regr. coeff.' figdata['expfit_examples_areaLabels'] = list() figdata['expfit_examples_data'] = list() figdata['expfit_examples_prediction'] = list() for iEg in range(len(area_eg_idx)): ax = fig.add_subplot(4,4,subplot[iEg]) areaidx = area_eg_idx[iEg] thisy = glm_summ['acorr_weights'][areaidx,:,wf_params['mouse_eg_id']] ax.plot(-(np.flip(glm_summ['acorr_lags']+.1)),np.flip(thisy),linestyle='-',linewidth=.75,color=[.3, .3, .3],label='Data') figdata['expfit_examples_data'].append(np.flip(thisy)) thisy = glm_summ['acorr_fit_mice'][areaidx,:,wf_params['mouse_eg_id']] thiscl = utils.getAreaColors([glm_summ['areaList'][areaidx]]) ax.plot(-(np.flip(glm_summ['acorr_xaxis']+.1)),np.flip(thisy),linestyle='-',linewidth=1,color=thiscl[0],label='Prediction') ax.set_xticks(np.arange(-1,.25,.25)) ax.set_xlim([-1,0]) ax.set_title(glm_summ['areaList'][areaidx]) figdata['expfit_examples_prediction'].append(np.flip(thisy)) figdata['expfit_examples_areaLabels'].append(glm_summ['areaList'][areaidx]) # if iEg == 0: # ax.legend() if iEg == 2: ax.set_xlabel('Lag (s)') if iEg == 3: ax.set_ylabel('Norm. auto-regr. coeff.') utils.applyPlotDefaults(ax) # plot exp. model R2 ax = fig.add_subplot(3,4,4) acc = glm_summ['acorr_fit_r2'].flatten() ax.hist(acc,bins=np.arange(0,1.05,.05),color=[.5,.5,.5]) ax.set_xticks(np.arange(0,1.25,.25)) ax.set_xlabel('Exponential fit R^2') ax.set_ylabel('Num. observations\n(Mice * ROI)') ax = utils.applyPlotDefaults(ax) figdata['exponentialFit_r2'] = acc # plot average fits ax = fig.add_subplot(3,4,8) figdata['expfit_areaList'] = glm_summ['areaList'] figdata['expFit_area_avg'] = list() for iArea in range(num_areas): plt.plot(-(np.flip(glm_summ['acorr_xaxis']+.1)),np.flip(glm_summ['acorr_fit_pred'][iArea,:]),color=colors[iArea],linewidth=.5) figdata['expFit_area_avg'].append(np.flip(glm_summ['acorr_fit_pred'][iArea,:])) ax.set_xlabel('Lag (s)') ax.set_ylabel('Norm. auto-regr. coeff.') ax.set_xticks(np.arange(-.5,.1,.1)) ax.set_yticks(np.arange(0,1.25,.25)) ax.set_xlim([-.5,-.05]) ax.set_ylim([0,1]) ax = utils.applyPlotDefaults(ax) # plot taus figdata['expFit_tau_bymouse'] = list() if plot_median: figdata['expFit_tau_median'] = list() figdata['expFit_tau_interQrange'] = list() else: figdata['expFit_tau_mean'] = list() figdata['expFit_tau_sem'] = list() num_mice = np.size(glm_summ['taus'],axis=1) jitter = np.random.uniform(size=(num_mice))*0.1-0.05 ax = fig.add_subplot(3,4,12) for iArea in range(num_areas): taus = glm_summ['taus'][iArea,:] figdata['expFit_tau_bymouse'].append(taus) if plot_median: thismean = np.median(taus) thissem = sp.stats.iqr(taus) figdata['expFit_tau_median'].append(thismean) figdata['expFit_tau_interQrange'].append(thissem) else: thismean = np.mean(taus) thissem = np.std(taus,ddof=1)/np.sqrt(num_mice) figdata['expFit_tau_mean'].append(thismean) figdata['expFit_tau_sem'].append(thissem) plt.bar(iArea,thismean,facecolor=colors[iArea]) plt.errorbar(iArea,thismean,thissem,color=colors[iArea]) ax.plot(iArea+jitter,taus,marker='.',c=[.6,.6,.6,.5], ls='None') ax.set_xticks(range(num_areas)) ax.set_xticklabels(glm_summ['areaList'],rotation=90) ax.set_ylabel('$\u03C4$ (s)') ax.set_ylim([0, .4]) ax.set_yticks(np.arange(0,.45,.1)) ax.text(0,.15,'p = {:1.3f}'.format(glm_summ['taus_anova_pval'][0])) ax = utils.applyPlotDefaults(ax) figdata['expFit_tau_pval'] = glm_summ['taus_anova_pval'][0] fig.subplots_adjust(left=.1, bottom=.25, right=.95, top=.75, wspace=.75, hspace=1) return fig, figdata # ============================================================================== # plot glm timescales def plot_glm_timescales_space(glm_summ,glm): """ fig = plot_glm_timescales(glm_summ,glm) takes glm and glm_summ dictionaries, plots data summary and examples with emphasis on timescales returns figure handle fig """ colors = utils.getAreaColors(glm_summ['areaList']) num_areas = len(glm_summ['areaList']) fig = plt.figure(figsize=(5,4)) # plot model performance ax = fig.add_subplot(2,4,5) for iArea in range(num_areas): plt.plot(glm_summ['accuracy_mean'][iArea,:],color=colors[iArea]) ax.set_xticks(range(4)) ax.set_xticklabels(glm_summ['model_names'],rotation=90) ax.set_ylabel('Cross-val accuracy (r)') ax.legend(glm_summ['areaList'],fontsize='x-small',ncol=1) ax.set_xlim([-.25,3.25]) ax = utils.applyPlotDefaults(ax) # plot example model predictions area_eg_idx = wf_params['area_eg_idx_glm'] data_points = range(wf_params['trial_idx_glm']*60,(wf_params['trial_idx_glm']+1)*60) xaxis = np.arange(0,300,5) # subplot = [2, 3, 9, 10] subplot = [2, 6, 10, 14] for iEg in range(len(area_eg_idx)): ax = fig.add_subplot(4,4,subplot[iEg]) thisy = sp.ndimage.gaussian_filter1d(glm['eg']['y'][area_eg_idx[iEg]][data_points], 1) ax.plot(xaxis,thisy,linestyle='-',linewidth=.75,color=[.3, .3, .3],label='Data') thisy = sp.ndimage.gaussian_filter1d(glm['eg']['yhat'][area_eg_idx[iEg]][data_points], 1) thiscl = utils.getAreaColors([glm['eg']['ROIlbl'][area_eg_idx[iEg]]]) ax.plot(xaxis,thisy,linestyle='-',linewidth=1,color=thiscl[0],label='Prediction') ax.set_xticks(range(0,400,100)) ax.set_title(glm['eg']['ROIlbl'][area_eg_idx[iEg]]) if iEg == 2: ax.set_xlabel('y pos. (cm)') if iEg == 3: ax.set_ylabel('Df/f (z-score)') utils.applyPlotDefaults(ax) # plot example exponential fits # subplot = [4, 5, 11, 12] subplot = [3, 7, 11, 15] area_eg_idx = wf_params['area_eg_idx_autoregr'] for iEg in range(len(area_eg_idx)): ax = fig.add_subplot(4,4,subplot[iEg]) areaidx = area_eg_idx[iEg] thisy = glm_summ['acorr_weights'][areaidx,:,wf_params['mouse_eg_id']] ax.plot(glm_summ['acorr_lags']+5,thisy,linestyle='-',linewidth=.75,color=[.3, .3, .3],label='Data') thisy = glm_summ['acorr_fit_mice'][areaidx,:,wf_params['mouse_eg_id']] thiscl = utils.getAreaColors([glm_summ['areaList'][areaidx]]) ax.plot(glm_summ['acorr_xaxis']+5,thisy,linestyle='-',linewidth=1,color=thiscl[0],label='Prediction') ax.set_xticks(range(0,125,25)) ax.set_xlim([0,50]) ax.set_title(glm_summ['areaList'][areaidx]) # if iEg == 0: # ax.legend() if iEg == 2: ax.set_xlabel('Lag (cm)') if iEg == 3: ax.set_ylabel('Norm. auto-regr. coeff.') utils.applyPlotDefaults(ax) # plot average fits ax = fig.add_subplot(2,4,4) for iArea in range(num_areas): plt.plot(glm_summ['acorr_xaxis']+5,glm_summ['acorr_fit_pred'][iArea,:],color=colors[iArea],linewidth=.5) ax.set_xlabel('Lag (cm)') ax.set_ylabel('Norm. auto-regr. coeff.') ax.set_xlim([2,25]) ax.set_xticks(range(5,30,10)) ax = utils.applyPlotDefaults(ax) # plot taus num_mice = np.size(glm_summ['taus'],axis=1) ax = fig.add_subplot(2,4,8) for iArea in range(num_areas): thismean = np.mean(glm_summ['taus'][iArea,:]) thissem = np.std(glm_summ['taus'][iArea,:],ddof=1)/np.sqrt(num_mice) plt.bar(iArea,thismean,facecolor=colors[iArea]) plt.errorbar(iArea,thismean,thissem,color=colors[iArea]) ax.set_xticks(range(num_areas)) ax.set_xticklabels(glm_summ['areaList'],rotation=90) ax.set_ylabel('$\u03C4$ (cm)') ax.set_ylim([0, 4]) ax.text(0,3,'p = {:1.3f}'.format(glm_summ['taus_anova_pval'][0])) ax = utils.applyPlotDefaults(ax) fig.subplots_adjust(left=.1, bottom=.25, right=.95, top=.75, wspace=.75, hspace=1) return fig # ============================================================================== # exponential decay function for fits def exp_decay(x,tau,a,b): return b+a*np.exp(-x/tau) # ============================================================================== # plot ROI activity predictors def plot_corr_pred(glm): """ fig = plot_corr_pred(glm) takes glm dictionary, plots coupling coefficients returns figure handle fig """ # extract relevant predictors ispred_idx = np.array([glm['summ'].predLbls[iPred].find('ROI') \ for iPred in range(np.size(glm['summ'].predLbls))])==0 num_areas = np.size(glm['summ'].ROIlbl) num_mice = np.size(glm['summ'].weights,axis=2) weights = np.ones((num_areas,num_areas,num_mice)) * np.nan # there are no self predictors, fill in accordingly for iArea in range(num_areas): area_idx = np.zeros(num_areas) == 0 area_idx[iArea] = False weights[iArea,area_idx,:] = glm['summ'].weights[iArea,ispred_idx,:] weights = weights[:-2,:-2,:] # remove somatosensory ctx from analysis wmean = np.mean(weights,axis=2) # avg across mice # plot fig = plt.figure(figsize=(3,3)) ax = fig.gca() plt.imshow(wmean,vmin=-0.3,vmax=0.3,cmap='PuOr') cb = plt.colorbar(ax=ax) cb.set_label('ROI activity coefficient') ax.set_xticks(range(num_areas-2)) ax.set_xticklabels(glm['summ'].ROIlbl[:-2],rotation=90) ax.set_yticks(range(num_areas-2)) ax.set_yticklabels(glm['summ'].ROIlbl[:-2]) return fig