8#include "tpcclibConfig.h"
27static char *info[] = {
28 "Calculates SUV (standardized uptake value) image from PET image",
29 "in ECAT 6.3 and 7.x, NIfTI, or Analyze 7.5 format.",
30 "SUV in image pixels is calculated as mean value in specified time range.",
31 "Before calculation, make sure that radioactivity concentration units in PET",
32 "image header are correct. Analyze and NIfTI images do not contain units,",
33 "therefore unit kBq/mL is assumed.",
34 "Analyze and NIfTI must be accompanied by SIF.",
35 "Image data and injected dose must be decay corrected to the same time",
36 "(usually the tracer injection time).",
38 "Usage: @P [Options] image starttime endtime dose weight suvimage",
43 "SUV calculation start and stop time must be entered in minutes;",
44 "If SUV calculation start and end times are set to zero, then no average",
45 "over time is calculated, but the (dynamic) PET image is saved",
46 "in SUV or %i.d./L units.",
48 "Injected dose must be given in units MBq at the time of injection.",
50 "Subject weight must be given in kg or liters.",
51 "Instead of SUV, the percentage of injected dose per tissue volume ",
52 "(PID/L, %i.d./L) is calculated, if the subject weight is set to 0 (or below).",
54 "See also: imgunit, ecattime, imginteg, imgcalc, eframe, dftsuv",
56 "Keywords: image, SUV, DUR, DAR, PID, dose, modelling",
75int main(
int argc,
char **argv)
77 int ai, help=0, version=0, verbose=1;
79 char petfile[FILENAME_MAX], suvfile[FILENAME_MAX];
80 char *cptr, tmp[512], output_name[64];
82 float tstart, tstop, f;
90 if(argc==1) {
tpcPrintUsage(argv[0], info, stderr);
return(1);}
91 petfile[0]=suvfile[0]=(char)0;
92 tstart=tstop=-1.0; dose=weight=nan(
"");
95 for(ai=1; ai<argc; ai++)
if(*argv[ai]==
'-') {
96 cptr=argv[ai]+1;
if(*cptr==
'-') cptr++;
if(cptr==NULL)
continue;
98 fprintf(stderr,
"Error: invalid option '%s'.\n", argv[ai]);
103 if(help==2) {
tpcHtmlUsage(argv[0], info,
"");
return(0);}
108 for(; ai<argc; ai++) {
110 strcpy(petfile, argv[ai]);
continue;
111 }
else if(tstart<0) {
112 tstart=
atof_dpi(argv[ai]);
continue;
115 }
else if(isnan(dose)) {
117 }
else if(isnan(weight)) {
119 }
else if(!suvfile[0]) {
120 strcpy(suvfile, argv[ai]);
continue;
122 fprintf(stderr,
"Error: invalid argument '%s'.\n", argv[ai]);
128 fprintf(stderr,
"Error: missing result file name.\n");
131 if(weight<1.0E-100) weight=nan(
"");
132 if(strcasecmp(suvfile, petfile)==0) {
133 fprintf(stderr,
"Error: check the output filenames.\n");
136 if(tstop<tstart || tstart<0.0) {
137 fprintf(stderr,
"Error: invalid time range arguments.\n");
140 if(weight>0.0) strcpy(output_name,
"SUV");
141 else strcpy(output_name,
"%i.d./L");
145 printf(
"petfile := %s\n", petfile);
146 printf(
"suvfile := %s\n", suvfile);
147 printf(
"tstart := %g min\n", tstart);
148 printf(
"tstop := %g\n", tstop);
149 printf(
"dose := %g MBq\n", dose);
150 if(!isnan(weight)) printf(
"weight := %g kg\n", weight);
155 if(tstart<=0.0 && tstop<=0.0) doAverage=0;
161 if(verbose>0) fprintf(stdout,
"reading image %s\n", petfile);
164 fprintf(stderr,
"Error: %s\n", pet.
statmsg);
if(verbose>2)
imgInfo(&pet);
168 if(verbose>0) fprintf(stderr,
"Warning: missing pixel values.\n");
171 fprintf(stderr,
"Error: %s is not an image.\n", petfile);
177 if(pet.
dimt==1 && doAverage==1) {
180 fprintf(stderr,
"Warning: image has only one frame.\n");
181 fprintf(stderr,
"Warning: user-specified time range is not used.\n");
185 fprintf(stderr,
"Error: %s does not contain frame times.\n", petfile);
190 if(verbose>1) fprintf(stdout,
"checking frame overlap in %s\n", petfile);
193 fprintf(stderr,
"Error: image %s has overlapping frame times.\n", petfile);
204 if(pet.
unit==IMGUNIT_UNKNOWN) {
205 pet.
unit=IMGUNIT_KBQ_PER_ML;
206 fprintf(stderr,
"Warning: image calibration unit assumed to be %s.\n",
214 printf(
"image calibration unit := %s\n", tmp);
215 if(verbose>3) printf(
"img.unit := %d\n", pet.
unit);
217 if(pet.
unit==IMGUNIT_KBQ_PER_ML) ret=0;
220 fprintf(stderr,
"Error: invalid calibration unit in image.\n");
225 printf(
"final image calibration unit := %s\n", tmp);
226 if(verbose>3) printf(
"final img.unit := %d\n", pet.
unit);
231 printf(
"converting radioactivity concentrations into %s\n", output_name);
232 if(weight>0.0) f=weight/dose;
else f=100.0/dose;
233 if(verbose>1) printf(
"image is multiplied by factor %g\n", f);
236 fprintf(stderr,
"Error: cannot calculate %s.\n", output_name);
239 pet.
unit=IMGUNIT_UNITLESS;
242 printf(
"converted image calibration unit := %s\n", tmp);
243 if(verbose>3) printf(
"converted img.unit := %d\n", pet.
unit);
251 if(verbose>1) fprintf(stdout,
"writing %s image\n", output_name);
254 fprintf(stderr,
"Error: %s\n", pet.
statmsg);
258 fprintf(stdout,
"%s image written in %s\n", output_name, suvfile);
268 if(verbose>1) fprintf(stdout,
"calculating average-over-time image\n");
269 ret=
imgTimeIntegral(&pet, 60.0*tstart, 60.0*tstop, &rout, 1, tmp, verbose-2);
271 fprintf(stderr,
"Error: %s.\n", tmp);
274 if(verbose>1) fprintf(stdout,
"%s.\n", tmp);
280 if(verbose>1) fprintf(stdout,
"writing static %s image\n", output_name);
283 fprintf(stderr,
"Error: %s\n", rout.
statmsg);
287 fprintf(stdout,
"static %s image written in %s\n", output_name, suvfile);
int atof_with_check(char *double_as_string, double *result_value)
double atof_dpi(char *str)
int imgExistentTimes(IMG *img)
unsigned long long imgNaNs(IMG *img, int fix)
void imgEmpty(IMG *image)
int imgConvertUnit(IMG *img, char *unit)
int imgArithmConst(IMG *img, float operand, char operation, float ulimit, int verbose)
int imgRead(const char *fname, IMG *img)
int imgWrite(const char *fname, IMG *img)
int imgDeleteFrameOverlap(IMG *img)
char * imgUnit(int dunit)
Header file for libtpccurveio.
Header file for libtpcimgio.
Header file for libtpcimgp.
Header file for libtpcmisc.
int tpcProcessStdOptions(const char *s, int *print_usage, int *print_version, int *verbose_level)
int tpcHtmlUsage(const char *program, char *text[], const char *path)
void tpcPrintBuild(const char *program, FILE *fp)
void tpcPrintUsage(const char *program, char *text[], FILE *fp)
Header file for libtpcmodel.
Header file for libtpcmodext.
int imgTimeIntegral(IMG *img, float t1, float t2, IMG *iimg, int calc_mode, char *status, int verbose)