Skip to content

Repository accompanying Regev, Casto et al. (2024) [Neural populations in the language network differ in the size of their temporal receptive windows] Nature Human Behavior

License

Notifications You must be signed in to change notification settings

coltoncasto/ecog_clustering_PUBLIC

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Neural populations in the language network differ in the size of their temporal receptive windows

Here, we provide code that can be used to regenerate the Figures (and Extended Data Figures) from Regev, Casto et al. (2024) using the preprocessed data files provided on OSF. Code that was used for preprocessing the raw signals and identifying language-reponsive electrodes can be found in subdirectories of this repository. However, note that they are not functional as the raw data are not publicly availible. We only provide them for transparency. Please contact Colton (ccasto at mit dot edu) and Tamar (tamarr at mit dot edu) if you have questions or run into issues with the code.

Cite As:

Regev, T. I.+, Casto, C.+, Hosseini, E. A., Adamek, M., Ritaccio, A. L., Willie, J. T., Brunner, P., & Fedorenko, E. (2024). Neural populations in the language network differ in the size of their temporal receptive windows. Nature Human Behavior (in press).
+equal contribution

bioRxiv

Contents

Download output/ Subdirectory

Before running any of the analyses below, download the output/ directory from OSF and place in the repository directory (ecog_clustering_PUBLIC). This is a pre-structured directory for saving output and plots that contains the datafiles needed to re-generate the figures. See Directory Structure below for details.

Directory Structure

The primary functions used for generating the figures can be found in the main directory of this repository. There exist six subdirectories as well:

  • output/ : contains all output and plots, organized by data that were used to generate them (e.g., Dataset 1 vs. Dataset 2). The output directory name is provided as the first argument to all analysis functions, which specifies the data to use to perform the analysis (located in e.g., DIRECTORY_NAME/data). We have provided preprocessed data matrices with metadata for the following analysis output directories:

    • MITSWJNTask_SWJN_kmedoids_correlation_FIGURES : Primary output directory for Dataset 1 (Figures 2-5 and S1-6).
    • MITSWJNTask_SWJN_kmedoids_correlation_STABILITY_FIGURES : Output directory for calculating split-half clustering for Dataset 1 (Figure 3A).
    • MITSWJNTask_SN_kmedoids_correlation_FIGURES : Output directory for Dataset 1 when clustering with only the Sentence and Nonword-list conditions (Figures 6F,I and S7),
    • MITLangloc_SN_8words_kmedoids_correlation_FIGURES : Primary output directory for Dataset 2 (Figures 6A,D-I, S8G, S9, and S10A).
    • MITLangloc_assignedFrom_MITSWJNTask_SN_kmedoids_correlation_FIGURES
    • _reliability : general output directory for calculating split-half reliability across datasets (Figure 1D, 6B-C).
    • _coordinates : output directory with anatomical locations of electrodes in MNI space for both datasets.
    • _templates : output directory with 'template' orderings of clusters (i.e., cluster centers from Dataset 1) which are used to help order the (arbitrarily-ordered) clustering algorithm output.
  • utils/ : helper functions used for analysis and plotting

  • anatomical/ : antomical location of electrodes in MNI space for all participants

  • stimuli/ : S-W-J-N stimuli for Dataset 1, used for calculating n-gram frequencies for Extended Data Figure 5. See OSF for the stimuli from Dataset 2.

  • preprocessing/ : code used for preprocessing the raw signals (non-functional!)

  • firstlevels/ : code for identifying language-responsive electrodes from preprocessed signals (non-functional!)

General Function Inputs

Here we provide a brief description of the generic arguments that are used across many of the functions below.

  • 'saveName' : subdirectory of output/ folder where data will be loaded from and output (plots, matrices, etc.) will be saved.
  • 'experiment' : 'MITSWJNTask' (Dataset 1) or 'MITLangloc' (Dataset 2).
  • 'useWandJ' : True/False; speciefies whether to use either four conditions (S+W+J+N; Figure 2) or only two (S+N; Extended Data Figure 7) for 'MITSWJNTask' (Dataset 1)

Figures

Below we provide a list of commands to regenerate the Figures and Extended Data Figures included in the main text. For those interested, these commands can be easily modified to explore the data further.

