1 /*****************************************************************************
2 Major portions of this software are copyrighted by the Medical College
3 of Wisconsin, 1994-2000, and are released under the Gnu General Public
4 License, Version 2. See the file README.Copyright for details.
5 ******************************************************************************/
6
7 #include "mrilib.h"
8
9 static ATR_float *Update_float_atr(char *aname, char *fvstring);
10 static ATR_int *Update_int_atr(char *aname, char *ivstring);
11
12 extern void Obliquity_to_coords(THD_3dim_dataset *);
13
Syntax(int detail)14 void Syntax(int detail)
15 {
16 int ii ;
17
18 printf(
19 "Changes some of the information inside a 3D dataset's header. ~1~\n"
20 "Note that this program does NOT change the .BRIK file at all;\n"
21 "the main purpose of 3drefit is to fix up errors made when\n"
22 "using to3d.\n"
23 "To see the current values stored in a .HEAD file, use the command\n"
24 "'3dinfo dataset'. Using 3dinfo both before and after 3drefit is\n"
25 "a good idea to make sure the changes have been made correctly!\n"
26 "\n"
27 "20 Jun 2006: 3drefit will now work on NIfTI datasets (but it will write\n"
28 " out the entire dataset, into the current working directory)\n\n"
29 ) ;
30
31 printf(
32 "Usage: 3drefit [options] dataset ... ~1~\n"
33 "where the options are\n"
34 " -quiet Turn off the verbose progress messages\n"
35 "\n"
36 " -orient code Sets the orientation of the 3D volume(s) in the .BRIK.\n"
37 " The code must be 3 letters, one each from the\n"
38 " pairs {R,L} {A,P} {I,S}. The first letter gives\n"
39 " the orientation of the x-axis, the second the\n"
40 " orientation of the y-axis, the third the z-axis:\n"
41 " R = right-to-left L = left-to-right\n"
42 " A = anterior-to-posterior P = posterior-to-anterior\n"
43 " I = inferior-to-superior S = superior-to-inferior\n"
44 " ** WARNING: when changing the orientation, you must be sure\n"
45 " to check the origins as well, to make sure that the volume\n"
46 " is positioned correctly in space.\n"
47 "\n"
48 " -xorigin distx Puts the center of the edge voxel off at the given\n"
49 " -yorigin disty distance, for the given axis (x,y,z); distances in mm.\n"
50 " -zorigin distz (x=first axis, y=second axis, z=third axis).\n"
51 " Usually, only -zorigin makes sense. Note that this\n"
52 " distance is in the direction given by the corresponding\n"
53 " letter in the -orient code. For example, '-orient RAI'\n"
54 " would mean that '-zorigin 30' sets the center of the\n"
55 " first slice at 30 mm Inferior. See the to3d manual\n"
56 " for more explanations of axes origins.\n"
57 " ** SPECIAL CASE: you can use the string 'cen' in place of\n"
58 " a distance to force that axis to be re-centered.\n"
59 "\n"
60 " -xorigin_raw xx Puts the center of the edge voxel at the given COORDINATE\n"
61 " -yorigin_raw yy rather than the given DISTANCE. That is, these values\n"
62 " -zorigin_raw zz directly replace the offsets in the dataset header,\n"
63 " without any possible sign changes.\n"
64 "\n"
65 " -duporigin cset Copies the xorigin, yorigin, and zorigin values from\n"
66 " the header of dataset 'cset'.\n"
67 "\n"
68 " -dxorigin dx Adds distance 'dx' (or 'dy', or 'dz') to the center\n"
69 " -dyorigin dy coordinate of the edge voxel. Can be used with the\n"
70 " -dzorigin dz values input to the 'Nudge xyz' plugin.\n"
71 " ** WARNING: you can't use these options at the same\n"
72 " time you use -orient.\n"
73 " ** WARNING: consider -shift_tags if dataset has tags\n"
74 "\n"
75 " -xdel dimx Makes the size of the voxel the given dimension,\n"
76 " -ydel dimy for the given axis (x,y,z); dimensions in mm.\n"
77 " -zdel dimz ** WARNING: if you change a voxel dimension, you will\n"
78 " probably have to change the origin as well.\n"
79 " -keepcen When changing a voxel dimension with -xdel (etc.),\n"
80 " also change the corresponding origin to keep the\n"
81 " center of the dataset at the same coordinate location.\n"
82 " -xyzscale fac Scale the size of the dataset voxels by the factor 'fac'.\n"
83 " This is equivalent to using -xdel, -ydel, -zdel together.\n"
84 " -keepcen is used on the first input dataset, and then\n"
85 " any others will be shifted the same amount, to maintain\n"
86 " their alignment with the first one.\n"
87 " ** WARNING: -xyzscale can't be used with any of the other\n"
88 " options that change the dataset grid coordinates!\n"
89 " ** N.B.: 'fac' must be positive, and using fac=1.0 is stupid.\n"
90 "\n"
91 " -TR time Changes the TR time to a new value (see 'to3d -help').\n"
92 " ** You can also put the name of a dataset in for 'time', in\n"
93 " which case the TR for that dataset will be used.\n"
94 " ** N.B.: If the dataset has slice time offsets, these will\n"
95 " be scaled by the factor newTR/oldTR. This scaling does not\n"
96 " apply if you use '-Tslices' in the same 3drefit run.\n"
97 " -notoff Removes the slice-dependent time-offsets.\n"
98 " -Torg ttt Set the time origin of the dataset to value 'ttt'.\n"
99 " (Time origins are set to 0 in to3d.)\n"
100 " ** WARNING: These 3 options apply only to 3D+time datasets.\n"
101 " **N.B.: Using '-TR' on a dataset without a time axis\n"
102 " will add a time axis to the dataset.\n"
103 "\n"
104 " -Tslices a b c d ...\n"
105 " Reset the slice time offsets to be 'a', 'b', 'c', ...\n"
106 " (in seconds). The number of values following '-Tslices'\n"
107 " should be the same as the number of slices in the dataset,\n"
108 " but 3drefit does NOT check that this is true.\n"
109 " ** If any offset time is < 0 or >= TR, a warning will be\n"
110 " printed (to stderr), but this is not illegal even though\n"
111 " it is a bad idea.\n"
112 " ** If the dataset does not have a TR set, then '-Tslices'\n"
113 " will fail. You can use '-TR' to set the inter-volume time\n"
114 " spacing in the same 3drefit command.\n"
115 " ** If you have the slices times stored (e.g., from DICOM) in\n"
116 " some other units, you can scale them to be in seconds by\n"
117 " putting a scale factor after the '-Tslices' option as follows:\n"
118 " -Tslices '*0.001' 300 600 900 ...\n"
119 " which would be used to scale from milliseconds to seconds.\n"
120 " The format is to start the scale factor with a '*' to tell\n"
121 " 3drefit that this number is not a slice offset but is to be\n"
122 " used a a scale factor for the rest of the following values.\n"
123 " Since '*' is a filename wildcard, it needs to be in quotes!\n"
124 " ** The program stops looking for number values after '-Tslices'\n"
125 " when it runs into something that does not look like a number.\n"
126 " Here, 'look like a number' means a character string that:\n"
127 " * starts with a digit 0..9\n"
128 " * starts with a decimal point '.' followed by a digit\n"
129 " * starts with a minus sign '-' followed by a digit\n"
130 " * starts with '-.' followed by a digit\n"
131 " So if the input dataset name starts with a digit, and the\n"
132 " last command line option '-Tslices', 3drefit will think\n"
133 " the filename is actually a number for a slice offset time.\n"
134 " To avoid this problem, you can do one of these things:\n"
135 " * Put in an option that is just the single character '-'\n"
136 " * Don't use '-Tslices' as the last option\n"
137 " * Put a directory name before the dataset name, as in\n"
138 " './Galacticon.nii'\n"
139 " ** If you have the slice time offsets stored in a text file\n"
140 " as a list of values, then you can input these values on\n"
141 " the command line using the Unix backquote operator, as in\n"
142 " -Tslices `cat SliceTimes.1D`\n"
143 " ** For example, if the slice time offsets are in a JSON\n"
144 " sidecar (a la BIDS), you might be able to something like\n"
145 " the following to extract the timings into a file:\n"
146 " abids_json_tool.py -json2txt -input sub-10506_task-pamenc_bold.json -prefix junk.txt\n"
147 " grep SliceTiming junk.txt | sed -e 's/^SliceTiming *://' > SliceTimes.1D\n"
148 " \\rm junk.txt\n"
149 "\n"
150 " -newid Changes the ID code of this dataset as well.\n"
151 "\n"
152 " -nowarp Removes all warping information from dataset.\n"
153 "\n"
154 " -apar aset Set the dataset's anatomy parent dataset to 'aset'\n"
155 " ** N.B.: The anatomy parent is the dataset from which the\n"
156 " transformation from +orig to +acpc and +tlrc coordinates\n"
157 " is taken. It is appropriate to use -apar when there is\n"
158 " more than 1 anatomical dataset in a directory that has\n"
159 " been transformed. In this way, you can be sure that\n"
160 " AFNI will choose the correct transformation. You would\n"
161 " use this option on all the +orig dataset that are\n"
162 " aligned with 'aset' (i.e., that were acquired in the\n"
163 " same scanning session).\n"
164 " ** N.B.: Special cases of 'aset'\n"
165 " aset = NULL --> remove the anat parent info from the dataset\n"
166 " aset = SELF --> set the anat parent to be the dataset itself\n"
167 "\n"
168 " -wpar wset Set the warp parent (the +orig version of a +tlrc dset).\n"
169 " This option is used by @auto_tlrc. Do not use it unless\n"
170 " you know what you're doing. \n"
171 "\n"
172 " -clear_bstat Clears the statistics (min and max) stored for each sub-brick\n"
173 " in the dataset. This is useful if you have done something to\n"
174 " modify the contents of the .BRIK file associated with this\n"
175 " dataset.\n"
176 " -redo_bstat Re-computes the statistics for each sub-brick. Requires\n"
177 " reading the .BRIK file, of course. Also does -clear_bstat\n"
178 " before recomputing statistics, so that if the .BRIK read\n"
179 " fails for some reason, then you'll be left without stats.\n"
180 "\n"
181 " -statpar v ... Changes the statistical parameters stored in this\n"
182 " dataset. See 'to3d -help' for more details.\n"
183 "\n"
184 " -markers Adds an empty set of AC-PC markers to the dataset,\n"
185 " if it can handle them (is anatomical, is in the +orig\n"
186 " view, and isn't 3D+time).\n"
187 " ** WARNING: this will erase any markers that already exist!\n"
188 "\n"
189 " -shift_tags Apply -dxorigin (and y and z) changes to tags.\n"
190 "\n"
191 " -dxtag dx Add dx to the coordinates of all tags.\n"
192 " -dytag dy Add dy to the coordinates of all tags.\n"
193 " -dztag dz Add dz to the coordinates of all tags.\n"
194 "\n"
195 " -view code Changes the 'view' to be 'code', where the string 'code'\n"
196 " is one of 'orig', 'acpc', or 'tlrc'.\n"
197 " ** WARNING: The program will also change the .HEAD and .BRIK\n"
198 " filenames to match. If the dataset filenames already\n"
199 " exist in the '+code' view, then this option will fail.\n"
200 " You will have to rename the dataset files before trying\n"
201 " to use '-view'. If you COPY the files and then use\n"
202 " '-view', don't forget to use '-newid' as well!\n"
203 " ** WARNING2: Changing the view without specifying the new \n"
204 " might lead to conflicting information. Consider specifying\n"
205 " the space along with -view\n"
206 " -space spcname Associates the dataset with a specific template type, e.g.\n"
207 " TLRC, MNI, ORIG. The default assumed for +tlrc datasets is\n"
208 " 'TLRC'. One use for this attribute is to use MNI space\n"
209 " coordinates and atlases instead of the default TLRC space.\n"
210 " ** See WARNING2 for -view option.\n"
211 " -cmap cmaptype Associate colormap type with dataset. Available choices are\n"
212 " CONT_CMAP (the default), INT_CMAP (integer colormap display)\n"
213 " and SPARSE_CMAP (for sparse integer colormaps). INT_CMAP is\n"
214 " appropriate for showing ROI mask datasets or Atlas datasets\n"
215 " where the continuous color scales are not useful.\n"
216 "\n"
217 " -label2 llll Set the 'label2' field in a dataset .HEAD file to the\n"
218 " string 'llll'. (Can be used as in AFNI window titlebars.)\n"
219 " -labeltable TTT Inset the label table TTT in the .HEAD file.\n"
220 " The label table format is described in README.environment\n"
221 " under the heading: 'Variable: AFNI_VALUE_LABEL_DTABLE'\n"
222 " See also -copytables\n"
223 "\n"
224 " -denote Means to remove all possibly-identifying notes from\n"
225 " the header. This includes the History Note, other text\n"
226 " Notes, keywords, and labels.\n"
227 "\n"
228 " -deoblique Replace transformation matrix in header with cardinal matrix.\n"
229 " This option DOES NOT deoblique the volume. To do so\n"
230 " you should use 3dWarp -deoblique. This option is not \n"
231 " to be used unless you really know what you're doing.\n"
232 "\n"
233 " -oblique_origin\n"
234 " assume origin and orientation from oblique transformation\n"
235 " matrix rather than traditional cardinal information\n"
236 "\n"
237 " -oblique_recenter\n"
238 " Adjust the origin so that the cardinalized 0,0,0 is in\n"
239 " the same brain location as that of the original (oblique?)\n"
240 " (scanner?) coordinates.\n"
241 " Round this to the nearest voxel center.\n"
242 " * Even if cardinal, rounding might cause an origin shift\n"
243 " (see -oblique_recenter_raw).\n"
244 "\n"
245 " -oblique_recenter_raw\n"
246 " Like -oblique_recenter, but do not round.\n"
247 " So coordinate 0,0,0 is in the exact same location, even\n"
248 " if not at a voxel center.\n"
249 "\n"
250
251 " -byteorder bbb Sets the byte order string in the header.\n"
252 " Allowable values for 'bbb' are:\n"
253 " LSB_FIRST MSB_FIRST NATIVE_ORDER\n"
254 " Note that this does not change the .BRIK file!\n"
255 " This is done by programs 2swap and 4swap.\n"
256 "\n"
257 " -checkaxes Doesn't alter the input dataset; rather, this just\n"
258 " checks the dataset axes orientation codes and the\n"
259 " axes matrices for consistency. (This option was\n"
260 " added primarily to check for bugs in various codes.)\n"
261 "\n"
262 " -appkey ll Appends the string 'll' to the keyword list for the\n"
263 " whole dataset.\n"
264 " -repkey ll Replaces the keyword list for the dataset with the\n"
265 " string 'll'.\n"
266 " -empkey Destroys the keyword list for the dataset.\n"
267 ) ;
268
269 printf(
270 "\n"
271 " -atrcopy dd nn Copy AFNI header attribute named 'nn' from dataset 'dd'\n"
272 " into the header of the dataset(s) being modified.\n"
273 " For more information on AFNI header attributes, see\n"
274 " documentation file README.attributes. More than one\n"
275 " '-atrcopy' option can be used.\n"
276 " **N.B.: This option is for those who know what they are doing!\n"
277 " Without the -saveatr option, this option is\n"
278 " meant to be used to alter attributes that are NOT\n"
279 " directly mapped into dataset internal structures, since\n"
280 " those structures are mapped back into attribute values\n"
281 " as the dataset is being written to disk. If you want\n"
282 " to change such an attribute, you have to use the\n"
283 " corresponding 3drefit option directly or use the \n"
284 " -saveatr option.\n"
285 "\n"
286 " If you are confused, try to understand this: \n"
287 " Option -atrcopy was never intended to modify AFNI-\n"
288 " specific attributes. Rather, it was meant to copy\n"
289 " user-specific attributes that had been added to some\n"
290 " dataset using -atrstring option. A cursed day came when\n"
291 " it was convenient to use -atrcopy to copy an AFNI-specific\n"
292 " attribute (BRICK_LABS to be exact) and for that to\n"
293 " take effect in the output, the option -saveatr was added.\n"
294 " Contact Daniel Glen and/or Rick Reynolds for further \n"
295 " clarification and any other needs you may have.\n"
296 "\n"
297 " Do NOT use -atrcopy or -atrstring with other modification\n"
298 " options.\n"
299 " See also -copyaux\n"
300 "\n"
301 " -atrstring n 'x' Copy the string 'x' into the dataset(s) being\n"
302 " modified, giving it the attribute name 'n'.\n"
303 " To be safe, the 'x' string should be in quotes.\n"
304 " **N.B.: You can store attributes with almost any name in\n"
305 " the .HEAD file. AFNI will ignore those it doesn't\n"
306 " know anything about. This technique can be a way of\n"
307 " communicating information between programs. However,\n"
308 " when most AFNI programs write a new dataset, they will\n"
309 " not preserve any such non-standard attributes.\n"
310 " **N.B.: Special case: if the string 'x' is of the form\n"
311 " 'file:name', then the contents of the file 'name' will\n"
312 " be read in as a single string and stored in the attribute.\n"
313 " -atrfloat name 'values'\n"
314 " -atrint name 'values'\n"
315 " Create or modify floating point or integer attributes.\n"
316 " The input values may be specified as a single string\n"
317 " in quotes or as a 1D filename or string. For example,\n"
318 " 3drefit -atrfloat IJK_TO_DICOM_REAL '1 0.2 0 0 -0.2 1 0 0 0 0 1 0'"
319 " dset+orig\n"
320 " 3drefit -atrfloat IJK_TO_DICOM_REAL flipZ.1D dset+orig\n"
321 " 3drefit -atrfloat IJK_TO_DICOM_REAL \\ \n"
322 " '1D:1,0.2,2@0,-0.2,1,2@0,2@0,1,0' \\ \n"
323 " dset+orig\n"
324 " Almost all afni attributes can be modified in this way\n"
325 " -saveatr (default) Copy the attributes that are known to AFNI into \n"
326 " the dset->dblk structure thereby forcing changes to known\n"
327 " attributes to be present in the output.\n"
328 " This option only makes sense with -atrcopy\n"
329 " **N.B.: Don't do something like copy labels of a dataset with \n"
330 " 30 sub-bricks to one that has only 10, or vice versa.\n"
331 " This option is for those who would deservedly earn a\n"
332 " hunting license.\n"
333 " -nosaveatr Opposite of -saveatr\n"
334 " Example: \n"
335 " 3drefit -saveatr -atrcopy WithLabels+tlrc BRICK_LABS NeedsLabels+tlrc\n"
336 ) ;
337
338 printf(
339 "\n"
340 " -'type' Changes the type of data that is declared for this\n"
341 " dataset, where 'type' is chosen from the following:\n"
342 ) ;
343 printf(" ANATOMICAL TYPES\n") ;
344 for( ii=FIRST_ANAT_TYPE ; ii <= LAST_ANAT_TYPE ; ii++ ){
345 printf(" %8s == %-16.16s",ANAT_prefixstr[ii],ANAT_typestr[ii] ) ;
346 if( (ii-FIRST_ANAT_TYPE)%2 == 1 ) printf("\n") ;
347 }
348 if( (ii-FIRST_ANAT_TYPE)%2 == 1 ) printf("\n") ;
349 printf(" FUNCTIONAL TYPES\n") ;
350 for( ii=FIRST_FUNC_TYPE ; ii <= LAST_FUNC_TYPE ; ii++ ){
351 printf(" %8s == %-16.16s",FUNC_prefixstr[ii],FUNC_typestr[ii] ) ;
352 if( (ii-FIRST_ANAT_TYPE)%2 == 1 ) printf("\n") ;
353 }
354 if( (ii-FIRST_ANAT_TYPE)%2 == 1 ) printf("\n") ;
355
356 printf( /* 08 Jun 2004 */
357 "\n"
358 " -copyaux auxset Copies the 'auxiliary' data from dataset 'auxset'\n"
359 " over the auxiliary data for the dataset being\n"
360 " modified. Auxiliary data comprises sub-brick labels,\n"
361 " keywords, statistics codes, nodelists, and labeltables\n"
362 " AND/OR atlas point lists.\n"
363 " '-copyaux' occurs BEFORE the '-sub' operations below,\n"
364 " so you can use those to alter the auxiliary data\n"
365 " that is copied from auxset.\n"
366 "\n" ) ;
367
368 printf( /* 11 Jan 2012 */
369 "\n"
370 " -copytables tabset Copies labeltables AND/OR atlas point lists, if any,\n"
371 " from tabset to the input dataset.\n"
372 " '-copyaux' occurs BEFORE the '-sub' operations below,\n"
373 " so you can use those to alter the auxiliary data\n"
374 " that is copied from tabset. \n"
375 "\n" ) ;
376
377
378 printf(
379 " -relabel_all xx Reads the file 'xx', breaks it into strings,\n"
380 " and puts these strings in as the sub-brick\n"
381 " labels. Basically a batch way of doing\n"
382 " '-sublabel' many times, for n=0, 1, ...\n"
383 " ** This option is executed BEFORE '-sublabel',\n"
384 " so any labels from '-sublabel' will over-ride\n"
385 " labels from this file.\n"
386 " ** Strings in the 'xx' file are separated by\n"
387 " whitespace (blanks, tabs, new lines).\n"
388 "\n" ) ;
389
390 printf(
391 " -relabel_all_str 'lab0 lab1 ... lab_p': Just like -relabel_all\n"
392 " but with labels all present in one string\n"
393 "\n" ) ;
394
395 printf(
396 " -sublabel_prefix PP: Prefix each sub-brick's label with PP\n"
397 " -sublabel_suffix SS: Suffix each sub-brick's label with SS\n"
398 "\n" ) ;
399
400 printf(
401 "The options below attach auxiliary data to sub-bricks in the dataset. ~1~\n"
402 "Each option may be used more than once so that\n"
403 "multiple sub-bricks can be modified in a single run of 3drefit.\n"
404 "\n"
405 " -sublabel n ll Attach to sub-brick #n the label string 'll'.\n"
406 " -subappkey n ll Add to sub-brick #n the keyword string 'll'.\n"
407 " -subrepkey n ll Replace sub-brick #n's keyword string with 'll'.\n"
408 " -subempkey n Empty out sub-brick #n' keyword string\n"
409 "\n"
410 " -substatpar n type v ...\n"
411 " Attach to sub-brick #n the statistical type and\n"
412 " the auxiliary parameters given by values 'v ...',\n"
413 " where 'type' is one of the following:\n"
414 ) ;
415 printf(" Stat Types: ~2~\n"
416 " type Description PARAMETERS\n"
417 " ---- ----------- ----------------------------------------\n" ) ;
418 for( ii=FIRST_FUNC_TYPE ; ii <= LAST_FUNC_TYPE ; ii++ ){
419 if( FUNC_IS_STAT(ii) )
420 printf(" %4s %-11.11s %s\n",
421 FUNC_prefixstr[ii] , FUNC_typestr[ii]+6 , FUNC_label_stat_aux[ii] ) ;
422 }
423 printf(
424 "\n"
425 "You can also use option '-unSTAT' to remove all statistical encodings\n"
426 "from sub-bricks in the dataset. This operation would be desirable if\n"
427 "you modified the values in the dataset (e.g., via 3dcalc).\n"
428 " ['-unSTAT' is done BEFORE the '-substatpar' operations, so you can ]\n"
429 " [combine these options to completely redo the sub-bricks, if needed.]\n"
430 " [Option '-unSTAT' also implies that '-unFDR' will be carried out. ]\n"
431 ) ;
432
433 printf(
434 "\n"
435 "The following options allow you to modify VOLREG fields: ~1~\n"
436 " -vr_mat val1 ... val12 Use these twelve values for VOLREG_MATVEC_index.\n"
437 " -vr_mat_ind index Index of VOLREG_MATVEC_index field to be modified.\n"
438 " Optional, default index is 0.\n"
439 "NB: You can only modify one VOLREG_MATVEC_index at a time\n"
440 " -vr_center_old x y z Use these 3 values for VOLREG_CENTER_OLD.\n"
441 " -vr_center_base x y z Use these 3 values for VOLREG_CENTER_BASE.\n"
442 "\n"
443 );
444
445 printf(
446 "\n"
447 "The following options let you modify the FDR curves stored in the header: ~1~\n"
448 "\n"
449 " -addFDR = For each sub-brick marked with a statistical code, (re)compute\n"
450 " the FDR curve of z(q) vs. statistic, and store in the dataset header\n"
451 " * '-addFDR' runs as if '-new -pmask' were given to 3dFDR, so that\n"
452 " stat values == 0 will be ignored in the FDR algorithm.\n"
453 "\n"
454 " -FDRmask mset = load dataset 'mset' and use it as a mask\n"
455 " -STATmask mset for the '-addFDR' calculations.\n"
456 " * This can be useful if you ran 3dDeconvolve/3dREMLFIT\n"
457 " without a mask, and want to apply a mask to improve\n"
458 " the FDR estimation procedure.\n"
459 " * If '-addFDR' is NOT given, then '-FDRmask' does nothing.\n"
460 " * 3drefit does not generate an automask for FDR purposes\n"
461 " (unlike 3dREMLfit and 3dDeconvolve), since the input\n"
462 " dataset may contain only statistics and no structural\n"
463 " information about the brain.\n"
464 "\n"
465 " -unFDR = Remove all FDR curves from the header\n"
466 " [you will want to do this if you have done something to ]\n"
467 " [modify the values in the dataset statistical sub-bricks]\n"
468 "\n"
469 ) ;
470
471 printf("++ Last program update: 27 Mar 2009\n");
472
473 PRINT_COMPILE_DATE ; exit(0) ;
474 }
475
SynErr(char * str)476 void SynErr(char *str)
477 {
478 if (str) ERROR_exit(str) ; /* does not return */
479 else Syntax(0);
480 return;
481 }
482
483
484 #define ASET_NULL 1
485 #define ASET_SELF 2
486
main(int argc,char * argv[])487 int main( int argc , char *argv[] )
488 {
489 THD_3dim_dataset * dset = NULL, * aset = NULL , *waset = NULL;
490 int aset_code = 0 ; /* 14 Dec 1999 */
491 int waset_code = 0;
492 THD_dataxes * daxes = NULL;
493 int new_stuff = 0 ;
494 int new_orient = 0 ; char orient_code[4]={"LOV"} ; int xxor=0,yyor=0,zzor=0 ;
495 int new_xorg = 0 ; float xorg = 0.0; int cxorg=0, dxorg=0 , duporg=0 ;
496 int new_yorg = 0 ; float yorg = 0.0; int cyorg=0, dyorg=0 ;
497 int new_zorg = 0 ; float zorg = 0.0; int czorg=0, dzorg=0 ;
498 int new_tags = 0 ; int shift_tags = 0 ; /* 08 May 2006 [rickr] */
499 float dxtag=0.0, dytag=0.0, dztag=0.0 ;
500 int new_xdel = 0 ; float xdel = 0.0;
501 int new_ydel = 0 ; float ydel = 0.0;
502 int new_zdel = 0 ; float zdel = 0.0;
503 int new_TR = 0 ; float TR = 0.0;
504 int new_Tslices= 0 ; float *Tslices = NULL ; /* 18 Dec 2018 */
505 int new_Torg = 0 ; float Torg = 0.0; /* 29 Jan 2003 */
506 int new_tunits = 0 ; int tunits = 0;
507 int new_idcode = 0 ;
508 int new_nowarp = 0 ;
509 int new_stataux= 0 ; float stataux[MAX_STAT_AUX] ;
510 int new_type = 0 ; int dtype = 0 , ftype = 0, nvals = 0;
511 int new_markers= 0 ;
512 int new_view = 0 ; int vtype = 0;
513 int new_key = 0 ; char * key = NULL;
514 int new_byte_order = 0 ; /* 25 Apr 1998 */
515 int new_toff_sl = 0 ; /* 12 Feb 2001 */
516 int clear_bstat = 0 ; /* 28 May 2002 */
517 int redo_bstat = 0 ; /* 01 Feb 2005 */
518 int copyaux = 0 ; /* 08 Jun 2004 */
519 int copytabs = 0 ; /* 11 Jan 2012 */
520 THD_3dim_dataset *auxset=NULL ; /* 08 Jun 2004 */
521 THD_3dim_dataset *tabset=NULL ; /* 11 Jan 2012 */
522 char *new_label2 = NULL ; /* 21 Dec 2004 */
523 char *labeltable = NULL; /* 25 Feb 2010 ZSS */
524 int denote = 0 ; /* 08 Jul 2005 */
525 RwcBoolean write_output ; /* 20 Jun 2006 [rickr] */
526 int keepcen = 0 ; /* 17 Jul 2006 [RWCox] */
527 float xyzscale = 0.0f ; /* 17 Jul 2006 */
528 int deoblique = 0; /* 20 Jun 2007 [drg] */
529 int use_oblique_origin = 0; /* 01 Dec 2008 */
530 int do_FDR = 0 ; /* 23 Jan 2008 [RWCox] */
531 int do_killSTAT = 0 ; /* 24 Jan 2008 [RWCox] */
532 int space = 0 ; /* 16 Mar 2009 [drg]*/
533 char *spacename = NULL;
534 byte *FDRmask = NULL ; /* 27 Mar 2009 [RWcox] */
535 int nFDRmask = 0 ;
536 int ndone=0 ; /* 18 Jul 2006 */
537 int verb =1 ;
538 int did_something ; /* 30 Mar 2010 */
539 int cmap = -1; /* colormap handling */
540 NI_str_array *sar_relab=NULL ; /* 18 Apr 2011 */
541 int geom_change = 0; /* 04 Nov 2011 [drg] */
542 int do_checkaxes = 0 ; /* 27 Jun 2014 [RWCox] */
543 int obl_recenter = 0 ; /* 17 Mar 2020 [rickr] */
544
545 #define VINFO(x) do{ if(verb)ININFO_message(x) ; } while(0)
546
547 char str[256] ;
548 int iarg , ii ;
549
550 typedef struct { int iv ; char lab[THD_MAX_SBLABEL] ; } SUBlabel ;
551 typedef struct { int iv ; float par[MAX_STAT_AUX+2] ; } SUBstatpar ;
552 typedef struct { int iv , code ; char * keyword ; } SUBkeyword ;
553 int nsublab = 0 ; SUBlabel * sublab = NULL ;
554 int nsubstatpar = 0 ; SUBstatpar * substatpar = NULL ;
555 int nsubkeyword = 0 ; SUBkeyword * subkeyword = NULL ;
556 char *cpt ;
557 int iv ;
558
559 float volreg_mat[12];
560 float center_old[3];
561 float center_base[3];
562 int Do_volreg_mat = 0, Do_center_old = 0, Do_center_base = 0,
563 volreg_matind = 0, icnt = 0;
564 char *lcpt=NULL, *subsuff=NULL, *subpref=NULL;
565
566 int num_atrcopy = 0 ; /* 03 Aug 2005 */
567 ATR_any **atrcopy = NULL ;
568 ATR_float *atr_flt ;
569
570 int saveatr = 1;
571 int atrmod = 0; /* if no ATR is modified, don't overwrite normal changes */
572 /* 28 Jul 2006 [rickr] */
573 THD_dmat33 tmat ;
574 THD_dfvec3 tvec ;
575
576 int code, acount;
577
578 /*-------------------------- help me if you can? --------------------------*/
579
580 /*-- 20 Apr 2001: addto the arglist, if user wants to [RWCox] --*/
581
582 mainENTRY("3drefit main"); machdep() ; PRINT_VERSION("3drefit") ; AUTHOR("RW Cox") ;
583 set_obliquity_report(0); /* silence obliquity */
584 { int new_argc ; char ** new_argv ;
585 addto_args( argc , argv , &new_argc , &new_argv ) ;
586 if( new_argv != NULL ){ argc = new_argc ; argv = new_argv ; }
587 }
588
589 AFNI_logger("3drefit",argc,argv) ;
590 AFNI_setenv("AFNI_COMPRESSOR=NONE") ; /* 26 Jul 2013 */
591
592 iarg = 1 ;
593 while( iarg < argc && argv[iarg][0] == '-' ){
594 if(strcmp(argv[iarg],"-h") == 0 ||
595 strncmp(argv[iarg],"-help",4) == 0 )
596 Syntax(strlen(argv[iarg]) > 3 ? 2:1) ;
597
598 if( strcmp(argv[iarg],"-") == 0 ){ iarg++ ; continue ; } /* 18 Dec 2018 */
599
600 /*----- -checkaxes [27 Jun 2014] -----*/
601
602 if( strcasecmp(argv[iarg],"-checkaxes") == 0 ){
603 do_checkaxes = 1 ; new_stuff++ ; iarg++ ; continue ;
604 }
605
606 /*----- -addFDR [23 Jan 2008] -----*/
607
608 if( strcasecmp(argv[iarg],"-addFDR") == 0 ){
609 do_FDR = 1 ; new_stuff++ ; iarg++ ; continue ;
610 }
611 if( strcasecmp(argv[iarg],"-killFDR") == 0 || strcasecmp(argv[iarg],"-unFDR") == 0 ){
612 do_FDR = -1 ; new_stuff++ ; iarg++ ; continue ;
613 }
614 if( strcasecmp(argv[iarg],"-killSTAT") == 0 || strcasecmp(argv[iarg],"-unSTAT") == 0 ){
615 do_killSTAT = 1 ; do_FDR = -1 ; new_stuff++ ; iarg++ ; continue ;
616 }
617
618 if( strcasecmp(argv[iarg],"-FDRmask") == 0 ||
619 strcasecmp(argv[iarg],"-STATmask") == 0 ){ /*-- 27 Mar 2009 --*/
620
621 bytevec *bvec ; /* 15 Jul 2010 */
622
623 if( iarg+1 >= argc ) SynErr("need 1 argument after -FDRmask!") ;
624 if( nFDRmask > 0 ) SynErr("can't have two -FDRmask options!") ;
625 bvec = THD_create_mask_from_string(argv[++iarg]) ;
626 if( bvec == NULL ) ERROR_exit("Can't decipher %s",argv[iarg-1]) ;
627 FDRmask = bvec->ar ; nFDRmask = bvec->nar ;
628 ii = THD_countmask(nFDRmask,FDRmask) ;
629 if( ii < 100 ){
630 WARNING_message("-FDRmask has only %d nonzero voxels: ignoring",ii) ;
631 KILL_bytevec(bvec) ; FDRmask = NULL ; nFDRmask = 0 ;
632 } else {
633 INFO_message("%s has %d nonzero voxels (out of %d total)",
634 argv[iarg-1],ii,nFDRmask) ;
635 }
636 iarg++ ; continue ;
637 }
638
639 /*----- -atrcopy dd nn [03 Aug 2005] -----*/
640
641 if( strcmp(argv[iarg],"-atrcopy") == 0 ){
642 THD_3dim_dataset *qset ; ATR_any *atr ;
643
644 if( iarg+2 >= argc ) SynErr("need 2 arguments after -atrcopy!") ;
645
646 qset = THD_open_dataset( argv[++iarg] ) ;
647 if( qset == NULL ){
648 WARNING_message("Can't open -atrcopy dataset %s",argv[iarg]) ;
649 iarg++ ; goto atrcopy_done ;
650 }
651 atr = THD_find_atr( qset->dblk , argv[++iarg] ) ;
652 if( atr == NULL ){
653 WARNING_message("Can't find attribute %s in -atrcopy dataset %s",
654 argv[iarg],argv[iarg-1]) ;
655 DSET_delete(qset) ; goto atrcopy_done ;
656 }
657
658 atrcopy = (ATR_any **)realloc( (void *)atrcopy ,
659 sizeof(ATR_any *)*(num_atrcopy+1) ) ;
660 atrcopy[num_atrcopy++] = THD_copy_atr( atr ) ;
661 /* atr_print( atr, NULL , NULL, '\0', 1) ; */
662 DSET_delete(qset) ;
663 atrmod = 1; /* replaced new_stuff 28 Jul 2006 rcr */
664
665 atrcopy_done:
666 iarg++ ; continue ;
667 }
668
669 /*----- -atrstring nn xx [03 Aug 2005] -----*/
670
671 if( strcmp(argv[iarg],"-atrstring") == 0 ){
672 ATR_string *atr ; char *aname , *xx , *yy=NULL ;
673
674 if( iarg+2 >= argc ) SynErr("need 2 arguments after -atrstring!") ;
675
676 aname = argv[++iarg] ;
677 if( !THD_filename_pure(aname) ){
678 WARNING_message("Illegal -atrstring name %s",aname) ;
679 iarg++ ; goto atrstring_done ;
680 }
681 xx = argv[++iarg] ;
682 atr = (ATR_string *)RwcMalloc(sizeof(ATR_string)) ;
683
684 if( strncmp(xx,"file:",5) == 0 && strlen(xx) > 5 ){ /* 08 Jul 2010 */
685 int ii ;
686 yy = AFNI_suck_file(xx+5) ;
687 if( yy == NULL ){
688 WARNING_message("Can't read '%s'",xx) ; goto atrstring_done ;
689 }
690 xx = yy ;
691 for( ii=strlen(yy)-1 ; ii > 0 && isspace(yy[ii]) ; ii-- )
692 yy[ii] = '\0' ; /* truncate trailing whitespace */
693 }
694
695 atr->type = ATR_STRING_TYPE ;
696 atr->name = RwcNewString( aname ) ;
697 atr->nch = strlen(xx)+1 ; ;
698 atr->ch = (char *)RwcMalloc( sizeof(char) * atr->nch ) ;
699 memcpy( atr->ch , xx , sizeof(char) * atr->nch ) ;
700
701 if( yy != NULL ) free(yy) ; /* 08 Jul 2010 */
702
703 atrcopy = (ATR_any **)realloc( (void *)atrcopy ,
704 sizeof(ATR_any *)*(num_atrcopy+1) ) ;
705 atrcopy[num_atrcopy++] = (ATR_any *)atr ;
706
707 atrmod = 1; /* replaced new_stuff++ 28 Jul 2006 [rickr] */
708 atrstring_done:
709 iarg++ ; continue ;
710 }
711
712
713 /*----- -atrfloat name "xx.xx yy.yy ..." [02 Oct 2008] -----*/
714 if( strcmp(argv[iarg],"-atrfloat") == 0 ){
715 ATR_float *atr ;
716
717 if( iarg+2 >= argc ) SynErr("need 2 arguments after -atrfloat!") ;
718 atr = Update_float_atr(argv[iarg+1], argv[iarg+2]);
719 if(atr) {
720 /* add this float attribute to list of attributes being modified */
721 atrcopy = (ATR_any **)realloc( (void *)atrcopy ,
722 sizeof(ATR_any *)*(num_atrcopy+1) ) ;
723 atrcopy[num_atrcopy++] = (ATR_any *)atr ;
724
725 atrmod = 1; /* replaced new_stuff++ 28 Jul 2006 [rickr] */
726 }
727
728 iarg+=3 ; continue ;
729 }
730
731 /*----- -atrint name "xx.xx yy.yy ..." [06 Oct 2008] -----*/
732 if( strcmp(argv[iarg],"-atrint") == 0 ){
733 ATR_int *atr ;
734
735 if( iarg+2 >= argc ) SynErr("need 2 arguments after -atrint!") ;
736 atr = Update_int_atr(argv[iarg+1], argv[iarg+2]);
737 if(atr) {
738 /* add this int attribute to list of attributes being modified */
739 atrcopy = (ATR_any **)realloc( (void *)atrcopy ,
740 sizeof(ATR_any *)*(num_atrcopy+1) ) ;
741 atrcopy[num_atrcopy++] = (ATR_any *)atr ;
742
743 atrmod = 1; /* new or modified attribute */
744 }
745
746 iarg+=3 ; continue ;
747 }
748
749
750 if( strcmp(argv[iarg],"-saveatr") == 0 ){
751 saveatr = 1 ; iarg++ ; continue ;
752 }
753
754 if( strcmp(argv[iarg],"-nosaveatr") == 0 ){
755 saveatr = 0 ; iarg++ ; continue ;
756 }
757
758 /*----- -denote [08 Jul 2005] -----*/
759
760 if( strcmp(argv[iarg],"-denote") == 0 ){
761 denote = 1 ; new_stuff++ ; iarg++ ; continue ;
762 }
763
764 /*----- -copyaux auxset [08 Jun 2004] -----*/
765
766 if( strcmp(argv[iarg],"-copyaux") == 0 ){
767
768 if( iarg+1 >= argc ) SynErr("need 1 argument after -copyaux!") ;
769
770 if( auxset != NULL ) SynErr("Can't have more than one -copyaux option!") ;
771
772 iarg++ ; copyaux = 1 ;
773 if( strcmp(argv[iarg],"NULL") == 0 ){ /* special case */
774 auxset = NULL ;
775 } else {
776 auxset = THD_open_one_dataset( argv[iarg] ) ;
777 if( auxset == NULL ) SynErr("Can't open -copyaux dataset!") ;
778 }
779
780 new_stuff++ ; iarg++ ; continue ; /* go to next arg */
781 }
782
783 /*----- -copytables tabset [12 Jan 2012] -----*/
784
785 if( strcmp(argv[iarg],"-copytables") == 0 ){
786
787 if( iarg+1 >= argc ) SynErr("need 1 argument after -copytables!") ;
788
789 if( tabset != NULL ) SynErr("Can't have more than one -copytables option!") ;
790
791 iarg++ ; copytabs = 1 ;
792
793 tabset = THD_open_one_dataset( argv[iarg] ) ;
794 if( tabset == NULL ) SynErr("Can't open -copytables dataset!") ;
795
796 new_stuff++ ; iarg++ ; continue ; /* go to next arg */
797 }
798
799 /*----- -apar aset [14 Oct 1999] -----*/
800
801 if( strcmp(argv[iarg],"-apar") == 0 ||
802 strcmp(argv[iarg],"-anatparent") == 0 ||
803 strcmp(argv[iarg],"-aset") == 0 ){
804
805 if( iarg+1 >= argc )
806 SynErr("need 1 argument after -apar!") ;
807
808 if( aset != NULL || aset_code != 0 ) /* 13-14 Dec 1999 */
809 SynErr("Can't have more than one -apar option!");
810
811 iarg++ ;
812 if( strcmp(argv[iarg],"NULL") == 0 ){ /* 14 Dec 1999: special cases */
813 aset_code = ASET_NULL ;
814 } else if( strcmp(argv[iarg],"SELF") == 0 ){
815 aset_code = ASET_SELF ;
816 } else {
817 aset = THD_open_one_dataset( argv[iarg] ) ;
818 if( aset == NULL )
819 SynErr("Can't open -apar dataset!") ;
820 }
821
822 new_stuff++ ; iarg++ ; continue ; /* go to next arg */
823 }
824
825 /*----- -wpar wset [ZSS June 06] -----*/
826
827 if( strcmp(argv[iarg],"-wpar") == 0 ||
828 strcmp(argv[iarg],"-warpparent") == 0 ||
829 strcmp(argv[iarg],"-wset") == 0 ){
830
831 if( iarg+1 >= argc )
832 SynErr("need 1 argument after -wpar!") ;
833
834 if( waset != NULL || waset_code != 0 )
835 SynErr("Can't have more than one -wpar option!");
836
837 iarg++ ;
838 if( strcmp(argv[iarg],"NULL") == 0 ){
839 waset_code = ASET_NULL ;
840 } else if( strcmp(argv[iarg],"SELF") == 0 ){
841 waset_code = ASET_SELF ;
842 } else {
843 waset = THD_open_one_dataset( argv[iarg] ) ;
844 if( waset == NULL )
845 SynErr("Can't open -wpar dataset!") ;
846 }
847
848 new_stuff++ ; iarg++ ; continue ; /* go to next arg */
849 }
850
851 /*----- -clear_bstat option [28 May 2002] -----*/
852
853 if( strcmp(argv[iarg],"-clear_bstat") == 0 ){
854 clear_bstat = 1 ;
855 new_stuff++ ; iarg++ ; continue ; /* go to next arg */
856 }
857
858 if( strcmp(argv[iarg],"-redo_bstat") == 0 ){ /* 01 Feb 2005 */
859 clear_bstat = 1 ; redo_bstat = 1 ;
860 new_stuff++ ; iarg++ ; continue ; /* go to next arg */
861 }
862
863 /*----- -byteorder option [25 April 1998] -----*/
864
865 if( strncmp(argv[iarg],"-byteorder",7) == 0 ){
866 if( iarg+1 >= argc )
867 SynErr("need 1 argument after -byteorder!") ;
868
869 iarg++ ;
870 if( strcmp(argv[iarg],LSB_FIRST_STRING) == 0 )
871 new_byte_order = LSB_FIRST ;
872 else if( strcmp(argv[iarg],MSB_FIRST_STRING) == 0 )
873 new_byte_order = MSB_FIRST ;
874 else if( strcmp(argv[iarg],NATIVE_STRING) == 0 )
875 new_byte_order = mri_short_order() ;
876 else
877 SynErr("illegal argument after -byteorder!") ;
878
879 new_stuff++ ; iarg++ ; continue ; /* go to next arg */
880 }
881
882 /*----- -relabel_all option -----*/
883
884 if( strcmp(argv[iarg],"-relabel_all") == 0 ||
885 strcmp(argv[iarg],"-relabel_all_str") == 0){ /* 18 Apr 2011 */
886 if( ++iarg >= argc ) SynErr("Need argument after -relabel_all*") ;
887 if (strcmp(argv[iarg-1],"-relabel_all") == 0 ) {
888 char *str ;
889 str = AFNI_suck_file(argv[iarg]) ;
890 if( str == NULL || *str == '\0' )
891 SynErr("Can't read file after -relabel_all") ;
892 sar_relab = NI_decode_string_list( str , "`" ) ; free(str) ;
893 } else {
894 sar_relab = NI_decode_string_list( argv[iarg], "`" );
895 }
896 if( sar_relab == NULL || sar_relab->num < 1 )
897 SynErr("Can't decode file or string after -relabel_all*") ;
898 INFO_message("-relabel_all* %s contains %d label%s" ,
899 argv[iarg] , sar_relab->num , (sar_relab->num==1) ? "\0" : "s" ) ;
900 new_stuff++ ; iarg++ ; continue ;
901 }
902
903
904 /*----- -sublabel_prefix -----*/
905
906 if( strcmp(argv[iarg],"-sublabel_prefix") == 0 ){ /* 15 Aug 2012 */
907 char *str ;
908 if( ++iarg >= argc ) SynErr("Need argument after -sublabel_prefix") ;
909 subpref = argv[iarg];
910
911 new_stuff++ ; iarg++ ; continue ;
912 }
913
914 /*----- -sublabel_suffix -----*/
915
916 if( strcmp(argv[iarg],"-sublabel_suffix") == 0 ){ /* 15 Aug 2012 */
917 char *str ;
918 if( ++iarg >= argc ) SynErr("Need argument after -sublabel_suffix") ;
919 subsuff = argv[iarg] ;
920
921 new_stuff++ ; iarg++ ; continue ;
922 }
923
924 /*----- -sublabel option -----*/
925
926 if( strncmp(argv[iarg],"-sublabel",7) == 0 ){
927 if( iarg+2 >= argc )
928 SynErr("need 2 arguments after -sublabel!") ;
929
930 iv = strtol( argv[++iarg] , &cpt , 10 ) ;
931 if( iv < 0 || (iv == 0 && cpt == argv[iarg]) )
932 SynErr("illegal sub-brick index after -sublabel!") ;
933
934 sublab = (SUBlabel *) RwcRealloc( (char *)sublab ,
935 sizeof(SUBlabel) * (nsublab+1) ) ;
936
937 sublab[nsublab].iv = iv ;
938 /* max sublabel = 64, 10/28/2011 drg */
939 MCW_strncpy( sublab[nsublab].lab , argv[++iarg] , THD_MAX_SBLABEL ) ;
940 nsublab++ ; new_stuff++ ; iarg++ ; continue ; /* go to next arg */
941 }
942
943 /*----- -subkeyword options -----*/
944
945 if( strncmp(argv[iarg],"-subappkey",7) == 0 ||
946 strncmp(argv[iarg],"-subrepkey",7) == 0 ||
947 strncmp(argv[iarg],"-subempkey",7) == 0 ){
948
949 int code , npl ;
950 if( strncmp(argv[iarg],"-subappkey",7) == 0 ) code = 1 ;
951 else if( strncmp(argv[iarg],"-subrepkey",7) == 0 ) code = 2 ;
952 else code = 3 ;
953
954 npl = (code == 3) ? 1 : 2 ;
955 if( iarg+npl >= argc )
956 SynErr("need arguments after -sub...key!") ;
957
958 iv = strtol( argv[++iarg] , &cpt , 10 ) ;
959 if( iv < 0 || (iv == 0 && cpt == argv[iarg]) )
960 SynErr("illegal sub-brick index after -sub...key!") ;
961
962 subkeyword = (SUBkeyword *) RwcRealloc( (char *)subkeyword ,
963 sizeof(SUBkeyword)*(nsubkeyword+1) ) ;
964
965 subkeyword[nsubkeyword].iv = iv ;
966 subkeyword[nsubkeyword].code = code ;
967 if( code != 3 ) subkeyword[nsubkeyword].keyword = argv[++iarg] ;
968
969 nsubkeyword++ ; new_stuff++ ; iarg++ ; continue ; /* go to next arg */
970 }
971
972 /*----- -keywords options -----*/
973
974 if( strncmp(argv[iarg],"-appkey",4) == 0 ||
975 strncmp(argv[iarg],"-repkey",4) == 0 ||
976 strncmp(argv[iarg],"-empkey",4) == 0 ){
977
978 int code , npl ;
979 if( strncmp(argv[iarg],"-appkey",4) == 0 ) code = 1 ;
980 else if( strncmp(argv[iarg],"-repkey",4) == 0 ) code = 2 ;
981 else code = 3 ;
982
983 npl = (code == 3) ? 0 : 1 ;
984 if( iarg+code >= argc )
985 SynErr("need arguments after -...key!") ;
986
987 new_key = code ;
988 if( code != 3 ) key = argv[++iarg] ;
989 new_stuff++ ; iarg++ ; continue ; /* go to next arg */
990 }
991
992 /*----- -substatpar option -----*/
993
994 if( strncmp(argv[iarg],"-substatpar",7) == 0 ){
995 int fc ; float val ;
996
997 if( iarg+2 >= argc )
998 SynErr("need at least 2 arguments after -substatpar!") ;
999
1000 iv = strtol( argv[++iarg] , &cpt , 10 ) ;
1001 if( iv < 0 || (iv == 0 && cpt == argv[iarg]) )
1002 SynErr("illegal sub-brick index after -substatpar!") ;
1003
1004 iarg++ ;
1005 if( strlen(argv[iarg]) < 3 )
1006 SynErr("illegal type code after -substatpar!") ;
1007 fc = (argv[iarg][0] == '-') ? 1 : 0 ;
1008
1009 for( ii=FIRST_FUNC_TYPE ; ii <= LAST_FUNC_TYPE ; ii++ ){
1010 if( ! FUNC_IS_STAT(ii) ) continue ;
1011 if( strncmp( &(argv[iarg][fc]) ,
1012 FUNC_prefixstr[ii] , THD_MAX_PREFIX ) == 0 ) break ;
1013 }
1014
1015 if( ii > LAST_FUNC_TYPE )
1016 SynErr("unknown type code after -substatpar!") ;
1017
1018 substatpar = (SUBstatpar *) RwcRealloc( (char *)substatpar ,
1019 sizeof(SUBstatpar) * (nsubstatpar+1) ) ;
1020
1021 substatpar[nsubstatpar].iv = iv ;
1022 substatpar[nsubstatpar].par[0] = ii ;
1023 substatpar[nsubstatpar].par[1] = MAX_STAT_AUX ;
1024
1025 for( ii=0 ; ii < MAX_STAT_AUX ; ii++ )
1026 substatpar[nsubstatpar].par[ii+2] = 0.0 ;
1027
1028 ii = 2 ; iarg++ ;
1029 do{
1030 val = strtod( argv[iarg] , &cpt ) ;
1031 if( *cpt != '\0' ) break ;
1032 substatpar[nsubstatpar].par[ii++] = val ;
1033 iarg++ ;
1034 } while( iarg < argc && ii-2 < MAX_STAT_AUX ) ;
1035
1036 nsubstatpar++ ; new_stuff++ ; continue ; /* go to next arg */
1037 }
1038
1039 /*----- -orient code option -----*/
1040
1041 #define ORCODE(aa) \
1042 ( (aa)=='R' ? ORI_R2L_TYPE : (aa)=='L' ? ORI_L2R_TYPE : \
1043 (aa)=='P' ? ORI_P2A_TYPE : (aa)=='A' ? ORI_A2P_TYPE : \
1044 (aa)=='I' ? ORI_I2S_TYPE : (aa)=='S' ? ORI_S2I_TYPE : ILLEGAL_TYPE )
1045
1046 #define OR3OK(x,y,z) ( ((x)&6) + ((y)&6) + ((z)&6) == 6 )
1047
1048 if( strncmp(argv[iarg],"-orient",4) == 0 ){
1049 char acod ;
1050
1051 if( iarg+1 >= argc ) SynErr("need an argument after -orient!");
1052
1053 MCW_strncpy(orient_code,argv[++iarg],4) ;
1054 if( strlen(orient_code) != 3 ) SynErr("Illegal -orient code") ;
1055
1056 acod = toupper(orient_code[0]) ; xxor = ORCODE(acod) ;
1057 acod = toupper(orient_code[1]) ; yyor = ORCODE(acod) ;
1058 acod = toupper(orient_code[2]) ; zzor = ORCODE(acod) ;
1059
1060 if( xxor<0 || yyor<0 || zzor<0 || ! OR3OK(xxor,yyor,zzor) )
1061 SynErr("Unusable -orient code!") ;
1062
1063 new_orient = 1 ; new_stuff++ ;
1064 iarg++ ; continue ; /* go to next arg */
1065 }
1066
1067 /** -?origin dist **/
1068
1069 if( strcmp(argv[iarg],"-xorigin") == 0 ){
1070 if( ++iarg >= argc ) SynErr("need an argument after -xorigin!");
1071 if( strncmp(argv[iarg],"cen",3) == 0 ) cxorg = 1 ;
1072 else xorg = strtod(argv[iarg],NULL) ;
1073 dxorg = 0 ; new_xorg = 1 ; new_stuff++ ;
1074 geom_change = 1;
1075 iarg++ ; continue ; /* go to next arg */
1076 }
1077
1078 if( strcmp(argv[iarg],"-yorigin") == 0 ){
1079 if( ++iarg >= argc ) SynErr("need an argument after -yorigin!");
1080 if( strncmp(argv[iarg],"cen",3) == 0 ) cyorg = 1 ;
1081 else yorg = strtod(argv[iarg],NULL) ;
1082 dyorg = 0 ; new_yorg = 1 ; new_stuff++ ;
1083 geom_change = 1;
1084 iarg++ ; continue ; /* go to next arg */
1085 }
1086
1087 if( strcmp(argv[iarg],"-zorigin") == 0 ){
1088 if( ++iarg >= argc ) SynErr("need an argument after -zorigin!");
1089 if( strncmp(argv[iarg],"cen",3) == 0 ) czorg = 1 ;
1090 else zorg = strtod(argv[iarg],NULL) ;
1091 dzorg = 0 ; new_zorg = 1 ; new_stuff++ ;
1092 geom_change = 1;
1093 iarg++ ; continue ; /* go to next arg */
1094 }
1095
1096 /* 13 Sep 2000: -duporigin */
1097
1098 if( strcmp(argv[iarg],"-duporigin") == 0 ){
1099 THD_3dim_dataset * cset ;
1100 if( ++iarg >= argc ) SynErr("need an argument after -duporigin!");
1101 cset = THD_open_dataset( argv[iarg] ) ;
1102 if( cset == NULL ) SynErr("couldn't open -duporigin dataset!");
1103 daxes = cset->daxes ;
1104 xorg = daxes->xxorg ; yorg = daxes->yyorg ; zorg = daxes->zzorg ;
1105 cxorg = cyorg = czorg = dxorg = dyorg = dzorg = 0 ;
1106 new_xorg = new_yorg = new_zorg = duporg = 1 ; new_stuff++ ;
1107 DSET_delete(cset) ;
1108 geom_change = 1;
1109 iarg++ ; continue ; /* go to next arg */
1110 }
1111
1112 /* 02 Mar 2000: -d?origin stuff, to go with plug_nudge.c */
1113
1114 if( strcmp(argv[iarg],"-oblique_recenter") == 0 ){
1115 obl_recenter = 2 ;
1116 new_stuff++ ;
1117 /* no geom change */
1118 iarg++ ; continue ; /* go to next arg */
1119 }
1120
1121 if( strcmp(argv[iarg],"-oblique_recenter_raw") == 0 ){
1122 obl_recenter = 1 ;
1123 new_stuff++ ;
1124 /* no geom change */
1125 iarg++ ; continue ; /* go to next arg */
1126 }
1127
1128 if( strncmp(argv[iarg],"-dxorigin",4) == 0 ){
1129 if( ++iarg >= argc ) SynErr("need an argument after -dxorigin!");
1130 xorg = strtod(argv[iarg],NULL) ; dxorg = 1 ; cxorg = 0 ;
1131 new_xorg = 1 ; new_stuff++ ;
1132 geom_change = 1;
1133 iarg++ ; continue ; /* go to next arg */
1134 }
1135
1136 if( strncmp(argv[iarg],"-dyorigin",4) == 0 ){
1137 if( ++iarg >= argc ) SynErr("need an argument after -dyorigin!");
1138 yorg = strtod(argv[iarg],NULL) ; dyorg = 1 ; cyorg = 0 ;
1139 new_yorg = 1 ; new_stuff++ ;
1140 geom_change = 1;
1141 iarg++ ; continue ; /* go to next arg */
1142 }
1143
1144 if( strncmp(argv[iarg],"-dzorigin",4) == 0 ){
1145 if( ++iarg >= argc ) SynErr("need an argument after -dzorigin!");
1146 zorg = strtod(argv[iarg],NULL) ; dzorg = 1 ; czorg = 0 ;
1147 new_zorg = 1 ; new_stuff++ ;
1148 geom_change = 1;
1149 iarg++ ; continue ; /* go to next arg */
1150 }
1151
1152 /** 04 Oct 2002: _raw origins **/
1153
1154 if( strcmp(argv[iarg],"-xorigin_raw") == 0 ){
1155 if( ++iarg >= argc ) SynErr("need an argument after -xorigin_raw!");
1156 xorg = strtod(argv[iarg],NULL) ; cxorg = dxorg = 0 ;
1157 new_xorg = 2 ; new_stuff++ ;
1158 geom_change = 1;
1159 iarg++ ; continue ; /* go to next arg */
1160 }
1161
1162 if( strcmp(argv[iarg],"-yorigin_raw") == 0 ){
1163 if( ++iarg >= argc ) SynErr("need an argument after -yorigin_raw!");
1164 yorg = strtod(argv[iarg],NULL) ; cyorg = dyorg = 0 ;
1165 new_yorg = 2 ; new_stuff++ ;
1166 geom_change = 1;
1167 iarg++ ; continue ; /* go to next arg */
1168 }
1169
1170 if( strcmp(argv[iarg],"-zorigin_raw") == 0 ){
1171 if( ++iarg >= argc ) SynErr("need an argument after -zorigin_raw!");
1172 zorg = strtod(argv[iarg],NULL) ; czorg = dzorg = 0 ;
1173 new_zorg = 2 ; new_stuff++ ;
1174 geom_change = 1;
1175 iarg++ ; continue ; /* go to next arg */
1176 }
1177
1178 /** 04 Oct 2002: zadd VOLREG fields **/
1179 if( strcmp(argv[iarg],"-vr_mat") == 0 ){
1180 if( iarg+12 >= argc ) SynErr("need 12 arguments after -vr_mat!");
1181 icnt = 0;
1182 while (icnt < 12) {
1183 ++iarg;
1184 volreg_mat[icnt] = strtod(argv[iarg], &lcpt) ; if (*lcpt != '\0') SynErr("Bad syntax in list of numbers!");
1185 ++icnt;
1186 }
1187 Do_volreg_mat = 1; new_stuff++ ;
1188 ++iarg;
1189 continue ; /* go to next arg */
1190 }
1191
1192 if( strcmp(argv[iarg],"-vr_mat_ind") == 0) {
1193 if (++iarg >= argc) SynErr("need 1 argument after -vr_mat_ind!");
1194 volreg_matind = (int)strtol(argv[iarg], &lcpt, 10); if (*lcpt != '\0') SynErr("Bad syntax in number argument!");
1195 ++iarg;
1196 continue ; /* go to next arg */
1197 }
1198
1199 if( strcmp(argv[iarg],"-vr_center_old") == 0) {
1200 if (iarg+3 >= argc) SynErr("need 3 arguments after -vr_center_old");
1201 ++iarg;
1202 center_old[0] = strtod(argv[iarg],&lcpt) ; ++iarg; if (*lcpt != '\0') SynErr("Bad syntax in list of numbers!");
1203 center_old[1] = strtod(argv[iarg],&lcpt) ; ++iarg; if (*lcpt != '\0') SynErr("Bad syntax in list of numbers!");
1204 center_old[2] = strtod(argv[iarg],&lcpt) ; if (*lcpt != '\0') SynErr("Bad syntax in list of numbers!");
1205 Do_center_old = 1; new_stuff++ ;
1206 ++iarg;
1207 continue ; /* go to next arg */
1208 }
1209
1210 if( strcmp(argv[iarg],"-vr_center_base") == 0) {
1211 if (iarg+3 >= argc) SynErr("need 3 arguments after -vr_center_base");
1212 ++iarg;
1213 center_base[0] = strtod(argv[iarg],&lcpt) ; ++iarg; if (*lcpt != '\0') SynErr("Bad syntax in list of numbers!");
1214 center_base[1] = strtod(argv[iarg],&lcpt) ; ++iarg; if (*lcpt != '\0') SynErr("Bad syntax in list of numbers!");
1215 center_base[2] = strtod(argv[iarg],&lcpt) ; if (*lcpt != '\0') SynErr("Bad syntax in list of numbers!");
1216 Do_center_base = 1; new_stuff++ ;
1217 ++iarg;
1218 continue ; /* go to next arg */
1219 }
1220
1221 /** -?del dim **/
1222
1223 if( strncmp(argv[iarg],"-xdel",4) == 0 ){
1224 if( iarg+1 >= argc ) SynErr("need an argument after -xdel!");
1225 xdel = strtod( argv[++iarg] , NULL ) ;
1226 if( xdel <= 0.0 ) SynErr("argument after -xdel must be positive!") ;
1227 new_xdel = 1 ; new_stuff++ ;
1228 geom_change = 1;
1229 iarg++ ; continue ; /* go to next arg */
1230 }
1231
1232 if( strncmp(argv[iarg],"-ydel",4) == 0 ){
1233 if( iarg+1 >= argc ) SynErr("need an argument after -ydel!");
1234 ydel = strtod( argv[++iarg] , NULL ) ;
1235 if( ydel <= 0.0 ) SynErr("argument after -ydel must be positive!") ;
1236 new_ydel = 1 ; new_stuff++ ;
1237 geom_change = 1;
1238 iarg++ ; continue ; /* go to next arg */
1239 }
1240
1241 if( strncmp(argv[iarg],"-zdel",4) == 0 ){
1242 if( iarg+1 >= argc ) SynErr("need an argument after -zdel!");
1243 zdel = strtod( argv[++iarg] , NULL ) ;
1244 if( zdel <= 0.0 ) SynErr("argument after -zdel must be positive!") ;
1245 new_zdel = 1 ; new_stuff++ ;
1246 geom_change = 1;
1247 iarg++ ; continue ; /* go to next arg */
1248 }
1249
1250 if( strncmp(argv[iarg],"-keepcen",7) == 0 ){ /* 17 Jul 2006 */
1251 keepcen = 1 ;
1252 geom_change = 1;
1253 iarg++ ; continue ; /* go to next arg */
1254 }
1255
1256 if( strcmp(argv[iarg],"-verb") == 0 ){
1257 verb++ ; iarg++ ; continue ;
1258 }
1259 if( strcmp(argv[iarg],"-quiet") == 0 ){ /* 18 Dec 2017 */
1260 verb = 0 ; iarg++ ; continue ;
1261 }
1262
1263 if( strncmp(argv[iarg],"-xyzscale",8) == 0 ){ /* 17 Jul 2006 */
1264 if( iarg+1 >= argc ) SynErr("need an argument after -xyzscale!");
1265 xyzscale = strtod( argv[++iarg] , NULL ) ;
1266 if( xyzscale <= 0.0f ) SynErr("argument after -xyzscale must be positive!");
1267 if( xyzscale == 1.0f )
1268 WARNING_message(
1269 "-xyzscale 1.0 really makes no sense, but if that's what you want" ) ;
1270 geom_change = 1;
1271 new_stuff++ ; iarg++ ; continue ; /* go to next arg */
1272 }
1273
1274 /** -TR **/
1275
1276 if( strncmp(argv[iarg],"-TR",3) == 0 ){
1277 char *eptr = "\0" ;
1278 if( ++iarg >= argc ) SynErr("need an argument after -TR!");
1279
1280 if( isalpha(argv[iarg][0]) ||
1281 strstr(argv[iarg],"+orig") != NULL ||
1282 strstr(argv[iarg],"+tlrc") != NULL ||
1283 strstr(argv[iarg],".nii") != NULL ){
1284 THD_3dim_dataset *qset = THD_open_dataset(argv[iarg]) ;
1285 if( qset != NULL ){
1286 DSET_UNMSEC(qset) ;
1287 TR = DSET_TR(qset); tunits = DSET_TIMEUNITS(qset);
1288 DSET_delete(qset) ; new_tunits = (tunits != ILLEGAL_TYPE) ;
1289 if( verb && TR > 0.0f ) INFO_message("new TR will be %g",TR) ;
1290 } else {
1291 ERROR_exit("-TR: can't open '%s' as a dataset",argv[iarg]) ;
1292 }
1293 } else {
1294 TR = strtod( argv[iarg] , &eptr ) ;
1295 }
1296 if( TR <= 0.0 ) SynErr("argument after -TR must give a positive result!") ;
1297
1298 if( strcmp(eptr,"ms")==0 || strcmp(eptr,"msec")==0 ){
1299 new_tunits = 1 ; tunits = UNITS_MSEC_TYPE ;
1300 ERROR_exit("TR expressed in milliseconds is no longer allowed.") ;
1301 } else if( strcmp(eptr,"s")==0 || strcmp(eptr,"sec")==0 ){
1302 new_tunits = 1 ; tunits = UNITS_SEC_TYPE ;
1303 } else if( strcmp(eptr,"Hz")==0 || strcmp(eptr,"Hertz")==0 ){
1304 new_tunits = 1 ; tunits = UNITS_HZ_TYPE ;
1305 }
1306
1307 new_TR = 1 ; new_stuff++ ;
1308 iarg++ ; continue ; /* go to next arg */
1309 }
1310
1311 /** -Tslices [18 Dec 2018] **/
1312
1313 #define IS_NUMERIC(sss) \
1314 ( ( isdigit((sss)[0]) ) || \
1315 ( (sss)[0] == '.' && isdigit((sss)[1]) ) || \
1316 ( (sss)[0] == '-' && isdigit((sss)[1]) ) || \
1317 ( (sss)[0] == '-' && (sss)[1] == '.' && isdigit((sss)[2]) ) )
1318
1319 if( strcasecmp(argv[iarg],"-Tslices") == 0 ){
1320 int ival ; float val , fac=1.0f ; char *cpt , *thisopt=argv[iarg];
1321 if( new_toff_sl > 0 )
1322 ERROR_exit("You cannot use -notoff and -Tslices in the same 3drefit command!") ;
1323 if( new_Tslices > 0 )
1324 ERROR_exit("You cannot uses option '%s' twice!",argv[iarg]) ;
1325 if( ++iarg >= argc )
1326 ERROR_exit("Option '%s' cannot be the last value on command line!",thisopt) ;
1327 if( argv[iarg][0] == '*' && IS_NUMERIC(argv[iarg]+1) ){
1328 fac = (float)strtod(argv[iarg]+1,&cpt ) ;
1329 if( fac <= 0.0f )
1330 ERROR_exit("Factor '%s' after option '%s' is illegal :(",argv[iarg],thisopt) ;
1331 iarg++ ;
1332 #if 0
1333 INFO_message("Set %s factor to %g",thisopt,fac) ;
1334 #endif
1335 }
1336 for( ival=0 ; iarg+ival < argc && IS_NUMERIC(argv[iarg+ival]) ; ival++ ){
1337 val = (float)strtod(argv[iarg+ival], &cpt ) ;
1338 if( cpt == argv[iarg+ival] ) break ; /* something bad */
1339 Tslices = (float *)realloc( Tslices , sizeof(float)*(ival+1) ) ;
1340 Tslices[ival] = fac * val ;
1341 if( val < 0.0f )
1342 WARNING_message("Value '%s' (#%d after option '%s') is negative :(",
1343 argv[iarg+ival] , iarg+1 , thisopt ) ;
1344 }
1345 new_Tslices = ival ;
1346 if( new_Tslices == 0 )
1347 ERROR_exit("No number values found after option '%s' :(",thisopt) ;
1348 else if( new_Tslices == 1 )
1349 ERROR_exit("Only one number value found after option '%s' :(",thisopt) ;
1350 #if 0
1351 { int qq ; fprintf(stderr,"%s values:",thisopt) ;
1352 for( qq=0 ; qq < new_Tslices ; qq++ ) fprintf(stderr," %g",Tslices[qq]) ;
1353 fprintf(stderr,"\n") ; }
1354 #endif
1355 iarg += ival ; new_stuff++ ;continue ;
1356 }
1357
1358 /** -notoff (12 Feb 2001) **/
1359
1360 if( strncmp(argv[iarg],"-notoff",7) == 0 ){
1361 if( new_Tslices > 0 )
1362 ERROR_exit("You cannot use -notoff and -Tslices in the same 3drefit command!") ;
1363 new_toff_sl = 1 ; new_stuff++ ;
1364 iarg++ ; continue ; /* go to next arg */
1365 }
1366
1367 /** -Torg (29 Jan 2003) **/
1368
1369 if( strncmp(argv[iarg],"-Torg",5) == 0 ){
1370 char *eptr ;
1371 if( iarg+1 >= argc ) SynErr("need an argument after -Torg!");
1372 Torg = strtod( argv[++iarg] , &eptr ) ;
1373 if( *eptr != '\0' )
1374 WARNING_message("-Torg %s ends in unexpected character\n",argv[iarg]) ;
1375 new_Torg = 1 ; new_stuff++ ;
1376 iarg++ ; continue ; /* go to next arg */
1377 }
1378
1379 /** -newid **/
1380
1381 if( strncmp(argv[iarg],"-newid",4) == 0 ){
1382 new_idcode = 1 ; new_stuff++ ;
1383 iarg++ ; continue ; /* go to next arg */
1384 }
1385
1386 /** -nowarp **/
1387
1388 if( strncmp(argv[iarg],"-nowarp",6) == 0 ){
1389 new_nowarp = 1 ; new_stuff++ ;
1390 iarg++ ; continue ; /* go to next arg */
1391 }
1392
1393 /** -statpar x x x **/
1394
1395 if( strncmp(argv[iarg],"-statpar",4) == 0 ){
1396 float val ; char * ptr ;
1397
1398 if( ++iarg >= argc ) SynErr("need an argument after -statpar!") ;
1399
1400 for( ii=0 ; ii < MAX_STAT_AUX ; ii++ ) stataux[ii] = 0.0 ;
1401
1402 ii = 0 ;
1403 do{
1404 val = strtod( argv[iarg] , &ptr ) ;
1405 if( *ptr != '\0' ) break ;
1406 stataux[ii++] = val ;
1407 iarg++ ;
1408 } while( iarg < argc ) ;
1409
1410 if( ii == 0 ) SynErr("No numbers given after -statpar?") ;
1411
1412 new_stataux = 1 ; new_stuff++ ;
1413 continue ;
1414 }
1415
1416 /** -markers **/
1417
1418 if( strncmp(argv[iarg],"-markers",4) == 0 ){
1419 new_markers = 1 ; new_stuff++ ;
1420 iarg++ ; continue ; /* go to next arg */
1421 }
1422
1423 /** -label2 [21 Dec 2004] **/
1424
1425 if( strcmp(argv[iarg],"-label2") == 0 ){
1426 new_label2 = argv[++iarg] ; new_stuff++ ;
1427 iarg++ ; continue ; /* go to next arg */
1428 }
1429
1430 /** -labeltable [25 Feb 2010 ZSS] **/
1431
1432 if( strcmp(argv[iarg],"-labeltable") == 0 ){
1433 labeltable = argv[++iarg] ; new_stuff++ ;
1434 iarg++ ; continue ; /* go to next arg */
1435 }
1436
1437 /** -view code **/
1438
1439 if( strncmp(argv[iarg],"-view",4) == 0 ){
1440 char * code ;
1441 if( iarg+1 >= argc ) SynErr("need an argument after -view!") ;
1442 code = argv[++iarg] ; if( code[0] == '+' ) code++ ;
1443 for( vtype=0 ; vtype <= LAST_VIEW_TYPE ; vtype++ )
1444 if( strcmp(code,VIEW_codestr[vtype]) == 0 ) break ;
1445 if( vtype > LAST_VIEW_TYPE ) SynErr("argument after -view is illegal!") ;
1446 new_view = 1 ; new_stuff++ ;
1447 iarg++ ; continue ; /* go to next arg */
1448 }
1449
1450 /* tag options 08 May 2006 [rickr] */
1451
1452 /* -shift_tags, apply -d?origin to tags */
1453 if( strncmp(argv[iarg],"-shift_tags",11) == 0 ){
1454 shift_tags = 1 ;
1455 iarg++ ; continue ; /* go to next arg */
1456 }
1457
1458 if( strncmp(argv[iarg],"-dxtag",6) == 0 ){
1459 if( ++iarg >= argc ) SynErr("need an argument after -dxtag!");
1460 dxtag = strtod(argv[iarg],NULL) ;
1461 new_tags = 1 ; new_stuff++ ;
1462 iarg++ ; continue ; /* go to next arg */
1463 }
1464
1465 if( strncmp(argv[iarg],"-dytag",6) == 0 ){
1466 if( ++iarg >= argc ) SynErr("need an argument after -dytag!");
1467 dytag = strtod(argv[iarg],NULL) ;
1468 new_tags = 1 ; new_stuff++ ;
1469 iarg++ ; continue ; /* go to next arg */
1470 }
1471
1472 if( strncmp(argv[iarg],"-dztag",6) == 0 ){
1473 if( ++iarg >= argc ) SynErr("need an argument after -dztag!");
1474 dztag = strtod(argv[iarg],NULL) ;
1475 new_tags = 1 ; new_stuff++ ;
1476 iarg++ ; continue ; /* go to next arg */
1477 }
1478
1479 /*----- -deoblique option [20 Jun 2007] -----*/
1480
1481 if( strcmp(argv[iarg],"-deoblique") == 0 ){
1482 deoblique = 1 ;
1483 THD_set_oblique_report(0,0); /* turn off obliquity warning */
1484 new_stuff++ ; iarg++ ; continue ; /* go to next arg */
1485 }
1486
1487 /*----- -oblique_origin option [01 Dec 2008] -----*/
1488
1489 if( strcmp(argv[iarg],"-oblique_origin") == 0 ){
1490 use_oblique_origin = 1 ;
1491 THD_set_oblique_report(0,0); /* turn off obliquity warning */
1492 new_stuff++ ; iarg++ ; continue ; /* go to next arg */
1493 }
1494
1495 /*----- -space option [16 Mar 2009] -----*/
1496
1497 if( strcmp(argv[iarg],"-space") == 0 ){
1498 space = 1 ;
1499 spacename = argv[++iarg] ;
1500 new_stuff++ ; iarg++ ; continue ; /* go to next arg */
1501 }
1502
1503 /*----- -cmap option [31 Mar 2009] -----*/
1504 if( strcmp(argv[iarg],"-cmap") == 0 ){
1505 if( ++iarg >= argc ) SynErr("need an argument after -cmap!");
1506 if(strcmp(argv[iarg],"CONT_CMAP")==0)
1507 cmap = CONT_CMAP;
1508
1509 else {
1510 if(strcmp(argv[iarg],"INT_CMAP")==0) cmap = INT_CMAP;
1511 else {
1512 if(strcmp(argv[iarg],"SPARSE_CMAP")==0) cmap = SPARSE_CMAP;
1513 else SynErr("cmap value not valid");
1514 }
1515 }
1516 new_stuff++ ; iarg++ ; continue ; /* go to next arg */
1517 }
1518
1519 /** anything else must be a -type **/
1520 /* try the anatomy prefixes */
1521
1522 for( ii=FIRST_ANAT_TYPE ; ii <= LAST_ANAT_TYPE ; ii++ )
1523 if( strncmp( &(argv[iarg][1]) ,
1524 ANAT_prefixstr[ii] , THD_MAX_PREFIX ) == 0 ) break ;
1525
1526 /* fprintf(stderr,"== have type %d\n", ii); */
1527
1528 if( ii <= LAST_ANAT_TYPE ){
1529 ftype = ii ;
1530 dtype = HEAD_ANAT_TYPE ;
1531 nvals = ANAT_nvals[ftype] ;
1532 new_type = 1 ; new_stuff++ ;
1533 iarg++ ; continue ;
1534 }
1535
1536 /* try the function prefixes */
1537
1538 for( ii=FIRST_FUNC_TYPE ; ii <= LAST_FUNC_TYPE ; ii++ )
1539 if( strncmp( &(argv[iarg][1]) ,
1540 FUNC_prefixstr[ii] , THD_MAX_PREFIX ) == 0 ) break ;
1541
1542 if( ii <= LAST_FUNC_TYPE ){
1543 ftype = ii ;
1544 dtype = HEAD_FUNC_TYPE ;
1545 nvals = FUNC_nvals[ftype] ;
1546 new_type = 1 ; new_stuff++ ;
1547 iarg++ ; continue ;
1548 }
1549
1550 /** error **/
1551
1552 { char str[256] ;
1553 sprintf(str,"Unknown option %s. Check 3drefit -help.",argv[iarg]) ;
1554 ERROR_message(str);
1555 suggest_best_prog_option(argv[0], argv[iarg]);
1556 exit(1);
1557 }
1558
1559 } /* end of loop over switches */
1560 if (iarg < 2) Syntax(1) ;
1561
1562 /*-- some checks for erroneous inputs --*/
1563
1564 if( new_stuff == 0 && atrmod == 0 ) SynErr("No options given!?") ;
1565 if( new_stuff == 1 && atrmod == 1 ){ /* 28 Jul 2006 [rickr] */
1566 fprintf(stderr,"** Cannot use -atrcopy or -atrstring with other "
1567 "modification options.\n");
1568 SynErr("Illegal attribute syntax.");
1569 }
1570 if( iarg >= argc ) SynErr("No datasets given!?") ;
1571
1572 if( xyzscale != 0.0f &&
1573 (new_orient || new_xorg || new_yorg || new_zorg ||
1574 keepcen || new_xdel || new_ydel || new_zdel ) ){ /* 18 Jul 2006 */
1575 SynErr(
1576 "-xyzscale is incompatible with other options for changing voxel grid");
1577 }
1578
1579 if( obl_recenter && /* 17 Mar 2020 [rickr] */
1580 (new_orient || new_xorg || new_yorg || new_zorg ||
1581 keepcen || new_xdel || new_ydel || new_zdel ) ){
1582 SynErr(
1583 "-oblique_recenter is not compatible with other voxel grid modifications");
1584 }
1585
1586 if( new_orient && (dxorg || dyorg || dzorg) ) /* 02 Mar 2000 */
1587 SynErr("Can't use -orient with -d?origin!?") ;
1588
1589 if( new_tags || shift_tags ){ /* 08 May 2006 [rickr] */
1590 if( new_tags && shift_tags )
1591 SynErr("Cant' use -shift_tags with -d{xyz}tag") ;
1592 if( new_orient )
1593 SynErr("Can't use -orient with -shift_tags or -d{xyz}tags") ;
1594 if( shift_tags && !dxorg && !dyorg && !dzorg )
1595 SynErr("-shift_tags option requires a -d{xyz}origin option") ;
1596
1597 if( shift_tags ){ /* then copy shifts to tag vars */
1598 if( dxorg ) dxtag = xorg ;
1599 if( dyorg ) dytag = yorg ;
1600 if( dzorg ) dztag = zorg ;
1601 }
1602 }
1603
1604 /*--- process datasets ---*/
1605 for( ; iarg < argc ; iarg++ ){
1606 write_output = False ; /* some datasets will be overwritten */
1607 did_something = 0 ;
1608
1609 dset = THD_open_one_dataset( argv[iarg] ) ;
1610 if( dset == NULL ){
1611 ERROR_message("Can't open dataset %s\n",argv[iarg]) ;
1612 continue ;
1613 }
1614 if( DSET_IS_MINC(dset) ){
1615 ERROR_message("Can't process MINC dataset %s\n",argv[iarg]);
1616 continue ;
1617 }
1618 if( DSET_IS_ANALYZE(dset) ){
1619 ERROR_message("Can't process ANALYZE dataset %s\n",argv[iarg]);
1620 continue ;
1621 }
1622 if( DSET_IS_1D(dset) ){
1623 ERROR_message("Can't process 1D dataset %s\n",argv[iarg]);
1624 continue ;
1625 }
1626 if( DSET_IS_CTFMRI(dset) || DSET_IS_CTFSAM(dset) ){
1627 ERROR_message("Can't process CTF dataset %s\n",argv[iarg]);
1628 continue ;
1629 }
1630 if( DSET_IS_MPEG(dset) ){
1631 ERROR_message("Can't process MPEG dataset %s\n",argv[iarg]);
1632 continue ;
1633 }
1634
1635 /* any surviving non-AFNI dataset needs the data written out */
1636 if( IS_VALID_NON_AFNI_DSET(dset) ){
1637 write_output = True ; /* 13 Jul 2006 [rickr] */
1638 }
1639
1640 INFO_message("Processing AFNI dataset %s\n",argv[iarg]) ;
1641
1642 /*-- First off: check the axes for consistency --*/
1643
1644 if( do_checkaxes ){
1645 THD_dataxes *copy_dax , *orig_dax ; float dif ;
1646 orig_dax = dset->daxes ;
1647 copy_dax = (THD_dataxes *)malloc(sizeof(THD_dataxes)) ;
1648 memcpy( copy_dax , orig_dax , sizeof(THD_dataxes) ) ;
1649 LOAD_ZERO_MAT( copy_dax->to_dicomm ) ;
1650 THD_daxes_to_mat44( copy_dax ) ;
1651
1652 dif = MAT44_FLDIF( orig_dax->ijk_to_dicom , copy_dax->ijk_to_dicom ) ;
1653 if( dif > 0.001f ){
1654 WARNING_message("===== ijk_to_dicom from dataset header and from axes differ") ;
1655 DUMP_MAT44("ijk_to_dicom from dataset header",orig_dax->ijk_to_dicom) ;
1656 DUMP_MAT44("ijk_to_dicom from dataset axes" ,copy_dax->ijk_to_dicom) ;
1657 } else {
1658 INFO_message ("===== ijk_to_dicom from dataset header and from axes are equivalent") ;
1659 DUMP_MAT44("ijk_to_dicom from dataset header",orig_dax->ijk_to_dicom) ;
1660 }
1661
1662 dif = MAT44_FLDIF( orig_dax->dicom_to_ijk , copy_dax->dicom_to_ijk ) ;
1663 if( dif > 0.001f ){
1664 WARNING_message("===== dicom_to_ijk from dataset header and from axes differ") ;
1665 DUMP_MAT44("dicom_to_ijk from dataset header",orig_dax->dicom_to_ijk) ;
1666 DUMP_MAT44("dicom_to_ijk from dataset axes" ,copy_dax->dicom_to_ijk) ;
1667 } else {
1668 INFO_message ("===== dicom_to_ijk from dataset header and from axes are equivalent") ;
1669 DUMP_MAT44("dicom_to_ijk from dataset header",orig_dax->dicom_to_ijk) ;
1670 }
1671
1672 dif = MAT44_FLDIF( orig_dax->ijk_to_dicom , orig_dax->ijk_to_dicom_real ) ;
1673 if( dif > 0.001f ){
1674 WARNING_message("===== ijk_to_dicom and ijk_to_dicom_real from dataset header differ") ;
1675 DUMP_MAT44("ijk_to_dicom from dataset header",orig_dax->ijk_to_dicom) ;
1676 DUMP_MAT44("ijk_to_dicom_real from dataset header",orig_dax->ijk_to_dicom_real) ;
1677 } else {
1678 DUMP_MAT44("ijk_to_dicom from dataset header",orig_dax->ijk_to_dicom) ;
1679 INFO_message ("===== ijk_to_dicom and ijk_to_dicom_real from dataset header are equivalent") ;
1680 }
1681
1682 if( new_stuff == 1 ){ DSET_delete(dset) ; continue ; } /* nothing else to do */
1683 }
1684
1685 tross_Make_History( "3drefit" , argc,argv, dset ) ;
1686
1687 /* 21 Dec 2004: -label2 option */
1688
1689 if( new_label2 != NULL ){
1690 EDIT_dset_items( dset , ADN_label2 , new_label2 , ADN_none ) ;
1691 VINFO("setting label2") ;
1692 did_something++ ; /* 30 Mar 2010 */
1693 }
1694
1695 if(labeltable != NULL) {
1696 char *str = NULL;
1697 Dtable *vl_dtable=NULL ;
1698
1699 if (dset->Label_Dtable) {
1700 destroy_Dtable(dset->Label_Dtable); dset->Label_Dtable=NULL;
1701 }
1702 /* read the table */
1703 if (!(str = AFNI_suck_file( labeltable))) {
1704 ERROR_exit("Failed to read %s", labeltable);
1705 }
1706 if (!(vl_dtable = Dtable_from_nimlstring(str))) {
1707 ERROR_exit("Could not parse labeltable");
1708 }
1709 destroy_Dtable(vl_dtable); vl_dtable = NULL;
1710 THD_set_string_atr( dset->dblk , "VALUE_LABEL_DTABLE" , str ) ;
1711 VINFO("setting labeltable") ;
1712 free(str);
1713 did_something++ ; /* 30 Mar 2010 */
1714 }
1715
1716 /* 14 Oct 1999: change anat parent */
1717 /* 14 Dec 1999: allow special cases: SELF and NULL */
1718
1719 if( aset != NULL ){
1720 EDIT_dset_items( dset , ADN_anat_parent , aset , ADN_none ) ;
1721 VINFO("setting Anat parent") ;
1722 did_something++ ; /* 30 Mar 2010 */
1723 } else if( aset_code == ASET_SELF ){
1724 EDIT_dset_items( dset , ADN_anat_parent , dset , ADN_none ) ;
1725 VINFO("setting Anat parent") ;
1726 did_something++ ; /* 30 Mar 2010 */
1727 } else if( aset_code == ASET_NULL ){
1728 EDIT_ZERO_ANATOMY_PARENT_ID( dset ) ;
1729 dset->anat_parent_name[0] = '\0' ;
1730 VINFO("clearing Anat parent") ;
1731 did_something++ ; /* 30 Mar 2010 */
1732 }
1733
1734 /* ZSS June 06, add a warp parent field please */
1735 if( waset != NULL ){
1736 EDIT_dset_items( dset , ADN_warp_parent , waset , ADN_none ) ;
1737 VINFO("setting Warp parent") ;
1738 did_something++ ; /* 30 Mar 2010 */
1739 } else if( waset_code == ASET_SELF ){
1740 EDIT_dset_items( dset , ADN_warp_parent , dset , ADN_none ) ;
1741 VINFO("setting Warp parent") ;
1742 did_something++ ; /* 30 Mar 2010 */
1743 } else if( waset_code == ASET_NULL ){
1744 EDIT_ZERO_ANATOMY_PARENT_ID( dset ) ;
1745 dset->warp_parent_name[0] = '\0' ;
1746 VINFO("clearing Warp parent") ;
1747 did_something++ ; /* 30 Mar 2010 */
1748 }
1749 /* Oct 04/02: zmodify volreg fields */
1750 if (Do_volreg_mat) {
1751 sprintf(str,"VOLREG_MATVEC_%06d", volreg_matind) ;
1752 if( verb ) ININFO_message("Modifying %s ...\n", str);
1753 THD_set_float_atr( dset->dblk , str , 12 , volreg_mat ) ;
1754 did_something++ ; /* 30 Mar 2010 */
1755 }
1756
1757 if (Do_center_old) {
1758 VINFO("Modifying VOLREG_CENTER_OLD ...\n");
1759 THD_set_float_atr( dset->dblk , "VOLREG_CENTER_OLD" , 3 , center_old ) ;
1760 did_something++ ; /* 30 Mar 2010 */
1761 }
1762
1763 if (Do_center_base) {
1764 VINFO("Modifying VOLREG_CENTER_BASE ...\n");
1765 THD_set_float_atr( dset->dblk , "VOLREG_CENTER_BASE" , 3 , center_base ) ;
1766 did_something++ ; /* 30 Mar 2010 */
1767 }
1768
1769 /* 28 May 2002: clear brick stats */
1770
1771 if( clear_bstat ){
1772 if( !ISVALID_STATISTIC(dset->stats) ){
1773 WARNING_message("-clear_bstat: dataset has no brick statistics\n") ;
1774 } else {
1775 KILL_STATISTIC(dset->stats) ;
1776 REMOVEFROM_KILL( dset->kl , dset->stats ) ;
1777 REMOVEFROM_KILL( dset->kl , dset->stats->bstat ) ;
1778 dset->stats = NULL ;
1779 VINFO("clearing brick statistics") ;
1780 did_something++ ; /* 30 Mar 2010 */
1781 }
1782 }
1783
1784 if( redo_bstat ){
1785 VINFO("reloading brick statistics") ;
1786 THD_load_statistics( dset ) ; /* 01 Feb 2005 */
1787 did_something++ ; /* 30 Mar 2010 */
1788 }
1789
1790 if( new_byte_order > 0 ){
1791 VINFO("changing byte order") ;
1792 dset->dblk->diskptr->byte_order = new_byte_order ; /* 25 April 1998 */
1793 did_something++ ; /* 30 Mar 2010 */
1794 }
1795
1796 /*-- change space axes (lots of possibilities here) --*/
1797
1798 daxes = dset->daxes ;
1799
1800 if( new_orient ){
1801 VINFO("changing orientation codes") ;
1802 daxes->xxorient = xxor ;
1803 daxes->yyorient = yyor ;
1804 daxes->zzorient = zzor ;
1805 did_something++ ; /* 30 Mar 2010 */
1806 }
1807
1808 if( xyzscale > 0.0f ){ /* 18 Jul 2006 */
1809 float dxp = daxes->xxdel * xyzscale ; /* new grid */
1810 float dyp = daxes->yydel * xyzscale ; /* spacings */
1811 float dzp = daxes->zzdel * xyzscale ;
1812 int rl = abs(THD_get_axis_direction(daxes,ORI_R2L_TYPE)) ;
1813 int ap = abs(THD_get_axis_direction(daxes,ORI_A2P_TYPE)) ;
1814 int is = abs(THD_get_axis_direction(daxes,ORI_I2S_TYPE)) ;
1815 float xop , yop , zop ;
1816 static float shift[3] ;
1817
1818 VINFO("applying -xyzscale") ;
1819
1820 if( rl == 0 || ap == 0 || is == 0 )
1821 ERROR_exit("-xyzscale: Indeterminate axis directions!") ;
1822
1823 if( ndone == 0 ){ /* for the first dataset */
1824 float op[3] , oo[3] ;
1825 op[0] = xop = daxes->xxorg + (daxes->xxdel-dxp)*0.5f*(daxes->nxx-1) ;
1826 op[1] = yop = daxes->yyorg + (daxes->yydel-dyp)*0.5f*(daxes->nyy-1) ;
1827 op[2] = zop = daxes->zzorg + (daxes->zzdel-dzp)*0.5f*(daxes->nzz-1) ;
1828 oo[0] = daxes->xxorg ;
1829 oo[1] = daxes->yyorg ;
1830 oo[2] = daxes->zzorg ;
1831 shift[0] = op[rl-1] - xyzscale * oo[rl-1] ; /* RL shift */
1832 shift[1] = op[ap-1] - xyzscale * oo[ap-1] ; /* AP shift */
1833 shift[2] = op[is-1] - xyzscale * oo[is-1] ; /* IS shift */
1834
1835 } else { /* for later datasets */
1836
1837 xop = xyzscale * daxes->xxorg + shift[daxes->xxorient/2] ;
1838 yop = xyzscale * daxes->yyorg + shift[daxes->yyorient/2] ;
1839 zop = xyzscale * daxes->zzorg + shift[daxes->zzorient/2] ;
1840 }
1841
1842 daxes->xxdel = dxp ; daxes->yydel = dyp ; daxes->zzdel = dzp ;
1843 daxes->xxorg = xop ; daxes->yyorg = yop ; daxes->zzorg = zop ;
1844 did_something++ ; /* 30 Mar 2010 */
1845 }
1846
1847 if( !new_xorg ) xorg = fabs(daxes->xxorg) ;
1848 if( !new_yorg ) yorg = fabs(daxes->yyorg) ;
1849 if( !new_zorg ) zorg = fabs(daxes->zzorg) ;
1850
1851 if( !new_xdel ) xdel = fabs(daxes->xxdel) ;
1852 if( !new_ydel ) ydel = fabs(daxes->yydel) ;
1853 if( !new_zdel ) zdel = fabs(daxes->zzdel) ;
1854
1855 /* 17 Jul 2006 - deal with the '-keepcen' option */
1856
1857 if( keepcen && !new_xdel && !new_ydel && !new_zdel ){
1858 WARNING_message("-keepcen needs at least one of -xdel, -ydel, -zdel") ;
1859 keepcen = 0 ;
1860 }
1861 if( keepcen && (new_xorg || new_yorg || new_zorg || new_orient) ){
1862 WARNING_message(
1863 "-keepcen incompatible with explicit origin or orientation changes") ;
1864 keepcen = 0 ;
1865 }
1866 if( keepcen ){
1867 VINFO("applying -keepcen") ;
1868 if( new_xdel ){
1869 dxorg = 1 ; xorg = 0.5f*(daxes->nxx-1)*(fabs(daxes->xxdel)-xdel) ;
1870 if( ORIENT_sign[daxes->xxorient] == '-' ) xorg = -xorg ;
1871 }
1872 if( new_ydel ){
1873 dyorg = 1 ; yorg = 0.5f*(daxes->nyy-1)*(fabs(daxes->yydel)-ydel) ;
1874 if( ORIENT_sign[daxes->yyorient] == '-' ) yorg = -yorg ;
1875 }
1876 if( new_zdel ){
1877 dzorg = 1 ; zorg = 0.5f*(daxes->nzz-1)*(fabs(daxes->zzdel)-zdel) ;
1878 if( ORIENT_sign[daxes->zzorient] == '-' ) zorg = -zorg ;
1879 }
1880 }
1881
1882 if( cxorg ) xorg = 0.5 * (daxes->nxx - 1) * xdel ;
1883 if( cyorg ) yorg = 0.5 * (daxes->nyy - 1) * ydel ;
1884 if( czorg ) zorg = 0.5 * (daxes->nzz - 1) * zdel ;
1885
1886 if( dxorg )
1887 { daxes->xxorg += xorg ; did_something++ ; }
1888 else if( duporg || new_xorg==2 )
1889 { daxes->xxorg = xorg ; did_something++ ; }
1890 else if( new_xorg==1 || new_orient )
1891 { daxes->xxorg = (ORIENT_sign[daxes->xxorient] == '+') ? (-xorg) : (xorg) ; did_something++ ; }
1892
1893 if( dyorg )
1894 { daxes->yyorg += yorg ; did_something++ ; }
1895 else if( duporg || new_yorg==2 )
1896 { daxes->yyorg = yorg ; did_something++ ; }
1897 else if( new_yorg==1 || new_orient )
1898 { daxes->yyorg = (ORIENT_sign[daxes->yyorient] == '+') ? (-yorg) : (yorg) ; did_something++ ; }
1899
1900 if( dzorg )
1901 { daxes->zzorg += zorg ; did_something++ ; }
1902 else if( duporg || new_zorg==2 )
1903 { daxes->zzorg = zorg ; did_something++ ; }
1904 else if( new_zorg==1 || new_orient )
1905 { daxes->zzorg = (ORIENT_sign[daxes->zzorient] == '+') ? (-zorg) : (zorg) ; did_something++ ; }
1906
1907 if( new_xdel || new_orient )
1908 { daxes->xxdel = (ORIENT_sign[daxes->xxorient] == '+') ? (xdel) : (-xdel) ; did_something++ ; }
1909
1910 if( new_ydel || new_orient )
1911 { daxes->yydel = (ORIENT_sign[daxes->yyorient] == '+') ? (ydel) : (-ydel) ; did_something++ ; }
1912
1913 if( new_zdel || new_orient )
1914 { daxes->zzdel = (ORIENT_sign[daxes->zzorient] == '+') ? (zdel) : (-zdel) ; did_something++ ; }
1915
1916 /* shift ijk_to_dicom xyz=0,0,0 to match ijk_to_dicom_real=0,0,0, and */
1917 /* round to voxel center if not _raw version [23 Mar 2020 rickr] */
1918 if( obl_recenter ) {
1919 THD_fvec3 coords={{0.0, 0.0, 0.0}}; /* dicom 0,0,0 */
1920
1921 /* map 0,0,0 from scanner to cardinalized coords */
1922 if( THD_dicom_real_to_card(dset, & coords, obl_recenter==2) )
1923 ERROR_exit("-oblique_recenter failure");
1924
1925 /* convert from dicom to to dataset coords (permute) */
1926 coords = THD_dicomm_to_3dmm(dset, coords);
1927
1928 /* and subtract to re-center */
1929 daxes->xxorg -= coords.xyz[0];
1930 daxes->yyorg -= coords.xyz[1];
1931 daxes->zzorg -= coords.xyz[2];
1932
1933 INFO_message("shifting origin by %g %g %g",
1934 -coords.xyz[0], -coords.xyz[1], -coords.xyz[2]);
1935
1936 did_something++;
1937 }
1938
1939 /*-- deoblique - assume the data is cardinal 6/20/2007 */
1940 /* this should be after any other axis,
1941 orientation, origin, voxel size changes */
1942 if(deoblique || geom_change) { /* geom_change 04 Nov 2011 mod drg */
1943 /* replace transformation matrix with cardinal form */
1944 /* lose obliquity if using 3dWarp for any transformation */
1945 /* recompute Tc (Cardinal transformation matrix for new grid output */
1946 THD_make_cardinal(dset);
1947 VINFO("deoblique") ;
1948 did_something++ ; /* 30 Mar 2010 */
1949 }
1950
1951
1952 /* if user has selected, get origin from obliquity */
1953 /* overriding all the previous command-line options */
1954 if(use_oblique_origin){
1955 Obliquity_to_coords(dset);
1956 VINFO("oblique origin") ;
1957 did_something++ ; /* 30 Mar 2010 */
1958 }
1959
1960 /* set the space of the dataset */
1961 if(space) {
1962 int old_vtype = dset->view_type ;
1963 /* check if trying to assign a non-orig space to orig view data */
1964 if( strcmp("orig",VIEW_codestr[old_vtype]) == 0 ) {
1965 if(strncmp(spacename, "ORIG", 4)!=0){
1966 WARNING_message("Changing the space of an ORIG view dataset may cause confusion!");
1967 WARNING_message(" NIFTI copies will be interpreted as TLRC view (not TLRC space).");
1968 WARNING_message(" Consider changing the view of the dataset to TLRC view also");
1969 }
1970 }
1971 /* check if trying to assign orig space to tlrc view data */
1972 else if( strcmp("tlrc",VIEW_codestr[old_vtype]) == 0 ) {
1973 if(strncmp(spacename, "ORIG", 4)==0){
1974 WARNING_message("Changing the space of a TLRC view dataset to an ORIG type may cause confusion!");
1975 WARNING_message(" NIFTI copies will be interpreted as ORIG view.");
1976 WARNING_message(" Consider changing the view of the dataset to ORIG view also");
1977 }
1978 }
1979 /* actually update the space */
1980 MCW_strncpy(dset->atlas_space, spacename, THD_MAX_NAME);
1981 did_something++;
1982 }
1983
1984 /* set the colormap type of the dataset */
1985 if(cmap>=0)
1986 {
1987 dset->int_cmap = cmap;
1988 did_something++;
1989 }
1990
1991 /*-- change time axis --*/
1992
1993 if( new_TR ){
1994 if( dset->taxis == NULL ){
1995 if( DSET_NVALS(dset) < 2 ){
1996 WARNING_message("Can't process -TR for this dataset!") ;
1997 } else {
1998 WARNING_message("Adding time axis to this dataset") ;
1999 EDIT_dset_items( dset ,
2000 ADN_ntt , DSET_NVALS(dset) ,
2001 ADN_ttdel , TR ,
2002 ADN_tunits, UNITS_SEC_TYPE ,
2003 ADN_nsl , 0 ,
2004 ADN_none ) ;
2005 did_something++ ; /* 30 Mar 2010 */
2006 }
2007 } else {
2008 float frac = TR / dset->taxis->ttdel ;
2009 int ii ;
2010
2011 VINFO("changing TR") ;
2012 dset->taxis->ttdel = TR ;
2013 if( new_tunits ) dset->taxis->units_type = tunits ;
2014 if( dset->taxis->nsl > 0 ){
2015 for( ii=0 ; ii < dset->taxis->nsl ; ii++ )
2016 dset->taxis->toff_sl[ii] *= frac ;
2017 }
2018 did_something++ ; /* 30 Mar 2010 */
2019 }
2020 }
2021
2022 if( new_Torg ){ /* 29 Jan 2003 */
2023 if( dset->taxis == NULL ){
2024 WARNING_message("Can't process -Torg for this dataset!\n") ;
2025 } else {
2026 VINFO("changing Torg") ;
2027 dset->taxis->ttorg = Torg ;
2028 did_something++ ; /* 30 Mar 2010 */
2029 }
2030 }
2031
2032 if( new_toff_sl ){ /* 12 Feb 2001 */
2033 if( dset->taxis == NULL ){
2034 WARNING_message("-notoff: dataset has no time axis to clear!\n") ;
2035 } else if( dset->taxis->nsl <= 0 ){
2036 WARNING_message("-notoff: dataset has no time-offsets to clear!\n") ;
2037 } else {
2038 VINFO("clearing slice time offsets") ;
2039 EDIT_dset_items( dset , ADN_nsl,0 , ADN_none ) ;
2040 did_something++ ; /* 30 Mar 2010 */
2041 }
2042 }
2043
2044 if( new_Tslices > 0 ){ /* 18 Dec 2018 */
2045 if( dset->taxis == NULL ){
2046 WARNING_message("-Tslices: dataset has no time axis to add slice offset to!") ;
2047 } else {
2048 int qq ; float dt=DSET_TR(dset) ;
2049 if( dset->taxis->nsl > 0 )
2050 WARNING_message("-Tslices: altering existing slice offsets!") ;
2051 else
2052 VINFO("setting slice time offsets") ;
2053 EDIT_dset_items( dset ,
2054 ADN_nsl , new_Tslices ,
2055 ADN_toff_sl , Tslices ,
2056 ADN_none ) ;
2057 if( new_Tslices != dset->daxes->nzz )
2058 WARNING_message("-Tslices count %d is different than number of slices %d",
2059 new_Tslices , dset->daxes->nzz ) ;
2060 for( qq=0 ; qq < new_Tslices ; qq++ ){
2061 if( Tslices[qq] >= dt )
2062 WARNING_message("-Tslices value %g (#%d) is %s TR=%g",
2063 Tslices[qq] , qq+1 ,
2064 (Tslices[qq] == dt) ? "equal to" : "greater than" ,
2065 dt ) ;
2066 }
2067 did_something++ ;
2068 }
2069 }
2070
2071 if( (new_orient || new_zorg) && dset->taxis != NULL && dset->taxis->nsl > 0 ){
2072 VINFO("changing time axis slice offset z-origin") ;
2073 dset->taxis->zorg_sl = daxes->zzorg ;
2074 did_something++ ; /* 30 Mar 2010 */
2075 }
2076
2077 if( (new_orient || new_zdel) && dset->taxis != NULL && dset->taxis->nsl > 0 ){
2078 VINFO("changing time axis slice offset z-spacing") ;
2079 dset->taxis->dz_sl = daxes->zzdel ;
2080 did_something++ ; /* 30 Mar 2010 */
2081 }
2082
2083 if( new_idcode ){
2084 VINFO("changing ID code") ;
2085 dset->idcode = MCW_new_idcode() ;
2086 did_something++ ; /* 30 Mar 2010 */
2087 }
2088
2089 if( new_nowarp ){
2090 VINFO("clearing warp") ;
2091 ZERO_IDCODE( dset->warp_parent_idcode ) ;
2092 dset->warp_parent_name[0] = '\0' ;
2093 dset->warp = NULL ;
2094 did_something++ ; /* 30 Mar 2010 */
2095 }
2096
2097 if( new_type ){
2098 #if 0
2099 /* removed these tests where nvals is used as number of values per sub-brick
2100 instead of number of sub-bricks. Apparently from another era, these are
2101 limited to a value of 1 or 2 in 3ddata.h for each data type */
2102 /* if( nvals > 1 && dset->taxis != NULL ){
2103 ERROR_message("Can't change 3D+time dataset to new type:\n"
2104 " * new type has more than one value per voxel!\n") ;
2105 } else if( dset->taxis == NULL && nvals != dset->dblk->nvals &&
2106 ((dtype==HEAD_FUNC_TYPE && ftype!=FUNC_BUCK_TYPE)||
2107 (dtype==HEAD_ANAT_TYPE && ftype!=ANAT_BUCK_TYPE) ) ){
2108
2109 ERROR_message("Can't change dataset to new type:\n"
2110 " * mismatch in number of sub-bricks!\n") ;
2111 } else {
2112 */
2113 #endif
2114 VINFO("changing dataset 'type' marker") ;
2115 dset->type = dtype ;
2116 dset->func_type = ftype ;
2117
2118 if( ISBUCKET(dset) && dset->taxis != NULL ){ /* 29 April 1998 */
2119 WARNING_message("changing 3D+time dataset to bucket [no time axis]\n") ;
2120 EDIT_dset_items( dset , ADN_ntt , 0 , ADN_none ) ;
2121 }
2122
2123 did_something++ ; /* set either way 17 Nov 2011 [rickr, dglen] */
2124 /* }*/
2125 }
2126
2127 if( new_stataux ){
2128 for( ii=0 ; ii < MAX_STAT_AUX ; ii++ ){
2129 dset->stat_aux[ii] = stataux[ii] ;
2130 }
2131 did_something++ ; /* 30 Mar 2010 */
2132 VINFO("new stataux") ;
2133 }
2134
2135 if( new_view && dset->view_type != vtype ){
2136 int old_vtype = dset->view_type ;
2137 char old_head[THD_MAX_NAME] , old_brik[THD_MAX_NAME] ;
2138 char new_head[THD_MAX_NAME] , new_brik[THD_MAX_NAME] ;
2139 int brick_ccode = COMPRESS_filecode( DSET_BRIKNAME(dset) ) ;
2140
2141 VINFO("changing dataset view code") ;
2142 strcpy(old_head,DSET_HEADNAME(dset)) ;
2143 strcpy(old_brik,DSET_BRIKNAME(dset)) ;
2144 dset->view_type = vtype ;
2145 THD_init_diskptr_names( dset->dblk->diskptr ,
2146 NULL , NULL , NULL , vtype , True ) ;
2147
2148 #if 0 /* HEADNAME now has path, no need for catenation ZSS Fev 2012 */
2149 strcpy(new_head,DSET_DIRNAME(dset)) ;
2150 strcat(new_head,DSET_HEADNAME(dset)) ;
2151 strcpy(new_brik,DSET_DIRNAME(dset)) ;
2152 strcat(new_brik,DSET_BRIKNAME(dset)) ;
2153 #else
2154 strcpy(new_head,DSET_HEADNAME(dset)) ;
2155 strcpy(new_brik,DSET_BRIKNAME(dset)) ;
2156 #endif
2157
2158 if( THD_is_file(new_head) ){
2159 dset->view_type = old_vtype ;
2160 THD_init_diskptr_names( dset->dblk->diskptr ,
2161 NULL , NULL , NULL , old_vtype , True ) ;
2162 /* if not changing the current file, fail
2163 (i.e. accept in case of NIfTI or similar in -space)
2164 (suggested by I Schwabacher) 24 Apr 2013 [rickr] */
2165 if( strcmp(old_head, new_head) )
2166 ERROR_exit("Can't change view: would overwrite existing files!\n");
2167 } else {
2168 /* check whether this succeeds [16 Aug 2019 rickr/dglen] */
2169 if( rename( old_head , new_head ) )
2170 ERROR_exit("3drefit: failed to rename %s to %s\n",
2171 old_head, new_head) ;
2172
2173 { char * fff = COMPRESS_filename(old_brik) ;
2174 if( fff != NULL ){
2175 char * ggg = malloc( sizeof(char) * (strlen(fff)+32) ) ;
2176 strcpy(ggg,new_brik) ;
2177 if( brick_ccode >= 0 )
2178 strcat(ggg,COMPRESS_suffix[brick_ccode]) ;
2179 if( rename( fff , ggg ) )
2180 ERROR_exit("3drefit: failed to rename %s to %s\n",fff,ggg);
2181
2182 free(fff) ; free(ggg) ;
2183 }
2184 }
2185 ININFO_message("Changed dataset view type and filenames.\n") ;
2186 did_something++ ; /* 30 Mar 2010 */
2187 }
2188 }
2189
2190 /* check for tag shifts 08 May 2006 [rickr] */
2191 if( new_tags || shift_tags ){
2192 THD_usertag * tag;
2193 if( !dset->tagset ) WARNING_message("No tags to shift\n") ;
2194 else {
2195 ININFO_message("modifying tags") ;
2196 for( ii = 0; ii < dset->tagset->num; ii++ ){
2197 tag = dset->tagset->tag + ii ;
2198 tag->x += dxtag; tag->y += dytag; tag->z += dztag;
2199 }
2200 did_something++ ; /* 30 Mar 2010 */
2201 }
2202 } else if ( dset->tagset && ( new_xorg || new_yorg || new_zorg ||
2203 new_xdel || new_ydel || new_zdel ) )
2204 WARNING_message("modifying coordinates of dataset with tags") ;
2205
2206 /* code moved to edt_emptycopy.c 13 Sep 2005 [rickr] */
2207 if( new_markers && okay_to_add_markers(dset) ){
2208 dset->markers = create_empty_marker_set() ;
2209 did_something++ ; /* 30 Mar 2010 */
2210 VINFO("empty marker set") ;
2211
2212 } else if( new_markers ){
2213 WARNING_message("Can't add markers to this dataset\n") ;
2214 } /* end of markers */
2215
2216 /*-- 08 Jun 2004: copyaux? --*/
2217
2218 if( copyaux ){
2219 if( auxset != NULL ){
2220 THD_copy_datablock_auxdata( auxset->dblk , dset->dblk );
2221 INIT_STAT_AUX( dset , MAX_STAT_AUX , auxset->stat_aux ) ;
2222 did_something++ ; /* 30 Mar 2010 */
2223 VINFO("copy auxdata") ;
2224 } else {
2225 THD_copy_datablock_auxdata( NULL , dset->dblk );
2226 VINFO("null auxdata") ;
2227 did_something++ ; /* 30 Mar 2010 */
2228 }
2229 }
2230
2231 /*-- 11 Jan 2012: copytables? --*/
2232
2233 if( copytabs ){
2234 if( tabset != NULL ){
2235 if (!THD_copy_labeltable_atr( dset->dblk , tabset->dblk )) {
2236 WARNING_message("Failed to copy labletable attributes");
2237 }
2238 did_something++ ;
2239 VINFO("copy tabledata") ;
2240 }
2241 }
2242
2243
2244 /*-- relabel_all? [18 Apr 2011] --*/
2245
2246 if( sar_relab != NULL ){
2247 for( ii=0 ; ii < sar_relab->num && ii < DSET_NVALS(dset) ; ii++ ){
2248 if( sar_relab->str[ii][0] != '\0' ){
2249 EDIT_BRICK_LABEL( dset , ii , sar_relab->str[ii] ) ;
2250 did_something++ ;
2251 }
2252 }
2253 VINFO("relabel_all") ;
2254 }
2255
2256 /*-- new aux data? --*/
2257
2258 if( nsublab > 0 ){
2259 for( ii=0 ; ii < nsublab ; ii++ ){
2260 iv = sublab[ii].iv ;
2261 if( iv < 0 || iv >= DSET_NVALS(dset) ){
2262 WARNING_message("Can't put label on sub-brick %d\n",iv) ;
2263 } else {
2264 EDIT_dset_items( dset ,
2265 ADN_brick_label_one + iv , sublab[ii].lab ,
2266 ADN_none ) ;
2267 did_something++ ; /* 30 Mar 2010 */
2268 VINFO("edit sub-brick label") ;
2269 }
2270 }
2271 }
2272
2273 /* add suffix to labels? */
2274 if (subsuff) {
2275 char *olab=NULL, *sss=NULL;
2276 for( ii=0 ; ii < DSET_NVALS(dset) ; ii++ ){
2277 olab = DSET_BRICK_LABEL(dset,ii); if (!olab) { olab = ""; }
2278 sss = (char *)calloc(strlen(olab)+strlen(subsuff)+1, sizeof(char));
2279 sprintf(sss,"%s%s", olab, subsuff);
2280 EDIT_BRICK_LABEL( dset , ii , sss ) ;
2281 free(sss);
2282 did_something++ ;
2283 }
2284 VINFO("sublabel_suffix") ;
2285 }
2286
2287 /* add prefix to labels? */
2288 if (subpref) {
2289 char *olab=NULL, *sss=NULL;
2290 for( ii=0 ; ii < DSET_NVALS(dset) ; ii++ ){
2291 olab = DSET_BRICK_LABEL(dset,ii); if (!olab) { olab = ""; }
2292 sss = (char *)calloc(strlen(olab)+strlen(subpref)+1, sizeof(char));
2293 sprintf(sss,"%s%s", subpref, olab);
2294 EDIT_BRICK_LABEL( dset , ii , sss ) ;
2295 free(sss);
2296 did_something++ ;
2297 }
2298 VINFO("sublabel_prefix") ;
2299 }
2300
2301 if( nsubkeyword > 0 ){
2302 int code ;
2303 for( ii=0 ; ii < nsubkeyword ; ii++ ){
2304 iv = subkeyword[ii].iv ; code = subkeyword[ii].code ;
2305 if( iv < 0 || iv >= DSET_NVALS(dset) ){
2306 WARNING_message("Can't put keyword on sub-brick %d\n",iv) ;
2307 } else if( code == 1 ){
2308 EDIT_dset_items( dset ,
2309 ADN_brick_keywords_append_one + iv ,
2310 subkeyword[ii].keyword ,
2311 ADN_none ) ;
2312 did_something++ ; /* 30 Mar 2010 */
2313 VINFO("edit sub-brick keywords") ;
2314 } else if( code == 2 ){
2315 EDIT_dset_items( dset ,
2316 ADN_brick_keywords_replace_one + iv ,
2317 subkeyword[ii].keyword ,
2318 ADN_none ) ;
2319 did_something++ ; /* 30 Mar 2010 */
2320 VINFO("edit sub-brick keywords") ;
2321 } else if( code == 3 && dset->dblk->brick_keywords != NULL ){
2322 EDIT_dset_items( dset ,
2323 ADN_brick_keywords_replace_one + iv ,
2324 NULL ,
2325 ADN_none ) ;
2326 VINFO("nullify sub-brick keywords") ;
2327 did_something++ ; /* 30 Mar 2010 */
2328 }
2329 }
2330 }
2331
2332 switch( new_key ){
2333 case 1: EDIT_dset_items(dset, ADN_keywords_append , key , ADN_none); did_something++; break;
2334 case 2: EDIT_dset_items(dset, ADN_keywords_replace, key , ADN_none); did_something++; break;
2335 case 3: EDIT_dset_items(dset, ADN_keywords_replace, NULL, ADN_none); did_something++; break;
2336 }
2337
2338 if( do_killSTAT ){ /* 24 Jan 2008 */
2339 for( iv=0 ; iv < DSET_NVALS(dset) ; iv++ ){
2340 EDIT_BRICK_TO_NOSTAT(dset,iv) ;
2341 }
2342 VINFO("kill statistics") ;
2343 did_something++ ; /* 30 Mar 2010 */
2344 }
2345
2346 if( nsubstatpar > 0 ){
2347 for( ii=0 ; ii < nsubstatpar ; ii++ ){
2348 iv = substatpar[ii].iv ;
2349 if( iv < 0 || iv >= DSET_NVALS(dset) ){
2350 WARNING_message("Can't put statpar on sub-brick %d",iv) ;
2351 } else {
2352 EDIT_dset_items( dset ,
2353 ADN_brick_stataux_one + iv , substatpar[ii].par ,
2354 ADN_none ) ;
2355 did_something++ ; /* 30 Mar 2010 */
2356 if( verb )
2357 INFO_message("changed statcode[%d] to %d",iv,(int)substatpar[ii].par[0]) ;
2358 }
2359 }
2360 }
2361
2362 /* 03 Aug 2005: implement atrcopy */
2363 if( num_atrcopy > 0 )
2364 {
2365 ATR_any *atr;
2366 for( ii=0 ; ii < num_atrcopy ; ii++ ) {
2367 THD_insert_atr( dset->dblk , atrcopy[ii] ) ;
2368 }
2369 did_something++ ; /* 30 Mar 2010 */
2370 VINFO("atrcopy") ;
2371 }
2372 /* 23 Jan 2008: the FDR stuff */
2373
2374 if( do_FDR ){
2375 DSET_BRICK_FDRCURVE_ALLKILL(dset) ;
2376 DSET_BRICK_MDFCURVE_ALLKILL(dset) ; /* 22 Oct 2008 */
2377 if( do_FDR > 0 ){
2378 int nf ;
2379 mri_fdr_setmask( (nFDRmask == DSET_NVOX(dset)) ? FDRmask : NULL ) ;
2380 nf = THD_create_all_fdrcurves(dset) ;
2381 if( nf > 0 ){
2382 did_something += nf ; /* 30 Mar 2010 */
2383 ININFO_message("created %d FDR curve%s in dataset header",nf,(nf==1)?"\0":"s") ;
2384 } else {
2385 ININFO_message("failed to create FDR curves in dataset header") ;
2386 }
2387 }
2388 }
2389
2390 /* Do we want to force new attributes into output ? ZSS Jun 06*/
2391 /* (only if -atrcopy or -atrstring) 28 Jul 2006 [rickr] */
2392 if ( saveatr && atrmod ){
2393 THD_set_dset_atr_status(0);
2394 /* THD_updating_obliquity(1);*/ /* allow the possibility to update the obliquity -
2395 otherwise gets overwritten with cardinal matrix in
2396 THD_set_dataset_attributes() */
2397 /* apply attributes to header - dataxes and dblk*/
2398 INFO_message("applying attributes");
2399 THD_datablock_from_atr(dset->dblk , DSET_DIRNAME(dset) ,
2400 dset->dblk->diskptr->header_name);
2401 THD_datablock_apply_atr(dset );
2402 }
2403
2404 if( denote ){ THD_anonymize_write(1); did_something++; VINFO("denote");} /* 08 Jul 2005 */
2405
2406 if( !did_something ){
2407 ININFO_message("Didn't make any changes for dataset %s !",argv[iarg]) ;
2408 } else {
2409 if( write_output ) {
2410 ININFO_message(
2411 "loading and re-writing dataset %s (%s in %s storage)\n",
2412 argv[iarg], dset->dblk->diskptr->header_name,
2413 storage_mode_str(dset->dblk->diskptr->storage_mode) ) ;
2414 DSET_load(dset) ; /* 20 Jun 2006 */
2415 }
2416 THD_force_ok_overwrite(1); /* 24 Sep 2007 */
2417 THD_set_quiet_overwrite(1);
2418 THD_write_3dim_dataset( THD_filepath(argv[iarg]),NULL ,
2419 dset , write_output ) ;
2420 }
2421 THD_delete_3dim_dataset( dset , False ) ;
2422
2423 ndone++ ; /* 18 Jul 2006: number of datasets done */
2424
2425 } /* end of loop over datasets to be refitted */
2426
2427 /*--- DONE ---*/
2428
2429 INFO_message("3drefit processed %d datasets",ndone) ;
2430 exit(0) ;
2431 }
2432
2433 /* read float values from string or file into float attribute */
2434 static ATR_float *
Update_float_atr(char * aname,char * fvstring)2435 Update_float_atr(char *aname, char *fvstring)
2436 {
2437 ATR_float *atr ;
2438 MRI_IMAGE *mri_matrix = NULL;
2439 float *fptr;
2440 int nx, ny, nxy,ii, acount;
2441
2442 ENTRY("Update_float_atr");
2443 if( !THD_filename_pure(aname) ){
2444 WARNING_message("Illegal atrfloat name %s",aname) ;
2445 RETURN(NULL) ;
2446 }
2447
2448 atr = (ATR_float *)RwcMalloc(sizeof(ATR_float)) ;
2449 atr->type = ATR_FLOAT_TYPE ;
2450 atr->name = RwcNewString( aname ) ;
2451
2452 /* parse floats from string to attribute */
2453 /* try reading as float file or 1D: expression */
2454 mri_matrix = mri_read_1D(fvstring); /* string could be file name or commandline string */
2455 if (mri_matrix == NULL) {
2456 mri_matrix = mri_1D_fromstring(fvstring);
2457 }
2458
2459 if (mri_matrix == NULL) {
2460 printf("Error reading floating point attribute file");
2461 RETURN(NULL);
2462 }
2463
2464 /* number of floats in attribute */
2465 nx = mri_matrix->nx; ny = mri_matrix->ny; acount = nx*ny;
2466 atr->nfl = acount ;
2467 atr->fl = (float *) RwcMalloc( sizeof(float) * acount ) ;
2468 fptr = MRI_FLOAT_PTR (mri_matrix);
2469 for( ii=0 ; ii < acount ; ii++ ){
2470 atr->fl[ii] = *fptr++;
2471 }
2472 RETURN(atr);
2473 }
2474
2475 /* read integer values from string or file into int attribute */
2476 static ATR_int *
Update_int_atr(char * aname,char * ivstring)2477 Update_int_atr(char *aname, char *ivstring)
2478 {
2479 ATR_int *atr ;
2480 MRI_IMAGE *mri_matrix = NULL;
2481 float *fptr;
2482 int nx, ny, nxy,ii, acount;
2483
2484 ENTRY("Update_int_atr");
2485 if( !THD_filename_pure(aname) ){
2486 WARNING_message("Illegal atrint name %s",aname) ;
2487 RETURN(NULL) ;
2488 }
2489
2490 atr = (ATR_int *)RwcMalloc(sizeof(ATR_int)) ;
2491 atr->type = ATR_INT_TYPE ;
2492 atr->name = RwcNewString( aname ) ;
2493
2494 /* parse floats from string to attribute */
2495 /* try reading as float file or 1D: expression */
2496 mri_matrix = mri_read_1D(ivstring); /* string could be file name or commandline string */
2497 if (mri_matrix == NULL) {
2498 mri_matrix = mri_1D_fromstring(ivstring);
2499 }
2500
2501 if (mri_matrix == NULL) {
2502 WARNING_message("Error reading integer attribute file");
2503 RETURN(NULL);
2504 }
2505
2506 /* number of floats in attribute */
2507 nx = mri_matrix->nx; ny = mri_matrix->ny; acount = nx*ny;
2508 atr->nin = acount ;
2509 atr->in = (int *) RwcMalloc( sizeof(int) * acount ) ;
2510 fptr = MRI_FLOAT_PTR (mri_matrix);
2511 for( ii=0 ; ii < acount ; ii++ ){
2512 atr->in[ii] = *fptr++;
2513 }
2514
2515 RETURN(atr);
2516 }
2517