def plot_pair_examples(df, vthresh=5, sthresh=3, plot_dir=None): def select_cases(ntrial, ca, npair): if (ntrial==0) and (ca== 'CA1') and (npair==9): return 'kld', 1 elif (ntrial==7) and (ca== 'CA1') and (npair==22): return 'kld', 0 elif (ntrial==123) and (ca== 'CA1') and (npair==0): # 628 return 'eg', 14 elif (ntrial==9) and (ca== 'CA1') and (npair==1): # 140 return 'eg', 4 elif (ntrial==56) and (ca== 'CA1') and (npair==1): # 334 return 'eg', 8 elif (ntrial==73) and (ca== 'CA1') and (npair==2): # 394 return 'eg', 12 elif (ntrial==17) and (ca== 'CA2') and (npair==4): # 256 return 'eg', 0 elif (ntrial==18) and (ca== 'CA2') and (npair==4): # 263 return 'eg', 6 elif (ntrial==26) and (ca== 'CA3') and (npair==1): # 299 return 'eg', 10 elif (ntrial==21) and (ca== 'CA3') and (npair==2): # 283 return 'eg', 2 else: return None, None all_ntrials = [0, 7, 123, 9, 56, 73, 17, 18, 26, 21] # Paired spikes figw_pairedsp = total_figw*0.8 figh_pairedsp = figw_pairedsp/5 # Pair eg figw_paireg = total_figw*0.8 figh_paireg = figw_paireg/4 * 1.1 fig_paireg = plt.figure(figsize=(figw_paireg, figh_paireg)) ax_paireg = np.array([ fig_paireg.add_subplot(2, 8, 1), fig_paireg.add_subplot(2, 8, 2, polar=True), fig_paireg.add_subplot(2, 8, 3), fig_paireg.add_subplot(2, 8, 4, polar=True), fig_paireg.add_subplot(2, 8, 5), fig_paireg.add_subplot(2, 8, 6, polar=True), fig_paireg.add_subplot(2, 8, 7), fig_paireg.add_subplot(2, 8, 8, polar=True), fig_paireg.add_subplot(2, 8, 9), fig_paireg.add_subplot(2, 8, 10, polar=True), fig_paireg.add_subplot(2, 8, 11), fig_paireg.add_subplot(2, 8, 12, polar=True), fig_paireg.add_subplot(2, 8, 13), fig_paireg.add_subplot(2, 8, 14, polar=True), fig_paireg.add_subplot(2, 8, 15), fig_paireg.add_subplot(2, 8, 16, polar=True), ]) # KLD figw_kld = total_figw*0.9/2 # leave 0.2 for colorbar in fig 5 figh_kld = total_figw*0.9/4 fig_kld, ax_kld = plt.subplots(2, 4, figsize=(figw_kld, figh_kld), subplot_kw={'polar':True}) num_trials = df.shape[0] aedges = np.linspace(-np.pi, np.pi, 36) aedm = midedges(aedges) abind = aedges[1] - aedges[0] sp_binwidth = 5 precess_filter = PrecessionFilter() for ntrial in range(num_trials): if ntrial not in all_ntrials: continue wave = df.loc[ntrial, 'wave'] precesser = PrecessionProcesser(sthresh=sthresh, vthresh=vthresh, wave=wave) for ca in ['CA%d' % (i + 1) for i in range(3)]: # Get data pair_df = df.loc[ntrial, ca + 'pairs'] field_df = df.loc[ntrial, ca + 'fields'] indata = df.loc[ntrial, ca + 'indata'] if (indata.shape[0] < 1) & (pair_df.shape[0] < 1) & (field_df.shape[0] < 1): continue tunner = IndataProcessor(indata, vthresh=vthresh, smooth=True) interpolater_angle = interp1d(tunner.t, tunner.angle) interpolater_x = interp1d(tunner.t, tunner.x) interpolater_y = interp1d(tunner.t, tunner.y) all_maxt, all_mint = tunner.t.max(), tunner.t.min() trange = (all_maxt, all_mint) dt = tunner.t[1] - tunner.t[0] precesser.set_trange(trange) ## Loop for pairs num_pairs = pair_df.shape[0] for npair in range(num_pairs): case, case_axid = select_cases(ntrial, ca, npair) if case is None: continue print('trial %d, %s, pair %d, case=%s' % (ntrial, ca, npair, case)) # find within-mask indexes field_ids = pair_df.loc[npair, 'fi'] - 1 # minus 1 to convert to python index mask1 = field_df.loc[field_ids[0], 'mask'] mask2 = field_df.loc[field_ids[1], 'mask'] # field's boundaries xyval1 = field_df.loc[field_ids[0], 'xyval'] xyval2 = field_df.loc[field_ids[1], 'xyval'] # Find overlap pf1 = field_df.loc[field_ids[0], 'pf'] pf2 = field_df.loc[field_ids[1], 'pf'] _, ks_dist, _ = dist_overlap(pf1['map'], pf2['map'], mask1, mask2) # Field's center coordinates maskedmap1, maskedmap2 = pf1['map'] * mask1, pf2['map'] * mask2 cooridx1 = np.unravel_index(maskedmap1.argmax(), maskedmap1.shape) cooridx2 = np.unravel_index(maskedmap2.argmax(), maskedmap2.shape) fcoor1 = np.array([pf1['X'][cooridx1[0], cooridx1[1]], pf1['Y'][cooridx1[0], cooridx1[1]]]) fcoor2 = np.array([pf2['X'][cooridx2[0], cooridx2[1]], pf2['Y'][cooridx2[0], cooridx2[1]]]) # get single fields' statistics passdf1 = field_df.loc[field_ids[0], 'passes'] passdf2 = field_df.loc[field_ids[1], 'passes'] (x1list, y1list, t1list, angle1list), tsp1list = append_info_from_passes(passdf1, vthresh, sthresh, trange) (x2list, y2list, t2list, angle2list), tsp2list = append_info_from_passes(passdf2, vthresh, sthresh, trange) if (len(t1list) < 1) or (len(t2list) < 1) or (len(tsp1list) < 1) or (len(tsp2list) < 1): continue x1, x2 = np.concatenate(x1list), np.concatenate(x2list) y1, y2 = np.concatenate(y1list), np.concatenate(y2list) hd1, hd2 = np.concatenate(angle1list), np.concatenate(angle2list) pos1, pos2 = np.stack([x1, y1]).T, np.stack([x2, y2]).T tsp1, tsp2 = np.concatenate(tsp1list), np.concatenate(tsp2list) xsp1, xsp2 = interpolater_x(tsp1), interpolater_x(tsp2) ysp1, ysp2 = interpolater_y(tsp1), interpolater_y(tsp2) possp1, possp2 = np.stack([xsp1, ysp1]).T, np.stack([xsp2, ysp2]).T hdsp1, hdsp2 = interpolater_angle(tsp1), interpolater_angle(tsp2) nspks1, nspks2 = tsp1.shape[0], tsp2.shape[0] # Directionality biner1 = DirectionerBining(aedges, hd1) fangle1, fR1, (spbins1, occbins1, normprob1) = biner1.get_directionality(hdsp1) mlmer1 = DirectionerMLM(pos1, hd1, dt=dt, sp_binwidth=sp_binwidth, a_binwidth=abind) fangle1_mlm, fR1_mlm, normprob1_mlm = mlmer1.get_directionality(possp1, hdsp1) normprob1_mlm[np.isnan(normprob1_mlm)] = 0 biner2 = DirectionerBining(aedges, hd2) fangle2, fR2, (spbins2, occbins2, normprob2) = biner2.get_directionality(hdsp2) mlmer2 = DirectionerMLM(pos2, hd2, dt=dt, sp_binwidth=sp_binwidth, a_binwidth=abind) fangle2_mlm, fR2_mlm, normprob2_mlm = mlmer2.get_directionality(possp2, hdsp2) normprob2_mlm[np.isnan(normprob2_mlm)] = 0 # Pass-based phaselag, extrinsic/intrinsic phase_finder = ThetaEstimator(0.005, 0.3, [5, 12]) AB_tsp1_list, BA_tsp1_list = [], [] AB_tsp2_list, BA_tsp2_list = [], [] nspikes_AB_list, nspikes_BA_list = [], [] duration_AB_list, duration_BA_list = [], [] t_all = [] passangles_all, x_all, y_all = [], [], [] paired_tsp_list = [] # Precession per pair neuro_keys_dict1 = dict(tsp='tsp1', spikev='spike1v', spikex='spike1x', spikey='spike1y', spikeangle='spike1angle') neuro_keys_dict2 = dict(tsp='tsp2', spikev='spike2v', spikex='spike2x', spikey='spike2y', spikeangle='spike2angle') pass_dict_keys = precesser._gen_precess_infokeys() pass_dict1 = precesser.gen_precess_dict(tag='1') pass_dict2 = precesser.gen_precess_dict(tag='2') pass_dictp = {**pass_dict1, **pass_dict2, **{'direction':[]}} pairedpasses = pair_df.loc[npair, 'pairedpasses'] num_passes = pairedpasses.shape[0] for npass in range(num_passes): # Get spikes tsp1, tsp2, vsp1, vsp2 = pairedpasses.loc[npass, ['tsp1', 'tsp2', 'spike1v', 'spike2v']] x, y, pass_angles, v = pairedpasses.loc[npass, ['x', 'y', 'angle', 'v']] # Straightness straightrank = compute_straightness(pass_angles) if straightrank < sthresh: continue # Find direction infield1, infield2, t = pairedpasses.loc[npass, ['infield1', 'infield2', 't']] loc, direction = ThetaEstimator.find_direction(infield1, infield2) duration = t.max() - t.min() # Speed threshold passmask = v > vthresh spmask1, spmask2 = vsp1 > vthresh, vsp2 > vthresh xinv, yinv, pass_angles_inv, tinv = x[passmask], y[passmask], pass_angles[passmask], t[passmask] tsp1_inv, tsp2_inv = tsp1[spmask1], tsp2[spmask2] # Find paired spikes pairidx1, pairidx2 = find_pair_times(tsp1_inv, tsp2_inv) paired_tsp1, paired_tsp2 = tsp1_inv[pairidx1], tsp2_inv[pairidx2] if (paired_tsp1.shape[0] < 1) and (paired_tsp2.shape[0] < 1): continue paired_tsp_eachpass = np.concatenate([paired_tsp1, paired_tsp2]) paired_tsp_list.append(paired_tsp_eachpass) # Get pass info passangles_all.append(pass_angles_inv) x_all.append(xinv) y_all.append(yinv) t_all.append(tinv) if direction == 'A->B': AB_tsp1_list.append(tsp1_inv) AB_tsp2_list.append(tsp2_inv) nspikes_AB_list.append(tsp1_inv.shape[0] + tsp2_inv.shape[0]) duration_AB_list.append(duration) elif direction == 'B->A': BA_tsp1_list.append(tsp1_inv) BA_tsp2_list.append(tsp2_inv) nspikes_BA_list.append(tsp1_inv.shape[0] + tsp2_inv.shape[0]) duration_BA_list.append(duration) if (direction == 'A->B') or (direction == 'B->A'): precess1 = precesser._get_precession(pairedpasses, npass, neuro_keys_dict1) precess2 = precesser._get_precession(pairedpasses, npass, neuro_keys_dict2) if (precess1 is None) or (precess2 is None): continue else: pass_dictp = precesser.append_pass_dict(pass_dictp, precess1, tag='1') pass_dictp = precesser.append_pass_dict(pass_dictp, precess2, tag='2') pass_dictp['direction'].append(direction) ############## Plot paired spikes examples ############## if (ntrial==26) and (ca=='CA3') and (npair==1) and (npass==10): if (tsp1_inv.shape[0] != 0) or (tsp2_inv.shape[0] != 0): mintsp_plt = np.min(np.concatenate([tsp1_inv, tsp2_inv])) tsp1_inv = tsp1_inv - mintsp_plt tsp2_inv = tsp2_inv - mintsp_plt tmp_idx1, tmp_idx2 = find_pair_times(tsp1_inv, tsp2_inv) pairedsp1, pairedsp2 = tsp1_inv[tmp_idx1], tsp2_inv[tmp_idx2] fig_pairsp, ax_pairsp = plt.subplots(figsize=(figw_pairedsp, figh_pairedsp)) ax_pairsp.eventplot(tsp1_inv, color='k', lineoffsets=0, linelengths=1, linewidths=0.75) ax_pairsp.eventplot(tsp2_inv, color='k', lineoffsets=1, linelengths=1, linewidths=0.75) ax_pairsp.eventplot(pairedsp1, color='darkorange', lineoffsets=0, linelengths=1, linewidths=0.75) ax_pairsp.eventplot(pairedsp2, color='darkorange', lineoffsets=1, linelengths=1, linewidths=0.75) ax_pairsp.set_yticks([0, 1]) ax_pairsp.set_yticklabels(['Field A', 'Field B']) ax_pairsp.set_ylim(-0.7, 1.7) ax_pairsp.tick_params(labelsize=ticksize) ax_pairsp.set_xlabel('t (s)', fontsize=fontsize) ax_pairsp.xaxis.set_label_coords(1, -0.075) ax_pairsp.spines['left'].set_visible(False) ax_pairsp.spines['right'].set_visible(False) ax_pairsp.spines['top'].set_visible(False) fig_pairsp.tight_layout() fig_pairsp.savefig(os.path.join(plot_dir, 'example_pairedspikes.%s' % (figext)), dpi=dpi) # fig_pairsp.savefig(os.path.join(plot_dir, 'examples_pairspikes', 'trial-%d_%s_pair-%d_pass-%d.%s' % (ntrial, ca, npair, npass, figext)), dpi=dpi) # Paired spikes if (len(paired_tsp_list) == 0) or (len(passangles_all) == 0): continue hd_pair = np.concatenate(passangles_all) x_pair, y_pair = np.concatenate(x_all), np.concatenate(y_all) pos_pair = np.stack([x_pair, y_pair]).T paired_tsp = np.concatenate(paired_tsp_list) paired_tsp = paired_tsp[(paired_tsp <= all_maxt) & (paired_tsp >= all_mint)] if paired_tsp.shape[0] < 1: continue num_spikes_pair = paired_tsp.shape[0] hdsp_pair = interpolater_angle(paired_tsp) xsp_pair = interpolater_x(paired_tsp) ysp_pair = interpolater_y(paired_tsp) possp_pair = np.stack([xsp_pair, ysp_pair]).T # Pair Directionality biner_pair = DirectionerBining(aedges, hd_pair) fanglep, fRp, (spbinsp, occbinsp, normprobp) = biner_pair.get_directionality(hdsp_pair) mlmer_pair = DirectionerMLM(pos_pair, hd_pair, dt, sp_binwidth, abind) fanglep_mlm, fRp_mlm, normprobp_mlm = mlmer_pair.get_directionality(possp_pair, hdsp_pair) normprobp_mlm[np.isnan(normprobp_mlm)] = 0 # KLD kld_mlm = calc_kld(normprob1_mlm, normprob2_mlm, normprobp_mlm) ############## Plot pair examples ############## if case == 'eg': ax_paireg[case_axid].plot(tunner.x, tunner.y, c='0.8', linewidth=0.75) ax_paireg[case_axid].plot(xyval1[:, 0], xyval1[:, 1], c='k', linewidth=1) ax_paireg[case_axid].plot(xyval2[:, 0], xyval2[:, 1], c='k', linewidth=1) ax_paireg[case_axid].axis('off') xp, yp = circular_density_1d(aedm, 20 * np.pi, 60, (-np.pi, np.pi), w=normprobp_mlm) ax_paireg[case_axid+1] = directionality_polar_plot(ax_paireg[case_axid+1], xp, yp, fanglep_mlm, linewidth=0.75) ax_paireg[case_axid].text(0.6, -0.05, '%0.2f' % (ks_dist), fontsize=legendsize, c='k', transform=ax_paireg[case_axid].transAxes) ax_paireg[case_axid+1].text(0.6, -0.05, '%0.2f' % (fRp_mlm), fontsize=legendsize, c='k', transform=ax_paireg[case_axid+1].transAxes) ############## Plot KLD examples ############## if case == 'kld': x1, y1 = circular_density_1d(aedm, 20 * np.pi, 60, (-np.pi, np.pi), w=normprob1_mlm) x2, y2 = circular_density_1d(aedm, 20 * np.pi, 60, (-np.pi, np.pi), w=normprob2_mlm) xp, yp = circular_density_1d(aedm, 20 * np.pi, 60, (-np.pi, np.pi), w=normprobp_mlm) indep_prob = normprob1_mlm * normprob2_mlm indep_prob = indep_prob / np.sum(indep_prob) indep_angle = circmean(aedm, w=indep_prob, d=abind) xindep, yindep = circular_density_1d(aedm, 20 * np.pi, 60, (-np.pi, np.pi), w=indep_prob) kld_linewidth = 0.75 ax_kld[case_axid, 0] = directionality_polar_plot(ax_kld[case_axid, 0], x1, y1, fangle1_mlm, linewidth=kld_linewidth) ax_kld[case_axid, 1] = directionality_polar_plot(ax_kld[case_axid, 1], x2, y2, fangle2_mlm, linewidth=kld_linewidth) ax_kld[case_axid, 2] = directionality_polar_plot(ax_kld[case_axid, 2], xindep, yindep, indep_angle, linewidth=kld_linewidth) ax_kld[case_axid, 3] = directionality_polar_plot(ax_kld[case_axid, 3], xp, yp, fanglep_mlm, linewidth=kld_linewidth) kldtext_x, kldtext_y = 0, -0.2 ax_kld[case_axid, 3].text(kldtext_x, kldtext_y, 'KLD=%0.2f' % (kld_mlm), fontsize=legendsize, transform=ax_kld[case_axid, 3].transAxes)
def plot_prefer_nonprefer(ax, prefer_pdf, nonprefer_pdf): ''' Parameters ---------- ax: ndarray Numpy array of axes objects with shape (6, ). ax[0] - Fraction of negative slope ax[1] - Prefer's precession ax[2] - Nonprefer's precession ax[3] - Difference in onsets for Prefer and Nonprefer ax[4] - Difference in slopes for Prefer and Nonprefer ax[5] - Difference in phases for Prefer and Nonprefer prefer_pdf: dataframe Pandas dataframe containing prefered passes (including non-precessing) nonprefer_pdf: dataframe Pandas dataframe containing nonprefered passes (including non-precessing) Returns ------- ''' pre_c = dict(prefer='r', nonprefer='b') prefer_allslope = prefer_pdf['slope'].to_numpy() nonprefer_allslope = nonprefer_pdf['slope'].to_numpy() prefer_slope = prefer_pdf[ prefer_pdf['precess_exist']]['slope'].to_numpy() * np.pi nonprefer_slope = nonprefer_pdf[ nonprefer_pdf['precess_exist']]['slope'].to_numpy() * np.pi prefer_onset = prefer_pdf[prefer_pdf['precess_exist']]['onset'].to_numpy() nonprefer_onset = nonprefer_pdf[ nonprefer_pdf['precess_exist']]['onset'].to_numpy() prefer_dsp = np.concatenate( prefer_pdf[prefer_pdf['precess_exist']]['dsp'].to_list()) nonprefer_dsp = np.concatenate( nonprefer_pdf[nonprefer_pdf['precess_exist']]['dsp'].to_list()) prefer_phasesp = np.concatenate( prefer_pdf[prefer_pdf['precess_exist']]['phasesp'].to_list()) nonprefer_phasesp = np.concatenate( nonprefer_pdf[nonprefer_pdf['precess_exist']]['phasesp'].to_list()) # Precession fraction prefer_neg_n, prefer_pos_n = (prefer_allslope < 0).sum(), (prefer_allslope > 0).sum() nonprefer_neg_n, nonprefer_pos_n = (nonprefer_allslope < 0).sum(), ( nonprefer_allslope > 0).sum() table_arr = np.array([[prefer_neg_n, prefer_pos_n], [nonprefer_neg_n, nonprefer_pos_n]]) table_df = pd.DataFrame(table_arr, columns=['-ve', '+ve'], index=['Prefer', 'Nonprefer']) p_frac = fisherexact(table_arr) prefer_frac = prefer_neg_n / (prefer_pos_n + prefer_neg_n) nonprefer_frac = nonprefer_neg_n / (nonprefer_pos_n + nonprefer_neg_n) bar_w, bar_x, bar_y = 0.5, np.array([0, 1]), np.array( [prefer_frac, nonprefer_frac]) ax[0].bar(bar_x, bar_y, width=bar_w) ax[0].errorbar(x=bar_x.mean(), y=0.8, xerr=1, c='k', capsize=2.5) ax[0].text(x=0, y=0.85, s='p%s' % (p2str(p_frac)), fontsize=legendsize) ax[0].set_xticks([0, 1]) ax[0].set_xticklabels(['Prefer', 'Nonprefer']) ax[0].tick_params(labelsize=fontsize) # Prefer precession xdum = np.linspace(0, 1, 10) mean_phasesp = circmean(prefer_phasesp) regress = rcc(prefer_dsp, prefer_phasesp) ydum = regress['phi0'] + xdum * 2 * np.pi * regress['aopt'] ax[1].scatter(prefer_dsp, prefer_phasesp, marker='.', c='gray', s=1) ax[1].scatter(prefer_dsp, prefer_phasesp + 2 * np.pi, marker='.', c='gray', s=1) ax[1].plot(xdum, ydum, c='k') ax[1].plot(xdum, ydum + 2 * np.pi, c='k') ax[1].plot(xdum, ydum + 2 * np.pi, c='k') ax[1].axhline(mean_phasesp, xmin=0, xmax=0.1, color='r') ax[1].set_ylim(-np.pi, 3 * np.pi) ax[1].set_xlim(0, 1) # Non-Prefer precession xdum = np.linspace(0, 1, 10) mean_phasesp = circmean(nonprefer_phasesp) regress = rcc(nonprefer_dsp, nonprefer_phasesp) ydum = regress['phi0'] + xdum * 2 * np.pi * regress['aopt'] ax[2].scatter(nonprefer_dsp, nonprefer_phasesp, marker='.', c='gray', s=1) ax[2].scatter(nonprefer_dsp, nonprefer_phasesp + 2 * np.pi, marker='.', c='gray', s=1) ax[2].plot(xdum, ydum, c='k') ax[2].plot(xdum, ydum + 2 * np.pi, c='k') ax[2].plot(xdum, ydum + 2 * np.pi, c='k') ax[2].axhline(mean_phasesp, xmin=0, xmax=0.1, color='r') ax[2].set_ylim(-np.pi, 3 * np.pi) ax[2].set_xlim(0, 1) # Onset vs Slope p_onset, _ = watson_williams(prefer_onset, nonprefer_onset) _, p_slope = ranksums(prefer_slope, nonprefer_slope) ax[3].scatter(prefer_slope, prefer_onset, marker='o', c=pre_c['prefer'], label='prefer') ax[3].scatter(nonprefer_slope, nonprefer_onset, marker='x', c=pre_c['nonprefer'], label='nonprefer') ax[3].set_xlabel('Precession slope (rad)') ax[3].set_ylabel('Precession onset (rad)') customlegend(ax[3], fontsize=legendsize) # # Onset # p_onset, _ = watson_williams(prefer_onset, nonprefer_onset) # onset_bins = np.linspace(0, 2*np.pi, 20) # prefer_onsetbins, _ = np.histogram(prefer_onset, bins=onset_bins) # nonprefer_onsetbins, _ = np.histogram(nonprefer_onset, bins=onset_bins) # ax[3].step(onset_bins[:-1], prefer_onsetbins/prefer_onsetbins.sum(), where='pre', c=pre_c['prefer'], label='prefer') # ax[3].step(onset_bins[:-1], nonprefer_onsetbins/nonprefer_onsetbins.sum(), where='pre', c=pre_c['nonprefer'], label='nonprefer') # ax[3].annotate('Watson-William\np%s'%(p2str(p_onset)), xy=(0.6, 0.6), xycoords='axes fraction') # ax[3].set_xlabel('Precession onset (rad)') # customlegend(ax[3], fontsize=legendsize) # # # Slope # _, p_slope = ranksums(prefer_slope, nonprefer_slope) # slope_bins = np.linspace(-2*np.pi, 0, 20) # prefer_slopebins, _ = np.histogram(prefer_slope, bins=slope_bins) # nonprefer_slopebins, _ = np.histogram(nonprefer_slope, bins=slope_bins) # ax[4].step(slope_bins[:-1], prefer_slopebins/prefer_slopebins.sum(), where='pre', c=pre_c['prefer'], label='prefer') # ax[4].step(slope_bins[:-1], nonprefer_slopebins/nonprefer_slopebins.sum(), where='pre', c=pre_c['nonprefer'], label='nonprefer') # ax[4].annotate('Ranksums\np%s'%(p2str(p_slope)), xy=(0.6, 0.6), xycoords='axes fraction') # ax[4].set_xlabel('Precession slope (rad)') # customlegend(ax[4], fontsize=legendsize) # Spike phase prefer_phasesp_mean, nonprefer_phasesp_mean = circmean( prefer_phasesp), circmean(nonprefer_phasesp) p_phasesp, _ = watson_williams(prefer_phasesp, nonprefer_phasesp) phasesp_bins = np.linspace(-np.pi, np.pi, 20) prefer_phasespbins, _ = np.histogram(prefer_phasesp, bins=phasesp_bins) nonprefer_phasespbins, _ = np.histogram(nonprefer_phasesp, bins=phasesp_bins) norm_preferphasebins = prefer_phasespbins / prefer_phasespbins.sum() norm_nonpreferphasebins = nonprefer_phasespbins / nonprefer_phasespbins.sum( ) maxl = max(norm_preferphasebins.max(), norm_nonpreferphasebins.max()) ax[4].step(midedges(phasesp_bins), norm_preferphasebins, color='r', label='prefer') ax[4].step(midedges(phasesp_bins), norm_nonpreferphasebins, color='b', label='nonprefer') ax[4].scatter(prefer_phasesp_mean, maxl * 1.1, color='r', marker='|', s=64) ax[4].scatter(nonprefer_phasesp_mean, maxl * 1.1, color='b', marker='|', s=64) ax[4].annotate('Watson-William\np%s' % (p2str(p_phasesp)), xy=(0.6, 0.2), xycoords='axes fraction') ax[4].set_xlabel('Precession spike phase') customlegend(ax[4], fontsize=legendsize) return ax
def plot_placefield_examples(rawdf, save_dir=None): example_dir = join(save_dir, 'example_fields2') os.makedirs(example_dir) field_figl = total_figw / 8 field_linew = 0.75 field_ms = 1 warnings.filterwarnings("ignore") # Parameters vthresh = 5 sthresh = 3 num_trials = rawdf.shape[0] aedges = np.linspace(-np.pi, np.pi, 36) aedm = midedges(aedges) abind = aedges[1] - aedges[0] sp_binwidth = 5 precess_filter = PrecessionFilter() # Plot color wheel fig_ch, ax_ch = color_wheel('hsv', (field_figl, field_figl)) fig_ch.savefig(os.path.join(save_dir, 'colorwheel.%s' % (figext)), transparent=True, dpi=dpi) # Selected Examples example_list = [ 'CA1-field16', 'CA2-field11', 'CA3-field378', # Precession 'CA1-field151', 'CA1-field222', 'CA1-field389', 'CA1-field400', 'CA1-field409', 'CA2-field28', 'CA2-field47', 'CA3-field75' ] fieldid = dict(CA1=0, CA2=0, CA3=0) fieldid_skip = dict(CA1=0, CA2=0, CA3=0) for ntrial in range(num_trials): wave = rawdf.loc[ntrial, 'wave'] precesser = PrecessionProcesser(wave=wave) for ca in ['CA%d' % i for i in range(1, 4)]: # Get data field_df = rawdf.loc[ntrial, ca + 'fields'] indata = rawdf.loc[ntrial, ca + 'indata'] if indata.shape[0] < 1: continue trajx, trajy = indata['x'].to_numpy(), indata['y'].to_numpy() num_fields = field_df.shape[0] tunner = IndataProcessor(indata, vthresh=5, sthresh=3, minpasstime=0.4, smooth=None) interpolater_angle = interp1d(tunner.t, tunner.angle) interpolater_x = interp1d(tunner.t, tunner.x) interpolater_y = interp1d(tunner.t, tunner.y) all_maxt, all_mint = tunner.t.max(), tunner.t.min() trange = (all_maxt, all_mint) dt = tunner.t[1] - tunner.t[0] precesser.set_trange(trange) for nfield in range(num_fields): if ('%s-field%d' % (ca, fieldid[ca])) not in example_list: fieldid[ca] += 1 continue print('Plotting fields: Trial %d/%d %s field %d/%d' % (ntrial, num_trials, ca, nfield, num_fields)) # Get field spikes xytsp, xyval = field_df.loc[nfield, ['xytsp', 'xyval']] tsp, xsp, ysp = xytsp['tsp'], xytsp['xsp'], xytsp['ysp'] pf = field_df.loc[nfield, 'pf'] # Get spike angles insession = np.where((tsp < all_maxt) & (tsp > all_mint))[0] tspins, xspins, yspins = tsp[insession], xsp[insession], ysp[ insession] anglespins = interpolater_angle(tspins) # Directionality passdf = field_df.loc[nfield, 'passes'] (xl, yl, tl, hdl), tspl = append_info_from_passes(passdf, vthresh, sthresh, trange) if (len(tspl) < 1) or (len(tl) < 1): # fieldid[ca] += 1 fieldid_skip[ca] += 1 continue x = np.concatenate(xl) y = np.concatenate(yl) pos = np.stack([x, y]).T hd = np.concatenate(hdl) tsp = np.concatenate(tspl) xsp, ysp = interpolater_x(tsp), interpolater_y(tsp) possp = np.stack([xsp, ysp]).T hdsp = interpolater_angle(tsp) # Directionality biner = DirectionerBining(aedges, hd) fieldangle, fieldR, (spike_bins, occ_bins, _) = biner.get_directionality(hdsp) mlmer = DirectionerMLM(pos, hd, dt, sp_binwidth, abind) fieldangle, fieldR, norm_prob = mlmer.get_directionality( possp, hdsp) norm_prob[np.isnan(norm_prob)] = 0 # # (Plot) Place field Example fig2 = plt.figure(figsize=(field_figl * 2, field_figl)) peak_rate = pf['map'].max() ax_field2 = fig2.add_subplot(1, 2, 1) ax_field2.plot(trajx, trajy, c='0.8', linewidth=0.25) ax_field2.plot(xyval[:, 0], xyval[:, 1], c='k', zorder=3, linewidth=field_linew) ax_field2.scatter(xspins, yspins, c=anglespins, marker='.', cmap='hsv', s=field_ms, zorder=2.5) ax_field2.axis('off') x_new, y_new = circular_density_1d(aedm, 30 * np.pi, 100, (-np.pi, np.pi), w=norm_prob) l = y_new.max() ax_polar = fig2.add_axes([0.33, 0.3, 0.6, 0.6], polar=True) ax_polar.plot(x_new, y_new, c='0.3', linewidth=field_linew, zorder=2.1) ax_polar.plot([x_new[-1], x_new[0]], [y_new[-1], y_new[0]], c='0.3', linewidth=field_linew, zorder=2.1) # ax_polar.plot([fieldangle, fieldangle], [0, l], c='k', linewidth=field_linew) ax_polar.annotate("", xy=(fieldangle, l), xytext=(0, 0), color='k', zorder=3, arrowprops=dict(arrowstyle="->")) ax_polar.annotate(r'$\theta_{rate}$', xy=(fieldangle, l), fontsize=legendsize) ax_polar.spines['polar'].set_visible(False) ax_polar.set_xticks([0, np.pi / 2, np.pi, 3 * np.pi / 2]) ax_polar.set_yticks([]) ax_polar.set_yticklabels([]) ax_polar.set_xticklabels([]) basey = -0.3 ax_polar.annotate('%0.2f' % (peak_rate), xy=(0.75, 0.05), color='k', zorder=3, fontsize=legendsize, xycoords='figure fraction') ax_polar.annotate('%0.2f' % (fieldR), xy=(0.75, 0.175), color='k', zorder=3, fontsize=legendsize, xycoords='figure fraction') # ax_polar.text(0.5, basey, '%0.2f' % (peak_rate), fontsize=legendsize, transform=ax_polar.transAxes) # ax_polar.text(0.5, basey + 0.25, '%0.2f' % (fieldR), fontsize=legendsize, transform=ax_polar.transAxes) fig2.tight_layout() fig2.savefig(os.path.join(example_dir, '%s-field%d.png' % (ca, fieldid[ca])), dpi=dpi) fig2.savefig(os.path.join(example_dir, '%s-field%d.eps' % (ca, fieldid[ca])), dpi=dpi) plt.close() fieldid[ca] += 1
def plot_both_slope_offset(self): density_figsize = (figl+0.5, figl*2) slice_figsize = (figl+0.5, figl*2) selected_adiff = np.linspace(0, np.pi, 6) # 20 adiff_ticks = [0, np.pi / 2, np.pi] adiff_ticksl = ['0', '$\pi$', '$2\pi$'] adiff_label = r'$|d(\theta_{pass}, \theta_{precess})|$' offset_label = 'Onset phase (rad)' offset_slicerange = (0, 2*np.pi) offset_bound = (0, 2 * np.pi) offset_xticks = [0, np.pi, 2*np.pi] offset_xticksl = ['0', '$\pi$', '$2\pi$'] offset_slicegap = 0.017 # 0.007 slope_label = 'Slope ' + '$(rad)$' slope_slicerange = (-2 * np.pi, 0) slope_bound = (-2 * np.pi, 0) slope_xticks = [-2 * np.pi, -np.pi, 0] slope_xticksl = ['$-2\pi$', '$-\pi$', '0'] slope_slicegap = 0.01 # 0.007 adiff_edges = np.linspace(0, np.pi, 500) offset_edges = np.linspace(offset_bound[0], offset_bound[1], 500) slope_edges = np.linspace(slope_bound[0], slope_bound[1], 500) fig_density, ax_density = plt.subplots(2, 1, figsize=density_figsize, sharex='col', sharey='row') fig_slices, ax_slices = plt.subplots(2, 1, figsize=slice_figsize, sharex='row', sharey='row') anglediff, pass_nspikes = self.stack_anglediff(self.singlefield_df, precess_ref=True) anglediff = np.abs(anglediff) slope = self.stack_key(self.singlefield_df, 'rcc_m') slope = slope * 2 * np.pi offset = self.stack_key(self.singlefield_df, 'rcc_c') # Expand sample according to spikes anglediff_spikes = repeat_arr(anglediff, pass_nspikes) # 1D spike hisotgram spikes_bins, spikes_edges = np.histogram(anglediff_spikes, bins=adiff_edges) # 2D slope/offset histogram offset_bins, offset_xedges, offset_yedges = np.histogram2d(anglediff, offset, bins=(adiff_edges, offset_edges)) slope_bins, slope_xedges, slope_yedges = np.histogram2d(anglediff, slope, bins=(adiff_edges, slope_edges)) offset_normbins = self.norm_div(offset_bins, spikes_bins) slope_normbins = self.norm_div(slope_bins, spikes_bins) # Unbinning offset_xedm, offset_yedm = midedges(offset_xedges), midedges(offset_yedges) slope_xedm, slope_yedm = midedges(slope_xedges), midedges(slope_yedges) offset_adiff, offset_norm = unfold_binning_2d(offset_normbins, offset_xedm, offset_yedm) slope_adiff, slope_norm = unfold_binning_2d(slope_normbins, slope_xedm, slope_yedm) # Linear-circular regression regress = rcc(offset_adiff, offset_norm) offset_m, offset_c, offset_rho, offset_p = regress['aopt'], regress['phi0'], regress['rho'], regress['p'] regress = rcc(slope_adiff, slope_norm) slope_m, slope_c, slope_rho, slope_p = regress['aopt'], regress['phi0'], regress['rho'], regress['p'] slope_c = slope_c - 2 * np.pi # Density offset_xx, offset_yy, offset_zz = linear_circular_gauss_density(offset_adiff, offset_norm, cir_kappa=4 * np.pi, lin_std=0.2, xbins=50, ybins=50, xbound=(0, np.pi), ybound=offset_bound) slope_xx, slope_yy, slope_zz = linear_circular_gauss_density(slope_adiff, slope_norm, cir_kappa=4 * np.pi, lin_std=0.2, xbins=50, ybins=50, xbound=(0, np.pi), ybound=slope_bound) # ax_density[0].pcolormesh(offset_xx, offset_yy, offset_zz) # Plot offset density cmap = 'Blues' ax_density[0].hist2d(offset_adiff, offset_norm, bins=(np.linspace(0, np.pi, 36), np.linspace(0, 2 * np.pi, 36)), density=True, cmap=cmap) regressed = (offset_c + offset_xedm * offset_m) ax_density[0].plot(offset_xedm, regressed, c='k') ax_density[0].text(np.pi/3, regressed.max() + 0.5, 'p%s'%p2str(offset_p), fontsize=legendsize) ax_density[0].set_xticks(adiff_ticks) ax_density[0].set_xticklabels(adiff_ticksl) ax_density[0].set_yticks(offset_xticks) ax_density[0].set_yticklabels(offset_xticksl) ax_density[0].tick_params(labelsize=ticksize, direction='inout') ax_density[0].set_ylabel(offset_label, fontsize=fontsize) # Plot slope density ax_density[1].hist2d(slope_adiff, slope_norm, bins=(np.linspace(0, np.pi, 36), np.linspace(-2 * np.pi, 0, 36)), density=True, cmap=cmap) regressed = (slope_c + slope_xedm * slope_m) # ax_density[1].pcolormesh(slope_xx, slope_yy, slope_zz) ax_density[1].plot(slope_xedm, regressed, c='k') ax_density[1].text(np.pi/3, regressed.max() + 0.5, 'p%s'%p2str(slope_p), fontsize=legendsize) ax_density[1].set_xticks(adiff_ticks) ax_density[1].set_xticklabels(adiff_ticksl) ax_density[1].set_yticks(slope_xticks) ax_density[1].set_yticklabels(slope_xticksl) ax_density[1].tick_params(labelsize=ticksize, direction='inout') ax_density[1].set_xlabel(adiff_label, fontsize=fontsize) ax_density[1].set_ylabel(slope_label, fontsize=fontsize) ax_slices[0], _ = plot_marginal_slices(ax_slices[0], offset_xx, offset_yy, offset_zz, selected_adiff, offset_slicerange, offset_slicegap) ax_slices[0].set_xticks(offset_xticks) ax_slices[0].set_xticklabels(offset_xticksl) ax_slices[0].set_xlabel(offset_label, fontsize=fontsize) ax_slices[0].tick_params(labelsize=ticksize, direction='inout') ax_slices[1], _ = plot_marginal_slices(ax_slices[1], slope_xx, slope_yy, slope_zz, selected_adiff, slope_slicerange, slope_slicegap) ax_slices[1].set_xticks(slope_xticks) ax_slices[1].set_xticklabels(slope_xticksl) ax_slices[1].tick_params(labelsize=ticksize, direction='inout') ax_slices[1].set_xlabel(slope_label, fontsize=fontsize) # Colorbar sm = plt.cm.ScalarMappable(cmap=cm.brg, norm=plt.Normalize(vmin=selected_adiff.min(), vmax=selected_adiff.max())) fig_colorbar = plt.figure(figsize=slice_figsize) fig_colorbar.subplots_adjust(right=0.8) cbar_ax = fig_colorbar.add_axes([0.7, 0.15, 0.03, 0.7]) cb = fig_colorbar.colorbar(sm, cax=cbar_ax) cb.set_ticks(adiff_ticks) cb.set_ticklabels(adiff_ticksl) cb.set_label(adiff_label, fontsize=fontsize, rotation=90) for ax in ax_slices.flatten(): ax.axes.get_yaxis().set_visible(False) ax.spines["top"].set_visible(False) ax.spines["right"].set_visible(False) ax.spines["left"].set_visible(False) # Others fig_density.tight_layout() fig_density.savefig(join(self.plot_dir, 'Networks_density.png'), dpi=300) fig_slices.tight_layout() fig_slices.savefig(join(self.plot_dir, 'Networks_slices.png'), dpi=300) # fig_colorbar.tight_layout() fig_colorbar.savefig(join(self.plot_dir, 'Networks_adiff_colorbar.png'), dpi=300) return None
def plot_field_bestprecession(self): fig_R, ax_R = plt.subplots(figsize=(figl, figl)) fig_2Dscatter, ax_2Dscatter = plt.subplots(figsize=(figl, figl), sharey=True) fig_pishift = plt.figure(figsize=(figl*2, figl)) ax_pishift = np.array( [fig_pishift.add_subplot(1, 2, i+1, polar=True) for i in range(2)] ) fid = 0 data = {'field': [], 'precess': [], 'precess_low':[], 'R':[], 'shufp':[]} # Re-organize & filter for i in range(self.singlefield_df.shape[0]): precess_info = self.singlefield_df.loc[i, 'precess_info'] if precess_info is None: continue fieldangle_mlm, precess_angle = self.singlefield_df.loc[i, ['fieldangle_mlm', 'precess_angle']] precess_angle_low = self.singlefield_df.loc[i, 'precess_angle_low'] data['field'].append(fieldangle_mlm) data['precess'].append(precess_angle) data['precess_low'].append(precess_angle_low) data['R'].append(precess_info['R']) data['shufp'].append(precess_info['pval']) fid += 1 # Plot Scatter: field vs precess angles ax_2Dscatter.scatter(data['field'], data['precess'], alpha=0.2, s=8, c='gray') ax_2Dscatter.plot([0, np.pi], [np.pi, 2 * np.pi], c='k') ax_2Dscatter.plot([np.pi, 2 * np.pi], [0, np.pi], c='k') ax_2Dscatter.set_xlabel(r'$\theta_{rate}$', fontsize=fontsize) ax_2Dscatter.set_xticks([0, np.pi, 2 * np.pi]) ax_2Dscatter.set_xticklabels(['$0$', '$\pi$', '$2\pi$']) ax_2Dscatter.set_yticks([0, np.pi, 2 * np.pi]) ax_2Dscatter.set_yticklabels(['$0$', '$\pi$', '$2\pi$']) ax_2Dscatter.tick_params(labelsize=ticksize, direction='inout') ax_2Dscatter.set_ylabel(r'$\theta_{Precess}$', fontsize=fontsize) fig_2Dscatter.tight_layout() fig_2Dscatter.savefig(join(self.plot_dir, 'Networks_field_precess_2Dscatter.png'), dpi=300) # Plot Histogram: d(precess, rate) fieldangles = np.array(data['field']) precessangles = np.array(data['precess']) nanmask = (~np.isnan(fieldangles)) & (~np.isnan(precessangles)) adiff = cdiff(precessangles[nanmask], fieldangles[nanmask]) bins, edges = np.histogram(adiff, bins=np.linspace(-np.pi, np.pi, 36)) bins_norm = bins / np.sum(bins) l = bins_norm.max() ax_pishift[0].bar(midedges(edges), bins_norm, width=edges[1] - edges[0], alpha=0.5, color='gray') mean_angle = circmean(adiff) mean_angle = np.mod(mean_angle + np.pi, 2 * np.pi) - np.pi ax_pishift[0].plot([mean_angle, mean_angle], [0, l], c='k', linestyle='dashed') ax_pishift[0].plot([0, 0], [0, l], c='k') ax_pishift[0].scatter(0, 0, s=16, c='gray') ax_pishift[0].text(0.18, l * 0.4, r'$\theta_{rate}$', fontsize=fontsize+2) ax_pishift[0].spines['polar'].set_visible(False) ax_pishift[0].set_yticklabels([]) ax_pishift[0].set_xticklabels([]) ax_pishift[0].grid(False) ax_pishift[0].set_ylabel('All passes', fontsize=fontsize) # ax_pishift[0].yaxis.labelpad = 5 v_pval, v_stat = vtest(adiff, mu=np.pi) ax_pishift[0].text(x=0.01, y=0.95, s='p%s'%(p2str(v_pval)), fontsize=legendsize, transform=ax_pishift[0].transAxes) # Plot Histogram: d(precess_low, rate) fieldangles = np.array(data['field']) precessangles_low = np.array(data['precess_low']) nanmask = (~np.isnan(fieldangles)) & (~np.isnan(precessangles_low)) adiff = cdiff(precessangles_low[nanmask], fieldangles[nanmask]) bins, edges = np.histogram(adiff, bins=np.linspace(-np.pi, np.pi, 36)) bins_norm = bins / np.sum(bins) l = bins_norm.max() ax_pishift[1].bar(midedges(edges), bins_norm, width=edges[1] - edges[0], alpha=0.5, color='gray') mean_angle = circmean(adiff) mean_angle = np.mod(mean_angle + np.pi, 2 * np.pi) - np.pi ax_pishift[1].plot([mean_angle, mean_angle], [0, l], c='k', linestyle='dashed') ax_pishift[1].plot([0, 0], [0, l], c='k') ax_pishift[1].scatter(0, 0, s=16, c='gray') ax_pishift[1].text(0.18, l * 0.4, r'$\theta_{rate}$', fontsize=fontsize+2) ax_pishift[1].spines['polar'].set_visible(False) ax_pishift[1].set_yticklabels([]) ax_pishift[1].set_xticklabels([]) ax_pishift[1].grid(False) ax_pishift[1].set_ylabel('Low-spike passes', fontsize=fontsize) v_pval, v_stat = vtest(adiff, mu=np.pi) ax_pishift[1].text(x=0.01, y=0.95, s='p%s'%(p2str(v_pval)), fontsize=legendsize, transform=ax_pishift[1].transAxes) fig_pishift.tight_layout() fig_pishift.savefig(join(self.plot_dir, 'Networks_field_precess_pishift.png'), dpi=300) # Plot R all_R = np.array(data['R']) rbins, redges = np.histogram(all_R, bins=50) rbinsnorm = np.cumsum(rbins) / rbins.sum() ax_R.plot(midedges(redges), rbinsnorm) ax_R.set_xlabel('R', fontsize=fontsize) ax_R.set_ylabel('Cumulative density', fontsize=fontsize) ax_R.tick_params(axis='both', which='major', labelsize=fontsize, direction='inout') ax_R.set_yticks([0, 0.5, 1]) fig_R.tight_layout() fig_R.savefig(join(self.plot_dir, 'Networks_field_precess_R.png'), dpi=300)
def plot_overall_bestprecession(self): print('Plot overall best precession') fig_basic, ax_basic = plt.subplots(figsize=(figl+0.1, figl), sharex=True, sharey=True) precess_adiff = [] precess_nspikes = [] nonprecess_adiff = [] nonprecess_nspikes = [] for i in range(self.singlefield_df.shape[0]): refangle = self.singlefield_df.loc[i, 'fieldangle_mlm'] allprecess_df = self.singlefield_df.loc[i, 'precess_df'] precess_df = allprecess_df[allprecess_df['precess_exist']] nonprecess_df = allprecess_df[~allprecess_df['precess_exist']] precess_counts = precess_df.shape[0] nonprecess_counts = nonprecess_df.shape[0] if precess_counts > 0: precess_adiff.append(cdiff(precess_df['spike_angle'].to_numpy(), refangle)) precess_nspikes.append(precess_df['pass_nspikes'].to_numpy()) if nonprecess_counts > 0: nonprecess_adiff.append(cdiff(nonprecess_df['spike_angle'].to_numpy(), refangle)) nonprecess_nspikes.append(nonprecess_df['pass_nspikes'].to_numpy()) # Density of Fraction, Spikes and Ratio precess_adiff = np.abs(np.concatenate(precess_adiff)) nonprecess_adiff = np.concatenate(nonprecess_adiff) precess_nspikes = np.abs(np.concatenate(precess_nspikes)) nonprecess_nspikes = np.concatenate(nonprecess_nspikes) adiff_spikes_p = repeat_arr(precess_adiff, precess_nspikes) adiff_spikes_np = repeat_arr(nonprecess_adiff, nonprecess_nspikes) adiff_bins = np.linspace(0, np.pi, 41) adm = midedges(adiff_bins) precess_bins, _ = np.histogram(precess_adiff, bins=adiff_bins) nonprecess_bins, _ = np.histogram(nonprecess_adiff, bins=adiff_bins) fraction_bins = precess_bins/(precess_bins + nonprecess_bins) spike_bins_p, _ = np.histogram(adiff_spikes_p, bins=adiff_bins) spike_bins_np, _ = np.histogram(adiff_spikes_np, bins=adiff_bins) spike_bins = spike_bins_p + spike_bins_np norm_bins = (fraction_bins / spike_bins) precess_allcount, nonprecess_allcount = precess_bins.sum(), nonprecess_bins.sum() rho, pval = spearmanr(adm, norm_bins) pm, pc, pr, ppval, _ = linregress(adm, norm_bins/ norm_bins.sum()) xdum = np.linspace(adm.min(), adm.max(), 10) ax_basic.step(adm, fraction_bins / fraction_bins.sum(), color='darkblue', alpha=0.7, linewidth=1, label='Precession') ax_basic.step(adm, spike_bins / spike_bins.sum(), color='darkorange', alpha=0.7, linewidth=1, label='Spike') ax_basic.step(adm, norm_bins / norm_bins.sum(), color='darkgreen', alpha=0.7, linewidth=1, label='Ratio') customlegend(ax_basic, fontsize=legendsize-1) ax_basic.set_xticks([0, np.pi / 2, np.pi]) ax_basic.set_xticklabels(['0', '$\pi/2$', '$\pi$']) # ax_basic.set_yticks([0, 0.04]) ax_basic.tick_params(axis='both', which='major', labelsize=ticksize, direction='in') # ax_basic.set_ylim(0, 0.045) ax_basic.set_ylabel('Normalized counts', fontsize=fontsize) ax_basic.set_xlabel(self.angle_title, fontsize=fontsize) plt.tight_layout() plt.savefig(join(self.plot_dir, 'Networks_overall_bestprecession.png'), dpi=300)
def plot_both_slope_offset_Romani(simdf, ax): def norm_div(target_hist, divider_hist): target_hist_norm = target_hist / divider_hist.reshape(-1, 1) target_hist_norm[np.isnan(target_hist_norm)] = 0 target_hist_norm[np.isinf(target_hist_norm)] = 0 target_hist_norm = target_hist_norm / np.sum( target_hist_norm) * np.sum(target_hist) return target_hist_norm nap_thresh = 1 selected_adiff = np.linspace(0, np.pi, 6) # 20 offset_bound = (0, 2 * np.pi) slope_bound = (-2 * np.pi, 0) adiff_edges = np.linspace(0, np.pi, 100) offset_edges = np.linspace(offset_bound[0], offset_bound[1], 100) slope_edges = np.linspace(slope_bound[0], slope_bound[1], 100) stat_fn = 'fig8_SIM_slopeoffset.txt' stat_record(stat_fn, True, 'Average Phase precession') # Construct pass df refangle_key = 'rate_angle' passdf_dict = { 'anglediff': [], 'slope': [], 'onset': [], 'pass_nspikes': [] } spikedf_dict = {'anglediff': [], 'phasesp': []} dftmp = simdf[(~simdf[refangle_key].isna()) & (simdf['numpass_at_precess'] >= nap_thresh)].reset_index() for i in range(dftmp.shape[0]): allprecess_df = dftmp.loc[i, 'precess_df'] precessdf = allprecess_df[allprecess_df['precess_exist']].reset_index( drop=True) numprecess = precessdf.shape[0] if numprecess < 1: continue ref_angle = dftmp.loc[i, refangle_key] anglediff_tmp = cdiff(precessdf['mean_anglesp'].to_numpy(), ref_angle) phasesp_tmp = np.concatenate(precessdf['phasesp'].to_list()) passdf_dict['anglediff'].extend(anglediff_tmp) passdf_dict['slope'].extend(precessdf['rcc_m']) passdf_dict['onset'].extend(precessdf['rcc_c']) passdf_dict['pass_nspikes'].extend(precessdf['pass_nspikes']) spikedf_dict['anglediff'].extend( repeat_arr(anglediff_tmp, precessdf['pass_nspikes'].to_numpy().astype(int))) spikedf_dict['phasesp'].extend(phasesp_tmp) passdf = pd.DataFrame(passdf_dict) passdf['slope_piunit'] = passdf['slope'] * 2 * np.pi spikedf = pd.DataFrame(spikedf_dict) absadiff_pass = np.abs(passdf['anglediff'].to_numpy()) offset = passdf['onset'].to_numpy() slope = passdf['slope_piunit'].to_numpy() absadiff_spike = np.abs(spikedf['anglediff'].to_numpy()) phase_spike = spikedf['phasesp'].to_numpy() # 1D spike hisotgram spikes_bins, spikes_edges = np.histogram(absadiff_spike, bins=adiff_edges) # 2D slope/offset histogram offset_bins, offset_xedges, offset_yedges = np.histogram2d( absadiff_pass, offset, bins=(adiff_edges, offset_edges)) slope_bins, slope_xedges, slope_yedges = np.histogram2d(absadiff_pass, slope, bins=(adiff_edges, slope_edges)) offset_xedm, offset_yedm = midedges(offset_xedges), midedges(offset_yedges) slope_xedm, slope_yedm = midedges(slope_xedges), midedges(slope_yedges) offset_normbins = norm_div(offset_bins, spikes_bins) slope_normbins = norm_div(slope_bins, spikes_bins) # Unbinning offset_adiff, offset_norm = unfold_binning_2d(offset_normbins, offset_xedm, offset_yedm) slope_adiff, slope_norm = unfold_binning_2d(slope_normbins, slope_xedm, slope_yedm) # Linear-circular regression regress = rcc(offset_adiff, offset_norm) offset_m, offset_c, offset_rho, offset_p = regress['aopt'], regress[ 'phi0'], regress['rho'], regress['p'] regress = rcc(slope_adiff, slope_norm) slope_m, slope_c, slope_rho, slope_p = regress['aopt'], regress[ 'phi0'], regress['rho'], regress['p'] slope_c = slope_c - 2 * np.pi stat_record( stat_fn, False, 'LC_Regression Onset-adiff $r_{(%d)}=%0.3f, p=%s$' % (offset_bins.sum(), offset_rho, p2str(offset_p))) stat_record( stat_fn, False, 'LC_Regression Slope-adiff $r_{(%d)}=%0.3f, p=%s$' % (slope_bins.sum(), slope_rho, p2str(slope_p))) # # Plot average precession curves low_mask = absadiff_pass < (np.pi / 6) high_mask = absadiff_pass > (np.pi - np.pi / 6) slopes_high_all, offsets_high_all = slope[high_mask], offset[high_mask] slopes_low_all, offsets_low_all = slope[low_mask], offset[low_mask] pval_slope, _, slope_descrips, slopetxt = my_kruskal_2samp( slopes_low_all, slopes_high_all, 'low-$|d|$', 'high-$|d|$') (mdn_slopel, lqr_slopel, hqr_slopel), (mdn_slopeh, lqr_slopeh, hqr_slopeh) = slope_descrips pval_offset, _, offset_descrips, offsettxt = my_ww_2samp( offsets_low_all, offsets_high_all, 'low-$|d|$', 'high-$|d|$') (cmean_offsetl, sem_offsetl), (cmean_offseth, sem_offseth) = offset_descrips xdum = np.linspace(0, 1, 10) high_agg_ydum = mdn_slopeh * xdum + cmean_offseth low_agg_ydum = mdn_slopel * xdum + cmean_offsetl slopel_valstr = r'low-$|d|=%0.2f$' % (mdn_slopel) slopeh_valstr = r'high-$|d|=%0.2f$' % (mdn_slopeh) offsetl_valstr = r'low-$|d|=%0.2f$' % (cmean_offsetl) offseth_valstr = r'high-$|d|=%0.2f$' % (cmean_offseth) stat_record(stat_fn, False, '===== Average precession curves ====') stat_record(stat_fn, False, 'Slope, %s, %s, %s' % (slopel_valstr, slopeh_valstr, slopetxt)) stat_record( stat_fn, False, 'Onset, %s, %s, %s' % (offsetl_valstr, offseth_valstr, offsettxt)) ax[0].plot(xdum, high_agg_ydum, c='lime', label='$|d|>5\pi/6$') ax[0].plot(xdum, low_agg_ydum, c='darkblue', label='$|d|<\pi/6$') ax[0].annotate('$p_s$' + '=%s' % (p2str(pval_slope)), xy=(0.015, 0.2 + 0.03), xycoords='axes fraction', fontsize=legendsize) ax[0].annotate('$p_o$' + '=%s' % (p2str(pval_offset)), xy=(0.015, 0.035 + 0.03), xycoords='axes fraction', fontsize=legendsize) ax[0].spines["top"].set_visible(False) ax[0].spines["right"].set_visible(False) ax[0].set_xticks([0, 1]) ax[0].set_xlim(0, 1) ax[0].set_ylim(-np.pi - 1, np.pi + 0.3) ax[0].set_yticks([-np.pi, 0, np.pi]) ax[0].set_yticklabels(['$-\pi$', '0', '$\pi$']) ax[0].tick_params(labelsize=ticksize) ax[0].set_xlabel('Position') customlegend(ax[0], fontsize=legendsize, loc='lower left', handlelength=0.5, bbox_to_anchor=(0.1, 0.7)) ax[0].set_ylabel('Phase (rad)', fontsize=fontsize) # # Spike phases low_mask_sp = absadiff_spike < (np.pi / 6) high_mask_sp = absadiff_spike > (np.pi - np.pi / 6) phasesph = phase_spike[high_mask_sp] phasespl = phase_spike[low_mask_sp] fstat, k_pval = circ_ktest(phasesph, phasespl) p_ww, _, _, p_wwtxt = my_ww_2samp(phasesph, phasespl, r'$high-|d|$', r'$low-|d|$') mean_phasesph = circmean(phasesph) mean_phasespl = circmean(phasespl) nh, _, _ = ax[1].hist(phasesph, bins=36, density=True, histtype='step', color='lime') nl, _, _ = ax[1].hist(phasespl, bins=36, density=True, histtype='step', color='darkblue') ml = max(nh.max(), nl.max()) ax[1].scatter(mean_phasesph, ml * 1.1, marker='|', color='lime', linewidth=0.75) ax[1].scatter(mean_phasespl, ml * 1.1, marker='|', color='darkblue', linewidth=0.75) ax[1].annotate(r'$p$=%s' % (p2str(p_ww)), xy=(0.3, 0.1), xycoords='axes fraction', fontsize=legendsize) ax[1].set_xlim(-np.pi, np.pi) ax[1].set_xticks([-np.pi, 0, np.pi]) ax[1].set_xticklabels(['$-\pi$', '0', '$\pi$']) ax[1].set_yticks([]) ax[1].tick_params(labelsize=ticksize) ax[1].spines["top"].set_visible(False) ax[1].spines["right"].set_visible(False) ax[1].spines["left"].set_visible(False) ax[1].set_xlabel('Phase (rad)', fontsize=fontsize) ax[1].set_ylabel('Relative\nfrequency', fontsize=fontsize) stat_record(stat_fn, False, 'SIM, difference of mean spike phases, %s' % (p_wwtxt)) stat_record(stat_fn, False, r'SIM, difference of concentration Bartlett\'s test $F_{(%d, %d)}=%0.2f, p=%s$' % \ (phasesph.shape[0], phasespl.shape[0], fstat, p2str(k_pval)))
def plot_field_bestprecession_Romani(simdf, ax): print('Plot field best precession') stat_fn = 'fig8_SIM_field_precess.txt' stat_record(stat_fn, True) nap_thresh = 1 # Stack data numpass_mask = simdf['numpass_at_precess'].to_numpy() >= nap_thresh numpass_low_mask = simdf['numpass_at_precess_low'].to_numpy() >= nap_thresh precess_adiff = [] precess_nspikes = [] all_adiff = [] all_slopes = [] # Density of Fraction, Spikes and Ratio df_this = simdf[numpass_mask & (~simdf['rate_angle'].isna())].reset_index(drop=True) for i in range(df_this.shape[0]): numpass_at_precess = df_this.loc[i, 'numpass_at_precess'] if numpass_at_precess < nap_thresh: continue refangle = df_this.loc[i, 'rate_angle'] allprecess_df = df_this.loc[i, 'precess_df'] if allprecess_df.shape[0] < 1: continue precess_df = allprecess_df[allprecess_df['precess_exist']] precess_counts = precess_df.shape[0] if precess_counts > 0: precess_adiff.append( cdiff(precess_df['mean_anglesp'].to_numpy(), refangle)) precess_nspikes.append(precess_df['pass_nspikes'].to_numpy()) if allprecess_df.shape[0] > 0: all_adiff.append( cdiff(allprecess_df['mean_anglesp'].to_numpy(), refangle)) all_slopes.append(allprecess_df['rcc_m'].to_numpy()) precess_adiff = np.abs(np.concatenate(precess_adiff)) precess_nspikes = np.abs(np.concatenate(precess_nspikes)) adiff_spikes_p = repeat_arr(precess_adiff, precess_nspikes.astype(int)) adiff_bins = np.linspace(0, np.pi, 45) adm = midedges(adiff_bins) precess_bins, _ = np.histogram(precess_adiff, bins=adiff_bins) spike_bins_p, _ = np.histogram(adiff_spikes_p, bins=adiff_bins) spike_bins = spike_bins_p norm_bins = (precess_bins / spike_bins) norm_bins[np.isnan(norm_bins)] = 0 norm_bins[np.isinf(norm_bins)] = 0 precess_allcount = precess_bins.sum() rho, pval = spearmanr(adm, norm_bins) pm, pc, pr, ppval, _ = linregress(adm, norm_bins / norm_bins.sum()) xdum = np.linspace(adm.min(), adm.max(), 10) linew_ax0 = 0.6 ax[0].step(adm, precess_bins / precess_bins.sum(), color='navy', linewidth=linew_ax0, label='Precession') ax[0].step(adm, spike_bins / spike_bins.sum(), color='orange', linewidth=linew_ax0, label='Spike') ax[0].step(adm, norm_bins / norm_bins.sum(), color='green', linewidth=linew_ax0, label='Ratio') ax[0].plot(xdum, xdum * pm + pc, color='green', linewidth=linew_ax0) ax[0].set_xticks([0, np.pi / 2, np.pi]) ax[0].set_xticklabels(['0', '$\pi/2$', '$\pi$']) # ax[0].set_ylim([0.01, 0.06]) ax[0].set_yticks([0, 0.1]) ax[0].tick_params(labelsize=ticksize) ax[0].spines["top"].set_visible(False) ax[0].spines["right"].set_visible(False) ax[0].set_xlabel(r'$|d(\theta_{pass}, \theta_{rate})|$' + ' (rad)', fontsize=fontsize) ax[0].set_ylabel('Relative count', fontsize=fontsize, labelpad=5) customlegend(ax[0], fontsize=legendsize, bbox_to_anchor=[0, 0.5], loc='lower left') ax[0].annotate('p=%s' % (p2str(pval)), xy=(0.4, 0.5), xycoords='axes fraction', fontsize=legendsize, color='green') stat_record( stat_fn, False, r"SIM Spearman's correlation: $r_{s(%d)}=%0.2f, p=%s$ " % (precess_allcount, rho, p2str(pval))) # Plot Rate angles vs Precess angles nprecessmask = simdf['precess_df'].apply( lambda x: x['precess_exist'].sum()) > 1 numpass_mask = numpass_mask[nprecessmask] numpass_low_mask = numpass_low_mask[nprecessmask] simdf2 = simdf[nprecessmask].reset_index(drop=True) rateangles = simdf2['rate_angle'].to_numpy() precessangles = simdf2['precess_angle'].to_numpy() precessangles_low = simdf2['precess_angle_low'].to_numpy() ax[1].scatter(rateangles[numpass_mask], precessangles[numpass_mask], marker='.', c='gray', s=2) ax[1].plot([0, np.pi], [np.pi, 2 * np.pi], c='k') ax[1].plot([np.pi, 2 * np.pi], [0, np.pi], c='k') ax[1].set_xlabel(r'$\theta_{rate}$', fontsize=fontsize) ax[1].set_xticks([0, np.pi, 2 * np.pi]) ax[1].set_xticklabels(['$0$', '$\pi$', '$2\pi$'], fontsize=fontsize) ax[1].set_yticks([0, np.pi, 2 * np.pi]) ax[1].set_yticklabels(['$0$', '$\pi$', '$2\pi$'], fontsize=fontsize) ax[1].spines["top"].set_visible(False) ax[1].spines["right"].set_visible(False) ax[1].set_ylabel(r'$\theta_{Precess}$', fontsize=fontsize) # Plot Histogram: d(precess, rate) mask = (~np.isnan(rateangles)) & (~np.isnan(precessangles) & numpass_mask) adiff = cdiff(precessangles[mask], rateangles[mask]) bins, edges = np.histogram(adiff, bins=np.linspace(-np.pi, np.pi, 36)) bins_norm = bins / np.sum(bins) l = bins_norm.max() ax[2].bar(midedges(edges), bins_norm, width=edges[1] - edges[0], zorder=0, color='gray') linewidth = 1 mean_angle = shiftcyc_full2half(circmean(adiff)) ax[2].annotate("", xy=(mean_angle, l), xytext=(0, 0), color='k', zorder=3, arrowprops=dict(arrowstyle="->")) ax[2].plot([0, 0], [0, l], c='k', linewidth=linewidth, zorder=3) ax[2].scatter(0, 0, s=16, c='gray') ax[2].spines['polar'].set_visible(False) ax[2].set_xticks([0, np.pi / 2, np.pi, 3 * np.pi / 2]) ax[2].set_yticks([0, l / 2]) ax[2].set_yticklabels([]) ax[2].set_xticklabels([]) v_pval, v_stat = vtest(adiff, mu=np.pi) ax[2].annotate('p=%s' % (p2str(v_pval)), xy=(0.25, 0.95), xycoords='axes fraction', fontsize=legendsize) ax[2].annotate(r'$\theta_{rate}$', xy=(0.95, 0.525), xycoords='axes fraction', fontsize=fontsize + 1) stat_record( stat_fn, False, r'SIM, d(precess, rate), $V_{(%d)}=%0.2f, p=%s$' % (bins.sum(), v_stat, p2str(v_pval))) ax[2].set_ylabel('All\npasses', fontsize=fontsize) # Plot Histogram: d(precess_low, rate) mask_low = (~np.isnan(rateangles)) & (~np.isnan(precessangles_low) & numpass_low_mask) adiff = cdiff(precessangles_low[mask_low], rateangles[mask_low]) bins, edges = np.histogram(adiff, bins=np.linspace(-np.pi, np.pi, 36)) bins_norm = bins / np.sum(bins) l = bins_norm.max() ax[3].bar(midedges(edges), bins_norm, width=edges[1] - edges[0], color='gray', zorder=0) mean_angle = shiftcyc_full2half(circmean(adiff)) ax[3].annotate("", xy=(mean_angle, l), xytext=(0, 0), color='k', zorder=3, arrowprops=dict(arrowstyle="->")) ax[3].plot([0, 0], [0, l], c='k', linewidth=linewidth, zorder=3) ax[3].scatter(0, 0, s=16, c='gray') ax[3].spines['polar'].set_visible(False) ax[3].set_xticks([0, np.pi / 2, np.pi, 3 * np.pi / 2]) ax[3].set_yticks([0, l / 2]) ax[3].set_yticklabels([]) ax[3].set_xticklabels([]) v_pval, v_stat = vtest(adiff, mu=np.pi) ax[3].annotate('p=%s' % (p2str(v_pval)), xy=(0.25, 0.95), xycoords='axes fraction', fontsize=legendsize) ax[3].annotate(r'$\theta_{rate}$', xy=(0.95, 0.525), xycoords='axes fraction', fontsize=fontsize + 1) stat_record( stat_fn, False, r'SIM, d(precess_low, rate), $V_{(%d)}=%0.2f, p=%s$' % (bins.sum(), v_stat, p2str(v_pval))) ax[3].set_ylabel('Low-spike\npasses', fontsize=fontsize)