Figure 1

Panel C: Anatomical locations of electrodes in Dataset 1.

makeAllAnatomical('MITSWJNTask_SWJN_kmedoids_correlation_FIGURES',...
                  'experiment','MITSWJNTask',...
                  'doBoth',true,...
                  'doLang',true,...
                  'doTRW',false,...
                  'angle',270);

Panel D: Split-half relibility language- vs. non-language-responsive electrodes.

calculateReliability('saveNameAdditional','MITSWJNTask_SWJN_kmedoids_correlation_FIGURES',...
                     'expt1','MITSWJNTask',...
                     'expt2','MITSWJNTask',...
                     'useLangElecs1',true,...
                     'useLangElecs2',false,...
                     'useWandJ',true);

Figure 2

Panels A-F: Dataset 1 k-medoids clustering with k=3.

To generate figures from the existing cluster assignments used in the paper:

runAll('MITSWJNTask_SWJN_kmedoids_correlation_FIGURES',...  
       'experiment','MITSWJNTask',...  
       'useWandJ',true,...  
       'doClustering',false,...  
       'doClusterMean',true,...             % Figure 2E
       'doClusterBarplot',true,...          % Figure 2F 
       'method','kmedoids',...  
       'distance','correlation',...
       'template','SWJN_template_clusters_K=3.mat',...
       'minK',3,...
       'maxK',3,...
       'doAnatomical',true,...              % Figure 5A
       'doDimensionalityReduction',true,... % Figure 2C
       'elecSize',60,...
       'shadeByReliability',true); 

To cluster from scratch: (CAUTION: will overwrite existing clustering/MITSWJNTask_langElecs_cluster_assignments.csv file which contains the assignments used in the paper)

runAll('MITSWJNTask_SWJN_kmedoids_correlation_FIGURES',...  
       'experiment','MITSWJNTask',...  
       'useWandJ',true,...  
       'doClustering',true,... % Figure 2B 
       'doClusterMean',true,...
       'doClusterBarplot',true,...  
       'doElbow',true,...      % Figure 2A    
       'method','kmedoids',...  
       'distance','correlation',...
       'template','SWJN_template_clusters_K=3.mat',...
       'minK',3,...
       'maxK',3,...
       'doAnatomical',true,...
       'doDimensionalityReduction',true,...
       'elecSize',60,...
       'shadeByReliability',true);

Panel A (inset): Elbow method filtering by electrode reliability.

doElbowMultipleTimes('MITSWJNTask_SWJN_kmedoids_correlation_FIGURES',...
                     'experiment','MITSWJNTask',...
                     'useWandJ',true,...
                     'reliabThresh',0:0.1:0.4);

Figure 3

Panel A: Cluster stability across trials

To run clustering on odd or even trials only (note the change in 'saveName'):

clusterData('MITSWJNTask_SWJN_kmedoids_correlation_STABILITY_FIGURES',...
            'experiment','MITSWJNTask',...
            'useWandJ',true,...
            'method','kmedoids',...
            'distance','correlation',...
            'split','even') % or 'odd'

To compare the full clustering solutions to the clustering solution when half the trials are used:

compareClusteringSolutions('MITSWJNTask_SWJN_kmedoids_correlation_FIGURES',...
                           'MITSWJNTask_SWJN_kmedoids_correlation_STABILITY_FIGURES',... 
                           'experiment1','MITSWJNTask',...
                           'useWandJ',true,...
                           'k1',3,'k2',3,...
                           'compareAssignments',false,...
                           'doHeatmap',true,...
                           'doSignificance',true,...
                           'iterations',1000);

Panel B: Cluster robustness to data loss

To run clustering omitting random subsets of electrodes:

validateClusters('MITSWJNTask_SWJN_kmedoids_correlation_FIGURES',...
                 'experiment','MITSWJNTask',...
                 'useWandJ',true,...
                 'omitIterations',100,...
                 'omitChannelsBy',5,...
                 'threshold',0.92);

To additionally run the permutation test for establishing the significance threshold (manually provided to the function above):

validateClustersThreshold('MITSWJNTask_SWJN_kmedoids_correlation_FIGURES',...
                          'experiment','MITSWJNTask',...
                          'useWandJ',true,...
                          'k',3,...
                          'iterations',1000)

