function [err,Info, opt] = New_HEAD (opt) % % [err,Info, Opt] = New_HEAD (Opt) % %Purpose: % A function for the likes of Greg Detre. % It makes the creation of an AFNI dataset % from a 3 or 4 dimensional matrix in matlab a breeze. % % % %Input Parameters: % opt is an options structure with the following fields: % .prefix: A string containg the AFNI dataset's prefix % .prefix and one of .dimen or .master must % be used. % .dimen: A string or array containing the dimensions of % the dataset (at least 3 dimensions need be present). % The following four options are from 3dUndump. See 3dUndump -help % .view: '+orig' (default) or '+acpc' or '+tlrc' % If you choose +tlrc, the resultant volume % will fit the Talairach box. % .master: Name of an existing AFNI dataset that would % provide the needed matrix size, orientation etc. % Do not mix .master with .dimen % .datum: 'byte', 'short' (default), or 'float' % .orient: Orientation of data in matrix. Default in 'RAI' % % .tr: a float specifying the TR in seconds. % The presence of such a field necessitates a 4 dimensional % .scale: 0/1 This is only meaningful with 'short' data where it % defaults to 1. It defaults to 0 for other types. It is % used when storing float data as shorts to minimize disk % use while preserving numeric percision. % %Output Parameters: % err : 0 No Problem % : 1 Problems % Info: The header structure, given the options specified % Opt: A modified version of the input Opt. It will be passed % along with the data array to WriteBrik for writing the % dataset to disk. (See Examples below) % %Examples: % Run New_HEAD('test') or see Test_New_HEAD.m for examples. % %More Info : % AFNI programs 3drefit and 3dAttribute are your friends % BrikLoad, BrikInfo, WriteBrik % README.attributes % % The function makes heavy use of 3dUndump % %This function requires AFNI binaries postdating Feb. 12 2007 % % % Author : Ziad Saad saadz@mail.nih.gov % Date : Fri Feb 9 16:29:51 EST 2007 % SSCC/NIMH/ National Institutes of Health, Bethesda Maryland %Define the function name for easy referencing FuncName = 'New_HEAD'; %Debug Flag DBG = 1; %initailize return variables err = 1; Info = []; %check on return parameters if (nargout == 2), fprintf(1, 'Notice %s:\nYou are not specifying a return argument for Opt.\n', FuncName); fprintf(1, ' Be aware that some fields in Opt might have been modified inside\n'); fprintf(1, ' %s but these changes are not reflected in the Opt structure you\n', FuncName); fprintf(1, ' will be passing to WriteBrik.\n'); fprintf(1, ' If this makes no sense to you, just use:\n'); fprintf(1, ' [err, Info, Opt] = New_HEAD(Opt);\n'); end %work options if (ischar(opt)), %perhaps test mode Test_New_HEAD; return; end %standardize input if (isfield(opt,'dimen')), if (ischar(opt.dimen)), v = str2num(opt.dimen); rmfield(opt, 'dimen'); opt.dimen = v; end end %create command for -master option or non-tlrc views if (~isfield(opt,'view') | ~strcmp(opt.view,'+tlrc') | isfield(opt,'master')), tmp_suf = '___NeW_hEaD_'; sopt = '3dUndump -head_only'; if (isfield(opt,'dimen')), sopt = sprintf('%s -dimen %s', sopt, num2str(opt.dimen(1:3))); end if (isfield(opt,'orient')), sopt = sprintf('%s -orient %s', sopt, opt.orient); end if (isfield(opt,'master')), [Status, mPrefix, mView] = PrefixStatus (opt.master); sopt = sprintf('%s -master %s', sopt, opt.master); else mView = '+orig'; end if (~isfield(opt,'datum')), opt.datum = 'short'; end if (isfield(opt,'datum')), if (~strcmp(opt.datum,'short') & ~strcmp(opt.datum, 'byte') & ~strcmp(opt.datum,'float')), fprintf(1,'Error %s:\ndatum option must be one of ''byte'', ''short'', ''float''\nI have %s\n', FuncName, opt.datum); return; end sopt = sprintf('%s -datum %s', sopt, opt.datum); end if (~isfield(opt,'view')), opt.view = '+orig'; end if (isfield(opt,'prefix')), [Status, Prefix, View] = PrefixStatus (opt.prefix); if (Status < 1 & strcmp(View,opt.view)), fprintf(1,'Error %s:\nLooks like %s exists already.\n', FuncName, opt.prefix); return; end opt.prefix = Prefix; ohead = sprintf('%s%s', tmp_suf, opt.prefix); sopt = sprintf('%s -prefix %s%s', sopt, ohead); else fprintf(1,'Error %s:\nNeed a .prefix option.\n', FuncName); return; end [e,w] = unix(sopt); if (e), fprintf(1,'Error %s:\nHeader creating command %s failed.\nSee this function''s help and 3dUndump -help\n3dUndump''s output was:\n%s\n', ... FuncName, sopt, w); New_HEAD_CLEAN(tmp_suf); return; end [err,Info] = BrikInfo(sprintf('%s%s', ohead,mView)); New_HEAD_CLEAN(tmp_suf); else %have +tlrc and no master mView = '+tlrc'; [e,d] = unix('which afni'); if (e), fprintf(1,'Error %s:\nFailed to find afni!\n', FuncName); return; end [e,pt] = GetPath(d); templ = sprintf('%s/TT_N27+tlrc.HEAD', pt); [e,Info] = BrikInfo(templ); if (e), fprintf(1,'Error %s:\nFailed to get header of %s!\n', FuncName, templ); return; end %recalculate the origin (res. of template is 1x1x1mm) oOrig = Info.ORIGIN; oDelta = Info.DELTA; oDimen = Info.DATASET_DIMENSIONS; %Calculate dimension ratio and adjust so that volume fits in box. rat = oDimen(1:3)./opt.dimen(1:3); Info.DELTA = Info.DELTA .* rat; Info.DATASET_DIMENSIONS(1:3) = opt.dimen(1:3); %Now shift the origin so that the final volume still fits in the same box (edge to edge) of TLRC box dOrig = 1./2*(Info.DELTA-oDelta); Info.ORIGIN = Info.ORIGIN+dOrig; %Have to deal with datum if (isfield(opt,'datum')), if (strcmp(opt.datum,'byte')), Info.BRICK_TYPES(1) = 0; elseif (strcmp(opt.datum,'short')), Info.BRICK_TYPES(1) = 1; elseif (strcmp(opt.datum,'float')), Info.BRICK_TYPES(1) = 3; else fprintf(1,'Error %s: Bad data type %s\n', FuncName, opt.datum); return; end else opt.datum = 'short' Info.BRICK_TYPES(1) = 1; end end %the scaling option if (isfield(opt,'scale')), if (opt.scale & ~strcmp(opt.datum,'short')), fprintf(1,'Warning %s:\n .scale option is only for ''short'' type data.\n Resetting it to 0.\n', FuncName); opt.scale = 0; end else if (strcmp(opt.datum,'short')), opt.scale = 1; else opt.scale = 0; end end %take care of prefix business Info.RootName = sprintf('%s%s', opt.prefix, opt.view); %take care of view if (strcmp(mView, opt.view) == 0), %different if (strcmp(opt.view,'+orig')) Info.SCENE_DATA(1) = 0; elseif (strcmp(opt.view,'+acpc')) Info.SCENE_DATA(1) = 1; elseif (strcmp(opt.view,'+tlrc')) Info.SCENE_DATA(1) = 2; else fprintf(1,'Error %s:\nBad view %s\n', FuncName, opt.view); return; end end %take care of 4th dimen if (length(opt.dimen) > 3), Info.DATASET_RANK(2) = opt.dimen(4); Info.BRICK_TYPES = Info.BRICK_TYPES(1).*ones(1,opt.dimen(4)); Info.BRICK_FLOAT_FACS = Info.BRICK_FLOAT_FACS(1) .*ones(1, opt.dimen(4)); end %take care of TR if (isfield(opt,'tr')), Info.TAXIS_NUMS(1) = Info.DATASET_RANK(2); Info.TAXIS_NUMS(2) = 0; %no time offset for slices at the moment Info.TAXIS_NUMS(3) = 77002; %units in seconds for tr (below) Info.TAXIS_FLOATS(1) = 0; %time origin 0 Info.TAXIS_FLOATS(2) = opt.tr; %TR in units of Info.TAXIS_NUMS(3) Info.TAXIS_FLOATS(3) = 0; %duration of acquisition Info.TAXIS_FLOATS(4) = 0; %no time offset please Info.TAXIS_FLOATS(5) = 0; %no time offset please Info.TAXIS_OFFSETS = zeros(1,Info.TAXIS_NUMS(1)); %no bloody time offset end err = 0; return; function New_HEAD_CLEAN(sss) unix(sprintf('rm -f %s*.HEAD >& /dev/null', sss)); return;