10#include "tpcclibConfig.h"
26static char *info[] = {
27 "Non-linear fitting of the exponential based function suggested by",
28 "Feng et al (1993) to the PET plasma or blood time-activity curve (TAC).",
31 " when t<=dt : f(t) = 0 ",
32 " when t>dt : f(t) = (p1*(t-dt)-p3-p5)*exp(p2*(t-dt)) ",
33 " + p3*exp(p4*(t-dt)) + p5*exp(p6*(t-dt))",
35 "Usage: @P [Options] tacfile [parfile]",
39 " Specify the constraints for function parameters;",
40 " This file with default values can be created by giving this",
41 " option as the only command-line argument to this program.",
42 " Without file name the default values are printed on screen.",
44 " Given datafile contains the AUC of TAC as function of time.",
46 " Weight by sampling interval.",
51 " The nr of exponential functions; A=determined automatically.",
52 " Default is 3; changing the default may lead to a bad fit.",
54 " Function approaches steady level; last exponent term is a constant,",
55 " i.e. either p6 or p8 is 0.",
57 " Delay time (dt) is constrained to specified value (>=0).",
59 " Error is returned if MRL check is not passed.",
61 " Speed up the fitting but increase the chance of failure, or",
62 " increase the reliability at the cost of computing time",
64 " Fitted parameters are also written in result file format.",
66 " Fitted and measured TACs are plotted in specified SVG file.",
68 " Initial part of fitted and measured TACs are plotted in SVG file",
70 " Lower part of fitted and measured TACs are plotted in SVG file",
72 " Fitted TACs are written in TAC format.",
75 "TAC file must contain at least two columns, sample times in the first,",
76 "and concentrations of TACs in the following columns.",
77 "To obtain a good fit, TAC should be corrected for physical decay and any",
78 "circulating metabolites.",
79 "Function parameters (p1, ..., dt) will be written in the parfile.",
82 "1. Feng D, Huang S-C, Wang X. Models for computer simulation studies of input",
83 " functions for tracer kinetic modeling with positron emission tomography.",
84 " Int J Biomed Comput. 1993;32:95-110.",
86 "See also: fit2dat, fit_sinf, fit_exp, fit_dexp, fit_ratf, extrapol",
88 "Keywords: curve fitting, input, modelling, simulation",
106 F_A1, F_A2, F_A3, F_A4, F_L1, F_L2, F_L3, F_L4, F_DT
111double *x, *ymeas, *yfit, *w, *ytmp;
112double func_normal(
int parNr,
double *p,
void*);
113double func_integ(
int parNr,
double *p,
void*);
114double func_normal_direct(
int parNr,
double *p,
void*);
115double func_integ_direct(
int parNr,
double *p,
void*);
122int main(
int argc,
char **argv)
124 int ai, help=0, version=0, verbose=1;
126 char tacfile[FILENAME_MAX], fitfile[FILENAME_MAX], limfile[FILENAME_MAX],
127 parfile[FILENAME_MAX], resfile[FILENAME_MAX], svgfile[FILENAME_MAX];
128 char svgfile1[FILENAME_MAX], svgfile2[FILENAME_MAX];
135 double fixed_delay=nan(
"");
141 def_pmin[F_A1]=0.0; def_pmax[F_A1]=1.0E+09;
142 def_pmin[F_A2]=0.0; def_pmax[F_A2]=1.0E+09;
143 def_pmin[F_A3]=0.0; def_pmax[F_A3]=1.0E+09;
144 def_pmin[F_A4]=0.0; def_pmax[F_A4]=1.0E+09;
145 def_pmin[F_L1]=-5.0; def_pmax[F_L1]=-0.001;
146 def_pmin[F_L2]=-5.0; def_pmax[F_L2]=-0.001;
147 def_pmin[F_L3]=-0.5; def_pmax[F_L3]=0.0;
148 def_pmin[F_L4]=-0.01; def_pmax[F_L4]=0.0;
149 def_pmin[F_DT]=0.0; def_pmax[F_DT]=5.0;
155 if(argc==1) {
tpcPrintUsage(argv[0], info, stderr);
return(1);}
156 tacfile[0]=fitfile[0]=limfile[0]=parfile[0]=resfile[0]=(char)0;
157 svgfile[0]=svgfile1[0]=svgfile2[0]=(char)0;
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(strcasecmp(cptr,
"W1")==0) {
164 }
else if(strcasecmp(cptr,
"WF")==0) {
166 }
else if(strncasecmp(cptr,
"INTEGRAL", 5)==0 || strcasecmp(cptr,
"AUC")==0) {
167 dat_type=1;
continue;
168 }
else if(strcasecmp(cptr,
"MRL")==0) {
169 MRL_check=1;
continue;
170 }
else if(strncasecmp(cptr,
"SVG=", 4)==0) {
171 if(
strlcpy(svgfile, cptr+4, FILENAME_MAX)>0)
continue;
172 }
else if(strncasecmp(cptr,
"SVG1=", 5)==0) {
173 if(
strlcpy(svgfile1, cptr+5, FILENAME_MAX)>0)
continue;
174 }
else if(strncasecmp(cptr,
"SVG2=", 5)==0) {
175 if(
strlcpy(svgfile2, cptr+5, FILENAME_MAX)>0)
continue;
176 }
else if(strncasecmp(cptr,
"FIT=", 4)==0 && strlen(cptr)>4) {
177 strlcpy(fitfile, cptr+4, FILENAME_MAX);
continue;
178 }
else if(strncasecmp(cptr,
"RES=", 4)==0 && strlen(cptr)>4) {
179 strlcpy(resfile, cptr+4, FILENAME_MAX);
continue;
180 }
else if(strncasecmp(cptr,
"EXTENDED", 1)==0) {
182 }
else if(strncasecmp(cptr,
"SIMPLIFIED", 5)==0) {
184 }
else if(strcasecmp(cptr,
"SS")==0) {
185 steadystate=1;
continue;
186 }
else if(strncasecmp(cptr,
"N=", 2)==0) {
187 cptr+=2;
if(strcasecmp(cptr,
"A")==0) {sumn=0;
continue;}
188 sumn=atoi(cptr);
if(sumn>=2 && sumn<=4)
continue;
189 }
else if(strncasecmp(cptr,
"DELAY=", 6)==0 && strlen(cptr)>6) {
190 if(!
atof_with_check(cptr+6, &fixed_delay) && fixed_delay>=0.0)
continue;
191 }
else if(strncasecmp(cptr,
"LIM=", 4)==0 && strlen(cptr)>4) {
192 strlcpy(limfile, cptr+4, FILENAME_MAX);
continue;
193 }
else if(strcasecmp(cptr,
"LIM")==0) {
194 strcpy(limfile,
"stdout");
continue;
195 }
else if(strcasecmp(cptr,
"SAFE")==0) {
197 }
else if(strcasecmp(cptr,
"NORMAL")==0) {
199 }
else if(strcasecmp(cptr,
"FAST")==0) {
202 fprintf(stderr,
"Error: invalid option '%s'.\n", argv[ai]);
207 if(help==2) {
tpcHtmlUsage(argv[0], info,
"");
return(0);}
212 if(ai<argc) {
strlcpy(tacfile, argv[ai], FILENAME_MAX); ai++;}
213 if(ai<argc) {
strlcpy(parfile, argv[ai], FILENAME_MAX); ai++;}
215 fprintf(stderr,
"Error: invalid argument '%s'.\n", argv[ai]);
218 if(!parfile[0]) strcpy(parfile,
"stdout");
223 if(limfile[0]) printf(
"limfile := %s\n", limfile);
224 printf(
"tacfile := %s\n", tacfile);
225 printf(
"parfile := %s\n", parfile);
226 printf(
"fitfile := %s\n", fitfile);
227 printf(
"resfile := %s\n", resfile);
228 printf(
"svgfile := %s\n", svgfile);
229 printf(
"svgfile1 := %s\n", svgfile1);
230 printf(
"svgfile2 := %s\n", svgfile2);
231 printf(
"MRL_check := %d\n", MRL_check);
232 printf(
"weights := %d\n", weights);
233 if(sumn>0) printf(
"sumn := %d\n", sumn);
234 printf(
"dat_type := %d\n", dat_type);
235 if(!isnan(fixed_delay)) printf(
"fixed_delay := %g\n", fixed_delay);
236 printf(
"tgo_iter_nr := %d\n", iter_nr);
242 if(limfile[0] && !tacfile[0]) {
244 if(strcasecmp(limfile,
"stdout")!=0 && access(limfile, 0) != -1) {
245 fprintf(stderr,
"Error: parameter constraint file %s exists.\n", limfile);
248 if(verbose>1 && strcasecmp(limfile,
"stdout")!=0)
249 printf(
"writing parameter constraints file\n");
252 iftPutDouble(&ift,
"A1_lower", def_pmin[F_A1], NULL, 0);
253 iftPutDouble(&ift,
"A1_upper", def_pmax[F_A1], NULL, 0);
254 iftPutDouble(&ift,
"L1_lower", def_pmin[F_L1], NULL, 0);
255 iftPutDouble(&ift,
"L1_upper", def_pmax[F_L1], NULL, 0);
256 iftPutDouble(&ift,
"A2_lower", def_pmin[F_A2], NULL, 0);
257 iftPutDouble(&ift,
"A2_upper", def_pmax[F_A2], NULL, 0);
258 iftPutDouble(&ift,
"L2_lower", def_pmin[F_L2], NULL, 0);
259 iftPutDouble(&ift,
"L2_upper", def_pmax[F_L2], NULL, 0);
260 iftPutDouble(&ift,
"A3_lower", def_pmin[F_A3], NULL, 0);
261 iftPutDouble(&ift,
"A3_upper", def_pmax[F_A3], NULL, 0);
262 iftPutDouble(&ift,
"L3_lower", def_pmin[F_L3], NULL, 0);
263 iftPutDouble(&ift,
"L3_upper", def_pmax[F_L3], NULL, 0);
264 iftPutDouble(&ift,
"A4_lower", def_pmin[F_A4], NULL, 0);
265 iftPutDouble(&ift,
"A4_upper", def_pmax[F_A4], NULL, 0);
266 iftPutDouble(&ift,
"L4_lower", def_pmin[F_L4], NULL, 0);
267 iftPutDouble(&ift,
"L4_upper", def_pmax[F_L4], NULL, 0);
268 iftPutDouble(&ift,
"DT_lower", def_pmin[F_DT], NULL, 0);
269 iftPutDouble(&ift,
"DT_upper", def_pmax[F_DT], NULL, 0);
272 fprintf(stderr,
"Error in writing '%s': %s\n", limfile, ift.
status);
275 if(strcasecmp(limfile,
"stdout")!=0)
276 fprintf(stdout,
"Parameter file %s with initial values written.\n", limfile);
283 fprintf(stderr,
"Error: missing command-line argument; use option --help\n");
294 if(verbose>1) printf(
"reading %s\n", limfile);
295 ret=
iftRead(&ift, limfile, 1, 0);
297 fprintf(stderr,
"Error in reading '%s': %s\n", limfile, ift.
status);
300 if(verbose>10)
iftWrite(&ift,
"stdout", 0);
321 if(n==0) {fprintf(stderr,
"Error: invalid parameter file.\n");
return(9);}
323 for(
int pi=0; pi<parNr; pi++)
if(def_pmax[pi]<def_pmin[pi]) {
324 double v=def_pmax[pi]; def_pmax[pi]=def_pmin[pi]; def_pmin[pi]=v;
329 fprintf(stderr,
"Error: no model parameters left free for fitting.\n");
333 if(isnan(fixed_delay)) {
335 if(fabs(def_pmax[F_DT]-def_pmin[F_DT])<1.0E-10) fixed_delay=def_pmin[F_DT];
338 def_pmax[F_DT]=def_pmin[F_DT]=fixed_delay;
341 printf(
"constraints :=");
342 for(
int pi=0; pi<9; pi++) printf(
" [%g,%g]", def_pmin[pi], def_pmax[pi]);
351 if(verbose>1) printf(
"reading %s\n", tacfile);
354 fprintf(stderr,
"Error in reading '%s': %s\n", tacfile,
dfterrmsg);
357 if(verbose>1) printf(
"checking %s\n", tacfile);
358 if(verbose>1 && tac.
voiNr>1) printf(
"tacNr := %d\n", tac.
voiNr);
365 double tstart, tstop, miny, maxy;
366 ret=
dftMinMax(&tac, &tstart, &tstop, &miny, &maxy);
368 fprintf(stderr,
"Error: invalid contents in %s\n", tacfile);
371 if(tstop<=0.0 || maxy<=0.0) {
372 fprintf(stderr,
"Error: invalid contents in %s\n", tacfile);
375 if(tstart<0.0 && verbose>0) fprintf(stderr,
"Warning: negative x value(s).\n");
376 if(miny<0.0 && verbose>0) fprintf(stderr,
"Warning: negative y value(s).\n");
378 printf(
"x_range := %g - %g\n", tstart, tstop);
379 printf(
"sample_number := %d\n", tac.
frameNr);
384 fprintf(stderr,
"Error: missing sample(s) in %s\n", tacfile);
390 int i;
for(i=tac.
frameNr-1; i>=0; i--)
if(tac.
voi[0].
y[i]>0.0)
break;
395 fprintf(stderr,
"Error: %s does not contain enough valid samples.\n", tacfile);
406 }
else if(weights==1) {
408 }
else if(weights==2) {
412 printf(
"data_weights := %g", tac.
w[0]);
413 for(
int i=1; i<tac.
frameNr; i++) printf(
", %g", tac.
w[i]);
419 if(verbose>2) printf(
"samples_in_fit := %d\n", fitDataNr);
425 if(verbose>1) printf(
"allocating memory for fit parameters.\n");
429 fprintf(stderr,
"Error: cannot allocate memory for fit parameters.\n");
435 for(
int ri=0; ri<tac.
voiNr; ri++) {
436 if(sumn==2) fit.
voi[ri].
type=1312;
437 else if(sumn==4) fit.
voi[ri].
type=1314;
447 if(verbose>0) {printf(
"fitting\n"); fflush(stdout);}
448 double (*func)(
int parNr,
double *p,
void*);
450 if(dat_type==0) func=func_normal;
else func=func_integ;
452 if(dat_type==0) func=func_normal_direct;
else func=func_integ_direct;
458 for(
int ri=0; ri<tac.
voiNr; ri++) {
459 if(tac.
voiNr>1 && verbose>0) {printf(
"."); fflush(stdout);}
462 x=tac.
x; ymeas=tac.
voi[ri].
y; yfit=tac.
voi[ri].
y2; w=tac.
w;
467 double xmax=nan(
""), ymax=nan(
"");
469 double dt=fixed_delay;
470 double lambda1=nan(
""), a1=nan(
"");
476 ret=
dftMinMaxTAC(&tac, ri, NULL, &xmax, NULL, &ymax, NULL, NULL, NULL, &imax);
478 int n=dataNr/5;
if(n<2) n=2;
479 double xstart=0.0;
if(!isnan(fixed_delay)) xstart=fixed_delay;
482 double xdmin=1.0E+10; imax=0;
483 for(
int i=0; i<dataNr; i++) {
484 double xd=fabs(x[i]-xmax);
if(xd<xdmin) {imax=i; xdmin=xd;}
488 fprintf(stderr,
"Error: invalid TAC data in %s\n", tacfile);
491 if(verbose>2) printf(
" maxy=%g max_x=%g max_i=%d\n", ymax, xmax, imax);
492 if(isnan(fixed_delay)) {
494 int i;
for(i=imax-1; i>0; i--)
if(ymeas[i]<0.5*ymax)
break;
497 dt=xmax-2.0*ht;
if(!(dt>0.0)) dt=0.0;
498 if(verbose>2) printf(
" guessed dt=%g (ht=%g)\n", dt, ht);
501 lambda1=1.0/(xmax-dt);
503 if(verbose>2) printf(
" a1=%g lambda1=%g\n", a1, lambda1);
507 if(sumn==0 || sumn==2) {
511 pmin[0]=def_pmin[F_A1]; pmax[0]=def_pmax[F_A1];
512 pmin[1]=def_pmin[F_L1]; pmax[1]=def_pmax[F_L1];
513 pmin[2]=def_pmin[F_A2]; pmax[2]=def_pmax[F_A2];
514 pmin[3]=def_pmin[F_L2]; pmax[3]=def_pmax[F_L2];
515 pmin[4]=def_pmin[F_DT]; pmax[4]=def_pmax[F_DT];
517 pmin[0]=0.25*a1; pmax[0]=20.0*a1;
518 pmin[1]=0.25*lambda1; pmax[1]=10.0*lambda1;
519 pmin[2]=0.0000001*a1; pmax[2]=50.0*a1;
520 pmin[3]=0.0000001*lambda1; pmax[3]=20.0*lambda1;
522 if(!isnan(fixed_delay)) {
523 pmin[parNr-1]=pmax[parNr-1]=fixed_delay;
525 pmin[parNr-1]=0.25*dt; pmax[parNr-1]=0.5*(dt+xmax);
529 int tgo_nr=150*parNr;
530 int neigh_nr=3*parNr;
533 ret=
tgo(pmin, pmax, func, NULL, parNr, neigh_nr, &wss, p, tgo_nr, iter_nr, verbose-5);
535 fprintf(stderr,
"Error %d in TGO.\n", ret);
539 printf(
"fitted parameters:\n");
540 for(
int i=0; i<parNr; i++)
541 printf(
"\tp%d\t%g\t(%g - %g)\n", 1+i, p[i], pmin[i], pmax[i]);
542 printf(
"\tWSS := %g\n", wss);
547 if(verbose>1) printf(
"\tChecking the MRL.\n");
550 if(m>3 && m>dataNr/3) {
551 fprintf(stderr,
"Error: bad fit.\n");
552 fprintf(stderr,
"\tMRL := %d / %d\n", m, dataNr);
555 }
else if(m>2 && m>dataNr/4) {
556 fprintf(stderr,
"\tWarning: bad fit.\n");
557 fprintf(stderr,
"\tMRL := %d / %d\n", m, dataNr);
558 }
else if(verbose>0) {
559 printf(
"\tMRL test passed.\n");
560 if(verbose>1) fprintf(stderr,
"\tMRL := %d / %d\n", m, dataNr);
563 if(m>3 && m>dataNr/3) mrl_passed=0;
571 if(verbose>2) printf(
"\tAIC := %g\n", aic);
573 for(
int i=0; i<parNr; i++) fit.
voi[ri].
p[i]=p[i];
580 if(sumn==0 || sumn==3) {
584 pmin[0]=def_pmin[F_A1]; pmax[0]=def_pmax[F_A1];
585 pmin[1]=def_pmin[F_L1]; pmax[1]=def_pmax[F_L1];
586 pmin[2]=def_pmin[F_A2]; pmax[2]=def_pmax[F_A2];
587 pmin[3]=def_pmin[F_L2]; pmax[3]=def_pmax[F_L2];
588 pmin[4]=def_pmin[F_A3]; pmax[4]=def_pmax[F_A3];
589 pmin[5]=def_pmin[F_L3]; pmax[5]=def_pmax[F_L3];
590 pmin[6]=def_pmin[F_DT]; pmax[6]=def_pmax[F_DT];
592 pmin[0]=0.5*a1; pmax[0]=10.0*a1;
593 pmin[1]=0.5*lambda1; pmax[1]=5.0*lambda1;
594 pmin[2]=0.00001*a1; pmax[2]=20.0*a1;
595 pmin[3]=0.01*lambda1; pmax[3]=10.0*lambda1;
596 pmin[4]=0.00001*ymax; pmax[4]=0.9*ymax;
597 pmin[5]=0.0; pmax[5]=0.75;
if(steadystate) pmax[5]=0.0;
599 if(!isnan(fixed_delay)) {
600 pmin[parNr-1]=pmax[parNr-1]=fixed_delay;
602 pmin[parNr-1]=0.25*dt; pmax[parNr-1]=0.5*(dt+xmax);
606 int tgo_nr=250*parNr;
607 int neigh_nr=1+2*parNr;
610 ret=
tgo(pmin, pmax, func, NULL, parNr, neigh_nr, &wss, p, tgo_nr, iter_nr, verbose-5);
612 fprintf(stderr,
"Error %d in TGO.\n", ret);
616 printf(
"fitted parameters:\n");
617 for(
int i=0; i<parNr; i++)
618 printf(
"\tp%d\t%g\t(%g - %g)\n", 1+i, p[i], pmin[i], pmax[i]);
619 printf(
"\tWSS := %g\n", wss);
624 if(verbose>1) printf(
"\tChecking the MRL.\n");
627 if(m>3 && m>dataNr/3) {
628 fprintf(stderr,
"Error: bad fit.\n");
629 fprintf(stderr,
"\tMRL := %d / %d\n", m, dataNr);
632 }
else if(m>2 && m>dataNr/4) {
633 fprintf(stderr,
"\tWarning: bad fit.\n");
634 fprintf(stderr,
"\tMRL := %d / %d\n", m, dataNr);
635 }
else if(verbose>0) {
636 printf(
"\tMRL test passed.\n");
637 if(verbose>1) fprintf(stderr,
"\tMRL := %d / %d\n", m, dataNr);
640 if(m>3 && m>dataNr/3) mrl_passed=0;
647 double laic=
aicSS(wss/a, fitDataNr,
parFreeNr(parNr, pmin, pmax));
648 if(verbose>2) printf(
"\tAIC := %g\n", laic);
649 if(sumn==3 || laic<aic) {
652 for(
int i=0; i<parNr; i++) fit.
voi[ri].
p[i]=p[i];
660 if(sumn==0 || sumn==4) {
664 pmin[0]=def_pmin[F_A1]; pmax[0]=def_pmax[F_A1];
665 pmin[1]=def_pmin[F_L1]; pmax[1]=def_pmax[F_L1];
666 pmin[2]=def_pmin[F_A2]; pmax[2]=def_pmax[F_A2];
667 pmin[3]=def_pmin[F_L2]; pmax[3]=def_pmax[F_L2];
668 pmin[4]=def_pmin[F_A3]; pmax[4]=def_pmax[F_A3];
669 pmin[5]=def_pmin[F_L3]; pmax[5]=def_pmax[F_L3];
670 pmin[6]=def_pmin[F_A4]; pmax[6]=def_pmax[F_A4];
671 pmin[7]=def_pmin[F_L4]; pmax[7]=def_pmax[F_L4];
672 pmin[8]=def_pmin[F_DT]; pmax[8]=def_pmax[F_DT];
674 if(sumn==4 || aic>1.0E+10) {
675 pmin[0]=0.5*a1; pmax[0]=10.0*a1;
676 pmin[1]=0.5*lambda1; pmax[1]=10.0*lambda1;
677 pmin[2]=0.00001*a1; pmax[2]=20.0*a1;
678 pmin[3]=0.01*lambda1; pmax[3]=10.0*lambda1;
679 pmin[4]=0.00001*ymax; pmax[4]=0.9*ymax;
680 pmin[5]=0.0001; pmax[5]=1.25;
681 pmin[6]=0.0; pmax[6]=0.9*ymax;
682 pmin[7]=0.0; pmax[7]=0.50;
if(steadystate) pmax[7]=0.0;
684 if(!isnan(fixed_delay)) {
685 pmin[parNr-1]=pmax[parNr-1]=fixed_delay;
687 pmin[parNr-1]=0.25*dt; pmax[parNr-1]=0.5*(dt+xmax);
690 pmin[0]=0.5*fit.
voi[ri].
p[0]; pmax[0]=1.2*fit.
voi[ri].
p[0];
691 pmin[1]=0.9*fit.
voi[ri].
p[1]; pmax[1]=2.5*fit.
voi[ri].
p[1];
692 pmin[2]=0.5*fit.
voi[ri].
p[2]; pmax[2]=1.2*fit.
voi[ri].
p[2];
693 pmin[3]=0.9*fit.
voi[ri].
p[3]; pmax[3]=1.5*fit.
voi[ri].
p[3];
694 pmin[4]=0.9*fit.
voi[ri].
p[4]; pmax[4]=1.2*fit.
voi[ri].
p[4];
695 pmin[5]=0.01; pmax[5]=1.10;
696 pmin[6]=0.0; pmax[6]=0.5*ymax;
697 pmin[7]=0.0; pmax[7]=0.25;
if(steadystate) pmax[7]=0.0;
699 if(!isnan(fixed_delay)) {
700 pmin[parNr-1]=pmax[parNr-1]=fixed_delay;
702 pmin[parNr-1]=0.9*fit.
voi[ri].
p[6]; pmax[parNr-1]=1.1*fit.
voi[ri].
p[6];
707 int tgo_nr=300*parNr;
708 int neigh_nr=2+2*parNr;
711 ret=
tgo(pmin, pmax, func, NULL, parNr, neigh_nr, &wss, p, tgo_nr, iter_nr, verbose-5);
713 fprintf(stderr,
"Error %d in TGO.\n", ret);
717 printf(
"fitted parameters:\n");
718 for(
int i=0; i<parNr; i++)
719 printf(
"\tp%d\t%g\t(%g - %g)\n", 1+i, p[i], pmin[i], pmax[i]);
720 printf(
"\tWSS := %g\n", wss);
725 if(verbose>1) printf(
"\tChecking the MRL.\n");
728 if(m>3 && m>dataNr/3) {
729 fprintf(stderr,
"Error: bad fit.\n");
730 fprintf(stderr,
"\tMRL := %d / %d\n", m, dataNr);
733 }
else if(m>2 && m>dataNr/4) {
734 fprintf(stderr,
"\tWarning: bad fit.\n");
735 fprintf(stderr,
"\tMRL := %d / %d\n", m, dataNr);
736 }
else if(verbose>0) {
737 printf(
"\tMRL test passed.\n");
738 if(verbose>1) fprintf(stderr,
"\tMRL := %d / %d\n", m, dataNr);
741 if(m>3 && m>dataNr/3) mrl_passed=0;
748 double laic=
aicSS(wss/a, fitDataNr,
parFreeNr(parNr, pmin, pmax));
749 if(verbose>2) printf(
"\tAIC := %g\n", laic);
750 if(sumn==4 || laic<aic) {
753 for(
int i=0; i<parNr; i++) fit.
voi[ri].
p[i]=p[i];
761 fprintf(stderr,
"Error: fitting not successful.\n");
767 for(
int pi=5; pi<fit.
voi[ri].
parNr; pi+=2) fit.
voi[ri].
p[pi]*=fit.
voi[ri].
p[pi-2];
769 for(
int pi=1; pi<fit.
voi[ri].
parNr; pi+=2) fit.
voi[ri].
p[pi]*=-1.0;
774 if(verbose>3) printf(
"\tparNr := %d\n", fit.
voi[ri].
parNr);
776 n/=2;
if(verbose>2) printf(
"\tsumn := %d\n", n);
777 if(n==2) fit.
voi[ri].
type=1312;
778 else if(n==3) fit.
voi[ri].
type=1313;
783 printf(
"Sample\tX\tY\tYfit\tWeight\n");
784 for(
int i=0; i<dataNr; i++)
785 printf(
"%d\t%9.2e\t%9.2e\t%9.2e\t%7.1e\n", 1+i, x[i], ymeas[i], yfit[i], w[i]);
789 if(tac.
voiNr>1 && verbose>0) {printf(
"\n"); fflush(stdout);}
795 if(verbose>1) printf(
"saving results in %s\n", parfile);
796 ret=
fitWrite(&fit, parfile);
if(ret) {
797 fprintf(stderr,
"Error in writing '%s': %s\n", parfile,
fiterrmsg);
800 if(verbose>0) {printf(
"Function parameters written in %s\n", parfile); fflush(stdout);}
804 if(verbose>1) {printf(
"allocating memory for results.\n"); fflush(stdout);}
809 fprintf(stderr,
"Error in making results: %s\n", buf); fflush(stderr);
814 sumn--; sumn/=2;
if(verbose>3) {printf(
" sumn=%d\n", sumn); fflush(stdout);}
816 strcpy(res.
parname[n++],
"Function");
817 for(
int i=1; i<=sumn; i++) {
818 sprintf(res.
parname[n++],
"A%d", i);
819 sprintf(res.
parname[n++],
"L%d", i);
821 strcpy(res.
parname[n++],
"dT");
822 strcpy(res.
parname[n++],
"WSS");
824 sprintf(res.
datarange,
"%g - %g", tstart, tstop);
835 if(verbose>1) {printf(
"saving results in %s\n", resfile); fflush(stdout);}
836 if(
resWrite(&res, resfile, verbose-3)) {
837 fprintf(stderr,
"Error in writing '%s': %s\n", resfile,
reserrmsg);
841 if(verbose>1) {printf(
"Function parameters written in %s\n", resfile); fflush(stdout);}
849 if(svgfile[0] || svgfile1[0] || svgfile2[0]) {
851 if(verbose>1) printf(
"calculating fitted curve at automatically generated sample times\n");
855 fprintf(stderr,
"Error %d in memory allocation for fitted curves.\n", ret);
859 if(dat_type==1)
for(
int ri=0; ri<adft.
voiNr; ri++)
861 else for(
int ri=0; ri<adft.
voiNr; ri++)
864 fprintf(stderr,
"Error: cannot calculate fitted curve for '%s'.\n", svgfile);
873 if(verbose>1) printf(
"writing %s\n", svgfile);
874 ret=
plot_fitrange_svg(&tac, &adft, tmp, 0.0, nan(
""), 0.0, nan(
""), svgfile, verbose-10);
876 fprintf(stderr,
"Error (%d) in writing '%s'.\n", ret, svgfile);
880 if(verbose>0) printf(
"Plots written in %s\n", svgfile);
884 if(dat_type==0 && (svgfile1[0] || svgfile2[0]))
885 dftMinMaxTAC(&tac, 0, NULL, &tmax, NULL, NULL, NULL, NULL, NULL, NULL);
889 if(verbose>1) printf(
"writing %s\n", svgfile1);
890 ret=
plot_fitrange_svg(&tac, &adft, tmp, 0.0, 2.*tmax, 0.0, nan(
""), svgfile1, verbose-10);
892 fprintf(stderr,
"Error (%d) in writing '%s'.\n", ret, svgfile1);
896 if(verbose>0) printf(
"Plots written in %s\n", svgfile1);
900 if(verbose>1) printf(
"writing %s\n", svgfile2);
902 nan(
""), 0.0, nan(
""), svgfile2, verbose-10);
904 fprintf(stderr,
"Error (%d) in writing '%s'.\n", ret, svgfile2);
908 if(verbose>0) printf(
"Plots written in %s\n", svgfile2);
920 if(verbose>1) printf(
"writing fitted TAC(s)\n");
922 if(dat_type==1)
for(
int ri=0; ri<tac.
voiNr; ri++)
924 else for(
int ri=0; ri<tac.
voiNr; ri++)
927 fprintf(stderr,
"Error: cannot calculate fitted curve for '%s'.\n", fitfile);
935 fprintf(stderr,
"Error: cannot write '%s'.\n", fitfile);
953double func_normal(
int parNr,
double *p,
void *fdata)
956 double A1, A2, A3, A4, L1, L2, L3, L4;
959 double e1, e2, e3, e4;
966 if(parNr==5 || parNr==7 || parNr==9) dt=pa[parNr-1];
else dt=0.0;
968 if(parNr>=6) A3=pa[4];
else A3=0.0;
969 if(parNr>=8) A4=pa[6];
else A4=0.0;
971 if(parNr>=6) L3=L2*pa[5];
else L3=0.0;
972 if(parNr>=8) L4=L3*pa[7];
else L4=0.0;
973 L1*=-1.0; L2*=-1.0; L3*=-1.0; L4*=-1.0;
976 double d= A1 + A2*L2 + A3*L3 + A4*L4 - L1*(A2+A3+A4);
977 if(d<=0.0) penalty*=100.0;
980 for(i=0, wss=0.0; i<dataNr; i++) {
990 yfit[i]=(A1*xt -A2 - A3 - A4)*e1 + A2*e2 + A3*e3 + A4*e4;
992 double v=yfit[i]-ymeas[i]; wss+=w[i]*v*v;
998double func_integ(
int parNr,
double *p,
void *fdata)
1001 double A1, A2, A3, A4, L1, L2, L3, L4;
1004 double e1, e2, e3, e4;
1011 if(parNr==5 || parNr==7 || parNr==9) dt=pa[parNr-1];
else dt=0.0;
1013 if(parNr>=6) A3=pa[4];
else A3=0.0;
1014 if(parNr>=8) A4=pa[6];
else A4=0.0;
1016 if(parNr>=6) L3=L2*pa[5];
else L3=0.0;
1017 if(parNr>=8) L4=L3*pa[7];
else L4=0.0;
1018 L1*=-1.0; L2*=-1.0; L3*=-1.0; L4*=-1.0;
1021 double d= A1 + A2*L2 + A3*L3 + A4*L4 - L1*(A2+A3+A4);
1022 if(d<=0.0) penalty*=100.0;
1025 for(i=0, wss=0.0; i<dataNr; i++) {
1032 yfit[i]+=(A2/L1)*(1.0-e1) + (A3/L1)*(1.0-e1) + (A4/L1)*(1.0-e1);
1033 yfit[i]+=(A1/(L1*L1))*(1.0 + e1*(L1*xt-1.0));
1037 yfit[i]+=(A2/L2)*(e2-1.0);
1040 yfit[i]+=(A3/L3)*(e3-1.0);
1043 yfit[i]+=(A4/L4)*(e4-1.0);
1045 double v=yfit[i]-ymeas[i]; wss+=w[i]*v*v;
1053double func_normal_direct(
int parNr,
double *p,
void *fdata)
1056 double A1, A2, A3, A4, L1, L2, L3, L4;
1059 double e1, e2, e3, e4;
1066 if(parNr==5 || parNr==7 || parNr==9) dt=pa[parNr-1];
else dt=0.0;
1068 if(parNr>=6) A3=pa[4];
else A3=0.0;
1069 if(parNr>=8) A4=pa[6];
else A4=0.0;
1071 if(parNr>=6) L3=pa[5];
else L3=0.0;
1072 if(parNr>=8) L4=pa[7];
else L4=0.0;
1075 double d= A1 + A2*L2 + A3*L3 + A4*L4 - L1*(A2+A3+A4);
1076 if(d<=0.0) penalty*=100.0;
1079 for(i=0, wss=0.0; i<dataNr; i++) {
1089 yfit[i]=(A1*xt -A2 - A3 - A4)*e1 + A2*e2 + A3*e3 + A4*e4;
1091 double v=yfit[i]-ymeas[i]; wss+=w[i]*v*v;
1097double func_integ_direct(
int parNr,
double *p,
void *fdata)
1100 double A1, A2, A3, A4, L1, L2, L3, L4;
1103 double e1, e2, e3, e4;
1110 if(parNr==5 || parNr==7 || parNr==9) dt=pa[parNr-1];
else dt=0.0;
1112 if(parNr>=6) A3=pa[4];
else A3=0.0;
1113 if(parNr>=8) A4=pa[6];
else A4=0.0;
1115 if(parNr>=6) L3=pa[5];
else L3=0.0;
1116 if(parNr>=8) L4=pa[7];
else L4=0.0;
1119 double d= A1 + A2*L2 + A3*L3 + A4*L4 - L1*(A2+A3+A4);
1120 if(d<=0.0) penalty*=100.0;
1123 for(i=0, wss=0.0; i<dataNr; i++) {
1130 yfit[i]+=(A2/L1)*(1.0-e1) + (A3/L1)*(1.0-e1) + (A4/L1)*(1.0-e1);
1131 yfit[i]+=(A1/(L1*L1))*(1.0 + e1*(L1*xt-1.0));
1135 yfit[i]+=(A2/L2)*(e2-1.0);
1138 yfit[i]+=(A3/L3)*(e3-1.0);
1141 yfit[i]+=(A4/L4)*(e4-1.0);
1143 double v=yfit[i]-ymeas[i]; wss+=w[i]*v*v;
int parFreeNr(const int n, double *pLower, double *pUpper)
Calculate the number of free parameters.
double aicSS(double ss, const int n, const int k)
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)
int dftMinMaxTAC(DFT *dft, int tacindex, double *minx, double *maxx, double *miny, double *maxy, int *mini, int *maxi, int *mins, int *maxs)
int dftSortByFrame(DFT *dft)
int dftMinMax(DFT *dft, double *minx, double *maxx, double *miny, double *maxy)
int dft_nr_of_NA(DFT *dft)
int dftRead(char *filename, DFT *data)
int dftWrite(DFT *data, char *filename)
int fitToResult(FIT *fit, RES *res, char *status)
int fit_allocate_with_dft(FIT *fit, 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)
Header file for libtpccurveio.
int fitEvaltac(FitVOI *r, double *x, double *y, int dataNr)
int fitWrite(FIT *fit, char *filename)
int resWrite(RES *res, char *filename, int verbose)
int fitIntegralEvaltac(FitVOI *r, double *x, double *yi, int dataNr)
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)
int studynr_from_fname(char *fname, char *studynr)
void tpcPrintBuild(const char *program, FILE *fp)
void tpcPrintUsage(const char *program, char *text[], FILE *fp)
Header file for libtpcmodel.
int highest_slope_after(double *x, double *y, int n, int slope_n, double x_start, double *m, double *c, double *xi, double *xh)
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)
int mrl_between_tacs(double y1[], double y2[], int n)
Header file for libtpcmodext.
int dftWSampleNr(DFT *tac)
int dftWeightByFreq(DFT *dft)
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 datafile[FILENAME_MAX]
char studynr[MAX_STUDYNR_LEN+1]
char parname[MAX_RESPARAMS][MAX_RESPARNAME_LEN+1]
double parameter[MAX_RESPARAMS]