Panel C: Degree of locking

channel_locking('MITSWJNTask_SWJN_kmedoids_correlation_FIGURES',...
                'experiment','MITSWJNTask',...
                'useWandJ',true,...
                'k',3,...
                'calcFlag',1)

Panel D-F: Condition decoding

To run decoding for one pair of conditions and for one cluster (in this case, sentences vs. word-lists for Cluster 1) use the functional call below. One can modify the 'decoders' argument to compare other conditions (the form is assumed to be 'cond1cond2': e.g., 'JN') and/or the 'singleK' argument to perform the decoding analysis on other clusters. Note that the permutations will take time to run--it is recommended to run this analysis in batches on a computing cluster if availible.

decodeCondition('MITSWJNTask_SWJN_kmedoids_correlation_FIGURES',...
                'experiment','MITSWJNTask',...
                'doCummulative',true,...  
                'permutations',1000,...  
                'slideBy',100,...  
                'iterations',20,...
                'threshold',0.05,...  
                'singleK',1,...
                'singleDecoder',true,...
                'decoders','SW');

Once the null distributions for all condition comparisons and clusters have been saved, the decoding plots can be generated with the following command (it will only load existing mat files with null distributions):

decodeCondition('MITSWJNTask_SWJN_kmedoids_correlation_FIGURES',...
               'experiment','MITSWJNTask',...
               'decoders','SW',...
               'doPlot',true,...
               'loadData',true);

Figure 4

fitReceptiveWindow('MITSWJNTask_SWJN_kmedoids_correlation_FIGURES',...
                   'experiment','MITSWJNTask',...
                   'useWandJ',true,...
                   'whichKernel','gaussian_wide');

Figure 5

Panels C-E: Violin plots with MNI coordinate values by cluster.

The function below will generate all anatomical violin plots presented in the paper (Figure 5C-E, Extended Data Figure 9C-H). It also evaluates the MNI coordinate values statistically using a linear mixed effects model (LME) (Supplementary Table S2A-D, S3A-D, S4A-D).

Note that the code to generate Figure 6C needs to be run first in order for this part to work

analyzeCoordinates_YZ % NOTE that this function is not general--it will only work for the specified cases, but it can be easily adapted for additional exploration. 

Panel F: Electrode locations colored by TRW

makeAllAnatomical('MITSWJNTask_SWJN_kmedoids_correlation_FIGURES',...
                  'experiment','MITSWJNTask',...
                  'doBoth',false,...
                  'doLang',true,...
                  'doTRW',true,...
                  'angle',270)

Figure 6

Panel E (and Extended Data Figure 7): Clustering Dataset 1 using only the Sentence and Nonword-list conditions

To perform clustering on Dataset 1 using only the Sentence and Nonword-list conditions, use the command below (note the different 'saveName'). To perform the clustering from scratch, change the 'doClustering' argument to true. This command will also generate the output necessary for Extended Data Figure 7.

runAll('MITSWJNTask_SN_kmedoids_correlation_FIGURES',...  
       'experiment','MITSWJNTask',...  
       'useWandJ',false,...               % NOTE
       'doClustering',false,...           % Extended Data Figure 7B
       'doClusterMean',true,...           % Figure 6E / Extended Data Figure 7C
       'doClusterBarplot',true,...        % Extended Data Figure 7D
       'method','kmedoids',...  
       'distance','correlation',...
       'template','SN_template_clusters_K=3.mat',...
       'minK',3,...
       'maxK',3,...
       'doAnatomical',true,...            % Extended Data Figure 7F
       'doDimensionalityReduction',true); % Extended Data Figure 7E

Panels A,D-E,G-H: Clustering Dataset 2

To perform clustering on Dataset 2, run the command below. As above, to perform the clustering from scratch, change the 'doClustering' argument to true.

runAll('MITLangloc_SN_8words_kmedoids_correlation_FIGURES',...  
       'experiment','MITLangloc',...      % NOTE
       'useWandJ',false,...
       'doClustering',false,...           % Figure 6D
       'doClusterMean',true,...           % Figure 6G
       'doClusterBarplot',true,...        % Figure 6H
       'method','kmedoids',...  
       'distance','correlation',...
       'template','SN_template_clusters_K=3.mat',...
       'minK',3,...
       'maxK',3,...
       'doAnatomical',true,...            % Extended Data Figure 9A
       'doGeneralAnatomical',false,...    % Figure 6A
       'angle',[90,180,270],...
       'doDimensionalityReduction',true); % Figure 6E

