8#include "tpcclibConfig.h"
27double *petmeas, *petsim;
31double wss_wo_penalty=0.0;
34double cm2Func(
int parNr,
double *p,
void*);
38static char *info[] = {
39 "Non-linear fitting of one-tissue compartment model to plasma input, blood,",
40 "and tissue time-activity curves (PTAC, BTAC, and TTAC) to estimate",
41 "parameters K1, k2, and Vb. Sample times must be in minutes.",
43 "To fit only parameters K1 and Vb, assuming k2=0, create limit file (see options),",
44 "and set the lower and upper limit for K1/k2 to zero.",
48 " | Ca | ---> | C1 | ",
49 " |______| |______| ",
53 "Usage: @P [Options] ptacfile btacfile ttacfile endtime resultfile",
57 " Specify the constraints for model parameters;",
58 " This file with default values can be created by giving this",
59 " option as the only command-line argument to this program.",
60 " Without filename the default values are printed on screen.",
62 " Standard deviations are calculated and saved in results (Y, default),",
63 " or not calculated (n).",
64 " Program runs a lot faster if SD and CL are not calculated.",
66 " 95% Confidence limits are calculated and saved in results (y), or",
67 " not calculated (N, default).",
69 " Enter a fixed Vb; fitted by default.",
70 " -<BPnd|BPp|DVR>=<Reference region id or filename>",
71 " Optional reference region is used to calculate BPnd, BPp, or DVR;",
72 " BPnd=DVroi/DVref-1, BPp=DVroi-DVref, and DVR=DVroi/DVref",
74 " Fitted regional TACs are written in DFT format.",
76 " Fitted and measured TACs are plotted in specified SVG file.",
79 "Example 1: estimate K1, K1/k2 and Vb, with estimation of parameter SD",
80 " @P -sd=y a919ap.bld a919ab.bld a919.tac 60 a919k2.res",
82 "Example 2: estimate K1 and DV (=K1/k2); Vb is constrained to 0%;",
83 "DVRs are calculated by dividing DVs by the DV of region 'cer'",
84 " @P -Vb=0 -R=cer p25apc.bld none p25.tac 60 p25_k2.res",
86 "See also: logan, lhsoldv, fitk2di, fitk4, fit_h2o, p2t_v3c, tacweigh, taccbv",
88 "Keywords: TAC, modelling, distribution volume, reversible uptake, 1TCM",
107int main(
int argc,
char **argv)
109 int ai, help=0, version=0, verbose=1;
110 int ri, fi, pi, m, n, ret;
111 int ref=-1, refAdded=0, inputtype;
113 char dfile[FILENAME_MAX], pfile[FILENAME_MAX], bfile[FILENAME_MAX],
114 rfile[FILENAME_MAX], ffile[FILENAME_MAX], limfile[FILENAME_MAX];
115 char svgfile[FILENAME_MAX];
116 char *cptr, refname[FILENAME_MAX], tmp[FILENAME_MAX];
117 double fitdur, wss, aic;
120 int doBootstrap=0, doSD=0, doCL=0;
121 double *sd, *cl1, *cl2;
127 def_pmin[0]=0.0; def_pmax[0]=10.0;
128 def_pmin[1]=0.0; def_pmax[1]=500.0;
129 def_pmin[2]=0.0; def_pmax[2]=0.08;
134 if(argc==1) {
tpcPrintUsage(argv[0], info, stderr);
return(1);}
135 dfile[0]=pfile[0]=bfile[0]=rfile[0]=ffile[0]=refname[0]=limfile[0]=(char)0;
140 for(ai=1; ai<argc; ai++)
if(*argv[ai]==
'-') {
141 cptr=argv[ai]+1;
if(*cptr==
'-') cptr++;
if(cptr==NULL)
continue;
143 if(strncasecmp(cptr,
"CL", 2)==0) {
144 if(strlen(cptr)==2) {doCL=1;
continue;}
145 cptr+=2;
if(*cptr==
'=') {
147 if(*cptr==
'Y' || *cptr==
'y') {doCL=1;
continue;}
148 if(*cptr==
'N' || *cptr==
'n') {doCL=0;
continue;}
150 }
else if(strncasecmp(cptr,
"SD", 2)==0) {
151 if(strlen(cptr)==2) {doSD=1;
continue;}
152 cptr+=2;
if(*cptr==
'=') {
154 if(*cptr==
'Y' || *cptr==
'y') {doSD=1;
continue;}
155 if(*cptr==
'N' || *cptr==
'n') {doSD=0;
continue;}
157 }
else if(strncasecmp(cptr,
"LIM=", 4)==0 && strlen(cptr)>4) {
158 strlcpy(limfile, cptr+4, FILENAME_MAX);
continue;
159 }
else if(strncasecmp(cptr,
"I=", 2)==0 && strlen(cptr)>2) {
160 strlcpy(limfile, cptr+2, FILENAME_MAX);
continue;
161 }
else if(strcasecmp(cptr,
"LIM")==0) {
162 strcpy(limfile,
"stdout");
continue;
163 }
else if(strcasecmp(cptr,
"I")==0) {
164 strcpy(limfile,
"stdout");
continue;
165 }
else if(strncasecmp(cptr,
"Vb=", 3)==0 && strlen(cptr)>3) {
167 if(fVb>=0.0 && fVb<1.0) {
168 if(fVb<0.01) fprintf(stderr,
"Warning: Vb was set to %g%%\n", 100.*fVb);
169 def_pmin[2]=def_pmax[2]=fVb;
173 }
else if(strncasecmp(cptr,
"DVR=", 4)==0) {
174 bp_type=1;
strlcpy(refname, cptr+4, FILENAME_MAX);
175 if(strlen(refname)>0.0)
continue;
176 }
else if(strncasecmp(cptr,
"BPnd=", 5)==0) {
177 bp_type=2;
strlcpy(refname, cptr+5, FILENAME_MAX);
178 if(strlen(refname)>0.0)
continue;
179 }
else if(strncasecmp(cptr,
"BPp=", 4)==0) {
180 bp_type=3;
strlcpy(refname, cptr+4, FILENAME_MAX);
181 if(strlen(refname)>0.0)
continue;
182 }
else if(strncasecmp(cptr,
"FIT=", 4)==0) {
183 strlcpy(ffile, cptr+4, FILENAME_MAX);
if(strlen(ffile)>0)
continue;
184 }
else if(strncasecmp(cptr,
"SVG=", 4)==0) {
185 strlcpy(svgfile, cptr+4, FILENAME_MAX);
if(strlen(svgfile)>0)
continue;
187 fprintf(stderr,
"Error: invalid option '%s'.\n", argv[ai]);
192 if(help==2) {
tpcHtmlUsage(argv[0], info,
"");
return(0);}
197 for(; ai<argc; ai++) {
199 strlcpy(pfile, argv[ai], FILENAME_MAX);
continue;
200 }
else if(!bfile[0]) {
201 strlcpy(bfile, argv[ai], FILENAME_MAX);
continue;
202 }
else if(!dfile[0]) {
203 strlcpy(dfile, argv[ai], FILENAME_MAX);
continue;
204 }
else if(fitdur<0) {
206 fprintf(stderr,
"Error: invalid fit time '%s'.\n", argv[ai]);
208 }
else if(!rfile[0]) {
209 strlcpy(rfile, argv[ai], FILENAME_MAX);
continue;
212 fprintf(stderr,
"Error: too many arguments: '%s'.\n", argv[ai]);
215 if(doSD || doCL) doBootstrap=1;
else doBootstrap=0;
219 printf(
"pfile := %s\n", pfile);
220 printf(
"dfile :=%s\n", dfile);
221 printf(
"rfile := %s\n", rfile);
222 printf(
"ffile := %s\n", ffile);
223 printf(
"svgfile := %s\n", svgfile);
224 printf(
"limfile := %s\n", limfile);
225 printf(
"bp_type := %d\n", bp_type);
226 printf(
"refname := %s\n", refname);
227 printf(
"fitdur := %g\n", fitdur);
228 printf(
"doBootstrap := %d\n", doBootstrap);
229 printf(
"doSD := %d\n", doSD);
230 printf(
"doCL := %d\n", doCL);
236 if(limfile[0] && !pfile[0]) {
238 if(strcasecmp(limfile,
"stdout")!=0 && access(limfile, 0) != -1) {
239 fprintf(stderr,
"Error: parameter constraint file %s exists.\n", limfile);
242 if(verbose>1) printf(
"writing parameter constraints file\n");
252 fprintf(stderr,
"Error in writing '%s': %s\n", limfile, ift.
status);
255 if(strcasecmp(limfile,
"stdout")!=0)
256 fprintf(stdout,
"Parameter file %s with initial values written.\n", limfile);
261 if(fitdur==0) fitdur=1.0E+100;
262 else if(fitdur<0) {
tpcPrintUsage(argv[0], info, stderr);
return(1);}
264 fprintf(stderr,
"Error: missing command-line argument; use option --help\n");
274 if(verbose>1) printf(
"reading %s\n", limfile);
275 ret=
iftRead(&ift, limfile, 1, 0);
277 fprintf(stderr,
"Error in reading '%s': %s\n", limfile, ift.
status);
280 if(verbose>10)
iftWrite(&ift,
"stdout", 0);
292 if(n==0) {fprintf(stderr,
"Error: invalid parameter file.\n");
return(9);}
295 for(pi=n=0, ret=0; pi<parNr; pi++) {
296 if(def_pmin[pi]<0.0) ret++;
297 if(def_pmax[pi]<def_pmin[pi]) ret++;
298 if(def_pmax[pi]>def_pmin[pi]) n++;
301 fprintf(stderr,
"Error: invalid parameter constraints.\n");
305 fprintf(stderr,
"Error: no model parameters left free for fitting.\n");
310 if(fVb>=0.0) def_pmin[2]=def_pmax[2]=fVb;
311 if(def_pmin[2]==def_pmax[2]) fVb=def_pmin[2];
312 if(fVb==0.0) strcpy(bfile,
"");
314 printf(
"bfile := %s\n", bfile);
315 if(fVb>=0.0) printf(
"fVb := %g\n", fVb);
322 if(verbose>1) printf(
"reading tissue and input data\n");
324 &fitframeNr, &dft, &input, stdout, verbose-2, tmp);
326 fprintf(stderr,
"Error: %s\n", tmp);
329 if(fitframeNr<4 || input.
frameNr<4) {
330 fprintf(stderr,
"Error: too few samples in specified fit duration.\n");
335 if(verbose>2) printf(
"setting blood tac to zero\n");
338 fprintf(stderr,
"Error: cannot allocate more memory.\n");
343 for(fi=0; fi<input.
frameNr; fi++) input.
voi[1].
y[fi]=0.0;
350 fprintf(stdout,
"common_data_weights := %g", dft.
w[0]);
351 for(fi=1; fi<dft.
frameNr; fi++) fprintf(stdout,
", %g", dft.
w[fi]);
352 fprintf(stdout,
"\n");
361 if(verbose>1) printf(
"no reference region data\n");
364 if(verbose>1) printf(
"reading reference region data\n");
365 if((n=
dftReadReference(&dft, refname, &inputtype, &ref, tmp, verbose-3))<1) {
366 fprintf(stderr,
"Error in reading '%s': %s\n", refname, tmp);
367 if(verbose>2) printf(
"dftReadReference()=%d\n", n);
372 fprintf(stderr,
"Warning: %s selected of %d reference regions.\n",
375 fprintf(stdout,
"selected reference region := %s\n", dft.
voi[ref].
name);
377 refAdded=0; strcpy(refname,
"");
382 if(verbose>1) printf(
"Reference region: %s\n", dft.
voi[ref].
name );
388 fprintf(stderr,
"Error: cannot allocate more memory.\n");
400 if(verbose>1) printf(
"initializing result data\n");
402 fprintf(stderr,
"Error: cannot setup memory for results.\n");
411 if(refname[0]) strcpy(res.
reffile, refname);
415 if(fVb>=0.0) res.
Vb=100.0*fVb;
424 pi=0; strcpy(res.
parname[pi],
"K1"); strcpy(res.
parunit[pi],
"ml/(min*ml)");
425 pi++; strcpy(res.
parname[pi],
"K1/k2"); strcpy(res.
parunit[pi],
"ml/ml");
426 pi++; strcpy(res.
parname[pi],
"Vb"); strcpy(res.
parunit[pi],
"%");
431 }
else if(bp_type==2) {
437 pi++; strcpy(res.
parname[pi],
"WSS"); strcpy(res.
parunit[pi],
"");
438 pi++; strcpy(res.
parname[pi],
"AIC"); strcpy(res.
parunit[pi],
"");
445 fprintf(stdout,
"fitting regional TACs: ");
446 if(verbose>1) fprintf(stdout,
"\n");
449 for(ri=0; ri<dft.
voiNr; ri++) {
450 if(verbose>2) printf(
"\n %d %s:\n", ri, dft.
voi[ri].
name);
453 petmeas=dft.
voi[ri].
y; petsim=dft.
voi[ri].
y2;
456 pmin[0]=def_pmin[0]; pmax[0]=def_pmax[0];
457 pmin[1]=def_pmin[1]; pmax[1]=def_pmax[1];
458 pmin[2]=def_pmin[2]; pmax[2]=def_pmax[2];
460 printf(
" constraints :=");
461 for(pi=0; pi<parNr; pi++) printf(
" [%g,%g]", pmin[pi], pmax[pi]);
469 pmin, pmax, cm2Func, NULL, parNr, 8,
472 fprintf(stderr,
"\nError in optimization (%d).\n", ret);
476 printf(
" fitted_parameters :=");
477 for(pi=0; pi<parNr; pi++) printf(
" %g", res.
voi[ri].
parameter[pi]);
487 if(verbose>2) printf(
"\n bootstrapping\n");
490 if(doSD) sd=res.
voi[ri].
sd;
else sd=NULL;
491 if(doCL) {cl1=res.
voi[ri].
cl1; cl2=res.
voi[ri].
cl2;}
else cl1=cl2=NULL;
501 parNr, dft.
w, cm2Func, tmp, verbose-4
504 fprintf(stderr,
"\nError in bootstrap: %s\n", tmp);
505 for(pi=0; pi<parNr; pi++) {
506 if(doSD) sd[pi]=nan(
"");
507 if(doCL) cl1[pi]=cl2[pi]=nan(
"");
512 for(pi=0; pi<parNr; pi++)
516 for(pi=n=0; pi<parNr; pi++)
if(pmax[pi]>pmin[pi]) n++;
517 if(verbose>2) printf(
"nr_of_fitted_parameters := %d\n", n);
518 for(fi=m=0; fi<fitframeNr; fi++)
if(dft.
w[fi]>0.0) m++;
519 if(verbose>2) printf(
"nr_of_fitted_samples := %d\n", m);
520 aic=
aicSS(wss, m, n);
527 if(dft.
voiNr>2 && verbose==1) {fprintf(stdout,
"."); fflush(stdout);}
531 if(verbose>0) {fprintf(stdout,
"\n"); fflush(stdout);}
534 for(ri=0; ri<res.
voiNr; ri++){
536 if(!isnan(res.
voi[ri].
cl1[2])) res.
voi[ri].
cl1[2]*=100.;
537 if(!isnan(res.
voi[ri].
cl2[2])) res.
voi[ri].
cl2[2]*=100.;
538 if(!isnan(res.
voi[ri].
sd[2])) res.
voi[ri].
sd[2]*=100.;
541 if(bp_type==1 || bp_type==2) {
543 for(ri=0; ri<res.
voiNr; ri++) {
549 for(ri=0; ri<res.
voiNr; ri++)
553 for(ri=0; ri<res.
voiNr; ri++)
561 if(verbose>0) {
resPrint(&res); fprintf(stdout,
"\n");}
567 if(verbose>1) printf(
"saving results\n");
568 ret=
resWrite(&res, rfile, verbose-3);
570 fprintf(stderr,
"Error in writing '%s': %s\n", rfile,
reserrmsg);
574 if(verbose>0) fprintf(stdout,
"Model parameters written in %s\n", rfile);
580 if(svgfile[0] || ffile[0]) {
587 fprintf(stderr,
"Error: cannot save fitted curves.\n");
591 for(ri=0; ri<dft.
voiNr; ri++)
for(fi=0; fi<fitframeNr; fi++)
597 if(verbose>1) printf(
"saving SVG plot\n");
598 sprintf(tmp,
"1-tissue CM fit: ");
603 0.0, nan(
""), svgfile, verbose-8);
605 fprintf(stderr,
"Error (%d) in writing '%s'.\n", ret, svgfile);
609 if(verbose>0) printf(
"Plots written in %s\n", svgfile);
614 for(ri=dft2.
voiNr-1; ri>=0; ri--)
if(dft2.
voi[ri].
sw!=0)
620 if(verbose>1) printf(
"saving fitted curves\n");
622 sprintf(dft2.
comments,
"# program := %s\n", tmp);
624 fprintf(stderr,
"Error in writing '%s': %s\n", ffile,
dfterrmsg);
628 if(verbose>0) printf(
"Fitted TACs written in %s\n", ffile);
644double cm2Func(
int parNr,
double *p,
void *fdata)
647 double k2, Vb, d, wss=0.0;
655 if(pa[1]>0.0) k2=pa[0]/pa[1];
else k2=0.0;
656 if(fVb>=0.0) Vb=fVb;
else Vb=pa[2];
661 pa[0], k2, 0, 0, 0, 0, 0.0, Vb, 1.0,
662 input.
voi[0].
y2, NULL, NULL, NULL, NULL, NULL);
664 printf(
"error %d in simulation\n", ret);
672 dft.
x1, dft.
x2, petsim, NULL, NULL, fitframeNr);
676 dft.
x, petsim, NULL, NULL, fitframeNr);
678 printf(
"error %d in interpolation\n", ret);
683 for(fi=0; fi<fitframeNr; fi++)
if(dft.
w[fi]>0.0) {
684 d=petmeas[fi]-petsim[fi];
689 if(0) printf(
"%g %g %g => %g\n", pa[0], k2, pa[2], wss);
double aicSS(double ss, const int n, const int k)
int bootstrap(int iterNr, double *cLim1, double *cLim2, double *SD, double *parameter, double *lowlim, double *uplim, int frameNr, double *origTac, double *fitTac, double *bsTac, int parNr, double *weight, double(*objf)(int, double *, void *), char *status, int verbose)
int modelCheckParameters(int par_nr, double *lower_p, double *upper_p, double *test_p, double *accept_p, double *penalty)
int atof_with_check(char *double_as_string, double *result_value)
double atof_dpi(char *str)
int dftdup(DFT *dft1, DFT *dft2)
int dftAddmem(DFT *dft, int voiNr)
int dftDelete(DFT *dft, int voi)
int dftWrite(DFT *data, char *filename)
int res_allocate_with_dft(RES *res, DFT *dft)
int iftPutDouble(IFT *ift, char *key, double value, char *cmt_type, int verbose)
int iftRead(IFT *ift, char *filename, int is_key_required, int verbose)
int iftWrite(IFT *ift, char *filename, int verbose)
int iftGetDoubleValue(IFT *ift, int si, const char *key, double *value, int verbose)
int interpolate(double *x, double *y, int nr, double *newx, double *newy, double *newyi, double *newyii, int newnr)
Linear interpolation and integration.
int interpolate4pet(double *x, double *y, int nr, double *newx1, double *newx2, double *newy, double *newyi, double *newyii, int newnr)
Interpolate and integrate TAC to PET frames.
Header file for libtpccurveio.
int resWrite(RES *res, char *filename, int verbose)
#define DFT_TIME_STARTEND
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)
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 simC3vs(double *t, double *ca, double *cb, int nr, double k1, double k2, double k3, double k4, double k5, double k6, double f, double vb, double fa, double *cpet, double *cta, double *ctb, double *ctc, double *ctab, double *ctvb)
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_fitrange_svg(DFT *dft1, DFT *dft2, char *main_title, double x1, double x2, double y1, double y2, char *fname, int verbose)
Header file for libtpcsvg.
char studynr[MAX_STUDYNR_LEN+1]
char comments[_DFT_COMMENT_LEN+1]
char parname[MAX_RESPARAMS][MAX_RESPARNAME_LEN+1]
char plasmafile[FILENAME_MAX]
char datafile[FILENAME_MAX]
char reffile[FILENAME_MAX]
char parunit[MAX_RESPARAMS][MAX_RESPARNAME_LEN+1]
char bloodfile[FILENAME_MAX]
double parameter[MAX_RESPARAMS]
double cl2[MAX_RESPARAMS]
double cl1[MAX_RESPARAMS]
char voiname[MAX_REGIONSUBNAME_LEN+1]
char name[MAX_REGIONNAME_LEN+1]