FreeSurferのfile format

mriのT1.mgz. 1

surfのlh.pial 1

surfのlh.curv.pial 1

 

何故かbig endianです。

mriT1.mgz

以下を実行します。

mgh=gunzip(filename);

fid=fopen(mgh{1},'rb');

B=fread(fid,'*uint8');

fclose(fid);

delete(mgh{1});

F=[];

k=1:28;

x=swapbytes(typecast(B(k),'int32'));

F.version=x(1);

F.width=x(2);

F.height=x(3);

F.depth=x(4);

F.nframes=x(5);

F.type=x(6);% 0 uint8 1 int32 3 single 4 int16

switch F.type

    case 0;fmt='uint8';fbyte=1;

    case 1;fmt='int32';fbyte=4;

    case 3;fmt='single';fbyte=4;

    case 4;fmt='int16';fbyte=2;

end

F.dof=x(7);% degree of freedom

k=29:30;

F.goodRASFlag=swapbytes(typecast(B(k),'int16'));

k=31:90;

x=swapbytes(typecast(B(k),'single'));

F.spacingx=x(1);

F.spacingy=x(2);

F.spacingz=x(3);

F.xr=x(4);%RAS right anterior superior

F.xa=x(5);

F.xs=x(6);

F.yr=x(7);

F.ya=x(8);

F.ys=x(9);

F.zr=x(10);

F.za=x(11);

F.zs=x(12);

F.cr=x(13);

F.ca=x(14);

F.cs=x(15);

F

k=91:284;

B(k)'

k=284+(1:F.width*F.height*F.depth*fbyte);

F.data=swapbytes(typecast(B(k),fmt));

F.data=reshape(F.data,[F.width,F.height,F.depth]);

k=284+F.width*F.height*F.depth*fbyte;

[k,length(B),length(B)-k]

284byteまでがヘッダーです。Analyze formatみたいです。その後3次元画像データ部分になります。さらにその次があるのですが、よくわかりません。なくても大丈夫のようです。

ヘッダー部分、284byteあるんですが、ほとんど使用されてないので91284 byteはゼロになっています。

r,a,sは右、前、上の略です。

結果です。

F =

 

  フィールドをもつ struct:

 

        version: 1

          width: 256

         height: 256

          depth: 256

        nframes: 1

           type: 0

            dof: 0

    goodRASFlag: 1

       spacingx: 1

       spacingy: 1

       spacingz: 1

             xr: -1

             xa: 0

             xs: 0

             yr: 0

             ya: 0

             ys: -1

             zr: 0

             za: 1

             zs: 0

             cr: 0

             ca: 12.4000

             cs: 19

 

 

ans =

 

  1×194 uint8 行ベクトル

 

  1 列から 28

 

   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0

 

  29 列から 56

 

   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0

 

  57 列から 84

 

   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0

 

  85 列から 112

 

   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0

 

  113 列から 140

 

   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0

 

  141 列から 168

 

   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0

 

  169 列から 194

 

   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0

 

 

ans =

 

  1×3 int32 行ベクトル

 

   16777500   16790218      12718

 

>> 

読み込んだ画像を表示させてみます。

figure;

subplot(131);

imagesc(squeeze(F.data(round(F.width/2),:,:)));

daspect([F.spacingy,F.spacingz,F.spacingx]);

subplot(132);

imagesc(squeeze(F.data(:,round(F.height/2),:)));

daspect([F.spacingz,F.spacingx,F.spacingy]);

subplot(133);

imagesc(squeeze(F.data(:,:,round(F.depth/2))));

colormap(gray(256));

daspect([F.spacingx,F.spacingy,F.spacingz]);

結果です。

データ領域意向をナシにしたファイルを作成しました。

matlabgzipで圧縮、gunzipで解凍となります。拡張子が.mgh.gzとなりますが、movefileでファイル名を.mgzに変更しています。

savename=[filename(1:end-4),'s.mgh'];

fid=fopen(savename,'wb');

fwrite(fid,B(1:(284+F.width*F.height*F.depth*fbyte)),'uint8');

fclose(fid);

gzip(savename);

movefile([savename,'.gz'],[savename(1:end-1),'z']);

delete(savename);

FreeSurfer6freeviewで見てみました。

FreeSurfer6tkmeditで開いてみました。

データ領域部分以降がなくてもちゃんと認識されました。

 

surflh.pial

以下を実行します。

