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 /* prototypes */
10
11 static int THD_setup_mastery( THD_3dim_dataset * , int * ) ;
12 static THD_3dim_dataset * THD_open_3dcalc( char * ) ;
13
14 /*-----------------------------------------------------------------
15 11 Jan 1999: Open a dataset, allowing for possible mastering.
16 21 Feb 2001: Allow for <a..b> sub-ranging as well.
17 26 Jul 2004: Change THD_setup_mastery to return int. [rickr]
18 Add THD_copy_dset_subs() function.
19 -------------------------------------------------------------------*/
20
THD_open_dataset(char * pathname)21 THD_3dim_dataset * THD_open_dataset( char *pathname )
22 {
23 THD_3dim_dataset *dset=NULL ;
24 char dname[THD_MAX_NAME+222]="\0" , *subv=NULL ; /* 8 May 2007 */
25 char *cpt=NULL , *bpt=NULL ;
26 int *ivlist=NULL ;
27 int ii=-1, jj=-1, kk=-1;
28 float bot=1.0 , top=0.0 ;
29 char *qname=NULL ;
30
31 ENTRY("THD_open_dataset") ;
32
33 /*-- sanity check --*/
34
35 if( pathname == NULL ||
36 (ii=strlen(pathname)) == 0 ||
37 pathname[ii-1] == '/' ) RETURN(NULL) ;
38
39 /*-- [16 Mar 2016] jRandomDataset:nx,ny,nz,nt --*/
40
41 if( strncasecmp(pathname,"jRandomDataset:",15) == 0 && isdigit(pathname[15]) ){
42 int nx=0,ny=0,nz=0,nt=0 ;
43 if( strchr(pathname+15,':') != NULL )
44 sscanf( pathname+15 , "%d:%d:%d:%d" , &nx,&ny,&nz,&nt ) ;
45 else
46 sscanf( pathname+15 , "%d,%d,%d,%d" , &nx,&ny,&nz,&nt ) ;
47 dset = jRandomDataset(nx,ny,nz,nt) ;
48 if( dset == NULL )
49 WARNING_message("can't decode %s",pathname) ;
50 else
51 THD_patch_brickim(dset) ;
52 RETURN(dset) ;
53 }
54
55 /*-- [23 Mar 2001] perhaps get from across the Web --*/
56
57 if( strncmp(pathname,"http://",7) == 0 ||
58 strncmp(pathname,"ftp://" ,6) == 0 ){
59
60 dset = THD_fetch_dataset( pathname ) ;
61 if( ISVALID_DSET(dset) &&
62 !ISVALID_MAT44(dset->daxes->ijk_to_dicom) ) /* 15 Dec 2005 */
63 THD_daxes_to_mat44(dset->daxes) ;
64 THD_patch_brickim(dset) ; /* 20 Oct 2006 */
65 RETURN(dset) ;
66 }
67
68 /*-- [17 Mar 2000] check if this is a 3dcalc() run --*/
69
70 if( strncmp(pathname,"3dcalc(",7) == 0 ||
71 strncmp(pathname,"3dcalc ",7) == 0 ){
72 dset = THD_open_3dcalc( pathname ) ;
73 if( ISVALID_DSET(dset) &&
74 !ISVALID_MAT44(dset->daxes->ijk_to_dicom) ) /* 15 Dec 2005 */
75 THD_daxes_to_mat44(dset->daxes) ;
76 THD_patch_brickim(dset) ; /* 20 Oct 2006 */
77 RETURN(dset) ;
78 }
79
80 /*-- allow filelist:FILENAME to work like tcat 23 Jul 2012 [rickr] */
81 if( ! strncmp(pathname,"filelist:",9) ) {
82 dset = THD_open_tcat( pathname ) ;
83 if( ISVALID_DSET(dset) &&
84 !ISVALID_MAT44(dset->daxes->ijk_to_dicom) ) /* 15 Dec 2005 */
85 THD_daxes_to_mat44(dset->daxes) ;
86 THD_patch_brickim(dset);
87 RETURN(dset) ;
88 }
89
90 /*-- [04 Aug 2004] allow input of a list of datasets, separated by spaces --*/
91 /* unless a count command is used inside the brackets 9 May 2007 drg*/
92 /* allow use of spaces with AFNI_PATH_SPACES_OK 2 May 2012 [rickr] */
93 if( ! AFNI_yesenv("AFNI_PATH_SPACES_OK") &&
94 (strchr(pathname,' ') != NULL ) &&
95 (strstr(pathname,"[count ")==NULL) &&
96 (strstr(pathname,"[1dcat ")==NULL) ) {
97 dset = THD_open_tcat( pathname ) ;
98 if( ISVALID_DSET(dset) &&
99 !ISVALID_MAT44(dset->daxes->ijk_to_dicom) ) /* 15 Dec 2005 */
100 THD_daxes_to_mat44(dset->daxes) ;
101 THD_patch_brickim(dset);
102 RETURN(dset) ;
103 }
104
105 /*-- 7 Apr 2016 [rickr]: allow wildcards --*/
106 if( HAS_WILDCARD(pathname) ) {
107 dset = THD_open_tcat( pathname ) ;
108 if( ISVALID_DSET(dset) && !ISVALID_MAT44(dset->daxes->ijk_to_dicom) )
109 THD_daxes_to_mat44(dset->daxes) ;
110 THD_patch_brickim(dset);
111 RETURN(dset) ;
112 }
113
114 /*-- expand "~/" to home directory [13 Feb 2008] (from here, must free qname if it was used) --*/
115
116 if( pathname[0] == '~' && pathname[1] == '/' ){
117 char *eee = getenv("HOME") ;
118 if( eee != NULL ){
119 qname = (char *)malloc(sizeof(char)*(strlen(pathname)+strlen(eee)+222));
120 strcpy(qname,eee); strcat(qname,pathname+1);
121 pathname = qname ;
122 }
123 }
124
125 /*-- [18 Oct 2016] check if input filename is super long --*/
126
127 if( (ii=strlen(pathname)) >= THD_MAX_NAME ){ /* super long */
128 static int first=1 ;
129 ERROR_message("The following dataset filename is too long for AFNI:\n"
130 " %s\n** Length(filename)=%d --> The dataset above WILL NOT BE OPENED :((",
131 pathname , ii ) ;
132 if( first ){
133 ERROR_message("(The longest filename allowed in AFNI is %d characters)",THD_MAX_NAME-1) ;
134 first = 0 ;
135 }
136 if( qname != NULL ) free(qname) ;
137 RETURN(NULL) ;
138 } else if( ii > THD_MAX_NAME/2 ){ /* just pretty long */
139 static int first=1 ;
140 WARNING_message("The following dataset filename is very long and might cause troubles:\n"
141 " %s\n * Length(filename)=%d !!" ,
142 pathname , ii ) ;
143 if( first ){
144 WARNING_message("(The longest filename allowed in AFNI is %d characters)",THD_MAX_NAME-1) ;
145 first = 0 ;
146 }
147 }
148
149 /*-- 04 Mar 2003: allow input of .1D files, which deals with [] itself --*/
150 /*-- 19 May 2012: [rickr] moved after spaces check (allow space cat) --*/
151 /*-- 18 Dec 2019: [rickr] tried, but cannot simply check suffix, as
152 there might be a single quote at the end or similar
153 - let this whine if .1D is the middle of a name? --*/
154
155 if( strstr(pathname,".1D") != NULL || strncmp(pathname,"1D:",3) == 0 ){
156 dset = THD_open_1D( pathname ) ;
157 if( ISVALID_DSET(dset) &&
158 !ISVALID_MAT44(dset->daxes->ijk_to_dicom) ) /* 15 Dec 2005 */
159 THD_daxes_to_mat44(dset->daxes) ;
160 if( dset != NULL ){ THD_patch_brickim(dset); if(qname!=NULL)free(qname); RETURN(dset); }
161 }
162
163 /*-- find the opening "[" and/or "<" --*/
164
165 cpt = strstr(pathname,"[") ;
166 bpt = strstr(pathname,"<") ; /* 21 Feb 2001 */
167 if( cpt == NULL && bpt == NULL ){ /* no "[" or "<" */
168 dset = THD_open_one_dataset( pathname ) ; /* ==> open */
169 if( ISVALID_DSET(dset) &&
170 !ISVALID_MAT44(dset->daxes->ijk_to_dicom) ) /* 15 Dec 2005 */
171 THD_daxes_to_mat44(dset->daxes) ;
172 THD_patch_brickim(dset); if(qname!=NULL)free(qname); RETURN(dset); /* normally */
173 }
174
175 if( cpt == pathname || bpt == pathname ){
176 if(qname!=NULL)free(qname); RETURN(NULL); /* error */
177 }
178
179 /* copy dataset filename to dname and selector string to subv */
180
181 ii = (cpt != NULL ) ? cpt - pathname : 999999 ;
182 jj = (bpt != NULL ) ? bpt - pathname : 999999 ;
183 kk = MIN(ii,jj) ;
184 memcpy(dname,pathname,kk) ; dname[kk] = '\0' ;
185
186 /* allow NIfTI extensions here 14 Apr 2006 [rickr] */
187 if( STRING_HAS_SUFFIX(dname,".mnc") ||
188 STRING_HAS_SUFFIX(dname,".mri") ||
189 STRING_HAS_SUFFIX(dname,".svl") ){
190 ERROR_message("Can't use selectors on dataset: %s",pathname) ;
191 if(qname!=NULL)free(qname); RETURN(NULL) ;
192 }
193
194 /* open the dataset */
195 dset = THD_open_one_dataset( dname ) ;
196 if( dset == NULL ){
197 if(qname!=NULL)free(qname); RETURN(NULL) ;
198 }
199
200 /* parse the sub-brick selector string (if any) */
201
202 if( cpt != NULL ){
203 char *qpt ;
204 subv = strdup(cpt);
205 /* strcpy(subv,cpt) ; don't assume length 8 May 2007 [rickr,dglen] */
206 qpt = strstr(subv,"<") ; if( qpt != NULL ) *qpt = '\0' ;
207 ivlist = MCW_get_thd_intlist( dset , subv ); /* ZSS Dec 09 */
208 free(subv) ;
209 }
210 if( ivlist == NULL ){
211 if( cpt != NULL ) {/* ZSS Dec 09 */
212 /* The condition used to issue a warning and proceed.
213 Now it fails. */
214 ERROR_message("bad sub-brick selector %s", cpt);
215 if(qname!=NULL)free(qname); RETURN(NULL) ;
216 }
217 ivlist = (int *) malloc(sizeof(int)*(DSET_NVALS(dset)+1)) ;
218 ivlist[0] = DSET_NVALS(dset) ;
219 for( kk=0 ; kk < ivlist[0] ; kk++ ) ivlist[kk+1] = kk ;
220 }
221
222 /* ************************************************ */
223 /* 21 Feb 2001: if present, load the sub-range data */
224
225 /* THD_init_one_datablock() was not called 14 Apr 2006 [rickr] */
226 if( STRING_HAS_SUFFIX(dname,".hdr") || STRING_HAS_SUFFIX(dname,".nia") ||
227 STRING_HAS_SUFFIX(dname,".nii") || STRING_HAS_SUFFIX(dname,".nii.gz") ||
228 STRING_HAS_SUFFIX(dname,".niml.dset") ||
229 STRING_HAS_SUFFIX(dname,".gii") || STRING_HAS_SUFFIX(dname,".gii.dset")){
230 dset->dblk->master_bot = 1.0 ;
231 dset->dblk->master_top = 0.0 ;
232 }
233
234 /* - moved to new function that goes after labels 17 Apr 2012 [rickr] */
235 /* - set single value, float .. range, or comma-delimited int list */
236 /* - fail on illegal angle selector */
237 if( bpt != NULL ) {
238 if( thd_check_angle_selector(dset, bpt) ) {
239 ERROR_message("bad angle bracket selector: %s", bpt);
240 RETURN(NULL);
241 }
242 }
243
244 /* modify the dataset according to the selector string */
245
246 THD_setup_mastery( dset , ivlist ) ;
247 free(ivlist) ;
248
249 if( ISVALID_DSET(dset) &&
250 !ISVALID_MAT44(dset->daxes->ijk_to_dicom) ) /* 15 Dec 2005 */
251 THD_daxes_to_mat44(dset->daxes) ;
252
253 THD_patch_brickim(dset); if(qname!=NULL)free(qname);
254 RETURN(dset);
255 }
256
257 /*-----------------------------------------------------------------
258 Set up a dataset for being mastered; that is, reading only
259 a subset of sub-bricks from the master .BRIK file.
260 -------------------------------------------------------------------*/
261
THD_setup_mastery(THD_3dim_dataset * dset,int * ivlist)262 static int THD_setup_mastery( THD_3dim_dataset *dset , int *ivlist )
263 {
264 int ibr , old_nvals , new_nvals ;
265 THD_datablock *dblk ;
266 int *btype , *ivl ;
267
268 float *old_brick_fac ;
269 int64_t *old_brick_bytes ;
270 char **old_brick_lab ;
271 char **old_brick_keywords ;
272 int *old_brick_statcode ;
273 float **old_brick_stataux ;
274 floatvec **old_brick_fdrcurve ; /* 23 Jan 2008 */
275 floatvec **old_brick_mdfcurve ; /* 22 Oct 2008 */
276
277 ENTRY("THD_setup_mastery") ;
278
279 /** sanity checks **/
280
281 if( ! ISVALID_DSET(dset) || ivlist == NULL || ivlist[0] <= 0 ) RETURN(1) ;
282
283 new_nvals = ivlist[0] ;
284 ivl = ivlist + 1 ;
285 dblk = dset->dblk ;
286 old_nvals = dblk->nvals ;
287
288 ibr = THD_count_databricks(dblk) ; if( ibr > 0 ) RETURN(2) ;
289
290 for( ibr=0 ; ibr < new_nvals ; ibr++ )
291 if( ivl[ibr] < 0 || ivl[ibr] >= old_nvals ) RETURN(3) ;
292
293 /** save pointers to old datablock stuff **/
294
295 old_brick_fac = dblk->brick_fac ; dblk->brick_fac = NULL ;
296 old_brick_bytes = dblk->brick_bytes ; dblk->brick_bytes = NULL ;
297 old_brick_lab = dblk->brick_lab ; dblk->brick_lab = NULL ;
298 old_brick_keywords = dblk->brick_keywords ; dblk->brick_keywords = NULL ;
299 old_brick_statcode = dblk->brick_statcode ; dblk->brick_statcode = NULL ;
300 old_brick_stataux = dblk->brick_stataux ; dblk->brick_stataux = NULL ;
301 old_brick_fdrcurve = dblk->brick_fdrcurve ; dblk->brick_fdrcurve = NULL ;
302 old_brick_mdfcurve = dblk->brick_mdfcurve ; dblk->brick_mdfcurve = NULL ;
303
304 /** setup new dataset brick structure **/
305
306 dblk->diskptr->nvals = dblk->nvals = new_nvals ;
307 dblk->malloc_type = DATABLOCK_MEM_MALLOC ;
308
309 if( dset->taxis != NULL ){ /* must fix time axis */
310 if( new_nvals == 1 ){ /* no time dependence */
311 myRwcFree( dset->taxis->toff_sl ) ;
312 myRwcFree( dset->taxis ) ;
313 } else { /* different number of times */
314 dset->taxis->ntt = new_nvals ;
315 }
316 } else { /* 21 Feb 2001: change to bucket type */
317
318 if( ISANAT(dset) && !ISANATBUCKET(dset) )
319 EDIT_dset_items( dset , ADN_func_type,ANAT_BUCK_TYPE , ADN_none ) ;
320 else if( ISFUNC(dset) && !ISFUNCBUCKET(dset) )
321 EDIT_dset_items( dset , ADN_func_type,FUNC_BUCK_TYPE , ADN_none ) ;
322
323 }
324
325 /* redo brick_fac */
326
327 dblk->brick_fac = (float *) RwcMalloc( sizeof(float) * new_nvals ) ;
328 for( ibr=0 ; ibr < new_nvals ; ibr++ )
329 dblk->brick_fac[ibr] = old_brick_fac[ivl[ibr]] ;
330
331 /* redo brick and brick_bytes */
332
333 btype = (int *) malloc( sizeof(int) * new_nvals ) ;
334 for( ibr=0 ; ibr < new_nvals ; ibr++ )
335 btype[ibr] = DBLK_BRICK_TYPE(dblk,ivl[ibr]) ;
336 THD_init_datablock_brick( dblk , new_nvals , btype ) ;
337 free(btype) ;
338
339 /* redo brick_lab */
340
341 if( old_brick_lab != NULL ){
342 for( ibr=0 ; ibr < new_nvals ; ibr++ )
343 THD_store_datablock_label( dblk , ibr , old_brick_lab[ivl[ibr]] ) ;
344 }
345
346 /* redo brick_keywords */
347
348 if( old_brick_keywords != NULL ){
349 for( ibr=0 ; ibr < new_nvals ; ibr++ )
350 THD_store_datablock_keywords( dblk , ibr , old_brick_keywords[ivl[ibr]] ) ;
351 }
352
353 /* redo brick_statcode and brick_stataux */
354
355 if( old_brick_statcode != NULL ){
356 for( ibr=0 ; ibr < new_nvals ; ibr++ )
357 THD_store_datablock_stataux( dblk, ibr, old_brick_statcode[ivl[ibr]] ,
358 999 , old_brick_stataux [ivl[ibr]] ) ;
359 }
360
361 /* redo brick_fdrcurve now */
362
363 if( old_brick_fdrcurve != NULL ){ /* 23 Jan 2008 */
364 floatvec *fv , *nv ;
365 dblk->brick_fdrcurve = (floatvec **)calloc(sizeof(floatvec *),new_nvals) ;
366 for( ibr=0 ; ibr < new_nvals ; ibr++ ){
367 fv = old_brick_fdrcurve[ivl[ibr]] ;
368 if( fv == NULL ){ nv = NULL; } else { COPY_floatvec(nv,fv); }
369 dblk->brick_fdrcurve[ibr] = nv ;
370 }
371 }
372
373 if( old_brick_mdfcurve != NULL ){ /* 22 Oct 2008 */
374 floatvec *fv , *nv ;
375 dblk->brick_mdfcurve = (floatvec **)calloc(sizeof(floatvec *),new_nvals) ;
376 for( ibr=0 ; ibr < new_nvals ; ibr++ ){
377 fv = old_brick_mdfcurve[ivl[ibr]] ;
378 if( fv == NULL ){ nv = NULL; } else { COPY_floatvec(nv,fv); }
379 dblk->brick_mdfcurve[ibr] = nv ;
380 }
381 }
382
383 /** setup master stuff now **/
384
385 dblk->master_nvals = old_nvals ;
386 dblk->master_bytes = old_brick_bytes ;
387 dblk->master_ival = (int *) RwcMalloc( sizeof(int) * new_nvals ) ;
388 for( ibr=0 ; ibr < new_nvals ; ibr++ ) dblk->master_ival[ibr] = ivl[ibr] ;
389
390 /** destroy old datablock stuff now **/
391
392 myRwcFree( old_brick_fac ) ;
393
394 if( old_brick_lab != NULL ){
395 for( ibr=0 ; ibr < old_nvals ; ibr++ ) myRwcFree( old_brick_lab[ibr] ) ;
396 myRwcFree( old_brick_lab ) ;
397 }
398
399 if( old_brick_keywords != NULL ){
400 for( ibr=0 ; ibr < old_nvals ; ibr++ ) myRwcFree( old_brick_keywords[ibr] ) ;
401 myRwcFree( old_brick_keywords ) ;
402 }
403
404 if( old_brick_statcode != NULL ) myRwcFree( old_brick_statcode ) ;
405 if( old_brick_stataux != NULL ){
406 for( ibr=0 ; ibr < old_nvals ; ibr++ ) myRwcFree( old_brick_stataux[ibr] ) ;
407 myRwcFree( old_brick_stataux ) ;
408 }
409
410 if( old_brick_fdrcurve != NULL ){ /* 24 Jan 2008 */
411 for( ibr=0 ; ibr < old_nvals ; ibr++ )
412 KILL_floatvec( old_brick_fdrcurve[ibr] ) ;
413 free(old_brick_fdrcurve) ;
414 }
415 if( old_brick_mdfcurve != NULL ){ /* 22 Oct 2008 */
416 for( ibr=0 ; ibr < old_nvals ; ibr++ )
417 KILL_floatvec( old_brick_mdfcurve[ibr] ) ;
418 free(old_brick_mdfcurve) ;
419 }
420
421 /** if dataset has statistics, rearrange them **/
422
423 if( ISVALID_STATISTIC(dset->stats) ){
424 THD_statistics * new_stats , * old_stats ;
425 THD_brick_stats * bsold , * bsnew ;
426 float bot,top ;
427
428 old_stats = dset->stats ;
429 new_stats = myRwcNew( THD_statistics ) ;
430 new_stats->type = STATISTICS_TYPE ;
431 new_stats->parent = (RwcPointer) dset ;
432 new_stats->bstat = NULL ;
433
434 bsold = old_stats->bstat ;
435 bsnew = new_stats->bstat =
436 (THD_brick_stats *) RwcCalloc( new_nvals , sizeof(THD_brick_stats) ) ;
437
438 new_stats->nbstat = new_nvals ;
439
440 for( ibr=0 ; ibr < new_nvals ; ibr++ ){
441 if( ibr < old_stats->nbstat ) bsnew[ibr] = bsold[ivl[ibr]] ;
442 else INVALIDATE_BSTAT( bsnew[ibr] ) ;
443 }
444
445 REPLACE_KILL( dset->kl , bsold , bsnew ) ;
446 REPLACE_KILL( dset->kl , old_stats , new_stats ) ;
447 dset->stats = new_stats ;
448
449 myRwcFree(bsold) ; myRwcFree(old_stats) ;
450
451 /* 21 Feb 2001: mangle statistics if sub-ranging is used */
452
453 /* rcr - also if csv list is applied */
454
455 bot = dset->dblk->master_bot ; top = dset->dblk->master_top ;
456 if( bot <= top ){
457 if( bot > 0.0 ) bot = 0.0 ;
458 else if( top < 0.0 ) top = 0.0 ;
459
460 for( ibr=0 ; ibr < new_nvals ; ibr++ ){
461 if( ISVALID_BSTAT(bsnew[ibr]) ){
462 if( bsnew[ibr].min < bot ) bsnew[ibr].min = bot ;
463 if( bsnew[ibr].max > top ) bsnew[ibr].max = top ;
464 }
465 }
466 }
467 }
468
469 RETURN(0) ;
470 }
471
472 /*----------------------------------------------------------------------
473 Run 3dcalc to create a dataset and read it in.
474 -- RWCox - 17 Mar 2000
475 -- Modified 24 Jul 2009 to use unique name each time, fer shur
476 ------------------------------------------------------------------------*/
477
478 #include <sys/types.h>
479 #include <sys/wait.h>
480
THD_open_3dcalc(char * pname)481 static THD_3dim_dataset * THD_open_3dcalc( char *pname )
482 {
483 int Argc=1 , newArgc=0 , ii,ll ;
484 char *Argv[1]={ "3dcalc" } , **newArgv=NULL ;
485 char *qname , *tdir , prefix[128] , *uuid ;
486 pid_t child_pid ;
487 THD_3dim_dataset *dset ;
488
489 ENTRY("THD_open_3dcalc") ;
490
491 /*-- remove the "3dcalc(" and the ")" from the input string --*/
492
493 qname = (char *) malloc(sizeof(char)*(strlen(pname)+4096)) ;
494 strcpy(qname,pname+7) ;
495 ll = strlen(qname) ;
496 for( ii=ll-1 ; ii > 0 && isspace(qname[ii]) ; ii-- ) ; /*nada*/
497 if( ii == 0 ){ free(qname) ; RETURN(NULL) ; } /* all blanks? */
498 if( qname[ii] == ')' && isspace(qname[ii-1]) )
499 qname[ii] = '\0' ; /* remove trailing ' )' */
500
501 /*-- add -session to command string --*/
502
503 tdir = my_getenv("TMPDIR") ;
504 if( tdir == NULL || strlen(tdir) > 512 ) tdir = "/tmp" ;
505 strcat(qname," -session ") ; strcat(qname,tdir) ; ll = strlen(tdir) ;
506
507 /*-- add -prefix to command string --*/
508
509 for( ii=0 ; ii < 9999 ; ii++ ){ /* create dataset name */
510 uuid = UNIQ_idcode() ;
511 sprintf(prefix,"3dcalc_%s",uuid) ; free(uuid) ;
512 if( THD_is_dataset(tdir,prefix,-1) == -1 ) break ;
513 }
514 if( ii >= 9999 ){ /* should never happen */
515 ERROR_message("Can't find unused 3dcalc_ dataset name in %s!",tdir) ;
516 free(qname) ; RETURN(NULL) ;
517 }
518
519 strcat(qname," -prefix ") ; strcat(qname,prefix) ;
520 strcat(qname," -verbose") ;
521
522 /*-- add a placeholder to be the last argument --*/
523
524 strcat(qname," Zork") ;
525
526 /*-- create the arg list for 3dcalc, starting with program name --*/
527
528 append_string_to_args( qname , Argc , Argv , &newArgc , &newArgv ) ;
529
530 free(qname) ; /* not needed no more */
531
532 /*-- check if arg list was created OK --*/
533
534 if( newArgv == NULL ) RETURN(NULL) ; /* something bad? */
535
536 if( newArgc < 3 ){ /* too few args to 3dcalc */
537 for( ii=0 ; ii < newArgc ; ii++ ) free(newArgv[ii]) ;
538 free(newArgv) ; RETURN(NULL) ;
539 }
540
541 /*-- replace placeholder in arg list with NULL pointer --*/
542
543 free( newArgv[newArgc-1] ) ; newArgv[newArgc-1] = NULL ;
544
545 /*-- fork and exec --*/
546
547 INFO_message("Executing 3dcalc()") ;
548 #if 1
549 for(ii=0; ii< newArgc-1; ii++)
550 fprintf(stderr," argv[%d]=%s",ii,newArgv[ii]);
551 fprintf(stderr,"\n") ;
552 #endif
553
554 child_pid = fork() ;
555
556 if( child_pid == (pid_t)(-1) ){
557 perror("*** Can't fork 3dcalc()") ;
558 for( ii=0 ; ii < newArgc-1 ; ii++ ) free(newArgv[ii]) ;
559 free(newArgv) ; RETURN(NULL) ;
560 }
561
562 if( child_pid == 0 ){ /*-- I'm the child --*/
563
564 execvp( "3dcalc" , newArgv ) ; /* should not return */
565 perror("*** Can't execvp 3dcalc()") ;
566 _exit(1) ;
567
568 }
569
570 /*-- I'm the parent --*/
571
572 STATUS("Waiting for 3dcalc() process to run") ;
573
574 (void) waitpid( child_pid , NULL , 0 ) ; /* wait for child to exit */
575
576 ii = THD_is_dataset( tdir , prefix , -1 ) ;
577 if( ii == -1 ){
578 ERROR_message("3dcalc() failed - no dataset created!") ;
579 RETURN(NULL) ;
580 }
581 qname = THD_dataset_headname( tdir , prefix , ii ) ;
582 dset = THD_open_one_dataset( qname ) ; /* try to read result */
583
584 for( ii=0 ; ii < newArgc-1 ; ii++ ) free(newArgv[ii]) ; /* toss trash */
585 free(newArgv) ; free(qname) ;
586
587 if( dset == NULL ){ /* read failed */
588 ERROR_message("3dcalc() failed - can't read dataset!") ;
589 RETURN(NULL) ;
590 }
591
592 /* read dataset into memory */
593
594 DSET_mallocize(dset) ; DSET_load(dset) ;
595 if( !DSET_LOADED(dset) ){ /* can't read it? */
596 THD_delete_3dim_dataset( dset , True ) ; /* kill it dead */
597 ERROR_message("3dcalc() failed - can't load dataset!") ;
598 RETURN(NULL) ;
599 }
600
601 /* lock dataset into memory, delete its files */
602
603 DSET_lock(dset) ;
604 unlink( dset->dblk->diskptr->header_name ) ;
605 COMPRESS_unlink( dset->dblk->diskptr->brick_name ) ;
606
607 /* 30 Jul 2003: changes its directory to cwd */
608
609 EDIT_dset_items( dset , ADN_directory_name , "./" , ADN_none ) ;
610
611 if( ISVALID_DSET(dset) &&
612 !ISVALID_MAT44(dset->daxes->ijk_to_dicom) ) /* 15 Dec 2005 */
613 THD_daxes_to_mat44(dset->daxes) ;
614
615 RETURN(dset) ;
616 }
617
618 /*-----------------------------------------------------------------
619 Convenience function, for copying only a single sub-brick.
620 Wrapper for THD_copy_dset_subs().
621 -------------------------------------------------------------------*/
THD_copy_one_sub(THD_3dim_dataset * din,int sub)622 THD_3dim_dataset * THD_copy_one_sub( THD_3dim_dataset * din, int sub )
623 {
624 int sublist[2] = {1, sub};
625 return THD_copy_dset_subs(din, sublist);
626 }
627
628 /*-----------------------------------------------------------------
629 Copy a list of sub-bricks from a dataset. 26 Jul 2004 [rickr]
630 The first element of dlist is the number of sub-bricks to copy.
631 -------------------------------------------------------------------*/
THD_copy_dset_subs(THD_3dim_dataset * din,int * dlist)632 THD_3dim_dataset * THD_copy_dset_subs( THD_3dim_dataset * din, int * dlist )
633 {
634 THD_3dim_dataset * dout;
635 MRI_TYPE kind;
636 char * newdata;
637 int sub, subs;
638 int dsize, nxyz, rv;
639
640 ENTRY("THD_copy_dset_subs");
641
642 /* validate inputs */
643 if ( !din || !dlist )
644 {
645 fprintf(stderr, "** THD_copy_dset_subs: bad input (%p,%p)\n",
646 din,dlist);
647 RETURN(NULL);
648 }
649
650 if ( dlist[0] <= 0 )
651 {
652 fprintf(stderr,"** THD_copy_dset_subs: invalid dlist length %d\n",
653 dlist[0]);
654 RETURN(NULL);
655 }
656
657 /* verify that the input sub-brick list hold valid indices */
658 subs = dlist[0];
659 for ( sub = 0; sub < subs; sub++ )
660 {
661 if( dlist[sub+1] < 0 || dlist[sub+1] >= din->dblk->nvals )
662 {
663 fprintf(stderr,
664 "** THD_copy_dset_subs: index %d outside sub-brick range [0,%d]\n",
665 dlist[sub+1], din->dblk->nvals);
666 RETURN(NULL);
667 }
668 }
669
670 /* create initial dataset */
671 dout = EDIT_empty_copy(din);
672
673 /* use mastery to copy selected labels, statistics, etc. */
674 rv = THD_setup_mastery(dout, dlist);
675 if ( rv != 0 )
676 {
677 fprintf(stderr, "** failure: THD_setup_mastery() returned %d\n", rv);
678 RETURN(NULL);
679 }
680
681 /* be sure that we have some data to copy */
682 DSET_load(din);
683 if ( ! DSET_LOADED(din) )
684 {
685 fprintf(stderr,"** THD_copy_dset_subs: cannot load input dataset\n");
686 RETURN(NULL);
687 }
688
689 /* do not create any warp structure here, since data will be inserted */
690
691 dout->dblk->diskptr->byte_order = mri_short_order();
692 dout->dblk->diskptr->storage_mode = STORAGE_BY_BRICK;
693
694 /* now copy all of the sub-bricks */
695 nxyz = dout->daxes->nxx * dout->daxes->nyy * dout->daxes->nzz;
696 subs = dlist[0];
697 for ( sub = 0; sub < subs; sub++ )
698 {
699 kind = DSET_BRICK_TYPE(dout, sub);
700 dsize = mri_datum_size( kind );
701 if ( (newdata = (char *)malloc( nxyz * dsize )) == NULL )
702 {
703 fprintf( stderr, "r frdb: alloc failure: %d bytes!\n",
704 nxyz * dsize );
705 DSET_delete(dout);
706 RETURN(NULL);
707 }
708
709 memcpy(newdata,DSET_ARRAY(din,dlist[sub+1]), nxyz*dsize);
710 EDIT_substitute_brick(dout, sub, kind, (void *)newdata);
711 }
712
713 /* clear mastery information, since data is already stored */
714 if( DBLK_IS_MASTERED(dout->dblk) ){
715 dout->dblk->master_nvals = 0;
716 myRwcFree( dout->dblk->master_ival );
717 myRwcFree( dout->dblk->master_bytes );
718 }
719
720 dout->dblk->malloc_type = DATABLOCK_MEM_MALLOC;
721 dout->wod_flag = False; /* since data is now in memory */
722
723 RETURN(dout);
724 }
725
726 /*------------------------------------------------------------------------*/
727 /* Given a dataset selector like "name[1..3]", return individual selectors
728 like "name[1]", "name[2]", "name[3]". The reason for this is for older
729 programs like 3dttest that operate on a list of single brick datasets.
730 [19 Jul 2007 - RWCox]
731 Modified to allow use of labelized lists (per ZSS) -- 09 Dec 2011.
732 --------------------------------------------------------------------------*/
733
THD_multiplex_dataset(char * pathname)734 THD_string_array * THD_multiplex_dataset( char *pathname )
735 {
736 char *cpt , *pname , *bname ;
737 int *ivlist=NULL , ii ;
738 THD_string_array *sar ;
739 THD_3dim_dataset *qset ;
740
741 ENTRY("THD_multiplex_dataset") ;
742 if( pathname == NULL ) RETURN(NULL) ;
743 cpt = strstr(pathname,"[") ; if( cpt == NULL ) RETURN(NULL) ;
744
745 bname = strdup(pathname) ; cpt = strstr(bname,"[") ; *cpt = '\0' ;
746 if( STRING_HAS_SUFFIX(bname,".mnc") ||
747 STRING_HAS_SUFFIX(bname,".mri") ||
748 STRING_HAS_SUFFIX(bname,".svl") ){
749 ERROR_message("Can't use sub-brick selectors '[...]' on dataset %s",bname) ;
750 free(bname) ; RETURN(NULL) ;
751 }
752 qset = THD_open_one_dataset(bname) ; /* 09 Dec 2011 */
753 if( !ISVALID_DSET(qset) ){
754 ERROR_message("Can't open dataset %s",bname) ; free(bname) ; RETURN(NULL) ;
755 }
756 ivlist = MCW_get_thd_intlist(qset,cpt+1) ; DSET_delete(qset) ;
757 if( ivlist == NULL || ivlist[0] == 0 ){ free(bname); RETURN(NULL); }
758
759 INIT_SARR(sar) ;
760 pname = malloc(sizeof(char)*(strlen(bname)+16)) ;
761 for( ii=1 ; ii <= ivlist[0] ; ii++ ){
762 sprintf(pname,"%s[%d]",bname,ivlist[ii]) ;
763 ADDTO_SARR(sar,pname) ; /* makes a copy */
764 }
765
766 free(pname); free(ivlist); free(bname); RETURN(sar);
767 }
768