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