filename='c:\akira\surf\lh.pial';

fid=fopen(filename,'rb');

B=fread(fid,'*uint8');

fclose(fid);

k=1:3;

B(k)'

for kk=1:(length(B)-1)

    if B(kk)==10

        if B(kk+1)==10

            break;

        end

    end

end

kk=kk+1;

k=4:kk;

char(B(k))'

 

k=kk+(1:4);

n_vertices=swapbytes(typecast(B(k),'int32'))

k=kk+4+(1:4);

n_faces=swapbytes(typecast(B(k),'int32'))

k=kk+8+(1:(n_vertices*4*3));

vertices=swapbytes(typecast(B(k),'single'));

vertices=reshape(vertices,[3,n_vertices]);

k=kk+8+n_vertices*4*3+(1:(n_faces*4*3));

faces=swapbytes(typecast(B(k),'int32'));

faces=reshape(faces,[3,n_faces]);

[length(B),58+n_vertices*3*4+n_faces*3*4]

いろいろ試行錯誤して得た結果です。

big endianになっています。

最初はuint8 3byte255 255 254

次の4kk byteはテキスト文です。作者によってバイト数が変化します。

kkのところは10,10の改行コードです。

次はint32 頂点数、int32 面数です。

次はsingle3×頂点数で頂点の座標、

次はint323×面数で三角メッシュの組み合わせです。0,1,2・・・の順番ですので、MATLABでは1を足して1,2,3・・・とします。

最後はテキスト文です。

ans =

 

  1×3 uint8 行ベクトル

 

   255   255   254

 

 

ans =

 

    'created by centos on Thu Jun  6 04:29:29 2013

    

     '

 

 

n_vertices =

 

  int32

 

   160170

 

 

n_faces =

 

  int32

 

   320336

 

 

ans =

 

  1×2 int32 行ベクトル

 

   5767430   5766130

左皮髄境界を表示します。

figure;

faces1=faces+1;

h=patch('vertices',vertices','faces',faces1');

set(h,'edgecolor','none','facecolor',[1,1,0]);

view([-120,20]);

light('position',[0,0,1]);

daspect([1,1,1]);

rotate3d on;

 

残りのテキスト文です。なくても問題ないようです。

k=(kk+8+n_vertices*3*4+n_faces*3*4+1):length(B);

char(B(k))'

結果です。

>> 

ans =

 

    '   [1]       valid = 1  # volume info valid

     filename = ../mri/filled-pretess255.mgz

     volume = 256 256 256

     voxelsize = 1.000000000000000e+00 1.000000000000000e+00 1.000000000000000e+00

     xras   = -1.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00

     yras   = 0.000000000000000e+00 0.000000000000000e+00 -1.000000000000000e+00

     zras   = 0.000000000000000e+00 1.000000000000000e+00 0.000000000000000e+00

     cras   = 0.000000000000000e+00 1.240000915527344e+01 1.900000000000000e+01

       


      ƒmris_remove_intersection ../surf/lh.orig ../surf/lh.orig ProgramVersion: $Name: stable5 $  TimeStamp: 2013/06/05-17:37:26-GMT  BuildTimeStamp: May 22 2011 08:23:31  CVS: $Id: mris_remove_intersection.c,v 1.6 2011/03/02 00:04:32 nicks Exp $  User: centos  Machine: localhost.localdomain  Platform: Linux  PlatformVersion: 2.6.32-71.el6.x86_64  CompilerName: GCC  CompilerVersion: 30400     
     
mris_make_surfaces -white NOWRITE -mgz -T1 brain.finalsurfs hashizume_akira lh ProgramVersion: $Name: stable5 $  TimeStamp: 2013/06/05-19:20:06-GMT  BuildTimeStamp: May 22 2011 08:23:31  CVS: $Id: mris_make_surfaces.c,v 1.127 2011/03/02 00:04:33 nicks Exp $  User: centos  Machine: localhost.localdomain  Platform: Linux  PlatformVersion: 2.6.32-71.el6.x86_64  CompilerName: GCC  CompilerVersion: 30400   '

 

>> 

 

なおGIfTIからmris_convertで変換したときは

    '   [1]       valid = 0  # volume info invalid

     filename =

     volume = 0 0 0

     voxelsize = 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00

     xras   = 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00

     yras   = 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00

     zras   = 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00

     cras   = 0.000000000000000e+00 0.000000000000000e+00 0.000000000000000e+00

     '

