1 /*
2 3dTsplit4D.c
3 This is a quick program to split a 3d+time dataset into multiple
4 single 3D files. Mostly to facilitate transferring data into MATLAB toolboxes.
5 It can also be useful for deal with SPM and FSL programs.
6
7 Author: Peter J. Molfese, Haskins Laboratories/UConn/Yale
8 Contact: Peter.Molfese@yale.edu
9
10 January 5, 2016 - Initial Version
11 */
12
13
14
15 #include "mrilib.h"
16
help_3dTsplit4D()17 int help_3dTsplit4D( )
18 {
19 printf(
20 "USAGE: 3dTsplit4D [options] dataset\n\n"
21 "This program converts a 3D+time dataset into multiple 3D single-brick\n"
22 "files. The main purpose of this is to accelerate the process of\n"
23 "export AFNI/NIFTI datasets if you have the unfortunate need to work\n"
24 "with Some other PrograM that doesn't like datasets in the pseudo-4D\n"
25 "nature that AFNI knows and loves.\n"
26 "\n"
27 "examples:\n"
28 "\n"
29 " 1. Write the 152 time point dataset, epi_r1+orig, to 152 single\n"
30 " volume datasets, out/epi.000+orig ... epi.151+orig.\n"
31 "\n"
32 " 3dTsplit4D -prefix out/epi epi_r1+orig\n"
33 "\n"
34 " 2. Do the same thing, but write to 152 NIFTI volume datasets,\n"
35 " out/epi.000.nii ... out/epi.151.nii. Include .nii in -prefix.\n"
36 "\n"
37 " 3dTsplit4D -prefix out/epi.nii epi_r1+orig\n"
38 "\n"
39 " -prefix PREFIX : Prefix of the output datasets\n"
40 " Numbers will be added after the prefix to denote\n"
41 " prior sub-brick.\n"
42 " -keep_datum : output uses original datum (no conversion to float)\n"
43 " -digits DIGITS : number of digits to use for output filenames\n"
44 "\n\n"
45 "Authored by: Peter Molfese, UConn"
46 );
47
48 PRINT_COMPILE_DATE;
49 return(0);
50 }
51
52 /* a few updates 8 Dec 2016 [rickr] */
53
main(int argc,char * argv[])54 int main( int argc, char *argv[] )
55 {
56 THD_3dim_dataset *iset, *oset;
57 float ffac;
58 int iarg=1, kk, nval;
59 int datum=MRI_float, keep_datum=0, ndigits=0, prelen, smode;
60 char *prefix = "SPLIT";
61 char *sub_prefix, newlabel[32];
62 char *precopy=NULL, *exten=NULL; /* copied prefix and any needed ext */
63 MRI_IMAGE *inImage=NULL;
64
65 if( argc < 2 || strcmp(argv[1], "-help") == 0 )
66 {
67 help_3dTsplit4D( );
68 exit(0);
69 }
70
71 mainENTRY("3dTsplit4D");
72 machdep();
73
74 for( iarg=1; iarg < argc && argv[iarg][0] == '-'; iarg++ )
75 {
76 if( strcmp( argv[iarg], "-prefix") == 0 )
77 {
78 prefix = argv[++iarg];
79 if( !THD_filename_ok(prefix) )
80 ERROR_exit("bad -prefix value");
81 } else if( strcmp( argv[iarg], "-digits") == 0 )
82 {
83 ndigits = atoi(argv[++iarg]);
84 if( ndigits <= 0 )
85 ERROR_exit("bad -digits '%s'", argv[iarg-1]);
86 } else if( strcmp( argv[iarg], "-keep_datum") == 0 ) {
87 keep_datum = 1;
88 } else {
89 ERROR_exit("unknown option %s", argv[iarg]);
90 }
91 }
92
93 INFO_message("Prefix set to: %s\n", prefix);
94
95 /* Begin reading dataset, error checking like a good programmer */
96 iset = THD_open_dataset( argv[iarg] );
97 CHECK_OPEN_ERROR( iset, argv[iarg] );
98 THD_force_malloc_type( iset->dblk , DATABLOCK_MEM_MALLOC ) ;
99 DSET_load(iset);
100 CHECK_LOAD_ERROR(iset);
101
102 //begin looping through!
103
104 nval=DSET_NVALS(iset);
105 INFO_message("Dataset read...\n");
106 INFO_message("Number of Sub-bricks: %d\n", nval);
107
108 if( nval == 0 ) ERROR_exit("no volumes to output?");
109
110 /* how many digits do we need for the prefix trailer? 8 Dec 2016 */
111 if( ndigits == 0 )
112 ndigits = (int)(log(nval)/log(10)+1);
113
114 /* allocate sub_prefix */
115 kk = strlen(prefix) + ndigits + 4; /* full length of prefix, plus 2 extra */
116 sub_prefix = (char *)malloc(kk*sizeof(char));
117 if( ! sub_prefix ) ERROR_exit("failed to alloc %d bytes for prefix", kk);
118
119 /* make new prefix in case of non-AFNI writing, so it can be altered */
120 /* (precopy and exten will be used for actual output prefix) */
121 precopy = nifti_strdup(prefix);
122 exten = NULL;
123 smode = storage_mode_from_filename(prefix);
124 if( has_known_non_afni_extension(precopy)
125 && is_writable_storage_mode(smode) ) {
126 exten = find_filename_extension(precopy);
127 /* if found, terminate actual prefix, and point exten past '.' */
128 if( exten && exten > precopy )
129 *exten++ = '\0';
130 INFO_message("Using new prefix for non-AFNI write: %s\n", precopy);
131 }
132
133 oset = EDIT_empty_copy( iset ); //Easy to just copy!
134 THD_force_malloc_type( oset->dblk , DATABLOCK_MEM_MALLOC ) ;
135
136 printf("++ writing:");
137
138 for( kk=0 ; kk < nval ; kk++ )
139 {
140 /* MODIFY to make single brik output */
141 /* ALSO NEED TO CHANGE PREFIX EACH TIME! */
142
143 /* if there is a non-AFNI extension, use it 9 Dec 2016 [rickr] */
144 if(exten) sprintf(sub_prefix, "%s.%0*d.%s", precopy, ndigits, kk, exten);
145 else sprintf(sub_prefix, "%s.%0*d", precopy, ndigits, kk);
146
147 //sub_prefix = strncat( prefix, itoa(kk), 10 );
148
149 // INFO_message("File Saved: %s", sub_prefix);
150 if( kk == 0 || kk == (nval-1) )
151 printf(" %s ", sub_prefix);
152 else
153 putchar('.');
154
155 if( keep_datum ) datum = DSET_BRICK_TYPE(iset, kk);
156 else datum = MRI_float;
157
158 EDIT_dset_items( oset,
159 ADN_datum_all , datum ,
160 ADN_prefix , sub_prefix ,
161 ADN_ntt, 1 ,
162 ADN_nvals, 1, ADN_none);
163
164 if( DSET_HAS_LABEL(iset, kk) ) {
165 EDIT_dset_items( oset,
166 ADN_brick_label_one, DSET_BRICK_LABEL(iset, kk),
167 ADN_none );
168 } else {
169 sprintf(newlabel, "%.16s[%d]", DSET_PREFIX(iset), kk);
170 EDIT_dset_items( oset,
171 ADN_brick_label_one, newlabel,
172 ADN_none );
173 }
174
175 /* either pass the data along or make a float version */
176 if( keep_datum ) {
177 EDIT_substitute_brick( oset, 0, datum, DSET_ARRAY(iset, kk));
178 DSET_BRICK_FACTOR(oset,0) = DSET_BRICK_FACTOR(iset, kk);
179 } else {
180 inImage = THD_extract_float_brick(kk, iset);
181 if( inImage == NULL)
182 ERROR_exit("Failed to convert sub-brick %d of input dataset...",kk);
183
184 EDIT_substitute_brick( oset, 0, MRI_float, MRI_FLOAT_PTR(inImage) );
185 }
186
187 DSET_write( oset );
188 if( ! THD_is_file(DSET_BRIKNAME(oset)) )
189 ERROR_exit("failed to write dataset %s", sub_prefix);
190 //WROTE_DSET( oset );
191
192 DSET_unload_one(iset, kk);
193
194 /* for output, just clear borrowed pointer (being naughty?) */
195 DSET_BRICK(oset, 0) = NULL;
196
197 if( inImage) mri_clear_and_free( inImage );
198 } /* for each volume */
199
200 printf("\n...Done\n");
201
202 exit(0);
203 }
204