TPCCLIB
Loading...
Searching...
No Matches
imgdecay.c
Go to the documentation of this file.
1
9/*****************************************************************************/
10#include "tpcclibConfig.h"
11/*****************************************************************************/
12#include <stdio.h>
13#include <stdlib.h>
14#include <math.h>
15#include <string.h>
16#include <unistd.h>
17#include <time.h>
18/*****************************************************************************/
19#include "libtpcmisc.h"
20#include "libtpcimgio.h"
21/*****************************************************************************/
22
23/*****************************************************************************/
24static char *info[] = {
25 "Report and change the correction for physical decay in PET image data.",
26 " ",
27 "Usage: @P [Options] imagefile",
28 " ",
29 "Options:",
30 " -dd",
31 " Correct PET data for physical decay.",
32 " -rd",
33 " Remove decay correction.",
34 " Make sure that PET is decay corrected before this operation.",
35 " -i=<Isotope>",
36 " Changes or specifies the isotope.",
37 " Any previous decay correction must be removed before this operation.",
38 " Note that image may need to be recalibrated if isotope is changed;",
39 " at least branching fraction needs to be corrected.",
40/*
41 " -t<Time difference (sec)>",
42 " Correct frame times from scan start to the injection time.",
43 " Decay is assumed to be initially corrected to the start of scanning.",
44*/
45 " -dc",
46 " Add decay correction factors to the image data.",
47 " This option does not add decay correction to the pixel values.",
48 " This may not be effective in some image formats.",
49 " -rc",
50 " Remove decay correction factors from the image data.",
51 " This option does not remove decay correction from the pixel values.",
52 " This may not be effective in some image formats.",
53 " -stdoptions", // List standard options like --help, -v, etc
54 " ",
55 "If no option is specified, program reports the current state of decay",
56 "correction, but makes no changes to the data file.",
57 " ",
58 "See also: eframe, ecattime, egetstrt, esetstrt, imgunit, lmhdr, lshdr",
59 " ",
60 "Keywords: ECAT, image, physical decay, modelling, simulation",
61 0};
62/*****************************************************************************/
63
64/*****************************************************************************/
65/* Turn on the globbing of the command line, since it is disabled by default in
66 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
67 In Unix&Linux wildcard command line processing is enabled by default. */
68/*
69#undef _CRT_glob
70#define _CRT_glob -1
71*/
72int _dowildcard = -1;
73/*****************************************************************************/
74
75/*****************************************************************************/
79int main(int argc, char **argv)
80{
81 int ai, help=0, version=0, verbose=1;
82 int fi, ret;
83 char petfile[FILENAME_MAX], *cptr;
84 IMG img;
85 int info_on_image=1; // print info (1) or not (0)
86 int decaycor=0; // 0= do nothing
87 // 1= Add decay correction factors to the image data
88 // 2= Correct PET data for physical decay
89 // -1= Remove decay correction factors from the image
90 // -2= Remove decay correction
91 double halflife=0.0; // isotope halflife in sec
92
93
94 /*
95 * Get arguments
96 */
97 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
98 petfile[0]=(char)0;
99 imgInit(&img);
100 /* Options */
101 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') { /* options */
102 cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(cptr==NULL) continue;
103 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
104 cptr=argv[ai]+1;
105 if(strncasecmp(cptr, "I=", 2)==0) {
106 info_on_image=0; // Info is not reported if any options are specified
107 cptr+=2; cptr=hlCorrectIsotopeCode(cptr);
108 if(cptr!=NULL) {
109 halflife=60.0*hlFromIsotope(cptr);
110 if(halflife>0.0) continue;
111 }
112 fprintf(stderr, "Error: invalid isotope with option -i\n"); return(1);
113 } else if(strncasecmp(cptr, "D", 1)==0) {
114 info_on_image=0; // Info is not reported if any options are specified
115 if(decaycor!=0) {
116 fprintf(stderr, "Error: invalid combination of options.\n"); return(1);}
117 cptr++;
118 if(strncasecmp(cptr, "D", 1)==0) {decaycor=2; continue;}
119 if(strncasecmp(cptr, "C", 1)==0) {decaycor=1; continue;}
120 } else if(strncasecmp(cptr, "R", 1)==0) {
121 info_on_image=0; // Info is not reported if any options are specified
122 if(decaycor!=0) {
123 fprintf(stderr, "Error: invalid combination of options.\n"); return(1);}
124 cptr++;
125 if(strncasecmp(cptr, "D", 1)==0) {decaycor=-2; continue;}
126 if(strncasecmp(cptr, "C", 1)==0) {decaycor=-1; continue;}
127 }
128 fprintf(stderr, "Error: invalid option '%s'.\n", argv[ai]);
129 return(1);
130 } else break;
131
132 /* Print help or version? */
133 if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
134 if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
135 if(version) {tpcPrintBuild(argv[0], stdout); return(0);}
136
137 /* Process other arguments, starting from the first non-option */
138 for(; ai<argc; ai++) {
139 /* Image/sinogram file */
140 if(!petfile[0]) {strcpy(petfile, argv[ai]); continue;}
141 /* We should not be here */
142 fprintf(stderr, "Error: invalid argument '%s'.\n", argv[ai]);
143 return(1);
144 } /* next argument */
145
146 /* Is something missing? */
147 if(!petfile[0]) {
148 fprintf(stderr, "Error: missing command-line argument; try %s --help\n",
149 argv[0]);
150 return(1);
151 }
152
153 /* In verbose mode print arguments and options */
154 if(verbose>1) {
155 printf("petfile := %s\n", petfile);
156 printf("info_on_image: = %d\n", info_on_image);
157 printf("decaycor := %d\n", decaycor);
158 printf("halflife := %g\n", halflife);
159 }
160
161
162 /*
163 * Read image/sinogram data
164 */
165 if(verbose>=0) {fprintf(stdout, "reading %s\n", petfile); fflush(stdout);}
166 ret=imgRead(petfile, &img);
167 if(ret) {
168 fprintf(stderr, "Error in reading %s: %s\n", petfile, img.statmsg);
169 if(verbose>0) imgInfo(&img);
170 return(2);
171 }
172 if(verbose>20) imgInfo(&img);
173
174
175 /*
176 * Check if image contains decay correction factors
177 */
179 for(fi=0; fi<img.dimt; fi++)
180 if(img.decayCorrFactor[fi]>1.0) {
182
183
184 /*
185 * Print information on the image/sinogram
186 * Some information is printed even when not required
187 */
188 /* Isotope */
189 if(verbose>=0 || info_on_image==1)
190 fprintf(stdout, "isotope: %s\n", imgIsotope(&img) );
191 /* Current decay correction factors */
192 if(info_on_image==1 || verbose>0) {
194 fprintf(stdout, "Decay correction: unknown\n");
195 } else if(img.decayCorrection==IMG_DC_CORRECTED) {
196 fprintf(stdout, "Decay correction: corrected\n");
197 } else if(img.decayCorrection==IMG_DC_NONCORRECTED) {
198 fprintf(stdout, "Decay correction: not corrected\n");
199 }
201 fprintf(stdout, "decay correction factors:\n");
202 fprintf(stdout, "Frame start length Decay factor\n");
203 for(fi=0; fi<img.dimt; fi++) {
204 if(verbose>1) fprintf(stdout, "frame%d: %g %g %g\n", fi+1, img.start[fi],
205 img.end[fi]-img.start[fi], img.decayCorrFactor[fi] );
206 else fprintf(stdout, "%4d %6.0f %6.0f %g\n", fi+1, img.start[fi],
207 img.end[fi]-img.start[fi], img.decayCorrFactor[fi] );
208 }
209 }
210 } else {
212 if(img.type==IMG_TYPE_RAW)
213 fprintf(stdout, "Note: status of the decay correction is not known.\n");
214 else
215 fprintf(stdout, "Note: decay correction factors not available\n");
216 }
217 }
218/*
219 if(img.decayCorrection==IMG_DC_UNKNOWN) {
220 if(img.type==IMG_TYPE_RAW)
221 fprintf(stdout, "Note: status of the decay correction is not known.\n");
222 else
223 fprintf(stdout, "Note: decay correction factors not available\n");
224 } else if(info_on_image==1) {
225 fprintf(stdout, "decay correction factors:\n");
226 fprintf(stdout, "Frame start length Decay factor\n");
227 for(fi=0; fi<img.dimt; fi++) {
228 if(verbose>1) fprintf(stdout, "frame%d: %g %g %g\n", fi+1, img.start[fi],
229 img.end[fi]-img.start[fi], img.decayCorrFactor[fi] );
230 else fprintf(stdout, "%4d %6.0f %6.0f %g\n", fi+1, img.start[fi],
231 img.end[fi]-img.start[fi], img.decayCorrFactor[fi] );
232 }
233 }
234*/
235
236 /* When ready, exit */
237 if(info_on_image) {
238 if(verbose>1) printf("end of info.\n");
239 imgEmpty(&img);
240 return(0);
241 }
242
243
244 /*
245 * If required, set the isotope
246 */
247 if(halflife>0.0) {
248 if(verbose>1) printf("Request to set the halflife to %g\n", halflife);
249 if(img.isotopeHalflife==halflife) { /* no need for change */
250 if(verbose>1) printf("same isotope was previously set.\n");
251 /* if no further changes were required, then quit */
252 if(decaycor==0) {
253 if(verbose>=0) printf("Note: same isotope was previously set.\n");
254 imgEmpty(&img); return(0);
255 }
256 } else if(img.type==IMG_TYPE_RAW) { /* change if file is sinogram */
257 img.isotopeHalflife=halflife;
258 if(verbose>=0) printf("new sinogram isotope: %s\n", imgIsotope(&img) );
259 } else if(img.isotopeHalflife<=0.0) { /* change if not previously set */
260 img.isotopeHalflife=halflife;
261 if(verbose>=0) printf("new image isotope: %s\n", imgIsotope(&img) );
262 } else if(img.decayCorrection==IMG_DC_CORRECTED) {
263 /* previous decay correction should be removed first */
264 fprintf(stderr,
265 "Error: remove previous decay correction before changing isotope.\n");
266 imgEmpty(&img);
267 return(3);
268 } else { /* change the isotope, but give a warning */
269 img.isotopeHalflife=halflife;
270 fprintf(stderr, "Warning: possible decay correction should have been");
271 fprintf(stderr, " removed before isotope was changed to %s\n",
272 imgIsotope(&img) );
273 }
274 }
275
276
277 /*
278 * Check the frame information
279 */
280 ret=0; for(fi=0; fi<img.dimt; fi++) if(img.end[fi]<=0.0) ret=1;
281 if(ret) fprintf(stderr, "Warning: check the frame times.\n");
282
283
284 /*
285 * Check the halflife
286 */
287 if(img.isotopeHalflife<=0.0) {
288 fprintf(stderr, "Error: set isotope with option -i\n");
289 imgEmpty(&img);
290 return(5);
291 }
292
293
294 /*
295 * Decay correction or
296 * removal of decay correction
297 */
298 ret=0;
299 if(decaycor==2) {
300 if(verbose>=0) {
301 fprintf(stdout, "decay correction of PET data...\n"); fflush(stdout);}
302 /* Error, if already decay corrected */
304 fprintf(stderr, "Error: %s is already corrected for decay.\n", petfile);
305 imgEmpty(&img);
306 return(5);
307 }
308 /* Warning, if not known if data is corrected or not */
310 fprintf(stderr, "Warning: assuming %s was not corrected for decay.\n", petfile);
312 }
313 /* Then the decay correction */
314 ret=imgDecayCorrection(&img, 1);
315 if(ret) fprintf(stderr, "Error %d in decay correction.\n", ret);
316 } else if(decaycor==-2) {
317 if(img.decayCorrection==IMG_DC_CORRECTED && verbose>=0) {
318 fprintf(stdout, "removing decay correction...\n"); fflush(stdout);
319 } else {
320 fprintf(stderr, "Warning: removing decay correction.\n");
322 }
323 ret=imgDecayCorrection(&img, 0);
324 if(ret) fprintf(stderr, "Error %d in removal of decay correction.\n", ret);
325 } else if(decaycor==1) {
326 if(verbose>=0) printf("computing decay correction factors...\n");
327 /* Error, if already decay corrected */
329 fprintf(stderr, "Error: %s is already corrected for decay.\n", petfile);
330 imgEmpty(&img);
331 return(5);
332 }
333 if(img.type==IMG_TYPE_RAW) /* no reason to put factors in image, because
334 they are not saved anyway */
335 fprintf(stderr,
336 "Warning: decay correction factors are not saved in sinogram.\n");
337 ret=imgSetDecayCorrFactors(&img, 1);
338 if(ret)
339 fprintf(stderr, "Error %d in setting decay correction factors.\n", ret);
340 } else if(decaycor==-1) {
342 if(verbose>=0) printf("deleting decay correction factors...\n");
343 ret=imgSetDecayCorrFactors(&img, 0);
344 if(ret)
345 fprintf(stderr, "Error %d in removing decay correction factors.\n", ret);
346 } else {
347 fprintf(stderr, "Error: no need to delete decay correction factors.\n");
348 ret=10;
349 }
350 }
351 if(ret) {
352 imgEmpty(&img);
353 return(5);
354 }
355
356 /*
357 * Save corrected image/sinogram
358 */
359 if(verbose>1) {
360 fprintf(stdout, "writing %s ...", petfile); fflush(stdout);}
361 ret=imgWrite(petfile, &img);
362 if(ret) {
363 fprintf(stderr, "\nError: %s\n", img.statmsg);
364 imgEmpty(&img);
365 return(11);
366 }
367 if(verbose>=0) fprintf(stdout, "done.\n");
368
369
370 /* Print the final information and decay correction factors */
371 if(verbose>0) {
373 printf("PET data does not contain decay correction factors.\n");
374 } else {
375 printf("Frame start length Decay factor\n");
376 for(fi=0; fi<img.dimt; fi++)
377 printf("%4d %6.0f %6.0f %g\n", fi+1, img.start[fi],
378 img.end[fi]-img.start[fi], img.decayCorrFactor[fi] );
379 }
380 }
381
382
383 /* Free memory */
384 imgEmpty(&img);
385
386 return(0);
387}
388/*****************************************************************************/
389
390/*****************************************************************************/
char * hlCorrectIsotopeCode(char *isocode)
Definition halflife.c:141
double hlFromIsotope(char *isocode)
Definition halflife.c:55
void imgInfo(IMG *image)
Definition img.c:359
void imgEmpty(IMG *image)
Definition img.c:121
void imgInit(IMG *image)
Definition img.c:60
char * imgIsotope(IMG *img)
Definition imgdecayc.c:76
int imgSetDecayCorrFactors(IMG *image, int mode)
Definition imgdecayc.c:87
int imgDecayCorrection(IMG *image, int mode)
Definition imgdecayc.c:16
int imgRead(const char *fname, IMG *img)
Definition imgfile.c:26
int imgWrite(const char *fname, IMG *img)
Definition imgfile.c:136
Header file for libtpcimgio.
#define IMG_TYPE_RAW
#define IMG_DC_UNKNOWN
#define IMG_DC_CORRECTED
#define IMG_DC_NONCORRECTED
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
char type
char decayCorrection
unsigned short int dimt
float * start
float * end
float * decayCorrFactor
const char * statmsg
float isotopeHalflife