Panel I: Compare clustering solutions from Dataset 1 and Dataset 2

compareClusteringSolutions('MITSWJNTask_SN_kmedoids_correlation_FIGURES',...
                           'MITLangloc_SN_8words_kmedoids_correlation_STABILITY_FIGURES',... 
                           'experiment1','MITSWJNTask',...
                           'useWandJ',false,...
                           'k1',3,...
                           'k2',3,...
                           'compareAssignments',false,...
                           'doHeatmap',true,...
                           'doSignificance',true,...
                           'iterations',1000);

Panel B: Split-half reliability of Dataset 1 with the Sentence and Nonword-list condition only

calculateReliability('saveNameAdditional','MITSWJNTask_SN_kmedoids_correlation_FIGURES',...
                     'expt1','MITSWJNTask',...
                     'expt2','MITSWJNTask',...
                     'useLangElecs1',true,...
                     'useLangElecs2',false,...
                     'useWandJ',false)

Panel C: Split-half reliability of Dataset 2

calculateReliability('saveNameAdditional','MITLangloc_SN_8words_kmedoids_correlation_FIGURES',...
                     'expt1','MITLangloc',...
                     'expt2','MITLangloc',...
                     'useLangElecs1',true,...
                     'useLangElecs2',false,...
                     'useWandJ',false)

Extended Data Figure 1

plotSubjectCluster('MITSWJNTask_SWJN_kmedoids_correlation_FIGURES',...
                   'experiment','MITSWJNTask',...
                   'useWandJ',true,...
                   'k',3);

Extended Data Figure 2

runAll('MITSWJNTask_SWJN_kmedoids_correlation_FIGURES',...  
       'experiment','MITSWJNTask',...  
       'useWandJ',true,...  
       'doClustering',false,... 
       'doClusterMean',true,...
       'doClusterBarplot',true,...  
       'doElbow',false,... 
       'method','kmedoids',...  
       'distance','correlation',...
       'minK',10,...
       'maxK',10,...
       'doDimensionalityReduction',true);

Extended Data Figure 3

for ik=1:3
    plot_channels_clustDist('MITSWJNTask_SWJN_kmedoids_correlation_FIGURES',...
                            'experiment','MITSWJNTask',...
                            'useWandJ',true,...
                            'k',3,...
                            'whichk',ik,...
                            'distTo','medoids',...
                            'nselChans',100,...
                            'plotsec',15,...
                            'colorby','reliability',...
                            'transparency','none',...
                            'dispText','trw',...
                            'dispSub',true);
end

Extended Data Figure 4

Panels A-D: Partial correlation histograms and example electrodes.

calculatePartialCorrelation('MITSWJNTask_SWJN_kmedoids_correlation_FIGURES',...
                            'experiment','MITSWJNTask',...
                            'useWandJ',true);

Panel E: Anatomical distribution of partial correlations.

makeAllAnatomical('MITSWJNTask_SWJN_kmedoids_correlation_FIGURES',...
                  'experiment','MITSWJNTask',...
                  'doBoth',false,...
                  'doLang',true,...
                  'doPartialCorrelations',true,...
                  'angle',270)

Extended Data Figure 5

To extract n-gram frequencies for the Sentence and Word-list conditions run processNgrams.m. This script will load existing n-gram frequency tables (saved in stimuli/ngram) and plot them by condition. To see how the n-gram frequencies were calculated in the first place using the Google n-gram corpus, refer to the Jupyter notebook google_ngram_SWstim.ipynb.

Extended Data Figure 6

kernel_shapes = {'cosine','gaussian_wide','gaussian_narrow','square','linear_asym'};
for i=1:length(kernel_shapes)
    fitReceptiveWindow('MITSWJNTask_SWJN_kmedoids_correlation_FIGURES',...
                       'experiment','MITSWJNTask',...
                       'useWandJ',true,...
                       'whichKernel',kernel_shapes{i});
