8#include "tpcclibConfig.h"
26static char *info[] = {
27 "Computes an AUC ratio image from dynamic PET image and reference region TTAC.",
28 "AUCs are calculated between start and end time given in minutes.",
29 "Image data can be in ECAT, Analyze 7.5, or NIfTI-1 format.",
31 "Usage: @P [Options] imgfile ttacfile starttime endtime outputfile",
35 " Instead of VOXEL/REF, (VOXEL-REF)/REF ratio is calculated.",
37 " Pixels with AUC less than (threshold/100 x ref AUC) are set to zero;",
40 " Upper limit for output pixel values.",
42 " Negative pixel values are set to zero.",
46 " @P ua2918dy1.v ua2918cer.tac 60 90 ua2918ratio.v",
48 "See also: imginteg, imgcalc, dftratio, imgcbv, imgunit, tacunit",
50 "Keywords: image, modelling",
84 if(verbose>1) printf(
"ecatCopyHeadersNoQuant(%s, %s)\n", file1, file2);
85 if(file1==NULL || file2==NULL)
return(1);
92 strcpy(tmp,
"user_process_code");
94 strcpy(tmp,
"ecat_calibration_factor");
96 strcpy(tmp,
"calibration_units");
98 strcpy(tmp,
"calibration_units_label");
100 strcpy(tmp,
"num_frames");
104 for(mi=0; mi<ehdr.
nr; mi++) {
105 strcpy(tmp,
"scale_factor");
107 strcpy(tmp,
"image_min");
109 strcpy(tmp,
"image_max");
111 strcpy(tmp,
"scan_min");
113 strcpy(tmp,
"scan_max");
115 strcpy(tmp,
"frame_duration");
117 strcpy(tmp,
"frame_start_time");
119 strcpy(tmp,
"decay_corr_fctr");
126 if(ret!=0)
return(10+ret);
136int main(
int argc,
char **argv)
138 int ai, help=0, version=0, verbose=1;
141 char tacfile[FILENAME_MAX], petfile[FILENAME_MAX], ratfile[FILENAME_MAX];
143 float calcThreshold=0.10;
144 float upperLimit=-1.0;
145 int nonnegativity_constraint=0;
148 double v, tstart, tstop, aucref;
154 if(argc==1) {
tpcPrintUsage(argv[0], info, stderr);
return(1);}
155 tacfile[0]=petfile[0]=ratfile[0]=(char)0;
157 tstart=tstop=nan(
"");
159 for(ai=1; ai<argc; ai++)
if(*argv[ai]==
'-') {
160 char *cptr=argv[ai]+1;
if(*cptr==
'-') cptr++;
if(cptr==NULL)
continue;
162 if(strncasecmp(cptr,
"BOUND", 1)==0) {
164 }
else if(strncasecmp(cptr,
"THR=", 4)==0) {
167 calcThreshold=0.01*v;
if(calcThreshold<=2.0)
continue;
169 }
else if(strncasecmp(cptr,
"MAX=", 4)==0) {
170 double v;
if(
atof_with_check(cptr+4, &v)==0 && v>0.0) {upperLimit=(float)v;
continue;}
171 }
else if(strncasecmp(cptr,
"NONEG", 3)==0) {
172 nonnegativity_constraint=1;
continue;
174 fprintf(stderr,
"Error: unknown option '%s'.\n", argv[ai]);
179 if(help==2) {
tpcHtmlUsage(argv[0], info,
"");
return(0);}
184 if(ai<argc) {
strlcpy(petfile, argv[ai], FILENAME_MAX); ai++;}
185 if(ai<argc) {
strlcpy(tacfile, argv[ai], FILENAME_MAX); ai++;}
188 if(ai<argc) {
strlcpy(ratfile, argv[ai], FILENAME_MAX); ai++;}
189 if(ai<argc) {fprintf(stderr,
"Error: too many arguments.\n");
return(1);}
193 fprintf(stderr,
"Error: missing command-line argument; use option --help\n");
196 if(tstop<tstart || tstart<0.0) {
197 fprintf(stderr,
"Error: invalid time range arguments.\n");
200 if(strcasecmp(petfile, ratfile)==0) {
201 fprintf(stderr,
"Error: check the output filename.\n");
207 printf(
"tacfile := %s\n", tacfile);
208 printf(
"petfile := %s\n", petfile);
209 printf(
"ratfile := %s\n", ratfile);
210 printf(
"tstart := %g\n", tstart);
211 printf(
"tstop := %g\n", tstop);
212 printf(
"b_per_r := %d\n", b_per_r);
213 printf(
"calcThreshold := %g%%\n", 100.*calcThreshold);
214 printf(
"max := %f\n", upperLimit);
215 printf(
"nonnegativity_constraint := %d\n", nonnegativity_constraint);
223 if(verbose>1) printf(
"reading data files\n");
225 FILE *lfp;
if(verbose>1) lfp=stdout;
else lfp=NULL;
227 petfile, NULL, tacfile, NULL, NULL, &endtime, &ai, &img,
228 NULL, &tac, 0, lfp, verbose-2, tmp);
230 fprintf(stderr,
"Error in reading data: %s.\n", tmp);
231 if(verbose>1) printf(
" ret := %d\n", ret);
235 if(verbose>0) fprintf(stderr,
"Warning: missing pixel values.\n");
236 if(verbose>2) printf(
"endtime := %g min\n", endtime);
243 fprintf(stderr,
"Error: %s is not an image.\n", petfile);
253 if(verbose>1) printf(
"calculating TTAC AUC\n");
255 t[0]=tstart; t[1]=tstop;
258 fprintf(stderr,
"Error in integration of reference region TAC.\n");
259 if(verbose>1) printf(
"ret := %d\n", ret);
262 aucref=auc[1]-auc[0];
264 printf(
"ref_AUC1 := %g\n", auc[0]);
265 printf(
"ref_AUC2 := %g\n", auc[1]);
267 if(verbose>0) printf(
"ref_AUC := %g\n", aucref);
268 if(aucref<=1.0E-10) {
269 fprintf(stderr,
"Error: invalid reference region AUC; check the data.\n");
278 if(verbose>1) printf(
"allocating memory for parametric image\n");
283 fprintf(stderr,
"Error: cannot allocate IMG data.\n");
284 if(verbose>1) fprintf(stderr,
"ret := %d\n", ret);
288 rout.
start[0]=60.0*tstart; rout.
end[0]=60.0*tstop;
290 rout.
unit=CUNIT_UNITLESS;
298 float threshold=calcThreshold*tac.
voi[0].
y2[tac.
frameNr-1];
301 printf(
"threshold x AUC = %g\n", threshold);
303 if(verbose>0) printf(
"computing pixel-by-pixel\n");
306 float peti[img.
dimt];
307 float t[2], auc[2], aucroi;
308 t[0]=60.0*tstart; t[1]=60.0*tstop;
309 for(zi=0; zi<img.
dimz; zi++) {
310 if(verbose>5) printf(
"computing plane %d\n", img.
planeNumber[zi]);
311 else if(verbose>0 && img.
dimz>2) {fprintf(stdout,
"."); fflush(stdout);}
312 for(yi=0; yi<img.
dimy; yi++)
for(xi=0; xi<img.
dimx; xi++) {
314 rout.
m[zi][yi][xi][0]=0.0;
319 if(peti[img.
dimt-1]<threshold)
continue;
322 for(fi=0; fi<img.
dimt; fi++)
323 img.
m[zi][yi][xi][fi]-=tac.
voi[0].
y[fi];
326 auc[0]/=60.0; auc[1]/=60.0;
327 if(ret) aucroi=0.0;
else aucroi=auc[1]-auc[0];
329 rout.
m[zi][yi][xi][0]=aucroi/aucref;
330 if(verbose>4 && zi==img.
dimz/2 && yi==img.
dimy/3 && xi==img.
dimx/3) {
331 printf(
"\nVoxel [%d,%d,%d] AUC: %g - %g = %g\n", zi, yi, xi, auc[1], auc[0], aucroi);
332 printf(
"ratio := %g\n", aucroi/aucref);
338 if(verbose>2) printf(
"okNr := %lld\n", okNr);
343 if(verbose>0) fprintf(stdout,
"filtering out ratio values exceeding %g\n", upperLimit);
347 if(nonnegativity_constraint!=0) {
348 if(verbose>1) printf(
"setting negative ratio values to zero\n");
356 if(verbose>1) printf(
"writing image %s\n", ratfile);
359 fprintf(stderr,
"Error: %s\n", rout.
statmsg);
362 if(verbose==1) printf(
"Ratio image saved: %s\n", ratfile);
365 if(verbose>1) printf(
"copying header information\n");
367 if(verbose>0 && ret!=0) printf(
"copying headers not successful (%d).\n", ret);
371 if(verbose>0) printf(
"done.\n");
int atof_with_check(char *double_as_string, double *result_value)
int dftTimeunitConversion(DFT *dft, int tunit)
void ehdrEmpty(ECAT_HEADERS *ehdr)
int ecat7WriteHeaders(const char *fname, ECAT_HEADERS *ehdr, int verbose)
void ehdrInitiate(ECAT_HEADERS *ehdr)
int ecat7ReadHeaders(const char *fname, ECAT_HEADERS *ehdr, int verbose)
int iftDeleteItem(IFT *ift, int item, int verbose)
int iftGet(IFT *ift, char *key, int verbose)
unsigned long long imgNaNs(IMG *img, int fix)
int imgAllocateWithHeader(IMG *image, int planes, int rows, int columns, int frames, IMG *image_from)
void imgEmpty(IMG *image)
int ecat7CopyHeadersNoQuant(const char *file1, const char *file2, int verbose)
int imgWrite(const char *fname, IMG *img)
void imgCutoff(IMG *image, float cutoff, int mode)
int fpetintegral(float *x1, float *x2, float *y, int nr, float *ie, float *iie)
Integrate PET TAC data to frame mid times. Float version of petintegral().
int interpolate(double *x, double *y, int nr, double *newx, double *newy, double *newyi, double *newyii, int newnr)
Linear interpolation and integration.
int finterpolate(float *x, float *y, int nr, float *newx, float *newy, float *newyi, float *newyii, int newnr)
float version of interpolate().
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)
size_t strlcpy(char *dst, const char *src, size_t dstsize)
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.