2
fslio.c (Input and output routines for images in FSL)
5
FMRIB Image Analysis Group
12
The fslio.c file was originally part of FSL - FMRIB's Software Library
13
http://www.fmrib.ox.ac.uk/fsl
14
fslio.c has now been placed in the public domain.
16
Developed at FMRIB (Oxford Centre for Functional Magnetic Resonance
17
Imaging of the Brain), Department of Clinical Neurology, Oxford
18
University, Oxford, UK
23
\brief Main collection of FSL i/o routines, written by Mark Jenkinson, FMRIB
25
- updates by Rick Reynolds, SSCC, NIMH
31
static int FslIgnoreMFQ=0;
32
static int FslOverrideOutputType=-1;
34
#define FSLIOERR(x) { fprintf(stderr,"Error:: %s\n",(x)); fflush(stderr); exit(EXIT_FAILURE); }
37
/************************************************************
39
************************************************************/
40
/*! \fn char* FslFileTypeString(int filetype)
41
\brief Return a string describing the format of the dataset
42
\param filetype FSL data format code. Legal values are as defined
44
\return A string with the data format name, e.g. "ANALYZE-7.5"
47
char* FslFileTypeString(int filetype)
49
if (filetype==FSL_TYPE_ANALYZE) return "ANALYZE-7.5";
50
if (filetype==FSL_TYPE_NIFTI) return "NIFTI-1+";
51
if (filetype==FSL_TYPE_NIFTI_PAIR) return "NIFTI-1";
52
if (filetype==FSL_TYPE_ANALYZE_GZ) return "ANALYZE-7.5";
53
if (filetype==FSL_TYPE_NIFTI_GZ) return "NIFTI-1+";
54
if (filetype==FSL_TYPE_NIFTI_PAIR_GZ) return "NIFTI-1";
59
int FslIsValidFileType(int filetype)
61
if ( (filetype!=FSL_TYPE_ANALYZE) && (filetype!=FSL_TYPE_ANALYZE_GZ) &&
62
(filetype!=FSL_TYPE_NIFTI) && (filetype!=FSL_TYPE_NIFTI_GZ) &&
63
(filetype!=FSL_TYPE_NIFTI_PAIR) && (filetype!=FSL_TYPE_NIFTI_PAIR_GZ) &&
64
(filetype!=FSL_TYPE_MINC) && (filetype!=FSL_TYPE_MINC_GZ) ) {
65
fprintf(stderr,"Error: unrecognised file type: %d\n",filetype);
72
int FslBaseFileType(int filetype)
74
/* returns -1 to indicate error - unrecognised filetype */
75
if ( (filetype==FSL_TYPE_ANALYZE_GZ) || (filetype==FSL_TYPE_ANALYZE) )
76
return FSL_TYPE_ANALYZE;
77
if ( (filetype==FSL_TYPE_NIFTI_GZ) || (filetype==FSL_TYPE_NIFTI) )
78
return FSL_TYPE_NIFTI;
79
if ( (filetype==FSL_TYPE_NIFTI_PAIR_GZ) || (filetype==FSL_TYPE_NIFTI_PAIR) )
80
return FSL_TYPE_NIFTI_PAIR;
81
if ( (filetype==FSL_TYPE_MINC_GZ) || (filetype==FSL_TYPE_MINC) )
83
fprintf(stderr,"Error: unrecognised file type (%d)\n",filetype);
88
int FslGetFileType2(const FSLIO *fslio, int quiet)
91
if (fslio==NULL) FSLIOERR("FslGetFileType: Null pointer passed for FSLIO");
92
if ( (fslio->file_mode==FSL_TYPE_MINC) || (fslio->file_mode==FSL_TYPE_MINC_GZ) ) {
93
return fslio->file_mode;
95
if ( !FslIsValidFileType(fslio->file_mode) ) return -1;
97
if (fslio->niftiptr!=NULL) { /* check that it is nifti_type and filetype are consistent */
98
if (fslio->niftiptr->nifti_type != FslBaseFileType(fslio->file_mode)) {
100
fprintf(stderr,"Warning: nifti structure and fsl structure disagree on file type\n");
101
fprintf(stderr,"nifti = %d and fslio = %d\n",fslio->niftiptr->nifti_type,fslio->file_mode);
103
mutablefslio = (FSLIO *) fslio; /* dodgy and will generate warnings */
104
mutablefslio->niftiptr->nifti_type = FslBaseFileType(fslio->file_mode);
105
return fslio->file_mode;
108
return fslio->file_mode;
111
int FslGetFileType(const FSLIO *fslio)
113
return FslGetFileType2(fslio,0);
118
void FslSetFileType(FSLIO *fslio, int filetype)
120
if (fslio==NULL) FSLIOERR("FslSetFileType: Null pointer passed for FSLIO");
121
if ( (filetype==FSL_TYPE_MINC) || (filetype==FSL_TYPE_MINC_GZ) ) {
122
fslio->file_mode = filetype;
125
if (! FslIsValidFileType(filetype)) { return; }
126
fslio->file_mode = filetype; /* indicates general nifti - details in niftiptr */
127
if (fslio->niftiptr!=NULL) {
128
fslio->niftiptr->nifti_type = FslBaseFileType(filetype);
129
nifti_set_iname_offset(fslio->niftiptr);
135
int FslIsSingleFileType(int filetype)
137
if ( (filetype==FSL_TYPE_NIFTI) || (filetype==FSL_TYPE_NIFTI_GZ) ||
138
(filetype==FSL_TYPE_MINC) || (filetype==FSL_TYPE_MINC_GZ) )
144
int FslIsCompressedFileType(int filetype)
146
if ( filetype >=100 ) return 1;
151
int FslGetWriteMode(const FSLIO *fslio)
153
if (fslio==NULL) FSLIOERR("FslGetWriteMode: Null pointer passed for FSLIO");
154
return fslio->write_mode;
158
void FslSetWriteMode(FSLIO *fslio, int mode)
160
if (fslio==NULL) FSLIOERR("FslSetWriteMode: Null pointer passed for FSLIO");
161
fslio->write_mode = mode;
165
int FslGetEnvOutputType(void)
167
/* return type is one of FSL_TYPE_* or -1 to indicate error */
169
if (FslOverrideOutputType>=0) return FslOverrideOutputType;
170
otype = getenv("FSLOUTPUTTYPE");
172
fprintf(stderr,"ERROR:: Environment variable FSLOUTPUTTYPE is not set!\n");
173
fprintf(stderr,"Please make sure that the appropriate configuration file is sourced by your shell (e.g. by putting it in .profile).\n");
174
fprintf(stderr,"e.g. bash or sh users add the line \". ${FSLDIR}/etc/fslconf/fsl.sh\"\n");
175
fprintf(stderr,"e.g. tcsh or csh users add the line \"source ${FSLDIR}/etc/fslconf/fsl.csh\"\n");
178
if (strcmp(otype,"NIFTI")==0) { return FSL_TYPE_NIFTI; }
179
if (strcmp(otype,"NIFTI_GZ")==0) { return FSL_TYPE_NIFTI_GZ; }
180
if (strcmp(otype,"NIFTI_PAIR")==0) { return FSL_TYPE_NIFTI_PAIR; }
181
if (strcmp(otype,"NIFTI_PAIR_GZ")==0) { return FSL_TYPE_NIFTI_PAIR_GZ; }
182
fprintf(stderr,"ERROR:: Unrecognised value (%s) of environment variable FSLOUTPUTTYPE\n",otype);
183
fprintf(stderr,"Legal values are: NIFTI, NIFTI_PAIR, NIFTI_GZ, NIFTI_PAIR_GZ\n");
189
int FslFileType(const char* fname)
191
/* return type is FSL_TYPE_* or -1 to indicate undetermined */
192
/* use name as first priority but if that is ambiguous then resolve using environment */
195
if (fname==NULL) return retval;
196
flen = strlen(fname);
197
/* group conditions to avoid possible illegal memory access */
198
if (flen<5) return retval; /* smallest name + extension is a.nii */
199
if (strcmp(fname + flen - 4,".nii")==0) retval=FSL_TYPE_NIFTI;
200
if (strcmp(fname + flen - 4,".mnc")==0) retval=FSL_TYPE_MINC;
201
if (strcmp(fname + flen - 4,".hdr")==0) retval=FSL_TYPE_NIFTI_PAIR;
202
if (strcmp(fname + flen - 4,".img")==0) retval=FSL_TYPE_NIFTI_PAIR;
203
if ((retval==-1) && (flen<8)) return retval; /* small name + ext.gz is a.nii.gz */
204
if (strcmp(fname + flen - 7,".mnc.gz")==0) retval=FSL_TYPE_MINC;
205
if (strcmp(fname + flen - 7,".nii.gz")==0) retval=FSL_TYPE_NIFTI_GZ;
206
if (strcmp(fname + flen - 7,".hdr.gz")==0) retval=FSL_TYPE_NIFTI_PAIR_GZ;
207
if (strcmp(fname + flen - 7,".img.gz")==0) retval=FSL_TYPE_NIFTI_PAIR_GZ;
208
if ( (retval==FSL_TYPE_NIFTI_PAIR) || (retval==FSL_TYPE_NIFTI_PAIR_GZ) ) {
209
/* If it was hdr or img, check if Analyze was requested by environment */
210
if ( (FslGetEnvOutputType() == FSL_TYPE_ANALYZE) && (retval == FSL_TYPE_NIFTI_PAIR) )
211
retval=FSL_TYPE_ANALYZE;
212
if ( (FslGetEnvOutputType() == FSL_TYPE_ANALYZE_GZ) && (retval == FSL_TYPE_NIFTI_PAIR_GZ) )
213
retval=FSL_TYPE_ANALYZE_GZ;
219
/************************************************************
221
************************************************************/
222
/*! \fn int FslGetReadFileType(const FSLIO *fslio)
223
\brief return the best estimate of the true file type
225
This function is used to return the best estimate of the true file type once
226
a simple open has occurred - for now it is used after a nifti open call is made
228
\param fslio data structure
229
\return FSL_TYPE filetype code
232
int FslGetReadFileType(const FSLIO *fslio)
234
int filetype=FSL_TYPE_ANALYZE; /* unused default */
235
if (fslio==NULL) FSLIOERR("FslReadGetFileType: Null pointer passed for FSLIO");
236
/* Don't use fslio->file_mode as it hasn't been set yet */
237
if (fslio->niftiptr!=NULL) {
238
/* use the nifti_type and hdr or img name to determine the actual type */
239
if (fslio->niftiptr->nifti_type == FSL_TYPE_ANALYZE) {
240
if (FslIsCompressedFileType(FslFileType(fslio->niftiptr->iname))) {
241
filetype = FSL_TYPE_ANALYZE_GZ;
243
filetype = FSL_TYPE_ANALYZE;
246
if (fslio->niftiptr->nifti_type == FSL_TYPE_NIFTI_PAIR) {
247
if (FslIsCompressedFileType(FslFileType(fslio->niftiptr->iname))) {
248
filetype = FSL_TYPE_NIFTI_PAIR_GZ;
250
filetype = FSL_TYPE_NIFTI_PAIR;
253
if (fslio->niftiptr->nifti_type == FSL_TYPE_NIFTI) {
254
if (FslIsCompressedFileType(FslFileType(fslio->niftiptr->fname))) {
255
filetype = FSL_TYPE_NIFTI_GZ;
257
filetype = FSL_TYPE_NIFTI;
262
if (fslio->mincptr!=NULL) {
263
fprintf(stderr,"Warning:: Minc is not yet supported\n");
264
filetype = FSL_TYPE_MINC;
269
int FslFileExists(const char *filename)
271
/* return 1 if file(s) exists, otherwise return 0 */
272
char *hdrname = nifti_findhdrname(filename);
273
char *imgname = NULL;
275
imgname = nifti_findimgname(filename,
276
FslBaseFileType(FslFileType(hdrname)));
278
if (imgname != NULL) { free(imgname); return 1; }
283
char *FslMakeBaseName(const char *fname)
287
basename = nifti_makebasename(fname);
288
blen = strlen(basename);
290
if ((blen>7) && (strcmp(basename + blen-7,".mnc.gz") == 0))
291
{ basename[blen-7]='\0'; return basename; }
293
if ((blen>4) && (strcmp(basename + blen-4,".mnc") == 0))
294
{ basename[blen-4]='\0'; return basename; }
299
void FslGetHdrImgNames(const char* filename, const FSLIO* fslio,
300
char** hdrname, char** imgname)
304
basename = FslMakeBaseName(filename);
305
*hdrname = (char *)calloc(sizeof(char),strlen(basename)+8);
306
*imgname = (char *)calloc(sizeof(char),strlen(basename)+8);
307
strcpy(*hdrname,basename);
308
strcpy(*imgname,basename);
309
filetype = FslGetFileType(fslio);
310
if (filetype==FSL_TYPE_NIFTI_GZ) {
311
strcat(*hdrname,".nii.gz");
312
strcat(*imgname,".nii.gz");
316
if (filetype==FSL_TYPE_NIFTI) {
317
strcat(*hdrname,".nii");
318
strcat(*imgname,".nii");
322
if (filetype==FSL_TYPE_MINC_GZ) {
323
strcat(*hdrname,".mnc.gz");
324
strcat(*imgname,".mnc.gz");
328
if (filetype==FSL_TYPE_MINC) {
329
strcat(*hdrname,".mnc");
330
strcat(*imgname,".mnc");
334
if ( (filetype==FSL_TYPE_NIFTI_PAIR_GZ) || (filetype==FSL_TYPE_ANALYZE_GZ) ) {
335
strcat(*hdrname,".hdr.gz");
336
strcat(*imgname,".img.gz");
340
if ( (filetype==FSL_TYPE_NIFTI_PAIR) || (filetype==FSL_TYPE_ANALYZE) ) {
341
strcat(*hdrname,".hdr");
342
strcat(*imgname,".img");
347
fprintf(stderr,"Error: Unrecognised filetype (%d)\n",FslGetFileType(fslio));
357
/***************************************************************
359
***************************************************************/
360
/*! \fn FSLIO *FslInit()
361
\brief allocate space for the FSLIO struct and set some sensible defaults
362
\return A pointer to an initialized FSLIO data structure
367
fslio = (FSLIO *) calloc(1,sizeof(FSLIO));
372
void FslSetInit(FSLIO* fslio)
374
/* set some sensible defaults */
375
fslio->niftiptr = NULL;
376
fslio->mincptr = NULL;
377
FslSetFileType(fslio,FslGetEnvOutputType());
378
FslSetWriteMode(fslio,0);
379
fslio->written_hdr = 0;
384
void FslInit4Write(FSLIO* fslio, const char* filename, int ft)
386
/* ft determines filetype if ft>=0*/
389
FslSetWriteMode(fslio,1);
391
/* Determine file type from image name (first priority) or environment (default) */
393
imgtype = FslGetEnvOutputType();
395
if (ft >= 0) imgtype = ft;
397
if (!FslIsValidFileType(imgtype)) {
398
fprintf(stderr,"Error: Failed to determine file type for writing in FslOpen()\n");
402
if ( (FslBaseFileType(imgtype)!=FSL_TYPE_MINC) ) {
403
FslInitHeader(fslio, NIFTI_TYPE_FLOAT32,
404
1, 1, 1, 3, 0.0, 0.0, 0.0, 0.0, 4, "mm");
406
FslSetFileType(fslio,imgtype); /* this is after InitHeader as niftiptr set there */
408
/* determine the header and image filename */
409
FslGetHdrImgNames(filename,fslio,&(fslio->niftiptr->fname),&(fslio->niftiptr->iname));
410
if ( (fslio->niftiptr->fname == NULL) || (fslio->niftiptr->iname == NULL) ) {
411
fprintf(stderr,"Error: cannot find filenames for %s\n",filename);
414
} else if (FslBaseFileType(imgtype)==FSL_TYPE_MINC) {
415
fprintf(stderr,"Warning:: Minc is not yet supported\n");
418
fprintf(stderr,"Error:: unrecognised image type requested\n");
427
void FslInitHeader(FSLIO *fslio, short t,
428
size_t x, size_t y, size_t z, size_t v,
429
float vx, float vy, float vz, float tr,
433
/* NB: This function does not set the file type or write mode*/
435
if (fslio==NULL) FSLIOERR("FslInitHeader: Null pointer passed for FSLIO");
437
fslio->niftiptr = nifti_simple_init_nim();
438
/* make nifti type consistent with fslio */
439
fslio->niftiptr->nifti_type = FslBaseFileType(fslio->file_mode);
441
fslio->mincptr = NULL;
443
FslSetDataType(fslio,t);
444
FslSetDim(fslio,x,y,z,v);
445
FslSetVoxDim(fslio,vx,vy,vz,tr);
446
FslSetTimeUnits(fslio,"s");
447
FslSetDimensionality(fslio,dim);
451
void FslCloneHeader(FSLIO *dest, const FSLIO *src)
453
/* only clone the information that is stored in the disk version of the header */
454
/* - therefore _not_ the filenames, output type, write mode, etc */
456
char *fname=NULL, *iname=NULL;
458
int filetype, writemode;
459
int preserve_nifti_values = 0;
460
if (dest==NULL) FSLIOERR("FslCloneHeader: Null pointer passed for FSLIO");
461
if (src==NULL) FSLIOERR("FslCloneHeader: Null pointer passed for FSLIO");
463
if (src->niftiptr!=NULL) {
464
/* preserve the filenames, output type and write mode */
465
if (dest->niftiptr != NULL) {
466
fname = dest->niftiptr->fname;
467
iname = dest->niftiptr->iname;
468
data = dest->niftiptr->data;
469
preserve_nifti_values = 1;
471
filetype = FslGetFileType2(dest,1);
472
writemode = FslGetWriteMode(dest);
474
/* copy _all_ info across */
475
dest->niftiptr = nifti_copy_nim_info(src->niftiptr);
477
/* restore old values */
478
if (preserve_nifti_values) {
479
dest->niftiptr->fname = fname;
480
dest->niftiptr->iname = iname;
481
dest->niftiptr->data = data;
483
/* destroy the values that the nifti copy creates */
484
free(dest->niftiptr->fname);
485
free(dest->niftiptr->iname);
486
nifti_free_extensions(dest->niftiptr);
487
dest->niftiptr->fname = NULL;
488
dest->niftiptr->iname = NULL;
489
dest->niftiptr->data = NULL; /* should already be NULL */
491
FslSetFileType(dest,filetype);
492
FslSetWriteMode(dest,writemode);
495
if (src->mincptr!=NULL) {
496
fprintf(stderr,"Warning:: Minc is not yet supported\n");
502
int fsl_fileexists(const char* fname)
505
fp = znzopen( fname , "rb" , 1 ) ;
506
if( !znz_isnull(fp) ) { znzclose(fp); return 1; }
511
int FslCheckForMultipleFileNames(const char* filename)
513
char *basename, *tmpname;
514
int singlecount=0, hdrcount=0, imgcount=0, ambiguous=0;
515
basename = nifti_makebasename(filename);
516
tmpname = (char *)calloc(strlen(basename) + 10,sizeof(char));
518
strcpy(tmpname,basename);
519
strcat(tmpname,".nii");
520
if (fsl_fileexists(tmpname)) { singlecount++; }
521
strcpy(tmpname,basename);
522
strcat(tmpname,".nii.gz");
523
if (fsl_fileexists(tmpname)) { singlecount++; }
524
strcpy(tmpname,basename);
525
strcat(tmpname,".mnc");
526
if (fsl_fileexists(tmpname)) { singlecount++; }
527
strcpy(tmpname,basename);
528
strcat(tmpname,".mnc.gz");
529
if (fsl_fileexists(tmpname)) { singlecount++; }
531
strcpy(tmpname,basename);
532
strcat(tmpname,".img");
533
if (fsl_fileexists(tmpname)) { imgcount++; }
534
strcpy(tmpname,basename);
535
strcat(tmpname,".img.gz");
536
if (fsl_fileexists(tmpname)) { imgcount++; }
538
strcpy(tmpname,basename);
539
strcat(tmpname,".hdr");
540
if (fsl_fileexists(tmpname)) { hdrcount++; }
541
strcpy(tmpname,basename);
542
strcat(tmpname,".hdr.gz");
543
if (fsl_fileexists(tmpname)) { hdrcount++; }
546
if ( (hdrcount==1) && (imgcount==1) && (singlecount==0) ) { ambiguous=0; }
547
if ( (hdrcount==0) && (imgcount==0) && (singlecount==1) ) { ambiguous=0; }
549
/* treat no image found as not ambiguous - want opening errors instead */
550
if ( (hdrcount==0) && (imgcount==0) && (singlecount==0) ) { ambiguous=0; }
559
int check_for_multiple_filenames(const char* filename)
561
char *basename, *tmpname;
563
if (FslCheckForMultipleFileNames(filename))
565
basename = nifti_makebasename(filename);
566
tmpname = (char *)calloc(strlen(basename) + 10,sizeof(char));
567
fprintf(stderr,"\n\n\nWARNING!!!! Multiple image files detected:\n");
568
/* list the offending files */
569
strcpy(tmpname,basename);
570
strcat(tmpname,".nii");
571
if (fsl_fileexists(tmpname)) { fprintf(stderr,"%s ",tmpname); }
572
strcpy(tmpname,basename);
573
strcat(tmpname,".nii.gz");
574
if (fsl_fileexists(tmpname)) { fprintf(stderr,"%s ",tmpname); }
575
strcpy(tmpname,basename);
576
strcat(tmpname,".mnc");
577
if (fsl_fileexists(tmpname)) { fprintf(stderr,"%s ",tmpname); }
578
strcpy(tmpname,basename);
579
strcat(tmpname,".mnc.gz");
580
if (fsl_fileexists(tmpname)) { fprintf(stderr,"%s ",tmpname); }
581
strcpy(tmpname,basename);
582
strcat(tmpname,".img");
583
if (fsl_fileexists(tmpname)) { fprintf(stderr,"%s ",tmpname); }
584
strcpy(tmpname,basename);
585
strcat(tmpname,".img.gz");
586
if (fsl_fileexists(tmpname)) { fprintf(stderr,"%s ",tmpname); }
587
strcpy(tmpname,basename);
588
strcat(tmpname,".hdr");
589
if (fsl_fileexists(tmpname)) { fprintf(stderr,"%s ",tmpname); }
590
strcpy(tmpname,basename);
591
strcat(tmpname,".hdr.gz");
592
if (fsl_fileexists(tmpname)) { fprintf(stderr,"%s ",tmpname); }
593
fprintf(stderr,"\n\n");
596
otype = getenv("FSLMULTIFILEQUIT");
598
fprintf(stderr,"STOPPING PROGRAM\n");
608
/***************************************************************
610
***************************************************************/
611
/*! \fn FSLIO *FslOpen(const char *filename, const char *opts)
612
\brief Opens a file for either reading or writing.
614
The format of the output dataset is determined automatically by
615
passing filetype -1 to FslXOpen.
618
FSLIO *FslOpen(const char *filename, const char *opts)
620
/* Note: -1 for filetype indicates that FslXOpen should determine filetype for itself */
621
return FslXOpen(filename,opts,-1);
625
/***************************************************************
627
***************************************************************/
628
/*! \fn FSLIO *FslXOpen(const char *filename, const char *opts, int filetype)
629
\brief Opens a file for either reading or writing
631
Files to be read are automatically read whether
632
compressed or not. Also, reading uses the file extension
633
and will fail if that file does not exist.
634
For a more robust read, pass the basename in as then all types
636
\param filename Name (or basename) of the file to open
637
\param opts Flags for fopen() of dataset, eg "r", "wb", etc.
638
\param filetype specifies the type of file to be written. Legal
639
values are as defined by FSL_TYPE. If filetype is less than
640
zero, then it is ignored and the type is determined by the
641
filename extension or, failing that, the environment default.
642
\return pointer to FSLIO dataset datastructure
646
FSLIO *FslXOpen(const char *filename, const char *opts, int filetype)
657
for(i=0;i<strlen(opts);i++) {
658
if (opts[i]=='w') { FslSetWriteMode(fslio,1); }
659
if (opts[i]!='b' && opts[i]!='t') { bopts[bi++]=opts[i]; }
661
/* add in 'b' (at the end) for windows compatibility */
666
if (FslGetWriteMode(fslio)==1) {
668
/** ====================== Open file for writing ====================== **/
670
FslInit4Write(fslio,filename,filetype);
671
imgtype = FslGetFileType(fslio);
672
fslio->written_hdr = 0;
674
/* open the image file - not the header */
675
fslio->fileptr = znzopen(fslio->niftiptr->iname,bopts,FslIsCompressedFileType(imgtype));
676
if (znz_isnull(fslio->fileptr)) {
677
fprintf(stderr,"Error: failed to open file %s\n",fslio->niftiptr->iname);
681
if (!FslIsSingleFileType(imgtype)) {
682
/* set up pointer at end of iname_offset for dual file formats (not singles) */
683
FslSeekVolume(fslio,0);
691
/** ======================== Open file for reading ====================== **/
693
check_for_multiple_filenames(filename);
695
/* see if the extension indicates a minc file */
696
imgtype = FslFileType(filename);
697
if ((imgtype>=0) && (FslBaseFileType(imgtype)==FSL_TYPE_MINC)) {
698
fprintf(stderr,"Warning:: Minc is not yet supported\n");
702
/* otherwise open nifti file: read header and open img file (may be same file) */
703
fslio->fileptr = nifti_image_open(filename,bopts,&(fslio->niftiptr));
704
if (znz_isnull(fslio->fileptr)) {
705
fprintf(stderr,"Error: failed to open file %s\n",filename);
709
/* set the file type given what has been read - it uses nifti_type and filenames */
710
imgtype = FslGetReadFileType(fslio);
711
FslSetFileType(fslio,imgtype);
712
FslSetWriteMode(fslio,0);
714
/* if it is a nifti file but has inconsistent left-right ordering in the sform and qform then complain/crash */
715
if (FslBaseFileType(FslGetFileType(fslio))==FSL_TYPE_NIFTI) {
716
if (FslGetLeftRightOrder(fslio) == FSL_INCONSISTENT)
718
fprintf(stderr,"ERROR: inconsistent left-right order stored in sform and qform in file %s\n",filename);
719
fprintf(stderr," Using sform instead of qform values\n\n");
725
if (FslBaseFileType(FslGetFileType(fslio))==FSL_TYPE_ANALYZE) {
726
/* For the ANALYZE case in FSL, must cheat and grab the originator field! */
727
/* Note that the header file is always separate here and closed by now */
730
FslReadRawHeader(&ahdr,fslio->niftiptr->fname);
731
if (fslio->niftiptr->byteorder != nifti_short_order()) {
732
AvwSwapHeader(&ahdr);
734
/* Read the origin and set the sform up (if origin is non-zero) */
735
/* Note that signed pixdims are passed in to set the LR orientation */
736
memcpy(orig,&(ahdr.hist.originator),10);
737
FslSetAnalyzeSform(fslio, orig, fslio->niftiptr->pixdim[1],
738
fslio->niftiptr->pixdim[2], fslio->niftiptr->pixdim[3]);
741
/* from now on force all vox dims to be positive - LR info is in sform */
742
if (fslio->niftiptr!=NULL) {
743
fslio->niftiptr->dx = fabs(fslio->niftiptr->dx);
744
fslio->niftiptr->dy = fabs(fslio->niftiptr->dy);
745
fslio->niftiptr->dz = fabs(fslio->niftiptr->dz);
746
fslio->niftiptr->pixdim[1] = fabs(fslio->niftiptr->pixdim[1]);
747
fslio->niftiptr->pixdim[2] = fabs(fslio->niftiptr->pixdim[2]);
748
fslio->niftiptr->pixdim[3] = fabs(fslio->niftiptr->pixdim[3]);
750
/* set up pointer at end of iname_offset , ready for reading */
751
FslSeekVolume(fslio,0);
759
/***************************************************************
761
***************************************************************/
762
/*! \fn void* FslReadAllVolumes(FSLIO* fslio, char* filename)
763
\brief Read the header and all data into the FSLIO structure
765
There is no need for FslOpen or FslClose calls when FslReadAllVolumes()
767
<br>This routine allocates the buffer to hold the entire dataset.
768
<br>The data block returned will contain the data in whatever
769
datatype it is stored as on disk (therefore it is a void *).
770
<br>The data buffer will be byteswapped to native-endian.
771
<br>The data buffer will not be scaled.
772
<br>The best call to make before this is FslInit() or a calloc() for
773
fslio. (??? why calloc if this allocates the buffer ???)
775
\param fslio pointer to an open dataset
776
\param filename Name of the dataset to read.
777
\return A pointer to the data block buffer (allocated by this function).
778
<br> Return Null on error ??? is this true ???
780
<li>Note this pointer is also in the FSLIO structure as
781
fslio->niftiptr->data.</li>
782
<li>Note a void pointer is returned, as the datablock is of
783
variable datatype.</li>
787
void* FslReadAllVolumes(FSLIO* fslio, char* filename)
791
if (fslio==NULL) FSLIOERR("FslReadAllVolumes: Null pointer passed for FSLIO");
793
/* see if the extension indicates a minc file */
794
imgtype = FslFileType(filename);
795
if ((imgtype>=0) && (FslBaseFileType(imgtype)==FSL_TYPE_MINC)) {
796
fprintf(stderr,"Warning:: Minc is not yet supported\n");
800
/** otherwise it is a nifti file - so read it! **/
801
fslio->mincptr = NULL;
802
/* make sure an FslOpen hasn't locked the file */
803
if (!znz_isnull(fslio->fileptr)) FslClose(fslio);
805
fslio->niftiptr = nifti_image_read(filename,1);
807
/* check for failure, from David Akers */
808
if (fslio->niftiptr == NULL) {
809
FSLIOERR("FslReadAllVolumes: error reading NIfTI image");
813
FslSetFileType(fslio,fslio->niftiptr->nifti_type);
814
FslSetWriteMode(fslio,0);
815
return fslio->niftiptr->data;
820
/***************************************************************
822
***************************************************************/
823
/*! \fn size_t FslReadVolumes(FSLIO *fslio, void *buffer, size_t nvols)
824
\brief Read the first nvols Volumes from a 4D dataset
826
\param fslio pointer to open dataset
827
\param buffer buffer to read data into, allocated by ???
828
\param nvols number of volumes to read
829
\return Number of volumes read.
831
size_t FslReadVolumes(FSLIO *fslio, void *buffer, size_t nvols)
835
if (fslio==NULL) FSLIOERR("FslReadVolumes: Null pointer passed for FSLIO");
836
if (znz_isnull(fslio->fileptr)) FSLIOERR("FslReadVolumes: Null file pointer");
837
if (fslio->niftiptr!=NULL) {
838
fslio->niftiptr->data = buffer;
839
volbytes = FslGetVolSize(fslio) * fslio->niftiptr->nbyper;
840
retval = nifti_read_buffer(fslio->fileptr,fslio->niftiptr->data,nvols*volbytes,fslio->niftiptr);
844
if (fslio->mincptr!=NULL) {
845
fprintf(stderr,"Warning:: Minc is not yet supported\n");
852
/***************************************************************
854
***************************************************************/
855
/*! \fn void FslWriteAllVolumes(FSLIO *fslio, const void *buffer)
856
\brief Writes all data from buffer (using size info from fslio) to file.
858
Dimension and datatype of buffer are as is specified in nifti_image structure
860
Note: If file format is Analyze (not nifti) and in Neurological order then
861
SWAP DATA into Radiological order.
863
\param fslio pointer to open dataset
864
\param buffer pointer to data array. Size and datatype of this buffer
866
void FslWriteAllVolumes(FSLIO *fslio, const void *buffer)
870
if (fslio==NULL) FSLIOERR("FslWriteAllVolumes: Null pointer passed for FSLIO");
872
FslGetDim(fslio,&x,&y,&z,&t);
873
FslWriteHeader(fslio);
874
FslWriteVolumes(fslio,buffer,t);
880
/***************************************************************
882
***************************************************************/
883
/*! \fn size_t FslWriteVolumes(FSLIO *fslio, const void *buffer, size_t nvols)
884
\brief Write the first nvols volumes in buffer to disk.
886
Dimension and datatype of buffer are as is specified in nifti_image structure
888
Note: If file format is Analyze (not nifti) and in Neurological order then
889
SWAP DATA into Radiological order.
892
\param fslio pointer to open dataset
893
\param buffer pointer to data array. Size and datatype of this buffer
894
\param nvols number of volumes to write
895
\return ??? looks like return of retval is missing ??? 0 on error.
897
size_t FslWriteVolumes(FSLIO *fslio, const void *buffer, size_t nvols)
899
/* The dimensions and datatype must be set before calling this function */
901
if (fslio==NULL) FSLIOERR("FslWriteVolumes: Null pointer passed for FSLIO");
902
if ( (!fslio->written_hdr) && (FslIsSingleFileType(FslGetFileType(fslio))) &&
903
(FslIsCompressedFileType(FslGetFileType(fslio))) )
904
{ FSLIOERR("FslWriteVolumes: header must be written before data for single compressed file types"); }
906
if (fslio->niftiptr!=NULL) {
907
long int nbytes, bpv;
908
bpv = fslio->niftiptr->nbyper; /* bytes per voxel */
909
nbytes = nvols * FslGetVolSize(fslio) * bpv;
911
if ( (FslBaseFileType(FslGetFileType(fslio))==FSL_TYPE_ANALYZE)
912
&& (FslGetLeftRightOrder(fslio)==FSL_NEUROLOGICAL) ) {
913
/* If it is Analyze and Neurological order then SWAP DATA into Radiological order */
914
/* This is nasty - but what else can be done?!? */
915
char *tmpbuf, *inbuf;
916
long int x, b, n, nrows;
917
short nx=1, ny, nz, nv;
918
inbuf = (char *) buffer;
919
tmpbuf = (char *)calloc(nbytes,1);
920
FslGetDim(fslio,&nx,&ny,&nz,&nv);
921
nrows = nbytes / (nx * bpv);
922
for (n=0; n<nrows; n++) {
923
for (x=0; x<nx; x++) {
924
for (b=0; b<bpv; b++) {
925
tmpbuf[b + bpv * (n*nx + nx - 1 - x)] = inbuf[b + bpv * (n*nx + x)];
929
retval = nifti_write_buffer(fslio->fileptr, tmpbuf, nbytes);
932
retval = nifti_write_buffer(fslio->fileptr, buffer, nbytes);
935
if (fslio->mincptr!=NULL) {
936
fprintf(stderr,"Warning:: Minc is not yet supported\n");
938
return retval; /* failure */
942
/***************************************************************
944
***************************************************************/
945
/*! \fn void FslWriteHeader(FSLIO *fslio)
946
\brief Writes nifti/anz header and opens img file ready for writing
948
\param fslio pointer to open dataset
950
void FslWriteHeader(FSLIO *fslio)
952
short sform_code, qform_code;
954
/* writes header and opens img file ready for writing */
955
if (fslio==NULL) FSLIOERR("FslWriteHeader: Null pointer passed for FSLIO");
957
if (fslio->niftiptr!=NULL) {
958
fslio->written_hdr = 1;
959
if (znz_isnull(fslio->fileptr)) FSLIOERR("FslWriteHeader: no file opened!");
960
/* modify niftiptr for FSL-specific purposes */
961
strcpy(fslio->niftiptr->descrip,"FSL4.0");
962
/* set qform to equal sform if currently unset (or vice versa) */
963
qform_code = FslGetRigidXform(fslio,&qmat);
964
sform_code = FslGetStdXform(fslio,&smat);
965
if ( (sform_code != NIFTI_XFORM_UNKNOWN) &&
966
(qform_code == NIFTI_XFORM_UNKNOWN) ) {
967
FslSetRigidXform(fslio,sform_code,smat);
969
if ( (qform_code != NIFTI_XFORM_UNKNOWN) &&
970
(sform_code == NIFTI_XFORM_UNKNOWN) ) {
971
FslSetStdXform(fslio,qform_code,qmat);
973
if (FslIsSingleFileType(FslGetFileType(fslio))) {
974
/* write header info but don't close the file */
975
nifti_image_write_hdr_img2(fslio->niftiptr,2,"wb",fslio->fileptr,NULL);
976
/* set up pointer at end of iname_offset for single files only */
977
FslSeekVolume(fslio,0);
979
/* open a new hdr file, write it and close it */
980
nifti_image_write_hdr_img(fslio->niftiptr,0,"wb");
984
if (fslio->mincptr!=NULL) {
985
fprintf(stderr,"Warning:: Minc is not yet supported\n");
991
/***************************************************************
993
***************************************************************/
994
/*! \fn size_t FslReadSliceSeries(FSLIO *fslio, void *buffer, short slice, size_t nvols)
995
\brief Read one slice from each of the first nvols volumes in the dataset, ie get an xyt buffer.
997
Dimension and datatype of buffer are as is specified in nifti_image structure
999
Note: filepointer in file data array is restored to its initial position.
1001
\param fslio pointer to open dataset
1002
\param buffer buffer large enough to hold 1 slice from each volume
1003
\param slice slice number (0 based) to read [0 z-1]
1004
\param nvols number of volumes to read a slice from
1005
\return Number of volumes from which a slice was successfully read. 0 on error.
1007
size_t FslReadSliceSeries(FSLIO *fslio, void *buffer, short slice, size_t nvols)
1009
size_t slbytes,volbytes;
1010
size_t n, orig_offset;
1013
if (fslio==NULL) FSLIOERR("FslReadSliceSeries: Null pointer passed for FSLIO");
1014
if (fslio->niftiptr!=NULL) {
1016
FslGetDim(fslio,&x,&y,&z,&v);
1018
if ((slice<0) || (slice>=z)) FSLIOERR("FslReadSliceSeries: slice outside valid range");
1020
slbytes = x * y * (FslGetDataType(fslio, &type) / 8);
1021
volbytes = slbytes * z;
1023
orig_offset = znztell(fslio->fileptr);
1024
znzseek(fslio->fileptr, slbytes*slice, SEEK_CUR);
1026
for (n=0; n<nvols; n++) {
1027
if (n>0) znzseek(fslio->fileptr, volbytes - slbytes, SEEK_CUR);
1028
if (znzread((char *)buffer+n*slbytes, 1, slbytes, fslio->fileptr) != slbytes)
1029
FSLIOERR("FslReadSliceSeries: failed to read values");
1030
if (fslio->niftiptr->byteorder != nifti_short_order())
1031
nifti_swap_Nbytes(slbytes / fslio->niftiptr->swapsize,
1032
fslio->niftiptr->swapsize, (char *)buffer+n*slbytes);
1036
/* restore file pointer to original position */
1037
znzseek(fslio->fileptr,orig_offset,SEEK_SET);
1040
if (fslio->mincptr!=NULL) {
1041
fprintf(stderr,"Warning:: Minc is not yet supported\n");
1047
/***************************************************************
1049
***************************************************************/
1050
/*! \fn size_t FslReadRowSeries(FSLIO *fslio, void *buffer, short row, short slice, size_t nvols)
1051
\brief Read one row from one slice for first nvols volumes in dataset; ie get an xt buffer.
1053
Dimension and datatype of buffer are as is specified in nifti_image structure
1055
Note: filepointer in file data array is restored to its initial position.
1057
\param fslio pointer to open dataset
1058
\param buffer buffer to hold one row from each volume.
1059
\param row row number (0 based) to read [0 y-1]
1060
\param slice slice number (0 based) to read
1061
\param nvols number of volumes to read a row from
1062
\return Number of volumes from which a row was successfully read. 0 on error.
1064
size_t FslReadRowSeries(FSLIO *fslio, void *buffer, short row, short slice, size_t nvols)
1066
size_t rowbytes,slbytes,volbytes;
1067
size_t n, orig_offset;
1070
if (fslio==NULL) FSLIOERR("FslReadRowSeries: Null pointer passed for FSLIO");
1071
if (fslio->niftiptr!=NULL) {
1073
FslGetDim(fslio,&x,&y,&z,&v);
1075
if ((slice<0) || (slice>=z)) FSLIOERR("FslReadRowSeries: slice outside valid range");
1076
if ((row<0) || (row>=y)) FSLIOERR("FslReadRowSeries: row outside valid range");
1078
rowbytes = x * (FslGetDataType(fslio, &type)) / 8;
1079
slbytes = rowbytes * y;
1080
volbytes = slbytes * z;
1082
orig_offset = znztell(fslio->fileptr);
1083
znzseek(fslio->fileptr, rowbytes*row + slbytes*slice, SEEK_CUR);
1085
for (n=0; n<nvols; n++){
1086
if (n>0) znzseek(fslio->fileptr, volbytes - rowbytes, SEEK_CUR);
1087
if (znzread((char *)buffer+n*rowbytes, 1, rowbytes, fslio->fileptr) != rowbytes)
1088
FSLIOERR("FslReadRowSeries: failed to read values");
1089
if (fslio->niftiptr->byteorder != nifti_short_order())
1090
nifti_swap_Nbytes(rowbytes / fslio->niftiptr->swapsize,
1091
fslio->niftiptr->swapsize, (char *)buffer+n*rowbytes);
1094
/* restore file pointer to original position */
1095
znzseek(fslio->fileptr,orig_offset,SEEK_SET);
1098
if (fslio->mincptr!=NULL) {
1099
fprintf(stderr,"Warning:: Minc is not yet supported\n");
1105
/***************************************************************
1107
***************************************************************/
1108
/*! \fn size_t FslReadTimeSeries(FSLIO *fslio, void *buffer, short xVox, short yVox, short zVox, size_t nvols)
1109
\brief Read one voxel (xyz location) from first nvols volumes in dataset; ie get a t dim buffer.
1111
Dimension and datatype of buffer are as is specified in nifti_image structure
1113
Note: filepointer in file data array is restored to its initial position.
1115
\param fslio pointer to open dataset
1116
\param buffer buffer to hold one timeseries vector
1117
\param xVox x voxel [0 x-1]
1118
\param yVox y voxel [0 y-1]
1119
\param zVox z voxel [0 z-1]
1120
\param nvols number of volumes to read a voxel from
1121
\return Number of volumes from which a voxel was successfully read. 0 on error.
1123
size_t FslReadTimeSeries(FSLIO *fslio, void *buffer, short xVox, short yVox, short zVox,
1126
size_t volbytes, offset, orig_offset;
1128
short xdim,ydim,zdim,v,wordsize;
1130
if (fslio==NULL) FSLIOERR("FslReadTimeSeries: Null pointer passed for FSLIO");
1131
if (fslio->niftiptr!=NULL) {
1133
FslGetDim(fslio,&xdim,&ydim,&zdim,&v);
1135
if ((xVox<0) || (xVox >=xdim)) FSLIOERR("FslReadTimeSeries: voxel outside valid range");
1136
if ((yVox<0) || (yVox >=ydim)) FSLIOERR("FslReadTimeSeries: voxel outside valid range");
1137
if ((zVox<0) || (zVox >=zdim)) FSLIOERR("FslReadTimeSeries: voxel outside valid range");
1139
wordsize = fslio->niftiptr->nbyper;
1140
volbytes = xdim * ydim * zdim * wordsize;
1142
orig_offset = znztell(fslio->fileptr);
1143
offset = ((ydim * zVox + yVox) * xdim + xVox) * wordsize;
1144
znzseek(fslio->fileptr,offset,SEEK_CUR);
1146
for (n=0; n<nvols; n++) {
1147
if (n>0) znzseek(fslio->fileptr, volbytes - wordsize, SEEK_CUR);
1148
if (znzread((char *)buffer+(n*wordsize), 1, wordsize,fslio->fileptr) != wordsize)
1149
FSLIOERR("FslReadTimeSeries: failed to read values");
1150
if (fslio->niftiptr->byteorder != nifti_short_order())
1151
nifti_swap_Nbytes(1,fslio->niftiptr->swapsize,
1152
(char *)buffer+(n*wordsize));
1155
/* restore file pointer to original position */
1156
znzseek(fslio->fileptr,orig_offset,SEEK_SET);
1160
if (fslio->mincptr!=NULL) {
1161
fprintf(stderr,"Warning:: Minc is not yet supported\n");
1167
size_t FslReadCplxVolumes(FSLIO *fslio, void *buffer, size_t nvols, char mode)
1169
if (fslio==NULL) FSLIOERR("FslReadCplxVolumes: Null pointer passed for FSLIO");
1170
fprintf(stderr,"Warning:: FslReadCplxVolumes is not yet supported\n");
1174
size_t FslWriteCplxVolumes(FSLIO *fslio, void *buffer, size_t nvols, char mode)
1176
if (fslio==NULL) FSLIOERR("FslWriteCplxVolumes: Null pointer passed for FSLIO");
1177
fprintf(stderr,"Warning:: FslWriteCplxVolumes is not yet supported\n");
1181
long FslSeekVolume(FSLIO *fslio, size_t vols)
1184
if (fslio==NULL) FSLIOERR("FslSeekVolume: Null pointer passed for FSLIO");
1185
if (fslio->niftiptr!=NULL) {
1186
offset = fslio->niftiptr->iname_offset +
1187
vols * FslGetVolSize(fslio) * fslio->niftiptr->nbyper;
1188
if (znz_isnull(fslio->fileptr)) FSLIOERR("FslSeekVolume: Null file pointer");
1189
return znzseek(fslio->fileptr,offset,SEEK_SET);
1191
if (fslio->mincptr!=NULL) {
1192
fprintf(stderr,"Warning:: Minc is not yet supported\n");
1197
size_t FslGetVolSize(FSLIO *fslio)
1199
/* returns number of voxels per 3D volume */
1200
if (fslio==NULL) FSLIOERR("FslGetVolSize: Null pointer passed for FSLIO");
1201
if (fslio->niftiptr!=NULL) {
1202
return (fslio->niftiptr->nx * fslio->niftiptr->ny * fslio->niftiptr->nz);
1204
if (fslio->mincptr!=NULL) {
1205
fprintf(stderr,"Warning:: Minc is not yet supported\n");
1211
void FslSetDim(FSLIO *fslio, short x, short y, short z, short v)
1214
if (fslio==NULL) FSLIOERR("FslSetDim: Null pointer passed for FSLIO");
1215
if (fslio->niftiptr!=NULL) {
1218
if (v<=1) {ndim--; if (z<=1) {ndim--; if (y<=1) {ndim--; if (x<=1) {ndim--;}}}}
1220
fslio->niftiptr->ndim = ndim;
1222
if (x>=1) fslio->niftiptr->nx = x; else fslio->niftiptr->nx=1;
1223
if (y>=1) fslio->niftiptr->ny = y; else fslio->niftiptr->ny=1;
1224
if (z>=1) fslio->niftiptr->nz = z; else fslio->niftiptr->nz=1;
1225
if (v>=1) fslio->niftiptr->nt = v; else fslio->niftiptr->nt=1;
1226
fslio->niftiptr->nu = 1;
1227
fslio->niftiptr->nv = 1;
1228
fslio->niftiptr->nw = 1;
1230
/* deal with stupid redundancies */
1231
fslio->niftiptr->dim[0] = fslio->niftiptr->ndim ;
1232
fslio->niftiptr->dim[1] = fslio->niftiptr->nx;
1233
fslio->niftiptr->dim[2] = fslio->niftiptr->ny;
1234
fslio->niftiptr->dim[3] = fslio->niftiptr->nz;
1235
fslio->niftiptr->dim[4] = fslio->niftiptr->nt;
1236
fslio->niftiptr->dim[5] = fslio->niftiptr->nu;
1237
fslio->niftiptr->dim[6] = fslio->niftiptr->nv;
1238
fslio->niftiptr->dim[7] = fslio->niftiptr->nw;
1240
fslio->niftiptr->nvox = fslio->niftiptr->nx * fslio->niftiptr->ny * fslio->niftiptr->nz
1241
* fslio->niftiptr->nt * fslio->niftiptr->nu * fslio->niftiptr->nv * fslio->niftiptr->nw ;
1244
if (fslio->mincptr!=NULL) {
1245
fprintf(stderr,"Warning:: Minc is not yet supported\n");
1250
void FslGetDim(FSLIO *fslio, short *x, short *y, short *z, short *v)
1252
if (fslio==NULL) FSLIOERR("FslGetDim: Null pointer passed for FSLIO");
1253
if (fslio->niftiptr!=NULL) {
1254
*x = fslio->niftiptr->nx;
1255
*y = fslio->niftiptr->ny;
1256
*z = fslio->niftiptr->nz;
1257
*v = fslio->niftiptr->nt;
1259
if (fslio->mincptr!=NULL) {
1260
fprintf(stderr,"Warning:: Minc is not yet supported\n");
1265
void FslSetDimensionality(FSLIO *fslio, size_t dim)
1267
if (fslio==NULL) FSLIOERR("FslSetDimensionality: Null pointer passed for FSLIO");
1268
if (fslio->niftiptr!=NULL) {
1269
fslio->niftiptr->ndim = dim;
1270
fslio->niftiptr->dim[0] = dim;
1272
if (fslio->mincptr!=NULL) {
1273
fprintf(stderr,"Warning:: Minc is not yet supported\n");
1278
void FslGetDimensionality(FSLIO *fslio, size_t *dim)
1280
if (fslio==NULL) FSLIOERR("FslGetDimensionality: Null pointer passed for FSLIO");
1281
if (fslio->niftiptr!=NULL) {
1282
*dim = fslio->niftiptr->ndim;
1284
if (fslio->mincptr!=NULL) {
1285
fprintf(stderr,"Warning:: Minc is not yet supported\n");
1290
void FslSetVoxDim(FSLIO *fslio, float x, float y, float z, float tr)
1292
if (fslio==NULL) FSLIOERR("FslSetVoxDim: Null pointer passed for FSLIO");
1293
if (fslio->niftiptr!=NULL) {
1294
fslio->niftiptr->dx = fabs(x);
1295
fslio->niftiptr->dy = fabs(y);
1296
fslio->niftiptr->dz = fabs(z);
1297
fslio->niftiptr->dt = fabs(tr);
1298
fslio->niftiptr->pixdim[1] = fabs(x);
1299
fslio->niftiptr->pixdim[2] = fabs(y);
1300
fslio->niftiptr->pixdim[3] = fabs(z);
1301
fslio->niftiptr->pixdim[4] = fabs(tr);
1302
/* set the units to mm and seconds */
1303
fslio->niftiptr->xyz_units = NIFTI_UNITS_MM;
1304
fslio->niftiptr->time_units = NIFTI_UNITS_SEC;
1306
if (fslio->mincptr!=NULL) {
1307
fprintf(stderr,"Warning:: Minc is not yet supported\n");
1312
void FslGetVoxDim(FSLIO *fslio, float *x, float *y, float *z, float *tr)
1314
if (fslio==NULL) FSLIOERR("FslGetVoxDim: Null pointer passed for FSLIO");
1315
if (fslio->niftiptr!=NULL) {
1316
*x = fabs(fslio->niftiptr->dx);
1317
*y = fabs(fslio->niftiptr->dy);
1318
*z = fabs(fslio->niftiptr->dz);
1319
*tr = fabs(fslio->niftiptr->dt);
1320
/* now check the units and convert to mm and sec */
1321
if (fslio->niftiptr->xyz_units == NIFTI_UNITS_METER)
1322
{ *x *= 1000.0; *y *= 1000.0; *z *= 1000.0; }
1323
if (fslio->niftiptr->xyz_units == NIFTI_UNITS_MICRON)
1324
{ *x /= 1000.0; *y /= 1000.0; *z /= 1000.0; }
1325
if (fslio->niftiptr->xyz_units == NIFTI_UNITS_MSEC)
1327
if (fslio->niftiptr->xyz_units == NIFTI_UNITS_USEC)
1328
{ *tr /= 1000000.0; }
1329
/* if it is Hz or other frequency then leave it */
1331
if (fslio->mincptr!=NULL) {
1332
fprintf(stderr,"Warning:: Minc is not yet supported\n");
1337
void FslGetCalMinMax(FSLIO *fslio, float *min, float *max)
1339
if (fslio==NULL) FSLIOERR("FslGetCalMinMax: Null pointer passed for FSLIO");
1340
if (fslio->niftiptr!=NULL) {
1341
*min = fslio->niftiptr->cal_min;
1342
*max = fslio->niftiptr->cal_max;
1344
if (fslio->mincptr!=NULL) {
1345
fprintf(stderr,"Warning:: Minc is not yet supported\n");
1350
void FslSetCalMinMax(FSLIO *fslio, float min, float max)
1352
if (fslio==NULL) FSLIOERR("FslSetCalMinMax: Null pointer passed for FSLIO");
1353
if (fslio->niftiptr!=NULL) {
1354
fslio->niftiptr->cal_min = min;
1355
fslio->niftiptr->cal_max = max;
1357
if (fslio->mincptr!=NULL) {
1358
fprintf(stderr,"Warning:: Minc is not yet supported\n");
1363
void FslGetAuxFile(FSLIO *fslio,char *aux_file)
1365
if (fslio==NULL) FSLIOERR("FslGetAuxFile: Null pointer passed for FSLIO");
1366
if (fslio->niftiptr!=NULL) {
1367
strncpy(aux_file,fslio->niftiptr->aux_file, 24);
1368
aux_file[23] = '\0';
1370
if (fslio->mincptr!=NULL) {
1371
fprintf(stderr,"Warning:: Minc is not yet supported\n");
1376
void FslSetAuxFile(FSLIO *fslio,const char *aux_file)
1378
if (fslio==NULL) FSLIOERR("FslSetAuxFile: Null pointer passed for FSLIO");
1379
if (fslio->niftiptr!=NULL) {
1380
strncpy(fslio->niftiptr->aux_file, aux_file, 24);
1382
if (fslio->mincptr!=NULL) {
1383
fprintf(stderr,"Warning:: Minc is not yet supported\n");
1388
void FslSetVoxUnits(FSLIO *fslio, const char *units)
1391
if (fslio==NULL) FSLIOERR("FslSetVoxUnits: Null pointer passed for FSLIO");
1392
if (fslio->niftiptr!=NULL) {
1393
if (strcmp(units,nifti_units_string(NIFTI_UNITS_METER))==0) {
1394
unitcode = NIFTI_UNITS_METER;
1395
} else if (strcmp(units,nifti_units_string(NIFTI_UNITS_MM))==0) {
1396
unitcode = NIFTI_UNITS_MM;
1397
} else if (strcmp(units,nifti_units_string(NIFTI_UNITS_MICRON))==0) {
1398
unitcode = NIFTI_UNITS_MICRON;
1400
fslio->niftiptr->xyz_units = unitcode;
1402
if (fslio->mincptr!=NULL) {
1403
fprintf(stderr,"Warning:: Minc is not yet supported\n");
1408
void FslGetVoxUnits(FSLIO *fslio, char *units)
1410
if (fslio==NULL) FSLIOERR("FslGetVoxUnits: Null pointer passed for FSLIO");
1411
if (fslio->niftiptr!=NULL) {
1412
strcpy(units,nifti_units_string(fslio->niftiptr->xyz_units));
1414
if (fslio->mincptr!=NULL) {
1415
fprintf(stderr,"Warning:: Minc is not yet supported\n");
1419
void FslSetTimeUnits(FSLIO *fslio, const char *units)
1422
if (fslio==NULL) FSLIOERR("FslSetTimeUnits: Null pointer passed for FSLIO");
1423
if (fslio->niftiptr!=NULL) {
1424
if (strcmp(units,nifti_units_string(NIFTI_UNITS_HZ))==0) {
1425
unitcode = NIFTI_UNITS_HZ;
1426
} else if (strcmp(units,nifti_units_string(NIFTI_UNITS_PPM))==0) {
1427
unitcode = NIFTI_UNITS_PPM;
1428
} else if (strcmp(units,nifti_units_string(NIFTI_UNITS_RADS))==0) {
1429
unitcode = NIFTI_UNITS_RADS;
1430
} else if (strcmp(units,nifti_units_string(NIFTI_UNITS_SEC))==0) {
1431
unitcode = NIFTI_UNITS_SEC;
1432
} else if (strcmp(units,nifti_units_string(NIFTI_UNITS_MSEC))==0) {
1433
fprintf(stderr,"Warning::Setting time units to msec is not fully recommended in fslio\n");
1434
unitcode = NIFTI_UNITS_MSEC;
1435
} else if (strcmp(units,nifti_units_string(NIFTI_UNITS_USEC))==0) {
1436
fprintf(stderr,"Warning::Setting time units to msec is not fully recommended in fslio\n");
1437
unitcode = NIFTI_UNITS_USEC;
1439
fslio->niftiptr->time_units = unitcode;
1441
if (fslio->mincptr!=NULL) {
1442
fprintf(stderr,"Warning:: Minc is not yet supported\n");
1447
void FslGetTimeUnits(FSLIO *fslio, char *units)
1449
if (fslio==NULL) FSLIOERR("FslGetTimeUnits: Null pointer passed for FSLIO");
1450
if (fslio->niftiptr!=NULL) {
1451
strcpy(units,nifti_units_string(fslio->niftiptr->time_units));
1453
if (fslio->mincptr!=NULL) {
1454
fprintf(stderr,"Warning:: Minc is not yet supported\n");
1459
void FslSetDataType(FSLIO *fslio, short t)
1461
int nbytepix=0, ss=0;
1462
if (fslio==NULL) FSLIOERR("FslSetDataType: Null pointer passed for FSLIO");
1463
if (fslio->niftiptr!=NULL) {
1464
fslio->niftiptr->datatype = t;
1465
nifti_datatype_sizes(t,&nbytepix,&ss);
1466
fslio->niftiptr->nbyper = nbytepix;
1468
if (fslio->mincptr!=NULL) {
1469
fprintf(stderr,"Warning:: Minc is not yet supported\n");
1473
size_t FslGetDataType(FSLIO *fslio, short *t)
1475
/* returns bits per pixel */
1476
int nbytepix=32, ss=0;
1477
if (fslio==NULL) FSLIOERR("FslGetDataType: Null pointer passed for FSLIO");
1478
if (fslio->niftiptr!=NULL) {
1479
*t = fslio->niftiptr->datatype;
1480
nifti_datatype_sizes(*t,&nbytepix,&ss);
1482
if (fslio->mincptr!=NULL) {
1483
fprintf(stderr,"Warning:: Minc is not yet supported\n");
1485
return (size_t) 8 * nbytepix;
1489
void FslGetMMCoord(mat44 stdmat, float voxx, float voxy, float voxz,
1490
float *mmx, float *mmy, float *mmz)
1492
*mmx = stdmat.m[0][0] * voxx + stdmat.m[0][1] * voxy + stdmat.m[0][2] * voxz
1494
*mmy = stdmat.m[1][0] * voxx + stdmat.m[1][1] * voxy + stdmat.m[1][2] * voxz
1496
*mmz = stdmat.m[2][0] * voxx + stdmat.m[2][1] * voxy + stdmat.m[2][2] * voxz
1501
void FslGetVoxCoord(mat44 stdmat, float mmx, float mmy, float mmz,
1502
float *voxx, float *voxy, float *voxz)
1506
mm2vox = nifti_mat44_inverse(stdmat);
1507
*voxx = mm2vox.m[0][0] * mmx + mm2vox.m[0][1] * mmy + mm2vox.m[0][2] * mmz
1509
*voxy = mm2vox.m[1][0] * mmx + mm2vox.m[1][1] * mmy + mm2vox.m[1][2] * mmz
1511
*voxz = mm2vox.m[2][0] * mmx + mm2vox.m[2][1] * mmy + mm2vox.m[2][2] * mmz
1516
void FslSetStdXform(FSLIO *fslio, short sform_code, mat44 stdmat)
1518
/* NB: stdmat must point to a 4x4 array */
1519
if (fslio==NULL) FSLIOERR("FslSetStdXform: Null pointer passed for FSLIO");
1520
if (fslio->niftiptr!=NULL) {
1521
fslio->niftiptr->sform_code = sform_code;
1522
fslio->niftiptr->sto_xyz.m[0][0] = stdmat.m[0][0];
1523
fslio->niftiptr->sto_xyz.m[0][1] = stdmat.m[0][1];
1524
fslio->niftiptr->sto_xyz.m[0][2] = stdmat.m[0][2];
1525
fslio->niftiptr->sto_xyz.m[0][3] = stdmat.m[0][3];
1526
fslio->niftiptr->sto_xyz.m[1][0] = stdmat.m[1][0];
1527
fslio->niftiptr->sto_xyz.m[1][1] = stdmat.m[1][1];
1528
fslio->niftiptr->sto_xyz.m[1][2] = stdmat.m[1][2];
1529
fslio->niftiptr->sto_xyz.m[1][3] = stdmat.m[1][3];
1530
fslio->niftiptr->sto_xyz.m[2][0] = stdmat.m[2][0];
1531
fslio->niftiptr->sto_xyz.m[2][1] = stdmat.m[2][1];
1532
fslio->niftiptr->sto_xyz.m[2][2] = stdmat.m[2][2];
1533
fslio->niftiptr->sto_xyz.m[2][3] = stdmat.m[2][3];
1534
fslio->niftiptr->sto_xyz.m[3][0] = 0;
1535
fslio->niftiptr->sto_xyz.m[3][1] = 0;
1536
fslio->niftiptr->sto_xyz.m[3][2] = 0;
1537
fslio->niftiptr->sto_xyz.m[3][3] = 1;
1538
fslio->niftiptr->sto_ijk = nifti_mat44_inverse(fslio->niftiptr->sto_xyz);
1540
if (fslio->mincptr!=NULL) {
1541
fprintf(stderr,"Warning:: Minc is not yet supported\n");
1546
short FslGetStdXform(FSLIO *fslio, mat44 *stdmat)
1548
/* returns sform code (NB: stdmat must point to a 4x4 array) */
1550
if (fslio==NULL) FSLIOERR("FslGetStdXform: Null pointer passed for FSLIO");
1551
if (fslio->niftiptr!=NULL) {
1552
stdmat->m[0][0] = fslio->niftiptr->sto_xyz.m[0][0];
1553
stdmat->m[0][1] = fslio->niftiptr->sto_xyz.m[0][1];
1554
stdmat->m[0][2] = fslio->niftiptr->sto_xyz.m[0][2];
1555
stdmat->m[0][3] = fslio->niftiptr->sto_xyz.m[0][3];
1556
stdmat->m[1][0] = fslio->niftiptr->sto_xyz.m[1][0];
1557
stdmat->m[1][1] = fslio->niftiptr->sto_xyz.m[1][1];
1558
stdmat->m[1][2] = fslio->niftiptr->sto_xyz.m[1][2];
1559
stdmat->m[1][3] = fslio->niftiptr->sto_xyz.m[1][3];
1560
stdmat->m[2][0] = fslio->niftiptr->sto_xyz.m[2][0];
1561
stdmat->m[2][1] = fslio->niftiptr->sto_xyz.m[2][1];
1562
stdmat->m[2][2] = fslio->niftiptr->sto_xyz.m[2][2];
1563
stdmat->m[2][3] = fslio->niftiptr->sto_xyz.m[2][3];
1564
stdmat->m[3][0] = 0.0;
1565
stdmat->m[3][1] = 0.0;
1566
stdmat->m[3][2] = 0.0;
1567
stdmat->m[3][3] = 1.0;
1569
/* the code below gives a default but it really should never be used */
1570
if (fslio->niftiptr->sform_code == NIFTI_XFORM_UNKNOWN) {
1571
FslGetVoxDim(fslio,&dx,&dy,&dz,&tr);
1572
stdmat->m[0][0] = -dx; /* default Radiological convention */
1573
stdmat->m[0][1] = 0;
1574
stdmat->m[0][2] = 0;
1575
stdmat->m[0][3] = 0;
1576
stdmat->m[1][0] = 0;
1577
stdmat->m[1][1] = dy;
1578
stdmat->m[1][2] = 0;
1579
stdmat->m[1][3] = 0;
1580
stdmat->m[2][0] = 0;
1581
stdmat->m[2][1] = 0;
1582
stdmat->m[2][2] = dz;
1583
stdmat->m[2][3] = 0;
1584
stdmat->m[3][0] = 0.0;
1585
stdmat->m[3][1] = 0.0;
1586
stdmat->m[3][2] = 0.0;
1587
stdmat->m[3][3] = 1.0;
1589
return fslio->niftiptr->sform_code;
1591
if (fslio->mincptr!=NULL) {
1592
fprintf(stderr,"Warning:: Minc is not yet supported\n");
1594
return NIFTI_XFORM_UNKNOWN;
1598
void FslSetRigidXform(FSLIO *fslio, short qform_code, mat44 rigidmat)
1600
/* NB: rigidmat must point to an allocated mat44 */
1602
if (fslio==NULL) FSLIOERR("FslSetRigidXform: Null pointer passed for FSLIO");
1603
if (fslio->niftiptr!=NULL) {
1604
fslio->niftiptr->qform_code = qform_code;
1605
fslio->niftiptr->qto_xyz.m[0][0] = rigidmat.m[0][0];
1606
fslio->niftiptr->qto_xyz.m[0][1] = rigidmat.m[0][1];
1607
fslio->niftiptr->qto_xyz.m[0][2] = rigidmat.m[0][2];
1608
fslio->niftiptr->qto_xyz.m[0][3] = rigidmat.m[0][3];
1609
fslio->niftiptr->qto_xyz.m[1][0] = rigidmat.m[1][0];
1610
fslio->niftiptr->qto_xyz.m[1][1] = rigidmat.m[1][1];
1611
fslio->niftiptr->qto_xyz.m[1][2] = rigidmat.m[1][2];
1612
fslio->niftiptr->qto_xyz.m[1][3] = rigidmat.m[1][3];
1613
fslio->niftiptr->qto_xyz.m[2][0] = rigidmat.m[2][0];
1614
fslio->niftiptr->qto_xyz.m[2][1] = rigidmat.m[2][1];
1615
fslio->niftiptr->qto_xyz.m[2][2] = rigidmat.m[2][2];
1616
fslio->niftiptr->qto_xyz.m[2][3] = rigidmat.m[2][3];
1617
fslio->niftiptr->qto_xyz.m[3][0] = 0;
1618
fslio->niftiptr->qto_xyz.m[3][1] = 0;
1619
fslio->niftiptr->qto_xyz.m[3][2] = 0;
1620
fslio->niftiptr->qto_xyz.m[3][3] = 1;
1621
nifti_mat44_to_quatern(
1622
fslio->niftiptr->qto_xyz,&(fslio->niftiptr->quatern_b),
1623
&(fslio->niftiptr->quatern_c),&(fslio->niftiptr->quatern_d),
1624
&(fslio->niftiptr->qoffset_x),&(fslio->niftiptr->qoffset_y),
1625
&(fslio->niftiptr->qoffset_z),&dx,&dy,&dz,&(fslio->niftiptr->qfac));
1626
fslio->niftiptr->qto_ijk = nifti_mat44_inverse(fslio->niftiptr->qto_xyz);
1629
if (fslio->mincptr!=NULL) {
1630
fprintf(stderr,"Warning:: Minc is not yet supported\n");
1635
short FslGetRigidXform(FSLIO *fslio, mat44 *rigidmat)
1637
/* returns qform code (NB: rigidmat must point to an allocated mat44) */
1639
if (fslio==NULL) FSLIOERR("FslGetRigidXform: Null pointer passed for FSLIO");
1640
if (fslio->niftiptr!=NULL) {
1641
rigidmat->m[0][0] = fslio->niftiptr->qto_xyz.m[0][0];
1642
rigidmat->m[0][1] = fslio->niftiptr->qto_xyz.m[0][1];
1643
rigidmat->m[0][2] = fslio->niftiptr->qto_xyz.m[0][2];
1644
rigidmat->m[0][3] = fslio->niftiptr->qto_xyz.m[0][3];
1645
rigidmat->m[1][0] = fslio->niftiptr->qto_xyz.m[1][0];
1646
rigidmat->m[1][1] = fslio->niftiptr->qto_xyz.m[1][1];
1647
rigidmat->m[1][2] = fslio->niftiptr->qto_xyz.m[1][2];
1648
rigidmat->m[1][3] = fslio->niftiptr->qto_xyz.m[1][3];
1649
rigidmat->m[2][0] = fslio->niftiptr->qto_xyz.m[2][0];
1650
rigidmat->m[2][1] = fslio->niftiptr->qto_xyz.m[2][1];
1651
rigidmat->m[2][2] = fslio->niftiptr->qto_xyz.m[2][2];
1652
rigidmat->m[2][3] = fslio->niftiptr->qto_xyz.m[2][3];
1653
rigidmat->m[3][0] = 0.0;
1654
rigidmat->m[3][1] = 0.0;
1655
rigidmat->m[3][2] = 0.0;
1656
rigidmat->m[3][3] = 1.0;
1658
/* the code gives a default but it should never really be used */
1659
if (fslio->niftiptr->qform_code == NIFTI_XFORM_UNKNOWN) {
1660
FslGetVoxDim(fslio,&dx,&dy,&dz,&tr);
1661
rigidmat->m[0][0] = dx;
1662
rigidmat->m[0][1] = 0;
1663
rigidmat->m[0][2] = 0;
1664
rigidmat->m[0][3] = 0;
1665
rigidmat->m[1][0] = 0;
1666
rigidmat->m[1][1] = dy;
1667
rigidmat->m[1][2] = 0;
1668
rigidmat->m[1][3] = 0;
1669
rigidmat->m[2][0] = 0;
1670
rigidmat->m[2][1] = 0;
1671
rigidmat->m[2][2] = dz;
1672
rigidmat->m[2][3] = 0;
1673
rigidmat->m[3][0] = 0.0;
1674
rigidmat->m[3][1] = 0.0;
1675
rigidmat->m[3][2] = 0.0;
1676
rigidmat->m[3][3] = 1.0;
1678
return fslio->niftiptr->qform_code;
1680
if (fslio->mincptr!=NULL) {
1681
fprintf(stderr,"Warning:: Minc is not yet supported\n");
1683
return NIFTI_XFORM_UNKNOWN;
1687
void FslSetIntent(FSLIO *fslio, short intent_code, float p1, float p2, float p3)
1689
if (fslio==NULL) FSLIOERR("FslSetIntent: Null pointer passed for FSLIO");
1690
if (fslio->niftiptr!=NULL) {
1691
fslio->niftiptr->intent_code = intent_code;
1692
fslio->niftiptr->intent_p1 = p1;
1693
fslio->niftiptr->intent_p2 = p2;
1694
fslio->niftiptr->intent_p3 = p3;
1696
if (fslio->mincptr!=NULL) {
1697
fprintf(stderr,"Warning:: Minc is not yet supported\n");
1702
short FslGetIntent(FSLIO *fslio, short *intent_code, float *p1, float *p2,
1705
/* also returns intent code */
1706
if (fslio==NULL) FSLIOERR("FslGetIntent: Null pointer passed for FSLIO");
1707
if (fslio->niftiptr!=NULL) {
1708
*intent_code = fslio->niftiptr->intent_code;
1709
*p1 = fslio->niftiptr->intent_p1;
1710
*p2 = fslio->niftiptr->intent_p2;
1711
*p3 = fslio->niftiptr->intent_p3;
1712
return fslio->niftiptr->intent_code;
1714
if (fslio->mincptr!=NULL) {
1715
fprintf(stderr,"Warning:: Minc is not yet supported\n");
1717
return NIFTI_INTENT_NONE;
1723
void FslSetIntensityScaling(FSLIO *fslio, float slope, float intercept)
1725
if (fslio==NULL) FSLIOERR("FslSetIntensityScaling: Null pointer passed for FSLIO");
1726
if (fslio->niftiptr!=NULL) {
1727
fslio->niftiptr->scl_slope = slope;
1728
fslio->niftiptr->scl_inter = intercept;
1730
if (fslio->mincptr!=NULL) {
1731
fprintf(stderr,"Warning:: Minc is not yet supported\n");
1736
int FslGetIntensityScaling(FSLIO *fslio, float *slope, float *intercept)
1738
/* returns 1 if scaling required or 0 otherwise */
1739
if (fslio==NULL) FSLIOERR("FslGetIntensityScaling: Null pointer passed for FSLIO");
1740
if (fslio->niftiptr!=NULL) {
1741
*slope = fslio->niftiptr->scl_slope;
1742
*intercept = fslio->niftiptr->scl_inter;
1743
if (fabs(*slope)<1e-30) {
1748
if ( (fabs(*slope - 1.0)>1e-30) || (fabs(*intercept)>1e-30) ) {
1754
if (fslio->mincptr!=NULL) {
1755
fprintf(stderr,"Warning:: Minc is not yet supported\n");
1762
mat33 mat44_to_mat33(mat44 x)
1766
for (i=0; i<3; i++) {
1767
for (j=0; j<3; j++) {
1768
y.m[i][j] = x.m[i][j];
1775
int FslGetLeftRightOrder2(int sform_code, mat44 sform44,
1776
int qform_code, mat44 qform44)
1778
/* Determines if the image is stored in neurological or radiological convention */
1779
int order=FSL_RADIOLOGICAL;
1780
float dets=-1.0, detq=-1.0, det=-1.0;
1781
mat33 sform33, qform33;
1782
if (qform_code!=NIFTI_XFORM_UNKNOWN) {
1783
qform33 = mat44_to_mat33(qform44);
1784
detq = nifti_mat33_determ(qform33);
1787
if (sform_code!=NIFTI_XFORM_UNKNOWN) {
1788
sform33 = mat44_to_mat33(sform44);
1789
dets = nifti_mat33_determ(sform33);
1793
if (det<0.0) order=FSL_RADIOLOGICAL;
1794
else order=FSL_NEUROLOGICAL;
1795
/* check for inconsistency if both are set */
1796
if ( (sform_code!=NIFTI_XFORM_UNKNOWN) &&
1797
(qform_code!=NIFTI_XFORM_UNKNOWN) ) {
1798
if (dets * detq < 0.0) order=FSL_INCONSISTENT;
1804
int FslGetLeftRightOrder(FSLIO *fslio)
1806
int order=FSL_RADIOLOGICAL, sform_code, qform_code;
1807
mat44 sform44, qform44;
1808
if (fslio==NULL) FSLIOERR("FslGetLeftRightOrder: Null pointer passed for FSLIO");
1809
if (fslio->niftiptr!=NULL) {
1810
sform_code = FslGetStdXform(fslio,&sform44);
1811
qform_code = FslGetRigidXform(fslio,&qform44);
1812
return FslGetLeftRightOrder2(sform_code,sform44,qform_code,qform44);
1814
if (fslio->mincptr!=NULL) {
1815
fprintf(stderr,"Warning:: Minc is not yet supported\n");
1821
short FslGetVox2mmMatrix2(mat44 *vox2mm, int sform_code, mat44 sform44,
1822
int qform_code, mat44 qform44,
1823
float dx, float dy, float dz)
1825
short retcode=NIFTI_XFORM_UNKNOWN;
1827
if (sform_code!=NIFTI_XFORM_UNKNOWN) {
1828
for (ii=0; ii<4; ii++) {
1829
for (jj=0; jj<4; jj++) {
1830
vox2mm->m[ii][jj] = sform44.m[ii][jj];
1834
} else if (qform_code!=NIFTI_XFORM_UNKNOWN) {
1835
for (ii=0; ii<4; ii++) {
1836
for (jj=0; jj<4; jj++) {
1837
vox2mm->m[ii][jj] = qform44.m[ii][jj];
1842
/* default case - for FSLView is positive voxel to mm scalings */
1843
vox2mm->m[0][0] = dx;
1844
vox2mm->m[0][1] = 0.0;
1845
vox2mm->m[0][2] = 0.0;
1846
vox2mm->m[0][3] = 0.0;
1847
vox2mm->m[1][0] = 0.0;
1848
vox2mm->m[1][1] = dy;
1849
vox2mm->m[1][2] = 0.0;
1850
vox2mm->m[1][3] = 0.0;
1851
vox2mm->m[2][0] = 0.0;
1852
vox2mm->m[2][1] = 0.0;
1853
vox2mm->m[2][2] = dz;
1854
vox2mm->m[2][3] = 0.0;
1855
vox2mm->m[3][0] = 0.0;
1856
vox2mm->m[3][1] = 0.0;
1857
vox2mm->m[3][2] = 0.0;
1858
vox2mm->m[3][3] = 1.0;
1859
retcode=NIFTI_XFORM_UNKNOWN;
1865
short FslGetVox2mmMatrix(FSLIO *fslio, mat44 *vox2mm)
1867
int sform_code, qform_code;
1868
float dx, dy, dz, tr;
1869
mat44 sform44, qform44;
1870
if (fslio==NULL) FSLIOERR("FslGetVox2mmMatrix: Null pointer passed for FSLIO");
1871
if (fslio->niftiptr!=NULL) {
1872
sform_code = FslGetStdXform(fslio,&sform44);
1873
qform_code = FslGetRigidXform(fslio,&qform44);
1874
FslGetVoxDim(fslio,&dx,&dy,&dz,&tr);
1875
return FslGetVox2mmMatrix2(vox2mm,sform_code,sform44,
1876
qform_code,qform44,dx,dy,dz);
1878
if (fslio->mincptr!=NULL) {
1879
fprintf(stderr,"Warning:: Minc is not yet supported\n");
1881
return NIFTI_XFORM_UNKNOWN;
1884
void FslSetAnalyzeSform(FSLIO *fslio, const short *orig,
1885
float dx, float dy, float dz)
1887
/* Creates an sform matrix for an Analyze file */
1888
/* THIS ALWAYS CREATES A RADIOLOGICAL ORDERED SFORM */
1889
/* NB: the origin passed in here is in Analyze convention - starting at 1, not 0 */
1891
if (fslio==NULL) FSLIOERR("FslSetAnalyzeSform: Null pointer passed for FSLIO");
1892
if (fslio->niftiptr!=NULL) {
1893
if (FslBaseFileType(FslGetFileType(fslio))==FSL_TYPE_ANALYZE) {
1895
fslio->niftiptr->sform_code = NIFTI_XFORM_UNKNOWN;
1897
/* ignore all zero origins - really all serious coord stuff should
1898
be done via the FslSetStdCoord call */
1899
if ((orig[0]!=0) || (orig[1]!=0) || (orig[2]!=0))
1901
short origx=0, origy=0, origz=0;
1902
if ((orig[0]!=0) || (orig[1]!=0) || (orig[2]!=0)) {
1903
/* convert to nifti conventions (start at 0 not 1) */
1904
origx = orig[0] - 1;
1905
origy = orig[1] - 1;
1906
origz = orig[2] - 1;
1908
if ( dx * dy * dz > 0 ) {
1909
/* change neurological convention to radiological if necessary */
1912
if ( (FslBaseFileType(FslGetFileType(fslio))==FSL_TYPE_ANALYZE)
1913
|| (fslio->niftiptr->sform_code == NIFTI_XFORM_UNKNOWN) ) {
1914
/* make a default transform with the requested origin at xyz=000 */
1915
fslio->niftiptr->sform_code = NIFTI_XFORM_ALIGNED_ANAT;
1916
fslio->niftiptr->sto_xyz.m[0][0] = dx;
1917
fslio->niftiptr->sto_xyz.m[0][1] = 0;
1918
fslio->niftiptr->sto_xyz.m[0][2] = 0;
1919
fslio->niftiptr->sto_xyz.m[0][3] = -(origx)*(dx);
1920
fslio->niftiptr->sto_xyz.m[1][0] = 0;
1921
fslio->niftiptr->sto_xyz.m[1][1] = dy;
1922
fslio->niftiptr->sto_xyz.m[1][2] = 0;
1923
fslio->niftiptr->sto_xyz.m[1][3] = -(origy)*(dy);
1924
fslio->niftiptr->sto_xyz.m[2][0] = 0;
1925
fslio->niftiptr->sto_xyz.m[2][1] = 0;
1926
fslio->niftiptr->sto_xyz.m[2][2] = dz;
1927
fslio->niftiptr->sto_xyz.m[2][3] = -(origz)*(dz);
1928
fslio->niftiptr->sto_xyz.m[3][0] = 0;
1929
fslio->niftiptr->sto_xyz.m[3][1] = 0;
1930
fslio->niftiptr->sto_xyz.m[3][2] = 0;
1931
fslio->niftiptr->sto_xyz.m[3][3] = 1;
1932
fslio->niftiptr->sto_ijk =
1933
nifti_mat44_inverse(fslio->niftiptr->sto_xyz);
1935
/* update the existing origin */
1936
/* find out what the existing xyz of the requested origin is */
1937
x = fslio->niftiptr->sto_xyz.m[0][0] * origx
1938
+ fslio->niftiptr->sto_xyz.m[0][1] * origy
1939
+ fslio->niftiptr->sto_xyz.m[0][2] * origz
1940
+ fslio->niftiptr->sto_xyz.m[0][3];
1941
y = fslio->niftiptr->sto_xyz.m[1][0] * origx
1942
+ fslio->niftiptr->sto_xyz.m[1][1] * origy
1943
+ fslio->niftiptr->sto_xyz.m[1][2] * origz
1944
+ fslio->niftiptr->sto_xyz.m[1][3];
1945
z = fslio->niftiptr->sto_xyz.m[2][0] * origx
1946
+ fslio->niftiptr->sto_xyz.m[2][1] * origy
1947
+ fslio->niftiptr->sto_xyz.m[2][2] * origz
1948
+ fslio->niftiptr->sto_xyz.m[2][3];
1949
/* subtract off whatever is currently the xyz of the origin */
1950
fslio->niftiptr->sto_xyz.m[0][3] -= x;
1951
fslio->niftiptr->sto_xyz.m[1][3] -= y;
1952
fslio->niftiptr->sto_xyz.m[2][3] -= z;
1953
fslio->niftiptr->sto_ijk =
1954
nifti_mat44_inverse(fslio->niftiptr->sto_xyz);
1960
if (fslio->mincptr!=NULL) {
1961
fprintf(stderr,"Warning:: Minc is not yet supported\n");
1966
void FslGetAnalyzeOrigin(FSLIO *fslio, short orig[5])
1968
/* NB: orig returned here is in Analyze convention - starting at 1, not 0 */
1969
if (fslio==NULL) FSLIOERR("FslGetAnalyzeOrigin: Null pointer passed for FSLIO");
1970
if (fslio->niftiptr!=NULL) {
1971
/* Use sform or qform to determine the origin - default is zero */
1978
if (fslio->niftiptr->qform_code != NIFTI_XFORM_UNKNOWN) {
1979
orig[0]=(short) fslio->niftiptr->qto_ijk.m[0][3] + 1;
1980
orig[1]=(short) fslio->niftiptr->qto_ijk.m[1][3] + 1;
1981
orig[2]=(short) fslio->niftiptr->qto_ijk.m[2][3] + 1;
1984
if (fslio->niftiptr->sform_code != NIFTI_XFORM_UNKNOWN) {
1985
orig[0]=(short) fslio->niftiptr->sto_ijk.m[0][3] + 1;
1986
orig[1]=(short) fslio->niftiptr->sto_ijk.m[1][3] + 1;
1987
orig[2]=(short) fslio->niftiptr->sto_ijk.m[2][3] + 1;
1990
if (fslio->mincptr!=NULL) {
1991
fprintf(stderr,"Warning:: Minc is not yet supported\n");
1997
/***************************************************************
1999
***************************************************************/
2000
/*! \fn int FslClose(FSLIO *fslio)
2001
\brief Write header and image data if this dataset was open for
2002
writing. Close the dataset header and data files.
2005
\param fslio pointer to FSLIO data structure
2006
\return -1 on error, 0 OK ???.
2008
int FslClose(FSLIO *fslio)
2010
int retval=0, filetype;
2014
if (fslio==NULL) return 0;
2016
/* close the (data) file */
2017
if (!znz_isnull(fslio->fileptr)) retval=znzclose(fslio->fileptr);
2019
/** ----- if writing the image, need to worry about the header bit ----- **/
2021
if ( (fslio->niftiptr!=NULL) && (FslGetWriteMode(fslio)==1)
2022
&& (fslio->written_hdr==0) ) {
2024
/* ensure that the type is set correctly */
2025
fslio->niftiptr->nifti_type = FslBaseFileType(FslGetFileType(fslio));
2027
/* must write the header now */
2028
filetype = FslGetFileType(fslio);
2029
strcpy(fslio->niftiptr->descrip,"FSL4.0");
2030
if (!FslIsSingleFileType(filetype)) {
2031
/* for file pairs - open new header file and write it */
2032
nifti_image_write_hdr_img(fslio->niftiptr,0,"wb");
2034
/* for single files it is more complicated */
2035
if (!FslIsCompressedFileType(filetype)) {
2036
/* noncompressed -> reopen this file in r+ mode and write the header part again */
2037
nifti_image_write_hdr_img(fslio->niftiptr,0,"r+b");
2039
/* compressed mode -> not possible! */
2040
fprintf(stderr,"Error:: header must be written before writing any other data.\n");
2046
/* --- nasty hack to write the origin in Analyze files --- */
2048
if ( (FslGetWriteMode(fslio)==1) && (fslio->niftiptr!=NULL) &&
2049
(FslBaseFileType(FslGetFileType(fslio))==FSL_TYPE_ANALYZE) ) {
2051
/* read in the old header, change the origin and write it out again */
2052
hdr = (struct dsr *) calloc(1,sizeof(struct dsr));
2053
FslReadRawHeader(hdr,fslio->niftiptr->fname);
2054
if (fslio->niftiptr->byteorder != nifti_short_order()) {AvwSwapHeader(hdr);}
2056
/* calculate origin from sform (if set) */
2059
FslGetAnalyzeOrigin(fslio,blah);
2060
memcpy(hdr->hist.originator,blah,5*sizeof(short));
2062
/* Write out in radiological order if origin is non-zero */
2063
/* set negative pixdim if needed to keep LR orientation consistent */
2064
if ( (blah[0]!=0) || (blah[1]!=0) || (blah[2]!=0) ) {
2065
if (hdr->dime.pixdim[1] * hdr->dime.pixdim[2] * hdr->dime.pixdim[3] > 0) {
2066
hdr->dime.pixdim[1] = - hdr->dime.pixdim[1];
2071
/* swap back byte order and write out */
2072
if (fslio->niftiptr->byteorder != nifti_short_order()) {AvwSwapHeader(hdr);}
2073
hptr = znzopen(fslio->niftiptr->fname,"wb",FslIsCompressedFileType(FslGetFileType(fslio)));
2074
if (znz_isnull(hptr)) {
2075
fprintf(stderr,"Error:: Could not write origin data to header file %s.\n",
2076
fslio->niftiptr->fname);
2080
znzwrite(hdr,1,sizeof(struct dsr),hptr);
2085
if (fslio->mincptr!=NULL) {
2086
fprintf(stderr,"Warning:: Minc is not yet supported\n");
2094
void AvwSwapHeader(struct dsr *avw)
2098
ptr = (char *) &(avw->hk);
2099
nifti_swap_4bytes(1,ptr); /* sizeof_hdr */
2101
nifti_swap_4bytes(1,ptr); /* extents */
2103
nifti_swap_2bytes(1,ptr); /* session_error */
2105
ptr = (char *) &(avw->dime);
2106
nifti_swap_2bytes(8,ptr); /* dims */
2108
nifti_swap_2bytes(4,ptr); /* unused1, datatype, bitpix, dim_un0 */
2110
nifti_swap_4bytes(18,ptr); /* pixdim, vox_offset, ... */
2111
/* cal_min, compressed, ... glmin */
2113
ptr = (char *) &(avw->hist);
2115
nifti_swap_2bytes(5,ptr); /* originator (used to store origin) */
2117
nifti_swap_4bytes(8,ptr); /* views, ... smin */
2121
int FslReadRawHeader(void *buffer, const char* filename)
2125
fp = znzopen(filename,"rb",1);
2126
if (znz_isnull(fp)) {
2127
fprintf(stderr,"Could not open header %s\n",filename);
2130
retval = znzread(buffer,1,348,fp);
2132
if (retval != 348) {
2133
fprintf(stderr,"Could not read header %s\n",filename);
2139
void FslSetOverrideOutputType(int type)
2141
if ( (type==-1) || (FslIsValidFileType(type)) ) {
2142
FslOverrideOutputType=type;
2144
fprintf(stderr,"Invalid file type (%d) requested - ignoring this\n",type);
2148
int FslGetOverrideOutputType(void)
2150
return FslOverrideOutputType;
2153
void FslSetIgnoreMFQ(int flag)
2155
assert((flag==0) || (flag==1));
2160
int FslGetIgnoreMFQ(void)
2162
return FslIgnoreMFQ;
2165
/***************************************************************
2167
***************************************************************/
2168
/*! \fn FSLIO * FslReadHeader(char *fname)
2169
\brief Reads nifti/anz header, no data is read
2171
\param fname filename specification (could be .img,.hdr,.nii, or no ext
2172
\return FSLIO data structure with the nifti_image structure fields filled
2173
as per fname header.
2176
FSLIO * FslReadHeader(char *fname)
2178
char *hdrname, *imgname;
2184
/** get header file name */
2185
FslGetHdrImgNames(fname, fslio, &hdrname, &imgname);
2187
/** read header information */
2188
fslio->niftiptr = nifti_image_read(hdrname, 0);
2190
if (fslio->niftiptr == NULL) {
2191
FSLIOERR("FslReadHeader: error reading header information");
2195
fslio->file_mode = FslGetReadFileType(fslio);
2201
/***************************************************************
2202
* FslGetVolumeAsScaledDouble
2203
***************************************************************/
2204
/*! \fn double *** FslGetVolumeAsScaledDouble(FSLIO *fslio, int vol)
2205
\brief Return volume #vol (0-based) as a 3D array of scaled doubles.
2207
Volume Array is indexed as [0..zdim-1][0..ydim-1][0..xdim-1].
2208
<br>The array will be byteswapped to native-endian.
2209
<br>Array values are scaled as per fslio header slope and intercept fields.
2211
\param fslio pointer to open dataset
2212
\param vol volume number to read (legal range [0..tdim-1])
2213
\return Pointer to 3D double array, NULL on error
2215
double ***FslGetVolumeAsScaledDouble(FSLIO *fslio, int vol)
2225
if (fslio==NULL) FSLIOERR("FslGetVolumeAsScaledDouble: Null pointer passed for FSLIO");
2227
if ((fslio->niftiptr->dim[0] < 3) || (fslio->niftiptr->dim[0] > 4))
2228
FSLIOERR("FslGetVolumeAsScaledDouble: Incorrect dataset dimension, 3D-4D needed");
2230
/***** nifti dataset */
2231
if (fslio->niftiptr!=NULL) {
2232
xx = (fslio->niftiptr->nx == 0 ? 1 : (long)fslio->niftiptr->nx);
2233
yy = (fslio->niftiptr->ny == 0 ? 1 : (long)fslio->niftiptr->ny);
2234
zz = (fslio->niftiptr->nz == 0 ? 1 : (long)fslio->niftiptr->nz);
2236
if (fslio->niftiptr->scl_slope == 0) {
2241
slope = fslio->niftiptr->scl_slope;
2242
inter = fslio->niftiptr->scl_inter;
2246
/** allocate new 3D buffer */
2247
newbuf = d3matrix(zz-1,yy-1,xx-1);
2250
/** read in the data in disk format */
2253
dims_to_get[i] = -1;
2254
dims_to_get[4] = vol;
2258
ret = nifti_read_collapsed_image(fslio->niftiptr, dims_to_get, &diskbuf );
2260
fprintf(stderr,"ERROR:: read of disk buffer for volume %d from %s failed.\n",vol,fslio->niftiptr->iname);
2265
/** cvt disk buffer to scaled double buffer */
2266
ret = convertBufferToScaledDouble(newbuf[0][0], diskbuf, (long)(xx*yy*zz), slope, inter, fslio->niftiptr->datatype);
2278
if (fslio->mincptr!=NULL) {
2279
fprintf(stderr,"Warning:: Minc is not yet supported\n");
2288
/***************************************************************
2289
* FslGetBufferAsScaledDouble
2290
***************************************************************/
2291
/*! \fn double **** FslGetBufferAsScaledDouble(FSLIO *fslio)
2292
\brief Return the fslio data buffer of a 1-4D dataset as a 4D array of
2295
Array is indexed as buf[0..tdim-1][0..zdim-1][0..ydim-1][0..xdim-1].
2296
<br>The array will be byteswapped to native-endian.
2297
<br>Array values are scaled as per fslio header slope and intercept fields.
2299
\param fslio pointer to open dataset
2300
\return Pointer to 4D double array, NULL on error
2302
double ****FslGetBufferAsScaledDouble(FSLIO *fslio)
2309
if (fslio==NULL) FSLIOERR("FslGetBufferAsScaledDouble: Null pointer passed for FSLIO");
2311
if ((fslio->niftiptr->dim[0] <= 0) || (fslio->niftiptr->dim[0] > 4))
2312
FSLIOERR("FslGetBufferAsScaledDouble: Incorrect dataset dimension, 1-4D needed");
2314
/***** nifti dataset */
2315
if (fslio->niftiptr!=NULL) {
2316
xx = (fslio->niftiptr->nx == 0 ? 1 : (long)fslio->niftiptr->nx);
2317
yy = (fslio->niftiptr->ny == 0 ? 1 : (long)fslio->niftiptr->ny);
2318
zz = (fslio->niftiptr->nz == 0 ? 1 : (long)fslio->niftiptr->nz);
2319
tt = (fslio->niftiptr->nt == 0 ? 1 : (long)fslio->niftiptr->nt);
2321
if (fslio->niftiptr->scl_slope == 0) {
2326
slope = fslio->niftiptr->scl_slope;
2327
inter = fslio->niftiptr->scl_inter;
2331
/** allocate new 4D buffer */
2332
newbuf = d4matrix(tt-1,zz-1,yy-1,xx-1);
2335
ret = convertBufferToScaledDouble(newbuf[0][0][0], fslio->niftiptr->data, (long)(xx*yy*zz*tt), slope, inter, fslio->niftiptr->datatype);
2345
if (fslio->mincptr!=NULL) {
2346
fprintf(stderr,"Warning:: Minc is not yet supported\n");
2352
/***************************************************************
2353
* convertBufferToScaledDouble
2354
***************************************************************/
2355
/*! \fn int convertBufferToScaledDouble(double *outbuf, void *inbuf, long len, float slope, float inter, int nifti_datatype )
2356
\brief allocate a 4D buffer, use 1 contiguous buffer for the data
2358
Array is indexed as buf[0..th-1][0..zh-1][0..yh-1][0..xh-1].
2359
<br>To access all elements as a vector, use buf[0][0][0][i] where
2360
i can range from 0 to th*zh*yh*xh - 1.
2362
\param outbuf pointer to array of doubles of size len
2363
\param inbuf void pointer to an array of len items of datatype nifti_datatype
2364
\param len number of elements in outbuf and inbuf
2365
\param slope slope term of scaling to be applied
2366
\param inter intercept term of scaling to be applied: out = (in*slope)+inter
2367
\param nifti_datatype NIFTI datatype code for the datatype of the elements in inbuf
2368
\return error code: 0=OK -1=error
2370
int convertBufferToScaledDouble(double *outbuf, void *inbuf, long len, float slope, float inter, int nifti_datatype )
2376
/** fill the buffer */
2377
for (i=0; i<len; i++)
2378
switch(nifti_datatype) {
2379
case NIFTI_TYPE_UINT8:
2380
outbuf[i] = (double) ( *((THIS_UINT8 *)(inbuf)+i) * slope + inter);
2382
case NIFTI_TYPE_INT8:
2383
outbuf[i] = (double) ( *((THIS_INT8 *)(inbuf)+i) * slope + inter);
2385
case NIFTI_TYPE_UINT16:
2386
outbuf[i] = (double) ( *((THIS_UINT16 *)(inbuf)+i) * slope + inter);
2388
case NIFTI_TYPE_INT16:
2389
outbuf[i] = (double) ( *((THIS_INT16 *)(inbuf)+i) * slope + inter);
2391
case NIFTI_TYPE_UINT64:
2392
outbuf[i] = (double) ( *((THIS_UINT64 *)(inbuf)+i) * slope + inter);
2394
case NIFTI_TYPE_INT64:
2395
outbuf[i] = (double) ( *((THIS_INT64 *)(inbuf)+i) * slope + inter);
2397
case NIFTI_TYPE_UINT32:
2398
outbuf[i] = (double) ( *((THIS_UINT32 *)(inbuf)+i) * slope + inter);
2400
case NIFTI_TYPE_INT32:
2401
outbuf[i] = (double) ( *((THIS_INT32 *)(inbuf)+i) * slope + inter);
2403
case NIFTI_TYPE_FLOAT32:
2404
outbuf[i] = (double) ( *((THIS_FLOAT32 *)(inbuf)+i) * slope + inter);
2406
case NIFTI_TYPE_FLOAT64:
2407
outbuf[i] = (double) ( *((THIS_FLOAT64 *)(inbuf)+i) * slope + inter);
2410
case NIFTI_TYPE_FLOAT128:
2411
case NIFTI_TYPE_COMPLEX128:
2412
case NIFTI_TYPE_COMPLEX256:
2413
case NIFTI_TYPE_COMPLEX64:
2415
fprintf(stderr, "\nWarning, cannot support %s yet.\n",nifti_datatype_string(nifti_datatype));
2422
/***************************************************************
2424
***************************************************************/
2425
/*! \fn double ****d3matrix(int zh, int yh, int xh)
2426
\brief allocate a 3D buffer, use 1 contiguous buffer for the data
2428
Array is indexed as buf[0..zh][0..yh][0..xh].
2429
<br>To access all elements as a vector, use buf[0][0][i] where
2430
i can range from 0 to zh*yh*xh - 1.
2431
Adaptation of Numerical Recipes in C nrutil.c allocation routines.
2433
\param zh slowest changing dimension
2434
\param yh 2nd fastest changing dimension
2435
\param xh fastest changing dimension
2436
\return Pointer to 3D double array
2438
double ***d3matrix(int zh, int yh, int xh)
2448
/** allocate pointers to slices */
2449
t=(double ***) malloc((size_t)((nslice)*sizeof(double**)));
2450
if (!t) FSLIOERR("d3matrix: allocation failure");
2452
/** allocate pointers for ydim */
2453
t[0]=(double **) malloc((size_t)((nslice*nrow)*sizeof(double*)));
2454
if (!t[0]) FSLIOERR("d3matrix: allocation failure");
2457
/** allocate the data blob */
2458
t[0][0]=(double *) malloc((size_t)((nslice*nrow*ncol)*sizeof(double)));
2459
if (!t[0][0]) FSLIOERR("d3matrix: allocation failure");
2462
/** point everything to the data blob */
2463
for(j=1;j<nrow*nslice;j++) t[0][j]=t[0][j-1]+ncol;
2464
for(j=1;j<nslice;j++) t[j]=t[j-1]+nrow;
2470
/***************************************************************
2472
***************************************************************/
2473
/*! \fn double ****d4matrix(int th, int zh, int yh, int xh)
2474
\brief allocate a 4D buffer, use 1 contiguous buffer for the data
2476
Array is indexed as buf[0..th][0..zh][0..yh][0..xh].
2477
<br>To access all elements as a vector, use buf[0][0][0][i] where
2478
i can range from 0 to th*zh*yh*xh - 1.
2479
Adaptation of Numerical Recipes in C nrutil.c allocation routines.
2481
\param th slowest changing dimension
2482
\param zh 2nd slowest changing dimension
2483
\param yh 2nd fastest changing dimension
2484
\param xh fastest changing dimension
2485
\return Pointer to 4D double array
2487
double ****d4matrix(int th, int zh, int yh, int xh)
2498
/** allocate pointers to vols */
2499
t=(double ****) malloc((size_t)((nvol)*sizeof(double***)));
2500
if (!t) FSLIOERR("d4matrix: allocation failure");
2502
/** allocate pointers to slices */
2503
t[0]=(double ***) malloc((size_t)((nvol*nslice)*sizeof(double**)));
2504
if (!t[0]) FSLIOERR("d4matrix: allocation failure");
2506
/** allocate pointers for ydim */
2507
t[0][0]=(double **) malloc((size_t)((nvol*nslice*nrow)*sizeof(double*)));
2508
if (!t[0][0]) FSLIOERR("d4matrix: allocation failure");
2511
/** allocate the data blob */
2512
t[0][0][0]=(double *) malloc((size_t)((nvol*nslice*nrow*ncol)*sizeof(double)));
2513
if (!t[0][0][0]) FSLIOERR("d4matrix: allocation failure");
2516
/** point everything to the data blob */
2517
for(j=1;j<nrow*nslice*nvol;j++) t[0][0][j]=t[0][0][j-1]+ncol;
2518
for(j=1;j<nslice*nvol;j++) t[0][j]=t[0][j-1]+nrow;
2519
for(j=1;j<nvol;j++) t[j]=t[j-1]+nslice;