TPCCLIB
Loading...
Searching...
No Matches
ecat2ana.c
Go to the documentation of this file.
1
7/*****************************************************************************/
8#include "tpcclibConfig.h"
9/*****************************************************************************/
10#include <stdio.h>
11#include <stdlib.h>
12#include <math.h>
13#include <string.h>
14#include <time.h>
15#include <sys/stat.h>
16#include <unistd.h>
17#ifdef HAVE_DIRECT_H
18#include <direct.h>
19#endif
20/*****************************************************************************/
21#include "libtpcmisc.h"
22#include "libtpcimgio.h"
23#include "libtpcimgp.h"
24/*****************************************************************************/
25
26/*****************************************************************************/
27static char *info[] = {
28 "Converts ECAT 6.3 images or ECAT 7 image volumes to Analyze 7.5 image format.",
29 " ",
30 "The resulting Analyze database consists of two files, Analyze image (*.img)",
31 "and header file (*.hdr).",
32 "Analyze image format does not contain information on the frame times.",
33 "Frame times can be retrieved from SIF file, which can be created optionally.",
34 "SIF can also be created using other software.",
35 " ",
36 "By default, data is saved in big endian byte order (Sun Sparc).",
37 " ",
38 "Usage: @P [Options] ecatfile(s)",
39 " ",
40 "Options:",
41 " -Little or -pc or -intel",
42 " Data is saved in little endian (PC Intel) byte order.",
43 " -Big or -sun or -sparc",
44 " Data is saved in big endian (Sun Sparc, Motorola, PowerPC) byte order",
45 " (default).",
46 " -O=<output path>",
47 " Data directory for Analyze files; by default the output directory",
48 " ana_unix_files or ana_pc_files is created under input directory.",
49 " -flip=<y|n>",
50 " Override the default and environment variable ANALYZE_FLIP setting",
51 " by always flipping/not flipping image in z-direction (planes).",
52 " If environment variable is not set, then default is y.",
53 " Images are always flipped in x,y-directions.",
54 " -sif",
55 " SIF is saved with Analyze files; note that existing SIF will be",
56 " overwritten.",
57 " -frames",
58 " Time frames are saved as separate Analyze files.",
59 " -stdoptions", // List standard options like --help, -v, etc
60 " ",
61 "Example:",
62 " @P -o=anal *.v",
63 " ",
64 "Specific extensions to Analyze 7.5 format:",
65 " -Scale factor to retain quantitation in image_dimension.funused1",
66 " -Isotope halflife (sec) in image_dimension.funused3;",
67 " this does not imply whether data is corrected for decay or not.",
68 " -String in data_history.descrip tells whether data is corrected for decay;",
69 " 'Decay corrected.' or 'No decay correction.'",
70 " ",
71 "See also: ana2ecat, anabyteo, ana_lhdr, eframe, img2flat, ecat2nii",
72 " ",
73 "Keywords: image, format conversion, ECAT, Analyze",
74 0};
75/*****************************************************************************/
76
77/*****************************************************************************/
78/* Turn on the globbing of the command line, since it is disabled by default in
79 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
80 In Unix&Linux wildcard command line processing is enabled by default. */
81/*
82#undef _CRT_glob
83#define _CRT_glob -1
84*/
85int _dowildcard = -1;
86/*****************************************************************************/
87
88/*****************************************************************************/
92int main(int argc, char **argv)
93{
94 int ai, help=0, version=0, verbose=1;
95 int ret, errorNr=0, flipping, fi=0, ffi=0, fileNr=0;
96 int ana_order=1; /* 0=little (intel), 1=big endian (sparc) */
97 int separate_frames=0;
98 int file_format=0;
99 int save_sif=0; // SIF is made (1) or not made (0)
100 char ecatfile[FILENAME_MAX], dbname[FILENAME_MAX], *cptr;
101 char temp[FILENAME_MAX], outputdir[FILENAME_MAX], dbdir[FILENAME_MAX];
102 IMG img;
103 float fmin, fmax;
104 SIF sif;
105
106
107 /*
108 * Get arguments
109 */
110 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
111 outputdir[0]=ecatfile[0]=dbname[0]=dbdir[0]=(char)0;
112 flipping=anaFlipping();
113 imgInit(&img); sifInit(&sif);
114 /* Options */
115 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') { /* options */
116 cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(cptr==NULL) continue;
117 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
118 if(strncasecmp(cptr, "FLIP=", 5)==0) {
119 cptr+=5; if(*cptr=='n' || *cptr=='N') {flipping=0; continue;}
120 else if(*cptr=='y' || *cptr=='Y') {flipping=1; continue;}
121 } else if(strncasecmp(cptr, "FRAMES", 2)==0) {
122 separate_frames=1; continue;
123 } else if(strcasecmp(cptr, "LITTLE")==0) {
124 ana_order=0; continue;
125 } else if(strcasecmp(cptr, "PC")==0) {
126 ana_order=0; continue;
127 } else if(strcasecmp(cptr, "INTEL")==0) {
128 ana_order=0; continue;
129 } else if(strcasecmp(cptr, "BIG")==0) {
130 ana_order=1; continue;
131 } else if(strcasecmp(cptr, "SUN")==0) {
132 ana_order=1; continue;
133 } else if(strcasecmp(cptr, "SPARC")==0) {
134 ana_order=1; continue;
135 } else if(strncasecmp(cptr, "O=", 2)==0) {
136 cptr+=2;
137 if(strlen(cptr)>0) strcpy(outputdir, cptr); else strcpy(outputdir, ".");
138 continue;
139 } else if(strcasecmp(cptr, "SIF")==0) {
140 save_sif=1; continue;
141 }
142 fprintf(stderr, "Error: invalid option '%s'\n", argv[ai]);
143 return(1);
144 } else break;
145
146 /* Print help or version? */
147 if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
148 if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
149 if(version) {tpcPrintBuild(argv[0], stdout); return(0);}
150
151 /* Process other arguments, starting from the first non-option */
152 for(; ai<argc; ai++) {
153 /* Other arguments are ECAT files which must exist */
154 if(access(argv[ai], 0) == -1) {
155 fprintf(stderr, "Error: file %s does not exist\n", argv[ai]);
156 return(1);
157 }
158 if(ffi<1) ffi=ai;
159 fileNr++;
160 }
161
162 /* Is something missing? */
163 if(fileNr<1) {
164 fprintf(stderr, "Error: no ECAT files were specified.\n");
165 return(1);
166 }
167
168
169 /* In verbose mode print arguments and options */
170 if(verbose>1) {
171 printf("flipping := %d\n", flipping);
172 printf("ana_order := %d\n", ana_order);
173 printf("separate_frames := %d\n", separate_frames);
174 printf("save_sif := %d\n", save_sif);
175 printf("outputdir := %s\n", outputdir);
176 printf("fileNr := %d\n", fileNr);
177 }
178 if(verbose>2) IMG_TEST=ANALYZE_TEST=verbose-2; else IMG_TEST=ANALYZE_TEST=0;
179 if(verbose>0) {
180 if(flipping==0) printf("image(s) will not be flipped in z-direction.\n");
181 else printf("image(s) will be flipped in z-direction.\n");
182 }
183
184
185 /*
186 * Process each ECAT file separately
187 */
188 if(verbose>1) printf("processing...\n");
189 fileNr=0;
190 for(ai=ffi; ai<argc; ai++) {
191
192 strcpy(ecatfile, argv[ai]);
193 if(verbose>0) {fprintf(stdout, "%s : \n", ecatfile); fflush(stdout);}
194 imgEmpty(&img);
195 sifEmpty(&sif);
196
197 /*
198 * Make Analyze database name
199 */
200 /* Make output directory name, if it was not given */
201 if(strlen(outputdir)<1) {
202 /* Get input directory */
203 strcpy(dbdir, ecatfile);
204 cptr=strrchr(dbdir, '/'); if(cptr==NULL) cptr=strrchr(dbdir, '\\');
205 if(cptr!=NULL) {cptr++; cptr[0]=(char)0;} else dbdir[0]=(char)0;
206 /* Add default part */
207 if(ana_order==1) strcat(dbdir, "ana_unix_files");
208 else strcat(dbdir, "ana_pc_files");
209 } else {
210 strcpy(dbdir, outputdir);
211 /* Remove trailing slashes */
212 ret=strlen(dbdir)-1;
213 if(dbdir[ret]=='/' || dbdir[ret]=='\\') dbdir[ret]=(char)0;
214 }
215 /* Create the subdirectory */
216 if(access(dbdir, 0) == -1) {
217 if(verbose>0) {
218 fprintf(stdout, " Creating subdirectory %s\n", dbdir);
219 fflush(stdout);
220 }
221#ifdef HAVE_MKDIR2
222 ret=mkdir(dbdir, 00775);
223#elif defined HAVE_MKDIR1
224 ret=mkdir(dbdir);
225#elif defined HAVE__MKDIR
226 ret=_mkdir(dbdir);
227#else
228 ret=1;
229#endif
230 if(ret!=0) {
231 fprintf(stderr, " Error: cannot create subdirectory.\n");
232 fflush(stderr); errorNr++; continue;
233 }
234 }
235 /* Combine path and filename */
236 cptr=strrchr(ecatfile, '/'); if(cptr==NULL) cptr=strrchr(ecatfile, '\\');
237 if(cptr==NULL) cptr=ecatfile; else cptr++;
238#ifdef WIN32
239 snprintf(dbname, FILENAME_MAX, "%s\\%s", dbdir, cptr);
240#else
241 snprintf(dbname, FILENAME_MAX, "%s/%s", dbdir, cptr);
242#endif
243 cptr=strrchr(dbname, '.'); if(cptr!=NULL) cptr[0]=(char)0;
244 if(verbose>1) printf(" Analyze db_name: '%s'\n", dbname);
245 /* Check if file exists: Analyze database can be overwritten, but existing
246 ECAT 6.3 image (.img without .hdr) will lead to an error */
247 if(separate_frames!=1 && anaExists(dbname)==0) {
248 strcpy(temp, dbname); strcat(temp, ".img");
249 if(access(temp, 0) != -1) {
250 fprintf(stderr, " Error: %s would be overwritten.\n", temp);
251 fprintf(stdout, " No conversion is done for %s\n", ecatfile);
252 fflush(stdout); fflush(stderr);
253 errorNr++; continue;
254 }
255 }
256
257 /*
258 * Remove possibly existing database
259 */
260 ret=anaRemove(dbname); if(ret) return STATUS_CANNOTERASE;
261
262 /*
263 * Get the global min and max pixel values;
264 * those are needed for Analyze header, and for scaling pixels
265 */
266 if(verbose>1) fprintf(stdout, " searching min and max in %s\n", ecatfile);
267 ret=imgReadMinMax(ecatfile, &fmin, &fmax);
268 if(ret) {
269 fprintf(stderr, "Error: %s\n", imgStatus(ret));
270 if(verbose>3) imgInfo(&img);
271 errorNr++; fflush(stderr); continue;
272 }
273 if(verbose>2)
274 printf(" global_min := %g\n global_max := %g\n", fmin, fmax);
275
276 /*
277 * Get the frame number and allocate memory for SIF, if requested
278 */
279 if(save_sif) {
280 /* Read information from input image for SIF */
281 if(verbose>1) printf(" reading header information\n");
282 ret=imgReadHeader(ecatfile, &img, img._fileFormat);
283 if(ret) {
284 fprintf(stderr, "Error: %s\n", imgStatus(ret));
285 errorNr++; fflush(stderr); continue;
286 }
287 /* Allocate SIF to store frame times */
288 ret=sifSetmem(&sif, img.dimt); if(ret!=0) {
289 fprintf(stderr, "Error: out of memory.\n");
290 errorNr++; fflush(stderr); continue;
291 }
292 sif.colNr=4; sif.version=1;
293 imgEmpty(&img);
294 }
295
296 /*
297 * Conversion of ECAT file, one frame at a time
298 */
299 if(verbose>0) fprintf(stdout, " processing %s\n", ecatfile);
300 fi=0; imgEmpty(&img);
301 while((ret=imgReadFrame(ecatfile, fi+1, &img, 0)) == 0) {
302 if(verbose>1) printf(" frame %d\n", fi+1);
303 /* reverse the flipping/no-flipping in imgWriteAnalyzeFrame, if required */
304 if(flipping!=anaFlipping()) imgFlipPlanes(&img);
305 /* Set the write file format including byte order */
306 if(fi==0) file_format=img._fileFormat; // must be saved to enable reading
307 // the next frame
308 if(ana_order) img._fileFormat=IMG_ANA; else img._fileFormat=IMG_ANA_L;
309 /* Write the frame in Analyze format */
310 if(separate_frames!=1) { // into one Analyze file
311 ret=imgWriteAnalyzeFrame(dbname, fi+1, &img, 0, fmin, fmax);
312 if(ret) anaRemove(dbname); //printf("ret := %d\n", ret);
313 } else { // each frame in a separate Analyze file
314 snprintf(temp, FILENAME_MAX, "%s_fr%03d", dbname, fi+1); // make database name for frame
315 ret=imgMinMax(&img, &fmin, &fmax);
316 if(ret==0) ret=imgWriteAnalyzeFrame(temp, 1, &img, 0, fmin, fmax);
317 if(ret) anaRemove(temp);
318 }
319 if(ret!=STATUS_OK) break;
320 if(verbose>3) printf(" frame written.\n");
321 /* Set SIF contents for this frame, if requested */
322 if(save_sif) {
323 sif.x1[fi]=img.start[0]; sif.x2[fi]=img.end[0];
324 if(fi==0) {
325 /* Set isotope */
326 strcpy(sif.isotope_name, imgIsotope(&img) );
327 /* Set studynumber */
328 strcpy(sif.studynr, img.studyNr);
329 /* Set scan start time */
330 sif.scantime=img.scanStart;
331 }
332 }
333 /* Prepare to the next frame */
334 img._fileFormat=file_format;
335 fi++;
336 } // next frame
337 if(verbose>0) {
338 if(ret==STATUS_NOMATRIX)
339 fprintf(stdout, " %d frame(s) processed.\n", fi);
340 }
341 if(ret!=STATUS_OK && ret!=STATUS_NOMATRIX) {
342 fprintf(stderr, "Error: %s\n", imgStatus(ret)); //if(TEST) imgInfo(&img);
343 errorNr++; fflush(stderr); continue;
344 }
345 imgEmpty(&img);
346
347 /* Save SIF, if requested */
348 if(save_sif) {
349 char temp[FILENAME_MAX+4];
350 sprintf(temp, "%s.sif", dbname);
351 ret=sifWrite(&sif, temp);
352 if(ret!=0) {
353 fprintf(stderr, "Error: cannot write %s\n", temp);
354 errorNr++; fflush(stderr); continue;
355 }
356 sifEmpty(&sif);
357 }
358
359 } /* next file */
360
361 if(errorNr>0) return(errorNr+10);
362 return(0);
363}
364/*****************************************************************************/
365
366/*****************************************************************************/
int anaFlipping()
Definition analyze.c:635
int ANALYZE_TEST
Definition analyze.c:8
int anaExists(const char *dbname)
Definition analyze.c:17
int anaRemove(const char *dbname)
Definition analyze.c:666
int IMG_TEST
Definition img.c:6
void imgInfo(IMG *image)
Definition img.c:359
char * imgStatus(int status_index)
Definition img.c:330
void imgEmpty(IMG *image)
Definition img.c:121
void imgInit(IMG *image)
Definition img.c:60
int imgWriteAnalyzeFrame(const char *dbname, int frame_to_write, IMG *img, int frame_index, float fmin, float fmax)
Definition img_ana.c:751
char * imgIsotope(IMG *img)
Definition imgdecayc.c:76
int imgReadFrame(const char *fname, int frame_to_read, IMG *img, int frame_index)
Definition imgfile.c:269
int imgReadHeader(const char *fname, IMG *img, int format)
Definition imgfile.c:199
void imgFlipPlanes(IMG *img)
Definition imgflips.c:55
int imgReadMinMax(const char *fname, float *fmin, float *fmax)
Definition imgminmax.c:211
int imgMinMax(IMG *img, float *minvalue, float *maxvalue)
Definition imgminmax.c:154
Header file for libtpcimgio.
int sifWrite(SIF *data, char *filename)
Definition sifio.c:145
#define IMG_ANA_L
void sifInit(SIF *data)
Definition sif.c:17
#define IMG_ANA
int sifSetmem(SIF *data, int frameNr)
Definition sif.c:56
void sifEmpty(SIF *data)
Definition sif.c:33
Header file for libtpcimgp.
Header file for libtpcmisc.
int tpcProcessStdOptions(const char *s, int *print_usage, int *print_version, int *verbose_level)
Definition proginfo.c:40
int tpcHtmlUsage(const char *program, char *text[], const char *path)
Definition proginfo.c:213
void tpcPrintBuild(const char *program, FILE *fp)
Definition proginfo.c:383
void tpcPrintUsage(const char *program, char *text[], FILE *fp)
Definition proginfo.c:158
time_t scanStart
int _fileFormat
unsigned short int dimt
float * start
float * end
char studyNr[MAX_STUDYNR_LEN+1]
double * x1
double * x2
int version
char studynr[MAX_STUDYNR_LEN+1]
time_t scantime
char isotope_name[8]
int colNr