|
@@ -1,3 +1,4 @@
|
|
|
|
+</br>
|
|
|
|
|
|
# 1. Dataset information
|
|
# 1. Dataset information
|
|
|
|
|
|
@@ -36,7 +37,7 @@ Raw EEG data are saved in EEGLAB dataset format (*.set). Below are the list of f
|
|
**d) Example python scripts**
|
|
**d) Example python scripts**
|
|
|
|
|
|
[analysis_tutorial.ipynb]
|
|
[analysis_tutorial.ipynb]
|
|
- * written and tested on Google COLAB - Python 3 environment
|
|
|
|
|
|
+ * written and tested on Google Colab - Python 3 environment
|
|
|
|
|
|
|
|
|
|
# 3. How to get started (Python 3 without _gin_)
|
|
# 3. How to get started (Python 3 without _gin_)
|
|
@@ -49,28 +50,27 @@ As the data are saved in EEGLAB format, you need to install appropriate module t
|
|
|
|
|
|
### 1-1. Download dataset and MNE-python module
|
|
### 1-1. Download dataset and MNE-python module
|
|
|
|
|
|
-The dataset has been uploaded on G-Node and can be accessed by git command, by typing <code>git clone https://gin.g-node.org/hiobeen/Mouse_hdEEG_ASSR_Hwang_et_al</code>. However, it's currently not functioning because of the large size of each dataset (>100 MB). Instead, you can use *gin* command or custom function written below to copy dataset into your work environment. In *gin* repository, a python script <code>download_sample.py</code> is provided. It doesn't require *git* or *gin* command, simply using <code>request</code> module in Python 3. Try typing <code>python download_sample.py</code> on terminal/command after changing desired directory. In this Notebook document, Demo 1-1 is composed of download_sample.py script.
|
|
|
|
|
|
+The dataset has been uploaded on G-Node and can be accessed by git command, by typing <code>git clone https://gin.g-node.org/hiobeen/Mouse_hdEEG_ASSR_Hwang_et_al</code>. However, it's currently not functioning because of the large size of each dataset (>100 MB). Instead, you can use *gin* command or custom function written below to copy dataset into your work environment. In *gin* repository, a python script <code>download_sample.py</code> is provided. It doesn't require *git* or *gin* command, simply using <code>request</code> module in Python 3. Try typing <code>python download_sample.py</code> on terminal/command after changing desired directory. Demo 1-1 is composed of download_sample.py script in this Jupyter-Notebook document.
|
|
|
|
|
|
> Warning: Direct cloning using *git clone git@gin.g-node.org:/hiobeen/Mouse_hdEEG_ASSR_Hwang_et_al.git* may not work because of the large size of each dataset (>100 MB).
|
|
> Warning: Direct cloning using *git clone git@gin.g-node.org:/hiobeen/Mouse_hdEEG_ASSR_Hwang_et_al.git* may not work because of the large size of each dataset (>100 MB).
|
|
|
|
|
|
-To download dataset and install MNE-python module into your environment (local machine/COLAB), try running scripts below.
|
|
|
|
|
|
+Also, you need to install *MNE-Python* module using *pip* command to load EEGLAB-formatted EEG data. Install command using *pip* is located at the end of script <code>download_sample.py</code>. To download dataset and install MNE-python module into your environment (local machine/COLAB), try running scripts below.
|
|
|
|
|
|
-> Note: Through this step-by-step demonstration, we will use data from one animal (#Animal 2). Unnecessary data files will not be downloaded to prevent long download time. To download whole dataset, change this part; <code>dataset_to_download = [2]</code> into <code>dataset_to_download = [1,2,3,4,5,6]</code>.
|
|
|
|
-
|
|
|
|
-Also, you need to install *MNE-Python* module using *pip* command to load EEGLAB-formatted EEG data. Install command using *pip* is located at the end of script <code>download_sample.py</code>.
|
|
|
|
|
|
+> Note: Through this step-by-step demonstration, we will use data from one animal (#Animal 2). Unnecessary data files will not be downloaded to prevent long download time. To download whole dataset, change <code>dataset_to_download = [2]</code> into <code>dataset_to_download = [1,2,3,4,5,6]</code>.
|
|
|
|
|
|
|
|
|
|
```python
|
|
```python
|
|
# Demo 1-1. Setting an enviroment (download_sample.py)
|
|
# Demo 1-1. Setting an enviroment (download_sample.py)
|
|
from os import listdir, mkdir, path, system, getcwd
|
|
from os import listdir, mkdir, path, system, getcwd
|
|
|
|
+import warnings; warnings.simplefilter("ignore")
|
|
dir_origin = dir_origin = getcwd()+'/' # <- Change this in local machine
|
|
dir_origin = dir_origin = getcwd()+'/' # <- Change this in local machine
|
|
dir_dataset= 'dataset/'
|
|
dir_dataset= 'dataset/'
|
|
print('\n1)============ Start Downloading =================\n')
|
|
print('\n1)============ Start Downloading =================\n')
|
|
print('Target directory ... => [%s%s]'%(dir_origin,dir_dataset))
|
|
print('Target directory ... => [%s%s]'%(dir_origin,dir_dataset))
|
|
|
|
|
|
#!rm -rf /content/dataset/
|
|
#!rm -rf /content/dataset/
|
|
-import requests
|
|
|
|
-def download( dataset_to_download = range(1,7), dir_dataset = dir_dataset ):
|
|
|
|
|
|
+import requests, time
|
|
|
|
+def download_dataset( dataset_to_download = range(1,7), dir_dataset = dir_dataset ):
|
|
# Check directory
|
|
# Check directory
|
|
if not path.isdir('%s%s'%(dir_origin,dir_dataset)):
|
|
if not path.isdir('%s%s'%(dir_origin,dir_dataset)):
|
|
mkdir('%s%s'%(dir_origin,dir_dataset))
|
|
mkdir('%s%s'%(dir_origin,dir_dataset))
|
|
@@ -83,7 +83,7 @@ def download( dataset_to_download = range(1,7), dir_dataset = dir_dataset ):
|
|
file_ids.append( 'rawdata/epochs_animal%s.fdt'%set_id )
|
|
file_ids.append( 'rawdata/epochs_animal%s.fdt'%set_id )
|
|
|
|
|
|
# Request & download
|
|
# Request & download
|
|
- repo_url = 'https://gin.g-node.org/hiobeen/Mouse_hdEEG_ASSR_Hwang_et_al/raw/9a35f6b1a53f87a96d76b8b7912738cb7d8d3d36/'
|
|
|
|
|
|
+ repo_url = 'https://gin.g-node.org/hiobeen/Mouse_hdEEG_ASSR_Hwang_et_al/raw/3fa95eeb11021cf740ded020c9948c6aa0d1c904/'
|
|
for file_id in file_ids:
|
|
for file_id in file_ids:
|
|
fname_dest = "%s%s%s"%(dir_origin, dir_dataset, file_id)
|
|
fname_dest = "%s%s%s"%(dir_origin, dir_dataset, file_id)
|
|
if path.isfile(fname_dest) is False:
|
|
if path.isfile(fname_dest) is False:
|
|
@@ -93,13 +93,14 @@ def download( dataset_to_download = range(1,7), dir_dataset = dir_dataset ):
|
|
with open(fname_dest, "wb") as file:
|
|
with open(fname_dest, "wb") as file:
|
|
for block in r.iter_content(chunk_size=1024):
|
|
for block in r.iter_content(chunk_size=1024):
|
|
if block: file.write(block)
|
|
if block: file.write(block)
|
|
|
|
+ time.sleep(1) # wait a second to prevent possible errors
|
|
else:
|
|
else:
|
|
print('...skipping already existing file [%s]...'%fname_dest)
|
|
print('...skipping already existing file [%s]...'%fname_dest)
|
|
|
|
|
|
# Initiate downloading
|
|
# Initiate downloading
|
|
dataset_to_download = [2] # Partial download to prevent long download time
|
|
dataset_to_download = [2] # Partial download to prevent long download time
|
|
-#dataset_to_download = [1,2,3,4,5,6] # Download of whole dataset
|
|
|
|
-download(dataset_to_download)
|
|
|
|
|
|
+#dataset_to_download = [1,2,3,4,5,6] # Full download
|
|
|
|
+download_dataset(dataset_to_download)
|
|
print('\n============= Download finished ==================\n\n')
|
|
print('\n============= Download finished ==================\n\n')
|
|
|
|
|
|
# List up 'dataset/' directory
|
|
# List up 'dataset/' directory
|
|
@@ -124,10 +125,10 @@ if not path.isdir(dir_fig): mkdir('%s%s'%(dir_origin, dir_fig))
|
|
1)============ Start Downloading =================
|
|
1)============ Start Downloading =================
|
|
|
|
|
|
Target directory ... => [/content/dataset/]
|
|
Target directory ... => [/content/dataset/]
|
|
- ...skipping already existing file [/content/dataset/meta.csv]...
|
|
|
|
- ...skipping already existing file [/content/dataset/montage.csv]...
|
|
|
|
- ...skipping already existing file [/content/dataset/rawdata/epochs_animal2.set]...
|
|
|
|
- ...skipping already existing file [/content/dataset/rawdata/epochs_animal2.fdt]...
|
|
|
|
|
|
+ ...copying to [/content/dataset/meta.csv]...
|
|
|
|
+ ...copying to [/content/dataset/montage.csv]...
|
|
|
|
+ ...copying to [/content/dataset/rawdata/epochs_animal2.set]...
|
|
|
|
+ ...copying to [/content/dataset/rawdata/epochs_animal2.fdt]...
|
|
|
|
|
|
============= Download finished ==================
|
|
============= Download finished ==================
|
|
|
|
|
|
@@ -135,7 +136,7 @@ if not path.isdir(dir_fig): mkdir('%s%s'%(dir_origin, dir_fig))
|
|
|
|
|
|
2)=== List of available files in google drive ====
|
|
2)=== List of available files in google drive ====
|
|
|
|
|
|
- ['rawdata', 'meta.csv', 'montage.csv']
|
|
|
|
|
|
+ ['meta.csv', 'montage.csv', 'rawdata']
|
|
|
|
|
|
============= End of the list ==================
|
|
============= End of the list ==================
|
|
|
|
|
|
@@ -162,9 +163,13 @@ File *meta.csv* contains the demographic information of 6 mice. Using <code>read
|
|
## Demo 1-2. Display meta-data file
|
|
## Demo 1-2. Display meta-data file
|
|
from pandas import read_csv
|
|
from pandas import read_csv
|
|
meta = read_csv('%s%smeta.csv'%(dir_origin, dir_dataset));
|
|
meta = read_csv('%s%smeta.csv'%(dir_origin, dir_dataset));
|
|
|
|
+print('Table 1. Meta-data')
|
|
meta
|
|
meta
|
|
```
|
|
```
|
|
|
|
|
|
|
|
+ Table 1. Meta-data
|
|
|
|
+
|
|
|
|
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -248,6 +253,26 @@ meta
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+
|
|
|
|
+```python
|
|
|
|
+# (Optional: Check total number of trials for each experimental condition)
|
|
|
|
+"""
|
|
|
|
+# Count number of trials for each experimental condition (all files)
|
|
|
|
+import pandas as pd
|
|
|
|
+n_trials = np.zeros((7,8),dtype='int')
|
|
|
|
+for dataset_idx in range(6):
|
|
|
|
+ EEG_temp, f_name = get_eeg_data( dataset_idx )
|
|
|
|
+ for condition in range(1,8):
|
|
|
|
+ # Accessing event info: print( EEG.event )
|
|
|
|
+ trialIdx = np.where(EEG_temp.events[:,2]==condition)[0]
|
|
|
|
+ n_trials[dataset_idx,condition-1] = len(trialIdx)
|
|
|
|
+n_trials[-1,:], n_trials[:,-1] = np.sum(n_trials,axis=0), np.sum(n_trials,axis=1)
|
|
|
|
+n_trials = pd.DataFrame(n_trials, index=['animal1','animal2','animal3','animal4','animal5','animal6', 'Total'],
|
|
|
|
+ columns=['In-phase','Out-of-phase','Delayed','Advanced','Continuous','Sound only', 'Light only', 'Total'])
|
|
|
|
+n_trials
|
|
|
|
+""";
|
|
|
|
+```
|
|
|
|
+
|
|
### 1-3. Data loading and dimensionality check
|
|
### 1-3. Data loading and dimensionality check
|
|
|
|
|
|
Each _*.fdt_ file is consisted of different number of trials. To load dataset, a function <code>get_eeg_data()</code> is defined below. To maintain original dimensionality order (cf. channel-time-trial in EEGLAB of Matlab), <code>np.moveaxis()</code> was applied.
|
|
Each _*.fdt_ file is consisted of different number of trials. To load dataset, a function <code>get_eeg_data()</code> is defined below. To maintain original dimensionality order (cf. channel-time-trial in EEGLAB of Matlab), <code>np.moveaxis()</code> was applied.
|
|
@@ -258,7 +283,7 @@ Each _*.fdt_ file is consisted of different number of trials. To load dataset, a
|
|
# Demo 1-3. Data loading and dimensionality check
|
|
# Demo 1-3. Data loading and dimensionality check
|
|
from mne.io import read_epochs_eeglab as loadeeg
|
|
from mne.io import read_epochs_eeglab as loadeeg
|
|
import numpy as np
|
|
import numpy as np
|
|
-def get_eeg_data(dataset_idx, CAL=1e-6):
|
|
|
|
|
|
+def get_eeg_data(dataset_idx=1, CAL=1e-6):
|
|
f_name = '%s%srawdata/%s'%(dir_origin,dir_dataset,meta.file_name[dataset_idx])
|
|
f_name = '%s%srawdata/%s'%(dir_origin,dir_dataset,meta.file_name[dataset_idx])
|
|
EEG = loadeeg(f_name, verbose=False)
|
|
EEG = loadeeg(f_name, verbose=False)
|
|
EEG.data = np.moveaxis(EEG.get_data(), 0, 2) / CAL
|
|
EEG.data = np.moveaxis(EEG.get_data(), 0, 2) / CAL
|
|
@@ -272,13 +297,11 @@ print('File name : [%s]'%f_name)
|
|
print('File contains [%d channels, %4d time points, %3d trials]'%(EEG.data.shape))
|
|
print('File contains [%d channels, %4d time points, %3d trials]'%(EEG.data.shape))
|
|
```
|
|
```
|
|
|
|
|
|
-
|
|
|
|
-
|
|
|
|
File name : [/content/dataset/rawdata/epochs_animal2.set]
|
|
File name : [/content/dataset/rawdata/epochs_animal2.set]
|
|
File contains [38 channels, 5200 time points, 557 trials]
|
|
File contains [38 channels, 5200 time points, 557 trials]
|
|
|
|
|
|
|
|
|
|
-Note that voltage calibration value (*CAL*) is set to 1e-6 in 0.11.0 version of [eeglab.py](https://github.com/mne-tools/mne-python/blob/master/mne/io/eeglab/eeglab.py])
|
|
|
|
|
|
+Note that voltage calibration value (*CAL*) is set to 1e-6 in 0.11.0 version of [eeglab.py](https://github.com/mne-tools/mne-python/blob/master/mne/io/eeglab/eeglab.py]).
|
|
|
|
|
|
|
|
|
|
### 1-4. Getting channel coordinates
|
|
### 1-4. Getting channel coordinates
|
|
@@ -292,7 +315,7 @@ The EEG data are recorded with 38 electrode array, and two of the electrodes wer
|
|
from matplotlib import pyplot as plt; plt.style.use('ggplot')
|
|
from matplotlib import pyplot as plt; plt.style.use('ggplot')
|
|
plt.rcParams['font.family']='sans-serif'
|
|
plt.rcParams['font.family']='sans-serif'
|
|
plt.rcParams['text.color']='black'; plt.rcParams['axes.labelcolor']='black'
|
|
plt.rcParams['text.color']='black'; plt.rcParams['axes.labelcolor']='black'
|
|
-plt.rcParams['xtick.color']='black' ;plt.rcParams['ytick.color']='black'
|
|
|
|
|
|
+plt.rcParams['xtick.color']='black'; plt.rcParams['ytick.color']='black'
|
|
|
|
|
|
from pandas import read_csv
|
|
from pandas import read_csv
|
|
montage_table = read_csv('%s%smontage.csv'%(dir_origin, dir_dataset))
|
|
montage_table = read_csv('%s%smontage.csv'%(dir_origin, dir_dataset))
|
|
@@ -345,7 +368,7 @@ plt.gcf().savefig(dir_fig+'fig1-4.png', format='png', dpi=300);
|
|
```
|
|
```
|
|
|
|
|
|
|
|
|
|
-![png](figures/output_12_0.png)
|
|
|
|
|
|
+![png](figures/output_13_0.png)
|
|
|
|
|
|
|
|
|
|
## Part 2. Plotting Event-Related Potentials
|
|
## Part 2. Plotting Event-Related Potentials
|
|
@@ -385,7 +408,7 @@ plt.gcf().savefig(dir_fig+'fig2-1.png', format='png', dpi=300);
|
|
```
|
|
```
|
|
|
|
|
|
|
|
|
|
-![png](figures/output_15_0.png)
|
|
|
|
|
|
+![png](figures/output_16_0.png)
|
|
|
|
|
|
|
|
|
|
### 2-2. Visualizing example single-trial trace
|
|
### 2-2. Visualizing example single-trial trace
|
|
@@ -427,7 +450,7 @@ plt.gcf().savefig(dir_fig+'fig2-2.png', format='png', dpi=300);
|
|
```
|
|
```
|
|
|
|
|
|
|
|
|
|
-![png](figures/output_19_0.png)
|
|
|
|
|
|
+![png](figures/output_20_0.png)
|
|
|
|
|
|
|
|
|
|
Note that channels 1 to 36 contain actual EEG data from 36-channel electrode array (from FP1 to PO8), and channel 37 and 38 contain binary stimulus profile (0: no stimulation, 1: stimulation) of light and sound, respectively.
|
|
Note that channels 1 to 36 contain actual EEG data from 36-channel electrode array (from FP1 to PO8), and channel 37 and 38 contain binary stimulus profile (0: no stimulation, 1: stimulation) of light and sound, respectively.
|
|
@@ -450,7 +473,7 @@ plt.gcf().savefig(dir_fig+'fig2-3.png', format='png', dpi=300);
|
|
```
|
|
```
|
|
|
|
|
|
|
|
|
|
-![png](figures/output_22_0.png)
|
|
|
|
|
|
+![png](figures/output_23_0.png)
|
|
|
|
|
|
|
|
|
|
### 2-4. ERP in frequency domain
|
|
### 2-4. ERP in frequency domain
|
|
@@ -458,55 +481,6 @@ plt.gcf().savefig(dir_fig+'fig2-3.png', format='png', dpi=300);
|
|
To calculate the amplitude of 40-Hz auditory steady-state response, fast Fourier transform can be applied as follow.
|
|
To calculate the amplitude of 40-Hz auditory steady-state response, fast Fourier transform can be applied as follow.
|
|
|
|
|
|
|
|
|
|
-```python
|
|
|
|
-EEG.info['ch_names']
|
|
|
|
-```
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- ['Ch01-FP1',
|
|
|
|
- 'Ch02-FP2',
|
|
|
|
- 'Ch03-AF3',
|
|
|
|
- 'Ch04-AF4',
|
|
|
|
- 'Ch05-AF7',
|
|
|
|
- 'Ch06-AF8',
|
|
|
|
- 'Ch07-F1',
|
|
|
|
- 'Ch08-F2',
|
|
|
|
- 'Ch09-F5',
|
|
|
|
- 'Ch10-F6',
|
|
|
|
- 'Ch11-FC1',
|
|
|
|
- 'Ch12-FC2',
|
|
|
|
- 'Ch13-FC5',
|
|
|
|
- 'Ch14-FC6',
|
|
|
|
- 'Ch15-C1',
|
|
|
|
- 'Ch16-C2',
|
|
|
|
- 'Ch17-C3',
|
|
|
|
- 'Ch18-C4',
|
|
|
|
- 'Ch19-C5',
|
|
|
|
- 'Ch20-C6',
|
|
|
|
- 'Ch21-CP1',
|
|
|
|
- 'Ch22-CP2',
|
|
|
|
- 'Ch23-CP3',
|
|
|
|
- 'Ch24-CP4',
|
|
|
|
- 'Ch25-CP5',
|
|
|
|
- 'Ch26-CP6',
|
|
|
|
- 'Ch27-P1',
|
|
|
|
- 'Ch28-P2',
|
|
|
|
- 'Ch29-P3',
|
|
|
|
- 'Ch30-P4',
|
|
|
|
- 'Ch31-P5',
|
|
|
|
- 'Ch32-P6',
|
|
|
|
- 'Ch33-PO3',
|
|
|
|
- 'Ch34-PO4',
|
|
|
|
- 'Ch35-PO7',
|
|
|
|
- 'Ch36-PO8',
|
|
|
|
- 'LightStim',
|
|
|
|
- 'SoundStim']
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-
|
|
|
|
```python
|
|
```python
|
|
# Demo 2-4. Time- and frequency-domain visualization of grand-averaged ERP
|
|
# Demo 2-4. Time- and frequency-domain visualization of grand-averaged ERP
|
|
def fft_half(x, Fs=2000): return np.fft.fft(x)[:int(len(x)/2)]/len(x), np.linspace(0,Fs/2,len(x)/2)
|
|
def fft_half(x, Fs=2000): return np.fft.fft(x)[:int(len(x)/2)]/len(x), np.linspace(0,Fs/2,len(x)/2)
|
|
@@ -1014,8 +988,7 @@ plt.gcf().savefig(dir_fig+'fig3-3.png', format='png', dpi=300);
|
|
```
|
|
```
|
|
|
|
|
|
|
|
|
|
-
|
|
|
|
-![png](figures/output_36_1.png)
|
|
|
|
|
|
+![png](figures/output_36_0.png)
|
|
|
|
|
|
|
|
|
|
### 3-4. Band-power topography: Comparison across various experimental conditions
|
|
### 3-4. Band-power topography: Comparison across various experimental conditions
|
|
@@ -1049,9 +1022,7 @@ plt.gcf().savefig(dir_fig+'fig3-4.png', format='png', dpi=300);
|
|
```
|
|
```
|
|
|
|
|
|
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-![png](figures/output_38_1.png)
|
|
|
|
|
|
+![png](figures/output_38_0.png)
|
|
|
|
|
|
|
|
|
|
<br>
|
|
<br>
|