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.
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
- Download
output/
Subdirectory - Directory Structure
- General Function Inputs
- Figures
- Figure 1
- Figure 2
- Figure 3
- Figure 4
- Figure 5
- Figure 6
- Extended Data Figure 1
- Extended Data Figure 2
- Extended Data Figure 3
- Extended Data Figure 4
- Extended Data Figure 5
- Extended Data Figure 6
- Extended Data Figure 7
- Extended Data Figure 8
- Extended Data Figure 9
- Extended Data Figure 10
- Supplementary Table 1
- Supplementary Tables 2-4
- Supplementary Tables 5-9
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.
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!)
Here we provide a brief description of the generic arguments that are used across many of the functions below.
'saveName'
: subdirectory ofoutput/
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)
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.
makeAllAnatomical('MITSWJNTask_SWJN_kmedoids_correlation_FIGURES',...
'experiment','MITSWJNTask',...
'doBoth',true,...
'doLang',true,...
'doTRW',false,...
'angle',270);
calculateReliability('saveNameAdditional','MITSWJNTask_SWJN_kmedoids_correlation_FIGURES',...
'expt1','MITSWJNTask',...
'expt2','MITSWJNTask',...
'useLangElecs1',true,...
'useLangElecs2',false,...
'useWandJ',true);
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);
doElbowMultipleTimes('MITSWJNTask_SWJN_kmedoids_correlation_FIGURES',...
'experiment','MITSWJNTask',...
'useWandJ',true,...
'reliabThresh',0:0.1:0.4);
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);
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)
channel_locking('MITSWJNTask_SWJN_kmedoids_correlation_FIGURES',...
'experiment','MITSWJNTask',...
'useWandJ',true,...
'k',3,...
'calcFlag',1)
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);
fitReceptiveWindow('MITSWJNTask_SWJN_kmedoids_correlation_FIGURES',...
'experiment','MITSWJNTask',...
'useWandJ',true,...
'whichKernel','gaussian_wide');
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.
makeAllAnatomical('MITSWJNTask_SWJN_kmedoids_correlation_FIGURES',...
'experiment','MITSWJNTask',...
'doBoth',false,...
'doLang',true,...
'doTRW',true,...
'angle',270)
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
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
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);
calculateReliability('saveNameAdditional','MITSWJNTask_SN_kmedoids_correlation_FIGURES',...
'expt1','MITSWJNTask',...
'expt2','MITSWJNTask',...
'useLangElecs1',true,...
'useLangElecs2',false,...
'useWandJ',false)
calculateReliability('saveNameAdditional','MITLangloc_SN_8words_kmedoids_correlation_FIGURES',...
'expt1','MITLangloc',...
'expt2','MITLangloc',...
'useLangElecs1',true,...
'useLangElecs2',false,...
'useWandJ',false)
plotSubjectCluster('MITSWJNTask_SWJN_kmedoids_correlation_FIGURES',...
'experiment','MITSWJNTask',...
'useWandJ',true,...
'k',3);
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);
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
calculatePartialCorrelation('MITSWJNTask_SWJN_kmedoids_correlation_FIGURES',...
'experiment','MITSWJNTask',...
'useWandJ',true);
makeAllAnatomical('MITSWJNTask_SWJN_kmedoids_correlation_FIGURES',...
'experiment','MITSWJNTask',...
'doBoth',false,...
'doLang',true,...
'doPartialCorrelations',true,...
'angle',270)
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
.
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
See output from the runAll
function call used to generate Panels B,F of Figure 6.
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);
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);
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.
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.
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');
See the output from the channel_locking.m
function, called for Figure 3C.
See the output from the analyzeCoordinates_YZ.m
function, called for Figure 5C-E.
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