end

Extended Data Figure 7

See output from the runAll function call used to generate Panels B,F of Figure 6.

Panel G: Cluster robustness to data loss for Dataset 1 S and N conditions only

To run clustering omitting random subsets of electrodes:

validateClusters('MITSWJNTask_SN_kmedoids_correlation_FIGURES',...
                 'experiment','MITSWJNTask',...
                 'useWandJ',false,...
                 'omitIterations',100,...
                 'omitChannelsBy',5,...
                 'threshold',0.92);

To additionally run the permutation test for establishing the significance threshold (manually provided to the function above):

validateClustersThreshold('MITSWJNTask_SN_kmedoids_correlation_FIGURES',...
                          'experiment','MITSWJNTask',...
                          'useWandJ',false,...
                          'k',3,...
                          'iterations',1000);

Extended Data Figure 8

Panel A

To assign electrodes from Dataset 2 to the most correlated cluster from Dataset 1, run the following command (or rely on the assignments that were used in the paper in the clustering/MITLangloc_langElecs_cluster_assignments.csv file):

assignCluster('MITLangloc_assignedFrom_MITSWJNTask_SN_kmedoids_correlation_FIGURES',...
              'distance','correlation',...
              'expt1','MITSWJNTask',...
              'expt2','MITLangloc',...
              'k',3);

Panels B-E

Then to generate the rest of the panels, use the runAll command below:

runAll('MITLangloc_assignedFrom_MITSWJNTask_SN_kmedoids_correlation_FIGURES',...  
       'experiment','MITLangloc',...  
       'useWandJ',false,...  
       'doClustering',false,... 
       'doClusterMean',true,...
       'doClusterBarplot',true,...        % Extended Data Figure 8C
       'doElbow',false,... 
       'minK',3,...
       'maxK',3,...
       'doAnatomical',true,...            % Extended Data Figure 8E
       'angle',[90,180,270],...
       'doDimensionalityReduction',true); % Extended Data Figure 8D

Panel F-G Comparing clustering solution (Figure 6) to winner-take-all approach (Extended Data Figure 8)

compareAssignmentsDataset2 % NOTE that this function is not general--it will only work for the specified case, but it can be easily adapted for additional exploration. 

Extended Data Figure 9

See output from runAll command used in Figure 6

To generate the violin plots comparing the MNI coordinate values for Dataset 2, see the output from the analyzeCoordinates_YZ.m function, called for Figure 5C-E.

Extended Data Figure 10

Panels A-B: Estimation of TRW size for cluster assignments for Dataset 2

fitReceptiveWindow('MITLangloc_SN_8words_kmedoids_correlation_FIGURES',...
                   'experiment','MITLangloc',...
                   'useWandJ',false,...
                   'whichKernel','gaussian_wide');

Panels C-D: Estimation of TRW size for winner-take-all group assignments (Extended Data Figure 8) for Dataset 2

fitReceptiveWindow('MITLangloc_assignedFrom_MITSWJNTask_SN_kmedoids_correlation_FIGURES',...
                   'experiment','MITLangloc',...
                   'useWandJ',false,...
                   'whichKernel','gaussian_wide');

Supplementary Table 1

See the output from the channel_locking.m function, called for Figure 3C.

Supplementary Tables 2-4

See the output from the analyzeCoordinates_YZ.m function, called for Figure 5C-E.

Supplementary Tables 5-9

Before running the TRW_lme.m script below, make sure that you have run all of the fitReceptiveWindow.m commands above (Figure 4,Extended Data Figure 10). Additionally, you will need to run the command below to fit receptive windows for Dataset 1 by presentation rate (used for Supplementary Table 6).

fitReceptiveWindowByTime('MITSWJNTask_SWJN_kmedoids_correlation_FIGURES',...
                         'experiment','MITSWJNTask',...
                         'useWandJ',true,...
                         'whichKernel','gaussian_wide');

Then, you can run the command below to statistically evaluate the fitted receptive window sizes by cluster, using a linear mixed effects model (LME):

TRW_lme

About

Repository accompanying Regev, Casto et al. (2024) [Neural populations in the language network differ in the size of their temporal receptive windows] Nature Human Behavior

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published