となります。

テキスト文なしのファイルを作成してみます。

kk=1:(58+n_vertices*3*4+n_faces*3*4);

savename=[filename,'s'];

fid=fopen(savename,'wb');

fwrite(fid,B(kk),'uint8');

fclose(fid);

FreeSurfer6freeviewで読み込ませてみました。

FreeSurfer6tksurferで読み込ませてみました。

テキスト部分がなくてもちゃんと開きました。

 

surflh.curv.pial

メッシュにはcurv曲率?があります。lh/rh.whitelh/rh.inflatedlh/rh.curvlh/rh.piallh/rh.curv.pialが対応しています。以下を実行します。

filename='c:\akira\surf\lh.curv.pial';

fid=fopen(filename,'rb');

B=fread(fid,'*uint8');

fclose(fid);

k=1:3;

B(k)'

k=3+(1:4);

n_vertices=swapbytes(typecast(B(k),'int32'))

k=7+(1:4);

n_faces=swapbytes(typecast(B(k),'int32'))

k=11+(1:4);

n_=swapbytes(typecast(B(k),'int32'))

k=15+(1:(n_vertices*4));

curv=swapbytes(typecast(B(k),'single'));

size(curv)

[length(B),k(end)]

いろいろ試行錯誤して得た結果です。

big endianになっています。

最初はuint8 3byte255 255 255

次はint32 頂点数、int32 面数、int32 何か?で、

最後がsingle 曲率×頂点数となっています。

ans =

 

  1×3 uint8 行ベクトル

 

   255   255   255

 

 

n_vertices =

 

  int32

 

   160170

 

 

n_faces =

 

  int32

 

   320336

 

 

n_ =

 

  int32

 

   1

 

 

ans =

 

      160170           1

 

 

ans =

 

  1×2 int32 行ベクトル

 

   640695   640695

以下を実行します。

figure;

faces1=faces+1;

sulcus=curv;

h=trimesh(faces1',vertices(1,:),vertices(2,:),vertices(3,:),sulcus);

set(h,'facecolor','interp');

set(gca,'clim',[-1,1]*0.2);

colormap(jet(256));

daspect([1,1,1]);

view([-120,20]);

colorbar('veretical');

lh.inflatedlh.curvを使って、mne_analyzeの画像を作成してみました。

filename='c:\akira\surf\lh.inflated';

fid=fopen(filename,'rb');

B=fread(fid,'*uint8');

fclose(fid);

for kk=1:(length(B)-1)

    if B(kk)==10

        if B(kk+1)==10

            break;

        end

    end

end

 

kk=kk+1;

k=kk+(1:4);

n_vertices=swapbytes(typecast(B(k),'int32'));

k=kk+4+(1:4);

n_faces=swapbytes(typecast(B(k),'int32'));

k=kk+8+(1:(n_vertices*4*3));

vertices=swapbytes(typecast(B(k),'single'));

vertices=reshape(vertices,[3,n_vertices]);

k=kk+8+n_vertices*4*3+(1:(n_faces*4*3));

faces=swapbytes(typecast(B(k),'int32'));

faces=reshape(faces,[3,n_faces]);

 

filename='c:\akira\surf\lh.curv';

fid=fopen(filename,'rb');

B=fread(fid,'*uint8');

fclose(fid);

k=3+(1:4);

n_vertices=swapbytes(typecast(B(k),'int32'));

k=7+(1:4);

n_faces=swapbytes(typecast(B(k),'int32'));

k=11+(1:4);

n_=swapbytes(typecast(B(k),'int32'));

k=15+(1:(n_vertices*4));

curv=swapbytes(typecast(B(k),'single'));

 

figure;

faces1=faces+1;

sulcus=curv;

h=trimesh(faces1',vertices(1,:),vertices(2,:),vertices(3,:),sulcus);

set(h,'facecolor','interp');

set(gca,'clim',[-1,1]*0.5);

map=flipud(gray(2)*0.5)+0.25;

colormap(map);

daspect([1,1,1]);

view([-120,20]);

colorbar('veretical');

このlh.curvrh.curvがないとmne_analyzeinflatedwhiteを開くと

となります。lh.curvrh.curvがあると

となります。pialの場合は、あんまり関係ないみたいです。lh.curvrh.curvlh.curv.pialrh.curv.pialがないときです。

lh.curv.pialrh.curv.pialがあるときです。違いはわかりません。