TPCCLIB
Loading...
Searching...
No Matches
e7to63.c
Go to the documentation of this file.
1
8/*****************************************************************************/
9#include "tpcclibConfig.h"
10/*****************************************************************************/
11#include <stdio.h>
12#include <stdlib.h>
13#include <math.h>
14#include <string.h>
15#include <time.h>
16/*****************************************************************************/
17#include "libtpcmisc.h"
18#include "libtpcimgio.h"
19#include "ehdrconv.h"
20/*****************************************************************************/
21
22/*****************************************************************************/
23static char *info[] = {
24 "Converting PET sinogram or image volume file in ECAT 7.x format to ECAT 6.3",
25 "format.",
26 " ",
27 "Usage: @P [Options] ECAT7_file [ECAT6_file]",
28 " ",
29 "Options:",
30 " -C=<o|k>",
31 " Image calibration unit is changed from Bq/mL or MBq/mL to",
32 " kBq/mL (k, default), or the original unit is preserved (o).",
33 " -stdoptions", // List standard options like --help, -v, etc
34 " ",
35 "Examples:",
36 "1. Convert one image, let program give name to ECAT6 file",
37 " e7to63 is02345.v",
38 "2. Convert one image, give a specific name to the ECAT6 file",
39 " e7to63 is02345.v is2345dy1.img",
40 "3. Convert all images in current working directory in Windows command shell",
41 " for %g in (*.v) do e7to63 %g",
42 " ",
43 "See also: e63to7, lmlist, ecat2ana, img2flat, imgadd, esplit",
44 " ",
45 "Keywords: image, ECAT, format conversion",
46 0};
47/*****************************************************************************/
48
49/*****************************************************************************/
50/* Turn on the globbing of the command line, since it is disabled by default in
51 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
52 In Unix&Linux wildcard command line processing is enabled by default. */
53/*
54#undef _CRT_glob
55#define _CRT_glob -1
56*/
57int _dowildcard = -1;
58/*****************************************************************************/
59
60/*****************************************************************************/
64int main(int argc, char **argv)
65{
66 int ai, help=0, version=0, verbose=1;
67 int ret, tokBq=1;
68 char infile[FILENAME_MAX], outfile[FILENAME_MAX], *cptr;
69 FILE *fp1=NULL, *fp2=NULL;
70 ECAT7_mainheader main_header1;
71 ECAT7_imageheader image_header1;
72 ECAT7_2Dscanheader scan2d_header1;
73 ECAT7_scanheader scan3d_header1;
74 ECAT7_MATRIXLIST mlist1;
75 ECAT7_Matval matval1;
76 ECAT63_mainheader main_header2;
77 ECAT63_imageheader image_header2;
78 ECAT63_scanheader scan_header2;
79
80
81 /*
82 * Get arguments
83 */
84 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
85 infile[0]=outfile[0]=(char)0;
86 ecat7InitMatlist(&mlist1);
87 /* Options */
88 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') { /* options */
89 cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(cptr==NULL) continue;
90 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
91 cptr=argv[ai]+1;
92 if(strncasecmp(cptr, "C=", 2)==0) {
93 cptr+=2;
94 if(*cptr=='o' || *cptr=='O') {tokBq=0; continue;}
95 else if(*cptr=='k' || *cptr=='K') {tokBq=1; continue;}
96 }
97 fprintf(stderr, "Error: invalid option '%s'.\n", argv[ai]);
98 return(1);
99 } else break;
100
101 /* Print help or version? */
102 if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
103 if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
104 if(version) {tpcPrintBuild(argv[0], stdout); return(0);}
105
106 /* Process other arguments, starting from the first non-option */
107 for(; ai<argc; ai++) {
108 if(!infile[0]) {
109 strcpy(infile, argv[ai]); continue;
110 } else if(!outfile[0]) {
111 strcpy(outfile, argv[ai]); continue;
112 }
113 fprintf(stderr, "Error: invalid argument '%s'.\n", argv[ai]);
114 return(1);
115 }
116
117 /* Is something missing? */
118 if(!infile[0]) {
119 fprintf(stderr, "Error: missing command-line argument; try %s --help\n",
120 argv[0]);
121 return(1);
122 }
123
124 /* In verbose mode print arguments and options */
125 if(verbose>1) {
126 printf("infile := %s\n", infile);
127 printf("outfile := %s\n", outfile);
128 printf("tokBq := %d\n", tokBq);
129 }
130
131
132 if(verbose==1) printf("reading %s\n", infile);
133
134 /*
135 * Open input ECAT file
136 */
137 if(verbose>1) printf("opening %s\n", infile);
138 if((fp1=fopen(infile, "rb")) == NULL) {
139 fprintf(stderr, "Error: cannot open file %s\n", infile);
140 return(2);
141 }
142
143 /*
144 * Read main header
145 */
146 if(verbose>1) printf("reading mainheader in %s\n", infile);
147 if((ret=ecat7ReadMainheader(fp1, &main_header1))) {
148 fprintf(stderr, "Error (%d): cannot read main header.\n", ret);
149 fclose(fp1); return(3);
150 }
151 if(verbose>5) ecat7PrintMainheader(&main_header1, stdout);
152
153 /* Check file format and type */
154 if(strncmp(main_header1.magic_number, ECAT7V_MAGICNR, 7)!=0) {
155 fprintf(stderr, "Error: %s is not an ECAT 7.x file.\n", infile);
156 fclose(fp1); return(3);
157 }
158 if(main_header1.file_type!=ECAT7_IMAGE16 &&
159 main_header1.file_type!=ECAT7_IMAGE8 &&
160 main_header1.file_type!=ECAT7_VOLUME16 &&
161 main_header1.file_type!=ECAT7_VOLUME8 &&
162 main_header1.file_type!=ECAT7_2DSCAN &&
163 main_header1.file_type!=ECAT7_3DSCAN &&
164 main_header1.file_type!=ECAT7_3DSCANFIT &&
165 main_header1.file_type!=ECAT7_3DSCAN8
166 ) {
167 fprintf(stderr, "Error: currently images and sinograms can be processed.\n");
168 fclose(fp1); return(3);
169 }
170 /* If output filename was not given, construct it from input filename */
171 if(!outfile[0]) {
172 strcpy(outfile, infile); cptr=strrchr(outfile, '.');
173 if(cptr!=NULL) cptr++;
174 *cptr=(char)0;
175 if(main_header1.file_type==ECAT7_2DSCAN ||
176 main_header1.file_type==ECAT7_3DSCAN ||
177 main_header1.file_type==ECAT7_3DSCANFIT ||
178 main_header1.file_type==ECAT7_3DSCAN8)
179 strcat(outfile, "scn"); else strcat(outfile, "img");
180 }
181 if(strcmp(infile, outfile)==0) {
182 fprintf(stderr, "Error: input and output files have the same name!\n");
183 fclose(fp1); return(1);
184 }
185
186 /*
187 * Read matrix list
188 */
189 if(verbose>1) printf("reading matrix list\n");
190 ret=ecat7ReadMatlist(fp1, &mlist1, verbose-2);
191 if(ret) {
192 fprintf(stderr, "Error (%d): cannot read matrix list.\n", ret);
193 fclose(fp1); return(4);
194 }
195 if(mlist1.matrixNr<=0) {
196 fprintf(stderr, "Error: matrix list is empty.\n");
197 fclose(fp1); ecat7EmptyMatlist(&mlist1); return(4);
198 }
199 if(verbose>6) ecat7PrintMatlist(&mlist1);
200
201
202 /*
203 * Create ECAT 6 file and write main header
204 */
205 if(verbose>1) printf("creating mainheader\n");
206 /* Create 6.3 mainheader */
207 ret=ecatCopy7to63mainheader(&main_header1, &main_header2);
208 if(ret) {
209 fprintf(stderr, "Error: matrix filetype %d is not yet supported.\n",
210 main_header1.file_type);
211 fclose(fp1); ecat7EmptyMatlist(&mlist1);
212 return(21);
213 }
214 main_header2.data_type=VAX_I2;
215 /* Open output file */
216 fp2=ecat63Create(outfile, &main_header2);
217 if(fp2==NULL) {
218 fprintf(stderr, "Error: cannot create %s.\n", outfile);
219 fclose(fp1); ecat7EmptyMatlist(&mlist1); return(31);
220 }
221
222
223 /*
224 * Process ECAT matrices one at a time
225 */
226 if(verbose>0 && mlist1.matrixNr>1) {
227 fprintf(stdout, "Converting %d matrices", mlist1.matrixNr);
228 fflush(stdout);
229 }
230 int mi, di, pxlNr=0, planeNr=0, max_frame=0;
231 float *fdata, *fptr;
232 for(mi=0; mi<mlist1.matrixNr; mi++) {
233 if(verbose>2) printf("\nmatrix %d\n", mi+1);
234 /* Get matrix values */
235 ecat7_id_to_val(mlist1.matdir[mi].id, &matval1);
236 /* By the way, get also the highest frame number in the file */
237 if(matval1.frame>max_frame) max_frame=matval1.frame;
238 /* Read subheader and float data */
239 switch(main_header1.file_type) {
240 case ECAT7_IMAGE8:
241 case ECAT7_IMAGE16:
242 ret=ecat7ReadImageMatrix(fp1, mlist1.matdir[mi].strtblk,
243 mlist1.matdir[mi].endblk, &image_header1, &fdata);
244 if(verbose>9) ecat7PrintImageheader(&image_header1, stdout);
245 pxlNr=image_header1.x_dimension*image_header1.y_dimension;
246 planeNr=1;
247 /* If unit is Bq/mL or MBq/mL, then convert it to kBq/mL, if required */
248 if(tokBq && main_header1.calibration_units==1) {
249 if(strcasecmp(main_header1.data_units, "MBq/cc")==0) {
250 main_header2.calibration_units=10;
251 image_header1.scale_factor*=1000.0;
252 for(di=0, fptr=fdata; di<pxlNr; di++, fptr++) *fptr *= 1000.0;
253 } else if(strcasecmp(main_header1.data_units, "Bq/cc")==0) {
254 main_header2.calibration_units=10;
255 image_header1.scale_factor*=0.001;
256 for(di=0, fptr=fdata; di<pxlNr*planeNr; di++, fptr++) *fptr *= 0.001;
257 }
258 }
259 break;
260 case ECAT7_VOLUME8:
261 case ECAT7_VOLUME16:
262 ret=ecat7ReadImageMatrix(fp1, mlist1.matdir[mi].strtblk,
263 mlist1.matdir[mi].endblk, &image_header1, &fdata);
264 if(verbose>9) ecat7PrintImageheader(&image_header1, stdout);
265 pxlNr=image_header1.x_dimension*image_header1.y_dimension;
266 planeNr=image_header1.z_dimension;
267 /* If unit is MBq/mL, then convert pixel values to kBq/mL, if required */
268 if(tokBq && main_header1.calibration_units==1) {
269 if(strcasecmp(main_header1.data_units, "MBq/cc")==0) {
270 main_header2.calibration_units=10;
271 image_header1.scale_factor*=1000.0;
272 for(di=0, fptr=fdata; di<pxlNr; di++, fptr++) *fptr *= 1000.0;
273 } else if(strcasecmp(main_header1.data_units, "Bq/cc")==0) {
274 main_header2.calibration_units=10;
275 image_header1.scale_factor*=0.001;
276 for(di=0, fptr=fdata; di<pxlNr*planeNr; di++, fptr++) *fptr *= 0.001;
277 }
278 }
279 break;
280 case ECAT7_2DSCAN:
281 ret=ecat7Read2DScanMatrix(fp1, mlist1.matdir[mi].strtblk,
282 mlist1.matdir[mi].endblk, &scan2d_header1, &fdata);
283 if(verbose>9) ecat7Print2DScanheader(&scan2d_header1, stdout);
284 pxlNr=scan2d_header1.num_r_elements*scan2d_header1.num_angles;
285 planeNr=scan2d_header1.num_z_elements;
286 break;
287 case ECAT7_3DSCAN:
288 case ECAT7_3DSCANFIT:
289 case ECAT7_3DSCAN8:
290 ret=ecat7ReadScanMatrix(fp1, mlist1.matdir[mi].strtblk,
291 mlist1.matdir[mi].endblk, &scan3d_header1, &fdata);
292 if(verbose>9) ecat7PrintScanheader(&scan3d_header1, stdout);
293 /*if(scan3d_header1.axial_compression>0 &&
294 scan3d_header1.num_z_elements[1]>0) {
295 fprintf(stderr, "\nError: axial compression is not yet supported.\n");
296 ret=-1; break;
297 }*/
298 pxlNr=scan3d_header1.num_r_elements*scan3d_header1.num_angles;
299 int i;
300 for(i=planeNr=0; i<64; i++) planeNr+=scan3d_header1.num_z_elements[i];
301 break;
302 default:
303 fprintf(stderr, "\nError: matrix filetype %d is not yet supported.\n",
304 main_header1.file_type);
305 ret=-1;
306 }
307 if(ret) {
308 if(ret>0) fprintf(stderr, "\nError: cannot read subheader %d.\n", mi+1);
309 fclose(fp1); fclose(fp2); ecat7EmptyMatlist(&mlist1); free(fdata);
310 remove(outfile); return(22);
311 }
312 /* Copy and set subheader */
313 switch(main_header1.file_type) {
314 case ECAT7_IMAGE8:
315 case ECAT7_IMAGE16:
316 ret=ecatCopy7to63imageheader(&image_header1, &image_header2);
317 image_header2.data_type=VAX_I2;
318 image_header2.quant_units=main_header2.calibration_units;
319 break;
320 case ECAT7_VOLUME8:
321 case ECAT7_VOLUME16:
322 ret=ecatCopy7to63imageheader(&image_header1, &image_header2);
323 image_header2.data_type=VAX_I2;
324 image_header2.quant_units=main_header2.calibration_units;
325 break;
326 case ECAT7_2DSCAN:
327 ret=ecatCopy7_2D_to63scanheader(&scan2d_header1, &scan_header2);
328 scan_header2.data_type=VAX_I2;
329 if(scan_header2.sample_distance<=0.0)
330 scan_header2.sample_distance=main_header1.bin_size;
331 scan_header2.isotope_halflife=main_header1.isotope_halflife;
332 break;
333 case ECAT7_3DSCAN:
334 case ECAT7_3DSCANFIT:
335 case ECAT7_3DSCAN8:
336 ret=ecatCopy7to63scanheader(&scan3d_header1, &scan_header2);
337 scan_header2.data_type=VAX_I2;
338 if(scan_header2.sample_distance<=0.0)
339 scan_header2.sample_distance=main_header1.bin_size;
340 scan_header2.isotope_halflife=main_header1.isotope_halflife;
341 break;
342 default: ret=-1;
343 }
344 if(ret) {
345 fprintf(stderr, "\nError: cannot copy subheader.\n");
346 fclose(fp1); fclose(fp2); ecat7EmptyMatlist(&mlist1); free(fdata);
347 remove(outfile); return(23);
348 }
349 /* Write each plane */
350 for(int i=0; i<planeNr; i++) {
351 /* Create ECAT 6.3 matrix id (i.e. matnum) */
352 int matnum;
353 matnum=mat_numcod(matval1.frame, matval1.plane+i, matval1.gate,
354 matval1.data, matval1.bed);
355 /* Write subheader and plane data */
356 fptr=fdata+(i*pxlNr);
357 switch(main_header1.file_type) {
358 case ECAT7_IMAGE8:
359 case ECAT7_IMAGE16:
360 case ECAT7_VOLUME8:
361 case ECAT7_VOLUME16:
362 ret=ecat63WriteImageMatrix(fp2, matnum, &image_header2, fptr);
363 break;
364 case ECAT7_2DSCAN:
365 case ECAT7_3DSCAN:
366 case ECAT7_3DSCANFIT:
367 case ECAT7_3DSCAN8:
368 ret=ecat63WriteScanMatrix(fp2, matnum, &scan_header2, fptr);
369 break;
370 default: ret=-1;
371 }
372 if(ret) {
373 fprintf(stderr, "\nError in writing matrix: %s\n", ecat63errmsg);
374 fclose(fp1); fclose(fp2); ecat7EmptyMatlist(&mlist1); free(fdata);
375 remove(outfile); return(24);
376 }
377 } /* next plane */
378 free(fdata);
379 /* Prepare for the next matrix */
380 if(mlist1.matrixNr>1 && verbose>=0) {
381 fprintf(stdout, "."); fflush(stdout);}
382 } /* next matrix */
383 if(mlist1.matrixNr>1 && verbose>=0) {
384 fprintf(stdout, "done\n"); fflush(stdout);}
385
386 /*
387 * Rewrite the main header contents
388 */
389 if(verbose>1) printf("rewriting main header in %s\n", outfile);
390 /* With correct plane and frame nr */
391 main_header2.num_planes=planeNr;
392 if(main_header2.num_frames!=max_frame) {
393 fprintf(stderr, "Warning: main header frame nr was changed %d -> %d.\n",
394 main_header2.num_frames, max_frame);
395 main_header2.num_frames=max_frame;
396 }
397 /* write */
398 ret=ecat63WriteMainheader(fp2, &main_header2);
399 if(ret) {
400 fprintf(stderr, "Error (%d): cannot write main header.\n", ret);
401 fclose(fp1); fclose(fp2); ecat7EmptyMatlist(&mlist1);
402 remove(outfile); return(25);
403 }
404
405
406 /*
407 * Close files
408 */
409 fclose(fp1); fclose(fp2);
410 if(verbose>=0) fprintf(stdout, "%s written.\n", outfile);
411
412 /*
413 * Free memory
414 */
415 ecat7EmptyMatlist(&mlist1);
416
417 return(0);
418}
419/*****************************************************************************/
420
421/*****************************************************************************/
char ecat63errmsg[128]
Definition ecat63h.c:7
int mat_numcod(int frame, int plane, int gate, int data, int bed)
Definition ecat63ml.c:242
int ecat63WriteScanMatrix(FILE *fp, int matnum, ECAT63_scanheader *h, float *fdata)
Definition ecat63w.c:781
int ecat63WriteImageMatrix(FILE *fp, int matnum, ECAT63_imageheader *h, float *fdata)
Definition ecat63w.c:697
FILE * ecat63Create(const char *fname, ECAT63_mainheader *h)
Definition ecat63w.c:365
int ecat63WriteMainheader(FILE *fp, ECAT63_mainheader *h)
Definition ecat63w.c:24
void ecat7InitMatlist(ECAT7_MATRIXLIST *mlist)
Definition ecat7ml.c:15
void ecat7_id_to_val(int matrix_id, ECAT7_Matval *matval)
Definition ecat7ml.c:262
int ecat7ReadMatlist(FILE *fp, ECAT7_MATRIXLIST *ml, int verbose)
Definition ecat7ml.c:41
void ecat7EmptyMatlist(ECAT7_MATRIXLIST *mlist)
Definition ecat7ml.c:26
void ecat7PrintMatlist(ECAT7_MATRIXLIST *ml)
Definition ecat7ml.c:112
void ecat7PrintImageheader(ECAT7_imageheader *h, FILE *fp)
Definition ecat7p.c:102
void ecat7Print2DScanheader(ECAT7_2Dscanheader *h, FILE *fp)
Definition ecat7p.c:364
void ecat7PrintMainheader(ECAT7_mainheader *h, FILE *fp)
Definition ecat7p.c:16
void ecat7PrintScanheader(ECAT7_scanheader *h, FILE *fp)
Definition ecat7p.c:181
int ecat7Read2DScanMatrix(FILE *fp, int first_block, int last_block, ECAT7_2Dscanheader *h, float **fdata)
Definition ecat7r.c:959
int ecat7ReadMainheader(FILE *fp, ECAT7_mainheader *h)
Definition ecat7r.c:15
int ecat7ReadImageMatrix(FILE *fp, int first_block, int last_block, ECAT7_imageheader *h, float **fdata)
Definition ecat7r.c:858
int ecat7ReadScanMatrix(FILE *fp, int first_block, int last_block, ECAT7_scanheader *h, float **fdata)
Definition ecat7r.c:1055
int ecatCopy7_2D_to63scanheader(ECAT7_2Dscanheader *h1, ECAT63_scanheader *h2)
Definition ehdrconv.c:492
int ecatCopy7to63scanheader(ECAT7_scanheader *h1, ECAT63_scanheader *h2)
Definition ehdrconv.c:457
int ecatCopy7to63imageheader(ECAT7_imageheader *h1, ECAT63_imageheader *h2)
Definition ehdrconv.c:404
int ecatCopy7to63mainheader(ECAT7_mainheader *h1, ECAT63_mainheader *h2)
Definition ehdrconv.c:279
Header file for ehdrconv.c.
Header file for libtpcimgio.
#define ECAT7_VOLUME8
#define ECAT7_3DSCAN
#define ECAT7_3DSCAN8
#define ECAT7_IMAGE16
#define ECAT7_3DSCANFIT
#define ECAT7_VOLUME16
#define ECAT7_IMAGE8
#define VAX_I2
#define ECAT7_2DSCAN
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
short int calibration_units
short int num_z_elements
short int num_r_elements
ECAT7_MatDir * matdir
short int y_dimension
short int z_dimension
short int x_dimension
short int file_type
char data_units[32]
char magic_number[14]
short int calibration_units
short int num_r_elements
short int num_angles
short int num_z_elements[64]