Skip to content

Commit c6eadb6

Browse files
committed
fix name and add limo
1 parent 89c329a commit c6eadb6

20 files changed

+1078
-26
lines changed

code/plugins/plugins.json

+7-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
},
88
{
99
"plugin": "dipfit",
10-
"name": "dipfit",
10+
"name": "Dipfit",
1111
"type": "readme",
1212
"link": "https://github.com/sccn/dipfit"
1313
},
@@ -160,5 +160,11 @@
160160
"name": "nsgportal",
161161
"type": "wiki",
162162
"link": "https://github.com/sccn/nsgportal"
163+
},
164+
{
165+
"plugin": "limo",
166+
"name": "LIMO",
167+
"type": "wiki",
168+
"link": "https://github.com/LIMO-EEG-Toolbox/limo_meeg"
163169
}
164170
]

code/plugins/reformat_plugin.py

+28-21
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ def reformat_wiki_pages(filepath, filename, parent, output_file, wiki_input_dir=
1212
grand_parent: Plugins
1313
'''.format(filename=filename, parent=parent)
1414

15-
if parent in ["nsgportal", "LIMO"]:
15+
print(f"Reformatting {filename}...")
16+
if parent in ["nsgportal", "limo"]:
1617
pages = []
1718
# load _Sidebar.md and extract all links from markdown file
1819
with open(os.path.join(wiki_input_dir, '_Sidebar.md')) as f:
@@ -34,7 +35,7 @@ def reformat_wiki_pages(filepath, filename, parent, output_file, wiki_input_dir=
3435
with open(output_file, 'w') as out:
3536
out.write(text)
3637

37-
def reformat_plugin_dir(plugin_input_dir, plugin_name, order, plugin_type='wiki'):
38+
def reformat_plugin_dir(plugin_input_dir, plugin_name, formatted_name, order, link, plugin_type='wiki'):
3839
# plugins_output_dir = '/Users/dtyoung/Documents/EEGLAB/sccn.github.io/plugins'
3940
plugin_output_dir = os.path.join('../../plugins', plugin_name)
4041
if not os.path.exists(plugin_output_dir):
@@ -54,25 +55,16 @@ def reformat_plugin_dir(plugin_input_dir, plugin_name, order, plugin_type='wiki'
5455

5556
index_file = os.path.join(plugin_output_dir, 'index.md')
5657
shutil.copyfile(os.path.join(plugin_input_dir, 'README.md'), index_file)
57-
with open(index_file) as f:
58-
text = f.read()
59-
append_text = '''---
58+
append_text = '''---
6059
layout: default
6160
title: {plugin_name}
6261
long_title: {plugin_name}
63-
parent: Plugins
64-
has_children: true
65-
nav_order: {order}
66-
---
67-
To view the plugin source code, please visit the plugin's [GitHub repository](https://github.com/sccn/{plugin_name}).
68-
69-
'''.format(plugin_name=plugin_name, order=order)
70-
text = append_text + text
71-
with open(index_file, 'w') as out:
72-
out.write(text)
62+
parent: Plugins'''.format(plugin_name=formatted_name)
7363

7464
if plugin_type == 'wiki':
65+
append_text += '\nhas_children: true'
7566
wiki_plugin_input_dir = plugin_input_dir + '.wiki'
67+
print(wiki_plugin_input_dir)
7668

7769
# copy image directory from input to output dir
7870
if os.path.exists(os.path.join(wiki_plugin_input_dir, 'images')):
@@ -86,17 +78,32 @@ def reformat_plugin_dir(plugin_input_dir, plugin_name, order, plugin_type='wiki'
8678
for root, dirs, files in os.walk(wiki_plugin_input_dir):
8779
for file in files:
8880
if file.endswith('.md') and not file.startswith('index') and not file.startswith('Home'):
89-
reformat_wiki_pages(os.path.join(wiki_plugin_input_dir, file), file.strip('.md'), plugin_name, os.path.join(plugin_output_dir, file), wiki_plugin_input_dir)
81+
reformat_wiki_pages(os.path.join(wiki_plugin_input_dir, file), file.strip('.md'), formatted_name, os.path.join(plugin_output_dir, file), wiki_plugin_input_dir)
82+
83+
84+
with open(index_file) as f:
85+
append_text += '''
86+
nav_order: {order}
87+
---
88+
To view the plugin source code, please visit the plugin's [GitHub repository]({link}).
89+
90+
'''.format(link=link, order=order)
91+
text = f.read()
92+
text = append_text + text
93+
with open(index_file, 'w') as out:
94+
out.write(text)
9095
# main
9196
def main():
92-
if len(sys.argv) != 5:
93-
print('Usage: python test.py <plugin_dir_path> <plugin_name> <plugin_type> <nav_order>')
97+
if len(sys.argv) != 7:
98+
print('Usage: python reformat_plugin.py <plugin_dir_path> <plugin_name> <formatted_name> <plugin_type> <nav_order> link')
9499
sys.exit(1)
95100
dirpath = sys.argv[1]
96101
plugin_name = sys.argv[2]
97-
plugin_type = sys.argv[3]
98-
order = sys.argv[4]
99-
reformat_plugin_dir(dirpath, plugin_name, order, plugin_type)
102+
formatted_name = sys.argv[3]
103+
plugin_type = sys.argv[4]
104+
order = sys.argv[5]
105+
link = sys.argv[6]
106+
reformat_plugin_dir(dirpath, plugin_name, formatted_name, order, link, plugin_type)
100107

101108
if __name__ == "__main__":
102109
main()

code/plugins/update_plugins.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ def run_command(command):
99
print(f"Command failed: {command}\nError: {result.stderr}")
1010
return result
1111

12-
def update_repo(repo, order, plugin_type='readme', plugin_link="https://github.com/sccn"):
12+
def update_repo(repo, formatted_name, order, plugin_type='readme', plugin_link="https://github.com/sccn"):
1313
print(f"Updating {repo}...")
1414
current_dir = os.getcwd()
1515
repo_path = os.path.join(current_dir, 'github', repo)
@@ -30,7 +30,7 @@ def update_repo(repo, order, plugin_type='readme', plugin_link="https://github.c
3030

3131
os.chdir(current_dir)
3232
script = 'reformat_plugin.py'
33-
command = f'python {script} {repo_path} {repo} {plugin_type} {order}'
33+
command = f'python {script} {repo_path} {repo} {formatted_name} {plugin_type} {order} {plugin_link}'
3434
run_command(command)
3535

3636
if __name__ == "__main__":
@@ -49,14 +49,14 @@ def update_repo(repo, order, plugin_type='readme', plugin_link="https://github.c
4949

5050
if len(sys.argv) == 1:
5151
for plugin in plugin_info:
52-
update_repo(plugin['plugin'], plugins.index(plugin['plugin']), plugin['type'], plugin['link'])
52+
update_repo(plugin['plugin'], plugin['name'], plugins.index(plugin['plugin']), plugin['type'], plugin['link'])
5353
elif len(sys.argv) == 2:
5454
plugin_name = sys.argv[1]
5555
if plugin_name not in plugins:
5656
print(f"Plugin {plugin_name} not found.")
5757
sys.exit(1)
5858
plugin = plugin_info[plugins.index(plugin_name)]
59-
update_repo(plugin['plugin'], plugins.index(plugin['plugin']), plugin['type'], plugin['link'])
59+
update_repo(plugin['plugin'], plugin['name'], plugins.index(plugin['plugin']), plugin['type'], plugin['link'])
6060
else:
6161
print('Usage: python update_plugins.py <plugin_name>')
6262
sys.exit(1)

plugins/limo/1.-Preprocessing.md

+120
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
---
2+
layout: default
3+
title: 1.-Preprocessing
4+
long_title: 1.-Preprocessing
5+
parent: LIMO
6+
grand_parent: Plugins
7+
---
8+
# Data for the tutorial
9+
10+
This tutorial aims at teaching how to use [LIMO MEEG](https://github.com/LIMO-EEG-Toolbox/limo_tools/wiki), in conjunction with [EEGLAB STUDY](https://sccn.ucsd.edu/wiki/Chapter_02:_STUDY_Creation). To get started, you must be familiar with [EEGLAB](https://sccn.ucsd.edu/eeglab/index.php). Also, make sure LIMO tools subdirectories are listed in the Matlab path.
11+
12+
The data used in this tutorial come from [Wakeman and Henson (2015)](https://www.nature.com/articles/sdata20151). In this experiment, MEG-EEG data were collected while subjects viewed famous, unfamiliar and scrambled faces. Each image was repeated twice (immediately in 50% of cases and 5–10 stimuli apart for the other 50%) and subjects pressed one of two keys with their left or right index finger indicating how symmetric they regarded each image relative to the average.
13+
14+
The data were prepared (i.e. EEG extracted, timing corrected, electrode position re-oriented, event recorded) by Dung Truong, Ramon Martinez & Arnaud Delorme and can be downloaded from [OpenNeuro](https://openneuro.org/datasets/ds002718/versions/1.0.2).
15+
16+
# Data pre-processing pipeline script
17+
18+
The data are organized according to the [Brain Imaging Data Structure](https://bids.neuroimaging.io/), in particular the [EEG BIDS extension](https://www.nature.com/articles/s41597-019-0104-8). It is worthwhile spending a bit of time looking at how files are organized and named, as we will follow this convention throughout. EEGLAB also has dedicated [BIDS tools called bids-matlab-tools](https://github.com/sccn/bids-matlab-tools) to create files, export and import BIDS dataset. This is available using the EEGLAB plugin manager and must be installed before running the code below.
19+
20+
Once you have downloaded the data, you can run the code below - can copy and paste to a file (changing Xs with your specific path) to get descent pre-processed data. Alternatively download the [code located here](https://github.com/LIMO-EEG-Toolbox/limo_meeg/blob/master/resources/code/henson_wakeman_preprocess.m). Be patient, this step will take several hours.
21+
22+
```matlab
23+
% start EEGLAB
24+
clear variables
25+
[ALLEEG, EEG, CURRENTSET, ALLCOM] = eeglab;
26+
27+
% import BIDS
28+
bidsfolder = 'F:\WakemanHenson_Faces\eeg';
29+
[STUDY, ALLEEG] = pop_importbids(bidsfolder, 'bidsevent','on','bidschanloc','on', ...
30+
'eventtype', 'trial_type', 'outputdir' ,fullfile(bidsfolder,'newderivatives'), 'studyName','Face_detection');
31+
ALLEEG = pop_select( ALLEEG, 'nochannel',{'061','062','063','064'});
32+
CURRENTSTUDY = 1; EEG = ALLEEG; CURRENTSET = 1:length(EEG);
33+
34+
% reorient if using previous version of the data
35+
EEG = pop_chanedit(EEG,'nosedir','+Y');
36+
37+
% Clean data - just the bad channels
38+
EEG = pop_clean_rawdata( EEG,'FlatlineCriterion',5,'ChannelCriterion',0.8,...
39+
'LineNoiseCriterion',4,'Highpass',[0.25 0.75] ,...
40+
'BurstCriterion','off','WindowCriterion','off','BurstRejection','off',...
41+
'Distance','Euclidian','WindowCriterionTolerances','off' );
42+
43+
% Rereference using average reference
44+
EEG = pop_reref( EEG,[],'interpchan',[]);
45+
46+
% Run ICA and flag artifactual components using IClabel
47+
for s=1:size(EEG,2)
48+
EEG(s) = pop_runica(EEG(s), 'icatype','runica','concatcond','on','options',{'pca',EEG(s).nbchan-1});
49+
EEG(s) = pop_iclabel(EEG(s),'default');
50+
EEG(s) = pop_icflag(EEG(s),[NaN NaN;0.8 1;0.8 1;NaN NaN;NaN NaN;NaN NaN;NaN NaN]);
51+
EEG(s) = pop_subcomp(EEG(s), find(EEG(s).reject.gcompreject), 0);
52+
end
53+
54+
% clear data using ASR - just the bad epochs
55+
EEG = pop_clean_rawdata( EEG,'FlatlineCriterion','off','ChannelCriterion','off',...
56+
'LineNoiseCriterion','off','Highpass','off','BurstCriterion',20,...
57+
'WindowCriterion',0.25,'BurstRejection','on','Distance','Euclidian',...
58+
'WindowCriterionTolerances',[-Inf 7] );
59+
60+
% Extract data epochs (no baseline removed)
61+
EEG = pop_epoch( EEG,{'famous_new','famous_second_early','famous_second_late','scrambled_new','scrambled_second_early','scrambled_second_late','unfamiliar_new','unfamiliar_second_early','unfamiliar_second_late'},...
62+
[-0.5 1] ,'epochinfo','yes');
63+
EEG = eeg_checkset(EEG);
64+
EEG = pop_saveset(EEG, 'savemode', 'resave');
65+
ALLEEG = EEG;
66+
67+
% Create study design
68+
STUDY = std_checkset(STUDY, ALLEEG);
69+
STUDY = std_makedesign(STUDY, EEG, 1, 'name','STUDY.FaceRepetition','delfiles','off','defaultdesign','off','variable1','type','values1',{});
70+
eeglab redraw
71+
```
72+
73+
# Loading the pre-processed EEGLAB STUDY
74+
75+
After data preprocessing, data should be clean, epochs marked, and a STUDY created. Load the study from the EEGLAB menu (File --> Load existing study - [figure 1](https://github.com/LIMO-EEG-Toolbox/limo_meeg/blob/master/resources/images/1.jpg)) and check that all the data are there (Study --> edit study info - [figure 2](https://github.com/LIMO-EEG-Toolbox/limo_meeg/blob/master/resources/images/1.jpg)). In total there are 18 subjects, named sub-002 to sub-019.
76+
77+
![Figure 1. Loading EEGLAB STUDY](https://github.com/LIMO-EEG-Toolbox/limo_meeg/blob/master/resources/images/1.jpg)
78+
_Figure 1. Loading EEGLAB STUDY_
79+
80+
![Figure 2. Wakeman_Henson STUDY](https://github.com/LIMO-EEG-Toolbox/limo_meeg/blob/master/resources/images/2.jpg)
81+
_Figure 2. Wakeman_Henson STUDY_
82+
83+
# Precompute STUDY measures
84+
85+
LIMO MEEG models data using a hierarchical approach with a general linear model at the subject level and then testing, at the group level, parameters obtained with robust methods. You can think of it as generating averages per condition at the subject level and do statistics on those averages at the group level. The difference (and advantage) is that subject-specific baselines are removed, among trial variance accounted for, and bad subjects are accounted for. For more details see the [San Diego 2016 lecture as pdf](https://github.com/LIMO-EEG-Toolbox/limo_meeg/blob/master/resources/2016_SanDiego_StatisticalanalysisofEEGdata.pdf) and/or on [YouTube](https://youtu.be/KfnN51frbuI).
86+
87+
## Step 1 – precompute single-trial measure(s)
88+
89+
No matter the design, using LIMO MEEG means we need single trials to obtain condition related parameters for each subject. EEGLAB will export all trial data measures and, depending on the design, will pass on only relevant ones to LIMO EEG (even if this is only the mean as for comparing spectra between groups).
90+
91+
Create ERPs and/or Spectra and/or ERSP (Study --> Precompute channel measures – [figure 3]((https://github.com/LIMO-EEG-Toolbox/limo_meeg/blob/master/resources/images/3.jpg))). Note you could set limits to your epoch at this stage (using ‘timelim’ and ‘freqlim’) or limit the statistical analysis at the next stage (which is what we will do). For ERPs, baseline correction can be added using `[-200 0]`. Note that ERSP can take a long time. You can start with ERP and Spectra only (of course if you do that, you will not be able to use LIMO on ERSP in the next sections).
92+
93+
![Figure 3. Precompute channel measures](https://github.com/LIMO-EEG-Toolbox/limo_meeg/blob/master/resources/images/3.jpg)
94+
_Figure 3. Precompute channel measures_
95+
96+
All single trials (erp, spectrum, ersp) can also be generated in command line using:
97+
98+
```matlab
99+
% Precompute ERP and Spectrum measures
100+
[STUDY, EEG] = std_precomp(STUDY, EEG, {}, 'savetrials','on','interp','on','recompute','on',...
101+
'erp','on','erpparams', {'rmbase' [-200 0]}, 'spec','on',...
102+
'ersp','on','itc','on', 'specparams',{'specmode','fft','logtrials','off'});
103+
```
104+
105+
## Step 2 – create your design
106+
107+
From a set of available conditions and trial information, there are many options available. In this tutorial, we’ll review the most common ones. For example, we can select the independent variable "face_type" that takes 3 categorical values (famous, scambled and unfamiliar faces). We will start by using this simple design and create more complex ones as we go along the tutorial (Study --> Select/Edit study designs(s) – [figure 4](https://github.com/LIMO-EEG-Toolbox/limo_meeg/blob/master/resources/images/4.jpg)).
108+
109+
![Figure 4. Select/Edit study design(s)](https://github.com/LIMO-EEG-Toolbox/limo_meeg/blob/master/resources/images/4.jpg)
110+
_Figure 4. Select/Edit study design(s)_
111+
112+
Every design can be generated from here, and the following sections will show you each time a different design. For now, let’s have a look at the ‘List of factors’ ([figure 5](https://github.com/LIMO-EEG-Toolbox/limo_meeg/blob/master/resources/images/5.jpg)). This lists all categorical variables from which we can make a design (this list appears if you select "list factors" for the independent variable). This list of factors is the list LIMO will use at the first level. In the next section, we will do a 1-way ANOVA testing the effect of familiarity (all famous vs. all unfamiliar vs. all scrambled faces).
113+
114+
![Figure 5. List of categorical variables](https://github.com/LIMO-EEG-Toolbox/limo_meeg/blob/master/resources/images/5.jpg)
115+
_Figure 5. List of categorical variables_
116+
117+
# Note on using LIMO default and sampling rate
118+
119+
By default, LIMO EEG uses a Weighted least Squares approach for each trial, which means you should aim to have more trials than time frames (for ERP and ERSP) or frequency frames (for Spectrum), while not mandatory. The data here are at 250Hz which is fine.
120+
+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
---
2+
layout: default
3+
title: 10.-Two-sample-t-tests
4+
long_title: 10.-Two-sample-t-tests
5+
parent: LIMO
6+
grand_parent: Plugins
7+
---
8+
Given the (non-significant) group effect observed in the between subjects’ ANOVA with repeated factor, we can also do a simple two samples t-tests between groups 1 and 2. From the 2nd level GUI ([figure 9](https://github.com/LIMO-EEG-Toolbox/limo_meeg/blob/master/resources/images/9.jpg)), click on two samples t-test, and select the beta files for group 1 and group 2. Let’s select parameter 1, i.e. famous faces ([figure 38](https://github.com/LIMO-EEG-Toolbox/limo_meeg/blob/master/resources/images/38.jpg)). Parameter question dialogue is repeated because you could for instance compare groups from 2 different studies, i.e. with different 1st level designs.
9+
10+
![Figure 38. Regression](https://github.com/LIMO-EEG-Toolbox/limo_meeg/blob/master/resources/images/38.jpg)
11+
_Figure 38. Selection of files for 2 samples t-test._
12+
13+
These steps can be executed in command line as:
14+
```matlab
15+
chanlocs = XXX\derivatives\limo_gp_level_chanlocs.mat';
16+
Files{1} = ‘XXX\LIMO_Face_detection\Beta_files_Gp1_Faces_GLM_Channels_Frequency_WLS.txt';
17+
Files{2} = 'XXX\LIMO_Face_detection\Beta_files_Gp2_Faces_GLM_Channels_Frequency_WLS.txt';
18+
LIMOPath = limo_random_select('two-samples t-test',chanlocs,'LIMOfiles',Files,...
19+
'analysis_type','Full scalp analysis', 'type','Channels','parameter',[1;1],'nboot',1000,'tfce',0);
20+
```
21+
22+
You should obtain results display on figure 39 for [ERP](https://github.com/LIMO-EEG-Toolbox/limo_meeg/blob/master/resources/images/39a.jpg), [Spectrum](https://github.com/LIMO-EEG-Toolbox/limo_meeg/blob/master/resources/images/39b.jpg) and [ERSP](https://github.com/LIMO-EEG-Toolbox/limo_meeg/blob/master/resources/images/39c.jpg).
23+
24+
![Figure 39. Regression ERP](https://github.com/LIMO-EEG-Toolbox/limo_meeg/blob/master/resources/images/39a.jpg)
25+
![Figure 39. Regression Spectrum](https://github.com/LIMO-EEG-Toolbox/limo_meeg/blob/master/resources/images/39b.jpg)
26+
![Figure 39. Regression ERSP](https://github.com/LIMO-EEG-Toolbox/limo_meeg/blob/master/resources/images/39c.jpg)
27+
_Figure 39. Results of the 2 samples t-test young vs old for famous faces._

0 commit comments

Comments
 (0)