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 int print_classic_label2index(THD_3dim_dataset * dset, char * labelname);
10 int print_classic_info (THD_3dim_dataset * dset, char * dname, int verb);
11 int validate_field_struct(int verb);
12
Syntax(TFORM targ,int detail)13 int Syntax(TFORM targ, int detail)
14 {
15 sphinx_printf(targ,"\n"
16 "Prints out sort-of-useful information from a 3D dataset's header\n"
17 "Usage: 3dinfo [-verb OR -short] dataset [dataset ...] ~1~\n"
18 " -verb means to print out lots of stuff\n"
19 " -VERB means even more stuff [including slice time offsets]\n"
20 " -short means to print out less stuff [now the default]\n"
21 "%s"
22 "\n"
23 ":SPX:"
24 "\n.. note::\n\n This could be anything. Just for the demo.\n\n"
25 ":SPX:"
26 "----------------------------------------------------------------------\n"
27 "Alternative Usage 1 (without either of the above options): ~1~\n"
28 " Output a large block of text per dataset. This has multiple options:\n"
29 "\n"
30 " -label2index label dataset : output index corresponding to label ~2~\n"
31 "\n"
32 " example: 3dinfo -label2index aud#0_Coef stats.FT+tlrc\n"
33 "\n"
34 " Prints to stdout the index corresponding to the sub-brick with\n"
35 " the name label, or a blank line if label not found.\n"
36 " The ONLY output is this sub-brick index.\n"
37 " This is intended for used in a script, as in this tcsh fragment:LIT:\n"
38 " set face = `3dinfo -label2index Face#0 AA_Decon+orig`\n"
39 " set hous = `3dinfo -label2index House#0 AA_Decon+orig`\n"
40 " 3dcalc -a AA_Decon+orig\"[$face]\" -b AA_Decon+orig\"[$hous]\" ...:LR:\n"
41 " * Added per the request and efforts of Colm Connolly.\n"
42 "\n"
43 " -niml_hdr dataset : output entire NIML-formatted header ~2~\n"
44 "\n"
45 " example: 3dinfo -niml_hdr stats.FT+tlrc\n"
46 "\n"
47 " Prints to stdout the NIML-formatted equivalent of the .HEAD file.\n"
48 "\n"
49 " -subbrick_info dataset : output only sub-brick part of info ~2~\n"
50 "\n"
51 " example: 3dinfo -subbrick_info stats.FT+tlrc\n"
52 "\n"
53 " Prints to stdout only the part of the full '3dinfo -VERB. output\n"
54 " that includes sub-brick info. The first such line might look like:\n"
55 "\n"
56 " -- At sub-brick #0 'Full_Fstat' datum type is float: 0 to 971.2\n"
57 "\n"
58 "----------------------------------------------------------------------\n"
59 "Alternate Usage 2: ~1~\n"
60 " 3dinfo <OPTION> [OPTION ..] dataset [dataset ...]\n"
61 " Outputs a specific piece of information depending on OPTION.\n"
62 " This can form a table of outputs per dataset.\n"
63 "\n"
64 " ==============================================================\n"
65 " Options producing one value (string) ~2~\n"
66 " ==============================================================\n"
67 " -exists: 1 if dset is loadable, 0 otherwise\n"
68 " This works on prefix also.\n"
69 " -id: Idcodestring of dset\n"
70 " -is_atlas: 1 if dset is an atlas.\n"
71 " -is_atlas_or_labeltable: 1 if dset has an atlas or labeltable.\n"
72 " -is_nifti: 1 if dset is NIFTI format, 0 otherwise\n"
73 " -dset_extension: show filename extension for valid dataset (e.g. .nii.gz)\n"
74 " -storage_mode: show internal storage mode of dataset (e.g. NIFTI)\n"
75 " -space: dataset's space\n"
76 " -gen_space: datasets generic space\n"
77 " -av_space: AFNI format's view extension for the space\n"
78 " -nifti_code: what AFNI would use for an output NIFTI (q)sform_code\n"
79 " -is_oblique: 1 if dset is oblique\n"
80 " -handedness: L if orientation is Left handed, R if it is right handed\n"
81 " -obliquity: Angle from plumb direction.\n"
82 " Angles of 0 (or close) are for cardinal orientations\n"
83 "\n"
84 " -prefix: Return the prefix\n"
85 " -prefix_noext: Return the prefix without extensions\n"
86 " -ni: Return the number of voxels in i dimension\n"
87 " -nj: Return the number of voxels in j dimension\n"
88 " -nk: Return the number of voxels in k dimension\n"
89 " -nijk: Return ni*nj*nk\n"
90 " -nv: Return number of points in time or the number of sub-bricks\n"
91 " -nt: same as -nv\n"
92 " -n4: same as -ni -nj -nk -nv\n"
93 " -nvi: The maximum sub-brick index (= nv -1 )\n"
94 " -nti: same as -nvi\n"
95 " -ntimes: Return number of sub-bricks points in time\n"
96 " This is an option for debugging use, stay away from it.\n"
97 " -max_node: For a surface-based dset, return the maximum node index\n"
98 " -di: Signed displacement per voxel along i direction, aka dx\n"
99 " -dj: Signed displacement per voxel along j direction, aka dy\n"
100 " -dk: Signed displacement per voxel along k direction, aka dz\n"
101 " -d3: same as -di -dj -dk\n"
102 " -adi: Voxel size along i direction (abs(di))\n"
103 " -adj: Voxel size along j direction (abs(dj))\n"
104 " -adk: Voxel size along k direction (abs(dk))\n"
105 " -ad3: same as -adi -adj -adk\n"
106 " -voxvol: Voxel volume in cubic millimeters\n"
107 " -oi: Volume origin along the i direction\n"
108 " -oj: Volume origin along the j direction\n"
109 " -ok: Volume origin along the k direction\n"
110 " -o3: same as -oi -oj -ok\n"
111 " -dcx: volumetric center in x direction (DICOM coordinates)\n"
112 " -dcy: volumetric center in y direction (DICOM coordinates)\n"
113 " -dcz: volumetric center in z direction (DICOM coordinates)\n"
114 " -dc3: same as -dcx -dcy -dcz\n"
115 " -tr: The TR value in seconds.\n"
116 " -dmin: The dataset's minimum value, scaled by fac\n"
117 " -dmax: The dataset's maximum value, scaled by fac\n"
118 " -dminus: The dataset's minimum value, unscaled.\n"
119 " -dmaxus: The dataset's maximum value, unscaled.\n"
120 " -smode: Dset storage mode string.\n"
121 " -header_name: Value of dset structure (sub)field 'header_name'\n"
122 " -brick_name: Value of dset structure (sub)field 'brick_name'\n"
123 " -iname: Name of dset as input on the command line\n"
124 " -orient: Value of orientation string.\n"
125 " For example, LPI means:\n"
126 " i direction grows from Left(negative) to Right(positive).\n"
127 " j direction grows from Posterior (neg.) to Anterior (pos.)\n" " k direction grows from Inferior (neg.) to Superior (pos.)\n"
128 " -extent: The spatial extent of the dataset along R, L, A, P, I and S\n"
129 " -Rextent: Extent along R\n"
130 " -Lextent: Extent along L\n"
131 " -Aextent: Extent along P\n"
132 " -Pextent: Extent along P\n"
133 " -Iextent: Extent along I\n"
134 " -Sextent: Extent along S\n"
135 " -all_names: Value of various dset structures handling filenames.\n"
136 "\n"
137 " ==============================================================\n"
138 " Options producing one value per sub-brick ~2~\n"
139 " ==============================================================\n"
140 " -fac: Return the float scaling factor\n"
141 " -label: The label of each sub-brick\n"
142 " -datum: The data storage type\n"
143 " -min: The minimum value, scaled by fac\n"
144 " -max: The maximum value, scaled by fac\n"
145 " -minus: The minimum value, unscaled.\n"
146 " -maxus: The maximum value, unscaled.\n"
147 "\n"
148 " ==============================================================\n"
149 " Options producing multiple values (strings of multiple lines) ~2~\n"
150 " ==============================================================\n"
151 " You can specify the delimiter between sub-brick parameters with\n"
152 " -sb_delim DELIM. Default DELIM is \"|\"\n"
153 " -labeltable: Show label table, if any\n"
154 " -labeltable_as_atlas_points: Show label table in atlas point format.\n"
155 " -atlas_points: Show atlas points list, if any\n"
156 " -history: History note. \n"
157 " -slice_timing: Show slice timing. \n"
158 "\n"
159 " ==============================================================\n"
160 " Options affecting output format ~2~\n"
161 " ==============================================================\n"
162 " -header_line: Output as the first line the names of attributes\n"
163 " in each field (column)\n"
164 " -hdr: Same as -header_line\n"
165 " -sb_delim SB_DELIM: Delimiter string between sub-brick values\n"
166 " Default SB_DELIM is \"|\"\n"
167 " -NA_flag NAFLAG: String to use when a field is not found or not\n"
168 " applicable. Default is \"NA\"\n"
169 " -atr_delim ATR_DELIM: Delimiter string between attributes\n"
170 " Default ATR_DELIM is the tab character.\n"
171 "\n"
172 " ==============================================================\n"
173 " Options for displaying ijk_to_xyz matrices ~2~\n"
174 " ==============================================================\n"
175 " A set of functions for displaying the matrices that tell us where\n"
176 " the data actually is in space! These 4x4---well 3x4, in practice,\n"
177 " because the bottom row of the matrix *must* be (0, 0, 0, 1)---\n"
178 " can be related to the NIFTI sform and qform matrices (which are LPI\n"
179 " native), but these aform_* matrices are RAI (DICOM) native.\n"
180 ""
181 " There are several types of matrices. Linear affine are the most general\n"
182 " (containing translation, rotation, shear and scaling info), followed by\n"
183 " orthogonal (no shear info; only translation, rotation and scale),\n"
184 " followed by cardinal (no rotation info; only translation and scale).\n"
185 " The 'scale' info is the voxel sizes. The 'translation' determines the\n"
186 " origin location in space. The 'rotation' describes a, well, rotation\n"
187 " relative to the scanner coords---this is the dreaded 'obliquity'. The\n"
188 " 'shear'... well, that could also be present, but it is not common, at\n"
189 " least to describe just-acquired data: it would tilt the axes away from\n"
190 " being mutually 90 deg to each other (i.e., they wouldn't be\n"
191 " orthogonal); this would likely just result from an alignment process.\n"
192 ""
193 " Note: the NIFTI sform can be linear affine, in general; in practice, it\n"
194 " is often just orthogonal. The NIFTI qform is a quaternion representation\n"
195 " of the orthogonalized sform; if sform is orthogonal, then they contain\n"
196 " the same information (common, but not required).\n"
197 ""
198 " The aform_real matrix is AFNI's equivalent of the NIFTI sform; it *can*\n"
199 " encode general linear affine mappings. (In practice, it rarely does so.)\n"
200 " The aform_orth is the orthogonalized aform_real, and thus equivalent\n"
201 " to the NIFTI qform. If aform_real is orthogonal (no shear info), then\n"
202 " these two matrices are equal. The aform_card is the cardinalized form of\n"
203 " the aform_orth; NIFTI does not have an equivalent. AFNI typically uses\n"
204 " this matrix to display your data on a rectangle that is parallel to your\n"
205 " computer screen, without any need to regrid/resample the data (hence, no\n"
206 " blurring introduced). This can be though of displaying your dataset in\n"
207 " a way that you *wish* your subject had been oriented. Note that if\n"
208 " there is no obliquity in the acquired data (that is, aform_orth does not\n"
209 " contain any rotation relative to the scanner coords), then\n"
210 " aform_card == aform_orth.\n"
211 ""
212 " The aform_card is an AFNI convenience (ha!) matrix, it does not have an\n"
213 " equivalent in the NIFTI stable of matrices.\n"
214 ""
215 " -aform_real: Display full 3x4 'aform_real' matrix (AFNI's RAI equivalent\n"
216 " of the sform matrix in NIFTI, may contain obliquity info),\n"
217 " with comment line first.\n"
218 " -aform_real_oneline: Display full 'aform_real' matrix (see '-aform_real')\n"
219 " as 1 row of 12 numbers. No additional comment.\n"
220 " -aform_real_refit_ori XXX: Display full 3x4 'aform_real' matrix (see \n"
221 " '-aform_real')\n"
222 " *if* the dset were reoriented (via 3drefit) to\n"
223 " new orient XXX. Includes comment line first.\n"
224 " -is_aform_real_orth: if true, aform_real == aform_orth, which should be\n"
225 " a very common occurrence.\n"
226 " -aform_orth: Display full 3x4 'aform_orth' matrix (AFNI's RAI matrix\n"
227 " equivalent of the NIFTI quaternion, which may contain\n"
228 " obliquity info), with comment line first.\n"
229 " This matrix is the orthogonalized form of aform_real,\n"
230 " and veeery often AFNI-produced dsets, we will have:\n"
231 " aform_orth == aform_real.\n"
232 " -perm_to_orient YYY: Display 3x3 permutation matrix to go from the\n"
233 " dset's current orientation to the YYY orient.\n"
234 "\n"
235 " ==============================================================\n"
236 " Options requiring dataset pairing at input ~2~\n"
237 " ==============================================================\n"
238 " 3dinfo allows you to make some comparisons between dataset pairs.\n"
239 " The comparison is always done in both directions whether or not\n"
240 " the answer can be different. For example:\n"
241 " 3dinfo -same_grid dset1 dset2 \n"
242 " will output two values, one comparing dset1 to dset2 and the second\n"
243 " comparing dset2 to dset1. With -same_grid, the answers will always\n"
244 " be identical, but this might be different for other queries.\n"
245 " This behaviour allows you to mix options requiring dataset pairs\n"
246 " with those that do not. For example:\n"
247 " 3dinfo -header_line -prefix -n4 -same_grid \\\n"
248 " DSET1+orig DSET2.nii DSET3.nii DSET4.nii\n"
249 "\n"
250 " -same_grid: Output 1 if the grid is identical between two dsets\n"
251 " 0 otherwise. \n"
252 " For -same_grid to be 1, all of -same_dim, -same_delta,\n"
253 " -same_orient, -same_center, and -same_obl must return 1\n"
254 " -same_dim: 1 if dimensions are the same between dset pairs\n"
255 " -same_delta: 1 if voxels sizes are the same between dset pairs\n"
256 " -same_orient: 1 if orientation is the same between dset pairs\n"
257 " -same_center: 1 if geometric center is the same between dset pairs\n"
258 " -same_obl: 1 if obliquity is the same between dset pairs\n"
259 " -same_all_grid: Equivalent to listing all of -same_dim -same_delta\n"
260 " -same_orient, -same_center, and -same_obl on the \n"
261 " command line.\n"
262 " -val_diff: Output the sum of absolute differences of all voxels in the\n"
263 " dataset pair.\n"
264 " -sval_diff: Same as -val_diff, but the sum is divided (scaled) by the \n"
265 " total number of voxels that are not zero in at least one\n"
266 " of the two datasets.\n"
267 "\n"
268 " -monog_pairs: Instead of pairing each dset with the first, pair each\n"
269 " couple separately. This requires you to have an even\n"
270 " number of dsets on the command line\n"
271 "\n"
272 " Examples with csh syntax using datasets in your afni binaries directory ~1~\n"
273 "\n"
274 " 0- First get some datasets with which we'll play\n"
275 " set dsets = ( `apsearch -list_all_afni_P_dsets` )\n"
276 "\n"
277 " 1- The classic\n"
278 " 3dinfo $dsets[1]\n"
279 "\n"
280 " 2- Produce a table of results using 1-value-options for two datasets\n"
281 " 3dinfo -echo_edu -prefix_noext -prefix -space -ni -nj -nk -nt \\\n"
282 " $dsets[1-2]\n"
283 "\n"
284 " 3- Use some of the options that operate on pairs, mix with other options\n"
285 " 3dinfo -echo_edu -header_line -prefix -n4 -same_grid $dsets[1-4]\n"
286 "\n"
287 "\n",
288 SUMA_Offset_SLines(get_help_help(),2)) ;
289 PRINT_COMPILE_DATE ; return(0) ;
290 }
291
load_3dinfo_dataset(char * name)292 THD_3dim_dataset *load_3dinfo_dataset(char *name)
293 {
294 THD_3dim_dataset *dset = NULL;
295
296 if( !name || name[0] == '\0' ) return(NULL);
297 dset = THD_open_dataset( name ) ;
298
299 if( dset == NULL ){ /* open failed */
300
301 /* 23 Jan 2008: try again with +orig, +acpc, +tlrc appended */
302
303 if( strchr(name,'+')==NULL && strstr(name,".nii")==NULL ){
304 char str[THD_MAX_NAME] ; int vv , ll=strlen(name) ;
305 for( vv=0 ; vv <= LAST_VIEW_TYPE && dset == NULL ; vv++ ){
306 strcpy(str,name); if( str[ll-1] == '.' ) str[ll-1] = '\0';
307 strcat(str,"+") ; strcat(str,VIEW_codestr[vv]) ;
308 dset = THD_open_dataset(str) ;
309 }
310 }
311
312 }
313 return(dset);
314 }
315
316 typedef enum {
317 CLASSIC=0, DSET_SPACE, AV_DSET_SPACE, DSET_GEN_SPACE, INFO_NIFTI_CODE,
318 IS_NIFTI, DSET_EXISTS,
319 DSET_EXTENSION, STORAGE_MODE, /* 4 Jun 2019 [rickr] */
320 IS_ATLAS, IS_ATLAS_OR_LABELTABLE, IS_OBLIQUE, OBLIQUITY,
321 AFORM_REAL, AFORM_REAL_ONELINE, AFORM_REAL_REFIT_ORI, // [PT: Nov 13, 2020]
322 IS_AFORM_REAL_ORTH,
323 AFORM_ORTH, // [PT: Nov 14, 2020]
324 PERM_TO_ORIENT, // [PT: Nov 23, 2020]
325 PREFIX , PREFIX_NOEXT,
326 NI, NJ, NK, NT, NTI, NTIMES, MAX_NODE,
327 NV, NVI, NIJK,
328 N4,
329 DI, DJ, DK, D3,
330 OI, OJ, OK, O3,
331 ADI, ADJ, ADK, AD3,
332 DCX, DCY, DCZ, DC3,
333 LTABLE, LTABLE_AS_ATLAS_POINT_LIST, ATLAS_POINTS,
334 SLICE_TIMING,
335 FAC, DATUM, LABEL,
336 MIN, MAX, MINUS, MAXUS,
337 DMIN, DMAX, DMINUS, DMAXUS,
338 TR, HEADER_NAME, BRICK_NAME, ALL_NAMES,
339 HISTORY, ORIENT,
340 SAME_GRID, SAME_DIM, SAME_DELTA, SAME_ORIENT, SAME_CENTER,
341 SAME_OBL, SVAL_DIFF, VAL_DIFF, SAME_ALL_GRID, ID, SMODE,
342 VOXVOL, INAME, HANDEDNESS,
343 EXTENT_R, EXTENT_L, EXTENT_A, EXTENT_P, EXTENT_I, EXTENT_S, EXTENT,
344 N_FIELDS } INFO_FIELDS; /* Keep synchronized with Field_Names
345 Leave N_FIELDS at the end */
346
347 char Field_Names[][32]={
348 {"-classic-"}, {"space"}, {"AV_spc"}, {"gen_spc"}, {"nifti_code"},
349 {"nifti?"}, {"exist?"}, {"exten"}, {"smode"},
350 {"atlas?"}, {"atlas_or_lt?"}, {"oblq?"}, {"oblq"},
351 {"aformr"}, {"aformr_line"}, {"aformr_refit"},
352 {"aformr_orth?"}, {"aform_orth"}, {"perm2ori"},
353 {"prefix"}, {"pref_nx"},
354 {"Ni"}, {"Nj"}, {"Nk"}, {"Nt"}, {"Nti"}, {"Ntimes"}, {"MxNode"},
355 {"Nv"}, {"Nvi"}, {"Nijk"},
356 {"Ni_Nj_Nk_Nv"},
357 {"Di"}, {"Dj"}, {"Dk"}, {"Di_Dj_Dk"},
358 {"Oi"}, {"Oj"}, {"Ok"}, {"Oi_Oj_Ok"},
359 {"ADi"}, {"ADj"}, {"ADk"}, {"ADi_ADj_ADk"},
360 {"DCx"}, {"DCy"}, {"DCz"}, {"DCx_DCy_DCz"},
361 {"label_table"}, {"LT_as_atlas_point_list"}, {"atlas_point_list"},
362 {"slice_timing"},
363 {"factor"}, {"datum"}, {"label"},
364 {"min"}, {"max"}, {"minus"}, {"maxus"},
365 {"dmin"}, {"dmax"}, {"dminus"}, {"dmaxus"},
366 {"TR"}, {"hdr_nm"}, {"brk_nm"}, {"all_nms"},
367 {"hist"}, {"orient"},
368 {"=grid?"}, {"=dim?"}, {"=delt?"}, {"=ornt?"}, {"=cent?"},
369 {"=obl?"}, {"sDval"}, {"Dval"}, {"=dim_delta_orient_center_obl"},
370 {"id"}, {"smode"},
371 {"voxvol"}, {"iname"}, {"hand"},
372 {"Rext"}, {"Lext"},{"Aext"}, {"Pext"}, {"Iext"}, {"Sext"}, {"RLAPIS_ext"},
373 {"\0"} }; /* Keep synchronized with INFO_FIELDS */
374
PrintForm(INFO_FIELDS sing,int namelen,byte ForHead)375 char *PrintForm(INFO_FIELDS sing , int namelen, byte ForHead)
376 {
377 static char form[5][15];
378 static int iret=-1;
379 ++iret; if (iret > 4) iret = 0;
380 if (ForHead) {
381 switch (sing) {
382 case PREFIX:
383 case PREFIX_NOEXT:
384 sprintf(form[iret],"%%%ds", namelen);
385 break;
386 default:
387 sprintf(form[iret],"%%s");
388 }
389 } else {
390 ERROR_message("Not ready for non-header format of %d\n", sing);
391 sprintf(form[iret],"F.ERROR:%%s");
392 }
393
394 return(form[iret]);
395 }
396
397 #define SPIT_DELIM(ii,N_ii, atrdelim) { \
398 if (N_ii > 1 && ii < N_ii-1) fprintf(stdout,"%s",atrdelim); \
399 else fprintf(stdout,"\n"); \
400 }
401
402
main(int argc,char * argv[])403 int main( int argc , char *argv[] )
404 {
405 THD_3dim_dataset *dset=NULL;
406 int iarg , verbose = -1 ;
407 char *stmp=NULL;
408 char *classic_labelName = NULL;
409 char *sbdelim = {"|"};
410 char *NAflag = {"NA"};
411 char *atrdelim = {"\t"}, *form=NULL;
412 INFO_FIELDS sing[512];
413 int iis=0, N_sing = 0, isb=0, withhead = 0, itmp=0;
414 int ip=0, needpair = 0, namelen=0, monog_pairs = 0;
415 int classic_niml_hdr = 0; /* classic: show niml header */
416 int classic_subb_info = 0; /* classic: show sub-brick info */
417 THD_3dim_dataset *tttdset=NULL, *dsetp=NULL;
418 THD_fvec3 fv = {{-666.0, -666.0, -666.0}};
419 char *tempstr = NULL;
420 int extinit = 0;
421 float RL_AP_IS[6];
422
423 char *aform_real_pbase= "(aform_real)";
424 char aform_real_pstr[100];
425 char *ocharB_aform_real=NULL; // new orient for aform_real disp
426 mat44 dset_mat44_P;
427 char *aform_orth_pbase= "(aform_orth)";
428 char aform_orth_pstr[100];
429
430 char *ochar_perm=NULL; // new orient for perm calc
431 char perm_pstr[100];
432
433 mainENTRY("3dinfo main") ; machdep() ;
434
435 strcpy(perm_pstr, "");
436 strcpy(aform_real_pstr, aform_real_pbase);
437 strcpy(aform_orth_pstr, aform_orth_pbase);
438
439 if( argc < 2) { Syntax(TXT,1) ; RETURN(0); }
440
441 iarg = 1 ;
442 while (iarg < argc && argv[iarg][0] == '-') {
443 CHECK_HELP(argv[iarg],Syntax);
444 if( strncmp(argv[iarg],"-verb" ,5) == 0 ){
445 verbose = 0; iarg++; continue; }
446 else if( strncmp(argv[iarg],"-VERB" ,5) == 0 ){
447 verbose = 1; iarg++; continue; }
448 else if( strncmp(argv[iarg],"-short",5) == 0 ){
449 verbose = -1; iarg++; continue; }
450 else if( strcasecmp(argv[iarg],"-header_line") == 0 ||
451 strcasecmp(argv[iarg],"-hdr") == 0 ){
452 withhead = 1; iarg++; continue; }
453 else if( strcasecmp(argv[iarg],"-monog_pairs") == 0 ){
454 monog_pairs = 1; iarg++; continue; }
455 /* long-format classic options */
456 else if ( strncmp(argv[iarg],"-label2",7) == 0 )
457 {
458 iarg++;
459 if (iarg >= argc)
460 ERROR_exit( "3dinfo needs an argument after -label2number\n");
461 classic_labelName = malloc(sizeof(char) * 2048);
462 strcpy(classic_labelName, argv[iarg]);
463 iarg++; continue;
464 }
465 else if( strcmp(argv[iarg],"-niml_hdr") == 0) {
466 classic_niml_hdr = 1; /* show niml header in classic case */
467 iarg++; continue;
468 }
469 else if( strcmp(argv[iarg],"-subbrick_info") == 0) {
470 classic_subb_info = 1; /* show sub-brick part of info */
471 iarg++; continue;
472 }
473 /* end: long-format classic options */
474 else if( strcasecmp(argv[iarg],"-sb_delim") == 0) {
475 iarg++;
476 if (iarg >= argc)
477 ERROR_exit( "3dinfo needs a string after -sb_delim\n");
478 sbdelim = argv[iarg];
479 iarg++; continue;
480 }
481 else if( strcasecmp(argv[iarg],"-NA_flag") == 0) {
482 iarg++;
483 if (iarg >= argc)
484 ERROR_exit( "3dinfo needs a string after -NA_flag\n");
485 NAflag = argv[iarg];
486 iarg++; continue;
487 }
488 else if( strcasecmp(argv[iarg],"-atr_delim") == 0) {
489 iarg++;
490 if (iarg >= argc)
491 ERROR_exit( "3dinfo needs a string after -atr_delim\n");
492 atrdelim = argv[iarg];
493 iarg++; continue;
494 }
495 else if( strcasecmp(argv[iarg],"-space") == 0) {
496 sing[N_sing++] = DSET_SPACE; iarg++; continue;
497 } else if( strcasecmp(argv[iarg],"-av_space") == 0) {
498 sing[N_sing++] = AV_DSET_SPACE; iarg++; continue;
499 } else if( strcasecmp(argv[iarg],"-gen_space") == 0) {
500 sing[N_sing++] = DSET_GEN_SPACE; iarg++; continue;
501 } else if( strcasecmp(argv[iarg],"-nifti_code") == 0) {
502 sing[N_sing++] = INFO_NIFTI_CODE; iarg++; continue;
503 } else if( strcasecmp(argv[iarg],"-is_nifti") == 0) {
504 sing[N_sing++] = IS_NIFTI; iarg++; continue;
505 } else if( strcasecmp(argv[iarg],"-dset_extension") == 0) {
506 sing[N_sing++] = DSET_EXTENSION; iarg++; continue;
507 } else if( strcasecmp(argv[iarg],"-storage_mode") == 0) {
508 sing[N_sing++] = STORAGE_MODE; iarg++; continue;
509 } else if( strcasecmp(argv[iarg],"-is_atlas") == 0) {
510 sing[N_sing++] = IS_ATLAS; iarg++; continue;
511 } else if( strcasecmp(argv[iarg],"-is_atlas_or_labeltable") == 0) {
512 sing[N_sing++] = IS_ATLAS_OR_LABELTABLE; iarg++; continue;
513 } else if( strcasecmp(argv[iarg],"-exists") == 0) {
514 sing[N_sing++] = DSET_EXISTS; iarg++; continue;
515 } else if( strcasecmp(argv[iarg],"-is_oblique") == 0) {
516 sing[N_sing++] = IS_OBLIQUE; iarg++; continue;
517 } else if( strcasecmp(argv[iarg],"-obliquity") == 0) {
518 sing[N_sing++] = OBLIQUITY; iarg++; continue;
519 } else if( strcasecmp(argv[iarg],"-aform_real") == 0) {
520 sing[N_sing++] = AFORM_REAL; iarg++; continue;
521 } else if( strcasecmp(argv[iarg],"-aform_real_oneline") == 0) {
522 sing[N_sing++] = AFORM_REAL_ONELINE; iarg++; continue;
523 } else if( strcasecmp(argv[iarg],"-aform_real_refit_ori") == 0) {
524 iarg++;
525 if (iarg >= argc)
526 ERROR_exit( "3dinfo needs a string after -aform_real_refit_ori\n");
527 ocharB_aform_real = argv[iarg];
528 sing[N_sing++] = AFORM_REAL_REFIT_ORI; iarg++; continue;
529 } else if( strcasecmp(argv[iarg],"-is_aform_real_orth") == 0) {
530 sing[N_sing++] = IS_AFORM_REAL_ORTH; iarg++; continue;
531 } else if( strcasecmp(argv[iarg],"-aform_orth") == 0) {
532 sing[N_sing++] = AFORM_ORTH; iarg++; continue;
533 } else if( strcasecmp(argv[iarg],"-perm_to_orient") == 0) {
534 iarg++;
535 if (iarg >= argc)
536 ERROR_exit( "3dinfo needs a string after -perm_to_orient\n");
537 ochar_perm = argv[iarg];
538 sing[N_sing++] = PERM_TO_ORIENT; iarg++; continue;
539 } else if( strcasecmp(argv[iarg],"-handedness") == 0) {
540 sing[N_sing++] = HANDEDNESS; iarg++; continue;
541 } else if( strcasecmp(argv[iarg],"-prefix") == 0) {
542 sing[N_sing++] = PREFIX; iarg++; continue;
543 } else if( strcasecmp(argv[iarg],"-prefix_noext") == 0) {
544 sing[N_sing++] = PREFIX_NOEXT; iarg++; continue;
545 } else if( strcasecmp(argv[iarg],"-ni") == 0) {
546 sing[N_sing++] = NI; iarg++; continue;
547 } else if( strcasecmp(argv[iarg],"-nj") == 0) {
548 sing[N_sing++] = NJ; iarg++; continue;
549 } else if( strcasecmp(argv[iarg],"-nk") == 0) {
550 sing[N_sing++] = NK; iarg++; continue;
551 } else if( strcasecmp(argv[iarg],"-n4") == 0) {
552 sing[N_sing++] = NI;
553 sing[N_sing++] = NJ;
554 sing[N_sing++] = NK;
555 sing[N_sing++] = NV; iarg++;
556 continue;
557 } else if( strcasecmp(argv[iarg],"-Rextent") == 0) {
558 sing[N_sing++] = EXTENT_R; iarg++;
559 continue;
560 } else if( strcasecmp(argv[iarg],"-Lextent") == 0) {
561 sing[N_sing++] = EXTENT_L; iarg++;
562 continue;
563 } else if( strcasecmp(argv[iarg],"-Aextent") == 0) {
564 sing[N_sing++] = EXTENT_A; iarg++;
565 continue;
566 } else if( strcasecmp(argv[iarg],"-Pextent") == 0) {
567 sing[N_sing++] = EXTENT_P; iarg++;
568 continue;
569 } else if( strcasecmp(argv[iarg],"-Iextent") == 0) {
570 sing[N_sing++] = EXTENT_I; iarg++;
571 continue;
572 } else if( strcasecmp(argv[iarg],"-Sextent") == 0) {
573 sing[N_sing++] = EXTENT_S; iarg++;
574 continue;
575 } else if( strcasecmp(argv[iarg],"-extent") == 0) {
576 sing[N_sing++] = EXTENT_R;
577 sing[N_sing++] = EXTENT_L;
578 sing[N_sing++] = EXTENT_A;
579 sing[N_sing++] = EXTENT_P;
580 sing[N_sing++] = EXTENT_I;
581 sing[N_sing++] = EXTENT_S;
582 iarg++;
583 continue;
584 } else if( strcasecmp(argv[iarg],"-di") == 0) {
585 sing[N_sing++] = DI; iarg++; continue;
586 } else if( strcasecmp(argv[iarg],"-dj") == 0) {
587 sing[N_sing++] = DJ; iarg++; continue;
588 } else if( strcasecmp(argv[iarg],"-dk") == 0) {
589 sing[N_sing++] = DK; iarg++; continue;
590 } else if( strcasecmp(argv[iarg],"-d3") == 0) {
591 sing[N_sing++] = DI;
592 sing[N_sing++] = DJ;
593 sing[N_sing++] = DK; iarg++;
594 continue;
595 } else if( strcasecmp(argv[iarg],"-adi") == 0) {
596 sing[N_sing++] = ADI; iarg++; continue;
597 } else if( strcasecmp(argv[iarg],"-adj") == 0) {
598 sing[N_sing++] = ADJ; iarg++; continue;
599 } else if( strcasecmp(argv[iarg],"-adk") == 0) {
600 sing[N_sing++] = ADK; iarg++; continue;
601 } else if( strcasecmp(argv[iarg],"-ad3") == 0) {
602 sing[N_sing++] = ADI;
603 sing[N_sing++] = ADJ;
604 sing[N_sing++] = ADK; iarg++;
605 continue;
606 } else if( strcasecmp(argv[iarg],"-dcx") == 0) {
607 sing[N_sing++] = DCX; iarg++; continue;
608 } else if( strcasecmp(argv[iarg],"-dcy") == 0) {
609 sing[N_sing++] = DCY; iarg++; continue;
610 } else if( strcasecmp(argv[iarg],"-dcz") == 0) {
611 sing[N_sing++] = DCZ; iarg++; continue;
612 } else if( strcasecmp(argv[iarg],"-dc3") == 0) {
613 sing[N_sing++] = DCX;
614 sing[N_sing++] = DCY;
615 sing[N_sing++] = DCZ; iarg++;
616 continue;
617 } else if( strcasecmp(argv[iarg],"-voxvol") == 0) {
618 sing[N_sing++] = VOXVOL; iarg++; continue;
619 } else if( strcasecmp(argv[iarg],"-iname") == 0) {
620 sing[N_sing++] = INAME; iarg++; continue;
621 } else if( strcasecmp(argv[iarg],"-oi") == 0) {
622 sing[N_sing++] = OI; iarg++; continue;
623 } else if( strcasecmp(argv[iarg],"-oj") == 0) {
624 sing[N_sing++] = OJ; iarg++; continue;
625 } else if( strcasecmp(argv[iarg],"-ok") == 0) {
626 sing[N_sing++] = OK; iarg++; continue;
627 } else if( strcasecmp(argv[iarg],"-o3") == 0) {
628 sing[N_sing++] = OI;
629 sing[N_sing++] = OJ;
630 sing[N_sing++] = OK; iarg++;
631 continue;
632 }else if( strcasecmp(argv[iarg],"-nt") == 0) {
633 sing[N_sing++] = NT; iarg++; continue;
634 } else if( strcasecmp(argv[iarg],"-nti") == 0) {
635 sing[N_sing++] = NTI; iarg++; continue;
636 } else if( strcasecmp(argv[iarg],"-nv") == 0) {
637 sing[N_sing++] = NV; iarg++; continue;
638 } else if( strcasecmp(argv[iarg],"-nvi") == 0) {
639 sing[N_sing++] = NVI; iarg++; continue;
640 } else if( strcasecmp(argv[iarg],"-ntimes") == 0) {
641 sing[N_sing++] = NTIMES; iarg++; continue;
642 } else if( strcasecmp(argv[iarg],"-max_node") == 0) {
643 sing[N_sing++] = MAX_NODE; iarg++; continue;
644 } else if( strcasecmp(argv[iarg],"-nijk") == 0) {
645 sing[N_sing++] = NIJK; iarg++; continue;
646 } else if( strcasecmp(argv[iarg],"-labeltable") == 0) {
647 sing[N_sing++] = LTABLE; iarg++; continue;
648 } else if( strcasecmp(argv[iarg],"-labeltable_as_atlas_points") == 0) {
649 sing[N_sing++] = LTABLE_AS_ATLAS_POINT_LIST; iarg++; continue;
650 } else if( strcasecmp(argv[iarg],"-atlas_points") == 0) {
651 sing[N_sing++] = ATLAS_POINTS; iarg++; continue;
652 } else if( strcasecmp(argv[iarg],"-fac") == 0) {
653 sing[N_sing++] = FAC; iarg++; continue;
654 } else if( strcasecmp(argv[iarg],"-datum") == 0) {
655 sing[N_sing++] = DATUM; iarg++; continue;
656 } else if( strcasecmp(argv[iarg],"-label") == 0) {
657 sing[N_sing++] = LABEL; iarg++; continue;
658 } else if( strcasecmp(argv[iarg],"-min") == 0) {
659 sing[N_sing++] = MIN; iarg++; continue;
660 } else if( strcasecmp(argv[iarg],"-max") == 0) {
661 sing[N_sing++] = MAX; iarg++; continue;
662 } else if( strcasecmp(argv[iarg],"-minus") == 0) {
663 sing[N_sing++] = MINUS; iarg++; continue;
664 } else if( strcasecmp(argv[iarg],"-maxus") == 0) {
665 sing[N_sing++] = MAXUS; iarg++; continue;
666 } else if( strcasecmp(argv[iarg],"-dmin") == 0) {
667 sing[N_sing++] = DMIN; iarg++; continue;
668 } else if( strcasecmp(argv[iarg],"-dmax") == 0) {
669 sing[N_sing++] = DMAX; iarg++; continue;
670 } else if( strcasecmp(argv[iarg],"-dminus") == 0) {
671 sing[N_sing++] = DMINUS; iarg++; continue;
672 } else if( strcasecmp(argv[iarg],"-dmaxus") == 0) {
673 sing[N_sing++] = DMAXUS; iarg++; continue;
674 } else if( strcasecmp(argv[iarg],"-TR") == 0) {
675 sing[N_sing++] = TR; iarg++; continue;
676 } else if( strcasecmp(argv[iarg],"-header_name") == 0) {
677 sing[N_sing++] = HEADER_NAME; iarg++; continue;
678 } else if( strcasecmp(argv[iarg],"-brick_name") == 0) {
679 sing[N_sing++] = BRICK_NAME; iarg++; continue;
680 } else if( strcasecmp(argv[iarg],"-history") == 0) {
681 sing[N_sing++] = HISTORY; iarg++; continue;
682 } else if( strcasecmp(argv[iarg],"-all_names") == 0) {
683 sing[N_sing++] = ALL_NAMES; iarg++; continue;
684 } else if( strcasecmp(argv[iarg],"-orient") == 0) {
685 sing[N_sing++] = ORIENT; iarg++; continue;
686 } else if( strcasecmp(argv[iarg],"-same_grid") == 0) {
687 sing[N_sing++] = SAME_GRID; needpair = 1; iarg++; continue;
688 } else if( strcasecmp(argv[iarg],"-same_dim") == 0) {
689 sing[N_sing++] = SAME_DIM; needpair = 1; iarg++; continue;
690 } else if( strcasecmp(argv[iarg],"-same_delta") == 0) {
691 sing[N_sing++] = SAME_DELTA; needpair = 1; iarg++; continue;
692 } else if( strcasecmp(argv[iarg],"-same_orient") == 0) {
693 sing[N_sing++] = SAME_ORIENT; needpair = 1; iarg++; continue;
694 } else if( strcasecmp(argv[iarg],"-same_center") == 0) {
695 sing[N_sing++] = SAME_CENTER; needpair = 1; iarg++; continue;
696 } else if( strcasecmp(argv[iarg],"-same_obl") == 0) {
697 sing[N_sing++] = SAME_OBL; needpair = 1; iarg++; continue;
698 } else if( strcasecmp(argv[iarg],"-slice_timing") == 0) {
699 sing[N_sing++] = SLICE_TIMING; iarg++; continue;
700 } else if( strcasecmp(argv[iarg],"-sval_diff") == 0) {
701 sing[N_sing++] = SVAL_DIFF; needpair = 1; iarg++; continue;
702 } else if( strcasecmp(argv[iarg],"-val_diff") == 0) {
703 sing[N_sing++] = VAL_DIFF; needpair = 1; iarg++; continue;
704 } else if( strcasecmp(argv[iarg],"-same_all_grid") == 0) {
705 sing[N_sing++] = SAME_DIM;
706 sing[N_sing++] = SAME_DELTA;
707 sing[N_sing++] = SAME_ORIENT;
708 sing[N_sing++] = SAME_CENTER;
709 sing[N_sing++] = SAME_OBL; needpair = 1; iarg++; continue;
710 } else if( strcasecmp(argv[iarg],"-id") == 0) {
711 sing[N_sing++] = ID; iarg++; continue;
712 } else if( strcasecmp(argv[iarg],"-smode") == 0) {
713 sing[N_sing++] = SMODE; iarg++; continue;
714 } else {
715 ERROR_message("Option %s unknown", argv[iarg]);
716 suggest_best_prog_option(argv[0], argv[iarg]);
717 exit(1);
718 }
719 }
720
721 if (N_sing == 0) {
722 sing[N_sing++] = CLASSIC;
723 }
724
725 if (sing[iis] == CLASSIC) PRINT_VERSION("3dinfo") ;
726
727 /* be sure field struct matches enum [26 Jul 2021 rickr] */
728 (void)validate_field_struct(verbose);
729
730 THD_allow_empty_dataset(1) ; /* 21 Mar 2007 */
731
732 if (iarg == argc) {
733 ERROR_message("No dsets on command line? I have nothing to do.\n");
734 exit(1);
735 }
736
737 if (needpair && monog_pairs) needpair = 2; /* pair each couple separately */
738
739 if (needpair==2 && (argc-iarg) % 2) {
740 ERROR_message("Using options requiring dset pairs but have odd number\n"
741 "of dsets (%d) on command line.\n", (argc-iarg));
742 exit (1);
743 } else if (needpair==1 && (argc-iarg) < 2) {
744 ERROR_message("Using options requiring dset pairs but have less than\n"
745 "two dsets (%d) on command line.\n", (argc-iarg));
746 exit (1);
747 }
748
749 ip = 0;
750 for( ; iarg < argc ; iarg++ ){
751 if (ip == 0) {
752 int kkk, nml; char *etr;
753 namelen = 0;
754 for (kkk=iarg; kkk<argc; ++kkk) {
755 if ((etr = THD_trailname(argv[kkk],0))) {
756 nml=strlen(etr);
757 if (nml < 48 && nml > namelen) namelen = nml;
758 }
759 }
760 if (namelen < 6) namelen = 6;
761 if (withhead) {
762 int havenew=0;
763 for (iis = 0; iis < N_sing; ++iis) {
764 if (sing[iis] != CLASSIC) {
765 ++havenew;
766 form = PrintForm(sing[iis], namelen, 1);
767 /*fprintf(stderr,"ZSS: %d %s >%s<\n",
768 sing[iis], Field_Names[sing[iis]], form);*/
769
770 fprintf(stdout, form, Field_Names[sing[iis]]);
771 }
772 if (havenew) {
773 if (N_sing > 1 && iis < N_sing-1)
774 fprintf(stdout,"%s",atrdelim);
775 else fprintf(stdout,"\n");
776 }
777 }
778 }
779 }
780 if( argv[iarg][0] == '\0' ) continue ; /* bad filename */
781
782 set_obliquity_report(0); /* silence obliquity */
783
784 if (!needpair) {
785 if (!(dset = load_3dinfo_dataset(argv[iarg]))) {
786 /* exit(1); */
787 }
788 } else {
789 if (needpair == 2) { /* Crazy idea of comparing each pair separately */
790 if (ip % 2 == 0) {
791 if (!(dset = load_3dinfo_dataset(argv[iarg] ))) {
792 /* exit(1); */
793 }
794 if (iarg+1==argc || argv[iarg+1][0] == '\0') {
795 ERROR_message("Bad dset pair for %s\n", argv[iarg]);
796 exit(1);
797 }
798 if (!(dsetp = load_3dinfo_dataset(argv[iarg+1] ))) {
799 /* exit(1); */
800 }
801 } else { /* swap the pair - this allows non pair requiring functions
802 to work as before.*/
803 tttdset = dsetp;
804 dsetp = dset;
805 dset = tttdset; tttdset=NULL;
806 }
807 } else { /* always compare to very first dset */
808 if (ip==0) {
809 if (!(dset = load_3dinfo_dataset(argv[iarg] ))) {
810 /*exit(1);*/
811 }
812 if (!(dsetp = load_3dinfo_dataset(argv[iarg+1] ))) {
813 /*exit(1);*/
814 }
815 } else if (ip==1) { /* switch order of first two */
816 tttdset = dsetp;
817 dsetp = dset; /* now dsetp is the very first dset */
818 dset = tttdset; tttdset=NULL;
819 } else { /* pair with very first, which is dsetp */
820 if (!(dset = load_3dinfo_dataset(argv[iarg] ))) {
821 /*exit(1);*/
822 }
823 }
824 }
825 }
826 ++ip;
827
828 if (0 && !dset) { /* allow for DSET_EXISTS option */
829 ERROR_exit("Should not get here");
830 }
831
832 /* we should re-capture this per dataset 5 Feb 2019 [rickr] */
833 extinit = 0;
834
835 for (iis = 0; iis < N_sing; ++iis) {
836 if (!dset) {
837 if (sing[iis] == CLASSIC) {
838 if( dset == NULL ){ /* still not open? */
839 ERROR_exit("Can't open dataset %s\n", argv[iarg]) ;
840 }
841 } else if (sing[iis] != DSET_EXISTS && sing[iis] != INAME) {
842 fprintf(stdout, "NO-DSET");
843 SPIT_DELIM(iis, N_sing, atrdelim);
844 continue;
845 }
846 }
847 switch (sing[iis]) {
848 case CLASSIC:
849 /* check for multiple cases under classic unbrella (make
850 new cases if this continues) [10 Oct 2019 rickr] */
851
852 if (classic_labelName != NULL ) { /*** get and output label ***/
853 print_classic_label2index(dset, classic_labelName);
854 } else if ( classic_niml_hdr ) {
855 if( ! THD_write_niml_to_stream(dset, "stdout:", 0) )
856 ERROR_exit("Can't write NIML for dataset %s",argv[iarg]) ;
857 } else if ( classic_subb_info ) {
858 tempstr = THD_dset_subbrick_info(dset, 0);
859 if( tempstr ) {
860 fputs(tempstr, stdout);
861 free(tempstr);
862 tempstr = NULL;
863 } else {
864 ERROR_exit("failed subbrick_info for dset %s",argv[iarg]) ;
865 }
866
867 } else { /*** real CLASSIC: get and output general info ***/
868 if( print_classic_info(dset, argv[iarg], verbose) )
869 exit(1);
870 }
871
872 THD_delete_3dim_dataset( dset , False ) ;
873 break;
874 case DSET_EXISTS:
875 fprintf(stdout, "%d", dset ? 1:0);
876 break;
877 case DSET_SPACE:
878 tempstr = THD_get_space(dset);
879 if(tempstr==NULL)
880 fprintf(stdout, "-----");
881 else
882 fprintf(stdout, "%s", tempstr);
883 break;
884 case DSET_GEN_SPACE:
885 tempstr = THD_get_generic_space(dset);
886 if(tempstr==NULL)
887 fprintf(stdout, "-----");
888 else
889 fprintf(stdout, "%s", tempstr);
890 break;
891 case INFO_NIFTI_CODE:
892 fprintf(stdout,"%d", space_to_NIFTI_code(dset));
893 break;
894 case AV_DSET_SPACE:
895 /* don't allow anything but the three AFNI views */
896 tempstr = THD_get_view_space(dset);
897 if(tempstr==NULL)
898 fprintf(stdout, "+orig");
899 else if (!strncasecmp(tempstr,"ORIG",4))
900 fprintf(stdout, "+orig");
901 else if (!strncasecmp(tempstr,"ACPC",4))
902 fprintf(stdout, "+acpc");
903 else if (!strncasecmp(tempstr,"TLRC",4))
904 fprintf(stdout, "+tlrc");
905 else /* shouldn't get here */
906 fprintf(stdout, "+orig");
907 break;
908 case IS_NIFTI:
909 if ( dset->dblk->diskptr &&
910 dset->dblk->diskptr->storage_mode == STORAGE_BY_NIFTI ) {
911 fprintf(stdout,"1");
912 } else {
913 fprintf(stdout,"0");
914 }
915 break;
916 case DSET_EXTENSION:
917 tempstr = find_filename_extension(argv[iarg]);
918 if ( tempstr ) {
919 fprintf(stdout,"%s", tempstr);
920 } else {
921 fprintf(stdout,"-----");
922 }
923 break;
924 case STORAGE_MODE:
925 tempstr = storage_mode_name(storage_mode_from_filename(argv[iarg]));
926 /* equate UNDEFINED with NULL case */
927 if ( tempstr && strcmp(tempstr, "UNDEFINED") ) {
928 fprintf(stdout,"%s", tempstr);
929 } else {
930 fprintf(stdout,"-----");
931 }
932 break;
933 case IS_ATLAS:
934 if ( is_Dset_Atlasy(dset, NULL) ) {
935 fprintf(stdout,"1");
936 } else {
937 fprintf(stdout,"0");
938 }
939 break;
940 case IS_ATLAS_OR_LABELTABLE:
941 {
942 char *str = NULL;
943 int iaol_val = 0;
944 if ( is_Dset_Atlasy(dset, NULL) ) {
945 iaol_val = 1;
946 }
947 else if ( (str = Dtable_to_nimlstring(DSET_Label_Dtable(dset),
948 "VALUE_LABEL_DTABLE")) ) {
949 // 'else if' for speed
950 iaol_val = 1;
951 free(str);
952 }
953 fprintf(stdout,"%d", iaol_val);
954 }
955 break;
956 case IS_OBLIQUE:
957 if (dset_obliquity(dset,NULL) > 0) {
958 fprintf(stdout,"1");
959 } else {
960 fprintf(stdout,"0");
961 }
962 break;
963 case HANDEDNESS:
964 if (THD_handedness(dset) > 0) {
965 fprintf(stdout,"R");
966 } else {
967 fprintf(stdout,"L");
968 }
969 break;
970 case OBLIQUITY:
971 fprintf(stdout,"%.3f",
972 THD_compute_oblique_angle(dset->daxes->ijk_to_dicom_real, 0));
973 break;
974 case AFORM_REAL:
975 DUMP_MAT44(aform_real_pstr, dset->daxes->ijk_to_dicom_real);
976 break;
977 case AFORM_REAL_ONELINE:
978 DUMP_MAT44_ONELINE(dset->daxes->ijk_to_dicom_real);
979 break;
980 case AFORM_REAL_REFIT_ORI:
981 {
982 char ostr[4];
983 // the work:
984 dset_mat44_P = THD_refit_orient_ijk_to_dicom_real( dset,
985 ocharB_aform_real );
986 // display formatting/messaging:
987 THD_fill_orient_str_3(dset->daxes, ostr);
988 strcat(aform_real_pstr, " after reorienting from (current) ");
989 strcat(aform_real_pstr, ostr);
990 strcat(aform_real_pstr, " to ");
991 strcat(aform_real_pstr, ocharB_aform_real);
992 DUMP_MAT44(aform_real_pstr, dset_mat44_P);
993 //mat44 TEST;
994 //dset_mat44_P.m[0][2] = 1;
995 //nifti_orthogonalize_mat44(dset_mat44_P, TEST);
996 }
997 break;
998 case IS_AFORM_REAL_ORTH:
999 fprintf(stdout,"%d",
1000 is_mat44_orthogonal(dset->daxes->ijk_to_dicom_real));
1001 break;
1002 case AFORM_ORTH:
1003 {
1004 mat44 aform_orth;
1005 aform_orth = nifti_orthogonalize_mat44(
1006 dset->daxes->ijk_to_dicom_real );
1007 DUMP_MAT44(aform_orth_pstr, aform_orth);
1008 break;
1009 }
1010 case PERM_TO_ORIENT:
1011 {
1012 mat33 P33;
1013 char ostr[4];
1014 // the work:
1015 P33 = THD_dset_reorient_perm_mat33(dset, ochar_perm);
1016
1017 // display formatting/messaging:
1018 THD_fill_orient_str_3(dset->daxes, ostr);
1019 strcat(perm_pstr, "Perm from current ");
1020 strcat(perm_pstr, ostr);
1021 strcat(perm_pstr, " to ");
1022 strcat(perm_pstr, ochar_perm);
1023 DUMP_MAT33b(perm_pstr, P33);
1024 }
1025 break;
1026 case PREFIX:
1027 form = PrintForm(sing[iis], namelen, 1);
1028 fprintf(stdout,form, DSET_PREFIX(dset));
1029 break;
1030 case PREFIX_NOEXT:
1031 {
1032 form = PrintForm(sing[iis], namelen, 1);
1033 stmp=DSET_prefix_noext(dset);
1034 fprintf(stdout,form, stmp);
1035 free(stmp); stmp=NULL;
1036 }
1037 break;
1038 case HEADER_NAME:
1039 fprintf(stdout,"%s", dset->dblk->diskptr->header_name);
1040 break;
1041 case BRICK_NAME:
1042 fprintf(stdout,"%s", dset->dblk->diskptr->brick_name);
1043 break;
1044 case ALL_NAMES:
1045 THD_show_dataset_names(dset, "FOR_3DINFO", stdout);
1046 break;
1047 case HISTORY:
1048 stmp = tross_Get_History(dset);
1049 fprintf(stdout,"%s", stmp ? stmp:NAflag);
1050 if (stmp) free(stmp); stmp=NULL;
1051 break;
1052 case NI:
1053 fprintf(stdout,"%d", DSET_NX(dset));
1054 break;
1055 case NJ:
1056 fprintf(stdout,"%d", DSET_NY(dset));
1057 break;
1058 case NK:
1059 fprintf(stdout,"%d", DSET_NZ(dset));
1060 break;
1061 case NIJK:
1062 fprintf(stdout,"%d", DSET_NVOX(dset));
1063 break;
1064 case NTIMES:
1065 fprintf(stdout,"%d", DSET_NUM_TIMES(dset));
1066 break;
1067 case MAX_NODE:
1068 DSET_MAX_NODE(dset,itmp);
1069 fprintf(stdout,"%d", itmp);
1070 break;
1071 case NT:
1072 case NV:
1073 fprintf(stdout,"%d", DSET_NVALS(dset));
1074 break;
1075 case NTI:
1076 case NVI:
1077 fprintf(stdout,"%d", DSET_NVALS(dset)-1);
1078 break;
1079 case DI:
1080 fprintf(stdout,"%f", DSET_DX(dset));
1081 break;
1082 case DJ:
1083 fprintf(stdout,"%f", DSET_DY(dset));
1084 break;
1085 case DK:
1086 fprintf(stdout,"%f", DSET_DZ(dset));
1087 break;
1088 case OI:
1089 fprintf(stdout,"%f", DSET_XORG(dset));
1090 break;
1091 case OJ:
1092 fprintf(stdout,"%f", DSET_YORG(dset));
1093 break;
1094 case OK:
1095 fprintf(stdout,"%f", DSET_ZORG(dset));
1096 break;
1097 case ADI:
1098 fprintf(stdout,"%f", fabs(DSET_DX(dset)));
1099 break;
1100 case DCX:
1101 /* modular but inefficient, get C? each time */
1102 fv = THD_dataset_center(dset);
1103 fprintf(stdout,"%f", fv.xyz[0]);
1104 break;
1105 case DCY:
1106 /* modular but inefficient, get C? each time */
1107 fv = THD_dataset_center(dset);
1108 fprintf(stdout,"%f", fv.xyz[1]);
1109 break;
1110 case DCZ:
1111 /* modular but inefficient, get C? each time */
1112 fv = THD_dataset_center(dset);
1113 fprintf(stdout,"%f", fv.xyz[2]);
1114 break;
1115 case EXTENT_R:
1116 case EXTENT_L:
1117 case EXTENT_A:
1118 case EXTENT_P:
1119 case EXTENT_I:
1120 case EXTENT_S:
1121 {
1122 if (!extinit) {
1123 THD_dset_extent(dset, '-', RL_AP_IS);
1124 extinit = 1;
1125 }
1126 fprintf(stdout,"%f", RL_AP_IS[sing[iis]-EXTENT_R]);
1127 }
1128 break;
1129
1130 case ADJ:
1131 fprintf(stdout,"%f", fabs(DSET_DY(dset)));
1132 break;
1133 case ADK:
1134 fprintf(stdout,"%f", fabs(DSET_DZ(dset)));
1135 break;
1136 case VOXVOL:
1137 fprintf(stdout,"%f", fabs(DSET_DX(dset))*
1138 fabs(DSET_DY(dset))*fabs(DSET_DZ(dset)));
1139 break;
1140 case INAME:
1141 fprintf(stdout,"%s", argv[iarg]);
1142 break;
1143 case LTABLE:
1144 {
1145 char *str;
1146 if ((str = Dtable_to_nimlstring(DSET_Label_Dtable(dset), "VALUE_LABEL_DTABLE"))) {
1147 fprintf(stdout,"%s", str);
1148 free(str);
1149 } else {
1150 fprintf(stdout,"NO_LABEL_TABLE");
1151 }
1152 }
1153 break;
1154 case LTABLE_AS_ATLAS_POINT_LIST:
1155 {
1156 ATLAS_POINT_LIST *apl=NULL;
1157 if ((apl =
1158 label_table_to_atlas_point_list(DSET_Label_Dtable(dset)))) {
1159 atlas_list_to_niml(apl,NULL);
1160 free_atlas_point_list(apl);
1161 } else {
1162 fprintf(stdout,"NO_LABEL_TABLE");
1163 }
1164 }
1165 break;
1166 case ATLAS_POINTS:
1167 {
1168 ATR_string *atr =
1169 THD_find_string_atr( dset->dblk, "ATLAS_LABEL_TABLE");
1170 if (atr) {
1171 fprintf(stdout,"%s", atr->ch);
1172 } else {
1173 fprintf(stdout,"NO_APL");
1174 }
1175 }
1176 break;
1177 case FAC:
1178 {
1179 for (isb=0; isb<DSET_NVALS(dset); ++isb) {
1180 fprintf(stdout,"%f%s",
1181 DSET_BRICK_FACTOR(dset,isb),
1182 (isb == (DSET_NVALS(dset)-1)) ? "" : sbdelim);
1183 }
1184 break;
1185 }
1186 case DATUM:
1187 {
1188 for (isb=0; isb<DSET_NVALS(dset); ++isb) {
1189 fprintf(stdout,"%s%s",
1190 MRI_TYPE_name[DSET_BRICK_TYPE(dset,isb)],
1191 (isb == (DSET_NVALS(dset)-1)) ? "" : sbdelim);
1192 }
1193 break;
1194 }
1195 case LABEL:
1196 {
1197 for (isb=0; isb<DSET_NVALS(dset); ++isb) {
1198 fprintf(stdout,"%s%s",
1199 DSET_BRICK_LABEL(dset,isb) ? DSET_BRICK_LABEL(dset,isb):NAflag,
1200 (isb == (DSET_NVALS(dset)-1)) ? "" : sbdelim);
1201 }
1202 break;
1203 }
1204 case MIN:
1205 case MINUS:
1206 case MAX:
1207 case MAXUS:
1208 {
1209 float vv=0.0, min, max;
1210 for (isb=0; isb<DSET_NVALS(dset); ++isb) {
1211 if (!THD_subbrick_minmax(dset, isb,
1212 (sing[iis] == MINUS || sing[iis] == MAXUS) ? 0:1,
1213 &min, &max)) {
1214 fprintf(stdout,"%s%s",
1215 NAflag,
1216 (isb == (DSET_NVALS(dset)-1)) ? "" : sbdelim);
1217 } else {
1218 if (sing[iis] == MINUS)
1219 vv = min;
1220 else if (sing[iis] == MAXUS)
1221 vv = max;
1222 else if (sing[iis] == MIN)
1223 vv = min;
1224 else if (sing[iis] == MAX)
1225 vv = max;
1226 fprintf(stdout,"%g%s",
1227 vv,
1228 (isb == (DSET_NVALS(dset)-1)) ? "" : sbdelim);
1229 }
1230 }
1231 break;
1232 }
1233 case DMIN:
1234 case DMINUS:
1235 case DMAX:
1236 case DMAXUS:
1237 {
1238 float vv=0.0, min, max;
1239 if (!THD_dset_minmax(dset,
1240 (sing[iis] == DMINUS || sing[iis] == DMAXUS) ? 0:1,
1241 &min, &max)) {
1242 fprintf(stdout,"%s%s",
1243 NAflag,
1244 (isb == (DSET_NVALS(dset)-1)) ? "" : sbdelim);
1245 } else {
1246 if (sing[iis] == DMINUS)
1247 vv = min;
1248 else if (sing[iis] == DMAXUS)
1249 vv = max;
1250 else if (sing[iis] == DMIN)
1251 vv = min;
1252 else if (sing[iis] == DMAX)
1253 vv = max;
1254 fprintf(stdout,"%g%s",
1255 vv,
1256 (isb == (DSET_NVALS(dset)-1)) ? "" : sbdelim);
1257 }
1258 break;
1259 }
1260 case TR:
1261 #if 0
1262 fprintf(stdout,"%f", DSET_TR_SEC(dset));
1263 #else
1264 fprintf(stdout,"%f", DSET_TR(dset));
1265 #endif
1266 break;
1267 case ORIENT:
1268 {
1269 /* fprintf(stdout,"%c%c%c",
1270 * ORIENT_typestr[dset->daxes->xxorient][0], ... ); */
1271 char ostr[4]; /* just to show 23 Jan 2013 [rickr] */
1272 THD_fill_orient_str_3(dset->daxes, ostr);
1273 fprintf(stdout,"%3s", ostr);
1274 }
1275 break;
1276 case SAME_GRID:
1277 fprintf(stdout,"%d",
1278 !THD_dataset_mismatch( dset , dsetp ));
1279 break;
1280 case SAME_DIM:
1281 fprintf(stdout,"%d",
1282 !(THD_dataset_mismatch( dset , dsetp ) & MISMATCH_DIMEN));
1283 break;
1284 case SAME_DELTA:
1285 fprintf(stdout,"%d",
1286 !(THD_dataset_mismatch( dset , dsetp ) & MISMATCH_DELTA));
1287 break;
1288 case SAME_ORIENT:
1289 fprintf(stdout,"%d",
1290 !(THD_dataset_mismatch( dset , dsetp ) & MISMATCH_ORIENT));
1291 break;
1292 case SAME_CENTER:
1293 fprintf(stdout,"%d",
1294 !(THD_dataset_mismatch( dset , dsetp ) & MISMATCH_CENTER));
1295 break;
1296 case SAME_OBL:
1297 fprintf(stdout,"%d",
1298 !(THD_dataset_mismatch( dset , dsetp ) & MISMATCH_OBLIQ));
1299 break;
1300 case SLICE_TIMING: /* 6 May 2013 [rickr] */
1301 {
1302 if( DSET_HAS_SLICE_TIMING(dset) ) {
1303 DSET_UNMSEC(dset); /* make sure times are in seconds */
1304 for (isb=0; isb<dset->taxis->nsl; ++isb) {
1305 fprintf(stdout,"%s%f",
1306 (isb > 0) ? sbdelim : "",
1307 dset->taxis->toff_sl[isb]);
1308 }
1309 } else { /* all slices times are at t=0.0 */
1310 for (isb=0; isb<DSET_NZ(dset); ++isb) {
1311 fprintf(stdout,"%s%f", (isb > 0) ? sbdelim : "", 0.0);
1312 }
1313 }
1314 }
1315 break;
1316 case SVAL_DIFF:
1317 fprintf(stdout,"%f",THD_diff_vol_vals(dset, dsetp, 1));
1318 break;
1319 case VAL_DIFF:
1320 fprintf(stdout,"%f",THD_diff_vol_vals(dset, dsetp, 0));
1321 break;
1322 case ID:
1323 fprintf(stdout,"%s", DSET_IDCODE_STR(dset));
1324 break;
1325 case SMODE:
1326 fprintf(stdout,"%s", DSET_STORAGE_MODE_STR(dset));
1327 break;
1328 default:
1329 ERROR_message("Info field not set properly (%d)\n", sing[iis]);
1330 exit(1);
1331 }
1332 if (sing[iis] != CLASSIC) {
1333 SPIT_DELIM(iis, N_sing, atrdelim);
1334 }
1335 }
1336 }
1337
1338 if( classic_labelName ) free(classic_labelName);
1339
1340 exit(0) ;
1341 }
1342
1343 /* validate Field_Names against INFO_FIELDS enum [26 Jul 2021 rickr] */
validate_field_struct(int verb)1344 int validate_field_struct(int verb)
1345 {
1346 INFO_FIELDS nfields = N_FIELDS;
1347 int nfcount=-1, nfsize=-1, mismatch;
1348
1349 ENTRY("validate_field_struct");
1350
1351 /* only validate and warn in verbose mode, which defaults to -1 */
1352 if( verb < 0 )
1353 RETURN(0);
1354
1355 /* compute nf by size, given that these are 32 char strings */
1356 /* (subtract 1 for the final empty string) */
1357 nfsize = (int)(sizeof(Field_Names)/sizeof(char[32])) - 1;
1358
1359
1360 for( nfcount = 0; Field_Names[nfcount][0]; nfcount++ )
1361 ;
1362
1363 /* note mismatch before continuing */
1364 mismatch = nfields != nfcount || nfields != nfsize;
1365
1366 /* possibly be verbose */
1367 if ( verb > 0 || mismatch ) {
1368 printf("++ checking INFO_FIELDS against Field_Names\n");
1369 printf(" N_FIELDS = %d\n", nfields);
1370 printf(" nfcount = %d\n", nfcount);
1371 printf(" nfsize = %d\n", nfsize);
1372 }
1373
1374 if( mismatch ) {
1375 fprintf(stderr,"** warning: INFO_FIELDS/Field_Names mismatch\n");
1376 RETURN(1);
1377 }
1378
1379 RETURN(0);
1380 }
1381
1382 /* try to print the index of the specified label */
print_classic_label2index(THD_3dim_dataset * dset,char * labelname)1383 int print_classic_label2index(THD_3dim_dataset * dset, char * labelname)
1384 {
1385 int nval_per;
1386 int foundLabel = 0;
1387 int ival=0;
1388
1389 ENTRY("print_classic_labels");
1390
1391 if( ! dset || ! labelname ) {
1392 ERROR_message("classic label2index: missing dset or label");
1393 RETURN(1);
1394 }
1395
1396 nval_per = DSET_NVALS(dset);
1397
1398 for (ival=0 ; ival < nval_per && !foundLabel; ival++ ) {
1399 if (strcmp(DSET_BRICK_LAB(dset,ival), labelname) == 0) {
1400 printf("%d\n", ival); foundLabel = 1;
1401 }
1402 }
1403 if (!foundLabel) printf("\n");
1404
1405 RETURN(0);
1406 }
1407
1408 /* try to print the index of the specified label */
print_classic_info(THD_3dim_dataset * dset,char * dname,int verb)1409 int print_classic_info(THD_3dim_dataset * dset, char * dname, int verb)
1410 {
1411 char * outbuf;
1412 ENTRY("print_classic_info");
1413
1414 outbuf = THD_dataset_info( dset , verb ) ;
1415 if( outbuf != NULL ){
1416 printf("\n") ;
1417 puts(outbuf) ;
1418 free(outbuf) ; outbuf = NULL ;
1419 RETURN(0);
1420 } else {
1421 ERROR_message("Can't get info for dataset %s", dname);
1422 RETURN(1);
1423 }
1424 }
1425
1426