00001 function [err, ErrMessage, Info] = CheckBrikHEAD (Info)
00002 %
00003 % [err, ErrMessage, InfoOut] = CheckBrikHEAD (Info)
00004 %
00005 %Purpose:
00006 % Checks to determine if the fields in Info are appropriate AFNI style
00007 %
00008 %
00009 %Input Parameters:
00010 % Info is a structure containing all the Header fields,
00011 %
00012 %
00013 %Output Parameters:
00014 % err : 0 No Problem
00015 % : 1 Mucho Problems
00016 % ErrMessage
00017 % Vector Indexing in error messages is done a la matlab.
00018 % so DATASET_RANK(1) in the error message refers to the first value in DATASET_RANK
00019 % which would be DATASET_RANK[0] in AFNI
00020 % InfoOut
00021 % same as Info , but with the empty optional fields trimmed out
00022 %
00023 %Key Terms:
00024 %
00025 %More Info :
00026 % BrikInfo for list of Mandatory fields and AFNI's README.attributes
00027 %
00028 %
00029 %
00030 % Author : Ziad Saad
00031 % Date : Fri Apr 6 09:48:49 PDT 2001
00032 % LBC/NIMH/ National Institutes of Health, Bethesda Maryland
00033
00034
00035 %Define the function name for easy referencing
00036 FuncName = 'CheckBrikHEAD';
00037
00038 %Debug Flag
00039 DBG = 1;
00040
00041 %initailize return variables
00042 err = 1;
00043
00044 ErrMessage = '';
00045
00046 %Mandatory Fields Specs
00047
00048 MandatoryFieldNames = 'DATASET_RANK~DATASET_DIMENSIONS~TYPESTRING~SCENE_DATA~ORIENT_SPECIFIC~ORIGIN~DELTA';
00049 N_Mandatory = WordCount(MandatoryFieldNames, '~');
00050
00051 %check if the mandatory fields are present
00052 for (im = 1:1:N_Mandatory),
00053 %Check that all the Mandatory Fields have been specified.
00054 [err, CurName] = GetWord(MandatoryFieldNames, im, '~');
00055 if(~isfield(Info, CurName)),
00056 err = 1; ErrMessage = sprintf('Error %s: Field %s must be specified for the Header to be proper.', FuncName, CurName);
00057 warndlg(ErrMessage);
00058 return;
00059 end
00060 end
00061
00062 %Now Get all the rules
00063 [err, ErrMessage, Rules] = HEAD_Rules;
00064 if (err), ErrMessage = sprintf('Error %s: Error in HEAD_RULES.\n%s', FuncName, ErrMessage); errordlg(ErrMessage); return; end
00065 N_Rules = length(Rules);
00066
00067 %auto checks and cleanup of empty fields
00068 for (ir = 1:1:N_Rules),
00069 %fprintf(1,'Checking %s ...', Rules(ir).Name);
00070 %Check that all the Remaining Fields are OK.
00071 if (isfield(Info, Rules(ir).Name)),
00072 if (isempty(getfield(Info, Rules(ir).Name))),
00073 %fprintf(1,' Empty .\n');
00074 %remove this field if it is empty, this reduces the clutter of the ascii .HEAD file
00075 Info = rmfield(Info, Rules(ir).Name);
00076 else
00077 %fprintf(1,'Not Empty .\n');
00078 %check for type coherence
00079 if (ischar(getfield(Info, Rules(ir).Name))),
00080 if (Rules(ir).isNum),
00081 err = 1; ErrMessage = sprintf('Error %s: Field %s type (string or numerical) is wrong.', FuncName, Rules(ir).Name);warndlg(ErrMessage);return;
00082 end
00083 else %a number, verify type
00084 if (Rules(ir).isNum == 1 & ~isint(getfield(Info, Rules(ir).Name))),
00085 err = 1; ErrMessage = sprintf('Error %s: Field %s type must be an integer.', FuncName, Rules(ir).Name);
00086 end
00087 end
00088 %check for length specs
00089 if (~isempty(Rules(ir).Length)),
00090 if (length(getfield(Info,Rules(ir).Name)) ~= Rules(ir).Length),
00091 err = 1; ErrMessage = sprintf('Error %s: Field %s length must be %d.', FuncName, Rules(ir).Name, Rules(ir).Length);warndlg(ErrMessage);return;
00092 end
00093 end
00094 %check for minimum length specs
00095 if (~isempty(Rules(ir).minLength)),
00096 if (length(getfield(Info,Rules(ir).Name)) < Rules(ir).minLength),
00097 err = 1; ErrMessage = sprintf('Error %s: Field %s length must be at least %d.', FuncName, Rules(ir), Rules(ir).minLength);warndlg(ErrMessage);return;
00098 end
00099 end
00100 end
00101 end
00102 end
00103
00104
00105
00106 %Further Field specfic checks
00107 %For Mandatory Fields
00108 if (Info.DATASET_RANK(1) ~= 3),
00109 err = 1; ErrMessage = sprintf('Error %s: DATASET_RANK(1) must be 3', FuncName); errordlg(ErrMessage); return;
00110 end
00111 if (length(Info.DATASET_RANK) < 8),
00112 v = zeros(1,8); v(1:length(Info.DATASET_RANK)) = Info.DATASET_RANK;
00113 Info.DATASET_RANK = v;
00114 end
00115 if (min(Info.DATASET_DIMENSIONS(1:3)) < 1),
00116 err = 1; ErrMessage = sprintf('Error %s: All values in DATASET_DIMENSIONS must be >= 1', FuncName); errordlg(ErrMessage); return;
00117 end
00118 if (length(Info.DATASET_DIMENSIONS) < 5),
00119 v = zeros(1,5); v(1:length(Info.DATASET_DIMENSIONS)) = Info.DATASET_DIMENSIONS;
00120 Info.DATASET_DIMENSIONS = v;
00121 end
00122
00123
00124 List = {'3DIM_HEAD_ANAT', '3DIM_HEAD_FUNC', '3DIM_GEN_ANAT', '3DIM_GEN_FUNC'};
00125 s = 0;
00126 for (il = 1:1:length(List)),
00127 s = s + strcmp(Info.TYPESTRING, char(List(il)));
00128 end
00129 if (s ~= 1),
00130 err = 1; ErrMessage = sprintf('Error %s: TYPESTRING must be one of \n3DIM_HEAD_ANAT, 3DIM_HEAD_FUNC, 3DIM_GEN_ANAT or 3DIM_GEN_FUNC', FuncName); errordlg(ErrMessage); return;
00131 end
00132
00133 if (Info.SCENE_DATA(1) < 0 | Info.SCENE_DATA(1) > 2),
00134 err = 1; ErrMessage = sprintf('Error %s: SCENE_DATA(1) must be between 0 and 2', FuncName); errordlg(ErrMessage); return;
00135 end
00136 if (Info.SCENE_DATA(2) < 0 | Info.SCENE_DATA(2) > 11),
00137 err = 1; ErrMessage = sprintf('Error %s: SCENE_DATA(2) must be between 0 and 11', FuncName); errordlg(ErrMessage); return;
00138 end
00139 if (Info.SCENE_DATA(3) < 0 | Info.SCENE_DATA(3) > 3),
00140 err = 1; ErrMessage = sprintf('Error %s: SCENE_DATA(3) must be between 0 and 3', FuncName); errordlg(ErrMessage); return;
00141 end
00142
00143 if (Info.ORIENT_SPECIFIC(1) < 0 | Info.ORIENT_SPECIFIC(1) > 5),
00144 err = 1; ErrMessage = sprintf('Error %s: ORIENT_SPECIFIC(1) must be between 0 and 5', FuncName); errordlg(ErrMessage); return;
00145 end
00146
00147
00148 %For remaining fields
00149
00150 if (isfield(Info, 'BRICK_STATS')),
00151 if (length(Info.BRICK_STATS) ~= 2.*Info.DATASET_RANK(2)),
00152 err = 1; ErrMessage = sprintf('Error %s: Info.BRICK_STATS should contain %d values (%d found).', FuncName, 2.*Info.DATASET_RANK(2), length(Info.BRICK_STATS)); errordlg(ErrMessage); return;
00153 end
00154 end
00155
00156 if (isfield(Info, 'BRICK_TYPES')),
00157 if (length(Info.BRICK_TYPES) ~= Info.DATASET_RANK(2)),
00158 err = 1; ErrMessage = sprintf('Error %s: Info.BRICK_TYPES should contain %d values (%d found).', FuncName, Info.DATASET_RANK(2), length(Info.BRICK_TYPES)); errordlg(ErrMessage); return;
00159 end
00160 end
00161
00162 if (isfield(Info, 'BRICK_FLOAT_FACS')),
00163 if (length(Info.BRICK_FLOAT_FACS) ~= Info.DATASET_RANK(2)),
00164 err = 1; ErrMessage = sprintf('Error %s: Info.BRICK_FLOAT_FACS should contain %d values (%d found).', FuncName, Info.DATASET_RANK(2), length(Info.BRICK_FLOAT_FACS)); errordlg(ErrMessage); return;
00165 end
00166 end
00167
00168 if (isfield(Info, 'TAXIS_NUMS')),
00169 if (~isfield(Info, 'TAXIS_FLOATS')),
00170 err = 1; ErrMessage = sprintf('Error %s: TAXIS_FLOATS must be specified along with TAXIS_NUMS', FuncName); errordlg(ErrMessage); return;
00171 end
00172 if (Info.TAXIS_NUMS(1) ~= Info.DATASET_RANK(2)),
00173 err = 1; ErrMessage = sprintf('Error %s: TAXIS_NUMS(1) must be equal to DATASET_RANK(2)', FuncName); errordlg(ErrMessage); return;
00174 end
00175
00176 if (Info.TAXIS_NUMS(2) & (~isfield(Info,'TAXIS_OFFSETS') | isempty(Info.TAXIS_OFFSETS))),
00177 err = 1; ErrMessage = sprintf('Error %s: TAXIS_OFFSETS must have a value if TAXIS_NUMS(2) is != 0', FuncName); errordlg(ErrMessage); return;
00178 end
00179 end
00180
00181 if (isfield(Info, 'IDCODE_DATE')),
00182 if (length(Info.IDCODE_DATE) > 46),
00183 err = 1; ErrMessage = sprintf('Error %s: IDCODE_DATE must be less than 46 characters.', FuncName); errordlg(ErrMessage); return;
00184 end
00185 end
00186
00187 if (isfield(Info, 'BYTEORDER_STRING')),
00188 if (~strcmp(Info.BYTEORDER_STRING, 'LSB_FIRST') & ~strcmp(Info.BYTEORDER_STRING, 'MSB_FIRST')),
00189 err = 1; ErrMessage = sprintf('Error %s: BYTEORDER_STRING must be either MSB_FIRST or LSB_FIRST', FuncName); errordlg(ErrMessage); return;
00190 end
00191 end
00192
00193 if (isfield('BRICK_LABS') & (WordCount(Info.BRICK_LABS, '~') ~= Info.DATASET_RANK(2))),
00194 err = 1; ErrMessage = sprintf('Error %s: There has to be exactly %d ~ separated labels in BRICK_LABS', FuncName, Info.DATASET_RANK(2)); errordlg(ErrMessage); return;
00195 end
00196
00197 if (isfield(Info, 'NOTES_COUNT') & (Info.NOTES_COUNT < 0 | Info.NOTES_COUNT > 999)),
00198 err = 1; ErrMessage = sprintf('Error %s: NOTES_COUNT must be between 0 and 999.', FuncName); errordlg(ErrMessage); return;
00199 end
00200
00201 if (isfield(Info, 'WARP_TYPE') & (Info.WARP_TYPE(1) ~= 0 & Info.WARP_TYPE(1) ~= 1)),
00202 err = 1; ErrMessage = sprintf('Error %s: WARP_TYPE(1) must be 0 or 1.', FuncName); errordlg(ErrMessage); return;
00203 end
00204
00205 if (isfield(Info, 'WARP_DATA')),
00206 if (rem(length(Info.WARP_DATA), 30)),
00207 err = 1; ErrMessage = sprintf('Error %s: The number of elements in WARP_DATA must be a multiple of 30.\nOtherwise BLTs would taste rotten.', FuncName); errordlg(ErrMessage); return;
00208 end
00209 end
00210
00211 if (isfield(Info, 'MARKS_FLAGS')),
00212 if (Info.MARKS_FLAGS(1) ~= 1 & Info.MARKS_FLAGS(1) ~= 2),
00213 err = 1; ErrMessage = sprintf('Error %s: MARKS_FLAGS(1) must be 0 or 1.', FuncName); errordlg(ErrMessage); return;
00214 end
00215 if (Info.MARKS_FLAGS(2) ~= 1),
00216 err = 1; ErrMessage = sprintf('Error %s: MARKS_FLAGS(2) must be 1.', FuncName); errordlg(ErrMessage); return;
00217 end
00218 end
00219
00220 if (isfield(Info, 'TAGSET_NUM')),
00221 if (Info.TAGSET_NUM(1) > 100),
00222 err = 1; ErrMessage = sprintf('Error %s: TAGSET_NUM(1) should not be larger than 100.', FuncName); errordlg(ErrMessage); return;
00223 end
00224 end
00225
00226 if (isfield(Info, 'TAGSET_NUM') & isfield(Info, 'TAGSET_FLOATS')),
00227 if (length(Info.TAGSET_FLOATS) ~= (Info.TAGSET_NUM(1) .* Info.TAGSET_NUM(2)) ), % Ask Ziad about this later
00228 err = 1; ErrMessage = sprintf('Error %s: Length of TAGSET_FLOATS must equal TAGSET_NUM(1) * TAGSET_NUM(2).', FuncName); errordlg(ErrMessage); return;
00229 end
00230 end
00231
00232 if (isfield(Info, 'TAGSET_NUM') & isfield(Info, 'TAGSET_LABELS')),
00233 if (WordCount(Info.TAGSET_LABELS, '~') ~= Info.TAGSET_NUM(1)), % Ask Ziad later
00234 err = 1; ErrMessage = sprintf('Error %s: TAGSET_LABELS must contain TAGSET_NUM(1) ~ delimited strings.', FuncName); errordlg(ErrMessage); return;
00235 end
00236 end
00237
00238 if (isfield(Info, 'BRICK_TYPES')),
00239 if (~isempty(unique(setdiff(Info.BRICK_TYPES, [0 1 3 5]))))
00240 err = 1; ErrMessage = sprintf('Error %s: BRICK_TYPES only types 0 1 3 5 are supported.', FuncName); errordlg(ErrMessage); return;
00241 end
00242 end
00243
00244 %checks on the rotate fields
00245 if (isfield(Info, 'VOLREG_ROTCOM_NUM')),
00246 for (i=1:1:Info.VOLREG_ROTCOM_NUM),
00247 sp = pad_strn(num2str(i-1), '0', 6, 1);
00248 spad = sprintf('~isfield(Info, ''VOLREG_MATVEC_%s'') | isempty(Info.VOLREG_MATVEC_%s) | ischar(Info.VOLREG_MATVEC_%s) | length(Info.VOLREG_MATVEC_%s) ~= 12', sp, sp, sp, sp);
00249 if (eval([ spad ])),
00250 err = 1; ErrMessage = sprintf('Error %s: Undefined VOLREG_MATVEC_%s or bad type (strings) or bad length (~=12)', FuncName, sp);errordlg(ErrMessage); return;
00251 end
00252 end
00253 end
00254
00255 %check on the NOT_NUMBER_... fields
00256 if (~isfield(Info, 'NOTES_COUNT') & isfield(Info, 'NOTE_NUMBER_001')),
00257 Info = rmfield(Info, 'NOTE_NUMBER_001');
00258 end
00259
00260 %check on the HISTORY field
00261 if (isfield(Info, 'HISTORY_NOTE')),
00262 vtmp = unique(double(Info.HISTORY_NOTE));
00263 if (~isempty(intersect([13 10 34 9 7 11 8], vtmp))),
00264 err = 1; ErrMessage = sprintf('Error %s: HISTORY_NOTE has not been TomRossed (formatted) properly.', FuncName); errordlg(ErrMessage);return;
00265 end
00266 end
00267
00268 %check on field groups
00269
00270 err = 0;
00271 return;
00272