10#include "tpcclibConfig.h"
29#define DEFAULT_LC 1.00
31#ifndef DEFAULT_DENSITY
32#define DEFAULT_DENSITY 1.00
37static char *info[] = {
38 "Calculates the net influx (uptake) rate constant (Ki) from dynamic PET image",
39 "in ECAT, NIfTI, or Analyze format, applying the multiple time graphical",
40 "analysis (MTGA) approach for irreversible tracer uptake (Patlak plot).",
41 "Simple non-iterative perpendicular line fitting algorithm (4) is applied.",
43 "Usage: @P [Options] input image starttime resultimage",
45 "Input can be either a TAC file containing arterial plasma PTAC or reference",
46 "region TTAC. Data must be in the same concentration units as the data in",
47 "image, and times in min; however, if units are specified inside the input",
48 "and image file, the program can automatically convert units.",
49 "Start time of the linear fit must be given in minutes; set to zero to",
50 "let the program automatically determine the start time (not recommended).",
54 " Concentration of native substrate in arterial plasma (mM),",
55 " for example plasma glucose in [18F]FDG studies.",
56 " With this option the metabolic rate (umol/(min*100 g)) is calculated.",
58 " Lumped Constant in MR calculation; default is 1.0.",
60 " Tissue density in MR calculation; default is 1.0 g/ml.",
62 " Pixels with AUC less than (threshold/100 x input AUC) are set to zero;",
67 " Pixels with negative Ki are set to zero.",
69 " Upper limit for Ki values.",
71 " Remove parametric pixel values that are over 4x higher than",
72 " their closest neighbours.",
73 " -end=<Fit end time (min)>",
74 " By default line is fitted to the end of data. Use this option to enter",
77 " Y axis intercepts are written as an image in specified file.",
79 " Numbers of selected plot data points are written as an image.",
82 "Example 1. Calculation of Ki image, starting linear fit from 20 minutes:",
83 " @P ua2918ap.kbq ua2918dy1.v 20 ua2918ki.v",
85 "Example 2. Calculation of glucose uptake image, when tissue density is 1.02,",
86 " plasma glucose concentration is 5.2 mM, lumped constant is 1.0,",
87 " starting linear fit from 10 minutes after radiotracer injection:",
88 " @P -density=1.02 -Ca=5.2 -LC=1.0 s8642ap.kbq s8642dy1.v 10 s8642ki.v",
90 "The unit of pixel values in the parametric (Ki) image is",
91 "(mL plasma)/(min*(mL tissue)) by default, and umol/(min*100 g) in metabolic",
94 "To calculate Ki images from [18F]FDOPA studies with plasma input:",
95 "subtract reference region TAC from dynamic image before using this program.",
98 "1. Gjedde A. Calculation of cerebral glucose phosphorylation from brain",
99 " uptake of glucose analogs in vivo: a re-examination. Brain Res. 1982;",
101 "2. Patlak CS, Blasberg RG, Fenstermacher JD. Graphical evaluation of",
102 " blood-to-brain transfer constants from multiple-time uptake data.",
103 " J Cereb Blood Flow Metab 1983;3:1-7.",
104 "3. Patlak CS, Blasberg RG. Graphical evaluation of blood-to-brain transfer",
105 " constants from multiple-time uptake data. Generalizations",
106 " J Cereb Blood Flow Metab 1985;5:584-590.",
107 "4. Varga J & Szabo Z. Modified regression model for the Logan plot.",
108 " J Cereb Blood Flow Metab 2002; 22:240-244.",
110 "See also: imgfur, imgbound, imgunit, imglhki, img2tif, patlak ",
112 "Keywords: image, MTGA, Patlak plot, modelling, Ki, metabolic rate",
131int main(
int argc,
char **argv)
133 int ai, help=0, version=0, verbose=1;
137 char inpfile[FILENAME_MAX], petfile[FILENAME_MAX];
138 char icfile[FILENAME_MAX], nrfile[FILENAME_MAX], outfile[FILENAME_MAX];
139 char tmp[1024], *cptr;
141 IMG img, out, icimg, nrimg;
142 double startTime=-1.0, upperLimit=-1.0, fittime=-1.0;
143 float calcThreshold=0.0;
144 int startSample=0, endSample=0, fitdimt=0;
146 double LC=-1.0, Ca=-1.0, density=-1.0;
152 if(argc==1) {
tpcPrintUsage(argv[0], info, stderr);
return(1);}
153 inpfile[0]=petfile[0]=outfile[0]=icfile[0]=nrfile[0]=(char)0;
157 for(ai=1; ai<argc; ai++)
if(*argv[ai]==
'-') {
158 cptr=argv[ai]+1;
if(*cptr==
'-') cptr++;
if(cptr==NULL)
continue;
160 if(strncasecmp(cptr,
"V=", 2)==0) {
161 strcpy(icfile, cptr+2);
if(strlen(icfile)>1)
continue;
162 }
else if(strncasecmp(cptr,
"N=", 2)==0) {
163 strcpy(nrfile, cptr+2);
if(strlen(nrfile)>1)
continue;
164 }
else if(strncasecmp(cptr,
"CA=", 3)==0) {
165 Ca=
atof_dpi(cptr+3);
if(Ca>0.0)
continue;
166 }
else if(strncasecmp(cptr,
"LC=", 3)==0) {
167 LC=
atof_dpi(cptr+3);
if(LC>0.0)
continue;
168 }
else if(strncasecmp(cptr,
"D=", 2)==0) {
169 density=
atof_dpi(cptr+2);
if(density>0.0)
continue;
170 }
else if(strncasecmp(cptr,
"DENSITY=", 8)==0) {
171 density=
atof_dpi(cptr+8);
if(density>0.0)
continue;
172 }
else if(strncasecmp(cptr,
"NONEGATIVES", 5)==0) {
174 }
else if(strncasecmp(cptr,
"MAX=", 4)==0) {
175 upperLimit=
atof_dpi(cptr+4);
if(upperLimit>0.0)
continue;
176 }
else if(strncasecmp(cptr,
"E=", 2)==0) {
177 fittime=60.0*
atof_dpi(cptr+2);
if(fittime>0.0)
continue;
178 }
else if(strncasecmp(cptr,
"END=", 4)==0) {
179 fittime=60.0*
atof_dpi(cptr+4);
if(fittime>0.0)
continue;
180 }
else if(strncasecmp(cptr,
"FILTER", 4)==0) {
181 param_filt=1;
continue;
182 }
else if(strncasecmp(cptr,
"THR=", 4)==0) {
184 if(ret==0) {calcThreshold=0.01*v;
continue;}
186 fprintf(stderr,
"Error: invalid option '%s'.\n", argv[ai]);
191 if(help==2) {
tpcHtmlUsage(argv[0], info,
"");
return(0);}
196 if(ai<argc)
strlcpy(inpfile, argv[ai++], FILENAME_MAX);
197 if(ai<argc)
strlcpy(petfile, argv[ai++], FILENAME_MAX);
198 if(ai<argc) {startTime=
atof_dpi(argv[ai++]);
if(startTime<0.0) startTime=0.0;}
199 if(ai<argc)
strlcpy(outfile, argv[ai++], FILENAME_MAX);
201 fprintf(stderr,
"Error: invalid argument '%s'.\n", argv[ai]);
207 fprintf(stderr,
"Error: missing result file name.\n");
214 fprintf(stderr,
"Warning: LC not set, using default %g\n", LC);
217 density=DEFAULT_DENSITY;
218 fprintf(stderr,
"Warning: tissue density not set, using default %g\n", density);
221 if(LC>0.0) fprintf(stderr,
"Warning: LC was set but is not used.\n");
222 if(density>0.0) fprintf(stderr,
"Warning: tissue density was set but is not used.\n");
228 printf(
"inpfile := %s\n", inpfile);
229 printf(
"petfile := %s\n", petfile);
230 printf(
"outfile := %s\n", outfile);
231 printf(
"startTime := %g min\n", startTime);
232 printf(
"icfile := %s\n", icfile);
233 printf(
"nrfile := %s\n", nrfile);
234 printf(
"max := %f\n", upperLimit);
235 printf(
"Ca := %g\n", Ca);
236 printf(
"LC := %g\n", LC);
237 printf(
"fittime := %g\n", fittime);
238 printf(
"density := %g\n", density);
239 printf(
"param_filt := %d\n", param_filt);
240 printf(
"calcThreshold := %g%%\n", 100.*calcThreshold);
241 printf(
"noneg := %d\n", noneg);
252 petfile, NULL, inpfile, NULL, NULL, &fittime, &fitdimt, &img,
253 &input, NULL, 1, NULL, verbose-2, tmp);
255 fprintf(stderr,
"Error in reading data: %s.\n", tmp);
260 if(verbose>0) fprintf(stderr,
"Warning: missing pixel values.\n");
264 printf(
"fittimeFinal := %g [min]\n", fittime/60.0);
265 printf(
"fitdimt := %d\n", fitdimt);
266 printf(
"endSampleIndex := %d\n", endSample);
267 printf(
"endSample := %d\n", endSample+1);
270 for(fi=startSample=0; fi<fitdimt; fi++)
271 if((img.
mid[fi]/60.0)>startTime)
break;
else startSample++;
273 printf(
"startSampleIndex := %d\n", startSample);
274 printf(
"startSample := %d\n", startSample+1);
275 printf(
"startTimeFinal := %g [min]\n", img.
start[startSample]/60.0);
277 if((fitdimt-startSample)<2) {
278 fprintf(stderr,
"Error: too few time frames to fit.\n");
288 if(verbose>1) fprintf(stdout,
"thresholding\n");
291 fprintf(stderr,
"Error in thresholding the dynamic image: %s\n", img.
statmsg);
296 fprintf(stdout,
"threshold_cutoff_nr := %d / %d\n", n, img.
dimx*img.
dimy*img.
dimz);
303 if(startTime>0.0) fit_range=PRESET;
else fit_range=EXCLUDE_BEGIN;
304 if(verbose>1) printf(
"fit_range := %d\n", (
int)fit_range);
306 IMG *picimg=NULL, *pnrimg=NULL;
307 if(icfile[0]) picimg=&icimg;
308 if(nrfile[0]) pnrimg=&nrimg;
310 if(verbose>0) fprintf(stdout,
"computing MTGA pixel-by-pixel\n");
311 clock_t fitStart, fitFinish;
313 ret=
img_patlak(&input, &img, startSample, endSample, fit_range, calcThreshold,
314 &out, picimg, pnrimg, tmp, verbose-5);
316 fprintf(stderr,
"Error (%d): %s\n", ret, tmp);
321 if(fitFinish>fitStart)
322 fprintf(stdout,
"done in %g seconds.\n",
323 (
double)(fitFinish - fitStart) / (
double)CLOCKS_PER_SEC );
324 else fprintf(stdout,
"done.\n");
336 if(verbose>0) fprintf(stdout,
"filtering out Ki values exceeding %g\n", upperLimit);
341 if(verbose>0) fprintf(stdout,
"filtering out negative Ki values\n");
349 if(verbose>0) printf(
"filtering extreme values from parametric images\n");
360 MRf=100.*Ca/(density*LC);
361 if(verbose>1) fprintf(stdout,
"converting Ki to metabolic rate with factor %g\n", MRf);
364 fprintf(stderr,
"Error: cannot calculate metabolic rate.\n");
368 out.
unit=CUNIT_UMOL_PER_MIN_PER_100G;
375 fprintf(stderr,
"Error: %s\n", tmp);
378 if(verbose>1) printf(
"%s\n", tmp);
381 fprintf(stderr,
"Error: %s\n", out.
statmsg);
385 if(Ca<=0.0) fprintf(stdout,
"Ki image %s saved.\n", outfile);
386 else fprintf(stdout,
"MR image %s saved.\n", outfile);
394 fprintf(stderr,
"Error: %s\n", tmp);
397 if(verbose>1) printf(
"%s\n", tmp);
398 ret=
imgWrite(icfile, &icimg);
if(ret) {
399 fprintf(stderr,
"Error: %s\n", icimg.
statmsg);
402 if(verbose>0) fprintf(stdout,
"Intercept image %s saved.\n", icfile);
410 fprintf(stderr,
"Error: %s\n", tmp);
413 if(verbose>1) printf(
"%s\n", tmp);
414 ret=
imgWrite(nrfile, &nrimg);
if(ret) {
415 fprintf(stderr,
"Error: %s\n", nrimg.
statmsg);
418 if(verbose>0) fprintf(stdout,
"Nr image %s saved.\n", nrfile);
int backupExistingFile(char *filename, char *backup_ext, char *status)
int atof_with_check(char *double_as_string, double *result_value)
double atof_dpi(char *str)
unsigned long long imgNaNs(IMG *img, int fix)
void imgEmpty(IMG *image)
int img_patlak(DFT *input, IMG *dyn_img, int start, int end, linefit_range fit_range, float thrs, IMG *ki_img, IMG *ic_img, IMG *nr_img, char *status, int verbose)
int imgArithmConst(IMG *img, float operand, char operation, float ulimit, int verbose)
int imgWrite(const char *fname, IMG *img)
void imgCutoff(IMG *image, float cutoff, int mode)
int imgThresholding(IMG *img, float threshold_level, long long *thr_nr)
int imgOutlierFilter(IMG *img, float limit)
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.