8#include "tpcclibConfig.h"
25double func(
int parNr,
double *p,
void*);
29double *x, *ymeas, *yfit, *w;
32double start_time, end_time;
36static char *info[] = {
37 "Estimates the half-life (t1/2) and elimination rate constant (kEL) of",
38 "a PET tracer in plasma, and the AUC of plasma time-activity curve (PTAC)",
39 "from 0 to infinite time. AUC can be used e.g. to estimate the total",
40 "clearance (ClT) of PET tracer after a single intravenous dose:",
47 "The natural logarithm of tracer concentration is plotted against time",
48 "from bolus infusion. The plot becomes linear in the end phase, as the",
49 "tracer is eliminated according to the laws of first-order reaction",
50 "kinetics. The slope of the linear part of the plot equals -kEL.",
52 "Usage: @P [Options] ptacfile [resultfile]",
55 " -end=<sample time>",
56 " Use data from 0 to given time in the line fit; by default",
57 " search for the best line fit extends to the last PTAC sample.",
58 " -start=<sample time>",
59 " Use data from given time to end in the line fit; by default,",
60 " the search for the best line fit extends to the first sample.",
62 " Best line fit is searched using algorithm that gives similar results",
63 " to WinNonlin with the same simple model.",
66 " -minnr=<sample number>",
67 " Enter the minimum number of samples to use in the fit; by default 3.",
69 " Plots of log transformed TACs and fitted lines are written in specified",
73 "Plasmafile must contain a time column, and one or more concentration columns",
74 "separated by space(s) or tabulator(s). The result is printed on screen.",
76 "See also: extrapol, interpol, fit_exp, fit_dexp, fit2dat, fit2auc",
78 "Keywords: input, modelling, pharmacokinetics, clearance, elimination rate",
97int main(
int argc,
char **argv)
99 int ai, help=0, version=0, verbose=1;
100 char datfile[FILENAME_MAX], outfile[FILENAME_MAX], svgfile[FILENAME_MAX], temp[512];
101 double fittime=-1.0, starttime=0.0;
102 int check_for_improvement=0;
112 if(argc==1) {
tpcPrintUsage(argv[0], info, stderr);
return(1);}
113 datfile[0]=outfile[0]=svgfile[0]=(char)0;
115 for(ai=1; ai<argc; ai++)
if(*argv[ai]==
'-') {
117 char *cptr=argv[ai]+1;
if(*cptr==
'-') cptr++;
if(cptr==NULL)
continue;
118 if(strncasecmp(cptr,
"E=", 2)==0 && strlen(cptr)>2) {
119 fittime=
atof_dpi(cptr+2);
if(fittime>0.0)
continue;
120 }
else if(strncasecmp(cptr,
"END=", 4)==0 && strlen(cptr)>4) {
121 fittime=
atof_dpi(cptr+4);
if(fittime>0.0)
continue;
122 }
else if(strncasecmp(cptr,
"ENDTIME=", 8)==0) {
123 fittime=
atof_dpi(cptr+8);
if(fittime>0.0)
continue;
124 }
else if(strncasecmp(cptr,
"START=", 6)==0 && strlen(cptr)>6) {
125 starttime=
atof_dpi(cptr+6);
if(starttime>=0.0)
continue;
126 }
else if(strncasecmp(cptr,
"STARTTIME=", 10)==0) {
127 starttime=
atof_dpi(cptr+10);
if(starttime>=0.0)
continue;
128 }
else if(strncasecmp(cptr,
"WINNONLIN", 3)==0) {
129 check_for_improvement=1;
continue;
130 }
else if(strcasecmp(cptr,
"NLFIT")==0) {
131 nonlinfit=1;
continue;
132 }
else if(strncasecmp(cptr,
"MINNR=", 6)==0) {
133 if(
atoi_with_check(cptr+6, &forced_minNr)==0 && forced_minNr>=3)
continue;
134 }
else if(strncasecmp(cptr,
"SVG=", 4)==0 && strlen(cptr)>4) {
135 strlcpy(svgfile, cptr+4, FILENAME_MAX);
continue;
137 fprintf(stderr,
"Error: invalid option '%s'.\n", argv[ai]);
142 if(help==2) {
tpcHtmlUsage(argv[0], info,
"");
return(0);}
147 if(ai<argc)
strlcpy(datfile, argv[ai++], FILENAME_MAX);
148 if(ai<argc)
strlcpy(outfile, argv[ai++], FILENAME_MAX);
149 if(ai<argc) {fprintf(stderr,
"Error: invalid argument '%s'.\n", argv[ai]);
return(1);}
153 fprintf(stderr,
"Error: missing command-line argument; use option --help\n");
157 if(check_for_improvement==1) nonlinfit=0;
161 printf(
"ptacfile := %s\n", datfile);
162 printf(
"svgfile := %s\n", svgfile);
163 if(outfile[0]) printf(
"resfile := %s\n", outfile);
164 if(fittime>=0.0) printf(
"endtime := %g\n", fittime);
165 if(starttime>=0.0) printf(
"starttime := %g\n", starttime);
166 if(forced_minNr>0) printf(
"forced_minNr := %d\n", forced_minNr);
167 printf(
"starttime := %g\n", starttime);
168 printf(
"check_for_improvement := %d\n", check_for_improvement);
169 printf(
"nonlinfit := %d\n", nonlinfit);
171 if(verbose>1) logfp=stdout;
else logfp=NULL;
177 if(verbose>1) printf(
"reading %s\n", datfile);
181 fprintf(stderr,
"Error in reading '%s': %s\n", datfile,
dfterrmsg);
186 fprintf(stderr,
"Error: missing sample(s) in %s\n", datfile);
195 while(dft.
x[fitNr-1]>fittime && fitNr>0) fitNr--;
197 fittime=dft.
x[fitNr-1];
198 if(verbose>1) printf(
"fittime := %g\n", dft.
x[fitNr-1]);
202 int min_nr=3;
if(forced_minNr>min_nr) min_nr=forced_minNr;
205 for(i=fitNr-1; i>=0; i--)
if(dft.
x[i]<starttime)
break;
209 printf(
"min_nr := %d\n", min_nr);
210 printf(
"max_nr := %d\n", max_nr);
213 if(max_nr<3 || max_nr<min_nr) {
215 fprintf(stderr,
"Error: too few samples for exponential fitting\n");
216 fflush(stderr);
dftEmpty(&dft);
return(2);
220 fprintf(stderr,
"Warning: few samples for exponential fitting\n");
227 if(verbose>1) printf(
"allocating memory for results.\n");
230 fprintf(stderr,
"Error: cannot setup memory for results.\n");
235 strncpy(res.
plasmafile, datfile, FILENAME_MAX);
244 pi=0; strcpy(res.
parname[pi],
"kEL"); strcpy(res.
parunit[pi],
"");
245 pi++; strcpy(res.
parname[pi],
"t1/2"); strcpy(res.
parunit[pi],
"");
246 pi++; strcpy(res.
parname[pi],
"AUC"); strcpy(res.
parunit[pi],
"");
247 pi++; strcpy(res.
parname[pi],
"Start"); strcpy(res.
parunit[pi],
"");
254 if(verbose>1) printf(
"allocating memory for ln transformed data\n");
256 if(
dftdup(&dft, &dftln)!=0) {
257 fprintf(stderr,
"Error: out of memory.\n");
260 if(verbose>1) printf(
"ln transformation\n");
261 if(
dft_ln(&dftln, NULL)!=0) {
262 fprintf(stderr,
"Error: cannot make ln transformation.\n");
265 if(verbose>10) {
dftPrint(&dftln); fflush(stdout);}
271 if(verbose>1) printf(
"linear fitting\n");
277 ret=
dft_end_line(&dftln, &f, &n, max_nr, -1.0, check_for_improvement,
281 fprintf(stderr,
"Error in linear fit: %s.\n", temp);
286 printf(
"Results of linear fitting:\n");
290 if(fit.
voiNr==1) printf(
"Adj_R^2 := %g (n=%d)\n", fit.
voi[0].
p[2], fit.
voi[0].
dataNr);
291 else for(
int ri=0; ri<fit.
voiNr; ri++)
299 if(verbose>0) printf(
"non-linear fitting\n");
300 for(
int ri=0; ri<dft.
voiNr; ri++) {
303 if(verbose>1) {fprintf(stdout,
"%s: \n", dft.
voi[ri].
name); fflush(stdout);}
306 x=dft.
x; ymeas=dft.
voi[ri].
y; yfit=dft.
voi[ri].
y2; w=dft.
w;
310 fit.
voi[ri].
wss=3.402823e+38;
311 for(pi=0; pi<parNr; pi++) pfit[pi]=0.0;
313 pmin[0]=0.0; pmax[0]=2.0*exp(fit.
voi[ri].
p[0]);
314 pmin[1]=2.0*fit.
voi[ri].
p[1]; pmax[1]=0.0;
316 ret=
tgo(pmin, pmax, func, NULL, parNr, 4, &fit.
voi[ri].
wss, pfit, 0, 0, verbose-19);
318 fprintf(stderr,
"Error %d in TGO.\n", ret);
324 printf(
" Measured Fitted:\n");
325 for(
int i=0; i<dft.
frameNr; i++)
326 printf(
" %2d: %8.2e %8.2e %8.2e\n", i+1, x[i], ymeas[i], yfit[i]);
329 printf(
" fitted parameters:");
330 for(
int pi=0; pi<parNr; pi++) printf(
" %g", pfit[pi]);
334 printf(
" parameter constraints:");
335 for(
int pi=0; pi<parNr; pi++) printf(
" (%g - %g)", pmin[pi], pmax[pi]);
339 fit.
voi[ri].
p[0]=log(pfit[0]);
340 fit.
voi[ri].
p[1]=pfit[1];
348 for(
int ri=0; ri<dftln.
voiNr; ri++) {
349 double auc_0_t, kel, c0, t12, auc_t_inf, auc_0_inf;
350 auc_0_t=kel=c0=t12=auc_t_inf=auc_0_inf=0.0;
351 if(verbose>0 && dft.
voiNr>1) printf(
"%s :\n", dftln.
voi[ri].
name);
354 auc_0_t=dft.
voi[ri].
y3[fitNr-1];
355 if(verbose>2) printf(
"auc_0_t := %g\n", auc_0_t);
357 kel=-fit.
voi[ri].
p[1];
358 c0=exp(fit.
voi[ri].
p[0]);
360 t12=
M_LN2/kel;
if(verbose>1) printf(
"t(1/2) := %g\n", t12);
362 auc_t_inf=c0*exp(-kel*fit.
voi[ri].
end)/kel;
363 if(verbose>2) printf(
"auc_t_inf := %g\n", auc_t_inf);
371 if(verbose>0 || !outfile[0]) {
372 fprintf(stdout,
" AUC(0-Inf)=%g [AUC(0-%g)=%g AUC(%g-Inf)=%g]\n",
373 auc_0_inf, fit.
voi[ri].
end, auc_0_t, fit.
voi[ri].
end, auc_t_inf);
374 fprintf(stdout,
" k(el)=%g t(1/2)=%g estimated between %g-%g\n",
392 fprintf(stderr,
"Error: cannot save fitted curves.\n");
396 for(
int ri=0; ri<dft3.
voiNr; ri++) {
399 for(
int fi=0; fi<dft3.
frameNr; fi++) {
400 dft3.
voi[ri].
y[fi]=nan(
"");
402 if(dft3.
x[fi]>fittime)
continue;
403 dft3.
voi[ri].
y[fi]=b+k*dft3.
x[fi];
408 if(verbose>1) printf(
"saving SVG plot\n");
409 sprintf(tmp,
"Line fit to log-transformed data ");
411 ret=
plot_fit_svg(&dftln, &dft3, tmp, svgfile, verbose-30);
413 fprintf(stderr,
"Error (%d) in writing '%s'.\n", ret, svgfile);
417 if(verbose>0) printf(
"Plots written in %s\n", svgfile);
428 if(verbose>1) printf(
"saving results in %s\n", outfile);
429 ret=
resWrite(&res, outfile, verbose-10);
431 fprintf(stderr,
"Error in writing '%s': %s\n", outfile,
reserrmsg);
448double func(
int parNr,
double *p,
void *fdata)
459 for(
int i=0; i<dataNr; i++) {
460 if(x[i]<start_time || x[i]>end_time || w[i]<=0.0)
continue;
461 yfit[i]=pa[0]*exp(pa[1]*x[i]);
462 v=yfit[i]-ymeas[i]; wss+=w[i]*v*v;
int modelCheckParameters(int par_nr, double *lower_p, double *upper_p, double *test_p, double *accept_p, double *penalty)
double atof_dpi(char *str)
int atoi_with_check(const char *int_as_string, int *result_value)
int dftdup(DFT *dft1, DFT *dft2)
int dftSortByFrame(DFT *dft)
int dft_nr_of_NA(DFT *dft)
int dftRead(char *filename, DFT *data)
int res_allocate_with_dft(RES *res, DFT *dft)
int integrate(double *x, double *y, int nr, double *yi)
Header file for libtpccurveio.
int resWrite(RES *res, char *filename, int verbose)
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)
void tpcProgramName(const char *program, int version, int copyright, char *prname, int n)
char * petTunit(int tunit)
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.
int tgo(double *lowlim, double *uplim, double(*objf)(int, double *, void *), void *objfData, int dim, int neighNr, double *fmin, double *gmin, int samNr, int tgoNr, int verbose)
Header file for libtpcmodext.
int plot_fit_svg(DFT *dft1, DFT *dft2, char *main_title, char *fname, int verbose)
Header file for libtpcsvg.
char name[MAX_REGIONNAME_LEN+1]
char studynr[MAX_STUDYNR_LEN+1]
char parname[MAX_RESPARAMS][MAX_RESPARNAME_LEN+1]
char plasmafile[FILENAME_MAX]
char parunit[MAX_RESPARAMS][MAX_RESPARNAME_LEN+1]
double parameter[MAX_RESPARAMS]
char name[MAX_REGIONNAME_LEN+1]