加算波形の三次元表示

Python 2.7です。

In [1]:
import sys
print(sys.version_info)
del sys
sys.version_info(major=2, minor=7, micro=13, releaselevel='final', serial=0)

データの読み込み

In [2]:
import mne
mne.set_log_level('INFO')
# filename='H:\\FS\\hashizume_akira\\041029\\SEF_median_ave.fif'
filename='c:\\170207\\hashizume_akira\\041029\\SEF_median_ave.fif'
meg=mne.read_evokeds(filename,proj=True)[0] # リストですけど1個しかありません
print(meg)
This filename (c:\170207\hashizume_akira\041029\SEF_median_ave.fif) does not conform to MNE naming conventions. All evoked files should end with -ave.fif or -ave.fif.gz
Reading c:\170207\hashizume_akira\041029\SEF_median_ave.fif ...
    Read a total of 8 projection items:
        grad_ssp_upright_040205.fif : PCA-v1 (1 x 306)  idle
        grad_ssp_upright_040205.fif : PCA-v2 (1 x 306)  idle
        grad_ssp_upright_040205.fif : PCA-v3 (1 x 306)  idle
        mag_ssp_upright_040205_V5.fif : PCA-v1 (1 x 306)  idle
        mag_ssp_upright_040205_V5.fif : PCA-v2 (1 x 306)  idle
        mag_ssp_upright_040205_V5.fif : PCA-v3 (1 x 306)  idle
        mag_ssp_upright_040205_V5.fif : PCA-v4 (1 x 306)  idle
        mag_ssp_upright_040205_V5.fif : PCA-v5 (1 x 306)  idle
    Found the data of interest:
        t =     -50.92 ...     500.20 ms (Category # 1)
        0 CTF compensation matrices available
        nave = 61 - aspect type = 100
<ipython-input-2-05eba3f90d2f>:5: RuntimeWarning: This filename (c:\170207\hashizume_akira\041029\SEF_median_ave.fif) does not conform to MNE naming conventions. All evoked files should end with -ave.fif or -ave.fif.gz
  meg=mne.read_evokeds(filename,proj=True)[0] # リストですけど1個しかありません
Created an SSP operator (subspace dimension = 8)
8 projection items activated
SSP projectors applied...
No baseline correction applied
<Evoked  |  comment : 'Category # 1', kind : average, time : [-0.050918, 0.500198], n_epochs : 61, n_channels x n_times : 315 x 553, ~7.0 MB>
In [3]:
# 脳磁図波形の前処置
tmin,tmax=-0.05,0.1
def showwave(meg,tmin,tmax):
    meg.copy().crop(tmin=tmin,tmax=tmax).plot();

# 元波形
showwave(meg,tmin,tmax)

# 基線補正
meg.apply_baseline(baseline=(None,0))
showwave(meg,tmin,tmax)

# 2~100Hzの周波数フィルタ
x=meg.data
Fs=meg.info['sfreq']
mne.filter.band_pass_filter(x=x,Fs=Fs,Fp1=2,Fp2=100)
showwave(meg,tmin,tmax)
Applying baseline correction (mode: mean)
Setting up band-pass filter from 2 - 1e+02 Hz
l_trans_bandwidth chosen to be 2.0 Hz
h_trans_bandwidth chosen to be 25.0 Hz
Filter length of 3305 samples (3.300 sec) selected
filter_length (3305) is longer than the signal (553), distortion is likely. Reduce filter length or filter a longer signal.
C:\Users\akira\Anaconda2\lib\site-packages\mne\utils.py:638: DeprecationWarning: Function band_pass_filter is deprecated; band_pass_filter is deprecated and will be removed in 0.15, use filter_data instead.
  warnings.warn(msg, category=DeprecationWarning)
<ipython-input-3-eabd8c84a409>:16: RuntimeWarning: filter_length (3305) is longer than the signal (553), distortion is likely. Reduce filter length or filter a longer signal.
  mne.filter.band_pass_filter(x=x,Fs=Fs,Fp1=2,Fp2=100)

MNE-Cで以下のコマンドを入力します。
cd subject
mne_wathershed_bem --atlas
cd ./bem/watershed
mne_convert_surface --surf inner_skull_surface --surfout ../inner_skull.surf
mne_convert_surface --surf outer_skull_surface --surfout ../outer_skull.surf
mne_convert_surface --surf outer_skin_surface --surfout ../outer_skuk.surf

In [4]:
# FreeSurferで切り出して作成したメッシュの確認
# subjects_dir='H:\\FS'
subjects_dir='c:\\170207'
subject='hashizume_akira'
mne.viz.plot_bem(subject=subject,subjects_dir=subjects_dir,brain_surfaces='white',orientation='coronal');
Using surface: c:\170207\hashizume_akira\bem\inner_skull.surf
Using surface: c:\170207\hashizume_akira\bem\outer_skull.surf
Using surface: c:\170207\hashizume_akira\bem\outer_skin.surf
In [5]:
# センサと頭皮の座標合わせ
# mne_analyzeなどで座標合わせしてください
trans=subjects_dir+'\\'+subject+'\\041029\\041029-trans.fif'
In [6]:
# jupyterではうまく描画できません
# mne.viz.plot_trans(meg.info,trans,subject=subject,dig=True,meg_sensors=True,subjects_dir=subjects_dir);

python consoleでは以下の図が描画されます。


python console用です。
import mne
filename='c:\\170207\\hashizume_akira\\041029\\SEF_median_ave.fif'
trans=subjects_dir+'\\'+subject+'\\041029\\041029-trans.fif'
meg=mne.read_evokeds(filename,proj=True)[0]
subjects_dir='c:\\170207'
subject='hashizume_akira'
mne.viz.plot_trans(meg.info,trans,subject=subject,dig=True,meg_sensors=True,subjects_dir=subjects_dir);

In [7]:
# 格子点の設定
src=mne.setup_source_space(subject,spacing='oct6',subjects_dir=subjects_dir,add_dist=False,overwrite=True)
print(src)
Setting up the source space with the following parameters:

SUBJECTS_DIR = c:\170207
Subject      = hashizume_akira
Surface      = white
Octahedron subdivision grade 6

Parameters 'fname' and 'overwrite' are deprecated and will be removed in version 0.16. In version 0.15 fname will default to None. Use mne.write_source_spaces instead.
Overwriting existing file.
>>> 1. Creating the source space...

Doing the octahedral vertex picking...
Loading c:\170207\hashizume_akira\surf\lh.white...
Mapping lh hashizume_akira -> oct (6) ...
    Triangle neighbors and vertex normals...
<ipython-input-7-9a336d0bafdd>:2: RuntimeWarning: Parameters 'fname' and 'overwrite' are deprecated and will be removed in version 0.16. In version 0.15 fname will default to None. Use mne.write_source_spaces instead.
  src=mne.setup_source_space(subject,spacing='oct6',subjects_dir=subjects_dir,add_dist=False,overwrite=True)
Loading geometry from c:\170207\hashizume_akira\surf\lh.sphere...
    Triangle neighbors and vertex normals...
Setting up the triangulation for the decimated surface...
loaded lh.white 4098/160170 selected to source space (oct = 6)

Loading c:\170207\hashizume_akira\surf\rh.white...
Mapping rh hashizume_akira -> oct (6) ...
    Triangle neighbors and vertex normals...
Loading geometry from c:\170207\hashizume_akira\surf\rh.sphere...
    Triangle neighbors and vertex normals...
Setting up the triangulation for the decimated surface...
loaded rh.white 4098/162626 selected to source space (oct = 6)

Overwriting existing file.
    Write a source space...
    [done]
    Write a source space...
    [done]
    2 source spaces written
Wrote c:\170207\hashizume_akira\bem\hashizume_akira-oct-6-src.fif
You are now one step closer to computing the gain matrix
<SourceSpaces: [<surface (lh), n_vertices=160170, n_used=4098, coordinate_frame=MRI (surface RAS)>, <surface (rh), n_vertices=162626, n_used=4098, coordinate_frame=MRI (surface RAS)>]>

クラスSourceSpace srcを細かく見てみます。

In [8]:
print('src list: %d' %len(src))
print(src[0].keys())
print('nearest, dist, dist, dist_limit, pinfo, nearest_dist, patch_inds: None') # NoneType
print('nn: %d x %d' %src[0]['nn'].shape+ ' + %d x %d' %src[1]['nn'].shape)
print('rr: %d x %d' %src[0]['rr'].shape+ '+ %d x %d' %src[1]['rr'].shape)
print('inuse: %d' %src[0]['inuse'].shape+' + %d' %src[1]['inuse'].shape)
print('nuse: %d' %src[0]['nuse']+ ' + %d' %src[1]['nuse'])
print('vertno: %d' %len(src[0]['vertno'])+' + %d' %len(src[1]['vertno']))
print('nuse_tri: %d' %src[0]['nuse_tri']+' + %d' %src[1]['nuse_tri'])
print('coord_frame: %d' %src[0]['coord_frame'])
print('ntri: %d' %src[0]['ntri']+' + %d' %src[1]['ntri'])
print('np: %d' %src[0]['np']+' + %d' %src[1]['np'])
print('subject_his_id: '+src[0]['subject_his_id'])
print('use_tris: %d x %d' %src[0]['use_tris'].shape)
print('type: '+src[0]['type']+' + '+src[1]['type'])
print('id: %d + %d' %(src[0]['id'], src[1]['id']))
print('tris: %d x %d' %src[0]['tris'].shape +' + %d x %d' %src[1]['tris'].shape)
src list: 2
['nearest_dist', 'dist', 'use_tris', 'nearest', 'nuse', 'dist_limit', 'pinfo', 'nuse_tri', 'tris', 'patch_inds', 'nn', 'rr', 'inuse', 'vertno', 'id', 'coord_frame', 'subject_his_id', 'np', 'type', 'ntri']
nearest, dist, dist, dist_limit, pinfo, nearest_dist, patch_inds: None
nn: 160170 x 3 + 162626 x 3
rr: 160170 x 3+ 162626 x 3
inuse: 160170 + 162626
nuse: 4098 + 4098
vertno: 4098 + 4098
nuse_tri: 8192 + 8192
coord_frame: 5
ntri: 320336 + 325248
np: 160170 + 162626
subject_his_id: hashizume_akira
use_tris: 8192 x 3
type: surf + surf
id: 101 + 102
tris: 320336 x 3 + 325248 x 3

srcは本来
mne.write_source_spaces(subject-oct-6-src.fif)
で保存するですが、上mne.setup_source_spaceを実行するとsubject-oct-6-src.fifという名前で保存されています。

In [9]:
del(src)
# srcの読み込み
src_name=subjects_dir+'\\'+subject+'\\bem\\'+subject+'-oct-6-src.fif'
src=mne.read_source_spaces(src_name);
print(src)
    Reading a source space...
    [done]
    Reading a source space...
    [done]
    2 source spaces read
<SourceSpaces: [<surface (lh), n_vertices=160170, n_used=4098, coordinate_frame=MRI (surface RAS)>, <surface (rh), n_vertices=162626, n_used=4098, coordinate_frame=MRI (surface RAS)>]>
In [10]:
# 格子点の確認
mne.viz.plot_bem(subject=subject,subjects_dir=subjects_dir,brain_surfaces='white',src=src,orientation='coronal');
Using surface: c:\170207\hashizume_akira\bem\inner_skull.surf
Using surface: c:\170207\hashizume_akira\bem\outer_skull.surf
Using surface: c:\170207\hashizume_akira\bem\outer_skin.surf
In [11]:
# jupyterではうまく描画されません
import numpy as np
from mayavi import mlab
from surfer import Brain
#brain=Brain('hashizume_akira','lh','inflated',subjects_dir=subjects_dir);
#surf=brain._geo
vertidx=np.where(src[0]['inuse'])[0]
#mlab.points3d(surf.x[vertidx],surf.y[vertidx],surf.z[vertidx],color=(1,1,0),scale_factor=1.5);

python consoleでは以下の図になります。


python console用です
import numpy as np
from mayavi import mlab
from surfer import Brain
import mne
subject='hashizume_akira'
subjects_dir='c:\\170207'
brain=Brain(subject,'lh','inflated',subjects_dir=subjects_dir);
surf=brain._geo
src_name=subjects_dir+'\\'+subject+'\\bem\\'+subject+'-oct-6-src.fif'
src=mne.read_source_spaces(src_name);
vertidx=np.where(src[0]['inuse'])[0]
mlab.points3d(surf.x[vertidx],surf.y[vertidx],surf.z[vertidx],color=(1,1,0),scale_factor=1.5);

In [12]:
conductivity=(0.3,) # single layer
model=mne.make_bem_model(subject='hashizume_akira',ico=4,conductivity=conductivity,subjects_dir=subjects_dir)
print('model list: %d' %len(model))
print(model[0].keys())
print('nn: %d x %d' %model[0]['nn'].shape)
print('rr: %d x %d' %model[0]['rr'].shape)
print('coord_frame: %d' %model[0]['coord_frame'])
print('ntri: %d' %model[0]['ntri'])
print('np: %d' %model[0]['np'])
print('sigma: %0.2f' %model[0]['sigma'])
print('id: %d' %model[0]['id'])
print('tris: %d x %d' %model[0]['tris'].shape)
Creating the BEM geometry...
Going from 5th to 4th subdivision of an icosahedron (n_tri: 20480 -> 5120)
inner skull CM is   0.47 -14.61   5.56 mm
Surfaces passed the basic topology checks.
Complete.

model list: 1
['nn', 'rr', 'coord_frame', 'ntri', 'np', 'sigma', 'id', 'tris']
nn: 2562 x 3
rr: 2562 x 3
coord_frame: 5
ntri: 5120
np: 2562
sigma: 0.30
id: 1
tris: 5120 x 3

BEM surfaceのファイルの読み書きは以下の通りです

In [13]:
ntri=model[0]['ntri']
surface_fname=subject+'-%d-%d-%d-bem.fif' %(ntri, ntri, ntri)
mne.write_bem_surfaces(surface_fname,model)
del model
model=mne.read_bem_surfaces(surface_fname)
print('ntri: %d' %model[0]['ntri'])
    1 BEM surfaces found
    Reading a surface...
[done]
    1 BEM surfaces read
ntri: 5120
In [14]:
bem=mne.make_bem_solution(model)
print(bem)
Approximation method : Linear collocation

Homogeneous model surface loaded.
Computing the linear collocation solution...
    Matrix coefficients...
        inner_skull (2562) -> inner_skull (2562) ...
    Inverting the coefficient matrix...
Solution ready.
BEM geometry computations complete.
<ConductorModel  |  BEM (1 layer)>

クラスConductorModelのbemの中身を見てみます。

In [15]:
print(bem.keys())
print('nsol: %d' %bem['nsol'])
print('field_mult: %0.9f' %bem['field_mult'])
print('solution: %d x %d' %bem['solution'].shape)
print('is_sphere: False') #bem['is_sphere]
print('bem_method: %d' %bem['bem_method'])
print('soruce_mult: %0.9f' %bem['source_mult'])
print('sigma: %0.9f' %bem['sigma'])
print('gamma: %0.9f' %bem['gamma'])
print('surf list: %d' %len(bem['surfs']))
print(bem['surfs'][0].keys())
print('surf nn: %d x %d' %bem['surfs'][0]['nn'].shape)
print('surf rr: %d x %d' %bem['surfs'][0]['rr'].shape)
print('surf tri_cent: %d x %d' %bem['surfs'][0]['tri_cent'].shape)
print('surf neighbor_tri (list): %d' %len(bem['surfs'][0]['neighbor_tri']))
print('surf neighbor_tri[0] : %d' %len(bem['surfs'][0]['neighbor_tri'][0]))
print('surf tri_nn: %d x %d' %bem['surfs'][0]['tri_nn'].shape)
print('surf coord_frame: %d' %bem['surfs'][0]['coord_frame'])
print('surf ntri: %d' %bem['surfs'][0]['ntri'])
print('surf np: %d' %bem['surfs'][0]['np'])
print('surf sigma: %0.9f' %bem['surfs'][0]['sigma'])
print('surf id: %d' %bem['surfs'][0]['id'])
print('surf tris: %d x %d' %bem['surfs'][0]['tris'].shape)
print('surf tri_area: %d' %bem['surfs'][0]['tri_area'].shape)
['nsol', 'field_mult', 'solution', 'is_sphere', 'bem_method', 'source_mult', 'surfs', 'sigma', 'gamma']
nsol: 2562
field_mult: 0.300000012
solution: 2562 x 2562
is_sphere: False
bem_method: 2
soruce_mult: 6.666666402
sigma: 0.300000012
gamma: 1.000000000
surf list: 1
['nn', 'rr', 'tri_cent', 'neighbor_tri', 'tri_nn', 'coord_frame', 'ntri', 'np', 'sigma', 'id', 'tris', 'tri_area']
surf nn: 2562 x 3
surf rr: 2562 x 3
surf tri_cent: 5120 x 3
surf neighbor_tri (list): 2562
surf neighbor_tri[0] : 5
surf tri_nn: 5120 x 3
surf coord_frame: 5
surf ntri: 5120
surf np: 2562
surf sigma: 0.300000012
surf id: 1
surf tris: 5120 x 3
surf tri_area: 5120

modelの辞書にtri_cent, neighbor_tri, tri_nn, tri_areaが追加され、bemにsurfsという項目で追加されます。
クラスConductorModelのファイルの読み書きは以下の通りです。

In [16]:
ntri=bem['surfs'][0]['ntri']
bem_fname=subjects_dir+'\\'+subject+'\\bem\\'+subject+'-%d-%d-%d-bem-sol.fif' %(ntri,ntri,ntri)
mne.write_bem_solution(bem_fname,bem)
del bem
bem=mne.read_bem_solution(bem_fname)
Loading surfaces...
Homogeneous model surface loaded.

Loading the solution matrix...

Loaded linear_collocation BEM solution from c:\170207\hashizume_akira\bem\hashizume_akira-5120-5120-5120-bem-sol.fif
In [17]:
# 磁場計算行列 Lead field matrix の計算 
# megでなくmeg.infoです
fwd=mne.make_forward_solution(meg.info,trans=trans,src=src,bem=bem,fname=None,meg=True,eeg=False,mindist=5.0,n_jobs=3)
Source space                 : <SourceSpaces: [<surface (lh), n_vertices=160170, n_used=4098, coordinate_frame=MRI (surface RAS)>, <surface (rh), n_vertices=162626, n_used=4098, coordinate_frame=MRI (surface RAS)>]>
MRI -> head transform source : c:\170207\hashizume_akira\041029\041029-trans.fif
Measurement data             : instance of Info
BEM model                    : dict
Accurate field computations
Do computations in head coordinates
Free source orientations
Destination for the solution : None

Read 2 source spaces a total of 8196 active source locations

Coordinate transformation: MRI (surface RAS) -> head
     0.998602  0.051476  0.012051      -4.25 mm
    -0.052868  0.972310  0.227634      19.67 mm
     0.000000 -0.227953  0.973672      40.70 mm
     0.000000  0.000000  0.000000       1.00

Read 306 MEG channels from info
81 coil definitions read
Coordinate transformation: MEG device -> head
     0.997806 -0.066204 -0.000753      -6.05 mm
     0.066190  0.997208  0.034567      -4.23 mm
    -0.001538 -0.034541  0.999402      42.28 mm
     0.000000  0.000000  0.000000       1.00
MEG coil definitions created in head coordinates.
Source spaces are now in head coordinates.

Employing the head->MRI coordinate transform with the BEM model.
BEM model dict is now set up

Source spaces are in head coordinates.
Checking that the sources are inside the bounding surface and at least    5.0 mm away (will take a few...)
8 source space point omitted because of the    5.0-mm distance limit.
[Parallel(n_jobs=3)]: Done   3 out of   3 | elapsed:    4.5s remaining:    0.0s
[Parallel(n_jobs=3)]: Done   3 out of   3 | elapsed:    4.5s finished
1 source space point omitted because of the    5.0-mm distance limit.
Thank you for waiting.

Setting up compensation data...
    No compensation set. Nothing more to do.

Composing the field computation matrix...
[Parallel(n_jobs=3)]: Done   3 out of   3 | elapsed:    4.4s remaining:    0.0s
[Parallel(n_jobs=3)]: Done   3 out of   3 | elapsed:    4.4s finished
[Parallel(n_jobs=3)]: Done   3 out of   3 | elapsed:    3.1s remaining:    0.0s
[Parallel(n_jobs=3)]: Done   3 out of   3 | elapsed:    3.2s finished
Computing MEG at 8187 source locations (free orientations)...
[Parallel(n_jobs=3)]: Done   3 out of   3 | elapsed:    3.4s remaining:    0.0s
[Parallel(n_jobs=3)]: Done   3 out of   3 | elapsed:    3.4s finished
[Parallel(n_jobs=3)]: Done   3 out of   3 | elapsed:    3.2s remaining:    0.0s
[Parallel(n_jobs=3)]: Done   3 out of   3 | elapsed:    3.2s finished
Finished.
In [18]:
# fwdの中身
print(fwd)
print(fwd.keys())
print(fwd['info'])
print('sol_grad: None') #fwd['sol_grad'])
print('nchan: %d' %fwd['nchan'])
print('src: src') # print(fwd['src'])
print('source_nn: %d x %d' %fwd['source_nn'].shape)
print(fwd['sol'].keys())
print('sol row_names: %d' %len(fwd['sol']['row_names']))
print('sol ncol: %d' %fwd['sol']['ncol'])
print('sol data: %d x %d' %fwd['sol']['data'].shape)
print('sol col_names: []') #fwd['sol']['col_names']
print('sol nrow: %d' %fwd['sol']['nrow'])
print('source_rr: %d x %d' %fwd['source_rr'].shape)
print('_orig_sol_grad: None') #fwd['_orig_sol_grad'])
print('surf_ori: False') #fwd['surf_ori'])
print('coord_frame: %d' %fwd['coord_frame'])
print('source_ori: %d' %fwd['source_ori'])
print('_orig_sol: %d x %d' %fwd['_orig_sol'].shape)
print('mri_head_t: MRI (surface RAS)->head') #fwd['mri_head_t']
print('nsource: %d' %fwd['nsource'])
print('_orig_source_ori: %d' %fwd['_orig_source_ori'])
<Forward | MEG channels: 306 | EEG channels: 0 | Source space: Surface with 8187 vertices | Source orientation: Free>
['info', 'sol_grad', 'nchan', 'src', 'source_nn', 'sol', 'source_rr', '_orig_sol_grad', 'surf_ori', 'coord_frame', 'source_ori', '_orig_sol', 'mri_head_t', 'nsource', '_orig_source_ori']
<Info | 12 non-empty fields
    bads : list | 0 items
    ch_names : list | MEG 0113, MEG 0112, MEG 0111, MEG 0122, MEG 0123, ...
    chs : list | 306 items (GRAD: 204, MAG: 102)
    command_line : str | 322 items
    comps : list | 0 items
    dev_head_t : 'mne.transforms.Transform | 3 items
    meas_file : str | 16 items
    mri_file : str | 49 items
    mri_head_t : 'mne.transforms.Transform | 3 items
    mri_id : dict | 4 items
    nchan : int | 306
    working_dir : str | 14 items
    meas_id : NoneType
>
sol_grad: None
nchan: 306
src: src
source_nn: 24561 x 3
['row_names', 'ncol', 'data', 'col_names', 'nrow']
sol row_names: 306
sol ncol: 24561
sol data: 306 x 24561
sol col_names: []
sol nrow: 306
source_rr: 8187 x 3
_orig_sol_grad: None
surf_ori: False
coord_frame: 4
source_ori: 2
_orig_sol: 306 x 24561
mri_head_t: MRI (surface RAS)->head
nsource: 8187
_orig_source_ori: 2

Lead Field行列はfwd['sol']['data']です。
クラスForward fwdのファイルの読み書きは以下の通りです。
なお、フォルダをbemから脳磁図データのあるフォルダに変更しています。

In [19]:
fwd_fname=subjects_dir+'\\'+subject+'\\041029\\'+subject+'fwd'
mne.write_forward_solution(fwd_fname,fwd,overwrite=True)
del fwd
fwd=mne.read_forward_solution(fwd_fname)
print(fwd)
This filename (c:\170207\hashizume_akira\041029\hashizume_akirafwd) does not conform to MNE naming conventions. All forward files should end with -fwd.fif or -fwd.fif.gz
Overwriting existing file.
    Write a source space...
    [done]
    Write a source space...
    [done]
    2 source spaces written
<ipython-input-19-cb5d9814c2ca>:2: RuntimeWarning: This filename (c:\170207\hashizume_akira\041029\hashizume_akirafwd) does not conform to MNE naming conventions. All forward files should end with -fwd.fif or -fwd.fif.gz
  mne.write_forward_solution(fwd_fname,fwd,overwrite=True)
This filename (c:\170207\hashizume_akira\041029\hashizume_akirafwd) does not conform to MNE naming conventions. All forward files should end with -fwd.fif or -fwd.fif.gz
Reading forward solution from c:\170207\hashizume_akira\041029\hashizume_akirafwd...
    Reading a source space...
    [done]
    Reading a source space...
    [done]
    2 source spaces read
<ipython-input-19-cb5d9814c2ca>:4: RuntimeWarning: This filename (c:\170207\hashizume_akira\041029\hashizume_akirafwd) does not conform to MNE naming conventions. All forward files should end with -fwd.fif or -fwd.fif.gz
  fwd=mne.read_forward_solution(fwd_fname)
    Desired named matrix (kind = 3523) not available
    Read MEG forward solution (8187 sources, 306 channels, free orientations)
    Source spaces transformed to the forward solution coordinate frame
    Cartesian source orientations...
[done]
<Forward | MEG channels: 306 | EEG channels: 0 | Source space: Surface with 8187 vertices | Source orientation: Free>

定常状態の分散行列の作成にはRawやEpochが必要で、Evokedからは作れません。
そこでまずEvokedをRawArrayに変換します。次にSTI 001チャンネルにトリガー信号があり、これを利用して分散行列を計算します。その次にnumpy.cov()を使って分散行列を書き換えます。とりあえず計算できればいいということで細かいことは無視します。

In [20]:
# 雑音行列の計算
# RawArrayに変換
raw=mne.io.RawArray(meg.data,meg.info)
# RawArrayから分散行列計算 
noise_cov=mne.compute_raw_covariance(raw)
print(noise_cov.keys())
print('cov data: %d x %d' %noise_cov['data'].shape) # covは306x306の行列であることを確認
# -0.05~0.0秒の脳磁図出ただけを取り出す
meg0=meg.copy().pick_types(meg=True).crop(tmin=-0.05,tmax=0.0)

# -0.05~0.0の分散行列の計算
import numpy
cov2=numpy.cov(meg0.data)
print('cov2: %d x %d' %cov2.shape)
# del numpy # 以後module numpyを使わないとき

# 分散行列の書き換え
noise_cov['data']=cov2
Creating RawArray with float64 data, n_channels=315, n_times=553
Current compensation grade : 0
    Range : 0 ... 552 =      0.000 ...     0.551 secs
Ready.
Using up to 2 segments
Too few samples (required : 1535 got : 400), covariance estimate may be unreliable
Number of samples used : 400
[done]
['dim', 'kind', 'bads', 'projs', 'diag', 'names', 'eig', 'eigvec', 'data', 'nfree']
cov data: 306 x 306
cov2: 306 x 306
<ipython-input-20-988250cb5def>:5: RuntimeWarning: Too few samples (required : 1535 got : 400), covariance estimate may be unreliable
  noise_cov=mne.compute_raw_covariance(raw)
In [21]:
# 脳磁図波形と定常状態の関係など
meg.plot_white(noise_cov);
noise_cov.plot(raw.info,proj=True);
estimated rank (grad): 50
estimated rank (mag): 50
estimated rank (mag + grad): 50
    Created an SSP operator (subspace dimension = 8)
Setting small MEG eigenvalues to zero.
Not doing PCA for MEG.
    Created an SSP operator (subspace dimension = 8)

クラスCovarianceのnoise_covのファイルの読み書きは以下の通りです。

In [22]:
cov_fname=subjects_dir+'\\'+subject+'\\041029\\'+'SEF_median_ave-cov.fif'
mne.write_cov(cov_fname,noise_cov)
del noise_cov
noise_cov=mne.read_cov(cov_fname)
print('cov data: %d x %d' %noise_cov['data'].shape)
    306 x 306 full covariance (kind = 1) found.
    Read a total of 8 projection items:
        grad_ssp_upright_040205.fif : PCA-v1 (1 x 306) active
        grad_ssp_upright_040205.fif : PCA-v2 (1 x 306) active
        grad_ssp_upright_040205.fif : PCA-v3 (1 x 306) active
        mag_ssp_upright_040205_V5.fif : PCA-v1 (1 x 306) active
        mag_ssp_upright_040205_V5.fif : PCA-v2 (1 x 306) active
        mag_ssp_upright_040205_V5.fif : PCA-v3 (1 x 306) active
        mag_ssp_upright_040205_V5.fif : PCA-v4 (1 x 306) active
        mag_ssp_upright_040205_V5.fif : PCA-v5 (1 x 306) active
cov data: 306 x 306
In [23]:
inverse_operator=mne.minimum_norm.make_inverse_operator(meg.info,fwd,noise_cov,loose=0.2,depth=0.8)
    Converting to surface-based source orientations...
[done]
Computing inverse operator with 306 channels.
    Created an SSP operator (subspace dimension = 8)
estimated rank (mag + grad): 50
Setting small MEG eigenvalues to zero.
Not doing PCA for MEG.
Total rank is 50
Creating the depth weighting matrix...
    204 planar channels
    limit = 7750/8187 = 10.021672
    scale = 5.12915e-08 exp = 0.8
Computing inverse operator with 306 channels.
Creating the source covariance matrix
Applying loose dipole orientations. Loose value of 0.2.
Whitening the forward solution.
Adjusting source covariance matrix.
Computing SVD of whitened and weighted lead field matrix.
    largest singular value = 3.02518
    scaling factor to adjust the trace = 7.7764e+21
In [24]:
# inverse_operatorの中身
print(inverse_operator.keys())
print('nave: %0.9f' %inverse_operator['nave'])
print('methods: %d'%inverse_operator['methods'])
print('eigen_fields: [row_names, ncol, data, nrow, col_names]') #print(inverse_operator['eigen_fields'].keys())
print('eigen_leads_weighted: False') #print(inverse_operator['eigen_leads_weighted'])
print('fmri_prior: None') #print(inverse_operator['fmri_prior'])
print('orient_prior: [dim, kind, bads, projs, diag, nfree, eig, eigvec, data, names]') #print(inverse_operator['orient_prior'].keys())
print('mri_head_t: MRI (surface RAS->head)') #print(inverse_operator['mri_head_t'])
print('sing: %d' %inverse_operator['sing'].shape)
print('noise_cov: class Covariance')#print(inverse_operator['noise_cov'])
print('nsource: %d' %inverse_operator['nsource'])
print('info: class Info')
print('src: class SourceSpaces') #print(inverse_operator['src'])
print('source_cov: [dim, kind, bads, projs, diag, nfree, names, eig, data, eigvec]')# print(inverse_operator['source_cov'])
print('projs: class Projection')#print(inverse_operator['projs'])
print('source_nn: %d x %d' %inverse_operator['source_nn'].shape)
print('depth_prior: [dim, kind, bads, projs, diag, nfree, eig, eigvec, data, names]')#print(inverse_operator['depth_prior'])
print('source_ori: %d' %inverse_operator['source_ori'])
print('coord_frame: %d' %inverse_operator['coord_frame'])
print('units: Am') #print(inverse_operator['units'])
print('eigen_leads: [row_names, ncol, data,col_names, nrow]') #print(inverse_operator['eigen_leads'])
['nave', 'methods', 'eigen_fields', 'eigen_leads_weighted', 'fmri_prior', 'orient_prior', 'mri_head_t', 'sing', 'noise_cov', 'nsource', 'info', 'src', 'source_cov', 'projs', 'source_nn', 'depth_prior', 'source_ori', 'coord_frame', 'units', 'eigen_leads']
nave: 1.000000000
methods: 1
eigen_fields: [row_names, ncol, data, nrow, col_names]
eigen_leads_weighted: False
fmri_prior: None
orient_prior: [dim, kind, bads, projs, diag, nfree, eig, eigvec, data, names]
mri_head_t: MRI (surface RAS->head)
sing: 306
noise_cov: class Covariance
nsource: 8187
info: class Info
src: class SourceSpaces
source_cov: [dim, kind, bads, projs, diag, nfree, names, eig, data, eigvec]
projs: class Projection
source_nn: 24561 x 3
depth_prior: [dim, kind, bads, projs, diag, nfree, eig, eigvec, data, names]
source_ori: 2
coord_frame: 4
units: Am
eigen_leads: [row_names, ncol, data,col_names, nrow]

クラスInverseOperator inverse_operatorのファイルの読み書きは以下の通りです。

In [25]:
inverse_operator_fname=subjects_dir+'\\'+subject+'\\041029\\'+subject+'oct-6-inv.fif'
mne.minimum_norm.write_inverse_operator(inverse_operator_fname,inverse_operator)
del inverse_operator
inverse_operator=mne.minimum_norm.read_inverse_operator(inverse_operator_fname)
print(inverse_operator)
Write inverse operator decomposition in c:\170207\hashizume_akira\041029\hashizume_akiraoct-6-inv.fif...
    Write a source space...
    [done]
    Write a source space...
    [done]
    2 source spaces written
    Writing inverse operator info...
    Writing noise covariance matrix.
    Writing source covariance matrix.
    Writing orientation priors.
    [done]
Reading inverse operator decomposition from c:\170207\hashizume_akira\041029\hashizume_akiraoct-6-inv.fif...
    Reading inverse operator info...
    [done]
    Reading inverse operator decomposition...
    [done]
    306 x 306 full covariance (kind = 1) found.
    Read a total of 8 projection items:
        grad_ssp_upright_040205.fif : PCA-v1 (1 x 306) active
        grad_ssp_upright_040205.fif : PCA-v2 (1 x 306) active
        grad_ssp_upright_040205.fif : PCA-v3 (1 x 306) active
        mag_ssp_upright_040205_V5.fif : PCA-v1 (1 x 306) active
        mag_ssp_upright_040205_V5.fif : PCA-v2 (1 x 306) active
        mag_ssp_upright_040205_V5.fif : PCA-v3 (1 x 306) active
        mag_ssp_upright_040205_V5.fif : PCA-v4 (1 x 306) active
        mag_ssp_upright_040205_V5.fif : PCA-v5 (1 x 306) active
    Noise covariance matrix read.
    24561 x 24561 diagonal covariance (kind = 2) found.
    Source covariance matrix read.
    24561 x 24561 diagonal covariance (kind = 6) found.
    Orientation priors read.
    24561 x 24561 diagonal covariance (kind = 5) found.
    Depth priors read.
    Did not find the desired covariance matrix (kind = 3)
    Reading a source space...
    [done]
    Reading a source space...
    [done]
    2 source spaces read
    Read a total of 8 projection items:
        grad_ssp_upright_040205.fif : PCA-v1 (1 x 306) active
        grad_ssp_upright_040205.fif : PCA-v2 (1 x 306) active
        grad_ssp_upright_040205.fif : PCA-v3 (1 x 306) active
        mag_ssp_upright_040205_V5.fif : PCA-v1 (1 x 306) active
        mag_ssp_upright_040205_V5.fif : PCA-v2 (1 x 306) active
        mag_ssp_upright_040205_V5.fif : PCA-v3 (1 x 306) active
        mag_ssp_upright_040205_V5.fif : PCA-v4 (1 x 306) active
        mag_ssp_upright_040205_V5.fif : PCA-v5 (1 x 306) active
    Source spaces transformed to the inverse solution coordinate frame
<InverseOperator | MEG channels: 306 | EEG channels: 0 | Source space: Surface with 8187 vertices | Source orientation: Free>
In [26]:
method='dSPM'
snr=3.
lambda2=1./snr**2
stc=mne.minimum_norm.apply_inverse(meg,inverse_operator,lambda2,method=method,pick_ori=None)
print(stc)
Preparing the inverse operator for use...
    Scaled noise and source covariance from nave = 1 to nave = 61
    Created the regularized inverter
    Created an SSP operator (subspace dimension = 8)
    Created the whitener using a full noise covariance matrix (256 small eigenvalues omitted)
    Computing noise-normalization factors (dSPM)...
[done]
Picked 306 channels from the data
Computing inverse...
(eigenleads need to be weighted)...
combining the current components...
(dSPM)...
[done]
<SourceEstimate  |  8187 vertices, subject : hashizume_akira, tmin : -50.918401273 (ms), tmax : 500.198412505 (ms), tstep : 0.99840002496 (ms), data size : 8187 x 553>
In [27]:
# stcの中身
# print(dir(stc))
print('data: %d x %d' %stc.data.shape)
print('lh_data: %d x %d' %stc.lh_data.shape)
print('rh_data: %d x %d' %stc.rh_data.shape)
data: 8187 x 553
lh_data: 4090 x 553
rh_data: 4097 x 553

クラスSourceEstimateのファイルの読み書きは以下の通りです。
左右半球脳表別に保存され、ファイル名は-lh.stc、-rh.stcとなります。
尚、mne.write_source_estimateというmethodはありません。

In [28]:
stc_fname=subjects_dir+'\\'+subject+'\\041029\\SEF_median_ave'
# mne.write_source_estimate(stc_fname,stc) # このmethodはない
stc.save(stc_fname)
del stc
stc=mne.read_source_estimate(stc_fname)
print(stc)
Writing STC to disk...
[done]
<SourceEstimate  |  8187 vertices, tmin : -50.9183998108 (ms), tmax : 500.19841814 (ms), tstep : 0.99840003252 (ms), data size : 8187 x 553>
In [29]:
# 図示 8187本も書くと大変なので最大値だけ
import numpy
maxdata=numpy.max(stc.data,axis=0)

import matplotlib.pyplot as plt
%matplotlib inline
plt.plot(1e3*stc.times,maxdata);
plt.xlim([-50.,100.]);

10~30 msの最大値の場所・時間を求めます。両側半球で求めることはできません。左半球か、右半球か指定する必要があります。

In [30]:
vertino_max,time_max=stc.get_peak(hemi='lh',tmin=0.01,tmax=0.03)
clim=dict(kind='value',lims=[30,400,500])
In [31]:
# jupyterではうまく描画されず
#brain=stc.plot(subject=subject,surface='inflated',hemi='both',subjects_dir=subjects_dir,clim=clim,initial_time=time_max,time_unit='s');
#brain.add_foci(vertno_max,coords_as_verts=True,hemi='lh',color='blue',scale_factor=0.6);

python consoleでは以下の図となります。


python console用
import mne
subjects_dir='c:\\170207'
subject='hashizume_akira'
stc_fname=subjects_dir+'\\'+subject+'\\041029\\SEF_median_ave'
stc=mne.read_source_estimate(stc_fname)
vertno_max,time_max=stc.get_peak(hemi='lh',tmin=0.01,tmax=0.03)
clim=dict(kind='value',lims=[300,400,500])
brain=stc.plot(subject=subject,surface='inflated',hemi='both',subjects_dir=subjects_dir,clim=clim,initial_time=time_max,time_unit='s');
brain.add_foci(vertno_max,coords_as_verts=True,hemi='lh',color='blue',scale_factor=0.6);

surfaceをinflated以外にしてみました。

In [32]:
# jupyterではうまく描画されず
#brain=stc.plot(subject=subject,surface='white',hemi='both',subjects_dir=subjects_dir,clim=clim,initial_time=time_max,time_unit='s',);
#brain.add_foci(vertno_max,coords_as_verts=True,hemi='lh',color='blue',scale_factor=0.6);

python consoleでは以下の図になります。


python console用
import mne
subjects_dir='c:\\170207'
subject='hashizume_akira'
stc_fname=subjects_dir+'\\'+subject+'\\041029\\SEF_median_ave'
stc=mne.read_source_estimate(stc_fname)
vertno_max,time_max=stc.get_peak(hemi='lh',tmin=0.01,tmax=0.03)
clim=dict(kind='value',lims=[300,400,500])
brain=stc.plot(subject=subject,surface='white',hemi='both',subjects_dir=subjects_dir,clim=clim,initial_time=time_max,time_unit='s');
brain.add_foci(vertno_max,coords_as_verts=True,hemi='lh',color='blue',scale_factor=0.6);

In [33]:
# 単一電流双極子推定
meg1=meg.copy().pick_types(meg=True,eeg=False).crop(0.02,0.025)
dip=mne.fit_dipole(meg1,noise_cov,bem,trans)
BEM               : <ConductorModel  |  BEM (1 layer)>
MRI transform     : c:\170207\hashizume_akira\041029\041029-trans.fif
Head origin       :   -4.4    5.6   50.0 mm rad =   77.3 mm.
Guess grid        :   20.0 mm
Guess mindist     :    5.0 mm
Guess exclude     :   20.0 mm
Using standard MEG coil definitions.

Coordinate transformation: MRI (surface RAS) -> head
     0.998602  0.051476  0.012051      -4.25 mm
    -0.052868  0.972310  0.227634      19.67 mm
     0.000000 -0.227953  0.973672      40.70 mm
     0.000000  0.000000  0.000000       1.00
Coordinate transformation: MEG device -> head
     0.997806 -0.066204 -0.000753      -6.05 mm
     0.066190  0.997208  0.034567      -4.23 mm
    -0.001538 -0.034541  0.999402      42.28 mm
     0.000000  0.000000  0.000000       1.00
0 bad channels total
Read 306 MEG channels from info
81 coil definitions read
Coordinate transformation: MEG device -> head
     0.997806 -0.066204 -0.000753      -6.05 mm
     0.066190  0.997208  0.034567      -4.23 mm
    -0.001538 -0.034541  0.999402      42.28 mm
     0.000000  0.000000  0.000000       1.00
MEG coil definitions created in head coordinates.
Decomposing the sensor noise covariance matrix...

---- Computing the forward solution for the guesses...
Guess surface (inner_skull) is in MRI (surface RAS) coordinates
Filtering (grid =     20 mm)...
Surface CM = (   0.5  -14.6    5.6) mm
Surface fits inside a sphere with radius   99.6 mm
Surface extent:
    x =  -71.1 ...   72.4 mm
    y = -103.5 ...   82.9 mm
    z =  -73.0 ...   81.1 mm
Grid extent:
    x =  -80.0 ...   80.0 mm
    y = -120.0 ...  100.0 mm
    z =  -80.0 ...  100.0 mm
1080 sources before omitting any.
512 sources after omitting infeasible sources.
Source spaces are in MRI coordinates.
Checking that the sources are inside the bounding surface and at least    5.0 mm away (will take a few...)
262 source space points omitted because they are outside the inner skull surface.
42 source space points omitted because of the    5.0-mm distance limit.
Thank you for waiting.
208 sources remaining after excluding the sources outside the surface and less than    5.0 mm inside.
Go through all guess source locations...
[done 208 sources]
---- Fitted :    20.0 ms, distance to inner skull : 16.6390 mm
---- Fitted :    21.0 ms, distance to inner skull : 16.3368 mm
---- Fitted :    22.0 ms, distance to inner skull : 15.2480 mm
---- Fitted :    23.0 ms, distance to inner skull : 39.8824 mm
---- Fitted :    24.0 ms, distance to inner skull : 39.4703 mm
---- Fitted :    25.0 ms, distance to inner skull : 42.3617 mm
6 time points fitted
In [34]:
#print(dip)の中身
print('dip list: %d' %len(dip))
print('dip[0] list: %d' %len(dip[0])) # クラスDipole
print('dip[0][0]: [times,pos,amplitude,ori,gof,name]');
#print(dip[0][0].times)
#print(dip[0][0].pos)
#print(dip[0][0].amplitude)
#print(dip[0][0].ori)
#print(dip[0][0].gof)
#print(dip[0][0].name)
print('dip[1]: %d x %d' %dip[1].shape) # ndarray
dip list: 2
dip[0] list: 6
dip[0][0]: [times,pos,amplitude,ori,gof,name]
dip[1]: 306 x 6

クラスDipoleのdip[0]のファイルの読み書きは以下の通りです。

In [35]:
dip_fname=subjects_dir+'\\'+subject+'\\041029\\SEF_median_ave.dip'
dip[0].save(dip_fname)
del dip
dip=mne.read_dipole(dip_fname) # dip[0]ではない
print(dip)
6 dipole(s) found
<Dipole  |  n_times : 6, tmin : 0.02, tmax : 0.025>
In [36]:
dip.plot_amplitudes(color='k');
# dip2=dip.copy().crop(tmin=0.022,tmax=0.024) # cropが無効?
dip[2].plot_locations(trans,subject,subjects_dir,mode='orthoview');
In [37]:
# jupyterでは描画されず
# plot_locations()でsphere
# dip[2].plot_locations(trans,subject,subjects_dir,mode='cone');

python consoleでは以下の図になります。


python console用です。
import mne
trans='c:\\170207\\hashizume_akira\\041029\\041029-trans.fif'
subject='hashizume_akira'
subjects_dir='c:\\170207'
dip_fname=subjects_dir+'\\'+subject+'\\041029\\SEF_median_ave.dip'
dip=mne.read_dipole(dip_fname)
dip[2].plot_locations(trans,subject,subjects_dir,mode='cone');