TPCCLIB
Loading...
Searching...
No Matches
ecat2nii.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 PET images from ECAT 6.3 or 7 to NIfTI-1 format.",
29 "Conversion can also be done using ImageConverter (.NET application).",
30 " ",
31 "Image byte order is determined by the computer where the program is run.",
32 "NIfTI 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 later using other software.",
35 " ",
36 "Usage: @P [Options] ecatfile(s)",
37 " ",
38 "Options:",
39 " -O=<output path>",
40 " Data directory for NIfTI files, if other than the current working path.",
41 " -dual",
42 " Save the image in dual file format (the header and voxel data in",
43 " separate files *.hdr and *.img); single file format (*.nii)",
44 " is the default.",
45 " -sif",
46 " SIF is saved with NIfTI; note that existing SIF will be overwritten.",
47 " -stdoptions", // List standard options like --help, -v, etc
48 " ",
49 "Example:",
50 " @P *.v",
51 " ",
52 "See also: nii2ecat, nii_lhdr, ecat2ana, eframe, img2flat",
53 " ",
54 "Keywords: image, format conversion, ECAT, NIfTI",
55 0};
56/*****************************************************************************/
57
58/*****************************************************************************/
59/* Turn on the globbing of the command line, since it is disabled by default in
60 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
61 In Unix&Linux wildcard command line processing is enabled by default. */
62/*
63#undef _CRT_glob
64#define _CRT_glob -1
65*/
66int _dowildcard = -1;
67/*****************************************************************************/
68
69/*****************************************************************************/
73int main(int argc, char **argv)
74{
75 int ai, help=0, version=0, verbose=1;
76 int ret, errorNr=0, fi=0, fileNr=0, ffi=0;
77 int fileformat=IMG_NIFTI_1S; /* IMG_NIFTI_1S = single file format,
78 IMG_NIFTI_1D = dual file format */
79 int save_sif=0; // SIF is made (1) or not made (0)
80 char ecatfile[FILENAME_MAX], dbname[FILENAME_MAX], *cptr;
81 char outputdir[FILENAME_MAX], dbdir[FILENAME_MAX];
82 IMG img;
83 float fmin, fmax;
84 SIF sif;
85 int prev_fileformat=0;
86
87
88 /*
89 * Get arguments
90 */
91 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
92 outputdir[0]=ecatfile[0]=dbname[0]=dbdir[0]=(char)0;
93 imgInit(&img); sifInit(&sif);
94 /* Options */
95 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') { /* options */
96 cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(cptr==NULL) continue;
97 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
98 if(strncasecmp(cptr, "DUAL", 3)==0) {
99 fileformat=IMG_NIFTI_1D; continue;
100 } else if(strncasecmp(cptr, "O=", 2)==0) {
101 cptr+=2;
102 if(strlen(cptr)>0) strcpy(outputdir, cptr); else strcpy(outputdir, ".");
103 continue;
104 } else if(strcasecmp(cptr, "SIF")==0) {
105 save_sif=1; continue;
106 }
107 fprintf(stderr, "Error: invalid option '%s'\n", argv[ai]);
108 return(1);
109 } else break;
110
111 /* Print help or version? */
112 if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
113 if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
114 if(version) {tpcPrintBuild(argv[0], stdout); return(0);}
115
116 /* Process other arguments, starting from the first non-option */
117 for(; ai<argc; ai++) {
118 /* Other files are ECAT files which must exist */
119 if(access(argv[ai], 0) == -1) {
120 fprintf(stderr, "Error: file %s does not exist\n", argv[ai]);
121 return(1);
122 }
123 if(ffi<1) ffi=ai;
124 fileNr++;
125 }
126
127 /* Is something missing? */
128 if(fileNr<1) {
129 fprintf(stderr, "Error: no ECAT files were specified.\n");
130 return(1);
131 }
132
133 /* In verbose mode print arguments and options */
134 if(verbose>1) {
135 printf("program := %s\n", argv[0]);
136 if(fileformat==IMG_NIFTI_1D) printf("fileformat := 1D\n");
137 else printf("fileformat := 1S\n");
138 printf("save_sif := %d\n", save_sif);
139 printf("outputdir := %s\n", outputdir);
140 printf("fileNr := %d\n", fileNr);
141 }
142 if(verbose>3) IMG_TEST=verbose-3; else IMG_TEST=0;
143
144
145 /*
146 * Process each ECAT file separately
147 */
148 if(verbose>1) printf("processing...\n");
149 fileNr=0;
150 for(ai=ffi; ai<argc; ai++) {
151
152 strlcpy(ecatfile, argv[ai], FILENAME_MAX);
153 if(verbose>0) {fprintf(stdout, "%s : \n", ecatfile); fflush(stdout);}
154 imgEmpty(&img);
155 sifEmpty(&sif);
156
157 /*
158 * Make NIfTI database name
159 */
160 /* Make output directory name, if it was not given */
161 if(strlen(outputdir)<1) {
162 strcpy(dbdir, ".");
163 } else {
164 strlcpy(dbdir, outputdir, FILENAME_MAX);
165 /* Remove trailing slashes */
166 ret=strlen(dbdir)-1;
167 if(dbdir[ret]=='/' || dbdir[ret]=='\\') dbdir[ret]=(char)0;
168 }
169 /* Create the subdirectory */
170 if(access(dbdir, 0) == -1) {
171 if(verbose>0) {
172 fprintf(stdout, " Creating subdirectory %s\n", dbdir);
173 fflush(stdout);
174 }
175#ifdef HAVE_MKDIR2
176 ret=mkdir(dbdir, 00775);
177#elif defined HAVE_MKDIR1
178 ret=mkdir(dbdir);
179#elif defined HAVE__MKDIR
180 ret=_mkdir(dbdir);
181#else
182 ret=1;
183#endif
184 if(ret!=0) {
185 fprintf(stderr, " Error: cannot create subdirectory.\n");
186 fflush(stderr); errorNr++; continue;
187 }
188 }
189 /* Combine path and filename */
190 cptr=strrchr(ecatfile, '/'); if(cptr==NULL) cptr=strrchr(ecatfile, '\\');
191 if(cptr==NULL) cptr=ecatfile; else cptr++;
192#ifdef WIN32
193 snprintf(dbname, FILENAME_MAX, "%s\\%s", dbdir, cptr);
194#else
195 snprintf(dbname, FILENAME_MAX, "%s/%s", dbdir, cptr);
196#endif
197 cptr=strrchr(dbname, '.'); if(cptr!=NULL) cptr[0]=(char)0;
198 if(verbose>1) printf(" NIfTI db_name: '%s'\n", dbname);
199
200 /* Delete previous NIfTI */
201 /* It does not need to be valid NIfTI format, just that the filenames
202 match */
203 if(verbose>1) printf(" checking if file exists\n");
204 char hdrfile[FILENAME_MAX], imgfile[FILENAME_MAX];
205 ret=niftiCreateFNames(dbname, hdrfile, imgfile, NULL, fileformat);
206 if(ret!=0) {
207 fprintf(stderr, " Error: invalid NIfTI name %s\n", dbname);
208 fprintf(stdout, " No conversion is done for %s\n", ecatfile);
209 fflush(stdout); fflush(stderr);
210 errorNr++; continue;
211 }
212 if(fileformat==IMG_NIFTI_1S) {
213 /* If single file format, then just try to delete */
214 ret=niftiRemove(dbname, fileformat, verbose-3);
215 } else {
216 /* Dual file format; check that we are not accidentally deleting
217 ECAT 6.3 or other .img file that is not NIfTI or Analyze */
218 if(access(hdrfile, 0)!=-1) {
219 /* hdr file exists, thus delete it and possible img file */
220 ret=niftiRemove(dbname, fileformat, verbose-3);
221 } else if(access(imgfile, 0)!=-1) {
222 /* only img exists */
223 fprintf(stderr, " Error: %s would be overwritten.\n", imgfile);
224 fprintf(stdout, " No conversion is done for %s\n", ecatfile);
225 fflush(stdout); fflush(stderr);
226 errorNr++; continue;
227 }
228 }
229
230
231 /*
232 * Get the global min and max pixel values;
233 * those are needed for the header, and for scaling pixels
234 */
235 if(verbose>1) fprintf(stdout, " searching min and max in %s\n", ecatfile);
236 ret=imgReadMinMax(ecatfile, &fmin, &fmax);
237 if(ret) {
238 fprintf(stderr, "Error: %s\n", imgStatus(ret));
239 errorNr++; fflush(stderr); continue;
240 }
241 if(verbose>2)
242 printf(" global_min := %g\n global_max := %g\n", fmin, fmax);
243
244 /*
245 * Get the frame number and allocate memory for SIF, if requested
246 */
247 if(save_sif) {
248 /* Read information from input image for SIF */
249 if(verbose>1) printf(" reading header information\n");
250 ret=imgReadHeader(ecatfile, &img, img._fileFormat);
251 if(ret) {
252 fprintf(stderr, "Error: %s\n", imgStatus(ret));
253 errorNr++; fflush(stderr); continue;
254 }
255 /* Allocate SIF to store frame times */
256 ret=sifSetmem(&sif, img.dimt); if(ret!=0) {
257 fprintf(stderr, "Error: out of memory.\n");
258 errorNr++; fflush(stderr); continue;
259 }
260 sif.colNr=4; sif.version=1;
261 imgEmpty(&img);
262 }
263
264 /*
265 * Conversion of ECAT file, one frame at a time
266 */
267 if(verbose>0) {
268 fprintf(stdout, " processing %s\n", ecatfile); fflush(stdout);}
269 fi=0; imgEmpty(&img);
270 while((ret=imgReadFrame(ecatfile, fi+1, &img, 0)) == 0) {
271 if(verbose>1) {printf(" frame %d\n", fi+1); fflush(stdout);}
272 /* Set the write file format including byte order */
273 if(fi==0) // must be saved for reading next frame
274 prev_fileformat=img._fileFormat;
275 img._fileFormat=fileformat;
276
277 /* Write the frame in NIfTI format */
278 ret=imgWriteNiftiFrame(dbname, fi+1, &img, 0, fmin, fmax, verbose-3);
279 if(ret) niftiRemove(dbname, fileformat, verbose-4);
280 //printf("ret := %d\n", ret);
281 if(ret!=STATUS_OK) {
282 if(verbose>2) fprintf(stderr, "Error: %s.\n", imgStatus(ret));
283 break;
284 }
285 if(verbose>2) {printf(" frame %d written.\n", fi+1); fflush(stdout);}
286 /* Set SIF contents for this frame, if requested */
287 if(save_sif) {
288 sif.x1[fi]=img.start[0]; sif.x2[fi]=img.end[0];
289 if(fi==0) {
290 /* Set isotope */
291 strcpy(sif.isotope_name, imgIsotope(&img) );
292 /* Set studynumber */
293 strcpy(sif.studynr, img.studyNr);
294 /* Set scan start time */
295 sif.scantime=img.scanStart;
296 }
297 }
298 /* Prepare to the next frame */
299 img._fileFormat=prev_fileformat;
300 fi++;
301 if(verbose>2) {
302 printf(" about to read frame %d\n", fi+1); fflush(stdout);}
303 } // next frame
304 if(verbose>0) {
305 if(ret==STATUS_NOMATRIX) {
306 fprintf(stdout, " %d frame(s) processed.\n", fi); fflush(stdout);
307 }
308 }
309 if(ret!=STATUS_OK && ret!=STATUS_NOMATRIX) {
310 fprintf(stderr, "Error: %s\n", imgStatus(ret)); // imgInfo(&img);
311 niftiRemove(dbname, fileformat, verbose-2);
312 errorNr++; fflush(stderr); continue;
313 }
314 imgEmpty(&img);
315
316 /* Save SIF, if requested */
317 if(save_sif) {
318 char temp[FILENAME_MAX+10];
319 sprintf(temp, "%s.sif", dbname);
320 ret=sifWrite(&sif, temp);
321 if(ret!=0) {
322 fprintf(stderr, "Error: cannot write %s\n", temp);
323 errorNr++; fflush(stderr); continue;
324 }
325 sifEmpty(&sif);
326 }
327
328 } /* next file */
329
330 if(errorNr>0) return(errorNr+10);
331 return(0);
332}
333/*****************************************************************************/
334
335/*****************************************************************************/
int IMG_TEST
Definition img.c:6
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 imgWriteNiftiFrame(const char *dbname, int frame_to_write, IMG *img, int frame_index, float fmin, float fmax, int verbose)
Definition img_nii.c:594
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:270
int imgReadHeader(const char *fname, IMG *img, int format)
Definition imgfile.c:200
int imgReadMinMax(const char *fname, float *fmin, float *fmax)
Definition imgminmax.c:211
Header file for libtpcimgio.
int sifWrite(SIF *data, char *filename)
Definition sifio.c:145
#define IMG_NIFTI_1S
int niftiCreateFNames(const char *filename, char *hdrfile, char *imgfile, char *siffile, int fileformat)
Definition nifti.c:44
void sifInit(SIF *data)
Definition sif.c:17
#define IMG_NIFTI_1D
int sifSetmem(SIF *data, int frameNr)
Definition sif.c:56
void sifEmpty(SIF *data)
Definition sif.c:33
int niftiRemove(const char *dbname, int fileformat, int verbose)
Definition nifti.c:100
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
size_t strlcpy(char *dst, const char *src, size_t dstsize)
Definition strext.c:244
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