Compositionality of social gaze in the prefrontal-amygdala circuits.
The 18 matches · 2 of them tie a paragraph to a whole file, not to given lines: weak matches, whose lines are not tinted
- [1] § Methods › Neural data analysis › Canonical correlation analysis (CCA) ↔ analysisCode/Cross_area_CCA.m, the whole file · a weak match · score 0.98 · canonical correlation, L2 regularization, fold cross validation, Pearson correlation, independently shuffled, population activity
- [2] § Methods › Neural data analysis › Encoding model of representational dissimilarity matrix (RDM) ↔ analysisCode/rsa_core_analysis.py, lines 1–88 · score 0.93 · Euclidean distances, dissimilarity matrices, representational geometry, neural RDM, Neural activity, brain region
- [3] § Methods › Neural data analysis › Encoding model of representational dissimilarity matrix (RDM) ↔ analysisCode/rsa_core_analysis.py, lines 1–88 · score 0.85 · multiple linear regression, dependent variable, regression model, neural RDM, diagonal, vectorized
- [4] § Methods › Neural data analysis › Population decoding analyses › Content decoding ↔ analysisCode/Cross_primitive_decoding.py, lines 1–64 · score 0.82 · fold cross validation, neural population activity, classifier trained, shuffling controls, decoding, neurons
- [5] § Methods › Neural data analysis › Population decoding analyses › Content decoding ↔ analysisCode/Cross_area_CCA.m, the whole file · a weak match · score 0.78 · fold cross validation, shuffling controls, population activity, repetitions, gaze events, trained
- [6] § Methods › Neural data analysis › Population decoding analyses › Cross-conditions decoding ↔ analysisCode/Cross_primitive_decoding.py, lines 1–64 · score 0.76 · cross primitives decoding, fold cross validation, neural representation, social gaze primitives, abstract, classifiers
- [7] § Results › Linear mixed selectivity neurons facilitate the generalization of social gaze primitives ↔ codes_for_figures1-5.py, lines 530–587 · score 0.75 · nonlinear mixed selectivity, pure content selective, pure state selective, error bars, neuron, BLA
- [8] § Methods › Behavioral data analysis › General linear mixed-effects modeling of M2’s social gaze ↔ analysisCode/GLMM.R, lines 44–116 · score 0.75 · lme4, M1 duration, M1 content, M1 state, binomial, logit
- [9] § Results › Linear mixed selectivity neurons facilitate the generalization of social gaze primitives ↔ codes_for_figures1-5.py, lines 530–587 · score 0.73 · nonlinear mixed selectivity, pure content selectivity, pure state selectivity, neuron, ACCg, BLA
- [10] § Methods › Behavioral data analysis › Control analyses for dominance hierarchy › Dominance as an additional predictor in the GLMM ↔ analysisCode/GLMM.R, lines 44–116 · score 0.61 · lme4, glmer, binomial, logit, GLMM, day
- [11] § Results › Combinations of social gaze primitives determine interactive social gaze behavior ↔ codes_for_supplementary_figuresS2-S16.py, lines 402–439 · score 0.58 · log odds, error bars, confidence intervals, Vertical, GLMM, positions
- [12] § Results › Combinations of social gaze primitives determine interactive social gaze behavior ↔ codes_for_figures1-5.py, lines 94–146 · score 0.57 · log odds, Predicted probabilities, M1 content, GLMM, square, bars
- [13] § Results › Combinations of social gaze primitives determine interactive social gaze behavior ↔ codes_for_figures1-5.py, lines 188–237 · score 0.57 · Predicted probabilities, M1 duration, M1 state, social gaze, Interaction, M2
- [14] § Methods › Neural data analysis › Population decoding analyses › Cross-primitives decoding ↔ analysisCode/Cross_primitive_decoding.py, lines 112–137 · score 0.56 · cross primitives decoding, fold, accuracy, classifier, trained, shuffled
- [15] § Results › Linear mixed selectivity neurons facilitate the generalization of social gaze primitives ↔ codes_for_supplementary_figuresS2-S16.py, lines 544–583 · score 0.55 · variance inflation, S9, VIF, collinearity, threshold, predictors
- [16] § Results › Combinations of social gaze primitives determine interactive social gaze behavior ↔ codes_for_supplementary_figuresS2-S16.py, lines 119–159 · score 0.54 · transformed correlation, S2, Fisher, pupil, median, bouts
- [17] § Methods › Neural data analysis › Population PSTHs recoded by state or content preference ↔ codes_for_supplementary_figuresS2-S16.py, lines 742–776 · score 0.52 · Population PSTHs, gaze onset, Firing rates, 200 ms
- [18] § Methods › Behavioral data analysis › Control analyses for dominance hierarchy › Dominance as an additional predictor in the GLMM ↔ codes_for_supplementary_figuresS2-S16.py, lines 402–439 · score 0.51 · log odds, confidence intervals, Dominance, GLMM
Paper
Loaded from Europe PMC by your browser, not stored by OSCR: doi.org · Europe PMC
The paper is loaded when this pane is shown.
The authors' code
Python · 1,220 lines · 42 KB · no license · 5 matches
- #%% import libs
- import copy
- import matplotlib.pyplot as plt
- import numpy as np
- import pandas as pd
- import seaborn as sns
- import scipy.stats as stats
- import pickle as pkl
- import matplotlib.colors as mcolors
- import matplotlib.collections as mcoll
- import matplotlib.cm as cm
- from scipy.stats import chi2
- #%% --------- figure S2 ---------
- #%% import figure S2 data
- dataS2 = pkl.load(open('figure_S2_data.pkl', 'rb'))
- sociFracMartMiniBlocResh = dataS2['sociFracMartMiniBlocResh']
- pupiMartMiniBlocResh = dataS2['pupiMartMiniBlocResh']
- pearColl_trans = dataS2['pearColl_trans']
- sociFracMartMiniBloc = dataS2['sociFracMartMiniBloc']
- pupiMartMiniBloc = dataS2['pupiMartMiniBloc']
- #%% plot figure S2A
- inpuData = copy.deepcopy(sociFracMartMiniBlocResh)
- with plt.style.context('style_paper.mplstyle'):
- # sns.set(style = "ticks")
- f, ax1 = plt.subplots(ncols=1, nrows=1, sharey=True,figsize=[3.54/1.5,3.54/2])
- g1 = sns.heatmap(
- inpuData,
- yticklabels = [i for i in range(1,inpuData.shape[0]+1)],
- cmap = 'viridis',
- # square = True,
- # linewidths=0.2,
- ax = ax1)
- ax1.set_yticks([1,11,21,31,41],[1,11,21,31,41])
- ax1.set_xticks([1.5,4.5,7.5,10.5,13.5,16.5,19.5,22.5],[1,2,3,4,5,6,7,8])
- plt.xlabel('Run')
- plt.ylabel('Session')
- plt.tight_layout()
- fileName = 'figS2A_social_bouts_fraction.pdf'
- # plt.savefig(fileName,dpi = 600)
- plt.show()
- #%% plot figure S2B
- inpuData = copy.deepcopy(pupiMartMiniBlocResh)
- with plt.style.context('style_paper.mplstyle'):
- # sns.set(style = "ticks")
- f, ax1 = plt.subplots(ncols=1, nrows=1, sharey=True,figsize=[3.54/1.5,3.54/2])
- g1 = sns.heatmap(
- inpuData,
- # xticklabels = [i for i in range(1,9)],
- yticklabels = [i for i in range(1,inpuData.shape[0]+1)],
- # yticklabels = [i for i in range(1,inpuData.shape[0]+1)],
- # cbar=False,
- # cmap = 'viridis',
- # square = True,
- # linewidths=0.2,
- ax = ax1)
- ax1.set_yticks([1,11,21,31,41],[1,11,21,31,41])
- ax1.set_xticks([1.5,4.5,7.5,10.5,13.5,16.5,19.5,22.5],[1,2,3,4,5,6,7,8])
- # ax1.set_yticks([,11,21,31,41],[1,11,21,31,41])
- # ax1.set_yticks([1,6,11],[1,6,11])
- plt.xlabel('Block')
- plt.ylabel('Session')
- # ax1.set_xticks([])
- # ax1.set_yticklabels(['1','0.5','0','-0.5'],rotation = 0)
- # plt.title('')
- plt.tight_layout()
- # fileName = 'blocLabelMatr_all_group.pdf'
- fileName = 'figS2B_blocLabelMatr_all_pupil.pdf'
- # plt.savefig(fileName,dpi = 600)
- plt.show()
- print(stats.ttest_1samp(pearColl_trans, 0))
- #%% plot figure S2C
- all_stateIndex = []
- all_pupilIndex = []
- with plt.style.context('style_paper.mplstyle'):
- plt.figure(figsize=(3.54/1.5, 3.54/2))
- for i in range(42):
- stateIndex = sociFracMartMiniBloc[i, :, :].flatten()
- pupilIndex = pupiMartMiniBloc[i, :, :].flatten()
- # Convert to DataFrame for seaborn plotting
- df_i = pd.DataFrame({'StateIndex': stateIndex, 'PupilIndex': pupilIndex})
- # Plot the linear regression line for each day (index i)
- sns.regplot(x='StateIndex', y='PupilIndex', data=df_i, scatter=False, ci=False,
- scatter_kws={'s': 5,
- 'alpha':.5,
- "edgecolor": "none",
- "color": "black"},
- line_kws={'color': '#1f77b4',
- 'lw':1,
- 'alpha': 0.75}, ax=plt.gca())
- # plt.title('Linear Regression Lines for Each Day (42 Lines)')
- plt.xlabel('Social bouts fraction')
- plt.ylabel('Pupil size\n(normalized)')
- plt.tight_layout()
- fileName = 'figS2C_linear_regression_social_state_pupil.pdf'
- # plt.savefig(fileName,dpi = 600)
- plt.show()
- #%% plot figure S2D
- with plt.style.context('style_paper.mplstyle'):
- plt.figure(figsize=(3.54/1.5, 3.54/2))
- # Histogram of Fisher Z transformed correlations
- # plt.figure(figsize=(3.54/2, 3.54/3))
- plt.hist(pearColl_trans, bins=10, edgecolor='black', alpha=0.7, color = '#1f77b4')
- # Calculate the mean of the Fisher Z-transformed correlations
- mean_z = np.mean(pearColl_trans)
- # Plot the red line for the mean
- plt.axvline(mean_z, color='red', linestyle='dashed', linewidth=1)
- # Add annotation for the mean
- plt.annotate(f'Mean = {mean_z:.4f}', xy=(mean_z, 5), xytext=(mean_z + 0.01, 9),
- fontsize=8, color='red')
- # plt.title('Histogram of Fisher Z-transformed Pearson Correlations')
- # plt.xlabel('Fisher Z-transformed Correlation')
- # plt.ylabel('Frequency')
- # plt.show()
- # plt.title('Histogram of Fisher Z-transformed Pearson Correlations')
- plt.xlabel('Correlation\n(Fisher Z-transformed)')
- plt.ylabel('Frequency')
- # plt.xlabel('Social bouts fraction')
- # plt.ylabel('Pupil size\n(normalized)')
- plt.tight_layout()
- fileName = 'figS2D_Fisher Z-transformed_corr_social_state_pupil.pdf'
- # plt.savefig(fileName,dpi = 600)
- plt.show()
- #%% --------- figure S3 ---------
- #%% import figure S3 data
- dataS3 = pkl.load(open('figure_S3_data.pkl', 'rb'))
- duraDisColl = dataS3['duraDisColl']
- faceDisColl = dataS3['faceDisColl']
- #%% plot duration distribution
- # Set up figure with shared axes
- with plt.style.context('style_paper.mplstyle'):
- fig, axes = plt.subplots(7, 6, figsize=(8, 6),)
- axes = axes.flatten()
- for i in range(42):
- session_data = np.array(duraDisColl[i])
- median = np.median(session_data)
- # Bin edges and centers
- bins = np.histogram_bin_edges(session_data, bins=25)
- bin_centers = 0.5 * (bins[1:] + bins[:-1])
- bin_width = bins[1] - bins[0]
- half_width = bin_width * 0.5
- # Count values by group
- short_counts = np.zeros(len(bins) - 1)
- long_counts = np.zeros(len(bins) - 1)
- bin_indices = np.digitize(session_data, bins) - 1
- for val, idx in zip(session_data, bin_indices):
- if 0 <= idx < len(short_counts):
- if val < median:
- short_counts[idx] += 1
- else:
- long_counts[idx] += 1
- # Plot side-by-side bars
- axes[i].bar(bin_centers - half_width * 0.5, short_counts,
- width=half_width, color='white', edgecolor='gray', label='Short (< median)')
- axes[i].bar(bin_centers + half_width * 0.5, long_counts,
- width=half_width, color='black', edgecolor='black', label='Long (≥ median)')
- axes[i].set_title(f'#{i+1}', fontsize=8)
- # Add legend and axis labels only to first subplot
- if i == 0:
- axes[i].legend(fontsize=6, loc='upper right')
- # Set common labels
- fig.text(0.5, 0, 'Gaze duration (s)', ha='center', fontsize=10)
- fig.text(0.0, 0.5, 'Gaze bouts number', va='center', rotation='vertical', fontsize=10)
- plt.tight_layout(rect=[0.06, 0.04, 1, 1])
- plt.tight_layout()
- fileName = 'figS3A_gazeDuraDistribu.pdf'
- # plt.savefig(fileName,dpi = 600)
- plt.show()
- # plt.show()
- #%% plot distribution of gaze content
- faceDisColl_face = [faceDisColl[i][0] for i in range(42)]
- faceDisColl_object = [faceDisColl[i][1] for i in range(42)]
- with plt.style.context('style_paper.mplstyle'):
- fig, axes = plt.subplots(1, 2, figsize=(4, 3),)
- axes = axes.flatten()
- plt.subplot(121)
- plt.hist(faceDisColl_face,color = '#E97F26')
- plt.ylabel('Sessions')
- plt.xlabel('Face gaze numbers')
- plt.subplot(122)
- plt.hist(faceDisColl_object,color = '#6BBA44')
- plt.xlabel('Object gaze numbers')
- # plt.
- fileName = 'figS3B_gazeContentDistribu.pdf'
- # plt.savefig(fileName,dpi = 600)
- plt.show()
- #%% --------- figure S4 ---------
- #%% import figure S4 data
- dataS4 = pkl.load(open('figure_S4_data.pkl', 'rb'))
- lrt_vs_full = dataS4['lrt_vs_full']
- delta_aic_vs_full = dataS4['delta_aic_vs_full']
- #%% plot figure S4A
- # LRT results vs full model
- # lrt_vs_full = pd.DataFrame({
- # "Removed_Primitive": ["State", "Content", "Duration"],
- # "Delta_2LL": [16.080, 58.362, 16.283],
- # "df": [4, 4, 4],
- # "p_value": [2.913e-03, 6.406e-12, 2.662e-03]
- # })
- # # ΔAIC vs full model
- # delta_aic_vs_full = pd.DataFrame({
- # "Removed_Primitive": ["State", "Content", "Duration"],
- # "DeltaAIC": [8.080167, 50.362017, 8.282597]
- # })
- with plt.style.context('style_paper.mplstyle'):
- fig, ax = plt.subplots(figsize=(4, 5))
- bars = ax.bar(
- lrt_vs_full["Removed_Primitive"],
- lrt_vs_full["Delta_2LL"],
- color="lightgray"
- )
- # Text annotations
- for i, row in lrt_vs_full.iterrows():
- ax.text(
- i,
- row["Delta_2LL"] + 1,
- f"df={row['df']}\nP={row['p_value']:.3g}",
- ha="center",
- va="bottom",
- fontsize=10
- )
- # Chi-square critical line (df = 4, alpha = 0.05)
- crit_df4 = chi2.ppf(0.95, df=4)
- ax.axhline(
- crit_df4,
- linestyle="--",
- alpha=0.6,
- color='gray'
- )
- ax.set_ylabel(r"$\Delta$ -2 log L (relative to full model)", fontsize=20)
- ax.set_xlabel("Primitive removed", fontsize=20)
- ax.tick_params(labelsize=18)
- plt.tight_layout()
- # plt.savefig("figS4A_Delta_2LL_primitives_remove.pdf", dpi=600)
- plt.show()
- # plt.close()
- #%% plot ΔAIC vs full model
- with plt.style.context('style_paper.mplstyle'):
- fig, ax = plt.subplots(figsize=(4, 5))
- # ax.axhline(2, linestyle="--", alpha=0.6, color='k')
- # ax.axhline(6, linestyle=":", alpha=0.6, color='k')
- ax.bar(
- delta_aic_vs_full["Removed_Primitive"],
- delta_aic_vs_full["DeltaAIC"],
- color="steelblue",alpha=0.8
- )
- # AIC rule-of-thumb thresholds
- ax.set_ylabel(r"$\Delta$ AIC (relative to full model)", fontsize=20)
- ax.set_xlabel("Primitive removed", fontsize=20)
- ax.tick_params(labelsize=18)
- plt.tight_layout()
- # plt.savefig("figS4B_Delta_AIC_primitives_remove.pdf", dpi=600)
- plt.show()
- # plt.close()
- #%% --------- figure S5 ---------
- #%% import figure S5 data
- dataS5 = pkl.load(open('figure_S5_data.pkl', 'rb'))
- coefs_pub = dataS5['coefs_pub']
- plot_state_df = dataS5['plot_state_df']
- #%% plot figure S5A
- # Sort predictors for better visualization
- coefs_pub_sorted = coefs_pub.sort_values("Estimate (log-odds)")
- with plt.style.context('style_paper.mplstyle'):
- fig, ax = plt.subplots(figsize=(5, 2))
- ax.errorbar(
- coefs_pub_sorted["Estimate (log-odds)"],
- coefs_pub_sorted["Predictor"],
- xerr=[
- coefs_pub_sorted["Estimate (log-odds)"] - coefs_pub_sorted["95% CI (Lower)"],
- coefs_pub_sorted["95% CI (Upper)"] - coefs_pub_sorted["Estimate (log-odds)"]
- ],
- fmt='.',
- color='#1f77b4', # consistent scientific blue
- ecolor='gray',
- capsize=0
- )
- ax.axvline(0, color='black', linestyle='--', linewidth=0.8)
- ax.set_xlabel("Estimate (log odds)", fontsize=9)
- ax.set_ylabel("Predictor",)
- ax.tick_params(axis='both')
- plt.tight_layout()
- fileName = 'figS5A_GLMM_Fixed_Effects_Social_State.pdf'
- # plt.savefig(fileName,dpi = 600)
- plt.show()
- #%% figS5B Predicted Probability for M1_state (Low vs. High)
- # Create bar plot
- with plt.style.context('style_paper.mplstyle'):
- fig, ax = plt.subplots(figsize=(1.75, 2))
- ax.bar(plot_state_df['M1_state'], plot_state_df['prob'],
- yerr=[plot_state_df['prob'] - plot_state_df['asymp.LCL'],
- plot_state_df['asymp.UCL'] - plot_state_df['prob']],
- capsize=0, color=['lightgray', 'orchid'], edgecolor='black')
- ax.set_title("Main effect: M1 state", fontsize=10)
- ax.set_ylabel("Predicted probability\n of M2 high social state")
- ax.set_xlabel("M1 state")
- ax.set_ylim(0, 0.8)
- # plt.grid(axis='y', linestyle='--', alpha=0.7)
- plt.tight_layout()
- fileName = 'figS5B_Predicted_Probability_of_M2_Social_State_by_M1_State.pdf'
- # plt.savefig(fileName,dpi = 600)
- plt.show()
- #%% --------- figure S6 ---------
- #%% import figure S6 data
- figure_S6_data = pkl.load(open('figure_S6_data.pkl', 'rb'))
- coefs_fixed = figure_S6_data['coefs_fixed']
- coefs_random = figure_S6_data['coefs_random']
- #%%
- # coefs_fixed = pd.DataFrame({
- # "term": [
- # "Intercept",
- # "M1_state1",
- # "M1_content1",
- # "M1_duration1",
- # "dominant1",
- # "M1_state1 × M1_content1",
- # "M1_state1 × M1_duration1",
- # "M1_content1 × M1_duration1",
- # "M1_state1 × dominant1",
- # "M1_content1 × dominant1",
- # "M1_duration1 × dominant1",
- # "M1_state1 × M1_content1 × M1_duration1",
- # "M1_state1 × M1_content1 × dominant1",
- # "M1_state1 × M1_duration1 × dominant1",
- # "M1_content1 × M1_duration1 × dominant1",
- # "M1_state1 × M1_content1 × M1_duration1 × dominant1"
- # ],
- # "estimate": [
- # -1.96, 0.388, 0.659, -0.0376, -0.158,
- # -0.369, 0.196, -0.108, -0.0488, -0.226,
- # 0.234, -0.170, 0.180, -0.388, -0.162, 0.175
- # ],
- # "conf.low": [
- # -2.56, -0.00504, 0.408, -0.380, -0.985,
- # -0.791, -0.388, -0.489, -0.535, -0.565,
- # -0.187, -0.793, -0.361, -1.11, -0.659, -0.621
- # ],
- # "conf.high": [
- # -1.35, 0.782, 0.910, 0.305, 0.670,
- # 0.0521, 0.779, 0.273, 0.438, 0.113,
- # 0.656, 0.454, 0.720, 0.331, 0.336, 0.972
- # ]
- # })
- #%%
- coefs_fixed = coefs_fixed.sort_values("estimate")
- y_pos = range(len(coefs_fixed))
- #%%
- with plt.style.context('style_paper.mplstyle'):
- plt.figure(figsize=(6, 4))
- # error bars
- plt.hlines(
- y=y_pos,
- xmin=coefs_fixed["conf.low"],
- xmax=coefs_fixed["conf.high"],
- color="gray",
- linewidth=1
- )
- # points
- plt.scatter(
- coefs_fixed["estimate"],
- y_pos,
- color="blue",
- s=120
- )
- # vertical zero line
- plt.axvline(0, linestyle="--", color="black", linewidth=0.8)
- # axes
- plt.yticks(y_pos, coefs_fixed["term"])
- plt.xlabel("Estimate (Log Odds)")
- plt.title("GLMM Fixed Effects with 95% Confidence Intervals")
- plt.grid(axis="x", alpha=0.3)
- plt.grid(axis="y", visible=False)
- plt.tight_layout()
- plt.savefig("figS6A_GLMM_fixed_effects_with_fixed_dominant.pdf", format="pdf", dpi=600)
- plt.show()
- # plt.close()
- #%% plot figure S6B
- # coefs_random = pd.DataFrame({
- # "term": [
- # "Intercept",
- # "M1_state1",
- # "M1_content1",
- # "M1_duration1",
- # "M1_state1 × M1_content1",
- # "M1_state1 × M1_duration1",
- # "M1_content1 × M1_duration1",
- # "M1_state1 × M1_content1 × M1_duration1"
- # ],
- # "estimate": [
- # -2.02, 0.361, 0.543, 0.122,
- # -0.289, -0.0655, -0.239, 0.00232
- # ],
- # "conf.low": [
- # -2.48, 0.132, 0.378, -0.0765,
- # -0.544, -0.401, -0.475, -0.372
- # ],
- # "conf.high": [
- # -1.57, 0.590, 0.707, 0.320,
- # -0.0330, 0.270, -0.00237, 0.376
- # ]
- # })
- coefs_random = coefs_random.sort_values("estimate")
- y_pos = range(len(coefs_random))
- with plt.style.context('style_paper.mplstyle'):
- plt.figure(figsize=(6, 4))
- plt.hlines(
- y=y_pos,
- xmin=coefs_random["conf.low"],
- xmax=coefs_random["conf.high"],
- color="gray",
- linewidth=1
- )
- plt.scatter(
- coefs_random["estimate"],
- y_pos,
- color="blue",
- s=120
- )
- plt.axvline(0, linestyle="--", color="black", linewidth=0.8)
- plt.yticks(y_pos, coefs_random["term"])
- plt.xlabel("Estimate (Log Odds)")
- plt.title("GLMM Fixed Effects with 95% Confidence Intervals")
- plt.grid(axis="x", alpha=0.3)
- plt.grid(axis="y", visible=False)
- plt.tight_layout()
- # plt.savefig("figS6B_GLMM_fixed_effects_with_random_dominant.pdf", format="pdf", dpi=600)
- plt.show()
- # plt.close()
- #%% --------- figure S7 ---------
- #%% import figure S7 data
- dataS7 = pkl.load(open('figure_S7_data.pkl', 'rb'))
- permTestMeanPartiaRegre = dataS7['permTestMeanPartiaRegre']
- permTestStdPartiaRegre = dataS7['permTestStdPartiaRegre']
- coffMatrPartiaRegre = dataS7['coffMatrPartiaRegre']
- #%% plot figure S7
- hypoLabes = ['Content', 'State', 'Duration']
- areas = ['BLA','ACCg','dmPFC','OFC']
- with plt.style.context('style_paper.mplstyle'):
- fig, ax = plt.subplots(figsize=(3.45*2.35,3.54/1.5))
- widt = 0.2
- colors = sns.color_palette()
- i = 0
- for j in [1,0,2,3]:# range(0,4):
- # i = 0
- plt.bar([1+i*widt,2+i*widt,3+i*widt],coffMatrPartiaRegre[j,[1,0,2],0],width = widt*0.75,label = areas[i],color = colors[j])
- if i==3:
- plt.errorbar([1+i*widt,2+i*widt,3+i*widt],permTestMeanPartiaRegre[j,[1,0,2]], yerr=permTestStdPartiaRegre[j,[1,0,2]]*1,
- lw = 0.5,
- color = 'black',
- linestyle='none',
- label='Shuffled data ± 1 std',capsize=1,)
- else:
- plt.errorbar([1+i*widt,2+i*widt,3+i*widt],permTestMeanPartiaRegre[j,[1,0,2]],
- yerr=permTestStdPartiaRegre[j,[1,0,2]]*1,
- lw = 0.5,
- color = 'black',
- linestyle='none',
- capsize=1)
- i+=1
- plt.xticks([1+1.5*widt,2+1.5*widt,3+1.5*widt],hypoLabes )
- plt.xlabel('Model RDM')
- plt.ylabel('Partial regression coefficient')
- # plt.legend(loc='upper right', bbox_to_anchor=(1, 1.1))
- plt.legend(bbox_to_anchor=(1, 0.8))
- # plt.tight_layout()
- fileName = 'figS7_partRegrRDMShufPost_mini_block_updated.pdf'
- # plt.savefig(fileName,dpi = 600)
- plt.show()
- #%% --------- figure S9 ---------
- #%% import figure S9 data
- dataS9 = pkl.load(open('figure_S9_data.pkl', 'rb'))
- df_vif = dataS9['df_vif']
- #%% --------- plot ----------
- with plt.style.context('style_paper.mplstyle'):
- fig, axes = plt.subplots(
- 1, 1,
- figsize=(6./2/2, 2.6/1.5),
- # gridspec_kw={"width_ratios": [1, 1.2]}
- )
- sns.boxplot(
- data=df_vif,
- x="Predictor",
- y="VIF",
- ax=axes,
- palette=["#4C72B0", "#DD8452"],
- width=0.5,
- flierprops=dict(
- marker='o',
- markersize=2,
- markerfacecolor='gray',
- markeredgecolor='gray',
- alpha=0.6
- )
- )
- # VIF threshold
- axes.axhline(5, ls="--", lw=0.8, color="gray", alpha=0.6)
- axes.set_xlabel("")
- axes.set_ylabel("Variance inflation\nfactor (VIF)")
- axes.set_title("Collinearity")
- axes.set_ylim([0.5, 5.2])
- axes.set_xticks([0,1],['Content','State'])
- plt.tight_layout()
- fileName = 'figS9_pairCorrVIF_pool_neurons.pdf'
- # plt.savefig(fileName,dpi = 600)
- plt.show()
- #%% --------- figure S10 ---------
- #%% import figure S10 data
- dataS10 = pkl.load(open('figure_S10_data.pkl', 'rb'))
- PSTHColl = dataS10['PSTHColl']
- examNeurDataColl = dataS10['examNeurDataColl']
- #%% helper function for plotting mean with shaded error bars
- def plot_mean_with_shade(data, label, color, linestyle='-', alpha=0.3,
- edge_alpha=1.0, edge_lw=0.8, edge_ls='-',timepoints = np.arange(200)):
- mean = np.mean(data, axis=0)
- sem = np.std(data, axis=0) / np.sqrt(data.shape[0])
- lower = mean - sem
- upper = mean + sem
- # Shaded fill
- ax.fill_between(timepoints, lower, upper, color=color, alpha=alpha)
- # Edge lines as dashed or solid lines
- ax.plot(timepoints, upper, color=color, linestyle=edge_ls, linewidth=edge_lw, alpha=edge_alpha)
- ax.plot(timepoints, lower, color=color, linestyle=edge_ls, linewidth=edge_lw, alpha=edge_alpha)
- # Mean line
- ax.plot(timepoints, mean, color=color, linestyle=linestyle, label=label)
- #%% plot example neuron PSTHs (face vs object, high vs low state)
- for i in PSTHColl.keys():
- socialHighActiv = PSTHColl[i]['socialHighActiv']
- socialLowActiv = PSTHColl[i]['socialLowActiv']
- nonSocialHighActiv = PSTHColl[i]['nonSocialHighActiv']
- nonSocialLowActiv = PSTHColl[i]['nonSocialLowActiv']
- with plt.style.context('style_paper.mplstyle'):
- fig, ax = plt.subplots(figsize=[3.54/2, 3.54/2.5])
- timepoints = np.arange(100)
- # Plot all four conditions with edge-highlighted shaded error
- plot_mean_with_shade(socialHighActiv, 'Face High', color='#e97f26', linestyle='-',edge_ls='', alpha=0.8)
- plot_mean_with_shade(socialLowActiv, 'Face Low', color='#E97F26', linestyle='--', alpha=0.2, edge_ls='', edge_alpha=0.15)
- plot_mean_with_shade(nonSocialHighActiv, 'Object High', color='#6bba44', linestyle='-', edge_ls='',alpha=0.8)
- plot_mean_with_shade(nonSocialLowActiv, 'Object Low', color='#6bba44', linestyle='--', alpha=0.2, edge_ls='', edge_alpha=0.15)
- # Axes and ticks
- ax.set_xlabel('Time from gaze onset (s)')
- ax.set_ylabel('Firing rate\n(normalized)')
- plt.xticks([0,50,100,150,200],
- [ -1, -0.5,0,0.5,1]) # Set x-ticks to match
- ax.set_xlim(50, 200)
- plt.tight_layout()
- figureName = f'figS10_PSTH_number_{i}.pdf'
- # plt.savefig(figureName,dpi = 600)
- plt.show()
- plt.close()
- #%% plot example neuron firing rate bar plot (face vs object, high vs low state)
- for i in examNeurDataColl.keys():
- # means = examNeurDataColl[i]['means']
- # sems = examNeurDataColl[i]['sems']
- counts = examNeurDataColl[i]['counts']
- df = examNeurDataColl[i]['df']
- normFiringRates = df['FiringRate'].values
- x_labels = ['Face', 'Object']
- x = np.arange(len(x_labels))
- bar_width = 0.35
- with plt.style.context('style_paper.mplstyle'):
- fig, ax = plt.subplots(
- ncols=1,
- nrows=1,
- figsize=[3.54 / 2, 3.54 / 2.5]
- )
- face_color = '#e97f26'
- object_color = '#6bba44'
- for ii, content in enumerate(x_labels):
- color = face_color if content == 'Face' else object_color
- x_high = x[ii] - bar_width / 1.8
- x_low = x[ii] + bar_width / 1.8
- high_key = (content, 'High state')
- low_key = (content, 'Low state')
- high_vals = df[
- (df['Content'] == content)
- & (df['State'] == 'High state')
- ]['FiringRate'].values
- low_vals = df[
- (df['Content'] == content)
- & (df['State'] == 'Low state')
- ]['FiringRate'].values
- # -------------------------
- # Boxplot as distribution summary
- # -------------------------
- bp = ax.boxplot(
- [high_vals, low_vals],
- positions=[x_high, x_low],
- widths=0.22,
- patch_artist=True,
- showfliers=False,
- medianprops={
- 'color': 'black',
- 'linewidth': 1.0
- },
- boxprops={
- 'linewidth': 1.0
- },
- whiskerprops={
- 'linewidth': 0.8
- },
- capprops={
- 'linewidth': 0.8
- },
- zorder=2
- )
- bp['boxes'][0].set_facecolor(color)
- bp['boxes'][0].set_alpha(0.30)
- bp['boxes'][0].set_edgecolor(color)
- bp['boxes'][1].set_facecolor('white')
- bp['boxes'][1].set_alpha(1.0)
- bp['boxes'][1].set_edgecolor(color)
- bp['boxes'][1].set_linestyle('--')
- for whisker in bp['whiskers']:
- whisker.set_color(color)
- for cap in bp['caps']:
- cap.set_color(color)
- ax.set_xticks(x)
- ax.set_xticklabels(x_labels)
- ax.set_xlabel('Content')
- ax.set_ylabel('Firing rate\n(normalized)')
- # ax.set_ylim(0, 1.12)
- ax.spines['top'].set_visible(False)
- ax.spines['right'].set_visible(False)
- fileName = (
- 'figS10_example_neur'
- + '_inde_'
- + str(i)
- + '_'
- + '_boxplot_update.pdf'
- )
- plt.tight_layout()
- # Uncomment to save
- # plt.savefig(figPath + fileName, dpi=300, bbox_inches='tight')
- plt.show()
- #%% --------- figure S11 ---------
- #%% import figure S11 data
- dataS11 = pkl.load(open('figure_S11_data.pkl', 'rb'))
- psthPreNonPreColl = dataS11['psthPreNonPreColl']
- #%% plot population PSTHs for preferred vs non-preferred conditions, with significant clusters highlighted
- areas =['ACCg','BLA','dmPFC','OFC']
- # =========================================================
- # loop: content & state
- # =========================================================
- bin_size_ms = 10
- time_ms = (np.arange(200) - 100) * bin_size_ms
- time_bins = np.arange(200)
- for primitive in ['content', 'state']:
- for ss in range(4):
- mean_p = psthPreNonPreColl[primitive][areas[ss]]['mean_p']
- sem_p = psthPreNonPreColl[primitive][areas[ss]]['sem_p']
- mean_n = psthPreNonPreColl[primitive][areas[ss]]['mean_n']
- sem_n = psthPreNonPreColl[primitive][areas[ss]]['sem_n']
- sig_clusters = psthPreNonPreColl[primitive][areas[ss]]['sig_clusters']
- # ---------- plot ----------
- with plt.style.context('style_paper.mplstyle'):
- fig, ax = plt.subplots(figsize=(3.2, 2.4))
- ax.plot(time_bins, mean_p, label='Preferred')
- ax.fill_between(time_bins, mean_p-sem_p, mean_p+sem_p, alpha=0.3)
- ax.plot(time_bins, mean_n, label='Non-preferred')
- ax.fill_between(time_bins, mean_n-sem_n, mean_n+sem_n, alpha=0.3)
- for cl in sig_clusters:
- ax.plot([cl[0],cl[-1]],[0.20,0.20],color='k')
- ax.axvline(100, ls='--', lw=0.8, color='gray')
- ax.set_xticks([0, 50, 100, 150, 200])
- ax.set_xticklabels([-1000, -500, 0, 500, 1000])
- ax.set_xlabel('Time from gaze onset (ms)')
- ax.set_ylabel('Firing rate (normalized)')
- ax.set_title(f'{areas[ss]} population PSTH ({primitive})')
- ax.legend(frameon=False)
- plt.tight_layout()
- fileName = f'figure_S11_{areas[ss]} population PSTH ({primitive})'+'.pdf'
- # plt.savefig(fileName,dpi = 600)
- plt.show()
- #%% --------- figure S12 ---------
- #%% import figure S12 data
- dataS12 = pkl.load(open('figure_S12_data.pkl', 'rb'))
- coffMatr= dataS12['coffMatr']
- permTestMean= dataS12['permTestMean']
- permTestStd= dataS12['permTestStd']
- # %% plot
- hypoLabes = [ 'Content','State', 'Duration']
- areas = ['BLA','ACCg','dmPFC','OFC']
- with plt.style.context('style_paper.mplstyle'):
- fig, ax = plt.subplots(figsize=(3.45*2.35,3.54/1.5))
- widt = 0.2
- colors = sns.color_palette()
- i = 0
- # for j in range([0,4)]:
- for j in [1,0,2,3]:
- # i = 0
- plt.bar([1+i*widt,2+i*widt,3+i*widt],coffMatr[j,[1,0,2],0],width = widt*0.75,label = areas[i],color = colors[j])
- if i==3:
- plt.errorbar([1+i*widt,2+i*widt,3+i*widt],permTestMean[j,[1,0,2]], yerr=permTestStd[j,[1,0,2]]*1,
- lw = 0.5,
- color = 'black',
- linestyle='none',
- label='Shuffled data ± 1 std',capsize=1)
- else:
- plt.errorbar([1+i*widt,2+i*widt,3+i*widt],permTestMean[j,[1,0,2]],
- yerr=permTestStd[j,[1,0,2]]*1,
- lw = 0.5,
- color = 'black',
- linestyle='none',
- capsize=1)
- i+=1
- plt.xticks([1+1.5*widt,2+1.5*widt,3+1.5*widt],hypoLabes )
- plt.xlabel('Model RDM')
- plt.ylabel('β estimate')
- plt.legend(bbox_to_anchor=(1, 0.8))
- # plt.tight_layout()
- fileName = 'figS12_encoding_model_remove_non_selective.pdf'
- # plt.savefig(fileName,dpi = 600)
- plt.show()
- #%% --------- figure S13 ---------
- #%% import figure S13 data
- dataS13 = pkl.load(open('figure_S13_data.pkl', 'rb'))
- crossDecodingMatrixACCg = dataS13['crossDecodingMatrixACCg']
- crossDecodingMatrixBLA = dataS13['crossDecodingMatrixBLA']
- crossDecodingMatrixdmPFC = dataS13['crossDecodingMatrixdmPFC']
- crossDecodingMatrixOFC = dataS13['crossDecodingMatrixOFC']
- #%% plot the data
- with plt.style.context("style_paper.mplstyle"):
- fig, ax = plt.subplots(figsize=(3.54/1.25, 3.45/2)) # Adjust aspect ratio for horizontal layout
- height = 0.1 # Bar height instead of width
- sns.heatmap(crossDecodingMatrixBLA,# adjust the matrix you want to plot
- square = True,vmin=0.5, vmax=1,annot=True,fmt=".2f",
- annot_kws={"size": 8},
- cbar_kws={'label': 'Decoding accuracy'})
- plt.xticks([0.5,1.5],['State','Content'])
- plt.yticks([0.5,1.5],['State','Content'])
- plt.xlabel('Testing')
- plt.ylabel('Training')
- # plt.title('BLA')
- plt.tight_layout()
- fileName = 'figS13_BLA_remo_non_sele.pdf'
- # plt.savefig(fileName,dpi = 600)
- plt.show()
- #%% --------- figure S14 ---------
- #%% import figure S14 data
- dataS14 = pkl.load(open('figure_S14_data.pkl', 'rb'))
- areas1 = dataS14['areas1']
- areas2 = dataS14['areas2']
- areas_paris = dataS14['areas_paris']
- inpuDataContentColl = dataS14['inpuDataContentColl']
- inpuDataAnnoContentColl = dataS14['inpuDataAnnoContentColl']
- #%% plot CCA results for content
- # Define significance annotation
- def significance_marker(val):
- if val < 0.001:
- return "***"
- elif val < 0.01:
- return "**"
- elif val < 0.05:
- return "*"
- else:
- return ""
- areas = ['ACCg','BLA','dmPFC','OFC']
- areas1 = ['ACCg','ACCg','ACCg','BLA', 'BLA', 'dmPFC']
- areas2 = ['BLA','dmPFC','OFC','dmPFC', 'OFC', 'OFC']
- areas_paris = ['ACCg_BLA','ACCg_dmPFC', 'ACCg_OFC','BLA_dmPFC','BLA_OFC', 'dmPFC_OFC']
- for i in range(6):
- inpuDataContent = copy.deepcopy(inpuDataContentColl[areas_paris[i]])
- inpuDataAnnoContent = copy.deepcopy(inpuDataAnnoContentColl[areas_paris[i]])
- with plt.style.context('style_paper.mplstyle'):
- # sns.set(style = "ticks")
- f, ax1 = plt.subplots(ncols=1, nrows=1, sharey=True,figsize=[3.54/1.5,3.54/2])
- g1 = sns.heatmap(
- inpuDataContent[1:4,1:4],
- annot=inpuDataAnnoContent[1:4,1:4], fmt="",
- # cbar=False,
- cmap = 'viridis',
- square = True,
- linewidths=0.2,
- vmin=0, vmax=0.5,
- ax = ax1)
- ax1.set_yticklabels(['-0.2','0','0.2'],rotation = 0)
- ax1.set_xticklabels(['-0.2','0','0.2'],rotation = 0)
- # ax1.set_yticklabels(['-0.4','-0.2','0','0.2','0.4'],rotation = 0)
- # ax1.set_xticklabels(['-0.4','-0.2','0','0.2','0.4'],rotation = 0)
- ax1.set_xlabel(areas2[i]+' time (s)')
- ax1.set_ylabel(areas1[i] +' time (s)')
- # ax1.set_yticklabels(['1','0.5','0','-0.5'],rotation = 0)
- # plt.title('')
- # plt.title([are,'State'])
- plt.tight_layout()
- fileName = 'figS14_CCA'+'content_'+areas1[i]+'_'+areas2[i]+'.pdf'
- # plt.savefig(fileName,dpi = 600)
- plt.show()
- #%% --------- figure S15 ---------
- #%% import figure S15 data
- dataS15 = pkl.load(open('figure_S15_data.pkl', 'rb'))
- areas1 = dataS15['areas1']
- areas2 = dataS15['areas2']
- areas_paris = dataS15['areas_paris']
- inpuDataStateColl = dataS15['inpuDataStateColl']
- inpuDataAnnoStateColl = dataS15['inpuDataAnnoStateColl']
- #%% plot CCA results for state, with significance annotation
- # Define significance annotation
- def significance_marker(val):
- if val < 0.001:
- return "***"
- elif val < 0.01:
- return "**"
- elif val < 0.05:
- return "*"
- else:
- return ""
- areas = ['ACCg','BLA','dmPFC','OFC']
- areas1 = ['ACCg','ACCg','ACCg','BLA', 'BLA', 'dmPFC']
- areas2 = ['BLA','dmPFC','OFC','dmPFC', 'OFC', 'OFC']
- areas_paris = ['ACCg_BLA','ACCg_dmPFC', 'ACCg_OFC','BLA_dmPFC','BLA_OFC', 'dmPFC_OFC']
- for i in range(6):
- inpuDataState = copy.deepcopy(inpuDataStateColl[areas_paris[i]])
- inpuDataAnnoState = copy.deepcopy(inpuDataAnnoStateColl[areas_paris[i]])
- with plt.style.context('style_paper.mplstyle'):
- # sns.set(style = "ticks")
- f, ax1 = plt.subplots(ncols=1, nrows=1, sharey=True,figsize=[3.54/1.5,3.54/2])
- g1 = sns.heatmap(
- inpuDataState[1:4,1:4],
- annot=inpuDataAnnoState[1:4,1:4], fmt="",
- # cbar=False,
- cmap = 'viridis',
- square = True,
- linewidths=0.2,
- vmin=0, vmax=0.5,
- ax = ax1)
- ax1.set_yticklabels(['-0.2','0','0.2'],rotation = 0)
- ax1.set_xticklabels(['-0.2','0','0.2'],rotation = 0)
- # ax1.set_yticklabels(['-0.4','-0.2','0','0.2','0.4'],rotation = 0)
- # ax1.set_xticklabels(['-0.4','-0.2','0','0.2','0.4'],rotation = 0)
- ax1.set_xlabel(areas2[i]+' time (s)')
- ax1.set_ylabel(areas1[i] +' time (s)')
- # ax1.set_yticklabels(['1','0.5','0','-0.5'],rotation = 0)
- # plt.title('')
- # plt.title([are,'State'])
- plt.tight_layout()
- fileName = 'figS15_CCA'+'state_'+areas1[i]+'_'+areas2[i]+'.pdf'
- # plt.savefig(fileName,dpi = 600)
- plt.show()
- #%% --------- figure S16 ---------
- #%% import figure S16 data
- figure_S16A_data = pkl.load(open('figure_S16A_data.pkl','rb'))
- edges_content_pre = figure_S16A_data['edges_content_pre']
- edges_content_fixation = figure_S16A_data['edges_content_fixation']
- edges_content_post = figure_S16A_data['edges_content_post']
- edges_state_pre = figure_S16A_data['edges_state_pre']
- edges_state_fixation = figure_S16A_data['edges_state_fixation']
- edges_state_post = figure_S16A_data['edges_state_post']
- figure_S16B_data = pkl.load(open('figure_S16B_data.pkl','rb'))
- content_directionality_index_mean = figure_S16B_data['content_directionality_index_mean']
- content_directionality_index_SEMs = figure_S16B_data['content_directionality_index_SEMs']
- state_directionality_index_mean = figure_S16B_data['state_directionality_index_mean']
- state_directionality_index_SEMs = figure_S16B_data['state_directionality_index_SEMs']
- # Define 4 nodes (fixed positions)
- node_labels = ["OFC", "dmPFC", "ACCg", "BLA"]
- positions = {
- "OFC": (0, 0),
- "dmPFC": (1, 1),
- "ACCg": (2, 0),
- "BLA": (1, -1)
- }
- # Assign unique colors to each node
- node_colors = {
- "OFC": "#FF7F00", # Red
- "dmPFC": "#099D84", # Blue
- "ACCg": "#CA2521", # Green
- "BLA": "#456ACF" # Purple
- }
- # Define edges with significance values
- edges = [
- ("OFC", "dmPFC", 0.8), # Higher significance
- ("dmPFC", "ACCg", 0.3), # Lower significance
- ("ACCg", "BLA", 0.5),
- ("BLA", "OFC", 0.9), # Most significant
- ("OFC", "ACCg", 0.6),
- ("dmPFC", "BLA", 0.1)
- ]
- # Convert edges to coordinate pairs
- edge_coords = [([positions[start], positions[end]], significance) for start, end, significance in edges_content_post]# Using edges_content_post as example
- # Normalize significance values for color and width
- vmin, vmax = 0, 0.5 # Set fixed colorbar range
- norm = mcolors.Normalize(vmin=vmin, vmax=vmax)
- cmap = plt.cm.Greys # Grayscale color map
- # Prepare edge segments and styles
- segments = []
- colors = []
- widths = []
- min_width, max_width = 1, 10 # Min and max thickness
- for (segment, sig) in edge_coords:
- segments.append(segment)
- colors.append(cmap(norm(sig))) # Map significance to color
- widths.append(min_width + (max_width - min_width) * norm(sig)) # Scale width
- # Plot with custom style
- with plt.style.context('style_paper.mplstyle'):
- fig, ax = plt.subplots(figsize=(3.54/1.5,3.54/1.2))
- ax.set_aspect('equal')
- # Draw edges with gradient and significance scaling
- lc = mcoll.LineCollection(segments, colors=colors, linewidths=widths)
- ax.add_collection(lc)
- # Draw nodes with individual colors and black edges
- node_size = 4000 # Adjusted for better proportion
- for label, (x, y) in positions.items():
- ax.scatter(x, y, color=node_colors[label], s=node_size, edgecolors='white', linewidth=1, zorder=3)
- ax.text(x, y, label, fontsize=8, ha='center', va='center', color='black', fontweight='bold')
- # Add colorbar for edge significance with fixed range
- sm = cm.ScalarMappable(cmap=cmap, norm=norm)
- sm.set_array([]) # Required for colorbar
- cbar = plt.colorbar(sm, ax=ax,orientation="horizontal")
- cbar.set_label("Cross Validated CC rhos")
- # Set fixed colorbar range
- sm.norm.vmin = vmin
- sm.norm.vmax = vmax
- ax.set_xlim(-0.5, 2.5)
- ax.set_ylim(-1.5, 1.5)
- # Remove all axes
- ax.set_xticks([])
- ax.set_yticks([])
- ax.axis("off") # Completely removes axis lines, labels, and ticks
- plt.tight_layout()
- fileName = 'figS16A_'+'CCA'+'edges_content_post'+'_func_conn'+'_without_linear_mixed_cells.pdf'
- # plt.savefig(fileName,bbox_inches="tight",dpi = 600)
- plt.show()
- #%% load figure S16B data for state and content directionality index distributions (for box plot)
- dataS16B = pkl.load(open('figure_S16B.pkl', 'rb'))
- directionality_index_Accg_Bla_state = dataS16B['Accg_Bla_state']
- directionality_index_Bla_Dmpfc_state = dataS16B['Bla_Dmpfc_state']
- directionality_index_Bla_Ofc_content = dataS16B['Bla_Ofc_content']
- directionality_index_Accg_Bla_content = dataS16B['Accg_Bla_content']
- #%% plot box plots for directionality index distributions, with alternating background and dual y-axis labels
- with plt.style.context('style_paper.mplstyle'):
- fig, ax = plt.subplots(figsize=(3.54/2, 3.54/2))
- # Y positions
- y_positions = np.array([1, 2]) * 1.5
- # Full distributions
- distributions = [
- np.asarray(directionality_index_Accg_Bla_state).flatten(),
- np.asarray(directionality_index_Bla_Dmpfc_state).flatten(),
- ]
- distributions = [d[~np.isnan(d)] for d in distributions]
- means = [np.nanmean(d) for d in distributions]
- errors = [np.nanstd(d) / np.sqrt(len(d)) for d in distributions]
- # Alternating background
- for i in range(len(y_positions)):
- ax.axhspan(
- y_positions[i] - 0.5,
- y_positions[i] + 0.5,
- color='lightgray' if i % 2 == 0 else 'white',
- alpha=0.3,
- zorder=1,
- )
- # ---- Box plot ----
- bp = ax.boxplot(
- distributions,
- positions=y_positions,
- vert=False,
- widths=0.55,
- patch_artist=True,
- showfliers=False,
- medianprops={'color': 'black', 'linewidth': 1.5},
- boxprops={'linewidth': 0.6, 'edgecolor': 'black'},
- whiskerprops={'linewidth': 0.6, 'color': 'black'},
- capprops={'linewidth': 0.6, 'color': 'black'},
- zorder=3,
- )
- for box in bp['boxes']:
- box.set_facecolor('black')
- box.set_alpha(0.4)
- # ---- Reference line ----
- ax.axvline(
- 0,
- color='black',
- linestyle=':',
- linewidth=0.7,
- alpha=0.6,
- zorder=1.5,
- )
- # ---- Axes ----
- ax.set_xlabel('Directionality Index')
- ax.set_yticks(y_positions)
- ytick_labels_left = ['ACCg → BLA', 'BLA → dmPFC']
- ytick_labels_right = ['BLA → ACCg', 'dmPFC → BLA']
- ax.set_yticklabels(ytick_labels_left)
- ax_right = ax.twinx()
- ax_right.set_yticks(y_positions)
- ax_right.set_yticklabels(ytick_labels_right)
- ax_right.set_ylim(ax.get_ylim())
- ax.xaxis.grid(True, linestyle='--', alpha=0.6)
- ax_right.spines['right'].set_visible(True)
- ax_right.spines['right'].set_color('black')
- ax_right.spines['right'].set_linewidth(1)
- plt.tight_layout()
- fileName = 'figS16B_CCA_Directionality_index_func_conn_state_BLAonly_without_linear_mixed_cells.pdf'
- # plt.savefig(dataPath + fileName, bbox_inches='tight', dpi=600)
- plt.show()
- with plt.style.context('style_paper.mplstyle'):
- fig, ax = plt.subplots(figsize=(3.54/2, 3.54/2))
- # Y positions
- y_positions = np.array([1, 2]) * 1.5
- # Full distributions (1000 iterations each)
- distributions = [
- np.asarray(directionality_index_Bla_Ofc_content).flatten(),
- np.asarray(directionality_index_Accg_Bla_content).flatten(),
- ]
- distributions = [d[~np.isnan(d)] for d in distributions]
- means = [np.nanmean(d) for d in distributions]
- errors = [np.nanstd(d) / np.sqrt(len(d)) for d in distributions]
- # Alternating background
- for i in range(len(y_positions)):
- ax.axhspan(
- y_positions[i] - 0.5, y_positions[i] + 0.5,
- color='lightgray' if i % 2 == 0 else 'white',
- alpha=0.3,
- zorder=1,
- )
- # ---- Box plot ----
- bp = ax.boxplot(
- distributions,
- positions=y_positions,
- vert=False,
- widths=0.55,
- patch_artist=True,
- showfliers=False,
- medianprops={'color': 'black', 'linewidth': 1.5},
- boxprops={'linewidth': 0.6, 'edgecolor': 'black'},
- whiskerprops={'linewidth': 0.6, 'color': 'black'},
- capprops={'linewidth': 0.6, 'color': 'black'},
- zorder=3,
- )
- for box in bp['boxes']:
- box.set_facecolor('black')
- box.set_alpha(0.4)
- # ---- Reference line ----
- ax.axvline(0, color='black', linestyle=':', linewidth=0.7, alpha=0.6, zorder=1.5)
- # ---- Axes ----
- ax.set_xlabel('Directionality Index')
- ax.set_yticks(y_positions)
- ytick_labels_left = ['BLA → OFC', 'ACCg → BLA']
- ytick_labels_right = ['OFC → BLA', 'BLA → ACCg']
- ax.set_yticklabels(ytick_labels_left)
- ax_right = ax.twinx()
- ax_right.set_yticks(y_positions)
- ax_right.set_yticklabels(ytick_labels_right)
- ax_right.set_ylim(ax.get_ylim())
- ax.xaxis.grid(True, linestyle='--', alpha=0.6)
- ax_right.spines['right'].set_visible(True)
- ax_right.spines['right'].set_color('black')
- ax_right.spines['right'].set_linewidth(1)
- plt.tight_layout()
- fileName = 'figS15B_CCA_Directionality_index_func_conn_content_BLAonly_without_linear_mixed_cells.pdf'
- # plt.savefig(dataPath + fileName, bbox_inches='tight', dpi=600)
- plt.show()
- # %%
codes_for_supplementary_figuresS2-S16.py at commit fe69fce, no license · at the source
Overview
- Department of Psychology, Yale University,New Haven, CT USA
- Department of Psychology, University of Turin,Torino, Italy
- The Laboratory of Neural Systems, The Rockefeller University,New York, NY USA
- Department of Neuroscience, Yale University School of Medicine,New Haven, CT USA
- Kavli Institute for Neuroscience, Yale University School of Medicine,New Haven, CT USA
- Wu Tsai Institute, Yale University,New Haven, CT USA
Abstract
The abstract is not reproduced here: the paper's license (CC BY-NC-ND) does not allow it. Read it in the paper, at the publisher or on Europe PMC.
Repositories
Its files are read in the Code ↔ Paper reader above, with 18 matches between paragraphs and lines of code.
changlabneuro/social_gaze_compositionality
fe69fceed216c477d8c8dbd8dab8bee14e1401d2, 6 May 2026Availability: 1 check, the latest on 27 September 2026: the link answers
- 27 September 2026: the link answers
9 files
- analysisCode/
Cross_area_CCA.m , MATLAB, 125 lines, 2 matches - analysisCode/
Cross_primitive_decoding , Python, 169 lines, 3 matches.py - analysisCode/
GLMM.R , R, 116 lines, 2 matches - analysisCode/
generalization_analysis. , Python, 175 linespy - analysisCode/
orthogonality_analysis_b , Python, 204 linesetween_state_content.py - analysisCode/
rsa_core_analysis.py , Python, 164 lines, 2 matches - codes_for_figures1-5.py, Python, 975 lines, 4 matches
- codes_for_supplementary_
figuresS2-S16.py , Python, 1,220 lines, 5 matches - README.md, Text, 22 lines
Zenodo 20061507
Availability: 1 check, the latest on 27 September 2026: the link answers (HTTP 200)
- 27 September 2026: the link answers (HTTP 200)
9 files
- analysisCode/
Cross_area_CCA.m , MATLAB, 125 lines - analysisCode/
Cross_primitive_decoding , Python, 169 lines.py - analysisCode/
GLMM.R , R, 116 lines - analysisCode/
generalization_analysis. , Python, 175 linespy - analysisCode/
orthogonality_analysis_b , Python, 204 linesetween_state_content.py - analysisCode/
rsa_core_analysis.py , Python, 164 lines - codes_for_figures1-5.py, Python, 975 lines
- codes_for_supplementary_
figuresS2-S16.py , Python, 1,220 lines - README.md, Text, 22 lines
qiguangyao/social_gaze_compositionality
fe69fceed216c477d8c8dbd8dab8bee14e1401d2, 6 May 2026Availability: 1 check, the latest on 27 September 2026: the link answers
- 27 September 2026: the link answers
9 files
- analysisCode/
Cross_area_CCA.m , MATLAB, 125 lines - analysisCode/
Cross_primitive_decoding , Python, 169 lines.py - analysisCode/
GLMM.R , R, 116 lines - analysisCode/
generalization_analysis. , Python, 175 linespy - analysisCode/
orthogonality_analysis_b , Python, 204 linesetween_state_content.py - analysisCode/
rsa_core_analysis.py , Python, 164 lines - codes_for_figures1-5.py, Python, 975 lines
- codes_for_supplementary_
figuresS2-S16.py , Python, 1,220 lines - README.md, Text, 22 lines
Code availability statement
The paper has a code availability statement. Its license (CC BY-NC-ND) does not allow reproducing it here; in short, from what the harvester recognized in it:
- it points to the authors' code: changlabneuro/
social_gaze_compositiona lity
Read it in the paper: doi.org/10.1038/s41467-026-74347-8.
Tracing map
Proposed by the machine: these links were found in the paper and verified at the source, without human review. The map will receive a Zenodo DOI once one of the paper's authors has validated it with their ORCID.
What the map holds:
- 3 repositories of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
- 24 scripts, each with its path and the digest of its content;
- 18 matches between paragraphs of the paper and lines of the code (method lexical-v1);
- neither the text of the paper nor the code itself.
Its JSON (tracing-map.json) is deposited on Zenodo with its DOI once the map is validated.
Data
No dataset and no data link were found in the paper.
Code and data availability statement
The paper has a code and data availability statement. Its license (CC BY-NC-ND) does not allow reproducing it here; in short, from what the harvester recognized in it:
- it points to the authors' code: changlabneuro/
social_gaze_compositiona lity
Read it in the paper: doi.org/10.1038/s41467-026-74347-8.
Versions
The history of this record: each version stored by the harvester or made by a correction of its authors or of the maintainers of its code, and what changed in its facts. The texts of the paper (its abstract, its availability statements) are not part of it; versions that changed only those are not listed.
Version 1, 27 September 2026: the first record
Recorded: type, language, journal, volume, issue, pages, dates, 4 authors, 2 keywords, 10 MeSH terms, 1 funder, 73 references.
Cite
This paper
Qi, G., Dal Monte, O., Fan, S., & Chang, S. W. C. (2026). Compositionality of social gaze in the prefrontal-amygdala circuits. Nature communications, 17(1), 7478. https://
BibTeX
@article{qi2026compositi
author = {Qi, Guangyao and Dal Monte, Olga and Fan, Siqi and Chang, Steve W. C.},
title = {{Compositionality of social gaze in the prefrontal-amygdala circuits}},
journal = {Nature communications},
year = {2026},
month = jun,
volume = {17},
number = {1},
pages = {7478},
publisher = {Nature Publishing Group},
issn = {2041-1723},
doi = {10.1038/
url = {https://
pmid = {42285960},
pmcid = {PMC13407908}
}
RIS
TY - JOUR
AU - Qi, Guangyao
AU - Dal Monte, Olga
AU - Fan, Siqi
AU - Chang, Steve W. C.
TI - Compositionality of social gaze in the prefrontal-amygdala circuits
T2 - Nature communications
J2 - Nat Commun
PY - 2026
DA - 2026/
VL - 17
IS - 1
SP - 7478
SN - 2041-1723
PB - Nature Publishing Group
DO - 10.1038/
UR - https://
LA - en
ER -
CSL-JSON
{
"id": "10.1038/
"type": "article-journal",
"title": "Compositionality of social gaze in the prefrontal-amygdala circuits",
"container-title": "Nature communications",
"author": [
{
"family": "Qi",
"given": "Guangyao"
},
{
"family": "Dal Monte",
"given": "Olga"
},
{
"family": "Fan",
"given": "Siqi"
},
{
"family": "Chang",
"given": "Steve W. C."
}
],
"container-title-short":
"volume": "17",
"issue": "1",
"page": "7478",
"DOI": "10.1038/
"PMID": "42285960",
"PMCID": "PMC13407908",
"ISSN": "2041-1723",
"publisher": "Nature Publishing Group",
"URL": "https://
"language": "en",
"issued": {
"date-parts": [
[
2026,
6,
12
]
]
}
}
The tracing map gets a citation of its own once an author has validated it and it has a DOI.
Similar papers
The papers with a page that share the most with this one: the tools found in their code, their categories, datasets, cited references and authors, the rarest counting most.
- [1] doi:10.1038/s41467-026-75220-4 [code]
- Causal Dynamics of Social Gaze in Primate Prefrontal-Amygdala Networks Revealed by Dynamic Bayesian Modeling.Journal: Nature communicationsIn common: statsmodels, scikit-learn, pandas, 3 other tools, non-human primate, systems, 7 references, author Steve W. C. Chang
- [2] doi:10.1038/s41593-026-02333-w [code]
- Learning shapes neural geometry in the primate prefrontal cortex.Journal: Nature neuroscienceIn common: seaborn, scikit-learn, pandas, 3 other tools, non-human primate, 7 references
- [3] doi:10.1162/imag.a.1321 [code]
- Phase similarity between similar objects indicates representational merging across retrieval training but not sleep.Journal: Imaging neuroscience (Cambridge, Mass.)In common: Pingouin, car, broom, 8 other tools
- [4] doi:10.1093/nc/niag029 [code]
- A data-driven approach to identifying and evaluating connectivity-based neural correlates of conscious visual perception.Journal: Neuroscience of consciousnessIn common: Pingouin, car, broom, 8 other tools
- [5] doi:10.34133/csbj.0042 [code]
- Using Steady-State Visual Evoked Potentials to Characterize Wide-Ranging Retinopathy Linked to &
lt;i& gt;CRB1& lt;/ i& gt;: Implications for Clinical Trials. Journal: Computational and structural biotechnology journalIn common: Pingouin, car, emmeans, 8 other tools - [6] doi:10.1038/s41593-026-02228-w [code]
- Circuit response to neuromodulation characterized with simultaneous deep brain stimulation and precision neuroimaging in humans.Journal: Nature neuroscienceIn common: Pingouin, emmeans, lme4, 7 other tools, systems
- [7] doi:10.1016/j.celrep.2026.117505 [code]
- Impaired spatial coding and neuronal hyperactivity in the medial entorhinal cortex of aged APP knock-in mice.Journal: Cell reportsIn common: car, broom, emmeans, 4 other tools, 2 references
- [8] doi:10.1016/j.isci.2026.117492 [code]
- Neural subspace reorganization reflects value-based decision-making.Journal: iScienceIn common: statsmodels, scikit-learn, pandas, 3 other tools, 5 references
- [9] doi:10.1093/bioinformatics/btag592 [code]
- Network-based stratification of allele-specific expression reveals patient subgroups in Huntington's disease.Journal: Bioinformatics (Oxford, England)In common: car, broom, emmeans, 7 other tools
- [10] doi:10.1038/s41597-026-07350-9 [code]
- An open multi-center MEG-EEG dataset for studying conscious visual perception.Journal: Scientific dataIn common: Pingouin, car, emmeans, 7 other tools
Contribute
The authors of this paper can claim it, correct its record and validate its tracing map, and the maintainers of its code (its owner, or a public member of its organization) correct what it says of their repository; anyone signed in can ask for its removal. Every request goes to OSCR's own machine, which answers it; your account page follows them.
Sign in with ORCID to claim this paper as one of its authors, correct its record or validate its tracing map: when the paper's metadata lists your ORCID iD, you are recognized at once. Maintainers of its code: sign in with GitHub, then claim the repository on your account page.
Claim this paper
Correct its record
Say what each link of this record is, remove the ones that are not the paper's, add the ones that are missing. The correction becomes a new version of the record, in its Versions section.
Validate its tracing map
You validate the map as this page shows it: 3 repositories of the authors' code, each at its verified commit and with its license, 24 scripts, and 18 matches between paragraphs and code (see the Code and Map sections). It then receives a DOI on Zenodo, with you (your ORCID iD) and OSCR as its creators; the code itself is not deposited.
The map's fingerprint: sha256:a30329f31320477a…
Add the badge to its README
The badge links the code to this page. Copy one of these into the README of the paper's code: only you decide where it goes, and nothing is changed for you.
Markdown
[, paste the snippet at the top, then “Commit changes…” and, to review it first, “Create a new branch and start a pull request”. You open the pull request; OSCR asks for no permission.
Request its removal
To ask OSCR to remove this record, the copies of its authors' scripts or its tracing map, use the removal request page: signed in, you say who you are, what to remove and why, then review and confirm the request. Published rules decide every request (how).
Discussion, reproductions, activity
Discussion: questions and error reports about this paper and its code, from signed-in readers and its authors. It opens with sign-in.
Reproductions: reports from readers who ran the authors' code: what they reproduced, with which environment, commit and data. It opens with sign-in.
Activity: what happens around this paper: new versions of its record, its map's validation, discussions and reproductions. It opens with sign-in.
