SPMに関して、はまりやすい点とその解決法を雑学的に集めたものです。主にコマンドライン上でSPMの代表的な関数を利用する場合のコツを集めています。
(2015/03/31赤間啓之作成、書きかけ)
(質問)SPMを起動している時、SPMとは関係しないグラフ描画をしようと思ったら、SPMが邪魔して灰色になってしまいました。どうすればよいでしょうか?
(回答)SPMで計算した結果をSPMを使わないでfigure化したい場合もあるでしょう。しかし、その時、SPMをcloseするのを忘れていると、SPM8のGraphicsに白黒表示されてしまいます。色は後で変えられますが、resizeがうまくできない(私が知る限りにおいてですが)ので、ちょっと苦労します。SPM8が立ち上がっているとresize可能なFigureウィンドウが開かないのです。ですから描画データは一旦保存し、SPMを閉じてからMatlabを開きなおして再ロードしましょう。
save('result.mat','result');-->Matlabをexit-->Matlabを再起動-->result=importdata('result.mat');-->plotする(histとかplot, subplot)-->saveas(gcf,'hoge.fig');
(質問)大きなfMRIデータの計算をSPMで行っていたら、PCが止まってしまいました。どうしたらよいでしょうか。
(回答)SPMでFixed EffectAnalysisなどのGLMを行なう場合、データが大きすぎ、配列の保存ができなくなって、
「変数 'SPM' は Version 7.3 よりも古い MAT ファイルには保存できません。」
というエラーメッセージを出して止まってしまうことが多いです。
その時は、
Matlabでファイル-->設定-->一般MAT-ファイルでMATLAB version 7.3以降のラジオボタンを選択し、
spm_spm.m, spm_contrast.mの
save('SPM','SPM','-V6')
を手で
save('SPM','SPM','-V7.3')
に変更します。
(追記)SPM12では
%save('SPM.mat','SPM', spm_get_defaults('mat.format'));
とコメントアウトして
save('SPM.mat','SPM', '-v7.3');
を加える。
(質問)SPMでコマンドラインを用い、あるいは自作のスクリプトを書いて、fMRI画像中のvoxelsの賦活値を抜き出したり、条件に合ったvoxelsのindex情報を取得したり、賦活値を変更したりすることはできますか?
(回答)以下のようにすれば簡単にできます。
V=spm_vol('filename.img');%Analyze(あるいはNifti)ファイルを読み込む
ima=spm_read_vols(V);%各voelsの値を抜き出す。返ってくるのは3次元の配列
ima(ima>threshold)=1;
ima(ima<=threshold)=0;
%thresholdより大きい値は1、以下の値は0になります。
V.fname='newfilename.img';
spm_write_vol(V,ima);%新しい画像に保存します。
(質問)SPMでvoxelの配列index情報から対応するMNI座標をコマンドラインで求めたいのですが、どうすればよいでしょうか?
(回答)もちろん画像がnormaliseされているのが条件ですが、
voxel indexを[i j k]として、
Nii=nifti('hoge.img');
mni_coord = Nii.mat(1:3,:)*[i;j;k;1]
とすればよいです。
>> Nii=nifti('hoge.img');
>> Nii
Nii =
NIFTI object: 1-by-1
dat: [53x63x23 file_array]
mat: [4x4 double]
mat_intent: 'Aligned'
mat0: [4x4 double]
mat0_intent: 'Aligned'
descrip: 'spm - 3D normalized'
>> Nii.mat
ans =
-3 0 0 81
0 3 0 -115
0 0 6 -56
0 0 0 1
>> Nii.mat(1:3,:)
ans =
-3 0 0 81
0 3 0 -115
0 0 6 -56
>> i=15;j=21;k=8;
>> mni_coord = Nii.mat(1:3,:)*[i;j;k;1]
mni_coord =
36
-52
-8
のようになります。
逆にMNI座標からindexに戻したい場合は
x=[mni_coord;1]
invNii=inv(Nii.mat)
invNii*x %で[i;j;k;1]の値が求められますね。
(質問)SPMでコマンドライン上で基底関数の値を知りたいのですがどうすればよいでしょうか。
(回答)基底関数の表示の仕方は次のようなものです。
TR = 1; hrf = spm_hrf(TR); plot(0:TR:10, hrf(1:11))
TR = 1; hrf = spm_hrf(TR); plot(0:TR:32, hrf);
hrf =
0
0.0037
0.0433
0.1210
0.1875
0.2105
0.1926
0.1526
0.1081
0.0690
0.0385
0.0162
0.0008
-0.0093
-0.0153
-0.0182
-0.0187
-0.0175
-0.0154
-0.0129
-0.0103
-0.0079
-0.0058
-0.0042
-0.0029
-0.0020
-0.0013
-0.0008
-0.0005
-0.0003
-0.0002
-0.0001
-0.0001
(質問)SPMでniiファイルのヘッダを変更したいのですが、どうすればよいでしょうか。
(回答)P=spm_select(1,'nifti');
を実行するとWindowが開きますので、hdr, niiファイルを選択します。
Nii = nifti(P);
変数エディタからNiiを選択します。
(例)
val =
NIFTI object: 1-by-1
dat: [4-D file_array]
mat: [4x4 double]
mat_intent: 'Aligned'
mat0: [4x4 double]
mat0_intent: 'Aligned'
descrip: '4D image'
Nii =
NIFTI object: 1-by-1
dat: [53x63x23 file_array]
mat: [4x4 double]
mat_intent: 'Aligned'
mat0: [4x4 double]
mat0_intent: 'Aligned'
descrip: 'spm - 3D normalized'
% Change the relevant fields of Nii
create(Nii)
と言った形でできます。
(質問)SPMで3Dファイルを4Dにしたいのですが、どうすればよいでしょうか。
(回答)SPMには"3D to 4D File Conversion" toolがあります。
それ以外に、単にAnlyze形式のファイルをNiiにしたい場合は、
V=spm_vol('filename.img');
ima=spm_read_vols(V);
V.fname='filename.nii';
spm_write_vol(V,ima);
といったやり方があります。
(質問)SPMでFWHM(Full width at half maximum)について勉強したいのですが、どうすればよいでしょうか。
(回答)http://en.wikipedia.org/wiki/Full_width_at_half_maximum
などを参考に以下のスクリプトを理解すればよいでしょう。
%How to produce a Basis Function
peak=5;
%Peak of the haemodynamic response is found at 5 seconds after the stimulus onset.
fwhm=[4.0:0.1:7.0];
for j=1:size(fwhm,2) %size(fwhm,2)=31
hrf=[];
for time=0:20
beta=fwhm(1,j)^2/peak/8/log(2);
alpha=peak^2/fwhm(1,j)^2*8*log(2);
gamma=(time/peak).^alpha.*exp(-(time-peak)./beta);
hrf=[hrf,gamma];
end
end
plot(0:20,hrf)
(質問)3次元配列からそれを冠状面の脳画像として表示するるMATLABスクリプトを教えてください。
(回答)以下を、 imagesc_coronal_lr.mとして保存し、MATLAB上で関数として使ってみてください。
%%%%
function img = imagesc_coronal_lr(threeDarray, slicenum)
if(size(size(threeDarray),2)~=3)
error('imagesc_coronal.m:The first argument should be a three dimensional array.');
end
if(slicenum>size(threeDarray,2))
error('imagesc_coronal.m:The slice number you assigned is too large.');
end
image_source=flipud(transpose(permute(threeDarray(:,slicenum,:), [1 3 2])));
subplot(1,2,1)
%The first row first column image number 1.
imagesc(image_source);
axis image
title(strcat('Coronal slice: ', num2str(slicenum)))
subplot(1,2,2)
%The first row second column image number 2.
imagesc(fliplr(image_source));
axis image
title(strcat('Mirror-reverse coronal slice: ', num2str(slicenum)))
%%%
(質問)SPMではバッチファイルはどのように書いたらよいでしょう。
(回答)どこにでも書いてありますが、以下のようなテンプレートに従って書けばよいです。
spm('defaults','fmri');
spm_jobman('initcfg');
matlabbatch{1}.spm... = ...;
spm_jobman('run',matlabbatch);
(質問)SPMで画像に対し、matファイルでGUIベースのbatch処理ではなく、mファイルにして、ファイルを選ぶとき、複雑な正規表現を入れたり、文字列を入れた変数を使ってstrcat()の結果を受け渡したりしたいのですが、どうしたら良いですか。
(回答)上記のようなスクリプトに、以下のようなコードを埋め込めば良いです。これ以外の方法はすべて失敗でした。
例
celldata={
nii, imgなどの画像名を示す、文字列を入れた変数、正規表現などを含む式
nii, imgなどの画像名を示す、文字列を入れた変数、正規表現などを含む式
nii, imgなどの画像名を示す、文字列を入れた変数、正規表現などを含む式
...
nii, imgなどの画像名を示す、文字列を入れた変数、正規表現などを含む式
}
datatoberead= [celldata{:}]';%一括して内容にアクセスして[]でansがばらばらにならぬよう集めて転置し、それをさらに変数に入れる、これが最大のTIPSです。
matlabbatch{1}.spm.util.cat.vols = datatoberead;%ふつうここに直接画像ファイル名を集めたセル配列が入る