TPCCLIB
Loading...
Searching...
No Matches
e63to7.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 image or sinogram in ECAT 6.3 format to ECAT 7 format.",
25 " ",
26 "Usage: @P [Options] ECAT6_file [ECAT7_file]",
27 " ",
28 "Options:",
29 " -C=<o|B|M>",
30 " Image calibration unit is changed from kBq/mL to Bq/mL (B, default)",
31 " or MBq/mL (M), or the original unit is not changed (o).",
32 " -stdoptions", // List standard options like --help, -v, etc
33 " ",
34 "Examples:",
35 "1. Convert one image, let program give name to the ECAT7 file",
36 " e63to7 is02345dy1.img",
37 "2. Convert one image, give a specific name to the ECAT7 file",
38 " e63to7 is02345dy1.img is2345.v",
39 "3. Convert all images in current working directory in Windows command shell",
40 " for %g in (*.img) do e63to7 %g",
41 " ",
42 "See also: e7to63, lmlist, ecat2ana, img2flat, imgadd, esplit",
43 " ",
44 "Keywords: image, ECAT, format conversion",
45 0};
46/*****************************************************************************/
47
48/*****************************************************************************/
49/* Turn on the globbing of the command line, since it is disabled by default in
50 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
51 In Unix&Linux wildcard command line processing is enabled by default. */
52/*
53#undef _CRT_glob
54#define _CRT_glob -1
55*/
56int _dowildcard = -1;
57/*****************************************************************************/
58
59/*****************************************************************************/
63int main(int argc, char **argv)
64{
65 int ai, help=0, version=0, verbose=1;
66 int ret, toMBq=0, toBq=1;
67 char infile[FILENAME_MAX], outfile[FILENAME_MAX], *cptr;
68 FILE *fp1=NULL, *fp2=NULL;
69 ECAT63_mainheader main_header1;
70 ECAT63_imageheader image_header1;
71 ECAT63_scanheader scan_header1;
72 static MATRIXLIST mlist1;
73 Matval matval1, matval1b;
74 ECAT7_mainheader main_header2;
75 ECAT7_imageheader image_header2;
76 ECAT7_scanheader scan_header2;
77
78
79 /*
80 * Get arguments
81 */
82 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
83 infile[0]=outfile[0]=(char)0;
84 /* Options */
85 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') { /* options */
86 cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(cptr==NULL) continue;
87 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
88 cptr=argv[ai]+1;
89 if(strncasecmp(cptr, "C=", 2)==0) {
90 cptr+=2;
91 if(*cptr=='o' || *cptr=='O') {toMBq=toBq=0; continue;}
92 else if(*cptr=='m' || *cptr=='M') {toMBq=1; toBq=0; continue;}
93 else if(*cptr=='b' || *cptr=='B') {toBq=1; toMBq=0; continue;}
94 }
95 fprintf(stderr, "Error: invalid option '%s'.\n", argv[ai]);
96 return(1);
97 } else break;
98
99 /* Print help or version? */
100 if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
101 if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
102 if(version) {tpcPrintBuild(argv[0], stdout); return(0);}
103
104 /* Process other arguments, starting from the first non-option */
105 for(; ai<argc; ai++) {
106 if(!infile[0]) {
107 strcpy(infile, argv[ai]); continue;
108 } else if(!outfile[0]) {
109 strcpy(outfile, argv[ai]); continue;
110 }
111 fprintf(stderr, "Error: invalid argument '%s'.\n", argv[ai]);
112 return(1);
113 }
114
115 /* Is something missing? */
116 if(!infile[0]) {
117 fprintf(stderr, "Error: missing command-line argument; try %s --help\n",
118 argv[0]);
119 return(1);
120 }
121
122 /* In verbose mode print arguments and options */
123 if(verbose>1) {
124 printf("infile := %s\n", infile);
125 printf("outfile := %s\n", outfile);
126 printf("toMBq := %d\n", toMBq);
127 printf("toBq := %d\n", toBq);
128 }
129
130
131 if(verbose==1) printf("reading %s\n", infile);
132
133 /*
134 * Open input ECAT file
135 */
136 if(verbose>1) printf("opening %s\n", infile);
137 if((fp1=fopen(infile, "rb")) == NULL) {
138 fprintf(stderr, "Error: cannot open file %s\n", infile);
139 return(2);
140 }
141
142 /*
143 * Read main header
144 */
145 if(verbose>1) printf("reading main header\n");
146 if((ret=ecat63ReadMainheader(fp1, &main_header1))) {
147 fprintf(stderr, "Error (%d): cannot read main header.\n", ret);
148 fclose(fp1); return(3);
149 }
150 if(verbose>5) ecat63PrintMainheader(&main_header1, stdout);
151
152 /* Check the file_type */
153 if(main_header1.file_type!=IMAGE_DATA && main_header1.file_type!=RAW_DATA) {
154 fprintf(stderr,
155 "Error: currently only image and scan files can be processed.\n");
156 fclose(fp1); return(3);
157 }
158
159 /* If output filename was not given, construct it from input filename */
160 if(!outfile[0]) {
161 strcpy(outfile, infile); cptr=strrchr(outfile, '.');
162 if(cptr!=NULL) cptr++;
163 *cptr=(char)0;
164 if(main_header1.file_type==RAW_DATA)
165 strcat(outfile, "s"); else strcat(outfile, "v");
166 }
167 if(strcasecmp(infile, outfile)==0) {
168 fprintf(stderr, "Error: input and output files have the same name!\n");
169 fclose(fp1); return(1);
170 }
171
172 /*
173 * Read matrix list
174 */
175 if(verbose>1) printf("reading matrix list\n");
176 ecat63InitMatlist(&mlist1);
177 ret=ecat63ReadMatlist(fp1, &mlist1, verbose-2);
178 if(ret) {
179 fprintf(stderr, "Error (%d): cannot read matrix list.\n", ret);
180 fclose(fp1); return(4);
181 }
182 if(mlist1.matrixNr<=0) {
183 fprintf(stderr, "Error: matrix list is empty.\n");
184 fclose(fp1); return(4);
185 }
186 if(ecat63CheckMatlist(&mlist1)) {
187 fprintf(stderr, "Error: check the matrix list.\n");
188 fclose(fp1); ecat63EmptyMatlist(&mlist1); return(4);
189 }
190 /* Trim extra frames */
191 if(main_header1.num_frames>0) {
192 int delNr;
193 delNr=ecat63DeleteLateFrames(&mlist1, main_header1.num_frames);
194 if(delNr>0 && verbose>=0)
195 printf(" %d entries in matrix list will not be used.\n", delNr);
196 }
197 if(verbose>6) ecat63PrintMatlist(&mlist1);
198 /* Check that there are no missing matrices */
199 {
200 int planeNr, frameNr;
201 ret=ecat63GetPlaneAndFrameNr(&mlist1, &main_header1, &planeNr, &frameNr);
202 if(ret==STATUS_MISSINGMATRIX) {
203 fprintf(stderr, "Error: missing matrix/matrices.\n");
204 fclose(fp1); ecat63EmptyMatlist(&mlist1); return(4);
205 }
206 }
207
208
209
210 /*
211 * Create ECAT 7 file and write main header
212 */
213 /* Initiate headers */
214 if(verbose>1) printf("creating mainheader\n");
215 /* Create ECAT 7 mainheader */
216 ret=ecatCopy63to7mainheader(&main_header1, &main_header2);
217 if(ret) {
218 fprintf(stderr, "Error: matrix filetype %d is not supported.\n",
219 main_header1.file_type);
220 fclose(fp1); ecat63EmptyMatlist(&mlist1);
221 return(21);
222 }
223 /* Open output file */
224 if(verbose>1) printf("creating file %s\n", outfile);
225 fp2=ecat7Create(outfile, &main_header2);
226 if(fp2==NULL) {
227 fprintf(stderr, "Error: cannot create %s.\n", outfile);
228 fclose(fp1); ecat63EmptyMatlist(&mlist1); return(31);
229 }
230
231
232 /*
233 * Process ECAT matrices one frame at a time
234 */
235 if(verbose>0 && mlist1.matrixNr>1)
236 printf("processing %d matrices\n", mlist1.matrixNr);
237 /* Sort matrix list by frame number, and secondarily by plane number */
239 if(verbose>7) {
240 printf("matrixlist after sort:\n"); ecat63PrintMatlist(&mlist1);
241 }
242 int mi=0, mj=0, planeNr, pxlNr=0, matrixId;
243 float *fdata=NULL, *voldata=NULL, *volptr, *fptr, f;
244 while(mi<mlist1.matrixNr) {
245 if(mlist1.matdir[mi].matstat!=1) {mj++; mi=mj; continue;}
246 /* Determine the number of planes in this frame */
247 planeNr=1; mat_numdoc(mlist1.matdir[mj].matnum, &matval1);
248 for(mj=mi+1; mj<mlist1.matrixNr; mj++) if(mlist1.matdir[mj].matstat==1) {
249 mat_numdoc(mlist1.matdir[mj].matnum, &matval1b);
250 if(matval1b.frame==matval1.frame) planeNr++; else break;
251 }
252 if(verbose>2) printf("Frame %d: planeNr=%d\n", matval1.frame, planeNr);
253 /* Read header and data matrix for each plane */
254 for(int pi=0; pi<planeNr; pi++) {
255 if(main_header1.file_type==IMAGE_DATA) {
256 ret=ecat63ReadImageMatrix(fp1, mlist1.matdir[mi+pi].strtblk,
257 mlist1.matdir[mi+pi].endblk, &image_header1, &fdata);
258 pxlNr=image_header1.dimension_1*image_header1.dimension_2;
259 /* If calibration factor in image subheader is the same as in */
260 /* main header, then divide it out from the pixel values */
261 if(image_header1.ecat_calibration_fctr!=0.0 &&
262 image_header1.ecat_calibration_fctr!=1.0 &&
263 fabs(main_header1.calibration_factor/
264 image_header1.ecat_calibration_fctr-1.0)<0.0001)
265 {
266 int di;
267 f=1.0/image_header1.ecat_calibration_fctr;
268 for(di=0, fptr=fdata; di<pxlNr; di++, fptr++) *fptr *= f;
269 image_header1.quant_scale*=f;
270 }
271 /* If unit is kBq/mL, then convert it to MBq/mL, if required */
272 if(toMBq && (main_header1.calibration_units==10 ||
273 image_header1.quant_units==10))
274 {
275 main_header1.calibration_units=1;
276 image_header1.quant_units=1;
277 image_header1.quant_scale*=0.001;
278 int di;
279 for(di=0, fptr=fdata; di<pxlNr; di++, fptr++) *fptr *= 0.001;
280 strcpy(main_header2.data_units, "MBq/cc");
281 }
282 /* If unit is kBq/mL, then convert it to Bq/mL, if required */
283 if(toBq && (main_header1.calibration_units==10 ||
284 image_header1.quant_units==10))
285 {
286 main_header1.calibration_units=9;
287 image_header1.quant_units=9;
288 image_header1.quant_scale*=1000.;
289 int di;
290 for(di=0, fptr=fdata; di<pxlNr; di++, fptr++) *fptr *= 1000.;
291 strcpy(main_header2.data_units, "Bq/cc");
292 }
293 } else if(main_header1.file_type==RAW_DATA) {
294 ret=ecat63ReadScanMatrix(fp1, mlist1.matdir[mi+pi].strtblk,
295 mlist1.matdir[mi+pi].endblk, &scan_header1, &fdata);
296 pxlNr=scan_header1.dimension_1*scan_header1.dimension_2;
297 }
298 if(ret) {
299 fprintf(stderr, "Error in reading matrix: %s\n", ecat63errmsg);
300 free(fdata); fclose(fp1); fclose(fp2); ecat63EmptyMatlist(&mlist1);
301 remove(outfile); return(13);
302 }
303 /* Allocate memory for volume */
304 if(pi==0) {
305 voldata=(float*)malloc(pxlNr*planeNr*sizeof(float));
306 if(voldata==NULL) {
307 fprintf(stderr, "Error: out of memory.\n");
308 free(fdata); fclose(fp1); fclose(fp2); ecat63EmptyMatlist(&mlist1);
309 remove(outfile); return(15);
310 }
311 }
312 /* Copy plane pixel values to volume */
313 memcpy(voldata+(pi*pxlNr), fdata, pxlNr*4);
314 free(fdata);
315 } /* next plane on this frame */
316 /* Set output subheader */
317 if(main_header1.file_type==IMAGE_DATA) {
318 ret=ecatCopy63to7imageheader(&image_header1, &image_header2);
319 image_header2.z_dimension=planeNr;
320 image_header2.data_type=ECAT7_SUNI2;
321 } else if(main_header1.file_type==RAW_DATA) {
322 ret=ecatCopy63to7scanheader(&scan_header1, &scan_header2);
323 if(planeNr==239) {
324 scan_header2.num_z_elements[0]=63;
325 scan_header2.num_z_elements[1]=106;
326 scan_header2.num_z_elements[2]=70;
327 } else {
328 scan_header2.num_z_elements[0]=planeNr;
329 }
330 scan_header2.data_type=ECAT7_SUNI2;
331 } else {ret=-1; }
332 if(ret) {
333 fprintf(stderr, "Error: cannot convert subheader.\n");
334 fclose(fp1); fclose(fp2); ecat63EmptyMatlist(&mlist1);
335 free(voldata); remove(outfile); return(24);
336 }
337 /* Create new matrix id (i.e. matnum) */
338 matrixId=ecat7_val_to_id(matval1.frame, 1, matval1.gate,
339 matval1.data, matval1.bed);
340 /* Write subheader and volume data */
341 volptr=voldata;
342 if(main_header1.file_type==IMAGE_DATA) {
343 ret=ecat7WriteImageMatrix(fp2, matrixId, &image_header2, volptr);
344 } else {
345 ret=ecat7WriteScanMatrix(fp2, matrixId, &scan_header2, volptr);
346 }
347 free(voldata);
348 if(ret) {
349 fprintf(stderr, "Error in writing matrix: %s\n", ecat7errmsg);
350 fclose(fp1); fclose(fp2); ecat63EmptyMatlist(&mlist1);
351 remove(outfile); return(23);
352 }
353 if(verbose>=0) fprintf(stdout, "written %d planes on frame %d\n",
354 planeNr, matval1.frame);
355 /* Prepare for the next frame */
356 mi=mj;
357 } /* next frame */
358
359
360 /*
361 * Put more information into main header, and rewrite it
362 */
363 if(verbose>1) printf("adding information into main headerin %s\n", outfile);
364 ret=0;
365 /* sample distance */
366 if(main_header1.file_type==RAW_DATA) {
367 main_header2.bin_size=scan_header1.sample_distance;
368 }
369 /* original filename */
370 if(strlen(main_header2.original_file_name)<1) {
371 cptr=strrchr(infile, '/'); if(cptr==NULL) cptr=strrchr(infile, '\\');
372 if(cptr==NULL) cptr=infile; else cptr++;
373 strncpy(main_header2.original_file_name, cptr, 32);
374 main_header2.original_file_name[31]=(char)0;
375 }
376 /* write */
377 ret=ecat7WriteMainheader(fp2, &main_header2);
378 if(ret) {
379 fprintf(stderr, "Error in writing main header (%d).\n", ret);
380 fclose(fp1); fclose(fp2); ecat63EmptyMatlist(&mlist1);
381 remove(outfile); return(36);
382 }
383
384 /*
385 * Close files
386 */
387 fclose(fp1); fclose(fp2);
388 if(verbose>=0) fprintf(stdout, "%s written.\n", outfile);
389
390 /*
391 * Free memory
392 */
393 ecat63EmptyMatlist(&mlist1);
394
395 return(0);
396}
397/*****************************************************************************/
398
399/*****************************************************************************/
char ecat63errmsg[128]
Definition ecat63h.c:7
int ecat63ReadMatlist(FILE *fp, MATRIXLIST *ml, int verbose)
Definition ecat63ml.c:46
int ecat63GetPlaneAndFrameNr(MATRIXLIST *mlist, ECAT63_mainheader *h, int *plane_nr, int *frame_nr)
Definition ecat63ml.c:400
void ecat63InitMatlist(MATRIXLIST *mlist)
Definition ecat63ml.c:20
void ecat63EmptyMatlist(MATRIXLIST *mlist)
Definition ecat63ml.c:31
int ecat63DeleteLateFrames(MATRIXLIST *ml, int frame_nr)
Definition ecat63ml.c:342
void ecat63PrintMatlist(MATRIXLIST *ml)
Definition ecat63ml.c:130
int ecat63CheckMatlist(MATRIXLIST *ml)
Definition ecat63ml.c:324
void mat_numdoc(int matnum, Matval *matval)
Definition ecat63ml.c:254
void ecat63SortMatlistByFrame(MATRIXLIST *ml)
Definition ecat63ml.c:297
void ecat63PrintMainheader(ECAT63_mainheader *h, FILE *fp)
Definition ecat63p.c:16
int ecat63ReadImageMatrix(FILE *fp, int first_block, int last_block, ECAT63_imageheader *h, float **fdata)
Definition ecat63r.c:627
int ecat63ReadScanMatrix(FILE *fp, int first_block, int last_block, ECAT63_scanheader *h, float **fdata)
Definition ecat63r.c:731
int ecat63ReadMainheader(FILE *fp, ECAT63_mainheader *h)
Definition ecat63r.c:25
char ecat7errmsg[128]
Definition ecat7h.c:7
int ecat7_val_to_id(int frame, int plane, int gate, int data, int bed)
Definition ecat7ml.c:245
int ecat7WriteImageMatrix(FILE *fp, int matrix_id, ECAT7_imageheader *h, float *fdata)
Definition ecat7w.c:635
int ecat7WriteScanMatrix(FILE *fp, int matrix_id, ECAT7_scanheader *h, float *fdata)
Definition ecat7w.c:802
FILE * ecat7Create(const char *fname, ECAT7_mainheader *h)
Definition ecat7w.c:567
int ecat7WriteMainheader(FILE *fp, ECAT7_mainheader *h)
Definition ecat7w.c:16
int ecatCopy63to7imageheader(ECAT63_imageheader *h1, ECAT7_imageheader *h2)
Definition ehdrconv.c:163
int ecatCopy63to7mainheader(ECAT63_mainheader *h1, ECAT7_mainheader *h2)
Definition ehdrconv.c:25
int ecatCopy63to7scanheader(ECAT63_scanheader *h1, ECAT7_scanheader *h2)
Definition ehdrconv.c:211
Header file for ehdrconv.c.
Header file for libtpcimgio.
#define RAW_DATA
#define IMAGE_DATA
#define ECAT7_SUNI2
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 dimension_2
short int dimension_1
short int z_dimension
short int data_type
char data_units[32]
char original_file_name[32]
short int data_type
short int num_z_elements[64]
MatDir * matdir
int matstat
int endblk
int matnum
int strtblk
int frame