diff --git a/README.txt b/README.txt
new file mode 100644
index 0000000..e69de29
diff --git a/mpi_code/AGLOGO_MACAQUE_DTI.xlsx b/mpi_code/AGLOGO_MACAQUE_DTI.xlsx
new file mode 100644
index 0000000..f905a66
Binary files /dev/null and b/mpi_code/AGLOGO_MACAQUE_DTI.xlsx differ
diff --git a/mpi_code/mex_anz/ANALYZE75.pdf b/mpi_code/mex_anz/ANALYZE75.pdf
new file mode 100644
index 0000000..97683de
Binary files /dev/null and b/mpi_code/mex_anz/ANALYZE75.pdf differ
diff --git a/mpi_code/mex_anz/Analyze_usage.pdf b/mpi_code/mex_anz/Analyze_usage.pdf
new file mode 100644
index 0000000..5b8a8e6
Binary files /dev/null and b/mpi_code/mex_anz/Analyze_usage.pdf differ
diff --git a/mpi_code/mex_anz/Contents.m b/mpi_code/mex_anz/Contents.m
new file mode 100644
index 0000000..ad9382d
--- /dev/null
+++ b/mpi_code/mex_anz/Contents.m
@@ -0,0 +1,23 @@
+% UTILS/MEX_ANZ
+% This direcotry contains utility functions to handle ANALYZE-7 format.
+%
+% SCRIPTS :
+% bru2spm - dumps Brucker 2dseq as ANALYZE-7 format for SPM.
+% anz_read - reads ANALYZE iamge/header.
+% anz_write - writes ANALYZE image/header.
+% hdr_init - initializes ANALIZE(TM) header structure.
+% hdr_read - reads ANALYZE header.
+% hdr_write - create a ANALYZE header file.
+% mexanz - creates mex programs.
+%
+% MEX :
+% swapbytes - swaps bytes of given data.
+%
+% INFO :
+% ANALYZE75.pdf - description for ANALYZE-7 header format.
+%
+% VERSION :
+% 0.90 06.06.05 YM
+% 0.91 11.10.07 YM update contents.m
+%
+% See also SPM2
diff --git a/mpi_code/mex_anz/anz_read.m b/mpi_code/mex_anz/anz_read.m
new file mode 100644
index 0000000..62fbaa7
--- /dev/null
+++ b/mpi_code/mex_anz/anz_read.m
@@ -0,0 +1,97 @@
+function [IMG HDR] = anz_read(filename)
+%ANZ_READ - reads ANALYZE image/header
+% [IMG HDR] = ANZ_READ(IMGFILE) reads ANALYZE(TM) image.
+%
+% VERSION :
+% 0.90 12.01.07 YM pre-release
+% 0.91 28.02.07 YM use uigetfile()
+% 0.92 06.08.07 YM bug fix when big-endian
+% 0.93 07.04.08 YM filename can be as .raw
+%
+% See also ANZ_WRITE HDR_READ UTLSWAPBYTES
+
+if nargin == 0 & nargout == 0, help anz_read; return; end
+
+IMG = []; HDR = [];
+if ~exist('filename','var'), filename = ''; end
+
+if isempty(filename),
+ [tmpf,tmpp] = uigetfile({'*.img;*.hdr','ANALYZE data (*.img/*hdr)';'*.*','All Files (*.*)'},...
+ 'Pick an ANALYZE file');
+ if tmpf == 0, return; end
+ filename = fullfile(tmpp,tmpf);
+ clear tmpf tmpp;
+end
+
+[fp,fr,fe] = fileparts(filename);
+
+if strcmpi(fe,'.hdr'),
+ % filename as 'header' file.
+ imgfile = fullfile(fp,sprintf('%s.img',fr));
+else
+ % filename as 'image' file, can be like *.raw or so.
+ imgfile = fullfile(fp,sprintf('%s%s',fr,fe));
+end
+hdrfile = fullfile(fp,sprintf('%s.hdr',fr));
+
+
+if ~exist(hdrfile,'file'),
+ error('%s: ''%s'' not found.',mfilename,hdrfile);
+end
+
+HDR = hdr_read(hdrfile);
+if isempty(HDR), return; end
+
+% checks need to swap bytes or not
+fid = fopen(hdrfile,'r');
+hsize = fread(fid, 1, 'int32=>int32');
+fclose(fid);
+if hsize > hex2dec('01000000'),
+ SWAP_BYTES = 1;
+else
+ SWAP_BYTES = 0;
+end
+
+
+if ~exist(imgfile,'file'),
+ error('%s: ''%s'' not found.',mfilename,imgfile);
+end
+
+% /* Acceptable values for datatype */
+% #define DT_NONE 0
+% #define DT_UNKNOWN 0
+% #define DT_BINARY 1
+% #define DT_UNSIGNED_CHAR 2
+% #define DT_SIGNED_SHORT 4
+% #define DT_SIGNED_INT 8
+% #define DT_FLOAT 16
+% #define DT_COMPLEX 32
+% #define DT_DOUBLE 64
+% #define DT_RGB 128
+% #define DT_ALL 255
+fid = fopen(imgfile,'rb');
+if HDR.dime.datatype == 2,
+ IMG = fread(fid,inf,'uint8=>uint8');
+elseif HDR.dime.datatype == 4,
+ IMG = fread(fid,inf,'int16=>int16');
+ if SWAP_BYTES > 0, IMG = utlswapbytes(IMG); end
+elseif HDR.dime.datatype == 8,
+ IMG = fread(fid,inf,'int32=>int32');
+ if SWAP_BYTES > 0, IMG = utlswapbytes(IMG); end
+elseif HDR.dime.datatype == 16,
+ IMG = fread(fid,inf,'float=>float');
+ if SWAP_BYTES > 0, IMG = utlswapbytes(IMG); end
+elseif HDR.dime.datatype == 64,
+ IMG = fread(fid,inf,'double=>double');
+else
+ fprintf('\n %s: unsupported datatype(=%d).\n',mfilename,HDR.dime.datatype);
+ IMG = NaN(HDR.dime.dim([1:HDR.dime.dim(1)]+1));
+end
+fclose(fid);
+
+
+IMG = reshape(IMG,HDR.dime.dim([1:HDR.dime.dim(1)]+1));
+
+
+
+return
diff --git a/mpi_code/mex_anz/anz_view.m b/mpi_code/mex_anz/anz_view.m
new file mode 100644
index 0000000..3ad5567
--- /dev/null
+++ b/mpi_code/mex_anz/anz_view.m
@@ -0,0 +1,1129 @@
+function varargout = anz_view(varargin)
+%ANZ_VIEW - displays ANALYZE format images
+% ANZ_VIEW(IMGFILE,...) displays ANALYZE format images.
+%
+% EXAMPLE :
+% >> anz_view('');
+% >> anz_view('D99_T1weighted.img');
+%
+% VERSION :
+% 0.90 02.05.08 YM pre-release
+% 0.91 05.05.08 YM improved memory usage
+%
+% See also anz_read anz_write
+
+if nargin == 0, help anz_view; return; end
+
+% execute callback function then return;
+if ischar(varargin{1}) & ~isempty(findstr(varargin{1},'Callback')),
+ if nargout
+ [varargout{1:nargout}] = feval(varargin{:});
+ else
+ feval(varargin{:});
+ end
+ return;
+end
+
+
+% DEFAULT CONTROL SETTINGS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% ANAP.anz_view.xxxx
+ANAP.anz_view.anascale = [];
+ANAP.anz_view.colormap = 'gray';
+ANAP.anz_view.xreverse = 0;
+ANAP.anz_view.yreverse = 0;
+ANAP.anz_view.zreverse = 1;
+
+IMGFILE = varargin{1};
+for N = 2:2:length(varargin),
+ switch lower(varargin{N}),
+ case {'anascale','scale'}
+ ANAP.anz_view.anascale = varargin{N+1};
+ case {'cmap','colormap','color'}
+ ANAP.anz_view.colormap = varargin{N+1};
+ case {'xreverse'}
+ ANAP.anz_view.xreverse = varargin{N+1};
+ case {'yreverse'}
+ ANAP.anz_view.yreverse = varargin{N+1};
+ case {'zreverse'}
+ ANAP.anz_view.zreverse = varargin{N+1};
+ end
+end
+
+
+% GET SCREEN SIZE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+oldunits = get(0,'units');
+set(0,'units','char');
+SZscreen = get(0,'ScreenSize');
+set(0,'units',oldunits);
+scrW = SZscreen(3); scrH = SZscreen(4);
+
+figW = 175; figH = 55;
+figX = 31; figY = scrH-figH-5;
+
+%[figX figY figW figH]
+
+
+% CREATE A MAIN FIGURE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+hMain = figure(...
+ 'Name',sprintf('%s: %s',mfilename,datestr(now)),...
+ 'NumberTitle','off', 'toolbar','figure',...
+ 'Tag','main', 'units','char', 'pos',[figX figY figW figH],...
+ 'HandleVisibility','on', 'Resize','on',...
+ 'DoubleBuffer','on', 'BackingStore','on', 'Visible','on',...
+ 'DefaultAxesFontSize',10,...
+ 'DefaultAxesFontName', 'Comic Sans MS',...
+ 'DefaultAxesfontweight','bold',...
+ 'PaperPositionMode','auto', 'PaperType','A4', 'PaperOrientation', 'landscape');
+
+
+
+% WIDGETS TO ANALYZE FILE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+XDSP = 10; H = figH - 2.5;
+AnzFileTxt = uicontrol(...
+ 'Parent',hMain,'Style','Text',...
+ 'Units','char','Position',[XDSP H-0.3 30 1.5],...
+ 'String','FILE:','FontWeight','bold',...
+ 'HorizontalAlignment','left',...
+ 'Tag','AnzFileTxt',...
+ 'BackgroundColor',get(hMain,'Color'));
+AnzFileEdt = uicontrol(...
+ 'Parent',hMain,'Style','Edit',...
+ 'Units','char','Position',[XDSP+8 H 96 1.5],...
+ 'Callback','anz_view(''Main_Callback'',gcbo,''init'',guidata(gcbo))',...
+ 'String',IMGFILE,'Tag','AnzFileEdt',...
+ 'HorizontalAlignment','left',...
+ 'TooltipString','ANALYZE file',...
+ 'FontWeight','Bold');
+AnzReadBtn = uicontrol(...
+ 'Parent',hMain,'Style','PushButton',...
+ 'Units','char','Position',[XDSP+105 H 15 1.5],...
+ 'Callback','anz_view(''Main_Callback'',gcbo,''browse-file'',guidata(gcbo))',...
+ 'Tag','AnzReadBtn','String','Browse...',...
+ 'TooltipString','browse a ANALYZE file','FontWeight','Bold');
+% AnzSaveBtn = uicontrol(...
+% 'Parent',hMain,'Style','PushButton',...
+% 'Units','char','Position',[XDSP+106 H 15 1.5],...
+% 'Callback','anz_view(''Main_Callback'',gcbo,''save-file'',guidata(gcbo))',...
+% 'Tag','AnzSaveBtn','String','Save...',...
+% 'TooltipString','save a ANALYZE file','FontWeight','Bold');
+
+cmaps = {'gray','jet','autumn','hot','cool','bone','copper','pink','red','green','blue','yellow'};
+idx = find(strcmpi(cmaps,ANAP.anz_view.colormap));
+if isempty(idx),
+ fprintf('WARNING %s: unknown colormap name ''%s''.\n',mfilename,ANAP.mview.colormap);
+ idx = 1;
+end
+ColormapCmb = uicontrol(...
+ 'Parent',hMain,'Style','Popupmenu',...
+ 'Units','char','Position',[XDSP+123 H 15 1.5],...
+ 'Callback','anz_view(''Main_Callback'',gcbo,''update-cmap'',guidata(gcbo))',...
+ 'String',cmaps,'Value',idx,'Tag','ColormapCmb',...
+ 'TooltipString','Select colormap',...
+ 'FontWeight','bold');
+clear cmaps idx;
+AnaScaleEdt = uicontrol(...
+ 'Parent',hMain,'Style','Edit',...
+ 'Units','char','Position',[XDSP+139 H 20 1.5],...
+ 'Callback','anz_view(''Main_Callback'',gcbo,''update-anascale'',guidata(gcbo))',...
+ 'String',deblank(sprintf('%g ',ANAP.anz_view.anascale)),'Tag','AnaScaleEdt',...
+ 'HorizontalAlignment','center',...
+ 'TooltipString','set anatomy scaling, [min max gamma]',...
+ 'FontWeight','bold');
+
+
+
+
+% AXES for plots %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% AXES FOR LIGHT BOX %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+H = 3; XSZ = 55; YSZ = 20;
+XDSP=10;
+LightiboxAxs = axes(...
+ 'Parent',hMain,'Tag','LightboxAxs',...
+ 'Units','char','Position',[XDSP H XSZ*2+12 YSZ*2+6.5],...
+ 'Box','off','color','black','Visible','off');
+
+
+
+
+% AXES FOR ORTHOGONL VIEW %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+H = 28; XSZ = 55; YSZ = 20;
+XDSP=10;
+CoronalTxt = uicontrol(...
+ 'Parent',hMain,'Style','Text',...
+ 'Units','char','Position',[XDSP H+YSZ 20 1.5],...
+ 'String','Coronal (X-Z)','FontWeight','bold',...
+ 'HorizontalAlignment','left',...
+ 'Tag','CoronalTxt',...
+ 'BackgroundColor',get(hMain,'Color'));
+CoronalEdt = uicontrol(...
+ 'Parent',hMain,'Style','Edit',...
+ 'Units','char','Position',[XDSP+22 H+YSZ+0.2 8 1.5],...
+ 'Callback','anz_view(''OrthoView_Callback'',gcbo,''edit-coronal'',guidata(gcbo))',...
+ 'String','','Tag','CoronalEdt',...
+ 'HorizontalAlignment','center',...
+ 'TooltipString','set coronal slice',...
+ 'FontWeight','Bold');
+CoronalSldr = uicontrol(...
+ 'Parent',hMain,'Style','slider',...
+ 'Units','char','Position',[XDSP+XSZ*0.6 H+YSZ+0.2 XSZ*0.4 1.2],...
+ 'Callback','anz_view(''OrthoView_Callback'',gcbo,''slider-coronal'',guidata(gcbo))',...
+ 'Tag','CoronalSldr','SliderStep',[1 4],...
+ 'TooltipString','coronal slice');
+CoronalAxs = axes(...
+ 'Parent',hMain,'Tag','CoronalAxs',...
+ 'Units','char','Position',[XDSP H XSZ YSZ],...
+ 'Box','off','Color','black');
+SagitalTxt = uicontrol(...
+ 'Parent',hMain,'Style','Text',...
+ 'Units','char','Position',[XDSP+10+XSZ H+YSZ 20 1.5],...
+ 'String','Sagital (Y-Z)','FontWeight','bold',...
+ 'HorizontalAlignment','left',...
+ 'Tag','SagitalTxt',...
+ 'BackgroundColor',get(hMain,'Color'));
+SagitalEdt = uicontrol(...
+ 'Parent',hMain,'Style','Edit',...
+ 'Units','char','Position',[XDSP+10+XSZ+22 H+YSZ+0.2 8 1.5],...
+ 'Callback','anz_view(''OrthoView_Callback'',gcbo,''edit-sagital'',guidata(gcbo))',...
+ 'String','','Tag','SagitalEdt',...
+ 'HorizontalAlignment','center',...
+ 'TooltipString','set sagital slice',...
+ 'FontWeight','Bold');
+SagitalSldr = uicontrol(...
+ 'Parent',hMain,'Style','slider',...
+ 'Units','char','Position',[XDSP+10+XSZ*1.6 H+YSZ+0.2 XSZ*0.4 1.2],...
+ 'Callback','anz_view(''OrthoView_Callback'',gcbo,''slider-sagital'',guidata(gcbo))',...
+ 'Tag','SagitalSldr','SliderStep',[1 4],...
+ 'TooltipString','sagital slice');
+SagitalAxs = axes(...
+ 'Parent',hMain,'Tag','SagitalAxs',...
+ 'Units','char','Position',[XDSP+10+XSZ H XSZ YSZ],...
+ 'Box','off','Color','black');
+
+
+H = 3;
+TransverseTxt = uicontrol(...
+ 'Parent',hMain,'Style','Text',...
+ 'Units','char','Position',[XDSP H+YSZ 20 1.5],...
+ 'String','Transverse (X-Y)','FontWeight','bold',...
+ 'HorizontalAlignment','left',...
+ 'Tag','TransverseTxt',...
+ 'BackgroundColor',get(hMain,'Color'));
+TransverseEdt = uicontrol(...
+ 'Parent',hMain,'Style','Edit',...
+ 'Units','char','Position',[XDSP+22 H+YSZ+0.2 8 1.5],...
+ 'Callback','anz_view(''OrthoView_Callback'',gcbo,''edit-transverse'',guidata(gcbo))',...
+ 'String','','Tag','TransverseEdt',...
+ 'HorizontalAlignment','center',...
+ 'TooltipString','set transverse slice',...
+ 'FontWeight','Bold');
+TransverseSldr = uicontrol(...
+ 'Parent',hMain,'Style','slider',...
+ 'Units','char','Position',[XDSP+XSZ*0.6 H+YSZ+0.2 XSZ*0.4 1.2],...
+ 'Callback','anz_view(''OrthoView_Callback'',gcbo,''slider-transverse'',guidata(gcbo))',...
+ 'Tag','TransverseSldr','SliderStep',[1 4],...
+ 'TooltipString','transverse slice');
+TransverseAxs = axes(...
+ 'Parent',hMain,'Tag','TransverseAxs',...
+ 'Units','char','Position',[XDSP H XSZ YSZ],...
+ 'Box','off','Color','black');
+
+TriplotAxs = axes(...
+ 'Parent',hMain,'Tag','TriplotAxs',...
+ 'Units','char','Position',[XDSP+10+XSZ H XSZ YSZ],...
+ 'Box','off','color','white');
+
+
+
+
+
+% VIEW MODE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+H = 28;
+XDSP=XDSP+XSZ+7;
+ViewModeCmb = uicontrol(...
+ 'Parent',hMain,'Style','Popupmenu',...
+ 'Units','char','Position',[XDSP+10+XSZ H+YSZ 32 1.5],...
+ 'Callback','anz_view(''Main_Callback'',gcbo,''view-mode'',guidata(gcbo))',...
+ 'String',{'orthogonal','lightbox-cor','lightbox-sag','lightbox-trans'},...
+ 'Tag','ViewModeCmb','Value',1,...
+ 'TooltipString','Select the view mode',...
+ 'FontWeight','bold');
+ViewPageList = uicontrol(...
+ 'Parent',hMain,'Style','Listbox',...
+ 'Units','char','Position',[XDSP+10+XSZ H+10 32 9],...
+ 'String',{'page1','page2','page3','page4'},...
+ 'Callback','anz_view(''Main_Callback'',gcbo,''view-page'',guidata(gcbo))',...
+ 'HorizontalAlignment','left',...
+ 'FontName','Comic Sans MS','FontSize',9,...
+ 'Tag','ViewPageList','Background','white');
+
+
+% INFORMATION TEXT %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+InfoTxt = uicontrol(...
+ 'Parent',hMain,'Style','Listbox',...
+ 'Units','char','Position',[XDSP+10+XSZ H+2.5 32 7],...
+ 'String',{'session','group','datsize','resolution'},...
+ 'HorizontalAlignment','left',...
+ 'FontName','Comic Sans MS','FontSize',9,...
+ 'Tag','InfoTxt','Background','white');
+
+
+
+
+% AXES FOR COLORBAR %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+H = 3;
+ColorbarAxs = axes(...
+ 'Parent',hMain,'Tag','ColorbarAxs',...
+ 'units','char','Position',[XDSP+10+XSZ H XSZ*0.1 YSZ],...
+ 'FontSize',8,...
+ 'Box','off','YAxisLocation','right','XTickLabel',{},'XTick',[]);
+
+
+% CHECK BOX FOR X,Y,Z direction %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+XReverseCheck = uicontrol(...
+ 'Parent',hMain,'Style','Checkbox',...
+ 'Units','char','Position',[XDSP+10+XSZ+15 H+YSZ/2 20 1.5],...
+ 'Tag','XReverseCheck','Value',ANAP.anz_view.xreverse,...
+ 'Callback','anz_view(''OrthoView_Callback'',gcbo,''dir-reverse'',guidata(gcbo))',...
+ 'String','X-Reverse','FontWeight','bold',...
+ 'TooltipString','Xdir reverse','BackgroundColor',get(hMain,'Color'));
+YReverseCheck = uicontrol(...
+ 'Parent',hMain,'Style','Checkbox',...
+ 'Units','char','Position',[XDSP+10+XSZ+15 H+YSZ/2-2.5 20 1.5],...
+ 'Tag','YReverseCheck','Value',ANAP.anz_view.yreverse,...
+ 'Callback','anz_view(''OrthoView_Callback'',gcbo,''dir-reverse'',guidata(gcbo))',...
+ 'String','Y-Reverse','FontWeight','bold',...
+ 'TooltipString','Ydir reverse','BackgroundColor',get(hMain,'Color'));
+ZReverseCheck = uicontrol(...
+ 'Parent',hMain,'Style','Checkbox',...
+ 'Units','char','Position',[XDSP+10+XSZ+15 H+YSZ/2-2.5*2 20 1.5],...
+ 'Callback','anz_view(''OrthoView_Callback'',gcbo,''dir-reverse'',guidata(gcbo))',...
+ 'Tag','ZReverseCheck','Value',ANAP.anz_view.zreverse,...
+ 'String','Z-Reverse','FontWeight','bold',...
+ 'TooltipString','Zdir reverse','BackgroundColor',get(hMain,'Color'));
+
+
+% CHECK BOX FOR "cross-hair" %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CrosshairCheck = uicontrol(...
+ 'Parent',hMain,'Style','Checkbox',...
+ 'Units','char','Position',[XDSP+10+XSZ+15 H+YSZ/2-7.5 20 1.5],...
+ 'Callback','anz_view(''OrthoView_Callback'',gcbo,''crosshair'',guidata(gcbo))',...
+ 'Tag','CrosshairCheck','Value',1,...
+ 'String','Crosshair','FontWeight','bold',...
+ 'TooltipString','show a crosshair','BackgroundColor',get(hMain,'Color'));
+
+
+
+
+
+% get widgets handles at this moment
+HANDLES = findobj(hMain);
+
+
+% INITIALIZE THE APPLICATION
+setappdata(hMain,'ANA',[]);
+setappdata(hMain,'ANAP',ANAP);
+Main_Callback(SagitalAxs,'init');
+set(hMain,'visible','on');
+
+
+
+% NOW SET "UNITS" OF ALL WIDGETS AS "NORMALIZED".
+HANDLES = HANDLES(find(HANDLES ~= hMain));
+set(HANDLES,'units','normalized');
+
+
+% RETURNS THE WINDOW HANDLE IF REQUIRED.
+if nargout,
+ varargout{1} = hMain;
+end
+
+
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+function Main_Callback(hObject,eventdata,handles)
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+wgts = guihandles(hObject);
+
+switch lower(eventdata),
+ case {'init'}
+
+ IMGFILE = get(wgts.AnzFileEdt,'String');
+ if isempty(IMGFILE), return; end
+
+ if ~exist(IMGFILE,'file'),
+ fprintf('\nERROR %s: ''%s'' not found.\n',mfilename,IMGFILE);
+ end
+
+ [img hdr] = anz_read(IMGFILE);
+ if ~ischar(hdr.dime.datatype),
+ switch hdr.dime.datatype,
+ case 1
+ hdr.dime.datatype = 'binary';
+ case 2
+ hdr.dime.datatype = 'uint8';
+ case 4
+ hdr.dime.datatype = 'int16';
+ case 8
+ hdr.dime.datatype = 'int32';
+ case 16
+ hdr.dime.datatype = 'single';
+ case 32
+ hdr.dime.datatype = 'complex';
+ case 64
+ hdr.dime.datatype = 'double';
+ case 128
+ hdr.dime.datatype = 'rgb';
+ otherwise
+ hdr.dime.datatype = 'unknown';
+ end
+ end
+
+
+ ANA.imgfile = IMGFILE;
+ ANA.hdr = hdr;
+ ANA.dat = img;
+ ANA.ds = hdr.dime.pixdim(2:4);
+ clear hdr img;
+
+ ANAP = getappdata(wgts.main,'ANAP');
+
+ % converts ANA.dat into RGB
+ anaminv = 0;
+ anamaxv = 0;
+ anagamma = 1.8;
+ if isfield(ANAP,'anz_view') & isfield(ANAP.anz_view,'anascale') & ~ ...
+ isempty(ANAP.anz_view.anascale),
+ if length(ANAP.anz_view.anascale) == 1,
+ anamaxv = ANAP.anz_view.anascale;
+ else
+ anaminv = ANAP.anz_view.anascale(1);
+ anamaxv = ANAP.anz_view.anascale(2);
+ if length(ANAP.anz_view.anascale) > 2,
+ anagamma = ANAP.anz_view.anascale(3);
+ end
+ end
+ end
+ if anamaxv == 0,
+ tmpana = double(ANA.dat);
+ %anamaxv = round(mean(tmpana(:))*3.5);
+ anamaxv = round(double(max(ANA.dat(:)))*0.7);
+ end
+ ANA.ana256 = subScaleAnatomy(ANA.dat,anaminv,anamaxv,anagamma);
+ ANA.scale = [anaminv anamaxv anagamma];
+ clear tmpana anaminv anamaxv anagamma;
+
+ setappdata(wgts.main,'ANA',ANA);
+
+ INFTXT = {};
+ INFTXT{end+1} = sprintf('dim: [%s]',deblank(sprintf('%d ',size(ANA.dat))));
+ INFTXT{end+1} = sprintf('res: [%s]',deblank(sprintf('%g ',ANA.ds)));
+ INFTXT{end+1} = sprintf('data: %s',ANA.hdr.dime.datatype);
+ set(wgts.InfoTxt,'String',INFTXT);
+
+
+ set(wgts.AnaScaleEdt,'String',sprintf('%g %g %g',ANA.scale));
+
+ % initialize view
+ OrthoView_Callback(hObject(1),'init',[]);
+ LightboxView_Callback(hObject(1),'init',[]);
+
+ Main_Callback(hObject,'redraw',[]);
+
+
+ case {'browse-file'}
+ [f,d] = uigetfile( ...
+ {'*.img', 'All ANALYZE Files (*.img)'; ...
+ '*.*', 'All Files (*.*)'}, ...
+ 'Pick ANALYZE file');
+ if isequal(f,0) | isequal(d,0), return; end
+ IMGFILE = fullfile(d,f);
+
+ setappdata(wgts.main,'ANA',[]);
+ set(wgts.AnzFileEdt,'String',IMGFILE);
+ Main_Callback(hObject,'init',[]);
+
+ case {'update-cmap'}
+ % update tick for colorbar
+ GRAHANDLE = getappdata(wgts.main,'GRAHANDLE');
+ if ~isempty(GRAHANDLE),
+ ANA = getappdata(wgts.main,'ANA');
+ MINV = ANA.scale(1); MAXV = ANA.scale(2);
+ ydat = [0:255]/255 * (MAXV - MINV) + MINV;
+ set(GRAHANDLE.colorbar,'ydata',ydat);
+ set(wgts.ColorbarAxs,'ylim',[MINV MAXV]);
+ end
+
+ CMAP = subGetColormap(wgts);
+ axes(wgts.ColorbarAxs); colormap(CMAP);
+ setappdata(wgts.main,'CMAP',CMAP);
+
+ Main_Callback(hObject,'redraw',[]);
+
+
+
+ case {'update-anascale'}
+ anascale = str2num(get(wgts.AnaScaleEdt,'String'));
+ if length(anascale) ~= 3, return; end
+ ANA = getappdata(wgts.main,'ANA');
+ if isempty(ANA), return; end
+ ANA.ana256 = subScaleAnatomy(ANA.dat,anascale(1),anascale(2),anascale(3));
+ setappdata(wgts.main,'ANA',ANA); clear ANA anascale;
+ Main_Callback(hObject,'update-cmap',[]);
+ %Main_Callback(hObject,'redraw',[]);
+
+ case {'redraw'}
+ ViewMode = get(wgts.ViewModeCmb,'String');
+ ViewMode = ViewMode{get(wgts.ViewModeCmb,'Value')};
+ if strcmpi(ViewMode,'orthogonal'),
+ OrthoView_Callback(hObject,'redraw',[]);
+ else
+ LightboxView_Callback(hObject,'redraw',[]);
+ end
+ %fprintf('redraw\n');
+
+ case {'view-mode'}
+ ViewMode = get(wgts.ViewModeCmb,'String');
+ ViewMode = ViewMode{get(wgts.ViewModeCmb,'Value')};
+ hL = [wgts.LightboxAxs];
+ hO = [wgts.CoronalTxt, wgts.CoronalEdt, wgts.CoronalSldr, wgts.CoronalAxs,...
+ wgts.SagitalTxt, wgts.SagitalEdt, wgts.SagitalSldr, wgts.SagitalAxs,...
+ wgts.TransverseTxt, wgts.TransverseEdt, wgts.TransverseSldr, wgts.TransverseAxs,...
+ wgts.CrosshairCheck];
+
+ if strcmpi(ViewMode,'orthogonal'),
+ set(hL,'visible','off');
+ set(findobj(hL),'visible','off');
+ set(hO,'visible','on');
+ h = findobj([wgts.CoronalAxs, wgts.SagitalAxs, wgts.TransverseAxs, wgts.TriplotAxs]);
+ set(h,'visible','on');
+ else
+ set(hL,'visible','on');
+ set(findobj(hL),'visible','on');
+ set(hO,'visible','off');
+ h = findobj([wgts.CoronalAxs, wgts.SagitalAxs, wgts.TransverseAxs, wgts.TriplotAxs]);
+ set(h,'visible','off');
+ LightboxView_Callback(hObject,'init',[]);
+ LightboxView_Callback(hObject,'redraw',[]);
+ end
+
+ case {'view-page'}
+ ViewMode = get(wgts.ViewModeCmb,'String');
+ ViewMode = ViewMode{get(wgts.ViewModeCmb,'Value')};
+ if ~isempty(strfind(ViewMode,'lightbox')),
+ LightboxView_Callback(hObject,'redraw',[]);
+ end
+
+ otherwise
+end
+
+return;
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% SUBFUNCTION to handle orthogonal view
+function OrthoView_Callback(hObject,eventdata,handles)
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+wgts = guihandles(get(hObject,'Parent'));
+ANA = getappdata(wgts.main,'ANA');
+
+switch lower(eventdata),
+ case {'init'}
+
+ iX = 1; iY = 1; iZ = 1;
+ nX = size(ANA.dat,1); nY = size(ANA.dat,2); nZ = size(ANA.dat,3);
+ % set slider edit value
+ set(wgts.SagitalEdt, 'String', sprintf('%d',iX));
+ set(wgts.CoronalEdt, 'String', sprintf('%d',iY));
+ set(wgts.TransverseEdt,'String', sprintf('%d',iZ));
+ % set slider, add +0.01 to prevent error.
+ set(wgts.SagitalSldr, 'Min',1,'Max',nX+0.01,'Value',iX);
+ set(wgts.CoronalSldr, 'Min',1,'Max',nY+0.01,'Value',iY);
+ set(wgts.TransverseSldr,'Min',1,'Max',nZ+0.01,'Value',iZ);
+ % set slider step, it is normalized from 0 to 1, not min/max
+ set(wgts.SagitalSldr, 'SliderStep',[1, 2]/max(1,nX));
+ set(wgts.CoronalSldr, 'SliderStep',[1, 2]/max(1,nY));
+ set(wgts.TransverseSldr,'SliderStep',[1, 2]/max(1,nZ));
+
+ CMAP = subGetColormap(wgts);
+ setappdata(wgts.main,'CMAP',CMAP);
+
+ AXISCOLOR = [0.8 0.2 0.8];
+ % now draw images
+ axes(wgts.SagitalAxs); cla;
+ tmpimg = squeeze(ANA.ana256(iX,:,:));
+ hSag = image(1:nY,1:nZ,ind2rgb(tmpimg',CMAP));
+ set(hSag,...
+ 'ButtonDownFcn','anz_view(''OrthoView_Callback'',gcbo,''button-sagital'',guidata(gcbo))');
+ set(wgts.SagitalAxs,'tag','SagitalAxs'); % set this again, some will reset.
+ axes(wgts.CoronalAxs); cla;
+ tmimg = squeeze(ANA.ana256(:,iY,:));
+ hCor = image(1:nX,1:nZ,ind2rgb(tmpimg',CMAP));
+ set(hCor,...
+ 'ButtonDownFcn','anz_view(''OrthoView_Callback'',gcbo,''button-coronal'',guidata(gcbo))');
+ set(wgts.CoronalAxs,'tag','CoronalAxs'); % set this again, some will reset.
+ axes(wgts.TransverseAxs); cla;
+ tmpimg = squeeze(ANA.ana256(:,:,iZ));
+ hTra = image(1:nX,1:nY,ind2rgb(tmpimg',CMAP));
+ set(hTra,...
+ 'ButtonDownFcn','anz_view(''OrthoView_Callback'',gcbo,''button-transverse'',guidata(gcbo))');
+ set(wgts.TransverseAxs,'tag','TransverseAxs'); % set this again, some will reset.
+
+ % now draw a color bar
+ MINV = ANA.scale(1); MAXV = ANA.scale(2);
+ axes(wgts.ColorbarAxs); cla;
+ ydat = [0:255]/255 * (MAXV - MINV) + MINV;
+ hColorbar = imagesc(1,ydat,[0:255]'); colormap(CMAP);
+ set(wgts.ColorbarAxs,'Tag','ColorbarAxs'); % set this again, some will reset.
+ set(wgts.ColorbarAxs,'ylim',[MINV MAXV],...
+ 'YAxisLocation','right','XTickLabel',{},'XTick',[],'Ydir','normal');
+
+ haxs = [wgts.SagitalAxs, wgts.CoronalAxs, wgts.TransverseAxs];
+ set(haxs,'fontsize',8,'xcolor',AXISCOLOR,'ycolor',AXISCOLOR);
+ GRAHANDLE.sagital = hSag;
+ GRAHANDLE.coronal = hCor;
+ GRAHANDLE.transverse = hTra;
+ GRAHANDLE.colorbar = hColorbar;
+
+ % draw crosshair(s)
+ axes(wgts.SagitalAxs);
+ hSagV = line([iY iY],[ 1 nZ],'color','y');
+ hSagH = line([ 1 nY],[iZ iZ],'color','y');
+ set([hSagV hSagH],...
+ 'ButtonDownFcn','anz_view(''OrthoView_Callback'',gcbo,''button-sagital'',guidata(gcbo))');
+ axes(wgts.CoronalAxs);
+ hCorV = line([iX iX],[ 1 nZ],'color','y');
+ hCorH = line([ 1 nX],[iZ iZ],'color','y');
+ set([hCorV hCorH],...
+ 'ButtonDownFcn','anz_view(''OrthoView_Callback'',gcbo,''button-coronal'',guidata(gcbo))');
+ axes(wgts.TransverseAxs);
+ hTraV = line([iX iX],[ 1 nY],'color','y');
+ hTraH = line([ 1 nX],[iY iY],'color','y');
+ set([hTraV hTraH],...
+ 'ButtonDownFcn','anz_view(''OrthoView_Callback'',gcbo,''button-transverse'',guidata(gcbo))');
+ if get(wgts.CrosshairCheck,'Value') == 0,
+ set([hSagV hSagH hCorV hCorH hTraV hTraH],'visible','off');
+ end
+
+ GRAHANDLE.sagitalV = hSagV;
+ GRAHANDLE.sagitalH = hSagH;
+ GRAHANDLE.coronalV = hCorV;
+ GRAHANDLE.coronalH = hCorH;
+ GRAHANDLE.transverseV = hTraV;
+ GRAHANDLE.transverseH = hTraH;
+
+ % tri-plot
+ axes(wgts.TriplotAxs); cla;
+ [xi,yi,zi] = meshgrid(iX,1:nY,1:nZ);
+ hSag = surface(...
+ 'xdata',reshape(xi,[nY,nZ]),'ydata',reshape(yi,[nY,nZ]),'zdata',reshape(zi,[nY,nZ]),...
+ 'cdata',squeeze(ANA.ana256(:,iX,:)),...
+ 'facecolor','texturemap','edgecolor','none',...
+ 'CDataMapping','direct','linestyle','none');
+ [xi,yi,zi] = meshgrid(1:nX,iY,1:nZ);
+ hCor = surface(...
+ 'xdata',reshape(xi,[nX,nZ]),'ydata',reshape(yi,[nX,nZ]),'zdata',reshape(zi,[nX,nZ]),...
+ 'cdata',squeeze(ANA.ana256(iY,:,:)),...
+ 'facecolor','texturemap','edgecolor','none',...
+ 'CDataMapping','direct','linestyle','none');
+ [xi,yi,zi] = meshgrid(1:nX,1:nY,iZ);
+ hTra = surface(...
+ 'xdata',1:nX,'ydata',1:nY,'zdata',reshape(zi,[nY,nX]),...
+ 'cdata',permute(squeeze(ANA.ana256(:,:,iZ)),[2 1 3]),...
+ 'facecolor','texturemap','edgecolor','none',...
+ 'CDataMapping','direct','linestyle','none');
+
+ set(gca,'Tag','TriplotAxs');
+ set(gca,'fontsize',8,...
+ 'xlim',[1 nX],'ylim',[1 nY],'zlim',[1 nZ],'zdir','reverse');
+ view(50,36); grid on;
+ xlabel('X'); ylabel('Y'); zlabel('Z');
+
+ GRAHANDLE.triSagital = hSag;
+ GRAHANDLE.triCoronal = hCor;
+ GRAHANDLE.triTransverse = hTra;
+
+ setappdata(wgts.main,'GRAHANDLE',GRAHANDLE);
+
+ OrthoView_Callback(hObject,'dir-reverse',[]);
+
+ case {'redraw'}
+ OrthoView_Callback(hObject,'slider-sagital',[]);
+ OrthoView_Callback(hObject,'slider-coronal',[]);
+ OrthoView_Callback(hObject,'slider-transverse',[]);
+
+ case {'slider-sagital'}
+ GRAHANDLE = getappdata(wgts.main,'GRAHANDLE');
+ if ~isempty(GRAHANDLE),
+ CMAP = getappdata(wgts.main,'CMAP');
+ iX = round(get(wgts.SagitalSldr,'Value'));
+ tmpimg = squeeze(ANA.ana256(iX,:,:));
+ set(GRAHANDLE.sagital,'cdata',ind2rgb(tmpimg',CMAP));
+ set(GRAHANDLE.coronalV, 'xdata',[iX iX]);
+ set(GRAHANDLE.transverseV,'xdata',[iX iX]);
+ set(wgts.SagitalEdt,'String',sprintf('%d',iX));
+ xdata = get(GRAHANDLE.triSagital,'xdata');
+ xdata(:) = iX;
+ set(GRAHANDLE.triSagital,'xdata',xdata,'cdata',tmpimg);
+ end
+
+
+ case {'slider-coronal'}
+ GRAHANDLE = getappdata(wgts.main,'GRAHANDLE');
+ if ~isempty(GRAHANDLE)
+ CMAP = getappdata(wgts.main,'CMAP');
+ iY = round(get(wgts.CoronalSldr,'Value'));
+ tmpimg = squeeze(ANA.ana256(:,iY,:));
+ set(GRAHANDLE.coronal,'cdata',ind2rgb(tmpimg',CMAP));
+ set(GRAHANDLE.sagitalV, 'xdata',[iY iY]);
+ set(GRAHANDLE.transverseH,'ydata',[iY iY]);
+ set(wgts.CoronalEdt,'String',sprintf('%d',iY));
+ ydata = get(GRAHANDLE.triCoronal,'ydata');
+ ydata(:) = iY;
+ set(GRAHANDLE.triCoronal,'ydata',ydata,'cdata',tmpimg);
+ end
+
+ case {'slider-transverse'}
+ GRAHANDLE = getappdata(wgts.main,'GRAHANDLE');
+ if ~isempty(GRAHANDLE)
+ CMAP = getappdata(wgts.main,'CMAP');
+ iZ = round(get(wgts.TransverseSldr,'Value'));
+ tmpimg = squeeze(ANA.ana256(:,:,iZ));
+ set(GRAHANDLE.transverse,'cdata',ind2rgb(tmpimg',CMAP));
+ set(GRAHANDLE.sagitalH, 'ydata',[iZ iZ]);
+ set(GRAHANDLE.coronalH, 'ydata',[iZ iZ]);
+ set(wgts.TransverseEdt,'String',sprintf('%d',iZ));
+ zdata = get(GRAHANDLE.triTransverse,'zdata');
+ zdata(:) = iZ;
+ set(GRAHANDLE.triTransverse,'zdata',zdata,'cdata',tmpimg);
+ end
+
+ case {'edit-sagital'}
+ iX = str2num(get(wgts.SagitalEdt,'String'));
+ if isempty(iX),
+ iX = round(get(wgts.SagitalSldr,'Value'));
+ set(wgts.SagitalEdt,'String',sprintf('%d',iX));
+ else
+ if iX < 0,
+ iX = 1;
+ set(wgts.SagitalEdt,'String',sprintf('%d',iX));
+ elseif iX > size(ANA.dat,1),
+ iX = size(ANA.dat,1);
+ set(wgts.SagitalEdt,'String',sprintf('%d',iX));
+ end
+ set(wgts.SagitalSldr,'Value',iX);
+ OrthoView_Callback(hObject,'slider-sagital',[]);
+ end
+
+ case {'edit-coronal'}
+ iY = str2num(get(wgts.CoronalEdt,'String'));
+ if isempty(iY),
+ iY = round(get(wgts.CoronalSldr,'Value'));
+ set(wgts.CoronalEdt,'String',sprintf('%d',iY));
+ else
+ if iY < 0,
+ iY = 1;
+ set(wgts.CoronalEdt,'String',sprintf('%d',iY));
+ elseif iY > size(ANA.dat,2),
+ iY = size(ANA.dat,1);
+ set(wgts.CoronalEdt,'String',sprintf('%d',iY));
+ end
+ set(wgts.CoronalSldr,'Value',iY);
+ OrthoView_Callback(hObject,'slider-coronal',[]);
+ end
+
+ case {'edit-transverse'}
+ iZ = str2num(get(wgts.TransverseEdt,'String'));
+ if isempty(iZ),
+ iZ = round(get(wgts.TransverseSldr,'Value'));
+ set(wgts.TransverseEdt,'String',sprintf('%d',iZ));
+ else
+ if iZ < 0,
+ iZ = 1;
+ set(wgts.TransverseEdt,'String',sprintf('%d',iZ));
+ elseif iZ > size(ANA.dat,3),
+ iZ = size(ANA.dat,1);
+ set(wgts.TransverseEdt,'String',sprintf('%d',iZ));
+ end
+ set(wgts.TransverseSldr,'Value',iZ);
+ OrthoView_Callback(hObject,'slider-transverse',[]);
+ end
+
+ case {'dir-reverse'}
+ % note that image(),imagesc() reverse Y axies
+ Xrev = get(wgts.XReverseCheck,'Value');
+ Yrev = get(wgts.YReverseCheck,'Value');
+ Zrev = get(wgts.ZReverseCheck,'Value');
+ if Xrev == 0,
+ corX = 'normal'; traX = 'normal';
+ else
+ corX = 'reverse'; traX = 'reverse';
+ end
+ if Yrev == 0,
+ sagX = 'normal'; traY = 'reverse';
+ else
+ sagX = 'reverse'; traY = 'normal';
+ end
+ if Zrev == 0,
+ sagY = 'reverse'; corY = 'reverse';
+ else
+ sagY = 'normal'; corY = 'normal';
+ end
+ set(wgts.SagitalAxs, 'xdir',sagX,'ydir',sagY);
+ set(wgts.CoronalAxs, 'xdir',corX,'ydir',corY);
+ set(wgts.TransverseAxs,'xdir',traX,'ydir',traY);
+
+ case {'crosshair'}
+ GRAHANDLE = getappdata(wgts.main,'GRAHANDLE');
+ if ~isempty(GRAHANDLE),
+ if get(wgts.CrosshairCheck,'value') == 0,
+ set(GRAHANDLE.sagitalV, 'visible','off');
+ set(GRAHANDLE.sagitalH, 'visible','off');
+ set(GRAHANDLE.coronalV, 'visible','off');
+ set(GRAHANDLE.coronalH, 'visible','off');
+ set(GRAHANDLE.transverseV,'visible','off');
+ set(GRAHANDLE.transverseH,'visible','off');
+ else
+ set(GRAHANDLE.sagitalV, 'visible','on');
+ set(GRAHANDLE.sagitalH, 'visible','on');
+ set(GRAHANDLE.coronalV, 'visible','on');
+ set(GRAHANDLE.coronalH, 'visible','on');
+ set(GRAHANDLE.transverseV,'visible','on');
+ set(GRAHANDLE.transverseH,'visible','on');
+ end
+ end
+
+ case {'button-sagital'}
+ click = get(wgts.main,'SelectionType');
+ if strcmpi(click,'alt') & get(wgts.CrosshairCheck,'Value') == 1,
+ pt = round(get(wgts.SagitalAxs,'CurrentPoint'));
+ iY = pt(1,1); iZ = pt(1,2);
+ if iY > 0 & iY <= size(ANA.dat,2),
+ set(wgts.CoronalEdt,'String',sprintf('%d',iY));
+ set(wgts.CoronalSldr,'Value',iY);
+ OrthoView_Callback(hObject,'slider-coronal',[]);
+ end
+ if iZ > 0 & iZ <= size(ANA.dat,3),
+ set(wgts.TransverseEdt,'String',sprintf('%d',iZ));
+ set(wgts.TransverseSldr,'Value',iZ);
+ OrthoView_Callback(hObject,'slider-transverse',[]);
+ end
+ elseif strcmpi(click,'open'),
+ % double click
+ subZoomIn('sagital',wgts,ANA);
+ end
+
+ case {'button-coronal'}
+ click = get(wgts.main,'SelectionType');
+ if strcmpi(click,'alt') & get(wgts.CrosshairCheck,'Value') == 1,
+ pt = round(get(wgts.CoronalAxs,'CurrentPoint'));
+ iX = pt(1,1); iZ = pt(1,2);
+ if iX > 0 & iX <= size(ANA.dat,1),
+ set(wgts.SagitalEdt,'String',sprintf('%d',iX));
+ set(wgts.SagitalSldr,'Value',iX);
+ OrthoView_Callback(hObject,'slider-sagital',[]);
+ end
+ if iZ > 0 & iZ <= size(ANA.dat,3),
+ set(wgts.TransverseEdt,'String',sprintf('%d',iZ));
+ set(wgts.TransverseSldr,'Value',iZ);
+ OrthoView_Callback(hObject,'slider-transverse',[]);
+ end
+ elseif strcmpi(click,'open'),
+ % double click
+ subZoomIn('coronal',wgts,ANA);
+ end
+
+ case {'button-transverse'}
+ click = get(wgts.main,'SelectionType');
+ if strcmpi(click,'alt') & get(wgts.CrosshairCheck,'Value') == 1,
+ pt = round(get(wgts.TransverseAxs,'CurrentPoint'));
+ iX = pt(1,1); iY = pt(1,2);
+ if iX > 0 & iX <= size(ANA.dat,1),
+ set(wgts.SagitalEdt,'String',sprintf('%d',iX));
+ set(wgts.SagitalSldr,'Value',iX);
+ OrthoView_Callback(hObject,'slider-sagital',[]);
+ end
+ if iY > 0 & iY <= size(ANA.dat,2),
+ set(wgts.CoronalEdt,'String',sprintf('%d',iY));
+ set(wgts.CoronalSldr,'Value',iY);
+ OrthoView_Callback(hObject,'slider-coronal',[]);
+ end
+ elseif strcmpi(click,'open'),
+ % double click
+ subZoomIn('transverse',wgts,ANA);
+ end
+
+ otherwise
+end
+
+
+return;
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% SUBFUNCTION to handle lightbox view
+function LightboxView_Callback(hObject,eventdata,handles)
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+wgts = guihandles(get(hObject,'Parent'));
+ANA = getappdata(wgts.main,'ANA');
+ViewMode = get(wgts.ViewModeCmb,'String');
+ViewMode = ViewMode{get(wgts.ViewModeCmb,'Value')};
+switch lower(ViewMode),
+ case {'lightbox-cor'}
+ iDimension = 2;
+ case {'lightbox-sag'}
+ iDimension = 1;
+ case {'lightbox-trans'}
+ iDimension = 3;
+ otherwise
+ iDimension = 3;
+end
+nmaximages = size(ANA.dat,iDimension);
+
+NCol = 5;
+NRow = 4;
+
+switch lower(eventdata),
+ case {'init'}
+ NPages = floor((nmaximages-1)/NCol/NRow)+1;
+ tmptxt = {};
+ for iPage = 1:NPages,
+ tmptxt{iPage} = sprintf('Page%d: %d-%d',iPage,...
+ (iPage-1)*NCol*NRow+1,min([nmaximages,iPage*NCol*NRow]));
+ end
+ set(wgts.ViewPageList,'String',tmptxt,'Value',1);
+ ViewMode = get(wgts.ViewModeCmb,'String');
+ ViewMode = ViewMode{get(wgts.ViewModeCmb,'Value')};
+ if strcmpi(ViewMode,'lightbox'),
+ LightboxView_Callback(hObject,'redraw',handles);
+ end
+
+ case {'redraw'}
+ axes(wgts.LightboxAxs); cla;
+ pagestr = get(wgts.ViewPageList,'String');
+ pagestr = pagestr{get(wgts.ViewPageList,'Value')};
+ ipage = sscanf(pagestr,'Page%d:');
+ SLICES = (ipage-1)*NCol*NRow+1:min([nmaximages,ipage*NCol*NRow]);
+ if iDimension == 1,
+ nX = size(ANA.dat,2); nY = size(ANA.dat,3);
+ INFSTR = 'Sag';
+ elseif iDimension == 2,
+ nX = size(ANA.dat,1); nY = size(ANA.dat,3);
+ INFSTR = 'Cor';
+ else
+ nX = size(ANA.dat,1); nY = size(ANA.dat,2);
+ INFSTR = 'Trans';
+ end
+ X = [0:nX-1]; Y = [nY-1:-1:0];
+ CMAP = getappdata(wgts.main,'CMAP');
+
+ for N = 1:length(SLICES),
+ iSlice = SLICES(N);
+ if iDimension == 1,
+ tmpimg = squeeze(ANA.ana256(iSlice,:,:));
+ elseif iDimension == 2,
+ tmpimg = squeeze(ANA.ana256(:,iSlice,:));
+ else
+ tmpimg = squeeze(ANA.ana256(:,:,iSlice));
+ end
+ iCol = floor((N-1)/NRow)+1;
+ iRow = mod((N-1),NRow)+1;
+ offsX = nX*(iRow-1);
+ offsY = nY*NCol - iCol*nY;
+ tmpx = X + offsX; tmpy = Y + offsY;
+ image(tmpx,tmpy,ind2rgb(tmpimg',CMAP)); hold on;
+ text(min(tmpx)+1,min(tmpy)+1,sprintf('%s=%d',INFSTR,iSlice),...
+ 'color',[0.9 0.9 0.5],'VerticalAlignment','bottom',...
+ 'FontName','Comic Sans MS','FontSize',8,'Fontweight','bold');
+ end
+ axes(wgts.LightboxAxs);
+ set(gca,'Tag','LightboxAxs','color','black');
+ set(gca,'XTickLabel',{},'YTickLabel',{},'XTick',[],'YTick',[]);
+ set(gca,'xlim',[0 nX*NRow],'ylim',[0 nY*NCol]);
+ set(gca,'YDir','normal');
+
+ otherwise
+end
+
+return;
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% SUBFUNCTION to scale anatomy image
+function ANASCALED = subScaleAnatomy(ANA,MINV,MAXV,GAMMA)
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+if isstruct(ANA),
+ tmpana = single(ANA.dat);
+else
+ tmpana = single(ANA);
+end
+clear ANA;
+tmpana = (tmpana - MINV) / (MAXV - MINV);
+tmpana = round(tmpana*255) + 1; % +1 for matlab indexing
+tmpana(find(tmpana(:) < 0)) = 1;
+tmpana(find(tmpana(:) > 256)) = 256;
+
+ANASCALED = uint8(round(tmpana));
+
+
+return;
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% SUBFUNCTION to scale anatomy image
+function ANARGB = subScaleAnatomy_OLD(ANA,MINV,MAXV,GAMMA)
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+if isstruct(ANA),
+ tmpana = single(ANA.dat);
+else
+ tmpana = single(ANA);
+end
+clear ANA;
+tmpana = (tmpana - MINV) / (MAXV - MINV);
+tmpana = round(tmpana*255) + 1; % +1 for matlab indexing
+tmpana(find(tmpana(:) < 0)) = 1;
+tmpana(find(tmpana(:) > 256)) = 256;
+anacmap = gray(256).^(1/GAMMA);
+for N = size(tmpana,3):-1:1,
+ ANARGB(:,:,:,N) = ind2rgb(tmpana(:,:,N),anacmap);
+end
+clear tmpana;
+
+ANARGB = permute(ANARGB,[1 2 4 3]); % [x,y,rgb,z] --> [x,y,z,rgb]
+
+
+return;
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% SUBFUNCTION to get a color map
+function cmap = subGetColormap(wgts)
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+cmapstr = get(wgts.ColormapCmb,'String');
+cmapstr = cmapstr{get(wgts.ColormapCmb,'value')};
+switch lower(cmapstr),
+ case {'jet','hsv','hot','cool','spring','summer','autumn','winter','gray','bone','copper','pink'}
+ eval(sprintf('cmap = %s(256);',cmapstr));
+ case {'red'}
+ %cmap = zeros(256,3); cmap(:,1) = 1;
+ cmap = gray(256); cmap(:,[2 3]) = 0;
+ case {'green'}
+ %cmap = zeros(256,3); cmap(:,2) = 1;
+ cmap = gray(256); cmap(:,[1 3]) = 0;
+ case {'blue'}
+ %cmap = zeros(256,3); cmap(:,3) = 1;
+ cmap = gray(256); cmap(:,[1 2]) = 0;
+ case {'yellow'}
+ %cmap = zeros(256,3); cmap(:,1) = 1; cmap(:,2) = 1;
+ cmap = gray(256); cmap(:,3) = 0;
+ otherwise
+ cmap = gray(256);
+end
+
+ANA = getappdata(wgts.main,'ANA');
+
+gammav = ANA.scale(3);
+if ~isempty(gammav),
+ cmap = cmap.^(1/gammav);
+end
+
+return
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% SUBFUNCTION to fuse anatomy and functional images
+function IMG = subFuseImage(ANARGB,STATV,MINV,MAXV,PVAL,ALPHA,CMAP)
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+IMG = ANARGB;
+if isempty(STATV) | isempty(PVAL) | isempty(ALPHA), return; end
+
+PVAL(find(isnan(PVAL(:)))) = 1; % to avoid error;
+
+tmpdat = repmat(PVAL,[1 1 3]); % for rgb
+idx = find(tmpdat(:) < ALPHA);
+if ~isempty(idx),
+ % scale STATV from MINV to MAXV as 0 to 1
+ STATV = (STATV - MINV)/(MAXV - MINV);
+ STATV = round(STATV*255) + 1; % +1 for matlab indexing
+ STATV(find(STATV(:) < 0)) = 1;
+ STATV(find(STATV(:) > 256)) = 256;
+ % map 0-256 as RGB
+ STATV = ind2rgb(STATV,CMAP);
+ % replace pixels
+ IMG(idx) = STATV(idx);
+end
+
+
+return;
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% SUBFUNCTION to zoom-in plot
+function subZoomIn(planestr,wgts,ANA)
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+switch lower(planestr)
+ case {'coronal'}
+ hfig = wgts.main + 1001;
+ hsrc = wgts.CoronalAxs;
+ DX = ANA.ds(1); DY = ANA.ds(3);
+ N = str2num(get(wgts.CoronalEdt,'String'));
+ tmpstr = sprintf('CORONAL %03d: %s',N, ANA.imgfile);
+ tmpxlabel = 'X (mm)'; tmpylabel = 'Z (mm)';
+ case {'sagital'}
+ hfig = wgts.main + 1002;
+ hsrc = wgts.SagitalAxs;
+ DX = ANA.ds(2); DY = ANA.ds(3);
+ N = str2num(get(wgts.SagitalEdt,'String'));
+ tmpstr = sprintf('SAGITAL %03d: %s',N,ANA.imgfile);
+ tmpxlabel = 'Y (mm)'; tmpylabel = 'Z (mm)';
+ case {'transverse'}
+ hfig = wgts.main + 1003;
+ hsrc = wgts.TransverseAxs;
+ DX = ANA.ds(1); DY = ANA.ds(2);
+ N = str2num(get(wgts.TransverseEdt,'String'));
+ tmpstr = sprintf('TRANSVERSE %03d: %s',N,ANA.imgfile);
+ tmpxlabel = 'X (mm)'; tmpylabel = 'Y (mm)';
+end
+
+tmpstr = strrep(tmpstr,'\','/');
+
+figure(hfig); clf;
+pos = get(hfig,'pos');
+set(hfig,'Name',tmpstr,'pos',[pos(1)-680+pos(3) pos(2)-500+pos(4) 680 500]);
+haxs = copyobj(hsrc,hfig);
+set(haxs,'ButtonDownFcn',''); % clear callback function
+set(hfig,'Colormap',get(wgts.main,'Colormap'));
+h = findobj(haxs,'type','image');
+set(h,'ButtonDownFcn',''); % clear callback function
+set(h,'xdata',get(h,'xdata')*DX,'ydata',get(h,'ydata')*DY);
+nx = length(get(h,'xdata')); ny = length(get(h,'ydata'));
+
+% to keep actual size correct, do like this...
+anasz = size(ANA.dat).*ANA.ds;
+maxsz = max(anasz);
+%set(haxs,'Position',[0.01 0.1 nx*DX/100 ny*DY/100],'units','normalized');
+set(haxs,'Position',[0.01 0.1 nx*DX/maxsz*0.85 ny*DY/maxsz*0.85],'units','normalized');
+h = findobj(haxs,'type','line');
+for N =1:length(h),
+ set(h(N),'xdata',get(h(N),'xdata')*DX,'ydata',get(h(N),'ydata')*DY);
+end
+set(haxs,'xlim',get(haxs,'xlim')*DX,'ylim',get(haxs,'ylim')*DY);
+set(haxs,'xtick',[0 10 20 30 40 50 60 70 80 90 100 110 120]);
+set(haxs,'ytick',[0 10 20 30 40 50 60 70 80 90 100 110 120]);
+xlabel(tmpxlabel); ylabel(tmpylabel);
+title(haxs,strrep(tmpstr,'_','\_'));
+%title(haxs,tmpstr);
+daspect(haxs,[1 1 1]);
+pos = get(haxs,'pos');
+hbar = copyobj(wgts.ColorbarAxs,hfig);
+set(hbar,'pos',[0.85 pos(2) 0.045 pos(4)]);
+
+return;
diff --git a/mpi_code/mex_anz/anz_write.m b/mpi_code/mex_anz/anz_write.m
new file mode 100644
index 0000000..10559b7
--- /dev/null
+++ b/mpi_code/mex_anz/anz_write.m
@@ -0,0 +1,93 @@
+function varargout = anz_write(filename,HDR,IMGDAT)
+%ANZ_WRITE - writes ANALYZE image/header
+% ANZ_WRITE(HDRFILE,HDR,IMGDAT) writes ANALYZE(TM) image.
+%
+% VERSION :
+% 0.90 27.02.07 YM pre-release
+%
+% See also ANZ_READ HDR_WRITE
+
+if nargin == 0, help anz_write; return; end
+
+if isempty(filename),
+ fprintf('\n ERROR %s: no filename specified.\n',mfilename);
+ return
+end
+
+[fp,fr,fe] = fileparts(filename);
+
+imgfile = fullfile(fp,sprintf('%s.img',fr));
+hdrfile = fullfile(fp,sprintf('%s.hdr',fr));
+
+
+% /* Acceptable values for datatype */
+% #define DT_NONE 0
+% #define DT_UNKNOWN 0
+% #define DT_BINARY 1
+% #define DT_UNSIGNED_CHAR 2
+% #define DT_SIGNED_SHORT 4
+% #define DT_SIGNED_INT 8
+% #define DT_FLOAT 16
+% #define DT_COMPLEX 32
+% #define DT_DOUBLE 64
+% #define DT_RGB 128
+% #define DT_ALL 255
+
+switch lower(HDR.dime.datatype)
+ %case {1,'binary'}
+ % ndatatype = 1;
+ % wdatatype = 'int8';
+ case {2,'uchar', 'uint8'}
+ ndatatype = 2;
+ wdatatype = 'uint8';
+ case {4,'short', 'int16'}
+ ndatatype = 4;
+ wdatatype = 'int16';
+ case {8,'int', 'int32', 'long'}
+ ndatatype = 8;
+ wdatatype = 'int32';
+ case {16,'float', 'single'}
+ ndatatype = 16;
+ wdatatype = 'single';
+ %case {32,'complex'}
+ % ndatatype = 32;
+ % wdatatype = 'complex';
+ case {64,'double'}
+ ndatatype = 64;
+ wdatatype = 'double';
+ case {128,'rgb'}
+ ndatatype = 128;
+ wdatatype = 'uint8';
+ otherwise
+ if ischar(HDR.dime.datatype),
+ fprintf('\n %s: unsupported datatype(=%s).\n',mfilename,HDR.dime.datatype);
+ else
+ fprintf('\n %s: unsupported datatype(=%d).\n',mfilename,HDR.dime.datatype);
+ end
+ return
+end
+
+% check image size
+imgdim = HDR.dime.dim([1:HDR.dime.dim(1)]+1);
+nvox = prod(double(HDR.dime.dim([1:HDR.dime.dim(1)]+1)));
+if ndatatype == 128,
+ nvox = nvox*3;
+end
+if numel(IMGDAT) ~= nvox,
+ fprintf('\n ERROR %s: dimensional mismatch, ');
+ fprintf(' HDR.dime.dim = ['); fprintf(' %d',HDR.dime.dim([1:HDR.dime.dim(1)]+1));
+ fprintf(' ], size(IMGDAT)=['); fprintf(' %d',size(IMGDAT));
+ fprintf(' ]\n');
+ return
+end
+
+
+
+hdr_write(hdrfile,HDR);
+
+fid = fopen(imgfile,'w');
+fwrite(fid,IMGDAT,wdatatype);
+fclose(fid);
+
+
+return
diff --git a/mpi_code/mex_anz/anzview.m b/mpi_code/mex_anz/anzview.m
new file mode 100644
index 0000000..de62ab1
--- /dev/null
+++ b/mpi_code/mex_anz/anzview.m
@@ -0,0 +1,6 @@
+function varargout = anzview(varargin)
+if nargout,
+ varargout = anz_view(varargin{:});
+else
+ anz_view(varargin{:});
+end
diff --git a/mpi_code/mex_anz/bru2analyze.m b/mpi_code/mex_anz/bru2analyze.m
new file mode 100644
index 0000000..23427b1
--- /dev/null
+++ b/mpi_code/mex_anz/bru2analyze.m
@@ -0,0 +1,489 @@
+function varargout = bru2analyze(varargin)
+%BRU2ANALYZE - dumps Brucker 2dseq as ANALIZE-7 format for SPM.
+% BRU2ANALYZE(2DSEQFILE,...)
+% BRU2ANALYZE(SESSION,EXPNO,...) dumps Brucker 2dseq as ANLYZE-7 format for SPM.
+% Optional setting can be given as a pair of the name and value, like,
+% BRU2ANALYZE(2dseqfile,'SaveDir','y:/temp/spm') % save to 'y:/temp/spm'
+% BRU2ANALYZE(2dseqfile,'FlipDim',[2]) % flips Y
+% Supported optional arguments are
+% 'ImageCrop' : [x y width height]
+% 'SliceCrop' : [slice-start num.slices]
+% 'FlipDim' : [1,2...] dimension(s) to flip, 1/2/3 as X/Y/Z
+% 'ExportAs2D' : 0/1 to export volumes 2D
+% 'SplitInTime' : 0/1 to export time series to different files
+% 'SaveDir' : directory to save
+% 'FileRoot' : filename without extension
+% 'Verbose' : 0/1
+%
+% EXAMPLE:
+% % exporting functional 2dseq for spm
+% >> bru2analyze('m02lx1',1)
+% % exporting 3D-MDEFT "WITH Y-AXIS FLIP" for BrainSight.
+% >> bru2analyze('//wks8/guest/D02.G01/5/pdata/1/2dseq','FlipDim',[2])
+% % exporting 3D-MDEFT as 2D images for photoshop etc.
+% >> bru2analyze('//wks8/guest/H03.BJ1/5/pdata/1/2dseq','SaveDir','../H03','ExportAs2D',1);
+%
+% IMAGE ORIENTATION :
+% hdr.hist.orient:.
+% 0 transverse unflipped (ANALYZE default)
+% +X=left, +Y=anterior, +Z=superior
+% 1 coronal unflipped
+% 2 sagittal unflipped
+% 3 transverse flipped
+% 4 coronal flipped
+% 5 sagittal flipped
+%
+% VERSION :
+% 0.90 13.06.05 YM pre-release
+% 0.91 14.06.05 YM bug fix, tested with 'm02lx1'
+% 0.92 08.08.05 YM checks reco.RECO_byte_order for machine format.
+% 0.93 12.02.07 YM bug fix on 3D-MDEFT
+% 0.94 13.02.07 YM supports FLIPDIM
+% 0.95 21.02.07 YM supports EXPORT_AS_2D
+% 0.96 27.02.07 YM supports SAVEDIR, hdr.dim.dim(1) as 4 always.
+% 0.97 20.03.08 YM supports 'FileRoot' as option.
+% 0.98 08.04.08 YM supports 'Verbose' as option.
+% 0.99 14.09.09 YM bug fix of RECO_transposition, help by MB.
+%
+% See also HDR_INIT HDR_WRITE TCIMG2SPM SPM2TCIMG PVREAD_RECO PVREAD_ACQP
+
+if nargin == 0, help bru2analyze; return; end
+
+SAVEDIR = 'spmanz';
+
+% GET FILENAME, CROPPING INFO. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+IMGCROP = []; SLICROP = []; FLIPDIM = [2];
+EXPORT_AS_2D = []; SPLIT_IN_TIME = [];
+FILE_ROOT = '';
+VERBOSE = 1;
+if ischar(varargin{1}) & ~isempty(strfind(varargin{1},'2dseq')),
+ % called like BRU2ANALYZE(2DSEQFILE,varargin)
+ TDSEQFILE = varargin{1};
+ % parse inputs
+ for N = 2:2:nargin,
+ switch lower(varargin{N}),
+ case {'imgcrop','imagecrop','image crop'}
+ IMGCROP = varargin{N+1};
+ case {'slicop','slicecrop','slice crop'}
+ SLICROP = varargin{N+1};
+ case {'flipdim','flip dim','flip dimension'}
+ FLIPDIM = varargin{N+1};
+ case {'exportas2d','export as 2d','export2d','export 2d'}
+ EXPORT_AS_2D = varargin{N+1};
+ case {'splitintime','splittime','split in time','splite time','tsplit'}
+ SPLIT_IN_TIME = varargin{N+1};
+ case {'savedir','save dir','savedirectory','save directory'}
+ SAVEDIR = varargin{N+1};
+ case {'fileroot','file root','froot','savename','filename','fname'}
+ FILE_ROOT = varargin{N+1};
+ case {'verbose'}
+ VERBOSE = varargin{N+1};
+ end
+ end
+else
+ % called like BRU2ANALYZE(SESSION,EXPNO,varargin)
+ Ses = goto(varargin{1});
+ ExpNo = varargin{2};
+ if ~isnumeric(ExpNo) | length(ExpNo) ~= 1,
+ fprintf('%s ERROR: 2nd arg. must be a numeric ExpNo.\n',mfilename);
+ return;
+ end
+ if nargout,
+ varargout = bru2analyze(catfilename(Ses,ExpNo,'2dseq'),varargin{:});
+ else
+ bru2analyze(catfilename(Ses,ExpNo,'2dseq'),varargin{:});
+ end
+ return
+end
+if isempty(EXPORT_AS_2D), EXPORT_AS_2D = 0; end
+if isempty(SPLIT_IN_TIME), SPLIT_IN_TIME = 1; end
+if ~isempty(FLIPDIM) & ischar(FLIPDIM),
+ % 'FLIPDIM' is given as a string like, 'Y' or 'XZ'
+ tmpdim = [];
+ for N=1:length(FLIPDIM),
+ tmpidx = strfind('xyz',lower(FLIPDIM(N)));
+ if ~isempty(tmpidx), tmpdim(end+1) = tmpidx; end
+ end
+ FLIPDIM = tmpdim;
+ clear tmpdim tmpidx;
+end
+
+
+[fp,fr,fe] = fileparts(TDSEQFILE);
+RECOFILE = fullfile(fp,'reco');
+[fp,fr,fe] = fileparts(fileparts(fp));
+ACQPFILE = fullfile(fp,'acqp');
+
+if exist(TDSEQFILE,'file') == 0,
+ fprintf(' %s ERROR: ''%s'' not found.\n',mfilename,TDSEQFILE);
+ return;
+end
+if exist(RECOFILE,'file') == 0,
+ fprintf(' %s ERROR: ''%s'' not found.\n',mfilename,RECOFILE);
+ return;
+end
+if exist(ACQPFILE,'file') == 0,
+ fprintf(' %s ERROR: ''%s'' not found.\n',mfilename,ACQPFILE);
+ return;
+end
+
+
+% READ RECO/ACQP INFO %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+if VERBOSE > 0,
+ fprintf(' %s: reading reco/acqp',mfilename);
+end
+reco = pvread_reco(RECOFILE);
+acqp = pvread_acqp(ACQPFILE);
+
+if length(reco.RECO_size) == 3,
+ % likely mdeft
+ nx = reco.RECO_size(1);
+ ny = reco.RECO_size(2);
+ nz = reco.RECO_size(3);
+ xres = reco.RECO_fov(1) / reco.RECO_size(1) * 10; % 10 for cm -> mm
+ yres = reco.RECO_fov(2) / reco.RECO_size(2) * 10; % 10 for cm -> mm
+ zres = reco.RECO_fov(3) / reco.RECO_size(3) * 10; % 10 for cm -> mm
+else
+ % likely epi
+ nx = reco.RECO_size(1);
+ ny = reco.RECO_size(2);
+ nz = acqp.NSLICES;
+ xres = reco.RECO_fov(1) / reco.RECO_size(1) * 10; % 10 for cm -> mm
+ yres = reco.RECO_fov(2) / reco.RECO_size(2) * 10; % 10 for cm -> mm
+ if nz > 1,
+ zres = acqp.ACQ_slice_sepn;
+ else
+ zres = acqp.ACQ_slice_thick;
+ end
+end
+
+tmpfs = dir(TDSEQFILE);
+switch reco.RECO_wordtype,
+ case {'_8BIT_UNSGN_INT'}
+ dtype = 'uint8';
+ nt = floor(tmpfs.bytes/nx/ny/nz);
+ case {'_16BIT_SGN_INT'}
+ dtype = 'int16';
+ nt = floor(tmpfs.bytes/nx/ny/nz/2);
+ case {'_32BIT_SGN_INT'}
+ dtype = 'int32';
+ nt = floor(tmpfs.bytes/nx/ny/nz/4);
+end
+if nt == 1, SPLIT_IN_TIME = 0; end
+if strcmpi(reco.RECO_byte_order,'bigEndian'),
+ machineformat = 'ieee-be';
+else
+ machineformat = 'ieee-le';
+end
+
+
+% check trasposition on reco
+transpos = 0;
+if isfield(reco,'RECO_transposition'),
+ transpos = reco.RECO_transposition(1);
+elseif isfield(reco,'RECO_transpose_dim'),
+ transpos = reco.RECO_transpose_dim(1);
+end
+if any(transpos),
+ if transpos == 1,
+ % (x,y,z) --> (y,x,z)
+ tmpx = nx; tmpy = ny;
+ nx = tmpy; ny = tmpx;
+ tmpx = xres; tmpy = yres;
+ xres = tmpy; yres = tmpx;
+ elseif transpos == 2,
+ % (x,y,z) --> (x,z,y)
+ tmpy = ny; tmpz = nz;
+ ny = tmpz; nz = tmpy;
+ tmpy = yres; tmpz = zres;
+ yres = tmpz; zres = tmpy;
+ elseif transpos == 3,
+ % (x,y,z) --> (z,y,x)
+ tmpx = nx; tmpz = nz;
+ nx = tmpz; nz = tmpx;
+ tmpx = xres; tmpz = zres;
+ xres = tmpz; zres = tmpx;
+ end
+ clear tmpx tmpy tmpz
+end
+
+
+% READ IMAGE DATA %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+if VERBOSE > 0,
+ fprintf('/2dseq[%dx%dx%d %d %s]...',nx,ny,nz,nt,dtype);
+end
+fid = fopen(TDSEQFILE,'rb',machineformat);
+IMG = fread(fid,inf,sprintf('%s=>%s',dtype,dtype));
+fclose(fid);
+if nt > 1,
+ IMG = reshape(IMG,[nx,ny,nz,nt]);
+else
+ IMG = reshape(IMG,[nx,ny,nz]);
+end
+RECOSZ = size(IMG);
+if ~isempty(FLIPDIM),
+ if VERBOSE > 0,
+ tmpstr = 'XYZT';
+ fprintf('flipping(%s)...',tmpstr(FLIPDIM));
+ end
+ for N = 1:size(FLIPDIM),
+ IMG = flipdim(IMG,FLIPDIM(N));
+ end
+end
+if ~isempty(IMGCROP),
+ if VERBOSE > 0,
+ fprintf('imgcrop[%d:%d %d:%d]...',...
+ IMGCROP(1),IMGCROP(3)+IMGCROP(1)-1,...
+ IMGCROP(2),IMGCROP(4)+IMGCROP(2)-1);
+ end
+ idx = [1:IMGCROP(3)] + IMGCROP(1) - 1;
+ IMG = IMG(idx,:,:,:);
+ idx = [1:IMGCROP(4)] + IMGCROP(2) - 1;
+ IMG = IMG(:,idx,:,:);
+end
+if ~isempty(SLICROP),
+ if VERBOSE > 0,
+ fprintf('slicrop[%d:%d]',SLICROP(1),SLICROP(2)+SLICROP(1)-1);
+ end
+ idx = [1:SLICROP(2)] + SLICROP(1) - 1;
+ IMG = IMG(:,:,idx,:);
+end
+
+
+% PREPARE HEADER %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% use size() instead of nx/ny/nz/nt because of cropping
+if nt > 1,
+ % functional
+ if SPLIT_IN_TIME > 0,
+ if size(IMG,3) == 1 || EXPORT_AS_2D > 0,
+ %dim = [2 size(IMG,1) size(IMG,2)];
+ %pixdim = [2 xres yres];
+ dim = [4 size(IMG,1) size(IMG,2) 1 1];
+ pixdim = [3 xres yres zres];
+ else
+ dim = [4 size(IMG,1) size(IMG,2) size(IMG,3) 1];
+ pixdim = [3 xres yres zres];
+ end
+ else
+ if EXPORT_AS_2D & size(IMG,3) > 1,
+ %dim = [3 size(IMG,1) size(IMG,2) size(IMG,4)];
+ %pixdim = [2 xres yres];
+ dim = [4 size(IMG,1) size(IMG,2) 1 size(IMG,4)];
+ pixdim = [3 xres yres zres];
+ else
+ dim = [4 size(IMG,1) size(IMG,2) size(IMG,3) size(IMG,4)];
+ pixdim = [3 xres yres zres];
+ end
+ end
+else
+ % anatomy
+ if size(IMG,3) == 1 || EXPORT_AS_2D > 0,
+ %dim = [2 size(IMG,1) size(IMG,2)];
+ %pixdim = [2 xres yres];
+ dim = [4 size(IMG,1) size(IMG,2) 1 1];
+ pixdim = [3 xres yres zres];
+ else
+ %dim = [3 size(IMG,1) size(IMG,2) size(IMG,3)];
+ dim = [4 size(IMG,1) size(IMG,2) size(IMG,3) 1];
+ pixdim = [3 xres yres zres];
+ end
+end
+
+
+HDR = hdr_init('dim',dim,'datatype',dtype,'pixdim',pixdim,'glmax',intmax('int16'));
+
+
+
+% SET OUTPUTS, IF REQUIRED. OTHERWISE SAVE TO FILES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+if nargout,
+ varargout{1} = HDR;
+ if nargout > 1,
+ varargout{2} = IMG;
+ end
+else
+ if VERBOSE > 0,
+ fprintf(' saving to ''%s''(2D=%d,SplitInTime=%d)...',SAVEDIR,EXPORT_AS_2D,SPLIT_IN_TIME);
+ end
+ %if exist(fullfile(pwd,SAVEDIR),'dir') == 0,
+ % mkdir(pwd,SAVEDIR);
+ %end
+ if exist(SAVEDIR,'dir') == 0,
+ mkdir(SAVEDIR);
+ end
+ if isempty(FILE_ROOT),
+ if exist('Ses','var') & ~isempty(Ses),
+ froot = sprintf('%s_%03d',Ses.name,ExpNo);
+ else
+ froot = subGetFileRoot(TDSEQFILE);
+ if isempty(froot),
+ froot = sprintf('anz');
+ end
+ end
+ else
+ froot = FILE_ROOT;
+ end
+
+ if nt > 1,
+ subExportFunctional(SAVEDIR,froot,HDR,IMG,EXPORT_AS_2D,SPLIT_IN_TIME);
+ else
+ % anatomy
+ if EXPORT_AS_2D > 0 & size(IMG,3) > 1,
+ for S = 1:size(IMG,3),
+ IMGFILE = sprintf('%s/%s_sl%03d.img',SAVEDIR,froot,S);
+ HDRFILE = sprintf('%s/%s_sl%03d.hdr',SAVEDIR,froot,S);
+ hdr_write(HDRFILE,HDR);
+ fid = fopen(IMGFILE,'wb');
+ fwrite(fid,IMG(:,:,S),class(IMG));
+ fclose(fid);
+ end
+ else
+ IMGFILE = sprintf('%s/%s.img',SAVEDIR,froot);
+ HDRFILE = sprintf('%s/%s.hdr',SAVEDIR,froot);
+ hdr_write(HDRFILE,HDR);
+ fid = fopen(IMGFILE,'wb');
+ fwrite(fid,IMG,class(IMG));
+ fclose(fid);
+ end
+ end
+ % write information as a text file
+ subWriteInfo(SAVEDIR,froot,HDR,...
+ TDSEQFILE,RECOSZ,[xres,yres,zres],EXPORT_AS_2D,SPLIT_IN_TIME,IMGCROP,SLICROP,FLIPDIM);
+end
+
+
+if VERBOSE > 0,
+ fprintf(' done.\n');
+end
+
+return;
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+function froot = subGetFileRoot(TDSEQFILE)
+
+try,
+ tmpf = TDSEQFILE;
+ for N=1:4, [tmpf scanno] = fileparts(tmpf); end
+ [tmpf,sesname,sesext] = fileparts(tmpf);
+ sesname = sprintf('%s%s',sesname,sesext);
+catch
+ sesname = ''; scanno = '';
+end
+
+if ~isempty(scanno) & ~isempty(sesname),
+ froot = sprintf('%s_scan%s',strrep(sesname,'.',''),scanno);
+else
+ froot = 'anz';
+end
+
+return
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+function subExportFunctional(SAVEDIR,froot,HDR,IMG,EXPORT_AS_2D,SPLIT_IN_TIME)
+
+if SPLIT_IN_TIME > 0,
+ if EXPORT_AS_2D > 0 & size(IMG,3) > 1,
+ for N = 1:size(IMG,4),
+ for S = 1:size(IMG,3),
+ IMGFILE = sprintf('%s/%s_%05d_sl%03d.img',SAVEDIR,froot,N,S);
+ HDRFILE = sprintf('%s/%s_%05d_sl%03d.hdr',SAVEDIR,froot,N,S);
+ hdr_write(HDRFILE,HDR);
+ fid = fopen(IMGFILE,'wb');
+ fwrite(fid,IMG(:,:,S,N),class(IMG));
+ fclose(fid);
+ end
+ end
+ else
+ for N = 1:size(IMG,4),
+ IMGFILE = sprintf('%s/%s_%05d.img',SAVEDIR,froot,N);
+ HDRFILE = sprintf('%s/%s_%05d.hdr',SAVEDIR,froot,N);
+ hdr_write(HDRFILE,HDR);
+ fid = fopen(IMGFILE,'wb');
+ fwrite(fid,IMG(:,:,:,N),class(IMG));
+ fclose(fid);
+ end
+ end
+else
+ if EXPORT_AS_2D > 0 & size(IMG,3) > 1,
+ for S = 1:size(IMG,3),
+ IMGFILE = sprintf('%s/%s_sl%05d.img',SAVEDIR,froot,S);
+ HDRFILE = sprintf('%s/%s_sl%05d.hdr',SAVEDIR,froot,S);
+ hdr_write(HDRFILE,HDR);
+ fid = fopen(IMGFILE,'wb');
+ fwrite(fid,IMG(:,:,S,:),class(IMG));
+ fclose(fid);
+ end
+ else
+ IMGFILE = sprintf('%s/%s.img',SAVEDIR,froot);
+ HDRFILE = sprintf('%s/%s.hdr',SAVEDIR,froot);
+ hdr_write(HDRFILE,HDR);
+ fid = fopen(IMGFILE,'wb');
+ fwrite(fid,IMG(:,:,:,:),class(IMG));
+ fclose(fid);
+ end
+end
+
+
+return
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+function subWriteInfo(SAVEDIR,froot,HDR,TDSEQFILE,RECOSZ,XYZRES,EXPORT_AS_2D,SPLIT_IN_TIME,IMGCROP,SLICROP,FLIPDIM)
+
+TXTFILE = sprintf('%s/%s_info.txt',SAVEDIR,froot);
+fid = fopen(TXTFILE,'wt');
+fprintf(fid,'date: %s\n',datestr(now));
+fprintf(fid,'program: %s\n',mfilename);
+
+fprintf(fid,'[input]\n');
+fprintf(fid,'2dseq: %s\n',TDSEQFILE);
+fprintf(fid,'recosize: ['); fprintf(fid,' %d',RECOSZ); fprintf(fid,' ]\n');
+fprintf(fid,'xyzres: ['); fprintf(fid,' %g',XYZRES); fprintf(fid,' ] in mm\n');
+fprintf(fid,'imgcrop: [');
+if ~isempty(IMGCROP),
+ fprintf(fid,'%d %d %d %d',IMGCROP(1),IMGCROP(2),IMGCROP(3),IMGCROP(4));
+end
+fprintf(fid,'] as [x y w h]\n');
+fprintf(fid,'slicrop: [');
+if ~isempty(SLICROP),
+ fprintf(fid,'%d %d',SLICROP(1),SLICROP(2));
+end
+fprintf(fid,'] as [start n]\n');
+fprintf(fid,'flipdim: [');
+if ~isempty(FLIPDIM), fprintf(fid,' %d',FLIPDIM); end
+fprintf(fid,' ]\n');
+fprintf(fid,'export_as_2d: %d\n',EXPORT_AS_2D);
+fprintf(fid,'split_in_time: %d\n',SPLIT_IN_TIME);
+
+fprintf(fid,'[output]\n');
+fprintf(fid,'dim: ['); fprintf(fid,' %d',HDR.dime.dim(2:end)); fprintf(fid,' ]\n');
+fprintf(fid,'pixdim: ['); fprintf(fid,' %g',HDR.dime.pixdim(2:end)); fprintf(fid,' ] in mm\n');
+fprintf(fid,'datatype: %d',HDR.dime.datatype);
+switch HDR.dime.datatype
+ case 1
+ dtype = 'binary';
+ case 2
+ dtype = 'char';
+ case 4
+ dtype = 'int16';
+ case 8
+ dtype = 'int32';
+ case 16
+ dtype = 'float';
+ case 32
+ dtype = 'complex';
+ case 64
+ dtype = 'double';
+ case 128
+ dtype = 'rgb';
+ otherwise
+ dtype = 'unknown';
+end
+fprintf(fid,'(%s)\n',dtype);
+
+fclose(fid);
+
+return
diff --git a/mpi_code/mex_anz/bru2spm.m b/mpi_code/mex_anz/bru2spm.m
new file mode 100644
index 0000000..93faef4
--- /dev/null
+++ b/mpi_code/mex_anz/bru2spm.m
@@ -0,0 +1,19 @@
+function varargout = bru2spm(varargin)
+%BRU2SPM - dumps Brucker 2dseq as ANALIZE-7 format for SPM.
+% BRU2SPM() just calls BRU2ANALYZE function and remains to keep compatibility.
+% See BRU2ANALYZE for detail.
+%
+% VERSION :
+% 0.90 24.10.07 YM renamed to bru2analyze.m
+%
+% See also BRU2ANALYZE
+
+if nargin == 0, help bru2spm; return; end
+
+if nargout,
+ varargout = bru2analyze(varargin{:});
+else
+ bru2analyze(varargin{:});
+end
+
+return
diff --git a/mpi_code/mex_anz/dbh.h b/mpi_code/mex_anz/dbh.h
new file mode 100644
index 0000000..595ff7a
--- /dev/null
+++ b/mpi_code/mex_anz/dbh.h
@@ -0,0 +1,140 @@
+/* ANALYZE(TM) Header File Format
+*
+* (c) Copyright, 1986-1995
+* Biomedical Imaging Resource
+* Mayo Foundation
+*
+* dbh.h
+*
+* databse sub-definitions
+*
+* 2005.05.31 Yusuke MURAYAMA @MPI :
+* changed "short int"-->"short".
+* adds _DBH_H_INCLUDED, __cplusplus and #pragma pack.
+* 2005.06.01 Yusuke MURAYAMA @MPI :
+* modified "image_dimension" to make compatible to Bru2Anz.exe.
+*/
+
+#ifndef _DBH_H_INCLUDED
+#define _DBH_H_INCLUDED
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define BRU2ANZ
+
+
+#pragma pack(1)
+struct header_key /* header key */
+{ /* off + size */
+ int sizeof_hdr; /* 0 + 4 */
+ char data_type[10]; /* 4 + 10 */
+ char db_name[18]; /* 14 + 18 */
+ int extents; /* 32 + 4 */
+ short session_error; /* 36 + 2 */
+ char regular; /* 38 + 1 */
+ char hkey_un0; /* 39 + 1 */
+}; /* total=40 bytes */
+
+
+struct image_dimension
+{ /* off + size */
+ short dim[8]; /* 0 + 16 */
+#ifdef BRU2ANZ
+ char vox_units[4]; /* 16 + 4 */
+ // up to 3 characters for the voxels units label; i.e. mm., um., cm.
+ char cal_units[8]; /* 20 + 8 */
+ // up to 7 characters for the calibration units label; i.e. HU
+#else
+ short unused8; /* 16 + 2 */
+ short unused9; /* 18 + 2 */
+ short unused10; /* 20 + 2 */
+ short unused11; /* 22 + 2 */
+ short unused12; /* 24 + 2 */
+ short unused13; /* 26 + 2 */
+#endif
+ short unused14; /* 28 + 2 */
+ short datatype; /* 30 + 2 */
+ short bitpix; /* 32 + 2 */
+ short dim_un0; /* 34 + 2 */
+ float pixdim[8]; /* 36 + 32 */
+ /*
+ pixdim[] specifies the voxel dimensitons:
+ pixdim[1] - voxel width
+ pixdim[2] - voxel height
+ pixdim[3] - interslice distance
+ ...etc
+ */
+ float vox_offset; /* 68 + 4 */
+#ifdef BRU2ANZ
+ float roi_scale; /* 72 + 4 */
+#else
+ float funused1; /* 72 + 4 */
+#endif
+ float funused2; /* 76 + 4 */
+ float funused3; /* 80 + 4 */
+ float cal_max; /* 84 + 4 */
+ float cal_min; /* 88 + 4 */
+ float compressed; /* 92 + 4 */
+ float verified; /* 96 + 4 */
+ int glmax,glmin; /* 100 + 8 */
+}; /* total=108 bytes */
+
+
+struct data_history
+{ /* off + size */
+ char descrip[80]; /* 0 + 80 */
+ char aux_file[24]; /* 80 + 24 */
+ char orient; /* 104 + 1 */
+ char originator[10]; /* 105 + 10 */
+ char generated[10]; /* 115 + 10 */
+ char scannum[10]; /* 125 + 10 */
+ char patient_id[10]; /* 135 + 10 */
+ char exp_date[10]; /* 145 + 10 */
+ char exp_time[10]; /* 155 + 10 */
+ char hist_un0[3]; /* 165 + 3 */
+ int views; /* 168 + 4 */
+ int vols_added; /* 172 + 4 */
+ int start_field; /* 176 + 4 */
+ int field_skip; /* 180 + 4 */
+ int omax, omin; /* 184 + 8 */
+ int smax, smin; /* 192 + 8 */
+}; /* total=200 bytes */
+
+struct dsr
+{
+ struct header_key hk; /* 0 + 40 */
+ struct image_dimension dime; /* 40 + 108 */
+ struct data_history hist; /* 148 + 200 */
+}; /* total= 348 bytes */
+
+typedef struct
+{
+ float real;
+ float imag;
+} COMPLEX;
+
+#pragma pack()
+
+
+/* Acceptable values for datatype */
+#define DT_NONE 0
+#define DT_UNKNOWN 0
+#define DT_BINARY 1
+#define DT_UNSIGNED_CHAR 2
+#define DT_SIGNED_SHORT 4
+#define DT_SIGNED_INT 8
+#define DT_FLOAT 16
+#define DT_COMPLEX 32
+#define DT_DOUBLE 64
+#define DT_RGB 128
+#define DT_ALL 255
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // end of _DBH_H_INCLUDED
diff --git a/mpi_code/mex_anz/dbh.orig.h b/mpi_code/mex_anz/dbh.orig.h
new file mode 100644
index 0000000..93c232f
--- /dev/null
+++ b/mpi_code/mex_anz/dbh.orig.h
@@ -0,0 +1,123 @@
+/* ANALYZE(TM) Header File Format
+*
+* (c) Copyright, 1986-1995
+* Biomedical Imaging Resource
+* Mayo Foundation
+*
+* dbh.h
+*
+* databse sub-definitions
+*
+* 2005.05.31 Yusuke MURAYAMA @MPI :
+* changed "short int"-->"short".
+* adds _DBH_H_INCLUDED, __cplusplus and #pragma pack.
+*/
+
+#ifndef _DBH_H_INCLUDED
+#define _DBH_H_INCLUDED
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#pragma pack(1)
+struct header_key /* header key */
+{ /* off + size */
+ int sizeof_hdr; /* 0 + 4 */
+ char data_type[10]; /* 4 + 10 */
+ char db_name[18]; /* 14 + 18 */
+ int extents; /* 32 + 4 */
+ short session_error; /* 36 + 2 */
+ char regular; /* 38 + 1 */
+ char hkey_un0; /* 39 + 1 */
+}; /* total=40 bytes */
+
+struct image_dimension
+{ /* off + size */
+ short dim[8]; /* 0 + 16 */
+ short unused8; /* 16 + 2 */
+ short unused9; /* 18 + 2 */
+ short unused10; /* 20 + 2 */
+ short unused11; /* 22 + 2 */
+ short unused12; /* 24 + 2 */
+ short unused13; /* 26 + 2 */
+ short unused14; /* 28 + 2 */
+ short datatype; /* 30 + 2 */
+ short bitpix; /* 32 + 2 */
+ short dim_un0; /* 34 + 2 */
+ float pixdim[8]; /* 36 + 32 */
+ /*
+ pixdim[] specifies the voxel dimensitons:
+ pixdim[1] - voxel width
+ pixdim[2] - voxel height
+ pixdim[3] - interslice distance
+ ...etc
+ */
+ float vox_offset; /* 68 + 4 */
+ float funused1; /* 72 + 4 */
+ float funused2; /* 76 + 4 */
+ float funused3; /* 80 + 4 */
+ float cal_max; /* 84 + 4 */
+ float cal_min; /* 88 + 4 */
+ float compressed; /* 92 + 4 */
+ float verified; /* 96 + 4 */
+ int glmax,glmin; /* 100 + 8 */
+}; /* total=108 bytes */
+
+struct data_history
+{ /* off + size */
+ char descrip[80]; /* 0 + 80 */
+ char aux_file[24]; /* 80 + 24 */
+ char orient; /* 104 + 1 */
+ char originator[10]; /* 105 + 10 */
+ char generated[10]; /* 115 + 10 */
+ char scannum[10]; /* 125 + 10 */
+ char patient_id[10]; /* 135 + 10 */
+ char exp_date[10]; /* 145 + 10 */
+ char exp_time[10]; /* 155 + 10 */
+ char hist_un0[3]; /* 165 + 3 */
+ int views; /* 168 + 4 */
+ int vols_added; /* 172 + 4 */
+ int start_field; /* 176 + 4 */
+ int field_skip; /* 180 + 4 */
+ int omax, omin; /* 184 + 8 */
+ int smax, smin; /* 192 + 8 */
+}; /* total=200 bytes */
+
+struct dsr
+{
+ struct header_key hk; /* 0 + 40 */
+ struct image_dimension dime; /* 40 + 108 */
+ struct data_history hist; /* 148 + 200 */
+}; /* total= 348 bytes */
+
+typedef struct
+{
+ float real;
+ float imag;
+} COMPLEX;
+
+#pragma pack()
+
+
+/* Acceptable values for datatype */
+#define DT_NONE 0
+#define DT_UNKNOWN 0
+#define DT_BINARY 1
+#define DT_UNSIGNED_CHAR 2
+#define DT_SIGNED_SHORT 4
+#define DT_SIGNED_INT 8
+#define DT_FLOAT 16
+#define DT_COMPLEX 32
+#define DT_DOUBLE 64
+#define DT_RGB 128
+#define DT_ALL 255
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // end of _DBH_H_INCLUDED
diff --git a/mpi_code/mex_anz/hdr_init.m b/mpi_code/mex_anz/hdr_init.m
new file mode 100644
index 0000000..6f82c1d
--- /dev/null
+++ b/mpi_code/mex_anz/hdr_init.m
@@ -0,0 +1,260 @@
+function HDR = hdr_init(varargin)
+%HDR_INIT - initializes ANALIZE(TM) header structure.
+% HDR = HDR_INIT() returns ANALIZE header structure.
+% HDR = HDR_INIT(NAME1,VALUE1,NAME2,VALUE2,...) returns
+% ANALYZE header initialized by given arguments.
+%
+% EXAMPLE :
+% hdr = hdr_init;
+% hdr = hdr_init('dim',[4 256 256 1 148 0 0 0],'datatype',8);
+% hdr = hdr_init('dim',[4 256 256 1 148 0 0 0],'datatype','int32');
+% hdr = hdr_init('dim',[4 256 256 1 148 0 0 0],'datatype','_32BIT_SGN_INT');
+%
+% VERSION :
+% 0.90 01.06.05 YM first release.
+% 0.91 01.06.05 YM modified for BRU2ANZ.
+% 0.92 13.06.05 YM accepts '_16BIT_SGN_INT' and '_32BIT_SGN_INT' as 'datatype'.
+% 0.93 12.09.05 YM set dime.roi_scale as 1 for safety.
+%
+% See also HDR_READ, HDR_WRITE, DBH.H
+%
+% ANALYZE HEADER ===================================
+% #pragma pack(1)
+% struct header_key /* header key */
+% { /* off + size */
+% long sizeof_hdr; /* 0 + 4 */ <---- must be 384
+% char data_type[10]; /* 4 + 10 */
+% char db_name[18]; /* 14 + 18 */
+% long extents; /* 32 + 4 */
+% short session_error; /* 36 + 2 */
+% char regular; /* 38 + 1 */ <---- should be 'r' ????
+% char hkey_un0; /* 39 + 1 */
+% }; /* total=40 bytes */
+%
+% struct image_dimension
+% { /* off + size */
+% short dim[8]; /* 0 + 16 */
+% #ifdef BRU2ANZ
+% char vox_units[4]; /* 16 + 4 */
+% // up to 3 characters for the voxels units label; i.e. mm., um., cm.
+% char cal_units[8]; /* 20 + 8 */
+% // up to 7 characters for the calibration units label; i.e. HU
+% #else
+% short unused8; /* 16 + 2 */
+% short unused9; /* 18 + 2 */
+% short unused10; /* 20 + 2 */
+% short unused11; /* 22 + 2 */
+% short unused12; /* 24 + 2 */
+% short unused13; /* 26 + 2 */
+% #endif
+% short unused14; /* 28 + 2 */
+% short datatype; /* 30 + 2 */
+% short bitpix; /* 32 + 2 */
+% short dim_un0; /* 34 + 2 */
+% float pixdim[8]; /* 36 + 32 */
+% /*
+% pixdim[] specifies the voxel dimensitons:
+% pixdim[1] - voxel width
+% pixdim[2] - voxel height
+% pixdim[3] - interslice distance
+% ...etc
+% */
+% float vox_offset; /* 68 + 4 */
+% #ifdef BRU2ANZ
+% float roi_scale; /* 72 + 4 */
+% #else
+% float funused1; /* 72 + 4 */
+% #endif
+% float funused2; /* 76 + 4 */
+% float funused3; /* 80 + 4 */
+% float cal_max; /* 84 + 4 */
+% float cal_min; /* 88 + 4 */
+% float compressed; /* 92 + 4 */
+% float verified; /* 96 + 4 */
+% long glmax,glmin; /* 100 + 8 */
+% }; /* total=108 bytes */
+%
+% struct data_history
+% { /* off + size */
+% char descrip[80]; /* 0 + 80 */
+% char aux_file[24]; /* 80 + 24 */
+% char orient; /* 104 + 1 */
+% char originator[10]; /* 105 + 10 */
+% char generated[10]; /* 115 + 10 */
+% char scannum[10]; /* 125 + 10 */
+% char patient_id[10]; /* 135 + 10 */
+% char exp_date[10]; /* 145 + 10 */
+% char exp_time[10]; /* 155 + 10 */
+% char hist_un0[3]; /* 165 + 3 */
+% long views; /* 168 + 4 */
+% long vols_added; /* 172 + 4 */
+% long start_field; /* 176 + 4 */
+% long field_skip; /* 180 + 4 */
+% long omax, omin; /* 184 + 8 */
+% long smax, smin; /* 192 + 8 */
+% }; /* total=200 bytes */
+%
+% struct dsr
+% {
+% struct header_key hk; /* 0 + 40 */
+% struct image_dimension dime; /* 40 + 108 */
+% struct data_history hist; /* 148 + 200 */
+% }; /* total= 348 bytes */
+%
+% typedef struct
+% {
+% float real;
+% float imag;
+% } COMPLEX;
+%
+% #pragma pack()
+%
+% /* Acceptable values for datatype */
+% #define DT_NONE 0
+% #define DT_UNKNOWN 0
+% #define DT_BINARY 1
+% #define DT_UNSIGNED_CHAR 2
+% #define DT_SIGNED_SHORT 4
+% #define DT_SIGNED_INT 8
+% #define DT_FLOAT 16
+% #define DT_COMPLEX 32
+% #define DT_DOUBLE 64
+% #define DT_RGB 128
+% #define DT_ALL 255
+%
+
+if nargin == 0 & nargout == 0,
+ help hdr_init;
+ return;
+end
+
+BRU2ANZ = 1;
+
+
+% read "header_key"
+HK.sizeof_hdr = int32(348);
+HK.data_type = '';
+HK.db_name = '';
+HK.extents = zeros(1,1, 'int32');
+HK.session_error = zeros(1,1, 'int16');
+HK.regular = 'r';
+HK.hkey_un0 = zeros(1,1, 'int8');
+
+% read "image_dimension"
+DIME.dim = zeros(1,8, 'int16');
+if BRU2ANZ,
+DIME.vox_units = '';
+DIME.cal_units = '';
+else
+DIME.unused8 = zeros(1,1, 'int16');
+DIME.unused9 = zeros(1,1, 'int16');
+DIME.unused10 = zeros(1,1, 'int16');
+DIME.unused11 = zeros(1,1, 'int16');
+DIME.unused12 = zeros(1,1, 'int16');
+DIME.unused13 = zeros(1,1, 'int16');
+end
+DIME.unused14 = zeros(1,1, 'int16');
+DIME.datatype = zeros(1,1, 'int16');
+DIME.bitpix = zeros(1,1, 'int16');
+DIME.dim_un0 = zeros(1,1, 'int16');
+DIME.pixdim = zeros(1,8, 'single')';
+DIME.vox_offset = zeros(1,1, 'single');
+if BRU2ANZ,
+% 2005.09.12 set as 1 to be safe, 0.00392157=1/255
+%DIME.roi_scale = zeros(1,1, 'single');
+%DIME.roi_scale = single(0.00392157); % why 0.00392157 ??? <--- 1/255
+DIME.roi_scale = single(1);
+else
+DIME.funused1 = zeros(1,1, 'single');
+end
+DIME.funused2 = zeros(1,1, 'single');
+DIME.funused3 = zeros(1,1, 'single');
+DIME.cal_max = zeros(1,1, 'single');
+DIME.cal_min = zeros(1,1, 'single');
+DIME.compressed = zeros(1,1, 'single');
+DIME.verified = zeros(1,1, 'single');
+DIME.glmax = zeros(1,1, 'int32');
+DIME.glmin = zeros(1,1, 'int32');
+
+% read "data_history"
+HIST.descrip = '';
+HIST.aux_file = '';
+HIST.orient = zeros(1,1, 'int8');
+HIST.originator = '';
+HIST.generated = '';
+HIST.scannum = '';
+HIST.patient_id = '';
+HIST.exp_date = '';
+HIST.exp_time = '';
+HIST.hist_un0 = '';
+HIST.views = zeros(1,1, 'int32');
+HIST.vols_added = zeros(1,1, 'int32');
+HIST.start_field = zeros(1,1, 'int32');
+HIST.field_skip = zeros(1,1, 'int32');
+HIST.omax = zeros(1,1, 'int32');
+HIST.omin = zeros(1,1, 'int32');
+HIST.smax = zeros(1,1, 'int32');
+HIST.smin = zeros(1,1, 'int32');
+
+
+% set values if given.
+for N = 1:2:nargin,
+ vname = varargin{N};
+ vvalue = varargin{N+1};
+ if strcmpi(vname,'datatype') & ischar(vvalue),
+ switch lower(vvalue),
+ case {'binary'}
+ vvalue = 1;
+ case {'uchar', 'uint8'}
+ vvalue = 2;
+ case {'short', 'int16', '_16bit_sgn_int'}
+ vvalue = 4;
+ case {'int', 'int32', 'long', '_32bit_sgn_int'}
+ vvalue = 8;
+ case {'float', 'single'}
+ vvalue = 16;
+ case {'complex'}
+ vvalue = 32;
+ case {'double'}
+ vvalue = 64;
+ case {'rgb'}
+ vvalue = 128;
+ otherwise
+ error('\n ERROR %s: datatype ''%s'' not supported.\n',mfilename,vvalue);
+ end
+ end
+ if isfield(HK,vname), HK.(vname) = vvalue; end
+ if isfield(DIME,vname), DIME.(vname) = vvalue; end
+ if isfield(HIST,vname), HIST.(vname) = vvalue; end
+end
+
+
+% update DIME.bitpix according to DIME.datatype
+switch DIME.datatype
+ case 1
+ DIME.bitpix = 1;
+ case 2
+ DIME.bitpix = 8;
+ case 4
+ DIME.bitpix = 16;
+ case 8
+ DIME.bitpix = 32;
+ case 16
+ DIME.bitpix = 32;
+ case 32
+ DIME.bitpix = 64;
+ case 64
+ DIME.bitpix = 64;
+ case 128
+ DIME.bitpix = 24;
+end
+
+
+
+% return the structure
+HDR.hk = HK; % header_key
+HDR.dime = DIME; % image_dimension
+HDR.hist = HIST; % data_history
+
+
+return;
diff --git a/mpi_code/mex_anz/hdr_read.m b/mpi_code/mex_anz/hdr_read.m
new file mode 100644
index 0000000..a4869e3
--- /dev/null
+++ b/mpi_code/mex_anz/hdr_read.m
@@ -0,0 +1,193 @@
+function HDR = hdr_read(filename)
+%HDR_READ - reads ANALYZE header
+% HDR = HDR_READ(FILENAME) reads a header file of ANALYZE(TM).
+%
+% For detail, see http://www.mayo.edu/bir/PDF/ANALYZE75.pdf
+%
+% REQUIREMENT :
+% utlswapbytes.dll
+%
+% VERSION :
+% 0.90 31.05.05 YM pre-release.
+% 0.91 01.06.05 YM modified for BRU2ANZ.
+% 0.92 06.08.07 YM bug fix, when big-endian.
+% 0.93 29.04.08 YM filename can be as .img
+%
+% See also ANZ_READ, MAKE_HDR, UTLSWAPBYTES, DBH.H
+
+if nargin == 0, help hdr_read; return; end
+
+HDR = [];
+if isempty(filename), return; end
+
+
+[fp fn fe] = fileparts(filename);
+if ~strcmpi(fe,'.hdr'),
+ filename = fullfile(fp,sprintf('%s.hdr',fn));
+end
+
+
+if ~exist(filename,'file'),
+ error('%s: ''%s'' not found.',mfilename,filename);
+end
+
+% check filesize
+tmp = dir(filename);
+if tmp.bytes < 4,
+ fclose(fid);
+ fprintf('\n %s ERROR: invalid file size[%d].',...
+ mfilename,tmp.bytes);
+ return;
+end
+
+
+BRU2ANZ = 1;
+
+% open the file
+fid = fopen(filename,'r');
+
+% read "header_key"
+HK.sizeof_hdr = fread(fid, 1, 'int32=>int32');
+hsize = HK.sizeof_hdr;
+if hsize > hex2dec('01000000'), hsize = utlswapbytes(hsize); end
+if tmp.bytes < hsize,
+ fclose(fid);
+ fprintf('\n %s ERROR: file size[%d] is smaller than %dbytes.',...
+ mfilename,tmp.bytes,hsize);
+ return;
+end
+HK.data_type = subConvStr(fread(fid,10, 'char'));
+HK.db_name = subConvStr(fread(fid,18, 'char'));
+HK.extents = fread(fid, 1, 'int32=>int32');
+HK.session_error = fread(fid, 1, 'int16=>int16');
+HK.regular = subConvStr(fread(fid, 1, 'char'));
+HK.hkey_un0 = fread(fid, 1, 'char');
+
+% read "image_dimension"
+DIME.dim = fread(fid, 8, 'int16=>int16')';
+if BRU2ANZ,
+DIME.vox_units = subConvStr(fread(fid, 4, 'char'));
+DIME.cal_units = subConvStr(fread(fid, 8, 'char'));
+else
+DIME.unused8 = fread(fid, 1, 'int16=>int16');
+DIME.unused9 = fread(fid, 1, 'int16=>int16');
+DIME.unused10 = fread(fid, 1, 'int16=>int16');
+DIME.unused11 = fread(fid, 1, 'int16=>int16');
+DIME.unused12 = fread(fid, 1, 'int16=>int16');
+DIME.unused13 = fread(fid, 1, 'int16=>int16');
+end
+DIME.unused14 = fread(fid, 1, 'int16=>int16');
+DIME.datatype = fread(fid, 1, 'int16=>int16');
+DIME.bitpix = fread(fid, 1, 'int16=>int16');
+DIME.dim_un0 = fread(fid, 1, 'int16=>int16');
+DIME.pixdim = fread(fid, 8, 'single=>single')';
+DIME.vox_offset = fread(fid, 1, 'single=>single');
+if BRU2ANZ,
+DIME.roi_scale = fread(fid, 1, 'single=>single');
+else
+DIME.funused1 = fread(fid, 1, 'single=>single');
+end
+DIME.funused2 = fread(fid, 1, 'single=>single');
+DIME.funused3 = fread(fid, 1, 'single=>single');
+DIME.cal_max = fread(fid, 1, 'single=>single');
+DIME.cal_min = fread(fid, 1, 'single=>single');
+DIME.compressed = fread(fid, 1, 'single=>single');
+DIME.verified = fread(fid, 1, 'single=>single');
+DIME.glmax = fread(fid, 1, 'int32=>int32');
+DIME.glmin = fread(fid, 1, 'int32=>int32');
+
+% read "data_history"
+HIST.descrip = subConvStr(fread(fid,80, 'char'));
+HIST.aux_file = subConvStr(fread(fid,24, 'char'));
+HIST.orient = fread(fid, 1, 'char');
+HIST.originator = subConvStr(fread(fid,10, 'char'));
+HIST.generated = subConvStr(fread(fid,10, 'char'));
+HIST.scannum = subConvStr(fread(fid,10, 'char'));
+HIST.patient_id = subConvStr(fread(fid,10, 'char'));
+HIST.exp_date = subConvStr(fread(fid,10, 'char'));
+HIST.exp_time = subConvStr(fread(fid,10, 'char'));
+HIST.hist_un0 = subConvStr(fread(fid, 3, 'char'));
+HIST.views = fread(fid, 1, 'int32=>int32');
+HIST.vols_added = fread(fid, 1, 'int32=>int32');
+HIST.start_field = fread(fid, 1, 'int32=>int32');
+HIST.field_skip = fread(fid, 1, 'int32=>int32');
+HIST.omax = fread(fid, 1, 'int32=>int32');
+HIST.omin = fread(fid, 1, 'int32=>int32');
+HIST.smax = fread(fid, 1, 'int32=>int32');
+HIST.smin = fread(fid, 1, 'int32=>int32');
+
+
+% for debug, ftell(fid) should return 348
+%ftell(fid)
+
+% close the file
+fclose(fid);
+
+% return the structure
+HDR.hk = HK; % header_key
+HDR.dime = DIME; % image_dimension
+HDR.hist = HIST; % data_history
+
+% swap header's bytes, if needed.
+if HDR.dime.dim(1) < 0 | HDR.dime.dim(1) > 15,
+ HDR = subSwapHdr(HDR,BRU2ANZ);
+end
+
+
+return;
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+function str = subConvStr(dat)
+dat = dat(:)';
+if any(dat)
+ str = deblank(char(dat));
+else
+ str = '';
+end
+
+return;
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+function HDR = subSwapHdr(HDR,BRU2ANZ)
+HDR.hk.sizeof_hdr = utlswapbytes(HDR.hk.sizeof_hdr);
+HDR.hk.extents = utlswapbytes(HDR.hk.extents);
+HDR.hk.session_error = utlswapbytes(HDR.hk.session_error);
+HDR.dime.dim(1) = utlswapbytes(HDR.dime.dim(1));
+HDR.dime.dim(2) = utlswapbytes(HDR.dime.dim(2));
+HDR.dime.dim(3) = utlswapbytes(HDR.dime.dim(3));
+HDR.dime.dim(4) = utlswapbytes(HDR.dime.dim(4));
+HDR.dime.dim(5) = utlswapbytes(HDR.dime.dim(5));
+HDR.dime.dim(6) = utlswapbytes(HDR.dime.dim(6));
+HDR.dime.dim(7) = utlswapbytes(HDR.dime.dim(7));
+HDR.dime.dim(8) = utlswapbytes(HDR.dime.dim(8));
+HDR.dime.unused14 = utlswapbytes(HDR.dime.unused14);
+HDR.dime.datatype = utlswapbytes(HDR.dime.datatype);
+HDR.dime.bitpix = utlswapbytes(HDR.dime.bitpix);
+HDR.dime.pixdim(1) = utlswapbytes(HDR.dime.pixdim(1));
+HDR.dime.pixdim(2) = utlswapbytes(HDR.dime.pixdim(2));
+HDR.dime.pixdim(3) = utlswapbytes(HDR.dime.pixdim(3));
+HDR.dime.pixdim(4) = utlswapbytes(HDR.dime.pixdim(4));
+HDR.dime.pixdim(5) = utlswapbytes(HDR.dime.pixdim(5));
+HDR.dime.pixdim(6) = utlswapbytes(HDR.dime.pixdim(6));
+HDR.dime.pixdim(7) = utlswapbytes(HDR.dime.pixdim(7));
+HDR.dime.pixdim(8) = utlswapbytes(HDR.dime.pixdim(8));
+HDR.dime.vox_offset = utlswapbytes(HDR.dime.vox_offset);
+if BRU2ANZ,
+ HDR.dime.roi_scale = utlswapbytes(HDR.dime.roi_scale);
+else
+ HDR.dime.funused1 = utlswapbytes(HDR.dime.funused1);
+end
+HDR.dime.funused2 = utlswapbytes(HDR.dime.funused2);
+HDR.dime.cal_max = utlswapbytes(HDR.dime.cal_max);
+HDR.dime.cal_min = utlswapbytes(HDR.dime.cal_min);
+HDR.dime.compressed = utlswapbytes(HDR.dime.compressed);
+HDR.dime.verified = utlswapbytes(HDR.dime.verified);
+HDR.dime.dim_un0 = utlswapbytes(HDR.dime.dim_un0);
+HDR.dime.glmax = utlswapbytes(HDR.dime.glmax);
+HDR.dime.glmin = utlswapbytes(HDR.dime.glmin);
+
+return;
+
diff --git a/mpi_code/mex_anz/hdr_write.m b/mpi_code/mex_anz/hdr_write.m
new file mode 100644
index 0000000..74e3e47
--- /dev/null
+++ b/mpi_code/mex_anz/hdr_write.m
@@ -0,0 +1,169 @@
+function hdr_write(filename, HDR)
+%HDR_WRITE - create a ANALYZE header file.
+% HDR_WRITE(FILENAME,HDR) writes a header file of ANALYZE(TM).
+% Input HDR can be given by HDR_INIT.
+%
+% For detail, see http://www.mayo.edu/bir/PDF/ANALYZE75.pdf
+%
+% VERSION :
+% 0.90 01.06.05 YM pre-release.
+% 0.91 01.06.05 YM mofified for BRU2ANZ.
+%
+% See also HDR_READ, HDR_INIT
+
+if nargin ~= 2, help hdr_write; return; end
+
+if ~ischar(filename) | isempty(filename),
+ fprintf('\n %s ERROR: first arg must be a filename string.',mfilename);
+ return;
+end
+if ~isstruct(HDR) | ~isfield(HDR,'hk') | ~isfield(HDR,'dime') | ~isfield(HDR,'hist'),
+ fprintf('\n %s ERROR: second arg must be a strucure by hdr_init().',mfilename);
+ return;
+end
+
+BRU2ANZ = 1;
+
+% update HDR.dime.datatype if it is a string
+if ischar(HDR.dime.datatype),
+ switch lower(HDR.dime.datatype)
+ case {'binary'}
+ HDR.dime.datatype = 1;
+ case {'uchar','uint8'}
+ HDR.dime.datatype = 2;
+ case {'short', 'int16'}
+ HDR.dime.datatype = 4;
+ case {'int', 'int32', 'long'}
+ HDR.dime.datatype = 8;
+ case {'float', 'single'}
+ HDR.dime.datatype = 16;
+ case {'complex'}
+ HDR.dime.datatype = 32;
+ case {'double'}
+ HDR.dime.datatype = 64;
+ case {'rgb'}
+ HDR.dime.datatype = 128;
+ end
+end
+
+% update HDR.dime.bitpix according to HDR.dime.datatype
+switch HDR.dime.datatype
+ case 1
+ HDR.dime.bitpix = 1;
+ case 2
+ HDR.dime.bitpix = 8;
+ case 4
+ HDR.dime.bitpix = 16;
+ case 8
+ HDR.dime.bitpix = 32;
+ case 16
+ HDR.dime.bitpix = 32;
+ case 32
+ HDR.dime.bitpix = 64;
+ case 64
+ HDR.dime.bitpix = 64;
+ case 128
+ HDR.dime.bitpix = 24;
+end
+
+% open the file
+fid = fopen(filename,'wb');
+
+% write "header_key"
+HK = HDR.hk;
+fwrite(fid, HK.sizeof_hdr(1), 'int32');
+fwrite(fid, subGetChar(HK.data_type,10), 'int8');
+fwrite(fid, subGetChar(HK.db_name,18), 'int8');
+fwrite(fid, HK.extents(1), 'int32');
+fwrite(fid, HK.session_error(1), 'int16');
+fwrite(fid, subGetChar(HK.regular,1), 'int8');
+fwrite(fid, HK.hkey_un0(1), 'int8');
+
+% write "image_dimension"
+DIME = HDR.dime;
+fwrite(fid, subGetValue(DIME.dim,8), 'int16');
+if BRU2ANZ,
+fwrite(fid, subGetChar(DIME.vox_units,4), 'int8');
+fwrite(fid, subGetChar(DIME.cal_units,8), 'int8');
+else
+fwrite(fid, DIME.unused8(1), 'int16');
+fwrite(fid, DIME.unused9(1), 'int16');
+fwrite(fid, DIME.unused10(1), 'int16');
+fwrite(fid, DIME.unused11(1), 'int16');
+fwrite(fid, DIME.unused12(1), 'int16');
+fwrite(fid, DIME.unused13(1), 'int16');
+end
+fwrite(fid, DIME.unused14(1), 'int16');
+fwrite(fid, DIME.datatype(1), 'int16');
+fwrite(fid, DIME.bitpix(1), 'int16');
+fwrite(fid, DIME.dim_un0(1), 'int16');
+fwrite(fid, subGetValue(DIME.pixdim,8), 'single');
+fwrite(fid, DIME.vox_offset(1), 'single');
+if BRU2ANZ,
+fwrite(fid, DIME.roi_scale(1), 'single');
+else
+fwrite(fid, DIME.funused1(1), 'single');
+end
+fwrite(fid, DIME.funused2(1), 'single');
+fwrite(fid, DIME.funused3(1), 'single');
+fwrite(fid, DIME.cal_max(1), 'single');
+fwrite(fid, DIME.cal_min(1), 'single');
+fwrite(fid, DIME.compressed(1), 'single');
+fwrite(fid, DIME.verified(1), 'single');
+fwrite(fid, DIME.glmax(1), 'int32');
+fwrite(fid, DIME.glmin(1), 'int32');
+
+% write "data_history"
+HIST = HDR.hist;
+fwrite(fid, subGetChar(HIST.descrip,80), 'int8');
+fwrite(fid, subGetChar(HIST.aux_file,24), 'int8');
+fwrite(fid, HIST.orient(1), 'int8');
+fwrite(fid, subGetChar(HIST.originator,10), 'int8');
+fwrite(fid, subGetChar(HIST.generated,10), 'int8');
+fwrite(fid, subGetChar(HIST.scannum,10), 'int8');
+fwrite(fid, subGetChar(HIST.patient_id,10), 'int8');
+fwrite(fid, subGetChar(HIST.exp_date,10), 'int8');
+fwrite(fid, subGetChar(HIST.exp_time,10), 'int8');
+fwrite(fid, subGetChar(HIST.hist_un0,3), 'int8');
+fwrite(fid, HIST.views(1), 'int32');
+fwrite(fid, HIST.vols_added(1), 'int32');
+fwrite(fid, HIST.start_field(1), 'int32');
+fwrite(fid, HIST.field_skip(1), 'int32');
+fwrite(fid, HIST.omax(1), 'int32');
+fwrite(fid, HIST.omin(1), 'int32');
+fwrite(fid, HIST.smax(1), 'int32');
+fwrite(fid, HIST.smin(1), 'int32');
+
+% close the file
+fclose(fid);
+
+
+return;
+
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+function v = subGetChar(x,n)
+v = x;
+if ischar(v), v = int8(v); end
+if length(v) > n,
+ v = v(1:n);
+elseif length(v) < n,
+ v(end+1:n) = 0;
+end
+
+return;
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+function v = subGetValue(x,n)
+v = x;
+if length(v) > n,
+ v = v(1:n);
+elseif length(v) < n,
+ v(end+1:n) = 0;
+end
+
+return;
+
diff --git a/mpi_code/mex_anz/html_files/Contents.html b/mpi_code/mex_anz/html_files/Contents.html
new file mode 100644
index 0000000..c9466d6
--- /dev/null
+++ b/mpi_code/mex_anz/html_files/Contents.html
@@ -0,0 +1,256 @@
+
+
+
+
+ Contents
+
+
+ ANA
+
+ Files
+ @SessionTemplate - - description of your poject/session
+ K02jP1 - - Block Design (Fahad)
+ a003c1 - - Phys+MRI
+ a003x1 - - Phys+MRI
+ a019p1 - - Block Design (Zoe)
+ a01lG1 - - Scotoma
+ a98nm1 - - Movie Phys
+ a98nm2 - - Physiology w/ Brief Stimuli and the HR-Flash Suppression
+ b003d1 - - Phys+MRI
+ b00401 - - Phys + MRI, Phys+MRI
+ b004h1 - - Phys+MRI
+ b004o1 - - Block Design (Margaret)
+ b00581 - - Scotoma
+ b005j1 - - Phys+MRI
+ b005y1 - - Phys+MRI
+ b006d1 - - Phys+MRI
+ b006r1 - - Block Design (Margaret)
+ b007t1 - - Block Design (Zoe)
+ b00851 - - Block Design (Zoe)
+ b009s1 - - Microstimulation
+ b00ae1 - - Microstimulation
+ b00au1 - - Microstimulation
+ b00bi1 - - Neuromod Phys+MRI
+ b00cg1 - - Neuromod Phys+MRI
+ b00cs1 - - Phys+MRI
+ b00nm1 - - Neuromod Phys
+ b019i1 - - Microstimulation
+ b01a21 - - Block Design (Margaret)
+ b01ae1 - - Glass Patterns
+ b01ak1 - - Block Design (Zoe)
+ b01bs1 - - Block Design (Margaret)
+ b01di1 - - Glass Patterns
+ b01du1 - - Block Design (Margaret)
+ b01lm1 - - Microstimulation
+ b01mz1 - - Movie Phys+MRI
+ b01nm3 - - Flash Suppression Phys
+ b01nm4 - - Flash Suppression Phys
+ b01nm5 - - Flash Suppression Phys
+ b02nm1 - - Attention, Flash Suppression Phys
+ b02nm2 - - Movie Phys
+ b02nm3 - - Physiology w/ Brief Stimuli and the HR-Flash Suppression
+ b03pD1 - - Psychophys w/ Brief Stimuli
+ b03pG1 - - Psychophys w/ Brief Stimuli
+ b03pN1 - B03PG1 - Psychophys w/ Brief Stimuli
+ b970q1 - - Block Design (Gregor)
+ b971q1 - - Block Design (Margaret)
+ b972y1 - - Phys+MRI
+ b973k1 - - Phys+MRI
+ b983m1 - - Block Design (Margaret)
+ b987c1 - - Glass Patterns
+ b99wr1 - - Block Design (Margaret)
+ c019q1 - - Microstimulation
+ c019t1 - - Block Design (Margaret)
+ c01aa1 - - Block Design (Zoe)
+ c01af1 - - Block Design (Zoe)
+ c01br1 - - Block Design (Zoe)
+ c01dl1 - - Block Design (Margaret)
+ c01ek1 - - Block Design (Margaret)
+ c01ep1 - - Block Design (Margaret)
+ c01hl1 - - Glass Patterns
+ c01i21 - - Block Design (Zoe)
+ c01ie1 - - Block Design (Faces)
+ c01jn1 - - Anesthesia Phys+MRI
+ c01jw1 - - Microstimulation, Flash Suppression Phys+MRI, Anesthesia Phys+MRI
+ c01kx1 - - Attention, Flash Suppression Phys+MRI, Anesthesia Phys+MRI
+ c01nm1 - - Movie Phys
+ c01nm2 - - Movie Phys
+ c01nm3 - - Physiology w/ Brief Stimuli and the HR-Flash Suppression
+ c01nn1 - - Movie MRI
+ c01ph1 - - Short stimuli -> Non-linearity of BOLD onset
+ c970z1 - - Block Design (Gregor)
+ c97241 - - Block Design (Margaret)
+ c97311 - - Block Design (Margaret)
+ c973p1 - - Block Design (Margaret)
+ c974l1 - - Phys+MRI
+ c98nm1 - - Movie Phys, Anesthesia Phys
+ c98nm2 - - Movie Phys
+ c98nm3 - - Movie Phys
+ c990q1 - - Block Design (Margaret)
+ c993a1 - - Block Design (Margaret)
+ c993t1 - - Block Design (Margaret)
+ c995s1 - - Block Design (Gregor)
+ d01hq1 - - Glass Patterns
+ d01lr1 - - Microstimulation
+ d01ml1 - - Movie Phys+MRI
+ d01nm1 - - Neuromod Phys
+ d01nm2 - - Neuromod Phys
+ d01nm4 - - Flash Suppression Phys
+ d01nm5 - - Flash Suppression Phys
+ d03pf1 - - Short stimuli
+ d04pk1 - - Short stimuli
+ d04qd1 - - Movie MRI
+ d970j1 - - Block Design (Margaret)
+ d970x1 - - Block Design (Margaret)
+ d972i1 - - Block Design (Margaret)
+ d972j1 - - Block Design (Ocular Dominance)
+ d973f1 - - Phys+MRI
+ d974b1 - - Block Design (Gregor)
+ d974f1 - - Block Design (Margaret)
+ d974m1 - - Block Design (Gregor)
+ d97571 - - Scotoma
+ d975n1 - - Block Design (Margaret)
+ d97621 - - Microstimulation
+ d976b1 - - Block Design (High Resolution)
+ d991i1 - - Phys+MRI
+ d992z1 - - Phys+MRI
+ e004u1 - - Block Design (Margaret)
+ e00nm1 - - Physiology w/ Brief Stimuli and the HR-Flash Suppression
+ e01fe1 - - Scotoma
+ e01js1 - - Scotoma
+ e02hQ1 - - Scotoma
+ e02iK1 - - Scotoma
+ e02jc1 - - Scotoma
+ e02jq1 - - Scotoma
+ e02kF1 - - Scotoma
+ e02kd1 - - Scotoma
+ e02mm1 - - Scotoma
+ e02nm1 - - Movie Phys
+ e04pl1 - - Short stimuli
+ e99wq1 - - Block Design (Margaret)
+ f003w1 - - Block Design (Margaret)
+ f01kj1 - - Attention, Flash Suppression Phys+MRI
+ f01kz1 - - Microstimulation
+ f01m91 - - Movie Phys+MRI
+ f01pr1 - - Short stimuli -> Non-linearity of BOLD onset
+ f970s1 - - Block Design (Margaret)
+ f971k1 - - Block Design (Gregor)
+ f972w1 - - Block Design (Ocular Dominance)
+ f973j1 - - Block Design (Gregor)
+ f975l1 - - Block Design (High Resolution)
+ f97641 - - Block Design (High Resolution)
+ g02j21 - - Phys+MRI, Anesthesia Phys+MRI
+ g02lv1 - - Movie Phys+MRI
+ g02mn1 - - Movie Phys+MRI
+ g02nm1 - - Movie Phys, Anesthesia Phys
+ g02nm2 - - Physiology w/ Brief Stimuli and the HR-Flash Suppression
+ g02pv1 - - Short stimuli -> Non-linearity of BOLD onset
+ g04pr1 - - NEWSOME PROJECT
+ g974c1 - - Block Design (Gregor)
+ g977d1 - - Glass Patterns
+ g97nm1 - - Movie Phys, Anesthesia Phys
+ g981v1 - - Block Design (Margaret)
+ g98nm1 - - Flash Suppression Phys, Anesthesia Phys
+ g98nm2 - - Flash Suppression Phys, Anesthesia Phys
+ h005v1 - - Phys+MRI
+ h005w1 - - Microstimulation
+ h006l1 - - Phys+MRI
+ h007l1 - - Glass Patterns
+ h00871 - - Glass Patterns
+ h008d1 - - Glass Patterns
+ h009d1 - - Phys+MRI
+ h00ag1 - - Microstimulation
+ h970w1 - - Block Design (Margaret)
+ h97361 - - Phys+MRI
+ h973l1 - - Phys+MRI
+ h974i1 - - Block Design (Gregor)
+ i006p1 - - Block Design (Gregor)
+ i007c1 - - Block Design (Margaret)
+ i007v1 - - Block Design (Zoe)
+ i00951 - - Phys+MRI
+ i009h1 - - Microstimulation
+ i00an1 - - Microstimulation
+ i00f41 - - Block Design (Margaret)
+ j00731 - - Block Design (Margaret)
+ j007f1 - - Microstimulation
+ j008e1 - - Glass Patterns
+ j00aq1 - - Block Design (Margaret)
+ j00b21 - - Microstimulation
+ j00bt1 - - Block Design (Margaret)
+ j00dh1 - - Phys+MRI
+ j00dj1 - - Phys+MRI
+ j00el1 - - Block Design (Zoe)
+ j00f11 - - Neuromod Phys+MRI
+ j00jx1 - - Block Design (High Resolution)
+ j00lq1 - - Movie Phys+MRI, Anesthesia Phys+MRI
+ j00me1 - - Movie Phys+MRI
+ j00nm1 - - Physiology w/ Brief Stimuli and the HR-Flash Suppression
+ j02hn1 - - Glass Patterns
+ j02l61 - - Glass Patterns
+ j02lw1 - - Block Design (High Resolution)
+ j02np1 - - Movie MRI
+ j02ol1 - - Spontaneous activity for dependence analysis,
+ j02pb1 - - Short stimuli
+ j02pp1 - - Short stimuli
+ j02q71 - - Short stimuli
+ j02qf1 - - Movie MRI
+ j02qp1 - - Traveling WAVE
+ j03ls1 - - Movie MRI
+ j97nm1 - - Physiology w/ Brief Stimuli and the HR-Flash Suppression
+ k005x1 - - Phys+MRI
+ k005z1 - - Microstimulation
+ k006i1 - - Phys+MRI
+ k00761 - - Block Design (Margaret)
+ k007w1 - - Block Design (Zoe)
+ k007z1 - - Glass Patterns
+ k008f1 - - Glass Patterns
+ k00911 - - Glass Patterns
+ k009u1 - - Phys+MRI
+ k00bk1 - - Neuromod Phys+MRI
+ k00dd1 - - Neuromod Phys+MRI
+ l00651 - - Block Design (Gregor)
+ m00631 - - Block Design (Margaret)
+ m02gs1 - - Phys+MRI
+ m02jC1 - - Anesthesia Phys+MRI
+ m02lx1 - - Two-electrode, Movie Phys+MRI, Injection(Propofol) [FORMAT]
+ m02pd1 - - Short stimuli
+ m03lu1 - - Movie MRI
+ m03pI1 - - Psychophys - Brief Stimuli
+ m03pO1 - - Psychophys - Brief Stimuli
+ n00a01 - - Block Design (Zoe)
+ n00ab1 - - Glass Patterns
+ n00eb1 - - Neuromod Phys+MRI
+ n02l71 - - Glass Patterns
+ n02lp1 - - Movie Phys+MRI, Anesthesia Phys+MRI
+ n02m21 - - Movie Phys+MRI
+ n02mv1 - - Movie MRI
+ n03mt1 - - Movie MRI
+ n03ow1 - - Short stimuli -> Non-linearity of BOLD onset
+ n03py1 - - Short stimuli, On/Off speparation(Wehrhahn)
+ n03qr1 - - TRAVELING WAVE
+ n03qv1 - - Traveling wave & Brief Pulses 28.06.04
+ o979x1 - - Scotoma
+ o979z1 - - Block Design (Zoe)
+ prz001 - - Short stimuli -> Non-linearity of BOLD onset
+ q02mA1 - - Scotoma
+ r97nm1 - - Movie Phys
+ s02jT1 - - Flash Suppression Phys+MRI, Anesthesia Phys+MRI
+ s02kr1 - - Flash Suppression Phys+MRI
+ s02kv1 - - Flash Suppression Phys+MRI
+ s02l81 - - Glass Patterns
+ s02nm1 - - Movie Phys
+ s02nm2 - - Physiology w/ Brief Stimuli and the HR-Flash Suppression
+ @SessionTemplate - @SESSIONTEMPLATE - description of your poject/session
+
+ Overloaded functions or methods (ones with the same name in other directories)
+ help icinterface/Contents.m
+ help instrument/Contents.m
+ help serial/Contents.m
+ help timer/Contents.m
+ help audioplayer/Contents.m
+ help audiorecorder/Contents.m
+ help strel/Contents.m
+
+
+
diff --git a/mpi_code/mex_anz/html_files/hdr_init.html b/mpi_code/mex_anz/html_files/hdr_init.html
new file mode 100644
index 0000000..79ceac2
--- /dev/null
+++ b/mpi_code/mex_anz/html_files/hdr_init.html
@@ -0,0 +1,134 @@
+
+
+
+
+ hdr_init
+
+
+ HDR_INIT - initializes ANALIZE(TM) header structure.
+ HDR = HDR_INIT() returns ANALIZE header structure.
+ HDR = HDR_INIT(NAME1,VALUE1,NAME2,VALUE2,...) returns
+ ANALYZE header initialized by given arguments.
+
+ EXAMPLE :
+ hdr = hdr_init;
+ hdr = hdr_init('dim',[4 256 256 1 148 0 0 0],'datatype',8);
+ hdr = hdr_init('dim',[4 256 256 1 148 0 0 0],'datatype','int32');
+ hdr = hdr_init('dim',[4 256 256 1 148 0 0 0],'datatype','_32BIT_SGN_INT');
+
+ VERSION :
+ 0.90 01.06.05 YM first release.
+ 0.91 01.06.05 YM modified for BRU2ANZ.
+ 0.92 13.06.05 YM accepts '_16BIT_SGN_INT' and '_32BIT_SGN_INT' as 'datatype'.
+ 0.93 12.09.05 YM set dime.roi_scale as 1 for safety.
+
+ See also HDR_READ, HDR_WRITE, DBH.H
+
+ ANALYZE HEADER ===================================
+ #pragma pack(1)
+ struct header_key /* header key */
+ { /* off + size */
+ long sizeof_hdr; /* 0 + 4 */ <---- must be 384
+ char data_type[10]; /* 4 + 10 */
+ char db_name[18]; /* 14 + 18 */
+ long extents; /* 32 + 4 */
+ short session_error; /* 36 + 2 */
+ char regular; /* 38 + 1 */ <---- should be 'r' ????
+ char hkey_un0; /* 39 + 1 */
+ }; /* total=40 bytes */
+
+ struct image_dimension
+ { /* off + size */
+ short dim[8]; /* 0 + 16 */
+ #ifdef BRU2ANZ
+ char vox_units[4]; /* 16 + 4 */
+ // up to 3 characters for the voxels units label; i.e. mm., um., cm.
+ char cal_units[8]; /* 20 + 8 */
+ // up to 7 characters for the calibration units label; i.e. HU
+ #else
+ short unused8; /* 16 + 2 */
+ short unused9; /* 18 + 2 */
+ short unused10; /* 20 + 2 */
+ short unused11; /* 22 + 2 */
+ short unused12; /* 24 + 2 */
+ short unused13; /* 26 + 2 */
+ #endif
+ short unused14; /* 28 + 2 */
+ short datatype; /* 30 + 2 */
+ short bitpix; /* 32 + 2 */
+ short dim_un0; /* 34 + 2 */
+ float pixdim[8]; /* 36 + 32 */
+ /*
+ pixdim[] specifies the voxel dimensitons:
+ pixdim[1] - voxel width
+ pixdim[2] - voxel height
+ pixdim[3] - interslice distance
+ ...etc
+ */
+ float vox_offset; /* 68 + 4 */
+ #ifdef BRU2ANZ
+ float roi_scale; /* 72 + 4 */
+ #else
+ float funused1; /* 72 + 4 */
+ #endif
+ float funused2; /* 76 + 4 */
+ float funused3; /* 80 + 4 */
+ float cal_max; /* 84 + 4 */
+ float cal_min; /* 88 + 4 */
+ float compressed; /* 92 + 4 */
+ float verified; /* 96 + 4 */
+ long glmax,glmin; /* 100 + 8 */
+ }; /* total=108 bytes */
+
+ struct data_history
+ { /* off + size */
+ char descrip[80]; /* 0 + 80 */
+ char aux_file[24]; /* 80 + 24 */
+ char orient; /* 104 + 1 */
+ char originator[10]; /* 105 + 10 */
+ char generated[10]; /* 115 + 10 */
+ char scannum[10]; /* 125 + 10 */
+ char patient_id[10]; /* 135 + 10 */
+ char exp_date[10]; /* 145 + 10 */
+ char exp_time[10]; /* 155 + 10 */
+ char hist_un0[3]; /* 165 + 3 */
+ long views; /* 168 + 4 */
+ long vols_added; /* 172 + 4 */
+ long start_field; /* 176 + 4 */
+ long field_skip; /* 180 + 4 */
+ long omax, omin; /* 184 + 8 */
+ long smax, smin; /* 192 + 8 */
+ }; /* total=200 bytes */
+
+ struct dsr
+ {
+ struct header_key hk; /* 0 + 40 */
+ struct image_dimension dime; /* 40 + 108 */
+ struct data_history hist; /* 148 + 200 */
+ }; /* total= 348 bytes */
+
+ typedef struct
+ {
+ float real;
+ float imag;
+ } COMPLEX;
+
+ #pragma pack()
+
+ /* Acceptable values for datatype */
+ #define DT_NONE 0
+ #define DT_UNKNOWN 0
+ #define DT_BINARY 1
+ #define DT_UNSIGNED_CHAR 2
+ #define DT_SIGNED_SHORT 4
+ #define DT_SIGNED_INT 8
+ #define DT_FLOAT 16
+ #define DT_COMPLEX 32
+ #define DT_DOUBLE 64
+ #define DT_RGB 128
+ #define DT_ALL 255
+
+
+
+
diff --git a/mpi_code/mex_anz/html_files/hdr_read.html b/mpi_code/mex_anz/html_files/hdr_read.html
new file mode 100644
index 0000000..d145d84
--- /dev/null
+++ b/mpi_code/mex_anz/html_files/hdr_read.html
@@ -0,0 +1,24 @@
+
+
+
+
+ hdr_read
+
+
+ HDR_READ - reads ANALYZE header
+ HDR = HDR_READ(FILENAME) reads a header file of ANALYZE(TM).
+
+ For detail, see http://www.mayo.edu/bir/PDF/ANALYZE75.pdf
+
+ REQUIREMENT :
+ swapbytes.dll
+
+ VERSION :
+ 0.90 31.05.05 YM pre-release.
+ 0.91 01.06.05 YM modified for BRU2ANZ.
+
+ See also MAKE_HDR, SWAPBYTES, DBH.H
+
+
+
diff --git a/mpi_code/mex_anz/html_files/hdr_write.html b/mpi_code/mex_anz/html_files/hdr_write.html
new file mode 100644
index 0000000..f87cc71
--- /dev/null
+++ b/mpi_code/mex_anz/html_files/hdr_write.html
@@ -0,0 +1,22 @@
+
+
+
+
+ hdr_write
+
+
+ HDR_WRITE - create a ANALYZE header file.
+ HDR_WRITE(FILENAME,HDR) writes a header file of ANALYZE(TM).
+ Input HDR can be given by HDR_INIT.
+
+ For detail, see http://www.mayo.edu/bir/PDF/ANALYZE75.pdf
+
+ VERSION :
+ 0.90 01.06.05 YM pre-release.
+ 0.91 01.06.05 YM mofified for BRU2ANZ.
+
+ See also HDR_READ, HDR_INIT
+
+
+
diff --git a/mpi_code/mex_anz/html_files/mexanz.html b/mpi_code/mex_anz/html_files/mexanz.html
new file mode 100644
index 0000000..1c09a4a
--- /dev/null
+++ b/mpi_code/mex_anz/html_files/mexanz.html
@@ -0,0 +1,15 @@
+
+
+
+
+ mexanz
+
+
+
+ mexanz.m : batch file to make all mex DLLs.
+
+ VERSION : 1.00 31-May-2005 YM
+
+
+
diff --git a/mpi_code/mex_anz/html_files/swapbytes.html b/mpi_code/mex_anz/html_files/swapbytes.html
new file mode 100644
index 0000000..f3a7155
--- /dev/null
+++ b/mpi_code/mex_anz/html_files/swapbytes.html
@@ -0,0 +1,30 @@
+
+
+
+
+ swapbytes
+
+
+ SWAPBYTES - swaps bytes of given data.
+ SV = SWAPBYTES(V) swaps bytes of V and returns the result.
+ SWAPBYTES(V) does the same thing but it will modify directly the original
+ data V without allocating additional memory for the result.
+ Input data V can be multi-dimesional, but its data class
+ must be 2bytes or 4bytes type, ie. int16/uint16/int32/uint32/single.
+
+ Usage: sv = swapbytes(v,[verbose=0|1])
+ Notes: class of 'v' must be int16,uint16,int32,uint32,single.
+ : if nargout==0, then swaps 'v' directly.
+
+ To compile,
+ mex swapbytes.c
+
+ VERSION :
+ 0.90 2005.05.31 Yusuke MURAYAMA @MPI first release.
+ 0.91 2005.06.01 Yusuke MURAYAMA @MPI if nargout==0, swap the original.
+
+ See also CLASS, INT16, UINT16, INT32, UINT32, SINGLE
+
+
+
diff --git a/mpi_code/mex_anz/make_hdr.c b/mpi_code/mex_anz/make_hdr.c
new file mode 100644
index 0000000..6f8d7f7
--- /dev/null
+++ b/mpi_code/mex_anz/make_hdr.c
@@ -0,0 +1,241 @@
+/* This program creates an ANALYZE(TM) database header */
+/*
+* (c) Copyright, 1986-1995
+* Biomedical Imaging Resource
+* Mayo Foundation
+*
+* to compile:
+* cc -o make_hdr make_hdr.c
+*
+* to compile in Matlab:
+* mex make_hdr.c -D_USE_IN_MATLAB
+*
+* 2005.05.31 Yusuke MURAYAMA @MPI supports Matlab.
+* 2005.06.01 Yusuke MURAYAMA @MPI supports BRU2ANZ.
+*
+* for detail, see http://www.mayo.edu/bir/PDF/ANALYZE75.pdf
+*/
+
+
+#include
+#include
+#include "dbh.h"
+
+#ifdef _USE_IN_MATLAB
+# include "matrix.h"
+# include "mex.h"
+/* Input Arguments */
+# define FILE_IN prhs[0]
+# define WIDTH_IN prhs[1]
+# define HEIGHT_IN prhs[2]
+# define DEPTH_IN prhs[3]
+# define VOLUME_IN prhs[4]
+# define DATATYPE_IN prhs[5]
+# define GLMAX_IN prhs[6]
+# define GLMIN_IN prhs[7]
+/* Output Arguments */
+# define STATUS_OUT plhs[0]
+#endif
+
+
+// PROTOTYPES //////////////////////////////////////////////////////
+int setup_header(struct dsr *, short, short, short, short, char *, int, int);
+
+
+// FUNCTIONS //////////////////////////////////////////////////////
+// setups the header with given parameters.
+int setup_header(struct dsr *phdr,
+ short width, short height, short depth, short volume,
+ char *typestr, int glmax, int glmin)
+{
+ static char DataTypes[9][12] = {"UNKNOWN", "BINARY",
+ "CHAR", "SHORT", "INT","FLOAT", "COMPLEX",
+ "DOUBLE", "RGB"};
+ static int DataTypeSizes[9] = {0,1,8,16,32,32,64,64,24};
+ int i;
+
+ memset(phdr,0, sizeof(struct dsr));
+
+ for(i = 0;i < 8; i++) phdr->dime.pixdim[i] = 0.0;
+ phdr->dime.vox_offset = 0.0;
+#ifdef BRU2ANZ
+ phdr->dime.roi_scale = 0.00392157f; // why 0.00392157f; ?????
+#else
+ phdr->dime.funused1 = 0.0;
+#endif
+ phdr->dime.funused2 = 0.0;
+ phdr->dime.funused3 = 0.0;
+ phdr->dime.cal_max = 0.0;
+ phdr->dime.cal_min = 0.0;
+ phdr->dime.datatype = -1;
+ for(i = 1; i <= 8; i++) {
+ if(stricmp(typestr,DataTypes[i]) == 0) {
+ phdr->dime.datatype = (1<<(i-1));
+ phdr->dime.bitpix = DataTypeSizes[i];
+ break;
+ }
+ }
+
+ phdr->dime.dim[0] = 4; // all Analyze images are taken as 4 dimensional
+ phdr->hk.regular = 'r';
+ phdr->hk.sizeof_hdr = sizeof(struct dsr);
+ phdr->dime.dim[1] = width; // slice width in pixels
+ phdr->dime.dim[2] = height; // slice height in pixels
+ phdr->dime.dim[3] = depth; // volume depth in slices
+ phdr->dime.dim[4] = volume; // number of volumes per file
+ phdr->dime.glmax = glmax; // maximum voxel value
+ phdr->dime.glmin = glmin; // minimum voxel value
+ // Set the voxel dimension fields:
+ // A value of 0.0 for these fields implies that the value is unknown.
+ // Change these values to what is appropriate for your data
+ // or pass additional command line arguments
+ phdr->dime.pixdim[1] = 0.0; /* voxel x dimension */
+ phdr->dime.pixdim[2] = 0.0; /* voxel y dimension */
+ phdr->dime.pixdim[3] = 0.0; /* pixel z dimension, slice thickness */
+ // Assume zero offset in .img file, byte at which pixel
+ // data starts in the image file
+ phdr->dime.vox_offset = 0.0;
+ // Planar Orientation;
+ // Movie flag OFF: 0 = transverse, 1 = coronal, 2 = sagittal
+ // Movie flag ON: 3 = transverse, 4 = coronal, 5 = sagittal
+ phdr->hist.orient = 0;
+
+#ifdef BRU2ANZ
+ // up to 3 characters for the voxels units label; i.e. mm., um., cm.
+ strcpy(phdr->dime.vox_units," ");
+ // up to 7 characters for the calibration units label; i.e. HU
+ strcpy(phdr->dime.cal_units," ");
+#endif
+
+ // Calibration maximum and minimum values;
+ // values of 0.0 for both fields imply that no
+ // calibration max and min values are used
+ phdr->dime.cal_max = 0.0;
+ phdr->dime.cal_min = 0.0;
+
+ return 0;
+}
+
+
+
+
+// MAIN FUNCTION /////////////////////////////////////////////////////
+#ifdef _USE_IN_MATLAB
+void mexFunction( int nlhs, mxArray *plhs[],
+ int nrhs, const mxArray*prhs[] )
+{
+ struct dsr hdr;
+ FILE *fp;
+ int status, i;
+ short x,y,z,t;
+ int glmax, glmin;
+ char *filename, *datatype;
+
+ if (nrhs == 0 || nrhs != 8) {
+ mexPrintf("Usage: status = make_hdr(filename,width,height,depth,volume,datatype,max,min)\n");
+ mexPrintf("Notes: datatype: BINARY,CHAR,SHORT,INT,FLOAT,COMPLEX,DOUBLE or RGB\n");
+ mexPrintf(" ver 0.91 Jun-2005 YM@MPI\n");
+ return;
+ }
+
+ filename = NULL; datatype = NULL;
+
+ if (mxIsChar(FILE_IN) != 1 || mxGetM(FILE_IN) != 1) {
+ mexErrMsgTxt("make_hdr: first arg must be a filename string.");
+ }
+ i = (mxGetM(FILE_IN) * mxGetN(FILE_IN)) + 1;
+ filename = mxCalloc(i,sizeof(char));
+ status = mxGetString(FILE_IN, filename, i);
+ if (status != 0)
+ mexWarnMsgTxt("make_hdr: not enough space, filename is truncated.");
+
+ x = (short) mxGetScalar(WIDTH_IN);
+ y = (short) mxGetScalar(HEIGHT_IN);
+ z = (short) mxGetScalar(DEPTH_IN);
+ t = (short) mxGetScalar(VOLUME_IN);
+ glmax = (int) mxGetScalar(GLMAX_IN);
+ glmin = (int) mxGetScalar(GLMIN_IN);
+
+ if (mxIsChar(DATATYPE_IN) != 1 || mxGetM(DATATYPE_IN) != 1) {
+ mexErrMsgTxt("make_hdr: 6th arg must be a datatype string.");
+ }
+ i = (mxGetM(DATATYPE_IN) * mxGetN(DATATYPE_IN)) + 1;
+ datatype = mxCalloc(i,sizeof(char));
+ status = mxGetString(DATATYPE_IN, datatype, i);
+ if (status != 0)
+ mexWarnMsgTxt("make_hdr: not enough space, datatype is truncated.");
+
+
+ status = setup_header(&hdr,x,y,z,t,datatype,glmax,glmin);
+ if(hdr.dime.datatype <= 0) {
+ mexPrintf("make_hdr: '%s' is an unacceptable datatype.\n", datatype);
+ mexErrMsgTxt("make_hdr: datatype should be BINARY,CHAR,SHORT,INT,FLOAT,COMPLEX,DOUBLE or RGB.");
+ }
+
+ if((fp = fopen(filename,"wb")) == NULL) {
+ mexPrintf("make_hdr: filename='%s'\n",filename);
+ mexErrMsgTxt("make_hdr: unable to create the file.");
+ }
+ i = fwrite(&hdr, sizeof(struct dsr),1,fp);
+ fclose(fp);
+#if 0
+ if (i != 1) {
+ mexPrintf("make_hdr: filename='%s'\n",filename);
+ mexErrMsgTxt("make_hdr: failed to write the header.");
+ }
+#endif
+
+ return;
+}
+
+#else
+void usage(void)
+{
+ printf("usage: make_hdr name.hdr x y z t datatype max min \n\n");
+ printf(" name.hdr = the name of the header file\n");
+ printf(" x = width, y = height, z = depth, t = number of volumes\n");
+ printf(" acceptable datatype values are: BINARY, CHAR, SHORT,\n");
+ printf(" INT, FLOAT, COMPLEX, DOUBLE, and RGB\n");
+ printf(" max = maximum voxel value, min = minimum voxel value\n");
+
+ return;
+}
+
+int main(int argc,char **argv) /* file x y z t datatype max min */
+{
+ struct dsr hdr;
+ FILE *fp;
+ int status;
+ short x,y,z,t;
+ int glmax, glmin;
+
+ if(argc != 9) {
+ usage();
+ exit(0);
+ }
+
+ x = (short)atoi(argv[2]); // slice width in pixels
+ y = (short)atoi(argv[3]); // slice height in pixels
+ z = (short)atoi(argv[4]); // volume depth in slices
+ t = (short)atoi(argv[5]); // number of volumes per file
+ glmax = atoi(argv[7]); // maximum voxel value
+ glmin = atoi(argv[8]); // minimum voxel value
+
+ status = setup_header(&hdr,x,y,z,t,argv[6],glmax,glmin);
+ if(hdr.dime.datatype <= 0) {
+ printf("<%s> is an unacceptable datatype \n\n", argv[6]);
+ usage();
+ exit(0);
+ }
+
+ if((fp = fopen(argv[1],"wb")) == 0) {
+ printf("unable to create: %s\n",argv[1]);
+ exit(0);
+ }
+ fwrite(&hdr,sizeof(struct dsr),1,fp);
+ fclose(fp);
+
+ return 1;
+}
+
+#endif
diff --git a/mpi_code/mex_anz/make_hdr.dll.old b/mpi_code/mex_anz/make_hdr.dll.old
new file mode 100644
index 0000000..489b0c2
Binary files /dev/null and b/mpi_code/mex_anz/make_hdr.dll.old differ
diff --git a/mpi_code/mex_anz/make_hdr.mexw32 b/mpi_code/mex_anz/make_hdr.mexw32
new file mode 100644
index 0000000..d2b0b82
Binary files /dev/null and b/mpi_code/mex_anz/make_hdr.mexw32 differ
diff --git a/mpi_code/mex_anz/make_hdr.mexw64 b/mpi_code/mex_anz/make_hdr.mexw64
new file mode 100644
index 0000000..0f668b3
Binary files /dev/null and b/mpi_code/mex_anz/make_hdr.mexw64 differ
diff --git a/mpi_code/mex_anz/mexanz.m b/mpi_code/mex_anz/mexanz.m
new file mode 100644
index 0000000..07d7b93
--- /dev/null
+++ b/mpi_code/mex_anz/mexanz.m
@@ -0,0 +1,14 @@
+%
+% mexanz.m : batch file to make all mex DLLs.
+%
+% VERSION : 1.00 31-May-2005 YM
+% : 1.01 10-Jan-2006 YM Matlab7.1 supports swapbytes()
+
+% make_hdr
+clear make_hdr;
+mex make_hdr.c -D_USE_IN_MATLAB
+
+% swap_endian
+clear utlswapbytes;
+mex utlswapbytes.c
+
diff --git a/mpi_code/mex_anz/nifti1.h b/mpi_code/mex_anz/nifti1.h
new file mode 100644
index 0000000..06d3665
--- /dev/null
+++ b/mpi_code/mex_anz/nifti1.h
@@ -0,0 +1,1490 @@
+/** \file nifti1.h
+ \brief Official definition of the nifti1 header. Written by Bob Cox, SSCC, NIMH.
+
+ HISTORY:
+
+ 29 Nov 2007 [rickr]
+ - added DT_RGBA32 and NIFTI_TYPE_RGBA32
+ - added NIFTI_INTENT codes:
+ TIME_SERIES, NODE_INDEX, RGB_VECTOR, RGBA_VECTOR, SHAPE
+ */
+
+#ifndef _NIFTI_HEADER_
+#define _NIFTI_HEADER_
+
+/*****************************************************************************
+ ** This file defines the "NIFTI-1" header format. **
+ ** It is derived from 2 meetings at the NIH (31 Mar 2003 and **
+ ** 02 Sep 2003) of the Data Format Working Group (DFWG), **
+ ** chartered by the NIfTI (Neuroimaging Informatics Technology **
+ ** Initiative) at the National Institutes of Health (NIH). **
+ **--------------------------------------------------------------**
+ ** Neither the National Institutes of Health (NIH), the DFWG, **
+ ** nor any of the members or employees of these institutions **
+ ** imply any warranty of usefulness of this material for any **
+ ** purpose, and do not assume any liability for damages, **
+ ** incidental or otherwise, caused by any use of this document. **
+ ** If these conditions are not acceptable, do not use this! **
+ **--------------------------------------------------------------**
+ ** Author: Robert W Cox (NIMH, Bethesda) **
+ ** Advisors: John Ashburner (FIL, London), **
+ ** Stephen Smith (FMRIB, Oxford), **
+ ** Mark Jenkinson (FMRIB, Oxford) **
+******************************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Note that the ANALYZE 7.5 file header (dbh.h) is
+ (c) Copyright 1986-1995
+ Biomedical Imaging Resource
+ Mayo Foundation
+ Incorporation of components of dbh.h are by permission of the
+ Mayo Foundation.
+
+ Changes from the ANALYZE 7.5 file header in this file are released to the
+ public domain, including the functional comments and any amusing asides.
+-----------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/*! INTRODUCTION TO NIFTI-1:
+ ------------------------
+ The twin (and somewhat conflicting) goals of this modified ANALYZE 7.5
+ format are:
+ (a) To add information to the header that will be useful for functional
+ neuroimaging data analysis and display. These additions include:
+ - More basic data types.
+ - Two affine transformations to specify voxel coordinates.
+ - "Intent" codes and parameters to describe the meaning of the data.
+ - Affine scaling of the stored data values to their "true" values.
+ - Optional storage of the header and image data in one file (.nii).
+ (b) To maintain compatibility with non-NIFTI-aware ANALYZE 7.5 compatible
+ software (i.e., such a program should be able to do something useful
+ with a NIFTI-1 dataset -- at least, with one stored in a traditional
+ .img/.hdr file pair).
+
+ Most of the unused fields in the ANALYZE 7.5 header have been taken,
+ and some of the lesser-used fields have been co-opted for other purposes.
+ Notably, most of the data_history substructure has been co-opted for
+ other purposes, since the ANALYZE 7.5 format describes this substructure
+ as "not required".
+
+ NIFTI-1 FLAG (MAGIC STRINGS):
+ ----------------------------
+ To flag such a struct as being conformant to the NIFTI-1 spec, the last 4
+ bytes of the header must be either the C String "ni1" or "n+1";
+ in hexadecimal, the 4 bytes
+ 6E 69 31 00 or 6E 2B 31 00
+ (in any future version of this format, the '1' will be upgraded to '2',
+ etc.). Normally, such a "magic number" or flag goes at the start of the
+ file, but trying to avoid clobbering widely-used ANALYZE 7.5 fields led to
+ putting this marker last. However, recall that "the last shall be first"
+ (Matthew 20:16).
+
+ If a NIFTI-aware program reads a header file that is NOT marked with a
+ NIFTI magic string, then it should treat the header as an ANALYZE 7.5
+ structure.
+
+ NIFTI-1 FILE STORAGE:
+ --------------------
+ "ni1" means that the image data is stored in the ".img" file corresponding
+ to the header file (starting at file offset 0).
+
+ "n+1" means that the image data is stored in the same file as the header
+ information. We recommend that the combined header+data filename suffix
+ be ".nii". When the dataset is stored in one file, the first byte of image
+ data is stored at byte location (int)vox_offset in this combined file.
+ The minimum allowed value of vox_offset is 352; for compatibility with
+ some software, vox_offset should be an integral multiple of 16.
+
+ GRACE UNDER FIRE:
+ ----------------
+ Most NIFTI-aware programs will only be able to handle a subset of the full
+ range of datasets possible with this format. All NIFTI-aware programs
+ should take care to check if an input dataset conforms to the program's
+ needs and expectations (e.g., check datatype, intent_code, etc.). If the
+ input dataset can't be handled by the program, the program should fail
+ gracefully (e.g., print a useful warning; not crash).
+
+ SAMPLE CODES:
+ ------------
+ The associated files nifti1_io.h and nifti1_io.c provide a sample
+ implementation in C of a set of functions to read, write, and manipulate
+ NIFTI-1 files. The file nifti1_test.c is a sample program that uses
+ the nifti1_io.c functions.
+-----------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* HEADER STRUCT DECLARATION:
+ -------------------------
+ In the comments below for each field, only NIFTI-1 specific requirements
+ or changes from the ANALYZE 7.5 format are described. For convenience,
+ the 348 byte header is described as a single struct, rather than as the
+ ANALYZE 7.5 group of 3 substructs.
+
+ Further comments about the interpretation of various elements of this
+ header are after the data type definition itself. Fields that are
+ marked as ++UNUSED++ have no particular interpretation in this standard.
+ (Also see the UNUSED FIELDS comment section, far below.)
+
+ The presumption below is that the various C types have particular sizes:
+ sizeof(int) = sizeof(float) = 4 ; sizeof(short) = 2
+-----------------------------------------------------------------------------*/
+
+/*=================*/
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*=================*/
+
+/*! \struct nifti_1_header
+ \brief Data structure defining the fields in the nifti1 header.
+ This binary header should be found at the beginning of a valid
+ NIFTI-1 header file.
+ */
+ /*************************/ /************************/
+struct nifti_1_header { /* NIFTI-1 usage */ /* ANALYZE 7.5 field(s) */
+ /*************************/ /************************/
+
+ /*--- was header_key substruct ---*/
+ int sizeof_hdr; /*!< MUST be 348 */ /* int sizeof_hdr; */
+ char data_type[10]; /*!< ++UNUSED++ */ /* char data_type[10]; */
+ char db_name[18]; /*!< ++UNUSED++ */ /* char db_name[18]; */
+ int extents; /*!< ++UNUSED++ */ /* int extents; */
+ short session_error; /*!< ++UNUSED++ */ /* short session_error; */
+ char regular; /*!< ++UNUSED++ */ /* char regular; */
+ char dim_info; /*!< MRI slice ordering. */ /* char hkey_un0; */
+
+ /*--- was image_dimension substruct ---*/
+ short dim[8]; /*!< Data array dimensions.*/ /* short dim[8]; */
+ float intent_p1 ; /*!< 1st intent parameter. */ /* short unused8; */
+ /* short unused9; */
+ float intent_p2 ; /*!< 2nd intent parameter. */ /* short unused10; */
+ /* short unused11; */
+ float intent_p3 ; /*!< 3rd intent parameter. */ /* short unused12; */
+ /* short unused13; */
+ short intent_code ; /*!< NIFTI_INTENT_* code. */ /* short unused14; */
+ short datatype; /*!< Defines data type! */ /* short datatype; */
+ short bitpix; /*!< Number bits/voxel. */ /* short bitpix; */
+ short slice_start; /*!< First slice index. */ /* short dim_un0; */
+ float pixdim[8]; /*!< Grid spacings. */ /* float pixdim[8]; */
+ float vox_offset; /*!< Offset into .nii file */ /* float vox_offset; */
+ float scl_slope ; /*!< Data scaling: slope. */ /* float funused1; */
+ float scl_inter ; /*!< Data scaling: offset. */ /* float funused2; */
+ short slice_end; /*!< Last slice index. */ /* float funused3; */
+ char slice_code ; /*!< Slice timing order. */
+ char xyzt_units ; /*!< Units of pixdim[1..4] */
+ float cal_max; /*!< Max display intensity */ /* float cal_max; */
+ float cal_min; /*!< Min display intensity */ /* float cal_min; */
+ float slice_duration;/*!< Time for 1 slice. */ /* float compressed; */
+ float toffset; /*!< Time axis shift. */ /* float verified; */
+ int glmax; /*!< ++UNUSED++ */ /* int glmax; */
+ int glmin; /*!< ++UNUSED++ */ /* int glmin; */
+
+ /*--- was data_history substruct ---*/
+ char descrip[80]; /*!< any text you like. */ /* char descrip[80]; */
+ char aux_file[24]; /*!< auxiliary filename. */ /* char aux_file[24]; */
+
+ short qform_code ; /*!< NIFTI_XFORM_* code. */ /*-- all ANALYZE 7.5 ---*/
+ short sform_code ; /*!< NIFTI_XFORM_* code. */ /* fields below here */
+ /* are replaced */
+ float quatern_b ; /*!< Quaternion b param. */
+ float quatern_c ; /*!< Quaternion c param. */
+ float quatern_d ; /*!< Quaternion d param. */
+ float qoffset_x ; /*!< Quaternion x shift. */
+ float qoffset_y ; /*!< Quaternion y shift. */
+ float qoffset_z ; /*!< Quaternion z shift. */
+
+ float srow_x[4] ; /*!< 1st row affine transform. */
+ float srow_y[4] ; /*!< 2nd row affine transform. */
+ float srow_z[4] ; /*!< 3rd row affine transform. */
+
+ char intent_name[16];/*!< 'name' or meaning of data. */
+
+ char magic[4] ; /*!< MUST be "ni1\0" or "n+1\0". */
+
+} ; /**** 348 bytes total ****/
+
+typedef struct nifti_1_header nifti_1_header ;
+
+/*---------------------------------------------------------------------------*/
+/* HEADER EXTENSIONS:
+ -----------------
+ After the end of the 348 byte header (e.g., after the magic field),
+ the next 4 bytes are a char array field named "extension". By default,
+ all 4 bytes of this array should be set to zero. In a .nii file, these
+ 4 bytes will always be present, since the earliest start point for
+ the image data is byte #352. In a separate .hdr file, these bytes may
+ or may not be present. If not present (i.e., if the length of the .hdr
+ file is 348 bytes), then a NIfTI-1 compliant program should use the
+ default value of extension={0,0,0,0}. The first byte (extension[0])
+ is the only value of this array that is specified at present. The other
+ 3 bytes are reserved for future use.
+
+ If extension[0] is nonzero, it indicates that extended header information
+ is present in the bytes following the extension array. In a .nii file,
+ this extended header data is before the image data (and vox_offset
+ must be set correctly to allow for this). In a .hdr file, this extended
+ data follows extension and proceeds (potentially) to the end of the file.
+
+ The format of extended header data is weakly specified. Each extension
+ must be an integer multiple of 16 bytes long. The first 8 bytes of each
+ extension comprise 2 integers:
+ int esize , ecode ;
+ These values may need to be byte-swapped, as indicated by dim[0] for
+ the rest of the header.
+ * esize is the number of bytes that form the extended header data
+ + esize must be a positive integral multiple of 16
+ + this length includes the 8 bytes of esize and ecode themselves
+ * ecode is a non-negative integer that indicates the format of the
+ extended header data that follows
+ + different ecode values are assigned to different developer groups
+ + at present, the "registered" values for code are
+ = 0 = unknown private format (not recommended!)
+ = 2 = DICOM format (i.e., attribute tags and values)
+ = 4 = AFNI group (i.e., ASCII XML-ish elements)
+ In the interests of interoperability (a primary rationale for NIfTI),
+ groups developing software that uses this extension mechanism are
+ encouraged to document and publicize the format of their extensions.
+ To this end, the NIfTI DFWG will assign even numbered codes upon request
+ to groups submitting at least rudimentary documentation for the format
+ of their extension; at present, the contact is mailto:rwcox@nih.gov.
+ The assigned codes and documentation will be posted on the NIfTI
+ website. All odd values of ecode (and 0) will remain unassigned;
+ at least, until the even ones are used up, when we get to 2,147,483,646.
+
+ Note that the other contents of the extended header data section are
+ totally unspecified by the NIfTI-1 standard. In particular, if binary
+ data is stored in such a section, its byte order is not necessarily
+ the same as that given by examining dim[0]; it is incumbent on the
+ programs dealing with such data to determine the byte order of binary
+ extended header data.
+
+ Multiple extended header sections are allowed, each starting with an
+ esize,ecode value pair. The first esize value, as described above,
+ is at bytes #352-355 in the .hdr or .nii file (files start at byte #0).
+ If this value is positive, then the second (esize2) will be found
+ starting at byte #352+esize1 , the third (esize3) at byte #352+esize1+esize2,
+ et cetera. Of course, in a .nii file, the value of vox_offset must
+ be compatible with these extensions. If a malformed file indicates
+ that an extended header data section would run past vox_offset, then
+ the entire extended header section should be ignored. In a .hdr file,
+ if an extended header data section would run past the end-of-file,
+ that extended header data should also be ignored.
+
+ With the above scheme, a program can successively examine the esize
+ and ecode values, and skip over each extended header section if the
+ program doesn't know how to interpret the data within. Of course, any
+ program can simply ignore all extended header sections simply by jumping
+ straight to the image data using vox_offset.
+-----------------------------------------------------------------------------*/
+
+/*! \struct nifti1_extender
+ \brief This structure represents a 4-byte string that should follow the
+ binary nifti_1_header data in a NIFTI-1 header file. If the char
+ values are {1,0,0,0}, the file is expected to contain extensions,
+ values of {0,0,0,0} imply the file does not contain extensions.
+ Other sequences of values are not currently defined.
+ */
+struct nifti1_extender { char extension[4] ; } ;
+typedef struct nifti1_extender nifti1_extender ;
+
+/*! \struct nifti1_extension
+ \brief Data structure defining the fields of a header extension.
+ */
+struct nifti1_extension {
+ int esize ; /*!< size of extension, in bytes (must be multiple of 16) */
+ int ecode ; /*!< extension code, one of the NIFTI_ECODE_ values */
+ char * edata ; /*!< raw data, with no byte swapping (length is esize-8) */
+} ;
+typedef struct nifti1_extension nifti1_extension ;
+
+/*---------------------------------------------------------------------------*/
+/* DATA DIMENSIONALITY (as in ANALYZE 7.5):
+ ---------------------------------------
+ dim[0] = number of dimensions;
+ - if dim[0] is outside range 1..7, then the header information
+ needs to be byte swapped appropriately
+ - ANALYZE supports dim[0] up to 7, but NIFTI-1 reserves
+ dimensions 1,2,3 for space (x,y,z), 4 for time (t), and
+ 5,6,7 for anything else needed.
+
+ dim[i] = length of dimension #i, for i=1..dim[0] (must be positive)
+ - also see the discussion of intent_code, far below
+
+ pixdim[i] = voxel width along dimension #i, i=1..dim[0] (positive)
+ - cf. ORIENTATION section below for use of pixdim[0]
+ - the units of pixdim can be specified with the xyzt_units
+ field (also described far below).
+
+ Number of bits per voxel value is in bitpix, which MUST correspond with
+ the datatype field. The total number of bytes in the image data is
+ dim[1] * ... * dim[dim[0]] * bitpix / 8
+
+ In NIFTI-1 files, dimensions 1,2,3 are for space, dimension 4 is for time,
+ and dimension 5 is for storing multiple values at each spatiotemporal
+ voxel. Some examples:
+ - A typical whole-brain FMRI experiment's time series:
+ - dim[0] = 4
+ - dim[1] = 64 pixdim[1] = 3.75 xyzt_units = NIFTI_UNITS_MM
+ - dim[2] = 64 pixdim[2] = 3.75 | NIFTI_UNITS_SEC
+ - dim[3] = 20 pixdim[3] = 5.0
+ - dim[4] = 120 pixdim[4] = 2.0
+ - A typical T1-weighted anatomical volume:
+ - dim[0] = 3
+ - dim[1] = 256 pixdim[1] = 1.0 xyzt_units = NIFTI_UNITS_MM
+ - dim[2] = 256 pixdim[2] = 1.0
+ - dim[3] = 128 pixdim[3] = 1.1
+ - A single slice EPI time series:
+ - dim[0] = 4
+ - dim[1] = 64 pixdim[1] = 3.75 xyzt_units = NIFTI_UNITS_MM
+ - dim[2] = 64 pixdim[2] = 3.75 | NIFTI_UNITS_SEC
+ - dim[3] = 1 pixdim[3] = 5.0
+ - dim[4] = 1200 pixdim[4] = 0.2
+ - A 3-vector stored at each point in a 3D volume:
+ - dim[0] = 5
+ - dim[1] = 256 pixdim[1] = 1.0 xyzt_units = NIFTI_UNITS_MM
+ - dim[2] = 256 pixdim[2] = 1.0
+ - dim[3] = 128 pixdim[3] = 1.1
+ - dim[4] = 1 pixdim[4] = 0.0
+ - dim[5] = 3 intent_code = NIFTI_INTENT_VECTOR
+ - A single time series with a 3x3 matrix at each point:
+ - dim[0] = 5
+ - dim[1] = 1 xyzt_units = NIFTI_UNITS_SEC
+ - dim[2] = 1
+ - dim[3] = 1
+ - dim[4] = 1200 pixdim[4] = 0.2
+ - dim[5] = 9 intent_code = NIFTI_INTENT_GENMATRIX
+ - intent_p1 = intent_p2 = 3.0 (indicates matrix dimensions)
+-----------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* DATA STORAGE:
+ ------------
+ If the magic field is "n+1", then the voxel data is stored in the
+ same file as the header. In this case, the voxel data starts at offset
+ (int)vox_offset into the header file. Thus, vox_offset=352.0 means that
+ the data starts immediately after the NIFTI-1 header. If vox_offset is
+ greater than 352, the NIFTI-1 format does not say much about the
+ contents of the dataset file between the end of the header and the
+ start of the data.
+
+ FILES:
+ -----
+ If the magic field is "ni1", then the voxel data is stored in the
+ associated ".img" file, starting at offset 0 (i.e., vox_offset is not
+ used in this case, and should be set to 0.0).
+
+ When storing NIFTI-1 datasets in pairs of files, it is customary to name
+ the files in the pattern "name.hdr" and "name.img", as in ANALYZE 7.5.
+ When storing in a single file ("n+1"), the file name should be in
+ the form "name.nii" (the ".nft" and ".nif" suffixes are already taken;
+ cf. http://www.icdatamaster.com/n.html ).
+
+ BYTE ORDERING:
+ -------------
+ The byte order of the data arrays is presumed to be the same as the byte
+ order of the header (which is determined by examining dim[0]).
+
+ Floating point types are presumed to be stored in IEEE-754 format.
+-----------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* DETAILS ABOUT vox_offset:
+ ------------------------
+ In a .nii file, the vox_offset field value is interpreted as the start
+ location of the image data bytes in that file. In a .hdr/.img file pair,
+ the vox_offset field value is the start location of the image data
+ bytes in the .img file.
+ * If vox_offset is less than 352 in a .nii file, it is equivalent
+ to 352 (i.e., image data never starts before byte #352 in a .nii file).
+ * The default value for vox_offset in a .nii file is 352.
+ * In a .hdr file, the default value for vox_offset is 0.
+ * vox_offset should be an integer multiple of 16; otherwise, some
+ programs may not work properly (e.g., SPM). This is to allow
+ memory-mapped input to be properly byte-aligned.
+ Note that since vox_offset is an IEEE-754 32 bit float (for compatibility
+ with the ANALYZE-7.5 format), it effectively has a 24 bit mantissa. All
+ integers from 0 to 2^24 can be represented exactly in this format, but not
+ all larger integers are exactly storable as IEEE-754 32 bit floats. However,
+ unless you plan to have vox_offset be potentially larger than 16 MB, this
+ should not be an issue. (Actually, any integral multiple of 16 up to 2^27
+ can be represented exactly in this format, which allows for up to 128 MB
+ of random information before the image data. If that isn't enough, then
+ perhaps this format isn't right for you.)
+
+ In a .img file (i.e., image data stored separately from the NIfTI-1
+ header), data bytes between #0 and #vox_offset-1 (inclusive) are completely
+ undefined and unregulated by the NIfTI-1 standard. One potential use of
+ having vox_offset > 0 in the .hdr/.img file pair storage method is to make
+ the .img file be a copy of (or link to) a pre-existing image file in some
+ other format, such as DICOM; then vox_offset would be set to the offset of
+ the image data in this file. (It may not be possible to follow the
+ "multiple-of-16 rule" with an arbitrary external file; using the NIfTI-1
+ format in such a case may lead to a file that is incompatible with software
+ that relies on vox_offset being a multiple of 16.)
+
+ In a .nii file, data bytes between #348 and #vox_offset-1 (inclusive) may
+ be used to store user-defined extra information; similarly, in a .hdr file,
+ any data bytes after byte #347 are available for user-defined extra
+ information. The (very weak) regulation of this extra header data is
+ described elsewhere.
+-----------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* DATA SCALING:
+ ------------
+ If the scl_slope field is nonzero, then each voxel value in the dataset
+ should be scaled as
+ y = scl_slope * x + scl_inter
+ where x = voxel value stored
+ y = "true" voxel value
+ Normally, we would expect this scaling to be used to store "true" floating
+ values in a smaller integer datatype, but that is not required. That is,
+ it is legal to use scaling even if the datatype is a float type (crazy,
+ perhaps, but legal).
+ - However, the scaling is to be ignored if datatype is DT_RGB24.
+ - If datatype is a complex type, then the scaling is to be
+ applied to both the real and imaginary parts.
+
+ The cal_min and cal_max fields (if nonzero) are used for mapping (possibly
+ scaled) dataset values to display colors:
+ - Minimum display intensity (black) corresponds to dataset value cal_min.
+ - Maximum display intensity (white) corresponds to dataset value cal_max.
+ - Dataset values below cal_min should display as black also, and values
+ above cal_max as white.
+ - Colors "black" and "white", of course, may refer to any scalar display
+ scheme (e.g., a color lookup table specified via aux_file).
+ - cal_min and cal_max only make sense when applied to scalar-valued
+ datasets (i.e., dim[0] < 5 or dim[5] = 1).
+-----------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* TYPE OF DATA (acceptable values for datatype field):
+ ---------------------------------------------------
+ Values of datatype smaller than 256 are ANALYZE 7.5 compatible.
+ Larger values are NIFTI-1 additions. These are all multiples of 256, so
+ that no bits below position 8 are set in datatype. But there is no need
+ to use only powers-of-2, as the original ANALYZE 7.5 datatype codes do.
+
+ The additional codes are intended to include a complete list of basic
+ scalar types, including signed and unsigned integers from 8 to 64 bits,
+ floats from 32 to 128 bits, and complex (float pairs) from 64 to 256 bits.
+
+ Note that most programs will support only a few of these datatypes!
+ A NIFTI-1 program should fail gracefully (e.g., print a warning message)
+ when it encounters a dataset with a type it doesn't like.
+-----------------------------------------------------------------------------*/
+
+#undef DT_UNKNOWN /* defined in dirent.h on some Unix systems */
+
+/*! \defgroup NIFTI1_DATATYPES
+ \brief nifti1 datatype codes
+ @{
+ */
+ /*--- the original ANALYZE 7.5 type codes ---*/
+#define DT_NONE 0
+#define DT_UNKNOWN 0 /* what it says, dude */
+#define DT_BINARY 1 /* binary (1 bit/voxel) */
+#define DT_UNSIGNED_CHAR 2 /* unsigned char (8 bits/voxel) */
+#define DT_SIGNED_SHORT 4 /* signed short (16 bits/voxel) */
+#define DT_SIGNED_INT 8 /* signed int (32 bits/voxel) */
+#define DT_FLOAT 16 /* float (32 bits/voxel) */
+#define DT_COMPLEX 32 /* complex (64 bits/voxel) */
+#define DT_DOUBLE 64 /* double (64 bits/voxel) */
+#define DT_RGB 128 /* RGB triple (24 bits/voxel) */
+#define DT_ALL 255 /* not very useful (?) */
+
+ /*----- another set of names for the same ---*/
+#define DT_UINT8 2
+#define DT_INT16 4
+#define DT_INT32 8
+#define DT_FLOAT32 16
+#define DT_COMPLEX64 32
+#define DT_FLOAT64 64
+#define DT_RGB24 128
+
+ /*------------------- new codes for NIFTI ---*/
+#define DT_INT8 256 /* signed char (8 bits) */
+#define DT_UINT16 512 /* unsigned short (16 bits) */
+#define DT_UINT32 768 /* unsigned int (32 bits) */
+#define DT_INT64 1024 /* long long (64 bits) */
+#define DT_UINT64 1280 /* unsigned long long (64 bits) */
+#define DT_FLOAT128 1536 /* long double (128 bits) */
+#define DT_COMPLEX128 1792 /* double pair (128 bits) */
+#define DT_COMPLEX256 2048 /* long double pair (256 bits) */
+#define DT_RGBA32 2304 /* 4 byte RGBA (32 bits/voxel) */
+/* @} */
+
+
+ /*------- aliases for all the above codes ---*/
+
+/*! \defgroup NIFTI1_DATATYPE_ALIASES
+ \brief aliases for the nifti1 datatype codes
+ @{
+ */
+ /*! unsigned char. */
+#define NIFTI_TYPE_UINT8 2
+ /*! signed short. */
+#define NIFTI_TYPE_INT16 4
+ /*! signed int. */
+#define NIFTI_TYPE_INT32 8
+ /*! 32 bit float. */
+#define NIFTI_TYPE_FLOAT32 16
+ /*! 64 bit complex = 2 32 bit floats. */
+#define NIFTI_TYPE_COMPLEX64 32
+ /*! 64 bit float = double. */
+#define NIFTI_TYPE_FLOAT64 64
+ /*! 3 8 bit bytes. */
+#define NIFTI_TYPE_RGB24 128
+ /*! signed char. */
+#define NIFTI_TYPE_INT8 256
+ /*! unsigned short. */
+#define NIFTI_TYPE_UINT16 512
+ /*! unsigned int. */
+#define NIFTI_TYPE_UINT32 768
+ /*! signed long long. */
+#define NIFTI_TYPE_INT64 1024
+ /*! unsigned long long. */
+#define NIFTI_TYPE_UINT64 1280
+ /*! 128 bit float = long double. */
+#define NIFTI_TYPE_FLOAT128 1536
+ /*! 128 bit complex = 2 64 bit floats. */
+#define NIFTI_TYPE_COMPLEX128 1792
+ /*! 256 bit complex = 2 128 bit floats */
+#define NIFTI_TYPE_COMPLEX256 2048
+ /*! 4 8 bit bytes. */
+#define NIFTI_TYPE_RGBA32 2304
+/* @} */
+
+ /*-------- sample typedefs for complicated types ---*/
+#if 0
+typedef struct { float r,i; } complex_float ;
+typedef struct { double r,i; } complex_double ;
+typedef struct { long double r,i; } complex_longdouble ;
+typedef struct { unsigned char r,g,b; } rgb_byte ;
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* INTERPRETATION OF VOXEL DATA:
+ ----------------------------
+ The intent_code field can be used to indicate that the voxel data has
+ some particular meaning. In particular, a large number of codes is
+ given to indicate that the the voxel data should be interpreted as
+ being drawn from a given probability distribution.
+
+ VECTOR-VALUED DATASETS:
+ ----------------------
+ The 5th dimension of the dataset, if present (i.e., dim[0]=5 and
+ dim[5] > 1), contains multiple values (e.g., a vector) to be stored
+ at each spatiotemporal location. For example, the header values
+ - dim[0] = 5
+ - dim[1] = 64
+ - dim[2] = 64
+ - dim[3] = 20
+ - dim[4] = 1 (indicates no time axis)
+ - dim[5] = 3
+ - datatype = DT_FLOAT
+ - intent_code = NIFTI_INTENT_VECTOR
+ mean that this dataset should be interpreted as a 3D volume (64x64x20),
+ with a 3-vector of floats defined at each point in the 3D grid.
+
+ A program reading a dataset with a 5th dimension may want to reformat
+ the image data to store each voxels' set of values together in a struct
+ or array. This programming detail, however, is beyond the scope of the
+ NIFTI-1 file specification! Uses of dimensions 6 and 7 are also not
+ specified here.
+
+ STATISTICAL PARAMETRIC DATASETS (i.e., SPMs):
+ --------------------------------------------
+ Values of intent_code from NIFTI_FIRST_STATCODE to NIFTI_LAST_STATCODE
+ (inclusive) indicate that the numbers in the dataset should be interpreted
+ as being drawn from a given distribution. Most such distributions have
+ auxiliary parameters (e.g., NIFTI_INTENT_TTEST has 1 DOF parameter).
+
+ If the dataset DOES NOT have a 5th dimension, then the auxiliary parameters
+ are the same for each voxel, and are given in header fields intent_p1,
+ intent_p2, and intent_p3.
+
+ If the dataset DOES have a 5th dimension, then the auxiliary parameters
+ are different for each voxel. For example, the header values
+ - dim[0] = 5
+ - dim[1] = 128
+ - dim[2] = 128
+ - dim[3] = 1 (indicates a single slice)
+ - dim[4] = 1 (indicates no time axis)
+ - dim[5] = 2
+ - datatype = DT_FLOAT
+ - intent_code = NIFTI_INTENT_TTEST
+ mean that this is a 2D dataset (128x128) of t-statistics, with the
+ t-statistic being in the first "plane" of data and the degrees-of-freedom
+ parameter being in the second "plane" of data.
+
+ If the dataset 5th dimension is used to store the voxel-wise statistical
+ parameters, then dim[5] must be 1 plus the number of parameters required
+ by that distribution (e.g., intent_code=NIFTI_INTENT_TTEST implies dim[5]
+ must be 2, as in the example just above).
+
+ Note: intent_code values 2..10 are compatible with AFNI 1.5x (which is
+ why there is no code with value=1, which is obsolescent in AFNI).
+
+ OTHER INTENTIONS:
+ ----------------
+ The purpose of the intent_* fields is to help interpret the values
+ stored in the dataset. Some non-statistical values for intent_code
+ and conventions are provided for storing other complex data types.
+
+ The intent_name field provides space for a 15 character (plus 0 byte)
+ 'name' string for the type of data stored. Examples:
+ - intent_code = NIFTI_INTENT_ESTIMATE; intent_name = "T1";
+ could be used to signify that the voxel values are estimates of the
+ NMR parameter T1.
+ - intent_code = NIFTI_INTENT_TTEST; intent_name = "House";
+ could be used to signify that the voxel values are t-statistics
+ for the significance of 'activation' response to a House stimulus.
+ - intent_code = NIFTI_INTENT_DISPVECT; intent_name = "ToMNI152";
+ could be used to signify that the voxel values are a displacement
+ vector that transforms each voxel (x,y,z) location to the
+ corresponding location in the MNI152 standard brain.
+ - intent_code = NIFTI_INTENT_SYMMATRIX; intent_name = "DTI";
+ could be used to signify that the voxel values comprise a diffusion
+ tensor image.
+
+ If no data name is implied or needed, intent_name[0] should be set to 0.
+-----------------------------------------------------------------------------*/
+
+ /*! default: no intention is indicated in the header. */
+
+#define NIFTI_INTENT_NONE 0
+
+ /*-------- These codes are for probability distributions ---------------*/
+ /* Most distributions have a number of parameters,
+ below denoted by p1, p2, and p3, and stored in
+ - intent_p1, intent_p2, intent_p3 if dataset doesn't have 5th dimension
+ - image data array if dataset does have 5th dimension
+
+ Functions to compute with many of the distributions below can be found
+ in the CDF library from U Texas.
+
+ Formulas for and discussions of these distributions can be found in the
+ following books:
+
+ [U] Univariate Discrete Distributions,
+ NL Johnson, S Kotz, AW Kemp.
+
+ [C1] Continuous Univariate Distributions, vol. 1,
+ NL Johnson, S Kotz, N Balakrishnan.
+
+ [C2] Continuous Univariate Distributions, vol. 2,
+ NL Johnson, S Kotz, N Balakrishnan. */
+ /*----------------------------------------------------------------------*/
+
+ /*! [C2, chap 32] Correlation coefficient R (1 param):
+ p1 = degrees of freedom
+ R/sqrt(1-R*R) is t-distributed with p1 DOF. */
+
+/*! \defgroup NIFTI1_INTENT_CODES
+ \brief nifti1 intent codes, to describe intended meaning of dataset contents
+ @{
+ */
+#define NIFTI_INTENT_CORREL 2
+
+ /*! [C2, chap 28] Student t statistic (1 param): p1 = DOF. */
+
+#define NIFTI_INTENT_TTEST 3
+
+ /*! [C2, chap 27] Fisher F statistic (2 params):
+ p1 = numerator DOF, p2 = denominator DOF. */
+
+#define NIFTI_INTENT_FTEST 4
+
+ /*! [C1, chap 13] Standard normal (0 params): Density = N(0,1). */
+
+#define NIFTI_INTENT_ZSCORE 5
+
+ /*! [C1, chap 18] Chi-squared (1 param): p1 = DOF.
+ Density(x) proportional to exp(-x/2) * x^(p1/2-1). */
+
+#define NIFTI_INTENT_CHISQ 6
+
+ /*! [C2, chap 25] Beta distribution (2 params): p1=a, p2=b.
+ Density(x) proportional to x^(a-1) * (1-x)^(b-1). */
+
+#define NIFTI_INTENT_BETA 7
+
+ /*! [U, chap 3] Binomial distribution (2 params):
+ p1 = number of trials, p2 = probability per trial.
+ Prob(x) = (p1 choose x) * p2^x * (1-p2)^(p1-x), for x=0,1,...,p1. */
+
+#define NIFTI_INTENT_BINOM 8
+
+ /*! [C1, chap 17] Gamma distribution (2 params):
+ p1 = shape, p2 = scale.
+ Density(x) proportional to x^(p1-1) * exp(-p2*x). */
+
+#define NIFTI_INTENT_GAMMA 9
+
+ /*! [U, chap 4] Poisson distribution (1 param): p1 = mean.
+ Prob(x) = exp(-p1) * p1^x / x! , for x=0,1,2,.... */
+
+#define NIFTI_INTENT_POISSON 10
+
+ /*! [C1, chap 13] Normal distribution (2 params):
+ p1 = mean, p2 = standard deviation. */
+
+#define NIFTI_INTENT_NORMAL 11
+
+ /*! [C2, chap 30] Noncentral F statistic (3 params):
+ p1 = numerator DOF, p2 = denominator DOF,
+ p3 = numerator noncentrality parameter. */
+
+#define NIFTI_INTENT_FTEST_NONC 12
+
+ /*! [C2, chap 29] Noncentral chi-squared statistic (2 params):
+ p1 = DOF, p2 = noncentrality parameter. */
+
+#define NIFTI_INTENT_CHISQ_NONC 13
+
+ /*! [C2, chap 23] Logistic distribution (2 params):
+ p1 = location, p2 = scale.
+ Density(x) proportional to sech^2((x-p1)/(2*p2)). */
+
+#define NIFTI_INTENT_LOGISTIC 14
+
+ /*! [C2, chap 24] Laplace distribution (2 params):
+ p1 = location, p2 = scale.
+ Density(x) proportional to exp(-abs(x-p1)/p2). */
+
+#define NIFTI_INTENT_LAPLACE 15
+
+ /*! [C2, chap 26] Uniform distribution: p1 = lower end, p2 = upper end. */
+
+#define NIFTI_INTENT_UNIFORM 16
+
+ /*! [C2, chap 31] Noncentral t statistic (2 params):
+ p1 = DOF, p2 = noncentrality parameter. */
+
+#define NIFTI_INTENT_TTEST_NONC 17
+
+ /*! [C1, chap 21] Weibull distribution (3 params):
+ p1 = location, p2 = scale, p3 = power.
+ Density(x) proportional to
+ ((x-p1)/p2)^(p3-1) * exp(-((x-p1)/p2)^p3) for x > p1. */
+
+#define NIFTI_INTENT_WEIBULL 18
+
+ /*! [C1, chap 18] Chi distribution (1 param): p1 = DOF.
+ Density(x) proportional to x^(p1-1) * exp(-x^2/2) for x > 0.
+ p1 = 1 = 'half normal' distribution
+ p1 = 2 = Rayleigh distribution
+ p1 = 3 = Maxwell-Boltzmann distribution. */
+
+#define NIFTI_INTENT_CHI 19
+
+ /*! [C1, chap 15] Inverse Gaussian (2 params):
+ p1 = mu, p2 = lambda
+ Density(x) proportional to
+ exp(-p2*(x-p1)^2/(2*p1^2*x)) / x^3 for x > 0. */
+
+#define NIFTI_INTENT_INVGAUSS 20
+
+ /*! [C2, chap 22] Extreme value type I (2 params):
+ p1 = location, p2 = scale
+ cdf(x) = exp(-exp(-(x-p1)/p2)). */
+
+#define NIFTI_INTENT_EXTVAL 21
+
+ /*! Data is a 'p-value' (no params). */
+
+#define NIFTI_INTENT_PVAL 22
+
+ /*! Data is ln(p-value) (no params).
+ To be safe, a program should compute p = exp(-abs(this_value)).
+ The nifti_stats.c library returns this_value
+ as positive, so that this_value = -log(p). */
+
+
+#define NIFTI_INTENT_LOGPVAL 23
+
+ /*! Data is log10(p-value) (no params).
+ To be safe, a program should compute p = pow(10.,-abs(this_value)).
+ The nifti_stats.c library returns this_value
+ as positive, so that this_value = -log10(p). */
+
+#define NIFTI_INTENT_LOG10PVAL 24
+
+ /*! Smallest intent_code that indicates a statistic. */
+
+#define NIFTI_FIRST_STATCODE 2
+
+ /*! Largest intent_code that indicates a statistic. */
+
+#define NIFTI_LAST_STATCODE 24
+
+ /*---------- these values for intent_code aren't for statistics ----------*/
+
+ /*! To signify that the value at each voxel is an estimate
+ of some parameter, set intent_code = NIFTI_INTENT_ESTIMATE.
+ The name of the parameter may be stored in intent_name. */
+
+#define NIFTI_INTENT_ESTIMATE 1001
+
+ /*! To signify that the value at each voxel is an index into
+ some set of labels, set intent_code = NIFTI_INTENT_LABEL.
+ The filename with the labels may stored in aux_file. */
+
+#define NIFTI_INTENT_LABEL 1002
+
+ /*! To signify that the value at each voxel is an index into the
+ NeuroNames labels set, set intent_code = NIFTI_INTENT_NEURONAME. */
+
+#define NIFTI_INTENT_NEURONAME 1003
+
+ /*! To store an M x N matrix at each voxel:
+ - dataset must have a 5th dimension (dim[0]=5 and dim[5]>1)
+ - intent_code must be NIFTI_INTENT_GENMATRIX
+ - dim[5] must be M*N
+ - intent_p1 must be M (in float format)
+ - intent_p2 must be N (ditto)
+ - the matrix values A[i][[j] are stored in row-order:
+ - A[0][0] A[0][1] ... A[0][N-1]
+ - A[1][0] A[1][1] ... A[1][N-1]
+ - etc., until
+ - A[M-1][0] A[M-1][1] ... A[M-1][N-1] */
+
+#define NIFTI_INTENT_GENMATRIX 1004
+
+ /*! To store an NxN symmetric matrix at each voxel:
+ - dataset must have a 5th dimension
+ - intent_code must be NIFTI_INTENT_SYMMATRIX
+ - dim[5] must be N*(N+1)/2
+ - intent_p1 must be N (in float format)
+ - the matrix values A[i][[j] are stored in row-order:
+ - A[0][0]
+ - A[1][0] A[1][1]
+ - A[2][0] A[2][1] A[2][2]
+ - etc.: row-by-row */
+
+#define NIFTI_INTENT_SYMMATRIX 1005
+
+ /*! To signify that the vector value at each voxel is to be taken
+ as a displacement field or vector:
+ - dataset must have a 5th dimension
+ - intent_code must be NIFTI_INTENT_DISPVECT
+ - dim[5] must be the dimensionality of the displacment
+ vector (e.g., 3 for spatial displacement, 2 for in-plane) */
+
+#define NIFTI_INTENT_DISPVECT 1006 /* specifically for displacements */
+#define NIFTI_INTENT_VECTOR 1007 /* for any other type of vector */
+
+ /*! To signify that the vector value at each voxel is really a
+ spatial coordinate (e.g., the vertices or nodes of a surface mesh):
+ - dataset must have a 5th dimension
+ - intent_code must be NIFTI_INTENT_POINTSET
+ - dim[0] = 5
+ - dim[1] = number of points
+ - dim[2] = dim[3] = dim[4] = 1
+ - dim[5] must be the dimensionality of space (e.g., 3 => 3D space).
+ - intent_name may describe the object these points come from
+ (e.g., "pial", "gray/white" , "EEG", "MEG"). */
+
+#define NIFTI_INTENT_POINTSET 1008
+
+ /*! To signify that the vector value at each voxel is really a triple
+ of indexes (e.g., forming a triangle) from a pointset dataset:
+ - dataset must have a 5th dimension
+ - intent_code must be NIFTI_INTENT_TRIANGLE
+ - dim[0] = 5
+ - dim[1] = number of triangles
+ - dim[2] = dim[3] = dim[4] = 1
+ - dim[5] = 3
+ - datatype should be an integer type (preferably DT_INT32)
+ - the data values are indexes (0,1,...) into a pointset dataset. */
+
+#define NIFTI_INTENT_TRIANGLE 1009
+
+ /*! To signify that the vector value at each voxel is a quaternion:
+ - dataset must have a 5th dimension
+ - intent_code must be NIFTI_INTENT_QUATERNION
+ - dim[0] = 5
+ - dim[5] = 4
+ - datatype should be a floating point type */
+
+#define NIFTI_INTENT_QUATERNION 1010
+
+ /*! Dimensionless value - no params - although, as in _ESTIMATE
+ the name of the parameter may be stored in intent_name. */
+
+#define NIFTI_INTENT_DIMLESS 1011
+
+ /*---------- these values apply to GIFTI datasets ----------*/
+
+ /*! To signify that the value at each location is from a time series. */
+
+#define NIFTI_INTENT_TIME_SERIES 2001
+
+ /*! To signify that the value at each location is a node index, from
+ a complete surface dataset. */
+
+#define NIFTI_INTENT_NODE_INDEX 2002
+
+ /*! To signify that the vector value at each location is an RGB triplet,
+ of whatever type.
+ - dataset must have a 5th dimension
+ - dim[0] = 5
+ - dim[1] = number of nodes
+ - dim[2] = dim[3] = dim[4] = 1
+ - dim[5] = 3
+ */
+
+#define NIFTI_INTENT_RGB_VECTOR 2003
+
+ /*! To signify that the vector value at each location is a 4 valued RGBA
+ vector, of whatever type.
+ - dataset must have a 5th dimension
+ - dim[0] = 5
+ - dim[1] = number of nodes
+ - dim[2] = dim[3] = dim[4] = 1
+ - dim[5] = 4
+ */
+
+#define NIFTI_INTENT_RGBA_VECTOR 2004
+
+ /*! To signify that the value at each location is a shape value, such
+ as the curvature. */
+
+#define NIFTI_INTENT_SHAPE 2005
+
+/* @} */
+
+/*---------------------------------------------------------------------------*/
+/* 3D IMAGE (VOLUME) ORIENTATION AND LOCATION IN SPACE:
+ ---------------------------------------------------
+ There are 3 different methods by which continuous coordinates can
+ attached to voxels. The discussion below emphasizes 3D volumes, and
+ the continuous coordinates are referred to as (x,y,z). The voxel
+ index coordinates (i.e., the array indexes) are referred to as (i,j,k),
+ with valid ranges:
+ i = 0 .. dim[1]-1
+ j = 0 .. dim[2]-1 (if dim[0] >= 2)
+ k = 0 .. dim[3]-1 (if dim[0] >= 3)
+ The (x,y,z) coordinates refer to the CENTER of a voxel. In methods
+ 2 and 3, the (x,y,z) axes refer to a subject-based coordinate system,
+ with
+ +x = Right +y = Anterior +z = Superior.
+ This is a right-handed coordinate system. However, the exact direction
+ these axes point with respect to the subject depends on qform_code
+ (Method 2) and sform_code (Method 3).
+
+ N.B.: The i index varies most rapidly, j index next, k index slowest.
+ Thus, voxel (i,j,k) is stored starting at location
+ (i + j*dim[1] + k*dim[1]*dim[2]) * (bitpix/8)
+ into the dataset array.
+
+ N.B.: The ANALYZE 7.5 coordinate system is
+ +x = Left +y = Anterior +z = Superior
+ which is a left-handed coordinate system. This backwardness is
+ too difficult to tolerate, so this NIFTI-1 standard specifies the
+ coordinate order which is most common in functional neuroimaging.
+
+ N.B.: The 3 methods below all give the locations of the voxel centers
+ in the (x,y,z) coordinate system. In many cases, programs will wish
+ to display image data on some other grid. In such a case, the program
+ will need to convert its desired (x,y,z) values into (i,j,k) values
+ in order to extract (or interpolate) the image data. This operation
+ would be done with the inverse transformation to those described below.
+
+ N.B.: Method 2 uses a factor 'qfac' which is either -1 or 1; qfac is
+ stored in the otherwise unused pixdim[0]. If pixdim[0]=0.0 (which
+ should not occur), we take qfac=1. Of course, pixdim[0] is only used
+ when reading a NIFTI-1 header, not when reading an ANALYZE 7.5 header.
+
+ N.B.: The units of (x,y,z) can be specified using the xyzt_units field.
+
+ METHOD 1 (the "old" way, used only when qform_code = 0):
+ -------------------------------------------------------
+ The coordinate mapping from (i,j,k) to (x,y,z) is the ANALYZE
+ 7.5 way. This is a simple scaling relationship:
+
+ x = pixdim[1] * i
+ y = pixdim[2] * j
+ z = pixdim[3] * k
+
+ No particular spatial orientation is attached to these (x,y,z)
+ coordinates. (NIFTI-1 does not have the ANALYZE 7.5 orient field,
+ which is not general and is often not set properly.) This method
+ is not recommended, and is present mainly for compatibility with
+ ANALYZE 7.5 files.
+
+ METHOD 2 (used when qform_code > 0, which should be the "normal" case):
+ ---------------------------------------------------------------------
+ The (x,y,z) coordinates are given by the pixdim[] scales, a rotation
+ matrix, and a shift. This method is intended to represent
+ "scanner-anatomical" coordinates, which are often embedded in the
+ image header (e.g., DICOM fields (0020,0032), (0020,0037), (0028,0030),
+ and (0018,0050)), and represent the nominal orientation and location of
+ the data. This method can also be used to represent "aligned"
+ coordinates, which would typically result from some post-acquisition
+ alignment of the volume to a standard orientation (e.g., the same
+ subject on another day, or a rigid rotation to true anatomical
+ orientation from the tilted position of the subject in the scanner).
+ The formula for (x,y,z) in terms of header parameters and (i,j,k) is:
+
+ [ x ] [ R11 R12 R13 ] [ pixdim[1] * i ] [ qoffset_x ]
+ [ y ] = [ R21 R22 R23 ] [ pixdim[2] * j ] + [ qoffset_y ]
+ [ z ] [ R31 R32 R33 ] [ qfac * pixdim[3] * k ] [ qoffset_z ]
+
+ The qoffset_* shifts are in the NIFTI-1 header. Note that the center
+ of the (i,j,k)=(0,0,0) voxel (first value in the dataset array) is
+ just (x,y,z)=(qoffset_x,qoffset_y,qoffset_z).
+
+ The rotation matrix R is calculated from the quatern_* parameters.
+ This calculation is described below.
+
+ The scaling factor qfac is either 1 or -1. The rotation matrix R
+ defined by the quaternion parameters is "proper" (has determinant 1).
+ This may not fit the needs of the data; for example, if the image
+ grid is
+ i increases from Left-to-Right
+ j increases from Anterior-to-Posterior
+ k increases from Inferior-to-Superior
+ Then (i,j,k) is a left-handed triple. In this example, if qfac=1,
+ the R matrix would have to be
+
+ [ 1 0 0 ]
+ [ 0 -1 0 ] which is "improper" (determinant = -1).
+ [ 0 0 1 ]
+
+ If we set qfac=-1, then the R matrix would be
+
+ [ 1 0 0 ]
+ [ 0 -1 0 ] which is proper.
+ [ 0 0 -1 ]
+
+ This R matrix is represented by quaternion [a,b,c,d] = [0,1,0,0]
+ (which encodes a 180 degree rotation about the x-axis).
+
+ METHOD 3 (used when sform_code > 0):
+ -----------------------------------
+ The (x,y,z) coordinates are given by a general affine transformation
+ of the (i,j,k) indexes:
+
+ x = srow_x[0] * i + srow_x[1] * j + srow_x[2] * k + srow_x[3]
+ y = srow_y[0] * i + srow_y[1] * j + srow_y[2] * k + srow_y[3]
+ z = srow_z[0] * i + srow_z[1] * j + srow_z[2] * k + srow_z[3]
+
+ The srow_* vectors are in the NIFTI_1 header. Note that no use is
+ made of pixdim[] in this method.
+
+ WHY 3 METHODS?
+ --------------
+ Method 1 is provided only for backwards compatibility. The intention
+ is that Method 2 (qform_code > 0) represents the nominal voxel locations
+ as reported by the scanner, or as rotated to some fiducial orientation and
+ location. Method 3, if present (sform_code > 0), is to be used to give
+ the location of the voxels in some standard space. The sform_code
+ indicates which standard space is present. Both methods 2 and 3 can be
+ present, and be useful in different contexts (method 2 for displaying the
+ data on its original grid; method 3 for displaying it on a standard grid).
+
+ In this scheme, a dataset would originally be set up so that the
+ Method 2 coordinates represent what the scanner reported. Later,
+ a registration to some standard space can be computed and inserted
+ in the header. Image display software can use either transform,
+ depending on its purposes and needs.
+
+ In Method 2, the origin of coordinates would generally be whatever
+ the scanner origin is; for example, in MRI, (0,0,0) is the center
+ of the gradient coil.
+
+ In Method 3, the origin of coordinates would depend on the value
+ of sform_code; for example, for the Talairach coordinate system,
+ (0,0,0) corresponds to the Anterior Commissure.
+
+ QUATERNION REPRESENTATION OF ROTATION MATRIX (METHOD 2)
+ -------------------------------------------------------
+ The orientation of the (x,y,z) axes relative to the (i,j,k) axes
+ in 3D space is specified using a unit quaternion [a,b,c,d], where
+ a*a+b*b+c*c+d*d=1. The (b,c,d) values are all that is needed, since
+ we require that a = sqrt(1.0-(b*b+c*c+d*d)) be nonnegative. The (b,c,d)
+ values are stored in the (quatern_b,quatern_c,quatern_d) fields.
+
+ The quaternion representation is chosen for its compactness in
+ representing rotations. The (proper) 3x3 rotation matrix that
+ corresponds to [a,b,c,d] is
+
+ [ a*a+b*b-c*c-d*d 2*b*c-2*a*d 2*b*d+2*a*c ]
+ R = [ 2*b*c+2*a*d a*a+c*c-b*b-d*d 2*c*d-2*a*b ]
+ [ 2*b*d-2*a*c 2*c*d+2*a*b a*a+d*d-c*c-b*b ]
+
+ [ R11 R12 R13 ]
+ = [ R21 R22 R23 ]
+ [ R31 R32 R33 ]
+
+ If (p,q,r) is a unit 3-vector, then rotation of angle h about that
+ direction is represented by the quaternion
+
+ [a,b,c,d] = [cos(h/2), p*sin(h/2), q*sin(h/2), r*sin(h/2)].
+
+ Requiring a >= 0 is equivalent to requiring -Pi <= h <= Pi. (Note that
+ [-a,-b,-c,-d] represents the same rotation as [a,b,c,d]; there are 2
+ quaternions that can be used to represent a given rotation matrix R.)
+ To rotate a 3-vector (x,y,z) using quaternions, we compute the
+ quaternion product
+
+ [0,x',y',z'] = [a,b,c,d] * [0,x,y,z] * [a,-b,-c,-d]
+
+ which is equivalent to the matrix-vector multiply
+
+ [ x' ] [ x ]
+ [ y' ] = R [ y ] (equivalence depends on a*a+b*b+c*c+d*d=1)
+ [ z' ] [ z ]
+
+ Multiplication of 2 quaternions is defined by the following:
+
+ [a,b,c,d] = a*1 + b*I + c*J + d*K
+ where
+ I*I = J*J = K*K = -1 (I,J,K are square roots of -1)
+ I*J = K J*K = I K*I = J
+ J*I = -K K*J = -I I*K = -J (not commutative!)
+ For example
+ [a,b,0,0] * [0,0,0,1] = [0,0,-b,a]
+ since this expands to
+ (a+b*I)*(K) = (a*K+b*I*K) = (a*K-b*J).
+
+ The above formula shows how to go from quaternion (b,c,d) to
+ rotation matrix and direction cosines. Conversely, given R,
+ we can compute the fields for the NIFTI-1 header by
+
+ a = 0.5 * sqrt(1+R11+R22+R33) (not stored)
+ b = 0.25 * (R32-R23) / a => quatern_b
+ c = 0.25 * (R13-R31) / a => quatern_c
+ d = 0.25 * (R21-R12) / a => quatern_d
+
+ If a=0 (a 180 degree rotation), alternative formulas are needed.
+ See the nifti1_io.c function mat44_to_quatern() for an implementation
+ of the various cases in converting R to [a,b,c,d].
+
+ Note that R-transpose (= R-inverse) would lead to the quaternion
+ [a,-b,-c,-d].
+
+ The choice to specify the qoffset_x (etc.) values in the final
+ coordinate system is partly to make it easy to convert DICOM images to
+ this format. The DICOM attribute "Image Position (Patient)" (0020,0032)
+ stores the (Xd,Yd,Zd) coordinates of the center of the first voxel.
+ Here, (Xd,Yd,Zd) refer to DICOM coordinates, and Xd=-x, Yd=-y, Zd=z,
+ where (x,y,z) refers to the NIFTI coordinate system discussed above.
+ (i.e., DICOM +Xd is Left, +Yd is Posterior, +Zd is Superior,
+ whereas +x is Right, +y is Anterior , +z is Superior. )
+ Thus, if the (0020,0032) DICOM attribute is extracted into (px,py,pz), then
+ qoffset_x = -px qoffset_y = -py qoffset_z = pz
+ is a reasonable setting when qform_code=NIFTI_XFORM_SCANNER_ANAT.
+
+ That is, DICOM's coordinate system is 180 degrees rotated about the z-axis
+ from the neuroscience/NIFTI coordinate system. To transform between DICOM
+ and NIFTI, you just have to negate the x- and y-coordinates.
+
+ The DICOM attribute (0020,0037) "Image Orientation (Patient)" gives the
+ orientation of the x- and y-axes of the image data in terms of 2 3-vectors.
+ The first vector is a unit vector along the x-axis, and the second is
+ along the y-axis. If the (0020,0037) attribute is extracted into the
+ value (xa,xb,xc,ya,yb,yc), then the first two columns of the R matrix
+ would be
+ [ -xa -ya ]
+ [ -xb -yb ]
+ [ xc yc ]
+ The negations are because DICOM's x- and y-axes are reversed relative
+ to NIFTI's. The third column of the R matrix gives the direction of
+ displacement (relative to the subject) along the slice-wise direction.
+ This orientation is not encoded in the DICOM standard in a simple way;
+ DICOM is mostly concerned with 2D images. The third column of R will be
+ either the cross-product of the first 2 columns or its negative. It is
+ possible to infer the sign of the 3rd column by examining the coordinates
+ in DICOM attribute (0020,0032) "Image Position (Patient)" for successive
+ slices. However, this method occasionally fails for reasons that I
+ (RW Cox) do not understand.
+-----------------------------------------------------------------------------*/
+
+ /* [qs]form_code value: */ /* x,y,z coordinate system refers to: */
+ /*-----------------------*/ /*---------------------------------------*/
+
+/*! \defgroup NIFTI1_XFORM_CODES
+ \brief nifti1 xform codes to describe the "standard" coordinate system
+ @{
+ */
+ /*! Arbitrary coordinates (Method 1). */
+
+#define NIFTI_XFORM_UNKNOWN 0
+
+ /*! Scanner-based anatomical coordinates */
+
+#define NIFTI_XFORM_SCANNER_ANAT 1
+
+ /*! Coordinates aligned to another file's,
+ or to anatomical "truth". */
+
+#define NIFTI_XFORM_ALIGNED_ANAT 2
+
+ /*! Coordinates aligned to Talairach-
+ Tournoux Atlas; (0,0,0)=AC, etc. */
+
+#define NIFTI_XFORM_TALAIRACH 3
+
+ /*! MNI 152 normalized coordinates. */
+
+#define NIFTI_XFORM_MNI_152 4
+/* @} */
+
+/*---------------------------------------------------------------------------*/
+/* UNITS OF SPATIAL AND TEMPORAL DIMENSIONS:
+ ----------------------------------------
+ The codes below can be used in xyzt_units to indicate the units of pixdim.
+ As noted earlier, dimensions 1,2,3 are for x,y,z; dimension 4 is for
+ time (t).
+ - If dim[4]=1 or dim[0] < 4, there is no time axis.
+ - A single time series (no space) would be specified with
+ - dim[0] = 4 (for scalar data) or dim[0] = 5 (for vector data)
+ - dim[1] = dim[2] = dim[3] = 1
+ - dim[4] = number of time points
+ - pixdim[4] = time step
+ - xyzt_units indicates units of pixdim[4]
+ - dim[5] = number of values stored at each time point
+
+ Bits 0..2 of xyzt_units specify the units of pixdim[1..3]
+ (e.g., spatial units are values 1..7).
+ Bits 3..5 of xyzt_units specify the units of pixdim[4]
+ (e.g., temporal units are multiples of 8).
+
+ This compression of 2 distinct concepts into 1 byte is due to the
+ limited space available in the 348 byte ANALYZE 7.5 header. The
+ macros XYZT_TO_SPACE and XYZT_TO_TIME can be used to mask off the
+ undesired bits from the xyzt_units fields, leaving "pure" space
+ and time codes. Inversely, the macro SPACE_TIME_TO_XYZT can be
+ used to assemble a space code (0,1,2,...,7) with a time code
+ (0,8,16,32,...,56) into the combined value for xyzt_units.
+
+ Note that codes are provided to indicate the "time" axis units are
+ actually frequency in Hertz (_HZ), in part-per-million (_PPM)
+ or in radians-per-second (_RADS).
+
+ The toffset field can be used to indicate a nonzero start point for
+ the time axis. That is, time point #m is at t=toffset+m*pixdim[4]
+ for m=0..dim[4]-1.
+-----------------------------------------------------------------------------*/
+
+/*! \defgroup NIFTI1_UNITS
+ \brief nifti1 units codes to describe the unit of measurement for
+ each dimension of the dataset
+ @{
+ */
+ /*! NIFTI code for unspecified units. */
+#define NIFTI_UNITS_UNKNOWN 0
+
+ /** Space codes are multiples of 1. **/
+ /*! NIFTI code for meters. */
+#define NIFTI_UNITS_METER 1
+ /*! NIFTI code for millimeters. */
+#define NIFTI_UNITS_MM 2
+ /*! NIFTI code for micrometers. */
+#define NIFTI_UNITS_MICRON 3
+
+ /** Time codes are multiples of 8. **/
+ /*! NIFTI code for seconds. */
+#define NIFTI_UNITS_SEC 8
+ /*! NIFTI code for milliseconds. */
+#define NIFTI_UNITS_MSEC 16
+ /*! NIFTI code for microseconds. */
+#define NIFTI_UNITS_USEC 24
+
+ /*** These units are for spectral data: ***/
+ /*! NIFTI code for Hertz. */
+#define NIFTI_UNITS_HZ 32
+ /*! NIFTI code for ppm. */
+#define NIFTI_UNITS_PPM 40
+ /*! NIFTI code for radians per second. */
+#define NIFTI_UNITS_RADS 48
+/* @} */
+
+#undef XYZT_TO_SPACE
+#undef XYZT_TO_TIME
+#define XYZT_TO_SPACE(xyzt) ( (xyzt) & 0x07 )
+#define XYZT_TO_TIME(xyzt) ( (xyzt) & 0x38 )
+
+#undef SPACE_TIME_TO_XYZT
+#define SPACE_TIME_TO_XYZT(ss,tt) ( (((char)(ss)) & 0x07) \
+ | (((char)(tt)) & 0x38) )
+
+/*---------------------------------------------------------------------------*/
+/* MRI-SPECIFIC SPATIAL AND TEMPORAL INFORMATION:
+ ---------------------------------------------
+ A few fields are provided to store some extra information
+ that is sometimes important when storing the image data
+ from an FMRI time series experiment. (After processing such
+ data into statistical images, these fields are not likely
+ to be useful.)
+
+ { freq_dim } = These fields encode which spatial dimension (1,2, or 3)
+ { phase_dim } = corresponds to which acquisition dimension for MRI data.
+ { slice_dim } =
+ Examples:
+ Rectangular scan multi-slice EPI:
+ freq_dim = 1 phase_dim = 2 slice_dim = 3 (or some permutation)
+ Spiral scan multi-slice EPI:
+ freq_dim = phase_dim = 0 slice_dim = 3
+ since the concepts of frequency- and phase-encoding directions
+ don't apply to spiral scan
+
+ slice_duration = If this is positive, AND if slice_dim is nonzero,
+ indicates the amount of time used to acquire 1 slice.
+ slice_duration*dim[slice_dim] can be less than pixdim[4]
+ with a clustered acquisition method, for example.
+
+ slice_code = If this is nonzero, AND if slice_dim is nonzero, AND
+ if slice_duration is positive, indicates the timing
+ pattern of the slice acquisition. The following codes
+ are defined:
+ NIFTI_SLICE_SEQ_INC == sequential increasing
+ NIFTI_SLICE_SEQ_DEC == sequential decreasing
+ NIFTI_SLICE_ALT_INC == alternating increasing
+ NIFTI_SLICE_ALT_DEC == alternating decreasing
+ NIFTI_SLICE_ALT_INC2 == alternating increasing #2
+ NIFTI_SLICE_ALT_DEC2 == alternating decreasing #2
+ { slice_start } = Indicates the start and end of the slice acquisition
+ { slice_end } = pattern, when slice_code is nonzero. These values
+ are present to allow for the possible addition of
+ "padded" slices at either end of the volume, which
+ don't fit into the slice timing pattern. If there
+ are no padding slices, then slice_start=0 and
+ slice_end=dim[slice_dim]-1 are the correct values.
+ For these values to be meaningful, slice_start must
+ be non-negative and slice_end must be greater than
+ slice_start. Otherwise, they should be ignored.
+
+ The following table indicates the slice timing pattern, relative to
+ time=0 for the first slice acquired, for some sample cases. Here,
+ dim[slice_dim]=7 (there are 7 slices, labeled 0..6), slice_duration=0.1,
+ and slice_start=1, slice_end=5 (1 padded slice on each end).
+
+ slice
+ index SEQ_INC SEQ_DEC ALT_INC ALT_DEC ALT_INC2 ALT_DEC2
+ 6 : n/a n/a n/a n/a n/a n/a n/a = not applicable
+ 5 : 0.4 0.0 0.2 0.0 0.4 0.2 (slice time offset
+ 4 : 0.3 0.1 0.4 0.3 0.1 0.0 doesn't apply to
+ 3 : 0.2 0.2 0.1 0.1 0.3 0.3 slices outside
+ 2 : 0.1 0.3 0.3 0.4 0.0 0.1 the range
+ 1 : 0.0 0.4 0.0 0.2 0.2 0.4 slice_start ..
+ 0 : n/a n/a n/a n/a n/a n/a slice_end)
+
+ The SEQ slice_codes are sequential ordering (uncommon but not unknown),
+ either increasing in slice number or decreasing (INC or DEC), as
+ illustrated above.
+
+ The ALT slice codes are alternating ordering. The 'standard' way for
+ these to operate (without the '2' on the end) is for the slice timing
+ to start at the edge of the slice_start .. slice_end group (at slice_start
+ for INC and at slice_end for DEC). For the 'ALT_*2' slice_codes, the
+ slice timing instead starts at the first slice in from the edge (at
+ slice_start+1 for INC2 and at slice_end-1 for DEC2). This latter
+ acquisition scheme is found on some Siemens scanners.
+
+ The fields freq_dim, phase_dim, slice_dim are all squished into the single
+ byte field dim_info (2 bits each, since the values for each field are
+ limited to the range 0..3). This unpleasantness is due to lack of space
+ in the 348 byte allowance.
+
+ The macros DIM_INFO_TO_FREQ_DIM, DIM_INFO_TO_PHASE_DIM, and
+ DIM_INFO_TO_SLICE_DIM can be used to extract these values from the
+ dim_info byte.
+
+ The macro FPS_INTO_DIM_INFO can be used to put these 3 values
+ into the dim_info byte.
+-----------------------------------------------------------------------------*/
+
+#undef DIM_INFO_TO_FREQ_DIM
+#undef DIM_INFO_TO_PHASE_DIM
+#undef DIM_INFO_TO_SLICE_DIM
+
+#define DIM_INFO_TO_FREQ_DIM(di) ( ((di) ) & 0x03 )
+#define DIM_INFO_TO_PHASE_DIM(di) ( ((di) >> 2) & 0x03 )
+#define DIM_INFO_TO_SLICE_DIM(di) ( ((di) >> 4) & 0x03 )
+
+#undef FPS_INTO_DIM_INFO
+#define FPS_INTO_DIM_INFO(fd,pd,sd) ( ( ( ((char)(fd)) & 0x03) ) | \
+ ( ( ((char)(pd)) & 0x03) << 2 ) | \
+ ( ( ((char)(sd)) & 0x03) << 4 ) )
+
+/*! \defgroup NIFTI1_SLICE_ORDER
+ \brief nifti1 slice order codes, describing the acquisition order
+ of the slices
+ @{
+ */
+#define NIFTI_SLICE_UNKNOWN 0
+#define NIFTI_SLICE_SEQ_INC 1
+#define NIFTI_SLICE_SEQ_DEC 2
+#define NIFTI_SLICE_ALT_INC 3
+#define NIFTI_SLICE_ALT_DEC 4
+#define NIFTI_SLICE_ALT_INC2 5 /* 05 May 2005: RWCox */
+#define NIFTI_SLICE_ALT_DEC2 6 /* 05 May 2005: RWCox */
+/* @} */
+
+/*---------------------------------------------------------------------------*/
+/* UNUSED FIELDS:
+ -------------
+ Some of the ANALYZE 7.5 fields marked as ++UNUSED++ may need to be set
+ to particular values for compatibility with other programs. The issue
+ of interoperability of ANALYZE 7.5 files is a murky one -- not all
+ programs require exactly the same set of fields. (Unobscuring this
+ murkiness is a principal motivation behind NIFTI-1.)
+
+ Some of the fields that may need to be set for other (non-NIFTI aware)
+ software to be happy are:
+
+ extents dbh.h says this should be 16384
+ regular dbh.h says this should be the character 'r'
+ glmin, } dbh.h says these values should be the min and max voxel
+ glmax } values for the entire dataset
+
+ It is best to initialize ALL fields in the NIFTI-1 header to 0
+ (e.g., with calloc()), then fill in what is needed.
+-----------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* MISCELLANEOUS C MACROS
+-----------------------------------------------------------------------------*/
+
+/*.................*/
+/*! Given a nifti_1_header struct, check if it has a good magic number.
+ Returns NIFTI version number (1..9) if magic is good, 0 if it is not. */
+
+#define NIFTI_VERSION(h) \
+ ( ( (h).magic[0]=='n' && (h).magic[3]=='\0' && \
+ ( (h).magic[1]=='i' || (h).magic[1]=='+' ) && \
+ ( (h).magic[2]>='1' && (h).magic[2]<='9' ) ) \
+ ? (h).magic[2]-'0' : 0 )
+
+/*.................*/
+/*! Check if a nifti_1_header struct says if the data is stored in the
+ same file or in a separate file. Returns 1 if the data is in the same
+ file as the header, 0 if it is not. */
+
+#define NIFTI_ONEFILE(h) ( (h).magic[1] == '+' )
+
+/*.................*/
+/*! Check if a nifti_1_header struct needs to be byte swapped.
+ Returns 1 if it needs to be swapped, 0 if it does not. */
+
+#define NIFTI_NEEDS_SWAP(h) ( (h).dim[0] < 0 || (h).dim[0] > 7 )
+
+/*.................*/
+/*! Check if a nifti_1_header struct contains a 5th (vector) dimension.
+ Returns size of 5th dimension if > 1, returns 0 otherwise. */
+
+#define NIFTI_5TH_DIM(h) ( ((h).dim[0]>4 && (h).dim[5]>1) ? (h).dim[5] : 0 )
+
+/*****************************************************************************/
+
+/*=================*/
+#ifdef __cplusplus
+}
+#endif
+/*=================*/
+
+#endif /* _NIFTI_HEADER_ */
diff --git a/mpi_code/mex_anz/nifti1diagrams_v2.pdf b/mpi_code/mex_anz/nifti1diagrams_v2.pdf
new file mode 100644
index 0000000..c83cee4
Binary files /dev/null and b/mpi_code/mex_anz/nifti1diagrams_v2.pdf differ
diff --git a/mpi_code/mex_anz/test.hdr b/mpi_code/mex_anz/test.hdr
new file mode 100644
index 0000000..f67bb12
Binary files /dev/null and b/mpi_code/mex_anz/test.hdr differ
diff --git a/mpi_code/mex_anz/test2.hdr b/mpi_code/mex_anz/test2.hdr
new file mode 100644
index 0000000..f67bb12
Binary files /dev/null and b/mpi_code/mex_anz/test2.hdr differ
diff --git a/mpi_code/mex_anz/utlswapbytes.c b/mpi_code/mex_anz/utlswapbytes.c
new file mode 100644
index 0000000..85d4c18
--- /dev/null
+++ b/mpi_code/mex_anz/utlswapbytes.c
@@ -0,0 +1,139 @@
+/* utlswapbytes.c : utility to swap bytes for Matlab.
+ *
+ *
+ * UTLSWAPBYTES - swaps bytes of given data.
+ *
+ * SV = UTLSWAPBYTES(V) swaps bytes of V and returns the result.
+ * UTLSWAPBYTES(V) does the same thing but it will modify directly the original
+ * data V without allocating additional memory for the result.
+ * Input data V can be multi-dimesional, but its data class
+ * must be 2bytes or 4bytes type, ie. int16/uint16/int32/uint32/single.
+ *
+ * Usage: sv = utlswapbytes(v,[verbose=0|1])
+ * Notes: class of 'v' must be int16,uint16,int32,uint32,single.
+ * : if nargout==0, then swaps 'v' directly.
+ *
+ * To compile,
+ * mex utlswapbytes.c
+ *
+ * VERSION :
+ * 0.90 2005.05.31 Yusuke MURAYAMA @MPI first release.
+ * 0.91 2005.06.01 Yusuke MURAYAMA @MPI if nargout==0, swaps the original.
+ */
+
+#include
+#include "matrix.h"
+#include "mex.h"
+
+// input arguments
+#define DATA_IN prhs[0]
+#define VERBOSE_IN prhs[1]
+
+// output arguments
+#define DATA_OUT plhs[0]
+
+
+// PROTOTYPES /////////////////////////////////////////////////////////
+void swap_short(short *, int, int);
+void swap_long(long *, int, int);
+
+
+
+// FUNCTIONS /////////////////////////////////////////////////////////
+void swap_short(unsigned char *ptr, int n, int verbose)
+{
+ unsigned char b0,b1;
+ int i;
+
+ for (i = 0; i < n; i++) {
+ // b0-b1 --> b1-b0
+ b0 = *ptr;
+ b1 = *(ptr+1);
+ *ptr = b1;
+ *(ptr+1) = b0;
+
+ ptr = ptr + 2;
+ }
+
+ if (verbose)
+ mexPrintf("[%d]: %02x %02x --> %02x %02x\n", n,b0,b1,b1,b0);
+
+ return;
+}
+
+void swap_long(unsigned char *ptr, int n, int verbose)
+{
+ unsigned char b0,b1,b2,b3;
+ int i;
+
+ for (i = 0; i < n; i++) {
+ // b0-b1-b2-b3 --> b3-b2-b1-b0
+ b0 = *ptr; b1 = *(ptr+1);
+ b2 = *(ptr+2); b3 = *(ptr+3);
+
+ *ptr = b3; *(ptr+1) = b2;
+ *(ptr+2) = b1; *(ptr+3) = b0;
+
+ ptr = ptr + 4;
+ }
+
+ if (verbose)
+ mexPrintf("[%d]: %02x %02x %02x %02x --> %x %x %x %x\n", n,b0,b1,b2,b3,b3,b2,b1,b0);
+
+ return;
+}
+
+
+// MAIN FUNCTION /////////////////////////////////////////////////////
+void mexFunction(int nlhs, mxArray *plhs[],
+ int nrhs, const mxArray *prhs[])
+{
+ char *datastr;
+ int n, dataclass, verbose;
+
+ if (nrhs == 0) {
+ mexPrintf("Usage: sv = utlswapbytes(v,[verbose=0|1])\n");
+ mexPrintf("Notes: class of 'v' must be int16,uint16,int32,uint32,single.\n");
+ mexPrintf(" : if nargout==0, then swaps 'v' directly.\n");
+ mexPrintf(" ver 0.91 Jun-2005 YM@MPI\n");
+ return;
+ }
+
+ verbose = 0;
+ if (nrhs > 1) {
+ verbose = (int)mxGetScalar(VERBOSE_IN);
+ }
+
+ dataclass = mxGetClassID(DATA_IN);
+ n = mxGetNumberOfElements(DATA_IN);
+
+ if (nlhs > 0) {
+ DATA_OUT = mxDuplicateArray(DATA_IN);
+ }
+
+ switch (dataclass) {
+ case mxINT16_CLASS:
+ case mxUINT16_CLASS:
+ if (nlhs > 0) {
+ swap_short((unsigned char *)mxGetData(DATA_OUT), n, verbose);
+ } else {
+ swap_short((unsigned char *)mxGetData(DATA_IN), n, verbose);
+ }
+ break;
+ case mxINT32_CLASS:
+ case mxUINT32_CLASS:
+ case mxSINGLE_CLASS:
+ if (nlhs > 0) {
+ swap_long((unsigned char *)mxGetData(DATA_OUT), n, verbose);
+ } else {
+ swap_long((unsigned char *)mxGetData(DATA_IN), n, verbose);
+ }
+ break;
+ default:
+ mexPrintf("utlswapbytes: '%s' is an unacceptable data class, 'help class' for detail.\n",
+ mxGetClassName(DATA_IN));
+ mexErrMsgTxt("utlswapbytes: dataclass must be int16,uint16,int32,uint32,single.");
+ }
+
+ return;
+}
diff --git a/mpi_code/mex_anz/utlswapbytes.dll.old b/mpi_code/mex_anz/utlswapbytes.dll.old
new file mode 100644
index 0000000..c08d7fb
Binary files /dev/null and b/mpi_code/mex_anz/utlswapbytes.dll.old differ
diff --git a/mpi_code/mex_anz/utlswapbytes.m b/mpi_code/mex_anz/utlswapbytes.m
new file mode 100644
index 0000000..bcf5df3
--- /dev/null
+++ b/mpi_code/mex_anz/utlswapbytes.m
@@ -0,0 +1,19 @@
+%UTLSWAPBYTES - swaps bytes of given data.
+% SV = UTLSWAPBYTES(V) swaps bytes of V and returns the result.
+% UTLSWAPBYTES(V) does the same thing but it will modify directly the original
+% data V without allocating additional memory for the result.
+% Input data V can be multi-dimesional, but its data class
+% must be 2bytes or 4bytes type, ie. int16/uint16/int32/uint32/single.
+%
+% Usage: sv = utlswapbytes(v,[verbose=0|1])
+% Notes: class of 'v' must be int16,uint16,int32,uint32,single.
+% : if nargout==0, then swaps 'v' directly.
+%
+% To compile,
+% mex utlswapbytes.c
+%
+% VERSION :
+% 0.90 2005.05.31 Yusuke MURAYAMA @MPI first release.
+% 0.91 2005.06.01 Yusuke MURAYAMA @MPI if nargout==0, swap the original.
+%
+% See also CLASS, INT16, UINT16, INT32, UINT32, SINGLE
diff --git a/mpi_code/mex_anz/utlswapbytes.mexw32 b/mpi_code/mex_anz/utlswapbytes.mexw32
new file mode 100644
index 0000000..6f62652
Binary files /dev/null and b/mpi_code/mex_anz/utlswapbytes.mexw32 differ
diff --git a/mpi_code/mex_anz/utlswapbytes.mexw64 b/mpi_code/mex_anz/utlswapbytes.mexw64
new file mode 100644
index 0000000..fcfa496
Binary files /dev/null and b/mpi_code/mex_anz/utlswapbytes.mexw64 differ
diff --git a/mpi_code/pvread/pv_imgpar.m b/mpi_code/pvread/pv_imgpar.m
new file mode 100644
index 0000000..d17c972
--- /dev/null
+++ b/mpi_code/pvread/pv_imgpar.m
@@ -0,0 +1,269 @@
+function IMGP = pv_imgpar(varargin)
+%PV_IMGPAR - Get ParaVision imaging parameters.
+% IMGP = PV_IMGPAR(IMGFILE,...)
+% IMGP = PV_IMGPAR(SESSION,EXPNO,...) gets ParaVision's imaging parameters.
+%
+% Supported options are
+% 'acqp' : set acqp parameters, see pvread_acqp
+% 'imnd' : set imnd parameters, see pvread_imnd
+% 'method' : set method parameters, see pvread_method
+% 'reco' : set reco parameters, see pvread_reco
+%
+% VERSION :
+% 0.90 29.08.08 YM pre-release
+% 0.91 18.09.08 YM supports both new csession and old getses.
+% 0.92 23.09.08 YM bug fix on IMND_num_segments/_numsegmetns, RECO_transposition.
+%
+% See also getpvpars pvread_2dseq pvread_acqp pvread_method pvread_reco
+
+if nargin < 1, eval(sprintf('help %s;',mfilename)); return; end
+
+
+if ischar(varargin{1}) & ~isempty(strfind(varargin{1},'2dseq')),
+ % Called like pv_imgpar(2DSEQFILE)
+ imgfile = varargin{1};
+ ivar = 2;
+else
+ % Called like pv_imgpar(SESSION,ExpNo)
+ if nargin < 2,
+ error(' ERROR %s: missing 2nd arg. as ExpNo.\n',mfilename);
+ return;
+ end
+ if exist('csession','class'),
+ ses = csession(varargin{1});
+ imgfile = ses.filename(varargin{2},'2dseq');
+ else
+ ses = goto(varargin{1});
+ imgfile = catfilename(ses,varargin{2},'2dseq');
+ end
+ ivar = 3;
+end
+
+
+% check the file.
+if ~exist(imgfile,'file'),
+ error(' ERROR %s: ''%s'' not found.',mfilename,imgfile);
+end
+
+% SET OPTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+reco = [];
+acqp = [];
+imnd = [];
+method = [];
+for N = ivar:2:length(varargin),
+ switch lower(varargin{N}),
+ case {'reco'}
+ reco = varargin{N+1};
+ case {'acqp'}
+ acqp = varargin{N+1};
+ case {'imnd'}
+ imnd = varargin{N+1};
+ case {'method'}
+ method = varargin{N+1};
+ end
+end
+
+if isempty(reco), reco = pvread_reco(imgfile); end
+if isempty(acqp), acqp = pvread_acqp(imgfile); end
+if isempty(method), method = pvread_method(imgfile,'verbose',0); end
+
+
+%if isfield(acqp,'ACQ_method') && ~isempty(acqp.ACQ_method),
+if isfield(method,'Method') && ~isempty(method.Method),
+ f_PVM = 1;
+else
+ f_PVM = 0;
+ if isempty(imnd),
+ imnd = pvread_imnd(fullfile(fileparts(acqp.filename),'imnd'));
+ end
+end
+
+
+nx = reco.RECO_size(1);
+if length(reco.RECO_size) < 2,
+ ny = 1;
+else
+ ny = reco.RECO_size(2);
+end
+ns = acqp.NSLICES;
+nt = acqp.NR;
+if strncmpi(acqp.PULPROG,' 2,
+ ns = reco.RECO_size(3);
+ end
+ nt = acqp.NI;
+end
+
+dx = reco.RECO_fov(1)*10/nx; % [mm]
+dy = reco.RECO_fov(2)*10/ny; % [mm]
+
+if length(reco.RECO_fov) >= 3,
+ ds = reco.RECO_fov(3)*10/ns;
+else
+ ds = mean(acqp.ACQ_slice_sepn);
+ if ~any(ds),
+ ds = acqp.ACQ_slice_thick;
+ end
+end
+
+
+if strncmp(acqp.PULPROG, ' 0
+ nechoes = acqp.NECHOES/acqp.ACQ_rare_factor; % don't count echoes used for RARE phase encode
+ else
+ nechoes = acqp.NECHOES;
+ end
+end
+nechoes = max([1 nechoes]);
+
+
+if f_PVM == 1
+ if isfield(method,'PVM_EpiNShots'),
+ nseg = method.PVM_EpiNShots;
+ else
+ nseg = 1;
+ end
+ slitr = acqp.ACQ_repetition_time/1000/acqp.NSLICES; % [s]
+ segtr = acqp.ACQ_repetition_time/1000;
+ imgtr = acqp.ACQ_repetition_time/1000*nseg;
+ if isfield(method,'PVM_EchoTime'),
+ effte = method.PVM_EchoTime/1000; % [s]
+ elseif isfield(method,'EchoTime'),
+ effte = method.EchoTime/1000; % [s]
+ else
+ effte = 0;
+ end
+ recovtr = acqp.ACQ_recov_time(:)'/1000; % [s] for T1 series
+else
+ if isfield(imnd,'IMND_numsegments') && any(imnd.IMND_numsegments),
+ nseg = imnd.IMND_numsegments;
+ elseif isfield(imnd,'IMND_num_segments') && any(imnd.IMND_num_segments),
+ nseg = imnd.IMND_num_segments;
+ else
+ nseg = 0;
+ end
+
+ % glitch for EPI
+ if isfield(imnd,'EPI_segmentation_mode') && strcmpi(imnd.EPI_segmentation_mode,'No_Segments'),
+ nseg = 1;
+ end
+
+ if strncmp(acqp.PULPROG, ' (y,x,z)
+ tmpvec = [2 1 3];
+ elseif transpos == 2,
+ % (x,y,z) --> (x,z,y)
+ tmpvec = [1 3 2];
+ elseif transpos == 3,
+ % (x,y,z) --> (z,y,x)
+ tmpvec = [3 2 1];
+ end
+ IMGP.imgsize(1:3) = IMGP.imgsize(tmpvec);
+ IMGP.dimsize(1:3) = IMGP.dimsize(tmpvec);
+ IMGP.dimname(1:3) = IMGP.dimname(tmpvec);
+ %IMGP.res = IMGP.dimsize([1 2]);
+end
+
+
+if nt == 1,
+ IMGP.imgsize = IMGP.imgsize(1:3);
+ IMGP.dimsize = IMGP.dimsize(1:3);
+ IMGP.dimunit = IMGP.dimunit(1:3);
+ IMGP.dimname = IMGP.dimname(1:3);
+end
+
+
+return
diff --git a/mpi_code/pvread/pvread_2dseq.m b/mpi_code/pvread/pvread_2dseq.m
new file mode 100644
index 0000000..24c54f7
--- /dev/null
+++ b/mpi_code/pvread/pvread_2dseq.m
@@ -0,0 +1,248 @@
+function varargout = pvread_2dseq(varargin)
+%PVREAD_2DSEQ - Read ParaVision 2dseq data.
+% [IDATA,IMGP] = PVREAD_2DSEQ(FILENAME,...)
+% IDATA = PVREAD_2DSEQ(FILENAME,...)
+% IDATA = PVREAD_2DSEQ(SESSION,EXPNO,...) read ParaVision 2dseq data.
+%
+% Supported options are...
+% 'ImgCrop' : cropping as [x,y,width,height], can be empty. x,y>=1.
+% 'ImgSize' : image size as [nx, ny, nslices, ntime], must not be empty.
+% 'TimeCrop' : cropping as [t,nt], can be empty. t>=1.
+% 'ByteOrder' : 'littleEndian' or 'bigEndian'
+% 'WordType' : '_16BIT_SGN_INT' or '_32BIT_SGN_INT'
+% 'reco' : reco sturcture returned by pvread_reco().
+% 'acqp' : acqp structure returned by pvread_acqp().
+% 'imgp' : image parameters returned by pv_imgpar().
+%
+% Returned IDATA is NOT 'double', but 'WordType'.
+%
+% VERSION :
+% 0.90 07.03.07 YM pre-release
+% 0.91 16.04.07 YM supports pvread_2dseq(Ses,ExpNo)
+% 0.92 29.08.08 YM supports both new csession and old getses.
+% 0.93 18.09.08 YM returns imgp instread of acqp/reco
+% 0.94 23.09.08 YM bug fix on RECO_transposition.
+%
+% See also pv_imgpar pvread_acqp pvread_reco pvread_imnd pvread_method pvread_visu_pars
+
+if nargin < 1, eval(sprintf('help %s;',mfilename)); return; end
+
+
+if ischar(varargin{1}) & ~isempty(strfind(varargin{1},'2dseq')),
+ % Called like pvread_2dseq(2DSEQFILE)
+ imgfile = varargin{1};
+ ivar = 2;
+else
+ % Called like pvread_2dseq(SESSION,ExpNo)
+ if nargin < 2,
+ error(' ERROR %s: missing 2nd arg. as ExpNo.\n',mfilename);
+ return;
+ end
+ if exist('csession','class'),
+ ses = csession(varargin{1});
+ imgfile = ses.filename(varargin{2},'2dseq');
+ else
+ ses = goto(varargin{1});
+ imgfile = catfilename(ses,varargin{2},'2dseq');
+ end
+ ivar = 3;
+end
+
+
+% check the file.
+if ~exist(imgfile,'file'),
+ error(' ERROR %s: ''%s'' not found.',mfilename,imgfile);
+end
+
+% SET OPTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ImgSize = [];
+ImgCrop = [];
+SliceCrop = [];
+TimeCrop = [];
+ByteOrder = '';
+WordType = '_16BIT_SGN_INT';
+reco = [];
+acqp = [];
+imgp = [];
+for N = ivar:2:length(varargin),
+ switch lower(varargin{N}),
+ case {'imgsize','imagesize'}
+ ImgSize = varargin{N+1};
+ case {'imgcrop','imagecrop'}
+ ImgCrop = varargin{N+1};
+ case {'slicrop','slicecrop'}
+ SliceCrop = varargin{N+1};
+ case {'timecrop','tcrop'}
+ TimeCrop = varargin{N+1};
+ case {'byteorder','endian','reco_byte_order'}
+ ByteOrder = varargin{N+1};
+ case {'wordtype','datatype','data type','reco_wordtype'}
+ WordType = varargin{N+1};
+ case {'reco'}
+ reco = varargin{N+1};
+ case {'acqp'}
+ acqp = varargin{N+1};
+ case {'imgpar','imgp','pvpar'}
+ imgp = varargin{N+1};
+ end
+end
+
+if nargout > 1 && isempty(imgp),
+ imgp = pv_imgpar(imgfile,'acqp',acqp,'reco',reco);
+end
+
+% set image parameters from 'pv_imgpar'.
+if ~isempty(imgp),
+ if isempty(ImgSize) ImgSize = imgp.imgsize; end
+ if isempty(ByteOrder), ByteOrder = imgp.RECO_byte_order; end
+ if isempty(WordType), WordType = imgp.RECO_wordtype; end
+end
+
+% set image size if needed %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+if isempty(ImgSize),
+ if isempty(reco), reco = pvread_reco(imgfile); end
+ if isempty(acqp), acqp = pvread_acqp(imgfile); end
+ nx = reco.RECO_size(1);
+ if length(reco.RECO_size) < 2,
+ ny = 1;
+ else
+ ny = reco.RECO_size(2);
+ end
+ ns = acqp.NSLICES;
+ nt = acqp.NR;
+ if strncmpi(acqp.PULPROG,' 2,
+ ns = reco.RECO_size(3);
+ end
+ nt = acqp.NI;
+ end
+ ImgSize = [nx ny ns nt];
+ % check transposition on reco
+ transpos = 0;
+ if isfield(reco,'RECO_transposition'),
+ transpos = reco.RECO_transposition(1);
+ elseif isfield(reco,'RECO_transpose_dim'),
+ transpos = reco.RECO_transpose_dim(1);
+ end
+ if any(transpos),
+ if transpos == 1,
+ % (x,y,z) --> (y,x,z)
+ tmpvec = [2 1 3];
+ elseif transpos == 2,
+ % (x,y,z) --> (x,z,y)
+ tmpvec = [1 3 2];
+ elseif transpos == 3,
+ % (x,y,z) --> (z,y,x)
+ tmpvec = [3 2 1];
+ end
+ ImgSize(1:3) = ImgSize(tmpvec);
+ end
+end
+
+% check image crop %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+if ~isempty(ImgCrop),
+ % ImgCrop as [x,y,width,height]
+ selx = [1:ImgCrop(3)] + ImgCrop(1) - 1;
+ sely = [1:ImgCrop(4)] + ImgCrop(2) - 1;
+ if min(selx) < 1 | max(selx) > ImgSize(1) | min(sely) < 1 | max(sely) > ImgSize(2),
+ fprintf('\n ImgSize=['); fprintf(' %d',ImgSize); fprintf(' ]');
+ fprintf('\n ImgCrop=['); fprintf(' %d',ImgCrop); fprintf(' ]');
+ error('\n %s error: imgcrop is out of range.\n',mfilename);
+ end
+end
+
+% check slice crop %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+if ~isempty(SliceCrop),
+ % SliceCrop as [s0, nslices]
+ sels = [1:SliceCrop(2)] + SliceCrop(1) - 1;
+ if min(sels) < 1 | max(sels) > ImgSize(3),
+ fprintf('\n ImgSize=['); fprintf(' %d',ImgSize); fprintf(' ]');
+ fprintf('\n SliceCrop=['); fprintf(' %d',SliceCrop); fprintf(' ]');
+ error('\n %s error: slicecrop is out of range.\n',mfilename);
+ end
+end
+
+% check time crop %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+if ~isempty(TimeCrop),
+ % TimeCrop as [t0, tlen]
+ selt = [1:TimeCrop(2)] + TimeCrop(1) - 1;
+ if min(selt) < 1 | max(selt) > ImgSize(4),
+ fprintf('\n ImgSize=['); fprintf(' %d',ImgSize); fprintf(' ]');
+ fprintf('\n TimeCrop=['); fprintf(' %d',TimeCrop); fprintf(' ]');
+ error('\n %s error: timecrop is out of range.\n',mfilename);
+ end
+end
+
+
+% set byte order %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+if isempty(ByteOrder),
+ if isempty(reco), reco = pvread_reco(imgfile); end
+ ByteOrder = reco.RECO_byte_order;
+end
+switch lower(ByteOrder),
+ case {'s','swap','b','big','bigendian','big-endian'}
+ ByteOrder = 'ieee-be';
+ case {'n','noswap','non-swap','l','little','littleendian','little-endian'}
+ ByteOrder = 'ieee-le';
+end
+
+
+% set data type %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+if isempty(WordType),
+ if isempty(reco), reco = pvread_reco(imgfile); end
+ WordType = reco.RECO_wordtype;
+end
+switch WordType,
+ case {'_16_BIT','_16BIT_SGN_INT','int16'}
+ WordType = 'int16=>int16';
+ case {'_32_BIT','_32BIT_SGN_INT','int32'}
+ WordType = 'int32=>int32';
+ otherwise
+ error(' %s error: unknown data type, ''%s''.',WordType,mfilename);
+end
+
+
+% READ DATA %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+fid = fopen(imgfile,'rb',ByteOrder);
+IDATA = fread(fid,inf,WordType);
+fclose(fid);
+
+if isfield(reco,'RECO_image_type') & strcmp(reco.RECO_image_type, 'COMPLEX_IMAGE'),
+ % According to ParaVision manual,
+ % first all real data is written to 2dseq, then imaginary data is appended to it.
+ IDATA = reshape(IDATA,length(IDATA)/2,2);
+ IDATA = complex(IDATA(:,1),IDATA(:,2));
+end
+
+try,
+ IDATA = reshape(IDATA,ImgSize);
+catch
+ fprintf('\n Num.elements=%d,',numel(IDATA));
+ fprintf('\n expected ImgSize=['); fprintf(' %d',ImgSize); fprintf(' ]');
+ error('\n %s error: size mismatch.\n',mfilename);
+end
+
+
+% CROPPING %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+if ~isempty(ImgCrop),
+ IDATA = IDATA(selx,sely,:,:);
+end
+if ~isempty(SliceCrop),
+ IDATA = IDATA(:,:,sels,:);
+end
+if ~isempty(TimeCrop),
+ IDATA = IDATA(:,:,:,selt);
+end
+
+
+% RETURN VALUES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+if nargout,
+ varargout{1} = IDATA;
+ if nargout > 1,
+ varargout{2} = imgp;
+ end
+end
+
+
+return;
+
diff --git a/mpi_code/pvread/pvread_acqp.m b/mpi_code/pvread/pvread_acqp.m
new file mode 100644
index 0000000..6b67cab
--- /dev/null
+++ b/mpi_code/pvread/pvread_acqp.m
@@ -0,0 +1,472 @@
+function varargout = pvread_acqp(varargin)
+%PVREAD_ACQP - Read ParaVision "acqp".
+% ACQP = PVREAD_ACQP(ACQPFILE,...)
+% ACQP = PVREAD_ACQP(2DSEQFILE,...)
+% ACQP = PVREAD_ACQP(SESSION,EXPNO,...) reads ParaVision's "acqp" and
+% returns its contents as a structre, ACQP.
+% Unknown parameter will be returned as a string.
+%
+% Supported options are
+% 'verbose' : 0|1, verbose or not.
+%
+% VERSION :
+% 0.90 13.06.05 YM pre-release
+% 0.91 27.02.07 YM supports also 2dseq as the first argument
+% 0.92 26.03.08 YM returns empty data if file not found.
+% 0.93 18.09.08 YM supports both new csession and old getses.
+% 0.94 15.01.09 YM supports some new parameters
+%
+% See also pv_imgpar pvread_2dseq pvread_imnd pvread_method pvread_reco pvread_visu_pars
+
+if nargin == 0, help pvread_acqp; return; end
+
+
+if ischar(varargin{1}) & ~isempty(strfind(varargin{1},'acqp')),
+ % Called like pvread_acqp(ACQPFILE)
+ ACQPFILE = varargin{1};
+ ivar = 2;
+elseif ischar(varargin{1}) & ~isempty(strfind(varargin{1},'2dseq')),
+ % Called like pvread_acqp(2DSEQFILE)
+ ACQPFILE = fullfile(fileparts(fileparts(fileparts(varargin{1}))),'acqp');
+ ivar = 2;
+else
+ % Called like pvread_acqp(SESSION,ExpNo)
+ if nargin < 2,
+ error(' ERROR %s: missing 2nd arg. as ExpNo.\n',mfilename);
+ return;
+ end
+ if exist('csession','class'),
+ ses = csession(varargin{1});
+ ACQPFILE = ses.filename(varargin{2},'acqp');
+ else
+ ses = goto(varargin{1});
+ ACQPFILE = catfilename(ses,varargin{2},'acqp');
+ end
+ ivar = 3;
+end
+
+% SET OPTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+VERBOSE = 1;
+for N = ivar:2:nargin,
+ switch lower(varargin{N}),
+ case {'verbose'}
+ VERBOSE = varargin{N+1};
+ end
+end
+
+
+if ~exist(ACQPFILE,'file'),
+ if VERBOSE,
+ fprintf(' ERROR %s: ''%s'' not found.\n',mfilename,ACQPFILE);
+ end
+ % SET OUTPUTS, IF REQUIRED %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ if nargout,
+ varargout{1} = [];
+ if nargout > 1, varargout{2} = {}; end
+ end
+ return;
+end
+
+
+% READ TEXT LINES OF "ACQP" %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+texts = {};
+fid = fopen(ACQPFILE,'rt');
+while ~feof(fid),
+ texts{end+1} = fgetl(fid);
+ %texts{end+1} = fgets(fid);
+end
+fclose(fid);
+
+
+
+% MAKE "acqp" structure %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+acqp.filename = ACQPFILE;
+
+acqp.PULPROG = '';
+acqp.GRDPROG = '';
+acqp.ACQ_experiment_mode = '';
+acqp.ACQ_user_filter = '';
+acqp.ACQ_DS_enabled = '';
+acqp.ACQ_switch_pll_enabled= '';
+acqp.ACQ_preload = [];
+acqp.ACQ_dim = [];
+acqp.ACQ_dim_desc = '';
+acqp.ACQ_size = [];
+acqp.ACQ_ns_list_size = [];
+acqp.ACQ_ns = [];
+acqp.ACQ_phase_factor = [];
+acqp.ACQ_scan_size = '';
+acqp.NI = [];
+acqp.NA = [];
+acqp.NAE = [];
+acqp.NR = [];
+acqp.DS = [];
+acqp.D = [];
+acqp.P = [];
+acqp.PL = [];
+acqp.TPQQ = '';
+acqp.DPQQ = '';
+acqp.SW_h = [];
+acqp.SW = [];
+acqp.FW = [];
+acqp.RG = [];
+acqp.AQ_mod = '';
+acqp.DR = [];
+acqp.PAPS = '';
+acqp.PH_ref = [];
+acqp.ACQ_BF_enable = '';
+acqp.BF1 = [];
+acqp.SFO1 = [];
+acqp.O1 = [];
+acqp.ACQ_O1_list_size = [];
+acqp.ACQ_O1_list = [];
+acqp.ACQ_O1B_list_size = [];
+acqp.ACQ_O1B_list = [];
+acqp.BF2 = [];
+acqp.SFO2 = [];
+acqp.O2 = [];
+acqp.ACQ_O2_list_size = [];
+acqp.ACQ_O2_list = [];
+acqp.BF3 = [];
+acqp.SFO3 = [];
+acqp.O3 = [];
+acqp.ACQ_O3_list_size = [];
+acqp.ACQ_O3_list = [];
+acqp.BF4 = [];
+acqp.SFO4 = [];
+acqp.O4 = [];
+acqp.BF5 = [];
+acqp.SFO5 = [];
+acqp.O5 = [];
+acqp.BF6 = [];
+acqp.SFO6 = [];
+acqp.O6 = [];
+acqp.BF7 = [];
+acqp.SFO7 = [];
+acqp.O7 = [];
+acqp.BF8 = [];
+acqp.SFO8 = [];
+acqp.O8 = [];
+acqp.NUC1 = '';
+acqp.NUC2 = '';
+acqp.NUC3 = '';
+acqp.NUC4 = '';
+acqp.NUC5 = '';
+acqp.NUC6 = '';
+acqp.NUC7 = '';
+acqp.NUC8 = '';
+acqp.NUCLEUS = '';
+acqp.ACQ_coil_config_file = '';
+acqp.ACQ_coils = '';
+acqp.ACQ_coil_elements = '';
+acqp.ACQ_operation_mode = '';
+acqp.ACQ_Routing = '';
+acqp.ACQ_routing_mode = '';
+acqp.L = [];
+acqp.ACQ_vd_list_size = [];
+acqp.ACQ_vd_list = [];
+acqp.ACQ_vp_list_size = [];
+acqp.ACQ_vp_list = [];
+acqp.ACQ_status = '';
+acqp.ACQ_Routing_base = '';
+acqp.ACQ_protocol_location = '';
+acqp.ACQ_protocol_name = '';
+acqp.ACQ_scan_name = '';
+acqp.ACQ_method = '';
+acqp.ACQ_completed = '';
+acqp.ACQ_pipe_status = '';
+acqp.ACQ_scans_completed = [];
+acqp.ACQ_nr_completed = [];
+acqp.ACQ_total_completed = [];
+acqp.ACQ_word_size = '';
+acqp.NECHOES = [];
+acqp.ACQ_n_echo_images = [];
+acqp.ACQ_n_movie_frames = [];
+acqp.ACQ_echo_descr = '';
+acqp.ACQ_movie_descr = '';
+acqp.ACQ_fov = [];
+acqp.ACQ_read_ext = [];
+acqp.ACQ_slice_angle = [];
+acqp.ACQ_slice_orient = '';
+acqp.ACQ_patient_pos = '';
+acqp.ACQ_read_offset = [];
+acqp.ACQ_phase1_offset = [];
+acqp.ACQ_phase2_offset = [];
+acqp.ACQ_slice_sepn = [];
+acqp.ACQ_slice_sepn_mode = '';
+acqp.ACQ_slice_thick = [];
+acqp.ACQ_slice_offset = [];
+acqp.ACQ_obj_order = [];
+acqp.ACQ_flip_angle = [];
+acqp.ACQ_flipback = '';
+acqp.ACQ_echo_time = [];
+acqp.ACQ_inter_echo_time = [];
+acqp.ACQ_recov_time = [];
+acqp.ACQ_repetition_time = [];
+acqp.ACQ_scan_time = [];
+acqp.ACQ_inversion_time = [];
+acqp.ACQ_temporal_delay = [];
+acqp.ACQ_time = '';
+acqp.ACQ_time_points = [];
+acqp.ACQ_abs_time = [];
+acqp.ACQ_operator = '';
+acqp.ACQ_RF_power = [];
+acqp.ACQ_transmitter_coil = '';
+acqp.ACQ_receiver_coil = '';
+acqp.ACQ_contrast_agent = '';
+acqp.ACQ_trigger_enable = '';
+acqp.ACQ_trigger_reference = '';
+acqp.ACQ_trigger_delay = [];
+acqp.ACQ_institution = '';
+acqp.ACQ_station = '';
+acqp.ACQ_sw_version = '';
+acqp.ACQ_calib_date = '';
+acqp.ACQ_grad_str_X = [];
+acqp.ACQ_grad_str_Y = [];
+acqp.ACQ_grad_str_Z = [];
+acqp.ACQ_position_X = [];
+acqp.ACQ_position_Y = [];
+acqp.ACQ_position_Z = [];
+acqp.Coil_operation = '';
+acqp.BYTORDA = '';
+acqp.INSTRUM = '';
+acqp.ACQ_adc_overflow = '';
+acqp.GRPDLY = [];
+acqp.FRQLO3 = [];
+acqp.FQ1LIST = '';
+acqp.FQ2LIST = '';
+acqp.FQ3LIST = '';
+acqp.FQ8LIST = '';
+acqp.SP = [];
+acqp.SPOFFS = [];
+acqp.SPNAM0 = '';
+acqp.SPNAM1 = '';
+acqp.SPNAM2 = '';
+acqp.SPNAM3 = '';
+acqp.SPNAM4 = '';
+acqp.SPNAM5 = '';
+acqp.SPNAM6 = '';
+acqp.SPNAM7 = '';
+acqp.SPNAM8 = '';
+acqp.SPNAM9 = '';
+acqp.SPNAM10 = '';
+acqp.SPNAM11 = '';
+acqp.SPNAM12 = '';
+acqp.SPNAM13 = '';
+acqp.SPNAM14 = '';
+acqp.SPNAM15 = '';
+acqp.HPPRGN = '';
+acqp.LOCNUC = '';
+acqp.QNP = [];
+acqp.SOLVENT = '';
+acqp.DIGMOD = '';
+acqp.DIGTYP = '';
+acqp.DQDMODE = '';
+acqp.DSPFIRM = '';
+acqp.DECIM = [];
+acqp.DSPFVS = [];
+acqp.ACQ_scan_shift = [];
+acqp.DEOSC = [];
+acqp.DE = [];
+acqp.FCUCHAN = [];
+acqp.RSEL = [];
+acqp.SWIBOX = [];
+acqp.HPMOD = [];
+acqp.RECCHAN = [];
+acqp.RECSEL = [];
+acqp.RECPRE = [];
+acqp.NLOGCH = [];
+acqp.POWMOD = '';
+acqp.PRECHAN = [];
+acqp.PRECHRX = [];
+acqp.OBSCHAN = [];
+acqp.ACQ_2nd_preamp = '';
+acqp.ACQ_n_trim = [];
+acqp.ACQ_trim = [];
+acqp.ACQ_scaling_read = [];
+acqp.ACQ_scaling_phase = [];
+acqp.ACQ_scaling_slice = [];
+acqp.ACQ_grad_matrix = [];
+acqp.NSLICES = [];
+acqp.ACQ_rare_factor = [];
+acqp.ACQ_phase_encoding_mode = '';
+acqp.ACQ_phase_enc_start = [];
+acqp.ACQ_spatial_size_1 = [];
+acqp.ACQ_spatial_phase_1 = [];
+acqp.GS_dim = [];
+acqp.GS_disp_update = '';
+acqp.GS_online_reco = '';
+acqp.GS_reco_display = '';
+acqp.GS_image_type = '';
+acqp.GS_typ = '';
+acqp.GS_auto_name = '';
+acqp.GS_info_dig_filling = '';
+acqp.GS_info_normalized_area = '';
+acqp.GS_info_max_point = '';
+acqp.GS_get_info_points = '';
+acqp.GS_continue = '';
+acqp.GS_ReceiverSelect = '';
+acqp.GO_init_files = '';
+acqp.GO_data_save = '';
+acqp.GO_block_size = '';
+acqp.GO_raw_data_format = '';
+acqp.GO_disp_update = '';
+acqp.GO_online_reco = '';
+acqp.GO_reco_display = '';
+acqp.GO_reco_each_nr = '';
+acqp.GO_max_reco_mem = [];
+acqp.GO_time_est = '';
+acqp.GO_use_macro = '';
+acqp.GO_macro = '';
+
+% for MDEFT
+acqp.ACQ_spatial_size_2 = [];
+
+% new parameters
+
+
+
+
+
+
+% GET "acqp" VALUES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+for N = 1:length(texts),
+ if strncmpi(texts{N},'##$',3),
+ % get the parameter name
+ idx = strfind(texts{N},'=');
+ tmpname = texts{N}(4:idx-1);
+ % get the value(s)
+ if isempty(strfind(texts{N},'=(')),
+ tmpval = texts{N}(idx+1:end);
+ tmpdim = [];
+ else
+ s1 = strfind(texts{N},'(');
+ s2 = strfind(texts{N},')');
+ if isempty(s2),
+ tmpdim = [];
+ tmpval = texts{N}(s1:end);
+ else
+ % get dimension
+ tmpdim = str2num(texts{N}(s1+1:s2-1));
+ tmpval = '';
+ end
+ K = N;
+ while ~strncmpi(texts{K+1},'##',2),
+ K = K + 1;
+ end
+ % USE sprintf() since strcat remove blank...
+ if isempty(tmpdim),
+ tmpval = sprintf('%s',tmpval,texts{N+1:K});
+ else
+ tmpval = sprintf('%s ',tmpval,texts{N+1:K});
+ end
+ %tmpval = strcat(texts{N+1:K});
+ N = K + 1;
+ end
+
+ % WHY?? THIS HAPPENS
+ idx = strfind(tmpval,'$$');
+ if ~isempty(idx), tmpval = tmpval(1:idx-1); end
+
+ % set the value(s)
+ tmpval = strtrim(tmpval);
+ if isfield(acqp,tmpname),
+ if ischar(acqp.(tmpname)),
+ if any(tmpdim) && tmpval(1) ~= '<',
+ acqp.(tmpname) = subStr2CellStr(tmpval,tmpdim);
+ else
+ acqp.(tmpname) = tmpval;
+ end
+ elseif isnumeric(acqp.(tmpname)),
+ acqp.(tmpname) = str2num(tmpval);
+ if length(tmpdim) > 1 & prod(tmpdim) == numel(acqp.(tmpname)),
+ acqp.(tmpname) = reshape(acqp.(tmpname),fliplr(tmpdim));
+ acqp.(tmpname) = permute(acqp.(tmpname),length(tmpdim):-1:1);
+ end
+ else
+ acqp.(tmpname) = tmpval;
+ end
+ else
+ acqp.(tmpname) = tmpval;
+ end
+ end
+end
+
+% after care of some parameters....
+%acqp.xxxx = subStr2CellNum(acqp.xxxx);
+
+
+% remove empty members
+fields = fieldnames(acqp);
+IDX = zeros(1,length(fields));
+for N = 1:length(fields), IDX(N) = isempty(acqp.(fields{N})); end
+acqp = rmfield(acqp,fields(find(IDX)));
+
+
+% SET OUTPUTS, IF REQUIRED %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+if nargout,
+ varargout{1} = acqp;
+ if nargout > 1,
+ varargout{2} = texts;
+ end
+end
+
+return;
+
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% SUBFUNCITON to make a cell string from a 'space' or '()' separeted string
+function val = subStr2CellStr(str,dim)
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+if isempty(str) || iscell(str),
+ val = str;
+ return;
+end
+
+if nargin < 2, dim = []; end
+
+val = {};
+
+if str(1) == '(',
+ idx1 = strfind(str,'(');
+ idx2 = strfind(str,')');
+ for N = 1:length(idx1),
+ val{N} = strtrim(str(idx1(N)+1:idx2(N)-1));
+ end
+else
+ % 'space' separated
+ [token, rem] = strtok(str,' ');
+ while ~isempty(token),
+ val{end+1} = token;
+ [token, rem] = strtok(rem,' ');
+ end
+end
+
+if length(dim) > 1 && prod(dim) > 0,
+ val = reshape(val,dim);
+end
+
+return;
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% SUBFUNCITON to make a cell matrix from a '()' separeted string
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+function val = subStr2CellNum(str)
+if isempty(str),
+ val = str;
+ return;
+end
+
+idx1 = strfind(str,'(');
+idx2 = strfind(str,')');
+
+val = {};
+for N = 1:length(idx1),
+ val{N} = str2num(str(idx1(N)+1:idx2(N)-1));
+end
+
+return;
diff --git a/mpi_code/pvread/pvread_imnd.m b/mpi_code/pvread/pvread_imnd.m
new file mode 100644
index 0000000..89371da
--- /dev/null
+++ b/mpi_code/pvread/pvread_imnd.m
@@ -0,0 +1,466 @@
+function varargout = pvread_imnd(varargin)
+%PVREAD_IMND - Read ParaVision "imnd".
+% IMND = PVREAD_IMND(IMNDFILE,...)
+% IMND = PVREAD_IMND(2DSEQFILE,...)
+% IMND = PVREAD_IMND(SESSION,EXPNO,...) reads ParaVision's "imnd" and
+% returns its contents as a structre, IMND.
+% Unknown parameter will be returned as a string.
+%
+% Supported options are
+% 'verbose' : 0|1, verbose or not.
+%
+% VERSION :
+% 0.90 13.06.05 YM pre-release
+% 0.91 14.06.05 YM checked both 'mdeft' and 'epi'.
+% 0.92 27.02.07 YM supports also 2dseq as the first argument
+% 0.93 26.03.08 YM returns empty data if file not found.
+% 0.94 18.09.08 YM supports both new csession and old getses.
+%
+% See also pv_imgpar pvread_2dseq pvread_acqp pvread_method pvread_reco pvread_visu_pars
+
+if nargin == 0, help pvread_imnd; return; end
+
+
+if ischar(varargin{1}) & ~isempty(strfind(varargin{1},'imnd')),
+ % Called like pvread_imnd(IMNDFILE)
+ IMNDFILE = varargin{1};
+ ivar = 2;
+elseif ischar(varargin{1}) & ~isempty(strfind(varargin{1},'2dseq')),
+ % Called like pvread_imnd(2DSEQFILE)
+ IMNDFILE = fullfile(fileparts(fileparts(fileparts(varargin{1}))),'imnd');
+ ivar = 2;
+else
+ % Called like pvread_imnd(SESSION,ExpNo)
+ if nargin < 2,
+ error(' ERROR %s: missing 2nd arg. as ExpNo.\n',mfilename);
+ return;
+ end
+ if exist('csession','class'),
+ ses = csession(varargin{1});
+ IMNDFILE = ses.filename(varargin{2},'imnd');
+ else
+ ses = goto(varargin{1});
+ IMNDFILE = catfilename(ses,varargin{2},'imnd');
+ end
+ ivar = 3;
+end
+
+
+% SET OPTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+VERBOSE = 1;
+for N = ivar:2:nargin,
+ switch lower(varargin{N}),
+ case {'verbose'}
+ VERBOSE = varargin{N+1};
+ end
+end
+
+
+if ~exist(IMNDFILE,'file'),
+ if VERBOSE,
+ fprintf(' ERROR %s: ''%s'' not found.\n',mfilename,IMNDFILE);
+ end
+ % SET OUTPUTS, IF REQUIRED %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ if nargout,
+ varargout{1} = [];
+ if nargout > 1, varargout{2} = {}; end
+ end
+ return;
+end
+
+
+% READ TEXT LINES OF "IMND" %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+texts = {};
+fid = fopen(IMNDFILE,'rt');
+while ~feof(fid),
+ texts{end+1} = fgetl(fid);
+ %texts{end+1} = fgets(fid);
+end
+fclose(fid);
+
+
+
+% MAKE "imnd" structure %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+imnd.filename = IMNDFILE;
+
+imnd.IMND_method = '';
+imnd.IMND_method_display_name = '';
+imnd.IMND_dummy_method = '';
+imnd.IMND_nucleus = '';
+imnd.IMND_matrix_eq = [];
+imnd.IMND_matrix = [];
+imnd.IMND_sw_h = [];
+imnd.IMND_scout_orient_matrix_curr = [];
+imnd.IMND_scout_orient_matrix = [];
+imnd.IMND_rep_time = [];
+imnd.IMND_recov_time = [];
+imnd.IMND_echo_time = [];
+imnd.IMND_add_delay = [];
+imnd.IMND_homospoil_delay = [];
+imnd.IMND_pulse_angle = [];
+imnd.IMND_total_time = [];
+imnd.IMND_pulse_length = [];
+imnd.IMND_refocus_length = [];
+imnd.IMND_sat_pulse_length = [];
+imnd.IMND_n_averages = [];
+imnd.IMND_flipback = '';
+imnd.IMND_n_echo_images = [];
+imnd.IMND_echo_scan_eq = [];
+imnd.IMND_n_echoes = [];
+imnd.IMND_rare_factor = [];
+imnd.EPI_AQ_mod = '';
+imnd.EPI_DIGMOD = '';
+imnd.EPI_DSPFIRM = '';
+imnd.EPI_max_read = [];
+imnd.IMND_max_read = [];
+imnd.EPI_int = [];
+imnd.EPI_double = [];
+imnd.EPI_diff_use_corr = '';
+imnd.EPI_supp_flag = '';
+imnd.EPI_trim = [];
+imnd.EPI_scan_mode = '';
+imnd.EPI_TE_eff = [];
+imnd.EPI_se_asymmetry_offset = [];
+imnd.EPI_read_spoiler = [];
+imnd.EPI_zero_phase = [];
+imnd.EPI_zero_phase_ms = [];
+imnd.EPI_seg_acq_time = [];
+imnd.EPI_image_time = [];
+imnd.EPI_even_only = '';
+imnd.EPI_read_echo_pos = [];
+imnd.EPI_phaseblip_asym = [];
+imnd.EPI_phasedur_asym = [];
+imnd.EPI_phaseblip_ms = [];
+imnd.EPI_phase_off = '';
+imnd.EPI_use_pipefilter = '';
+imnd.EPI_linear_regrid = '';
+imnd.IMND_regrid_mode = '';
+imnd.IMND_regrid_traj = [];
+imnd.EPI_correction_mode = '';
+imnd.EPI_navigation_type = '';
+imnd.EPI_ramp_time = [];
+imnd.EPI_ramp_gap = [];
+imnd.EPI_ramp_time_x = [];
+imnd.EPI_ramp_time_y = [];
+imnd.EPI_ramp_time_z = [];
+imnd.IMND_assym_acq = [];
+imnd.IMND_matched_bw = '';
+imnd.IMND_max_read = [];
+imnd.IMND_flow = [];
+imnd.EPI_FID = '';
+imnd.EPI_NAV_FIRST_NR = '';
+imnd.EPI_SE_DIFFUSION = '';
+imnd.EPI_SE_Inversion = '';
+imnd.EPI_SE_Tagging = '';
+imnd.EPI_SPIN_ECHO = '';
+imnd.EPI_STE_DIFFUSION = '';
+imnd.EPI_STIMULATED_ECHO = '';
+imnd.EPI_Not_TC = '';
+imnd.EPI_Set_TC = '';
+imnd.EPI_Set_TCnav = '';
+imnd.EPI_Set_TCnF = '';
+imnd.EPI_seg_grad = [];
+imnd.EPI_tagging_phase = '';
+imnd.EPI_tagging_read = '';
+imnd.EPI_O3_list_size = [];
+imnd.EPI_O6_list_size = [];
+imnd.EPI_O6_list = [];
+imnd.Trigger_In_Once = '';
+imnd.Trigger_In_Every_Package = '';
+imnd.Trigger_In_Every_Excitation = '';
+imnd.Trigger_Out_Once = '';
+imnd.Trigger_Out_Every_Package = '';
+imnd.Trigger_Out_Every_Excitation= '';
+imnd.EPI_xfer_buffer_size = [];
+imnd.EPI_grad_cal_const = [];
+imnd.EPI_X_factor = [];
+imnd.EPI_Y_factor = [];
+imnd.EPI_Z_factor = [];
+imnd.EPI_status = '';
+imnd.EPI_preemp_file = '';
+imnd.EPI_resid = '';
+imnd.IMND_store_sw_h = [];
+imnd.EPI_SEG_CALC = '';
+imnd.EPI_Trigger_In = '';
+imnd.EPI_Trigger_Out = '';
+imnd.EPI_Pause_Trigger_Out = '';
+imnd.EPI_DS_enabled = '';
+imnd.EPI_recm_slice_rep_time = [];
+imnd.EPI_slice_rep_time = [];
+imnd.EPI_use_vd = '';
+imnd.EPI_use_id = '';
+imnd.EPI_use_Synch = '';
+imnd.EPI_TC_mode = '';
+imnd.EPI_TimeToNav = [];
+imnd.EPI_TC_nslices = [];
+imnd.EPI_TC_DS = [];
+imnd.EPI_nav_DS = [];
+imnd.EPI_navAU_DS = [];
+imnd.EPI_n_navfids = [];
+imnd.EPI_n_navprep = [];
+imnd.EPI_n_navecho = [];
+imnd.EPI_TC_rep_time = [];
+imnd.EPI_TC_respFreq = [];
+imnd.EPI_dummy_echoes = [];
+imnd.EPI_ds_echopairs = [];
+imnd.EPI_recm_image_rep_time = [];
+imnd.EPI_image_rep_time = [];
+imnd.EPI_swh_eff_phase = [];
+imnd.EPI_segmentation_mode = '';
+imnd.IMND_numsegments = [];
+imnd.EPI_numsegments = [];
+imnd.EPI_nr = [];
+imnd.EPI_act_rep_time = [];
+imnd.IMND_inv_delay_storage = [];
+imnd.IMND_num_segments = [];
+imnd.IMND_tau_time = [];
+imnd.IMND_MagPrep_mode = '';
+imnd.IMND_dim = [];
+imnd.IMND_patient_pos = '';
+imnd.IMND_dimension = '';
+imnd.IMND_square_fov_matrix = '';
+imnd.IMND_isotropic = '';
+imnd.IMND_fov_eq = [];
+imnd.IMND_fov = [];
+imnd.IMND_slice_orient = '';
+imnd.IMND_n_slices = [];
+imnd.IMND_slice_offset = [];
+imnd.IMND_slice_sepn_mode = '';
+imnd.IMND_slice_sepn = [];
+imnd.IMND_slice_thick = [];
+imnd.IMND_slice_angle = [];
+imnd.IMND_slice_angle_eq = [];
+imnd.IMND_ScoutRel_SgRotAngle = [];
+imnd.IMND_ScoutRel_SgRotAngle_eq = [];
+imnd.IMND_ScoutRel_SgTiltAngle = [];
+imnd.IMND_ScoutRel_SgTiltAngle_eq= [];
+imnd.IMND_ScoutRel_RgRotAngle = [];
+imnd.IMND_ScoutRel_RgRotAngle_eq = [];
+imnd.IMND_read_ext = [];
+imnd.IMND_read_offset = [];
+imnd.IMND_read_offset_eq = [];
+imnd.IMND_slice_scheme = '';
+imnd.IMND_slice_list = [];
+imnd.IMND_n_slicepacks = [];
+imnd.IMND_slicepack_n_slices = [];
+imnd.IMND_slicepack_vector = [];
+imnd.IMND_slicepack_position = [];
+imnd.IMND_slicepack_gap = [];
+imnd.IMND_read_vector = [];
+imnd.IMND_slicepack_read_offset = [];
+imnd.IMND_phase1_offset = [];
+imnd.IMND_phase2_offset = [];
+imnd.IMND_anti_alias = [];
+imnd.IMND_csind_flag = '';
+imnd.IMND_acq_mode = '';
+imnd.IMND_trigger_enable = '';
+imnd.IMND_auto_adv = '';
+imnd.IMND_evolution_trigger = '';
+imnd.IMND_movie = '';
+imnd.IMND_mtc_mode = '';
+imnd.IMND_inv_mode = '';
+imnd.IMND_fat_mode = '';
+imnd.IMND_suppression = '';
+imnd.IMND_supp_shape_enum = '';
+imnd.IMND_supp_length = [];
+imnd.IMND_sat_mode = '';
+imnd.IMND_sat_shape = '';
+imnd.IMND_sat_slice_thick_hz = [];
+imnd.IMND_FovSat_n_slices = [];
+imnd.IMND_FovSat_thick = [];
+imnd.IMND_FovSat_offset = [];
+imnd.IMND_FovSat_dir_vector = [];
+imnd.IMND_FovSat_rot_angle = [];
+imnd.IMND_FovSat_tilt_angle = [];
+imnd.IMND_InflowSat_n_slices = [];
+imnd.IMND_InflowSat_thick = [];
+imnd.IMND_InflowSat_slice_offset = [];
+imnd.IMND_contrast_agent = '';
+imnd.IMND_grad_refo = '';
+imnd.IMND_rf_spoil = '';
+imnd.IMND_use_grad = [];
+imnd.IMND_use_rise_time = [];
+imnd.IMND_max_spoil_time = [];
+imnd.IMND_imag_shape_enum = '';
+imnd.IMND_imag_shape = '';
+imnd.IMND_sl_thick_hz = [];
+imnd.IMND_acq_time = [];
+imnd.IMND_DW_time = [];
+imnd.IMND_rep_delay = [];
+imnd.IMND_nuc1 = '';
+imnd.IMND_bf1 = [];
+imnd.IMND_rcvr_offset_bc = '';
+imnd.IMND_isotropic_reco = '';
+imnd.IMND_zf = [];
+imnd.IMND_apc = '';
+imnd.IMND_phase_encoding_mode_1 = '';
+imnd.IMND_phase_encoding_mode = '';
+imnd.IMND_phase_start_1 = [];
+imnd.IMND_phase_enc_start = [];
+imnd.IMND_user_phase = [];
+imnd.IMND_dscan_time = [];
+imnd.IMND_dscans = [];
+imnd.IMND_derive_gains = '';
+imnd.IMND_reference_gain = [];
+imnd.IMND_ref_gain_state = '';
+imnd.IMND_rg_defined = '';
+imnd.IMND_motionsup = '';
+imnd.IMND_EffEchoTime1 = [];
+imnd.IMND_NEchoScan1 = [];
+imnd.IMND_RareMaxEchoes = [];
+imnd.IMND_flowcomp = '';
+imnd.IMND_bandwidth_1 = [];
+imnd.IMND_ScanSummary = '';
+imnd.IMND_invflag = '';
+imnd.IMND_mtcflag = '';
+imnd.IMND_fatflag = '';
+imnd.IMND_FovSat_flag = [];
+imnd.IMND_InflowSat_flag = [];
+imnd.IMND_TE_long = '';
+
+
+
+% GET "imnd" VALUES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+for N = 1:length(texts),
+ if strncmpi(texts{N},'##$',3),
+ % get the parameter name
+ idx = strfind(texts{N},'=');
+ tmpname = texts{N}(4:idx-1);
+ % get the value(s)
+ if isempty(strfind(texts{N},'=(')),
+ tmpval = texts{N}(idx+1:end);
+ tmpdim = [];
+ else
+ s1 = strfind(texts{N},'(');
+ s2 = strfind(texts{N},')');
+ if isempty(s2),
+ tmpdim = [];
+ tmpval = texts{N}(s1:end);
+ else
+ % get dimension
+ tmpdim = str2num(texts{N}(s1+1:s2-1));
+ tmpval = '';
+ end
+ K = N;
+ while ~strncmpi(texts{K+1},'##',2),
+ K = K + 1;
+ end
+ % USE sprintf() since strcat remove blank...
+ if isempty(tmpdim),
+ tmpval = sprintf('%s',tmpval,texts{N+1:K});
+ else
+ tmpval = sprintf('%s ',tmpval,texts{N+1:K});
+ end
+ %tmpval = strcat(texts{N+1:K});
+ N = K + 1;
+ end
+
+ % WHY?? THIS HAPPENS
+ idx = strfind(tmpval,'$$');
+ if ~isempty(idx), tmpval = tmpval(1:idx-1); end
+
+ % set the value(s)
+ tmpval = strtrim(tmpval);
+ if isfield(imnd,tmpname),
+ if ischar(imnd.(tmpname)),
+ if any(tmpdim) && tmpval(1) ~= '<',
+ imnd.(tmpname) = subStr2CellStr(tmpval,tmpdim);
+ else
+ imnd.(tmpname) = tmpval;
+ end
+ imnd.(tmpname) = tmpval;
+ elseif isnumeric(imnd.(tmpname)),
+ imnd.(tmpname) = str2num(tmpval);
+ if length(tmpdim) > 1 & prod(tmpdim) == numel(imnd.(tmpname)),
+ imnd.(tmpname) = reshape(imnd.(tmpname),fliplr(tmpdim));
+ imnd.(tmpname) = permute(imnd.(tmpname),length(tmpdim):-1:1);
+ end
+ else
+ imnd.(tmpname) = tmpval;
+ end
+ else
+ imnd.(tmpname) = tmpval;
+ end
+ end
+end
+
+% after care of some parameters....
+%imnd.xxxx = subStr2CellNum(imnd.xxxx);
+
+
+% remove empty members
+fields = fieldnames(imnd);
+IDX = zeros(1,length(fields));
+for N = 1:length(fields), IDX(N) = isempty(imnd.(fields{N})); end
+imnd = rmfield(imnd,fields(find(IDX)));
+
+
+
+
+% SET OUTPUTS, IF REQUIRED %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+if nargout,
+ varargout{1} = imnd;
+ if nargout > 1,
+ varargout{2} = texts;
+ end
+end
+
+return;
+
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% SUBFUNCITON to make a cell string from a 'space' or '()' separeted string
+function val = subStr2CellStr(str,dim)
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+if isempty(str) || iscell(str),
+ val = str;
+ return;
+end
+
+if nargin < 2, dim = []; end
+
+val = {};
+
+if str(1) == '(',
+ idx1 = strfind(str,'(');
+ idx2 = strfind(str,')');
+ for N = 1:length(idx1),
+ val{N} = strtrim(str(idx1(N)+1:idx2(N)-1));
+ end
+else
+ % 'space' separated
+ [token, rem] = strtok(str,' ');
+ while ~isempty(token),
+ val{end+1} = token;
+ [token, rem] = strtok(rem,' ');
+ end
+end
+
+if length(dim) > 1 && prod(dim) > 0,
+ val = reshape(val,dim);
+end
+
+return;
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% SUBFUNCITON to make a cell matrix from a '()' separeted string
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+function val = subStr2CellNum(str)
+if isempty(str),
+ val = str;
+ return;
+end
+
+idx1 = strfind(str,'(');
+idx2 = strfind(str,')');
+
+val = {};
+for N = 1:length(idx1),
+ val{N} = str2num(str(idx1(N)+1:idx2(N)-1));
+end
+
+return;
diff --git a/mpi_code/pvread/pvread_method.m b/mpi_code/pvread/pvread_method.m
new file mode 100644
index 0000000..25a88f8
--- /dev/null
+++ b/mpi_code/pvread/pvread_method.m
@@ -0,0 +1,530 @@
+function varargout = pvread_method(varargin)
+%PVREAD_METHOD - Read ParaVision "method".
+% METHOD = PVREAD_METHOD(METHODFILE,...)
+% METHOD = PVREAD_METHOD(2DSEQFILE,...)
+% METHOD = PVREAD_METHOD(SESSION,EXPNO,...) reads ParaVision's "method" and
+% returns its contents as a structre, METHOD.
+% Unknown parameter will be returned as a string.
+%
+% Supported options are
+% 'verbose' : 0|1, verbose or not.
+%
+% VERSION :
+% 0.90 26.03.08 YM pre-release, checked epi/mdeft/rare/flash of 7T.
+% 0.91 18.09.08 YM supports both new csession and old getses.
+% 0.92 15.01.09 YM supports some new parameters
+%
+% See also pv_imgpar pvread_2dseq pvread_acqp pvread_imnd pvread_reco pvread_visu_pars
+
+if nargin == 0, help pvread_method; return; end
+
+
+if ischar(varargin{1}) & ~isempty(strfind(varargin{1},'method')),
+ % Called like pvread_method(METHODFILE)
+ METHODFILE = varargin{1};
+ ivar = 2;
+elseif ischar(varargin{1}) & ~isempty(strfind(varargin{1},'2dseq')),
+ % Called like pvread_method(2DSEQFILE)
+ METHODFILE = fullfile(fileparts(fileparts(fileparts(varargin{1}))),'method');
+ ivar = 2;
+else
+ % Called like pvread_method(SESSION,ExpNo)
+ if nargin < 2,
+ error(' ERROR %s: missing 2nd arg. as ExpNo.\n',mfilename);
+ return;
+ end
+ if exist('csession','class'),
+ ses = csession(varargin{1});
+ METHODFILE = ses.filename(varargin{2},'method');
+ else
+ ses = goto(varargin{1});
+ METHODFILE = catfilename(ses,varargin{2},'method');
+ end
+ ivar = 3;
+end
+
+
+% SET OPTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+VERBOSE = 1;
+for N = ivar:2:nargin,
+ switch lower(varargin{N}),
+ case {'verbose'}
+ VERBOSE = varargin{N+1};
+ end
+end
+
+
+if ~exist(METHODFILE,'file'),
+ if VERBOSE,
+ fprintf(' ERROR %s: ''%s'' not found.\n',mfilename,METHODFILE);
+ end
+ % SET OUTPUTS, IF REQUIRED %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ if nargout,
+ varargout{1} = [];
+ if nargout > 1, varargout{2} = {}; end
+ end
+ return;
+end
+
+
+% READ TEXT LINES OF "METHOD" %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+texts = {};
+fid = fopen(METHODFILE,'rt');
+while ~feof(fid),
+ texts{end+1} = fgetl(fid);
+ %texts{end+1} = fgets(fid);
+end
+fclose(fid);
+
+
+
+% MAKE "method" structure %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+method.filename = METHODFILE;
+
+method.Method = '';
+method.EchoTime = [];
+method.PVM_MinEchoTime = [];
+method.NSegments = [];
+method.PVM_RepetitionTime = [];
+method.PackDel = [];
+method.PVM_NAverages = [];
+method.PVM_NRepetitions = [];
+method.PVM_ScanTimeStr = '';
+method.SignalType = '';
+method.PVM_UserType = '';
+method.PVM_DeriveGains = '';
+method.PVM_EncUseMultiRec = '';
+method.PVM_EncActReceivers= '';
+method.PVM_EncZfRead = [];
+method.PVM_EncPpiAccel1 = [];
+method.PVM_EncPftAccel1 = [];
+method.PVM_EncPpiRefLines1= [];
+method.PVM_EncZfAccel1 = [];
+method.PVM_EncOrder1 = '';
+method.PVM_EncStart1 = [];
+method.PVM_EncMatrix = [];
+method.PVM_EncSteps1 = [];
+method.PVM_EncCentralStep1= [];
+method.PVM_EncTotalAccel = [];
+method.PVM_EncNReceivers = [];
+method.PVM_EncAvailReceivers = [];
+method.PVM_EncChanScaling = [];
+method.PVM_OperationMode = '';
+method.ExcPulseEnum = '';
+method.ExcPulse = '';
+method.RefPulseEnum = '';
+method.RefPulse = '';
+method.PVM_GradCalConst = [];
+method.PVM_Nucleus1Enum = '';
+method.PVM_Nucleus1 = '';
+method.PVM_RefAttMod1 = '';
+method.PVM_RefAttCh1 = [];
+method.PVM_RefAttStat1 = '';
+method.PVM_Nucleus2Enum = '';
+method.PVM_Nucleus3Enum = '';
+method.PVM_Nucleus4Enum = '';
+method.PVM_Nucleus5Enum = '';
+method.PVM_Nucleus6Enum = '';
+method.PVM_Nucleus7Enum = '';
+method.PVM_Nucleus8Enum = '';
+method.RephaseTime = [];
+method.PVM_EffSWh = [];
+method.PVM_EpiNavigatorMode='';
+method.PVM_EpiPrefixNavYes= '';
+method.PVM_EpiGradSync = '';
+method.PVM_EpiRampMode = '';
+method.PVM_EpiRampForm = '';
+method.PVM_EpiRampComp = '';
+method.PVM_EpiNShots = [];
+method.PVM_EpiEchoPosition= [];
+method.PVM_EpiRampTime = [];
+method.PVM_EpiSlope = [];
+method.PVM_EpiEffSlope = [];
+method.PVM_EpiBlipTime = [];
+method.PVM_EpiSwitchTime = [];
+method.PVM_EpiEchoDelay = [];
+method.PVM_EpiModuleTime = [];
+method.PVM_EpiGradDwellTime=[];
+method.PVM_EpiAutoGhost = '';
+method.PVM_EpiAcqDelayTrim= [];
+method.PVM_EpiBlipAsym = [];
+method.PVM_EpiReadAsym = [];
+method.PVM_EpiReadDephTrim= [];
+method.PVM_EpiEchoTimeShifting='';
+method.PVM_EpiEchoShiftA = [];
+method.PVM_EpiEchoShiftB = [];
+method.PVM_EpiDriftCorr = '';
+method.PVM_EpiGrappaThresh= [];
+method.PVM_EpiEchoSpacing = [];
+method.PVM_EpiEffBandwidth= [];
+method.PVM_EpiDephaseTime = [];
+method.PVM_EpiDephaseRampTime= [];
+method.PVM_EpiPlateau = [];
+method.PVM_EpiAcqDelay = [];
+method.PVM_EpiInterTime = [];
+method.PVM_EpiReadDephGrad = [];
+method.PVM_EpiReadOddGrad = [];
+method.PVM_EpiReadEvenGrad= [];
+method.PVM_EpiPhaseDephGrad= [];
+method.PVM_EpiPhaseRephGrad= [];
+method.PVM_EpiBlipOddGrad = [];
+method.PVM_EpiBlipEvenGrad= [];
+method.PVM_EpiPhaseEncGrad= [];
+method.PVM_EpiPhaseRewGrad= [];
+method.PVM_EpiNEchoes = [];
+method.PVM_EpiEchoCounter = [];
+method.PVM_EpiRampUpIntegral= [];
+method.PVM_EpiRampDownIntegral= [];
+method.PVM_EpiBlipIntegral= [];
+method.PVM_EpiSlopeFactor = [];
+method.PVM_EpiSlewRate = [];
+method.PVM_EpiNSamplesPerScan = [];
+method.PVM_EpiPrefixNavSize = [];
+method.PVM_EpiPrefixNavDur= [];
+method.PVM_EpiNScans = [];
+method.PVM_EpiNInitNav = [];
+method.PVM_EpiAdjustMode = [];
+method.PVM_EpiReadCenter = [];
+method.PVM_EpiPhaseCorrection = [];
+method.PVM_EpiGrappaCoefficients = [];
+method.BwScale = [];
+method.PVM_TrajectoryMeasurement = '';
+method.PVM_UseTrajectory = '';
+method.PVM_ExSliceRephaseTime = [];
+method.SliceSpoilerDuration = [];
+method.SliceSpoilerStrength = [];
+method.PVM_DigAutSet = '';
+method.PVM_DigQuad = '';
+method.PVM_DigFilter = '';
+method.PVM_DigRes = [];
+method.PVM_DigDw = [];
+method.PVM_DigSw = [];
+method.PVM_DigNp = [];
+method.PVM_DigShift = [];
+method.PVM_DigGroupDel = [];
+method.PVM_DigDur = [];
+method.PVM_DigEndDelMin = [];
+method.PVM_DigEndDelOpt = [];
+method.PVM_GeoMode = '';
+method.PVM_SpatDimEnum = '';
+method.PVM_Isotropic = '';
+method.PVM_Fov = [];
+method.PVM_FovCm = [];
+method.PVM_SpatResol = [];
+method.PVM_Matrix = [];
+method.PVM_MinMatrix = [];
+method.PVM_MaxMatrix = [];
+method.PVM_AntiAlias = [];
+method.PVM_MaxAntiAlias = [];
+method.PVM_SliceThick = [];
+method.PVM_ObjOrderScheme = '';
+method.PVM_ObjOrderList = [];
+method.PVM_NSPacks = [];
+method.PVM_SPackArrNSlices= [];
+method.PVM_MajSliceOri = '';
+method.PVM_SPackArrSliceOrient = '';
+method.PVM_SPackArrReadOrient = '';
+method.PVM_SPackArrReadOffset = [];
+method.PVM_SPackArrPhase1Offset = [];
+method.PVM_SPackArrPhase2Offset = [];
+method.PVM_SPackArrSliceOffset = [];
+method.PVM_SPackArrSliceGapMode = '';
+method.PVM_SPackArrSliceGap = [];
+method.PVM_SPackArrSliceDistance = [];
+method.PVM_SPackArrGradOrient = [];
+method.Reco_mode = '';
+method.NDummyScans = [];
+method.PVM_TriggerModule = '';
+method.PVM_TaggingOnOff = '';
+method.PVM_TaggingPulse = '';
+method.PVM_TaggingDeriveGainMode = '';
+method.PVM_TaggingMode = '';
+method.PVM_TaggingDir = '';
+method.PVM_TaggingDistance = [];
+method.PVM_TaggingMinDistance = [];
+method.PVM_TaggingThick = [];
+method.PVM_TaggingOffset1 = [];
+method.PVM_TaggingOffset2 = [];
+method.PVM_TaggingAngle = [];
+method.PVM_TaggingDelay = [];
+method.PVM_TaggingModuleTime = [];
+method.PVM_TaggingPulseNumber = [];
+method.PVM_TaggingPulseElement = [];
+method.PVM_TaggingGradientStrength = [];
+method.PVM_TaggingSpoilGrad = [];
+method.PVM_TaggingSpoilDuration = [];
+method.PVM_TaggingGridDelay = [];
+method.PVM_TaggingD0 = [];
+method.PVM_TaggingD1 = [];
+method.PVM_TaggingD2 = [];
+method.PVM_TaggingD3 = [];
+method.PVM_TaggingD4 = [];
+method.PVM_TaggingD5 = [];
+method.PVM_TaggingP0 = [];
+method.PVM_TaggingLp0 = [];
+method.PVM_TaggingGradAmp1= [];
+method.PVM_TaggingGradAmp2= [];
+method.PVM_TaggingGradAmp3= [];
+method.PVM_TaggingGradAmp4= [];
+method.PVM_TaggingSpoiler = [];
+method.PVM_FatSupOnOff = '';
+method.PVM_MagTransOnOff = '';
+method.PVM_FovSatOnOff = '';
+method.PVM_FovSatNSlices = [];
+method.PVM_FovSatSliceOrient = '';
+method.PVM_FovSatThick = [];
+method.PVM_FovSatOffset = [];
+method.PVM_FovSatSliceVec = [];
+method.PVM_SatSlicesPulseEnum = '';
+method.PVM_SatSlicesPulse = '';
+method.PVM_SatSlicesDeriveGainMode = '';
+method.PVM_FovSatGrad = [];
+method.PVM_FovSatSpoilTime = [];
+method.PVM_FovSatSpoilGrad = [];
+method.PVM_FovSatModuleTime = [];
+method.PVM_FovSatFL = [];
+method.PVM_SatD0 = [];
+method.PVM_SatD1 = [];
+method.PVM_SatD2 = [];
+method.PVM_SatP0 = [];
+method.PVM_SatLp0 = [];
+method.PVM_TriggerOutOnOff = '';
+method.PVM_TriggerOutMode = '';
+method.PVM_TriggerOutDelay = [];
+method.PVM_TrigOutD0 = [];
+method.PVM_PreemphasisSpecial = '';
+method.PVM_PreemphasisFileEnum = '';
+method.PVM_EchoTime1 = [];
+method.PVM_EchoTime2 = [];
+method.PVM_EchoTime = [];
+method.PVM_NEchoImages = [];
+
+% for MDEFT
+method.EchoRepTime = [];
+method.SegmRepTime = [];
+method.SegmDuration = [];
+method.SegmNumber = [];
+method.PVM_InversionTime = [];
+method.PVM_EchoPosition = [];
+method.SequenceOptimizationMode = '';
+method.EchoPad = [];
+method.RFSpoilerOnOff = '';
+method.SpoilerDuration = [];
+method.SpoilerStrength = [];
+method.NDummyEchoes = [];
+method.Mdeft_PreparationMode = '';
+method.Mdeft_ExcPulseEnum = '';
+method.Mdeft_ExcPulse = '';
+method.Mdeft_InvPulseEnum = '';
+method.Mdeft_InvPulse = '';
+method.Mdeft_PrepDeriveGainMode = '';
+method.Mdeft_PrepSpoilTime = [];
+method.Mdeft_PrepMinSpoilTime = [];
+method.Mdeft_PrepSpoilGrad = [];
+method.Mdeft_PrepModuleTime = [];
+method.PVM_ppgMode1 = [];
+method.PVM_ppgFreqList1Size = [];
+method.PVM_ppgFreqList1 = [];
+method.PVM_ppgGradAmp1 = [];
+
+% for RARE
+method.EffectiveTE = [];
+method.PVM_RareFactor = [];
+method.PVM_SliceBandWidthScale = [];
+method.PVM_ReadDephaseTime = [];
+method.PVM_2dPhaseGradientTime = [];
+method.PVM_EvolutionOnOff = '';
+method.PVM_SelIrOnOff = '';
+method.PVM_FatSupprPulseEnum = '';
+method.PVM_FatSupprPulse = '';
+method.PVM_FatSupDeriveGainMode = '';
+method.PVM_FatSupBandWidth = [];
+method.PVM_FatSupSpoilTime = [];
+method.PVM_FatSupSpoilGrad = [];
+method.PVM_FatSupModuleTime = [];
+method.PVM_FatSupFL = [];
+method.PVM_FsD0 = [];
+method.PVM_FsD1 = [];
+method.PVM_FsD2 = [];
+method.PVM_FsP0 = [];
+method.PVM_InFlowSatOnOff = '';
+method.PVM_InFlowSatNSlices = [];
+method.PVM_InFlowSatThick = [];
+method.PVM_InFlowSatGap = [];
+method.PVM_InFlowSatSide = [];
+method.PVM_FlowSatPulse = '';
+method.PVM_FlowSatDeriveGainMode= '';
+method.PVM_InFlowSatSpoilTime = [];
+method.PVM_InFlowSatSpoilGrad = [];
+method.PVM_InFlowSatModuleTime = [];
+method.PVM_SfD0 = [];
+method.PVM_SfD1 = [];
+method.PVM_SfD2 = [];
+method.PVM_SfP0 = [];
+method.PVM_SfLp0 = [];
+method.PVM_MotionSupOnOff = '';
+method.PVM_FlipBackOnOff = '';
+
+% for FLASH
+method.PVM_MotionSupOnOff = '';
+method.EchoTimeMode = '';
+method.ReadSpoilerDuration = [];
+method.ReadSpoilerStrength = [];
+method.PVM_MovieOnOff = '';
+method.PVM_NMovieFrames = [];
+method.TimeForMovieFrames = [];
+method.PVM_BlBloodOnOff = '';
+method.PVM_ppgFlag1 = '';
+
+% new parameters
+method.RECO_wordtype = '';
+method.RECO_map_mode = '';
+method.RECO_map_percentile = [];
+method.RECO_map_error = [];
+method.RECO_map_range = [];
+
+
+
+% GET "method" VALUES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+for N = 1:length(texts),
+ if strncmpi(texts{N},'##$',3),
+ % get the parameter name
+ idx = strfind(texts{N},'=');
+ tmpname = texts{N}(4:idx-1);
+ % get the value(s)
+ if isempty(strfind(texts{N},'=(')),
+ tmpval = texts{N}(idx+1:end);
+ tmpdim = [];
+ else
+ s1 = strfind(texts{N},'(');
+ s2 = strfind(texts{N},')');
+ if isempty(s2),
+ tmpdim = [];
+ tmpval = texts{N}(s1:end);
+ else
+ % get dimension
+ tmpdim = str2num(texts{N}(s1+1:s2-1));
+ tmpval = '';
+ end
+ K = N;
+ while ~strncmpi(texts{K+1},'##',2),
+ K = K + 1;
+ end
+ % USE sprintf() since strcat remove blank...
+ if isempty(tmpdim),
+ tmpval = sprintf('%s',tmpval,texts{N+1:K});
+ else
+ tmpval = sprintf('%s ',tmpval,texts{N+1:K});
+ end
+ %tmpval = strcat(texts{N+1:K});
+ N = K + 1;
+ end
+
+ % WHY?? THIS HAPPENS
+ idx = strfind(tmpval,'$$');
+ if ~isempty(idx), tmpval = tmpval(1:idx-1); end
+
+ % set the value(s)
+ tmpval = strtrim(tmpval);
+ if isfield(method,tmpname),
+ if ischar(method.(tmpname)),
+ if any(tmpdim) && tmpval(1) ~= '<',
+ method.(tmpname) = subStr2CellStr(tmpval,tmpdim);
+ else
+ method.(tmpname) = tmpval;
+ end
+ elseif isnumeric(method.(tmpname)),
+ method.(tmpname) = str2num(tmpval);
+ if length(tmpdim) > 1 & prod(tmpdim) == numel(method.(tmpname)),
+ method.(tmpname) = reshape(method.(tmpname),fliplr(tmpdim));
+ method.(tmpname) = permute(method.(tmpname),length(tmpdim):-1:1);
+ end
+ else
+ method.(tmpname) = tmpval;
+ end
+ else
+ method.(tmpname) = tmpval;
+ end
+ end
+end
+
+% after care of some parameters....
+%method.xxxx = subStr2CellStr(method.xxxx);
+
+
+% remove empty members
+fields = fieldnames(method);
+IDX = zeros(1,length(fields));
+for N = 1:length(fields), IDX(N) = isempty(method.(fields{N})); end
+method = rmfield(method,fields(find(IDX)));
+
+
+
+
+% SET OUTPUTS, IF REQUIRED %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+if nargout,
+ varargout{1} = method;
+ if nargout > 1,
+ varargout{2} = texts;
+ end
+end
+
+return;
+
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% SUBFUNCITON to make a cell string from a 'space' or '()' separeted string
+function val = subStr2CellStr(str,dim)
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+if isempty(str) || iscell(str),
+ val = str;
+ return;
+end
+
+if nargin < 2, dim = []; end
+
+val = {};
+
+if str(1) == '(',
+ idx1 = strfind(str,'(');
+ idx2 = strfind(str,')');
+ for N = 1:length(idx1),
+ val{N} = strtrim(str(idx1(N)+1:idx2(N)-1));
+ end
+else
+ % 'space' separated
+ [token, rem] = strtok(str,' ');
+ while ~isempty(token),
+ val{end+1} = token;
+ [token, rem] = strtok(rem,' ');
+ end
+end
+
+if length(dim) > 1 && prod(dim) > 0,
+ val = reshape(val,dim);
+end
+
+return;
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% SUBFUNCITON to make a cell matrix from a '()' separeted string
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+function val = subStr2CellNum(str)
+if isempty(str),
+ val = str;
+ return;
+end
+
+idx1 = strfind(str,'(');
+idx2 = strfind(str,')');
+
+val = {};
+for N = 1:length(idx1),
+ val{N} = str2num(str(idx1(N)+1:idx2(N)-1));
+end
+
+return;
diff --git a/mpi_code/pvread/pvread_reco.m b/mpi_code/pvread/pvread_reco.m
new file mode 100644
index 0000000..3632678
--- /dev/null
+++ b/mpi_code/pvread/pvread_reco.m
@@ -0,0 +1,311 @@
+function varargout = pvread_reco(varargin)
+%PVREAD_RECO - Read PraVision "reco".
+% RECO = PVREAD_RECO(RECOFILE,...)
+% RECO = PVREAD_RECO(2DSEQFILE,...)
+% RECO = PVREAD_RECO(SESSION,EXPNO,...) reads ParaVision's "reco" and returns
+% its contents as a structre, RECO.
+% Unknown parameter will be returned as a string.
+%
+% Supported options are
+% 'verbose' : 0|1, verbose or not.
+%
+% VERSION :
+% 0.90 13.06.05 YM pre-release
+% 0.91 27.02.07 YM supports also 2dseq as the first argument
+% 0.92 26.03.08 YM returns empty data if file not found.
+% 0.93 18.09.08 YM supports both new csession and old getses.
+% 0.94 15.01.09 YM supports some new parameters.
+%
+% See also pv_imgpar pvread_2dseq pvread_acqp pvread_imnd pvread_method pvread_visu_pars
+
+if nargin == 0, help pvread_reco; return; end
+
+
+if ischar(varargin{1}) & ~isempty(strfind(varargin{1},'reco')),
+ % Called like pvread_reco(RECOFILE)
+ RECOFILE = varargin{1};
+ ivar = 2;
+elseif ischar(varargin{1}) & ~isempty(strfind(varargin{1},'2dseq')),
+ % Called like pvread_reco(2DSEQFILE)
+ RECOFILE = fullfile(fileparts(varargin{1}),'reco');
+ ivar = 2;
+else
+ % Called like pvread_reco(SESSION,ExpNo)
+ if exist('csession','class'),
+ ses = csession(varargin{1});
+ RECOFILE = ses.filename(varargin{2},'reco');
+ else
+ ses = goto(varargin{1});
+ RECOFILE = catfilename(ses,varargin{2},'reco');
+ end
+ ivar = 3;
+end
+
+
+% SET OPTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+VERBOSE = 1;
+for N = ivar:2:nargin,
+ switch lower(varargin{N}),
+ case {'verbose'}
+ VERBOSE = varargin{N+1};
+ end
+end
+
+
+if ~exist(RECOFILE,'file'),
+ if VERBOSE,
+ fprintf(' ERROR %s: ''%s'' not found.\n',mfilename,RECOFILE);
+ end
+ % SET OUTPUTS, IF REQUIRED %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ if nargout,
+ varargout{1} = [];
+ if nargout > 1, varargout{2} = {}; end
+ end
+ return;
+end
+
+
+% READ TEXT LINES OF "RECO" %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+texts = {};
+fid = fopen(RECOFILE,'rt');
+while ~feof(fid),
+ texts{end+1} = fgetl(fid);
+ %texts{end+1} = fgets(fid);
+end
+fclose(fid);
+
+
+
+% MAKE "reco" structure %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+reco.filename = RECOFILE;
+
+reco.RECO_mode = '';
+reco.RECO_inp_order = '';
+reco.RECO_inp_size = [];
+reco.RECO_ft_size = [];
+reco.RECO_fov = [];
+reco.RECO_size = [];
+reco.RECO_offset = [];
+reco.RECO_regrid_mode = '';
+reco.RECO_regrid_offset = [];
+reco.RECO_ramp_gap = [];
+reco.RECO_ramp_time = [];
+reco.RECO_ne_mode = '';
+reco.RECO_ne_dist = '';
+reco.RECO_ne_dens = '';
+reco.RECO_ne_type = '';
+reco.RECO_ne_vals = [];
+reco.RECO_bc_mode = '';
+reco.RECO_bc_start = [];
+reco.RECO_bc_len = [];
+reco.RECO_dc_offset = [];
+reco.RECO_dc_divisor = [];
+reco.RECO_bc_coroff = [];
+reco.RECO_qopts = '';
+reco.RECO_wdw_mode = '';
+reco.RECO_lb = [];
+reco.RECO_sw = [];
+reco.RECO_gb = [];
+reco.RECO_sbs = [];
+reco.RECO_tm1 = [];
+reco.RECO_tm2 = [];
+reco.RECO_ft_mode = '';
+reco.RECO_pc_mode = '';
+reco.RECO_pc_lin = {};
+reco.RECO_rotate = [];
+reco.RECO_ppc_mode = '';
+reco.RECO_ref_image = [];
+reco.RECO_nr_supports = [];
+reco.RECO_sig_threshold = [];
+reco.RECO_ppc_degree = [];
+reco.RECO_ppc_coeffs = [];
+reco.RECO_dc_elim = '';
+reco.RECO_transposition = [];
+reco.RECO_image_type = '';
+reco.RECO_image_threshold = [];
+reco.RECO_ir_scale = [];
+reco.RECO_wordtype = '';
+reco.RECO_map_mode = '';
+reco.RECO_map_range = [];
+reco.RECO_map_percentile = [];
+reco.RECO_map_error = [];
+reco.RECO_globex = [];
+reco.RECO_minima = [];
+reco.RECO_maxima = [];
+reco.RECO_map_min = [];
+reco.RECO_map_max = [];
+reco.RECO_map_offset = [];
+reco.RECO_map_slope = [];
+reco.RECO_byte_order = '';
+reco.RECO_time = '';
+reco.RECO_abs_time = [];
+reco.RECO_base_image_uid = '';
+reco.GS_reco_display = '';
+reco.GS_image_type = '';
+reco.GO_reco_display = '';
+reco.GO_reco_each_nr = '';
+reco.GO_max_reco_mem = [];
+
+% new parameters
+reco.RecoUserUpdate = '';
+reco.RecoNumInputChan = [];
+reco.RecoScaleChan = [];
+reco.RecoCombineMode = '';
+reco.RecoSortDim = [];
+reco.RecoSortSize = [];
+reco.RecoSortRange = [];
+reco.RecoSortSegment = [];
+reco.RecoSortMaps = [];
+reco.RecoGrappaAccelFactor = [];
+reco.RecoGrappaKernelRead = [];
+reco.RecoGrappaKernelPhase = [];
+reco.RecoGrappaNumRefRead = [];
+reco.RecoGrappaNumRefPhase = [];
+reco.RecoGrappaIncludeRefLines = '';
+reco.RecoGrappaReadCenter = [];
+reco.RecoGrappaPhaseCenter = [];
+reco.RecoGrappaTruncThresh = [];
+
+
+
+
+% GET "reco" VALUES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+for N = 1:length(texts),
+ if strncmpi(texts{N},'##$',3),
+ % get the parameter name
+ idx = strfind(texts{N},'=');
+ tmpname = texts{N}(4:idx-1);
+ % get the value(s)
+ if isempty(strfind(texts{N},'=(')),
+ tmpval = texts{N}(idx+1:end);
+ tmpdim = [];
+ else
+ s1 = strfind(texts{N},'(');
+ s2 = strfind(texts{N},')');
+ if isempty(s2),
+ tmpdim = [];
+ tmpval = texts{N}(s1:end);
+ else
+ % get dimension
+ tmpdim = str2num(texts{N}(s1+1:s2-1));
+ tmpval = '';
+ end
+ K = N;
+ while ~strncmpi(texts{K+1},'##',2),
+ K = K + 1;
+ end
+ % USE sprintf() since strcat remove blank...
+ if isempty(tmpdim),
+ tmpval = sprintf('%s',tmpval,texts{N+1:K});
+ else
+ tmpval = sprintf('%s ',tmpval,texts{N+1:K});
+ end
+ %tmpval = strcat(texts{N+1:K});
+ N = K + 1;
+ end
+
+ % WHY?? THIS HAPPENS
+ idx = strfind(tmpval,'$$');
+ if ~isempty(idx), tmpval = tmpval(1:idx-1); end
+
+ % set the value(s)
+ tmpval = strtrim(tmpval);
+ if isfield(reco,tmpname),
+ if ischar(reco.(tmpname)),
+ if any(tmpdim) && tmpval(1) ~= '<',
+ reco.(tmpname) = subStr2CellStr(tmpval,tmpdim);
+ else
+ reco.(tmpname) = tmpval;
+ end
+ elseif isnumeric(reco.(tmpname)),
+ reco.(tmpname) = str2num(tmpval);
+ if length(tmpdim) > 1 & prod(tmpdim) == numel(reco.(tmpname)),
+ reco.(tmpname) = reshape(reco.(tmpname),fliplr(tmpdim));
+ reco.(tmpname) = permute(reco.(tmpname),length(tmpdim):-1:1);
+ end
+ else
+ reco.(tmpname) = tmpval;
+ end
+ else
+ reco.(tmpname) = tmpval;
+ end
+ end
+end
+
+% after care of some parameters....
+reco.RECO_pc_lin = subStr2CellNum(reco.RECO_pc_lin);
+
+% remove empty members
+fields = fieldnames(reco);
+IDX = zeros(1,length(fields));
+for N = 1:length(fields), IDX(N) = isempty(reco.(fields{N})); end
+reco = rmfield(reco,fields(find(IDX)));
+
+
+% SET OUTPUTS, IF REQUIRED %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+if nargout,
+ varargout{1} = reco;
+ if nargout > 1,
+ varargout{2} = texts;
+ end
+end
+
+return;
+
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% SUBFUNCITON to make a cell string from a 'space' or '()' separeted string
+function val = subStr2CellStr(str,dim)
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+if isempty(str) || iscell(str),
+ val = str;
+ return;
+end
+
+if nargin < 2, dim = []; end
+
+val = {};
+
+if str(1) == '(',
+ idx1 = strfind(str,'(');
+ idx2 = strfind(str,')');
+ for N = 1:length(idx1),
+ val{N} = strtrim(str(idx1(N)+1:idx2(N)-1));
+ end
+else
+ % 'space' separated
+ [token, rem] = strtok(str,' ');
+ while ~isempty(token),
+ val{end+1} = token;
+ [token, rem] = strtok(rem,' ');
+ end
+end
+
+if length(dim) > 1 && prod(dim) > 0,
+ val = reshape(val,dim);
+end
+
+return;
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% SUBFUNCITON to make a cell matrix from a '()' separeted string
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+function val = subStr2CellNum(str)
+if isempty(str),
+ val = str;
+ return;
+end
+
+idx1 = strfind(str,'(');
+idx2 = strfind(str,')');
+
+val = {};
+for N = 1:length(idx1),
+ val{N} = str2num(str(idx1(N)+1:idx2(N)-1));
+end
+
+return;
diff --git a/mpi_code/pvread/pvread_visu_pars.m b/mpi_code/pvread/pvread_visu_pars.m
new file mode 100644
index 0000000..6b0c9a3
--- /dev/null
+++ b/mpi_code/pvread/pvread_visu_pars.m
@@ -0,0 +1,290 @@
+function varargout = pvread_visu_pars(varargin)
+%PVREAD_VISU_PARS - Read ParaVision "visu_pars".
+% VISUPARS = PVREAD_VISU_PARS(VISUPARSFILE,...)
+% VISUPARS = PVREAD_VISU_PARS(2DSEQFILE,...)
+% VISUPARS = PVREAD_VISU_PARS(SESSION,EXPNO,...) reads ParaVision's "visu_pars" and
+% returns its contents as a structre, VISUPARS.
+% Unknown parameter will be returned as a string.
+%
+% Supported options are
+% 'verbose' : 0|1, verbose or not.
+%
+% VERSION :
+% 0.90 16.04.08 YM pre-release, checked epi/mdeft/rare/flash of 7T.
+% 0.91 18.09.08 YM supports both new csession and old getses.
+%
+% See also pv_imgpar pvread_2dseq pvread_acqp pvread_imnd pvread_method pvread_reco
+
+if nargin == 0, help pvread_visu_pars; return; end
+
+
+if ischar(varargin{1}) & ~isempty(strfind(varargin{1},'visu_pars')),
+ % Called like pvread_visu_pars(VISUFILE)
+ VISUFILE = varargin{1};
+ ivar = 2;
+elseif ischar(varargin{1}) & ~isempty(strfind(varargin{1},'2dseq')),
+ % Called like pvread_visu_pars(2DSEQFILE)
+ VISUFILE = fullfile(fileparts(varargin{1}),'visu_pars');
+ ivar = 2;
+else
+ % Called like pvread_visu_pars(SESSION,ExpNo)
+ if nargin < 2,
+ error(' ERROR %s: missing 2nd arg. as ExpNo.\n',mfilename);
+ return;
+ end
+ if exist('csession','class'),
+ ses = csession(varargin{1});
+ VISUFILE = ses.filename(varargin{2},'visu_pars');
+ else
+ ses = goto(varargin{1});
+ VISUFILE = catfilename(ses,varargin{2},'visu_pars');
+ end
+ ivar = 3;
+end
+
+
+% SET OPTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+VERBOSE = 1;
+for N = ivar:2:nargin,
+ switch lower(varargin{N}),
+ case {'verbose'}
+ VERBOSE = varargin{N+1};
+ end
+end
+
+
+if ~exist(VISUFILE,'file'),
+ if VERBOSE,
+ fprintf(' ERROR %s: ''%s'' not found.\n',mfilename,VISUFILE);
+ end
+ % SET OUTPUTS, IF REQUIRED %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ if nargout,
+ varargout{1} = [];
+ if nargout > 1, varargout{2} = {}; end
+ end
+ return;
+end
+
+
+% READ TEXT LINES OF "VISU_PARS" %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+texts = {};
+fid = fopen(VISUFILE,'rt');
+while ~feof(fid),
+ texts{end+1} = fgetl(fid);
+ %texts{end+1} = fgets(fid);
+end
+fclose(fid);
+
+
+
+% MAKE "visu" structure %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+visu.filename = VISUFILE;
+
+visu.VisuVersion = [];
+visu.isuUid = '';
+visu.VisuCreator = '';
+visu.VisuCreatorVersion = '';
+visu.VisuCreationDate = '';
+visu.VisuCoreFrameCount = [];
+visu.VisuCoreDim = [];
+visu.VisuCoreSize = [];
+visu.VisuCoreDimDesc = '';
+visu.VisuCoreExtent = [];
+visu.VisuCoreFrameThickness = [];
+visu.VisuCoreUnits = '';
+visu.VisuCoreOrientation = [];
+visu.VisuCorePosition = [];
+visu.VisuCoreDataMin = [];
+visu.VisuCoreDataMax = [];
+visu.VisuCoreDataOffs = [];
+visu.VisuCoreDataSlope = [];
+visu.VisuCoreFrameType = '';
+visu.VisuCoreWordType = '';
+visu.VisuCoreByteOrder = '';
+visu.VisuFGOrderDescDim = [];
+visu.VisuFGOrderDesc = '';
+visu.VisuGroupDepVals = '';
+visu.VisuSubjectName = '';
+visu.VisuSubjectId = '';
+visu.VisuSubjectBirthDate = '';
+visu.VisuSubjectSex = '';
+visu.VisuSubjectComment = '';
+visu.VisuStudyUid = '';
+visu.VisuStudyDate = '';
+visu.VisuStudyId = '';
+visu.VisuStudyNumber = [];
+visu.VisuSubjectWeight = [];
+visu.VisuStudyReferringPhysician = '';
+visu.VisuStudyDescription = '';
+visu.VisuSeriesNumber = [];
+visu.VisuSubjectPosition = '';
+visu.VisuSeriesTypeId = '';
+visu.VisuAcqSoftwareVersion = [];
+visu.VisuInstitution = '';
+visu.VisuStation = '';
+visu.VisuAcqDate = '';
+visu.VisuAcqEchoTrainLength = [];
+visu.VisuAcqSequenceName = '';
+visu.VisuAcqNumberOfAverages = [];
+visu.VisuAcqImagingFrequency = [];
+visu.VisuAcqImagedNucleus = '';
+visu.VisuAcqRepetitionTime = [];
+visu.VisuAcqPhaseEncSteps = [];
+visu.VisuAcqPixelBandwidth = [];
+visu.VisuAcqFlipAngle = [];
+visu.VisuAcqSize = [];
+visu.VisuAcqImageSizeAccellerated = '';
+visu.VisuAcqImagePhaseEncDir = '';
+visu.VisuAcqEchoTime = [];
+visu.VisuAcquisitionProtocol = '';
+visu.VisuAcqScanTime = [];
+
+% for MDEFT
+visu.VisuCoreDiskSliceOrder = '';
+visu.VisuAcqInversionTime = [];
+
+
+
+
+% GET "visu_pars" VALUES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+for N = 1:length(texts),
+ if strncmpi(texts{N},'##$',3),
+ % get the parameter name
+ idx = strfind(texts{N},'=');
+ tmpname = texts{N}(4:idx-1);
+ % get the value(s)
+ if isempty(strfind(texts{N},'=(')),
+ tmpval = texts{N}(idx+1:end);
+ tmpdim = [];
+ else
+ s1 = strfind(texts{N},'(');
+ s2 = strfind(texts{N},')');
+ if isempty(s2),
+ tmpdim = [];
+ tmpval = texts{N}(s1:end);
+ else
+ % get dimension
+ tmpdim = str2num(texts{N}(s1+1:s2-1));
+ tmpval = '';
+ end
+ K = N;
+ while ~strncmpi(texts{K+1},'##',2),
+ K = K + 1;
+ end
+ % USE sprintf() since strcat remove blank...
+ if isempty(tmpdim),
+ tmpval = sprintf('%s',tmpval,texts{N+1:K});
+ else
+ tmpval = sprintf('%s ',tmpval,texts{N+1:K});
+ end
+ %tmpval = strcat(texts{N+1:K});
+ N = K + 1;
+ end
+
+ % WHY?? THIS HAPPENS
+ idx = strfind(tmpval,'$$');
+ if ~isempty(idx), tmpval = tmpval(1:idx-1); end
+
+ % set the value(s)
+ tmpval = strtrim(tmpval);
+ if isfield(visu,tmpname),
+ if ischar(visu.(tmpname)),
+ if any(tmpdim) && tmpval(1) ~= '<',
+ visu.(tmpname) = subStr2CellStr(tmpval,tmpdim);
+ else
+ visu.(tmpname) = tmpval;
+ end
+ elseif isnumeric(visu.(tmpname)),
+ visu.(tmpname) = str2num(tmpval);
+ if length(tmpdim) > 1 & prod(tmpdim) == numel(visu.(tmpname)),
+ visu.(tmpname) = reshape(visu.(tmpname),fliplr(tmpdim));
+ visu.(tmpname) = permute(visu.(tmpname),length(tmpdim):-1:1);
+ end
+ else
+ visu.(tmpname) = tmpval;
+ end
+ else
+ visu.(tmpname) = tmpval;
+ end
+ end
+end
+
+% after care of some parameters....
+%visu.xxxx = subStr2CellNum(visu.xxxx);
+
+% remove empty members
+fields = fieldnames(visu);
+IDX = zeros(1,length(fields));
+for N = 1:length(fields), IDX(N) = isempty(visu.(fields{N})); end
+visu = rmfield(visu,fields(find(IDX)));
+
+
+
+
+% SET OUTPUTS, IF REQUIRED %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+if nargout,
+ varargout{1} = visu;
+ if nargout > 1,
+ varargout{2} = texts;
+ end
+end
+
+return;
+
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% SUBFUNCITON to make a cell string from a 'space' or '()' separeted string
+function val = subStr2CellStr(str,dim)
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+if isempty(str) || iscell(str),
+ val = str;
+ return;
+end
+
+if nargin < 2, dim = []; end
+
+val = {};
+
+if str(1) == '(',
+ idx1 = strfind(str,'(');
+ idx2 = strfind(str,')');
+ for N = 1:length(idx1),
+ val{N} = strtrim(str(idx1(N)+1:idx2(N)-1));
+ end
+else
+ % 'space' separated
+ [token, rem] = strtok(str,' ');
+ while ~isempty(token),
+ val{end+1} = token;
+ [token, rem] = strtok(rem,' ');
+ end
+end
+
+if length(dim) > 1 && prod(dim) > 0,
+ val = reshape(val,dim);
+end
+
+return;
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% SUBFUNCITON to make a cell matrix from a '()' separeted string
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+function val = subStr2CellNum(str)
+if isempty(str),
+ val = str;
+ return;
+end
+
+idx1 = strfind(str,'(');
+idx2 = strfind(str,')');
+
+val = {};
+for N = 1:length(idx1),
+ val{N} = str2num(str(idx1(N)+1:idx2(N)-1));
+end
+
+return;
diff --git a/mpi_code/readme.txt b/mpi_code/readme.txt
new file mode 100644
index 0000000..906a62b
--- /dev/null
+++ b/mpi_code/readme.txt
@@ -0,0 +1,10 @@
+put the folder mex_anz in your matlab path and use:
+
+bru2analyze to convert the raw data (bruker 2dseq) to analyze
+
+see help function of bru2analyze on how to use it.
+
+the 2dseq files are in the: session_directory/scan number/pdata/n
+
+where n usually equals 1 and represents the reconstruction number
+rarely there will be a second reconstruction with different parameters
\ No newline at end of file
diff --git a/nhpMpiBrukerBuildAnalyze.m b/nhpMpiBrukerBuildAnalyze.m
new file mode 100644
index 0000000..371b138
--- /dev/null
+++ b/nhpMpiBrukerBuildAnalyze.m
@@ -0,0 +1,35 @@
+function savedir = nhpMpiBrukerBuildAnalyze(scans,baseDir,saveDir)
+%
+% Reconstruct one Bruker/MPI scan at the time. Saves an analyze file.
+% This is a wrapper around the MPI bru2analyze.m
+%
+% INPUTS:
+% scans - A vector of scan indexes (1:n). These indexes refer to the
+% folders under baseDir/nhpDir.
+% baseDir - This is the base directory where all the MPI data set reside,
+% currently /azure/scr1/frk/nhp/
+% saveDir - This is the folder where the analyze files will be saved.
+%
+% OUTPUTS
+% savedir - Full-path to analyze file.
+%
+% Franco (c) Stanford Vista Team 2012
+
+
+% Loop over the scans for the current subject and save out an analyze file.
+for fi = length(scans) % Scan types
+ twodseqFile = fullfile(baseDir,sprintf('%i',scans(fi)),'/pdata/1/2dseq');
+
+ % Preprocess the Bruker scan only if it exists.
+ if exist(twodseqFile,'file')
+ % make a directory to save the ANALYZE file
+ savedir = fullfile(baseDir,saveDir,sprintf('scan00%i',scans(fi)));
+ if ~isdir(savedir), mkdir(savedir); end
+
+ fprintf('\n[%s] Saving analyze files: /*.hdr & *.img\n%s\n',mfilename, savedir);
+ bru2analyze(twodseqFile, 'SaveDir',savedir);
+ end
+end
+
+if nargout < 1, clear savedir;end
+end
\ No newline at end of file
diff --git a/nhpMpiBrukerBuildDiffusionGradients.m b/nhpMpiBrukerBuildDiffusionGradients.m
new file mode 100644
index 0000000..13f8f33
--- /dev/null
+++ b/nhpMpiBrukerBuildDiffusionGradients.m
@@ -0,0 +1,117 @@
+function [bvecs,bvals,dw] = nhpMpiBrukerBuildDiffusionGradients(method_fname)
+%
+% Read the 'method' file from a the MPI Bruker scanner and build diffusion
+% gradients informatation (bvecs and bvals).
+%
+% [bvecs,bvals,dw] = nhpMpiBrukerBuildDiffusionGradients(method_fname)
+%
+% INPUTS:
+% method_fname - the full path to a bruker 'method' file.
+%
+% OUTPUTS:
+% bvecs - 3xnBvecs vecotr containing the bvecs as expected by mrDiffusion.
+%
+% bvals - 1xNbvecs vector of bvals, as epxceted by mrDiffusion
+%
+% dw - a structure containing all the information rearding gradient
+% direction and bvals.
+%
+% See: http://filer.case.edu/vxs33/pvman/A/Docs/A06_MethDescr.pdf
+% http://filer.case.edu/vxs33/pvman/D/Docs/A13_MethProg.pdf
+%
+% Notes:
+% In an email Georgios A. Keliris he gave us the following
+% information regaridng the MPI-Bruker scan sequences:
+% - z (3rd dimension) in the image refers to the main filed (b0)
+% - The NHP head is positioned as follows:
+% z=H-F | x=A-P | y=R-L
+% - Gradeitns are most certainly stored as consecutie triplets:
+% [[x1,y,1z1],[x2,y2,z2],...,[xn,yn,zn]]
+% - Grdients are always normalized (PVM_DwDirectScale='yes')
+% - B0 and diffusion data are stored in the files as follows:
+% GAK: Based on the image (2dseg file). First volume respectively frame
+% 1 to Slices is B0 and Slices+1 to 2xSlices is the diffusion image.
+% Example: Study: M00.yO1, Scan 20, frame 1 to 48 is B0 and frame 49
+% to 96 is diffusion image.
+%
+% Franco (c) Stanford Vista Team 2012
+
+dw.bvals = [];dw.bvecs = [];
+
+% Read the method file
+mth = pvread_method(method_fname);
+
+% Check that this was a Diffusion scan:
+if ~strcmpi(mth.Method,'DtiEpi')
+ error('[%s] This scan does not seem to be a DW scan.\n[PVM_DwMeasMode: %s].',mafilename,mth.PVM_DwMeasMode);
+end
+
+% Check whether the diffusion directions vectors are normalized to norm = 1.0
+if ~strcmpi(mth.PVM_DwDirectScale,'no')
+ warning('[%s] The diffusion directions were not set to be normalized to 1.\nThe resulting bvecs might be wrong.',mafilename);
+end
+
+% Number of average DW measurements
+dw.nAverages = mth.PVM_DwNDiffExpEach;
+
+% Get the number of diffusion directions acquired.
+dw.nBvecs = str2double( mth.PVM_DwNDiffDir );
+
+% Get the number of bvals acquired:
+dw.nBvals = str2double( mth.PVM_DwAoImages );
+
+% Get the bvalue sued for this scan
+dw.bval = str2double( mth.PVM_DwBvalEach );
+
+% No bulld the bvals
+dw.bvals =repmat(dw.bval,dw.nBvals,3);
+
+% The indices of the b0 measuements in the DWI data file can be figured out
+% from the list of phases of the gradients. THe b0 measurements have
+% 0-phase (I think).
+dw.indicesb0 = find(str2num(mth.PVM_DwGradPhase) == 0);
+dw.indices = find(str2num(mth.PVM_DwGradPhase));
+
+% The diffusion directions on a DW sequence on a bruker scanner are stroed
+% in the struct variable: 'PVM_DwDir'
+dw.bvecs = str2num(mth.PVM_DwDir);
+dw.bvecs = reshape(dw.bvecs,3,dw.nBvecs)';
+
+% Check that the vectors are unit length.
+% If we organized the vectors corretly the dot product of the vector in the
+% rows of bvecs with itself should be 1.
+% This is valid onlyin the case in which 'PVM_DwDirectScale='no'. See
+% above.
+if ~all(round(dot(dw.bvecs,dw.bvecs,2)) == 1), keyboard; end
+
+% Concatenate the bvecs and set the gradients for the bvals to zero
+bvecs = zeros(3,size(dw.bvecs,1) + size(dw.bvals,1));
+bvecs(:,dw.indices) = dw.bvecs';
+% gradients (bvecs) are aligned in scanner space. Here we use the xform of
+% the nifti to reorient them in image space:
+%
+% xfrom from scanner to image space
+%xform = ni.qto_xyz;
+%
+% X-form the bvecs
+%bvecs2 = xform*bvecs';
+bvecNorm = sqrt(sum(bvecs.^2));
+nz = bvecNorm~=0;
+bvecs(:,nz) = bvecs(:,nz)./repmat(bvecNorm(nz),[3 1]);
+
+bvals = zeros(size(dw.bvecs,1) + size(dw.bvals,1),1);
+if (dw.bval > 10), divideby = 1000;
+else divideby = 1;end
+bvals(dw.indices) = dw.bval/divideby;
+bvals = bvals';
+
+% Save out mrDiffusion bevecs/bvals files
+%
+% Scale the bvalues according to gradient magnitude. This assumes that the
+% specified b-value is the max bvalue. Note that we only do this when all
+% the bvec norms are 1 or less. If any of the bvec norms are >1, then we
+% assume that the bvecs are just encoded sloppily and their norms do not
+% really reflect the gradient amplitudes.
+if( all(bvecNorm<=1) ), bvals = bvals.*bvecNorm.^2; end
+
+return
diff --git a/nhpMpiBuildNiftiFromAnalyze.m b/nhpMpiBuildNiftiFromAnalyze.m
new file mode 100644
index 0000000..09c6d5b
--- /dev/null
+++ b/nhpMpiBuildNiftiFromAnalyze.m
@@ -0,0 +1,52 @@
+function [fname,p, ni] = nhpMpiBuildNiftiFromAnalyze(analyzeFile,nFiles)
+%
+% Build a 3D nifti file from the individual analyze files
+%
+% analyzeFile = fullfile(baseDir,nhpDir,'analyze','scan0040','M00EM1_scan40_00001.img')
+%
+
+% Extract the path informatin from the analyzeFile.
+[p,fname] = fileparts(analyzeFile);
+
+% We rebuild the file name as a string
+fname = fname(1:14);
+
+% Load the first of many files
+% We will use this as a template for the ehader information.
+if exist(analyzeFile,'file')
+ ni = niftiRead(analyzeFile);
+else
+ keyboard
+end
+
+
+% We open on file at the time
+sz3d = size(ni.data);
+ni.data = nan(sz3d(1),sz3d(2),sz3d(3),nFiles);
+c=1;
+for fi = 1:nFiles
+ if fi < 10
+ thisfile = fullfile(p,sprintf('%s0000%i.hdr',fname,fi));
+ else
+ thisfile = fullfile(p,sprintf('%s000%i.hdr',fname,fi));
+ end
+ fprintf('Loading file: %s\n',thisfile)
+ ni_temp = niftiRead(thisfile);
+ % We append the data into the first opened file
+ ni.data(:,:,:,c) = ni_temp.data;
+ c = c +1;
+end
+
+% We update the header information
+% Notice, the headers in the analyze files do not have the corect center.
+% Build that here.
+fname = sprintf('%snA%i.nii.gz',fname,nFiles);
+ni.fname = fname;
+ni.dim = size(ni.data);
+ni.qform_code = 1; % the qto_* fields contain the xForm information
+ni.slice_dim = 3;
+ni.phase_dim = 2;
+ni.freq_dim = 1;
+ni.slice_start=0;
+ni.slice_end =size(ni.data,3)-1;
+end
diff --git a/nhpMpiDwiRootPath.m b/nhpMpiDwiRootPath.m
new file mode 100644
index 0000000..a7a3435
--- /dev/null
+++ b/nhpMpiDwiRootPath.m
@@ -0,0 +1,26 @@
+function rootPath = nhpMpiDwiRootPath(dataDir)
+% Determine path to root of the NHP MPI code set.
+%
+% rootPath = nhpMpiDwiRootPath;
+%
+% INPUTS:
+% dataDir - Logical.
+% - 1, returns the path to the data dir which is:
+% '/biac2/wandell2/data/diffusion/nhp'
+% - 0, returns the path to the code base which lives in
+% vistaproj/mpi_nhp. Default is 0.
+%
+% This function MUST reside in the directory at the base of the nhpMpiDwi
+% directory structure
+%
+% Franco & Hiromasa (c) Stanford Vista Team 2012
+if notDefined('dataDir'), dataDir = 0;end
+
+if ~dataDir % Return path to code set
+rootPath = which('nhpMpiDwiRootPath');
+rootPath = fileparts(rootPath);
+else
+ rootPath = '/biac2/wandell2/data/diffusion/nhp/';
+end
+
+return
diff --git a/nhpMpiSwapDimensions.m b/nhpMpiSwapDimensions.m
new file mode 100644
index 0000000..598ea91
--- /dev/null
+++ b/nhpMpiSwapDimensions.m
@@ -0,0 +1,29 @@
+function ni = nhpMpiSwapDimensions(ni,swapType)
+%
+% Sawp the dimensions of the nifti file created by loading a series of
+% analzuse fiels from the rbuker scanner.
+%
+% ni = nhpMpiSwapDimensions(ni,swapType)
+%
+% This might not be used. Still work in progress.
+%
+% Franco (c) Stanford Vista Team 2012
+
+switch swapType
+ case 'x'
+ case 'y'
+ [ni.data] = applyCannonicalXform(ni.data, img2std, ni.pixdim, insertMarkerFlag);
+ case 'z'
+ ni.data = applyCannonicalXform(ni.data, img2std, ni.pixdim, insertMarkerFlag);
+ case 'xy'
+ ni.data = applyCannonicalXform(ni.data, img2std, ni.pixdim, insertMarkerFlag);
+ case 'xz'
+ ni.data = applyCannonicalXform(ni.data, img2std, ni.pixdim, insertMarkerFlag);
+ case 'yz'
+ ni.data = applyCannonicalXform(ni.data, img2std, ni.pixdim, insertMarkerFlag);
+ case 'xyz'
+ ni.data = applyCannonicalXform(ni.data, img2std, ni.pixdim, insertMarkerFlag);
+ otherwise
+ keyboard
+end
+end
diff --git a/s_vista_2dseqToAnalyze.m b/s_vista_2dseqToAnalyze.m
new file mode 100644
index 0000000..71ba14b
--- /dev/null
+++ b/s_vista_2dseqToAnalyze.m
@@ -0,0 +1,106 @@
+%% Transform Bruker scan format (2dseq) to ANALYZE-7
+%
+% First attempt to debunk the bruker data from the MPI.
+%
+% Notes:
+% - Set the qform_code or sform_code to 1 depending on whether the xform
+% is stored in the qt_xyz/ijk or sto_xyz/ijk
+% - bvecs and bvals should be saved as (3,nDirs) amd (1,nDirs) in dimensions.
+%
+% Franco (c) Stanford Vista Team 2012
+
+% Move to the folder with NHP data
+baseDir = '/azure/scr1/frk/nhp';
+
+% Base folder for each subjct
+nhpDir = 'M00.EM1';% 'M00.yO1';
+analyzeDir = 'analyze';
+niftiDir = 'nifti';
+niftiFolder = fullfile(baseDir,nhpDir,'scan40/raw');
+scanstoload = {'40'};
+
+% Build an analyze file froma Bruker file
+nhpMpiBrukerBuildAnalyze(20,fullfile(baseDir,nhpDir),analyzeDir)
+
+%% function nhpMpiBuildNiftiFromAnalyze(analyzeFiles,saveName)
+% Build a 3D nifti file from the individual analyze files
+cd(fullfile(baseDir,nhpDir,'analyze','scan0040'))
+ni = niftiRead('M00EM1_scan40_00001.img');
+
+% We open on file at the time
+sz3d = size(ni.data);
+ni.data = nan(sz3d(1),sz3d(2),sz3d(3),68*length(scanstoload));
+c=1;
+for is = 1:length(scanstoload)
+ cd(fullfile(baseDir,nhpDir,'analyze',sprintf('scan00%s',scanstoload{is})));
+ for fi = 1:68
+ if fi < 10
+ thisfile = sprintf('M00EM1_scan%s_0000%i.hdr',scanstoload{is},fi);
+ else
+ thisfile = sprintf('M00EM1_scan%s_000%i.hdr',scanstoload{is},fi);
+ end
+ fprintf('Loading file: %s\n',thisfile)
+ ni_temp = niftiRead(thisfile);
+ % We append the data into the first opened file
+ ni.data(:,:,:,c) = ni_temp.data;
+ c = c +1;
+ end
+end
+% We update the header information
+% Notice, the headers in the analyze files do not have the corect center.
+% Build that here.
+ni.fname = 'M00EM1_scan40.nii.gz';
+ni.dim = size(ni.data);
+ni.qform_code = 1; % the qto_* fields contain the xForm information
+ni.slice_dim = 3;
+ni.phase_dim = 2;
+ni.freq_dim = 1;
+ni.slice_start=0;
+ni.slice_end =size(ni.data,3)-1;
+
+% Save the nifti file just created, one folder up
+if ~(exist(niftiFolder,'dir') == 7)
+ mkdir(niftiFolder);
+end
+p = pwd;
+cd(niftiFolder)
+niftiWrite(ni)
+cd(p)
+%% END nhpMpiBuildNiftiFromAnalyze
+
+
+% Build the bvecs
+c=1;
+for is = 1:length(scanstoload)
+% Build the gradients information fromt he Bruker 'method' file
+method_fname = fullfile(baseDir,nhpDir,sprintf('%s/method',scanstoload{is}));
+[bvecs,bvals,dw] = nhpMpiBrukerBuildDiffusionGradients(method_fname);
+
+all_bvecs = horzcat(bvecs);
+all_bvals = horzcat(bvals);
+end
+
+% Write out the bvals and bvecs
+b_fileName = fullfile(niftiFolder, 'M00EM1_scan40');
+dlmwrite([b_fileName '.bvecs'],all_bvecs,' ');
+dlmwrite([b_fileName '.bvals'],all_bvals,' ');
+
+% Reconstruct the T1 anatomical file
+cd(fullfile(baseDir, 'M00.yO1','analyze','scan0024'))
+ni = niftiRead('M00yO1_scan24.hdr');
+ni.fname = [ni.fname(1:end-4),'_t1.nii.gz'];
+ni.qform_code = 1; % the qto_* fields contain the xForm information
+ni.slice_dim = 3;
+ni.phase_dim = 2;
+ni.freq_dim = 1;
+ni.slice_start=0;
+ni.slice_end =size(ni.data,3)-1;
+
+p = pwd;
+cd(niftiFolder)
+niftiWrite(ni)
+cd(p)
+
+%% Preprocess the file
+cd(niftiFolder)
+dtiInit('M00EM1_scan40.nii.gz','M00yO1_scan24_t1.nii.gz')
diff --git a/s_vista_test_build_nifti.m b/s_vista_test_build_nifti.m
new file mode 100644
index 0000000..2f1b330
--- /dev/null
+++ b/s_vista_test_build_nifti.m
@@ -0,0 +1,90 @@
+% This script tests how to flip the dimensions of the analyze files before
+% building the nifti file that we use with mr diffusion.
+%
+% Really the only way to test that the nifti file was build the way we want
+% it is to run the process all the way down to dtiInit and tractography.
+%
+% Only by looking at the tracts generated using the tensor fit we can
+% understand whether the nifti were build correctly.
+%
+% Franco (c) Stanford Vista Team 2012
+
+% Move to the folder with NHP data
+baseDir = '/azure/scr1/frk/nhp';
+
+% Base folder for each subjct
+nhpDir = 'M00.yO1';
+analyzeDir = fullfile('analyze','scan0020');
+niftiDir = 'nifti';
+niftiFolder = fullfile(baseDir,nhpDir,'scan20/raw');
+nFiles = 68; % this is the number fo analuze files inside a folder,
+ % each analyze file is one volume acuired of diffusion
+ % weighted or b0-signal
+analyzeName = 'M00yO1_scan20_00001.img';
+
+% We assume that the analyzefiles were created already.
+% To build an analyze file from a Bruker file use:
+% nhpMpiBrukerBuildAnalyze(20,fullfile(baseDir,nhpDir),analyzeDir)
+
+% Now we build the nifti file by loadin a bunch of analyze files.
+analyzeFile = fullfile(baseDir,nhpDir,analyzeDir,analyzeName);
+[dw_name,~,ni] = nhpMpiBuildNiftiFromAnalyze(analyzeFile,nFiles);
+
+% This is the critical step. After we build the nifti file we need to check
+% whether the x,y or z dimension needs to be flipped.
+%
+% If one of the dimensions needs to be flipped the same flipping needs to
+% be applied to the bvecs. See below.
+%
+% First lets try without swapping dimensions.
+
+
+% Save the nifti file just created, one folder up
+if ~(exist(niftiFolder,'dir') == 7)
+ mkdir(niftiFolder);
+end
+p = pwd;
+cd(niftiFolder)
+niftiWrite(ni)
+cd(p)
+
+% Build the bvecs
+% Build the gradients information fromt he Bruker 'method' file
+method_fname = fullfile(baseDir,nhpDir,sprintf('%s/method','20'));
+[bvecs,bvals,dw] = nhpMpiBrukerBuildDiffusionGradients(method_fname);
+
+% Write out the bvals and bvecs
+b_fileName = fullfile(p, dw_name(1:end-7));
+dlmwrite([b_fileName '.bvecs'],bvecs,' ');
+dlmwrite([b_fileName '.bvals'],bvals,' ');
+
+% Reconstruct the T1 anatomical file
+cd(fullfile(baseDir, 'M00.yO1','analyze','scan0024'))
+ni = niftiRead('M00yO1_scan24.hdr');
+ni.fname = [ni.fname(1:end-4),'_t1.nii.gz'];
+ni.qform_code = 1; % the qto_* fields contain the xForm information
+ni.slice_dim = 3;
+ni.phase_dim = 2;
+ni.freq_dim = 1;
+ni.slice_start = 0;
+ni.slice_end = size(ni.data,3)-1;
+
+p = pwd;
+cd(niftiFolder)
+niftiWrite(ni)
+cd(p)
+
+% Align first then save it and do dtiInit/
+% http://white.stanford.edu/newlm/index.php/Anatomical-Processing
+
+% Align the T1 to ACPC and resample to a predetermined Resolution.
+% t1_name = 't1.nii.gz';
+% mrAnatAverageAcpcNifti({'M00yO1_scan24_t1.nii.gz'},t1_name,[],ni.pixdim(1:3))
+
+%% Preprocess the file
+cd(niftiFolder)
+dwParams = dtiInitParams('clobber',1,...
+ 'phaseEncodeDir',2, ...
+ 'dwOutMm',[1 1 1], ...
+ 'numBootStrapSamples',2);
+dtiInit(dw_name,t1_name,dwParams)