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(
"");
140 _set_output_format(_TWO_DIGIT_EXPONENT);
145 def_pmin[F_A1]=0.0; def_pmax[F_A1]=1.0E+09;
146 def_pmin[F_A2]=0.0; def_pmax[F_A2]=1.0E+09;
147 def_pmin[F_A3]=0.0; def_pmax[F_A3]=1.0E+09;
148 def_pmin[F_A4]=0.0; def_pmax[F_A4]=1.0E+09;
149 def_pmin[F_L1]=-5.0; def_pmax[F_L1]=-0.001;
150 def_pmin[F_L2]=-5.0; def_pmax[F_L2]=-0.001;
151 def_pmin[F_L3]=-0.5; def_pmax[F_L3]=0.0;
152 def_pmin[F_L4]=-0.01; def_pmax[F_L4]=0.0;
153 def_pmin[F_DT]=0.0; def_pmax[F_DT]=5.0;
159 if(argc==1) {
tpcPrintUsage(argv[0], info, stderr);
return(1);}
160 tacfile[0]=fitfile[0]=limfile[0]=parfile[0]=resfile[0]=(char)0;
161 svgfile[0]=svgfile1[0]=svgfile2[0]=(char)0;
163 for(ai=1; ai<argc; ai++)
if(*argv[ai]==
'-') {
164 char *cptr=argv[ai]+1;
if(*cptr==
'-') cptr++;
if(cptr==NULL)
continue;
166 if(strcasecmp(cptr,
"W1")==0) {
168 }
else if(strcasecmp(cptr,
"WF")==0) {
170 }
else if(strncasecmp(cptr,
"INTEGRAL", 5)==0 || strcasecmp(cptr,
"AUC")==0) {
171 dat_type=1;
continue;
172 }
else if(strcasecmp(cptr,
"MRL")==0) {
173 MRL_check=1;
continue;
174 }
else if(strncasecmp(cptr,
"SVG=", 4)==0) {
175 if(
strlcpy(svgfile, cptr+4, FILENAME_MAX)>0)
continue;
176 }
else if(strncasecmp(cptr,
"SVG1=", 5)==0) {
177 if(
strlcpy(svgfile1, cptr+5, FILENAME_MAX)>0)
continue;
178 }
else if(strncasecmp(cptr,
"SVG2=", 5)==0) {
179 if(
strlcpy(svgfile2, cptr+5, FILENAME_MAX)>0)
continue;
180 }
else if(strncasecmp(cptr,
"FIT=", 4)==0 && strlen(cptr)>4) {
181 strlcpy(fitfile, cptr+4, FILENAME_MAX);
continue;
182 }
else if(strncasecmp(cptr,
"RES=", 4)==0 && strlen(cptr)>4) {
183 strlcpy(resfile, cptr+4, FILENAME_MAX);
continue;
184 }
else if(strncasecmp(cptr,
"EXTENDED", 1)==0) {
186 }
else if(strncasecmp(cptr,
"SIMPLIFIED", 5)==0) {
188 }
else if(strcasecmp(cptr,
"SS")==0) {
189 steadystate=1;
continue;
190 }
else if(strncasecmp(cptr,
"N=", 2)==0) {
191 cptr+=2;
if(strcasecmp(cptr,
"A")==0) {sumn=0;
continue;}
192 sumn=atoi(cptr);
if(sumn>=2 && sumn<=4)
continue;
193 }
else if(strncasecmp(cptr,
"DELAY=", 6)==0 && strlen(cptr)>6) {
194 if(!
atof_with_check(cptr+6, &fixed_delay) && fixed_delay>=0.0)
continue;
195 }
else if(strncasecmp(cptr,
"LIM=", 4)==0 && strlen(cptr)>4) {
196 strlcpy(limfile, cptr+4, FILENAME_MAX);
continue;
197 }
else if(strcasecmp(cptr,
"LIM")==0) {
198 strcpy(limfile,
"stdout");
continue;
199 }
else if(strcasecmp(cptr,
"SAFE")==0) {
201 }
else if(strcasecmp(cptr,
"NORMAL")==0) {
203 }
else if(strcasecmp(cptr,
"FAST")==0) {
206 fprintf(stderr,
"Error: invalid option '%s'.\n", argv[ai]);
211 if(help==2) {
tpcHtmlUsage(argv[0], info,
"");
return(0);}
216 if(ai<argc) {
strlcpy(tacfile, argv[ai], FILENAME_MAX); ai++;}
217 if(ai<argc) {
strlcpy(parfile, argv[ai], FILENAME_MAX); ai++;}
219 fprintf(stderr,
"Error: invalid argument '%s'.\n", argv[ai]);
222 if(!parfile[0]) strcpy(parfile,
"stdout");
227 if(limfile[0]) printf(
"limfile := %s\n", limfile);
228 printf(
"tacfile := %s\n", tacfile);
229 printf(
"parfile := %s\n", parfile);
230 printf(
"fitfile := %s\n", fitfile);
231 printf(
"resfile := %s\n", resfile);
232 printf(
"svgfile := %s\n", svgfile);
233 printf(
"svgfile1 := %s\n", svgfile1);
234 printf(
"svgfile2 := %s\n", svgfile2);
235 printf(
"MRL_check := %d\n", MRL_check);
236 printf(
"weights := %d\n", weights);
237 if(sumn>0) printf(
"sumn := %d\n", sumn);
238 printf(
"dat_type := %d\n", dat_type);
239 if(!isnan(fixed_delay)) printf(
"fixed_delay := %g\n", fixed_delay);
240 printf(
"tgo_iter_nr := %d\n", iter_nr);
246 if(limfile[0] && !tacfile[0]) {
248 if(strcasecmp(limfile,
"stdout")!=0 && access(limfile, 0) != -1) {
249 fprintf(stderr,
"Error: parameter constraint file %s exists.\n", limfile);
252 if(verbose>1 && strcasecmp(limfile,
"stdout")!=0)
253 printf(
"writing parameter constraints file\n");
256 iftPutDouble(&ift,
"A1_lower", def_pmin[F_A1], NULL, 0);
257 iftPutDouble(&ift,
"A1_upper", def_pmax[F_A1], NULL, 0);
258 iftPutDouble(&ift,
"L1_lower", def_pmin[F_L1], NULL, 0);
259 iftPutDouble(&ift,
"L1_upper", def_pmax[F_L1], NULL, 0);
260 iftPutDouble(&ift,
"A2_lower", def_pmin[F_A2], NULL, 0);
261 iftPutDouble(&ift,
"A2_upper", def_pmax[F_A2], NULL, 0);
262 iftPutDouble(&ift,
"L2_lower", def_pmin[F_L2], NULL, 0);
263 iftPutDouble(&ift,
"L2_upper", def_pmax[F_L2], NULL, 0);
264 iftPutDouble(&ift,
"A3_lower", def_pmin[F_A3], NULL, 0);
265 iftPutDouble(&ift,
"A3_upper", def_pmax[F_A3], NULL, 0);
266 iftPutDouble(&ift,
"L3_lower", def_pmin[F_L3], NULL, 0);
267 iftPutDouble(&ift,
"L3_upper", def_pmax[F_L3], NULL, 0);
268 iftPutDouble(&ift,
"A4_lower", def_pmin[F_A4], NULL, 0);
269 iftPutDouble(&ift,
"A4_upper", def_pmax[F_A4], NULL, 0);
270 iftPutDouble(&ift,
"L4_lower", def_pmin[F_L4], NULL, 0);
271 iftPutDouble(&ift,
"L4_upper", def_pmax[F_L4], NULL, 0);
272 iftPutDouble(&ift,
"DT_lower", def_pmin[F_DT], NULL, 0);
273 iftPutDouble(&ift,
"DT_upper", def_pmax[F_DT], NULL, 0);
276 fprintf(stderr,
"Error in writing '%s': %s\n", limfile, ift.
status);
279 if(strcasecmp(limfile,
"stdout")!=0)
280 fprintf(stdout,
"Parameter file %s with initial values written.\n", limfile);
287 fprintf(stderr,
"Error: missing command-line argument; use option --help\n");
298 if(verbose>1) printf(
"reading %s\n", limfile);
299 ret=
iftRead(&ift, limfile, 1, 0);
301 fprintf(stderr,
"Error in reading '%s': %s\n", limfile, ift.
status);
304 if(verbose>10)
iftWrite(&ift,
"stdout", 0);
325 if(n==0) {fprintf(stderr,
"Error: invalid parameter file.\n");
return(9);}
327 for(
int pi=0; pi<parNr; pi++)
if(def_pmax[pi]<def_pmin[pi]) {
328 double v=def_pmax[pi]; def_pmax[pi]=def_pmin[pi]; def_pmin[pi]=v;
333 fprintf(stderr,
"Error: no model parameters left free for fitting.\n");
337 if(isnan(fixed_delay)) {
339 if(fabs(def_pmax[F_DT]-def_pmin[F_DT])<1.0E-10) fixed_delay=def_pmin[F_DT];
342 def_pmax[F_DT]=def_pmin[F_DT]=fixed_delay;
345 printf(
"constraints :=");
346 for(
int pi=0; pi<9; pi++) printf(
" [%g,%g]", def_pmin[pi], def_pmax[pi]);
355 if(verbose>1) printf(
"reading %s\n", tacfile);
358 fprintf(stderr,
"Error in reading '%s': %s\n", tacfile,
dfterrmsg);
361 if(verbose>1) printf(
"checking %s\n", tacfile);
362 if(verbose>1 && tac.
voiNr>1) printf(
"tacNr := %d\n", tac.
voiNr);
369 double tstart, tstop, miny, maxy;
370 ret=
dftMinMax(&tac, &tstart, &tstop, &miny, &maxy);
372 fprintf(stderr,
"Error: invalid contents in %s\n", tacfile);
375 if(tstop<=0.0 || maxy<=0.0) {
376 fprintf(stderr,
"Error: invalid contents in %s\n", tacfile);
379 if(tstart<0.0 && verbose>0) fprintf(stderr,
"Warning: negative x value(s).\n");
380 if(miny<0.0 && verbose>0) fprintf(stderr,
"Warning: negative y value(s).\n");
382 printf(
"x_range := %g - %g\n", tstart, tstop);
383 printf(
"sample_number := %d\n", tac.
frameNr);
388 fprintf(stderr,
"Error: missing sample(s) in %s\n", tacfile);
394 int i;
for(i=tac.
frameNr-1; i>=0; i--)
if(tac.
voi[0].
y[i]>0.0)
break;
399 fprintf(stderr,
"Error: %s does not contain enough valid samples.\n", tacfile);
410 }
else if(weights==1) {
412 }
else if(weights==2) {
416 printf(
"data_weights := %g", tac.
w[0]);
417 for(
int i=1; i<tac.
frameNr; i++) printf(
", %g", tac.
w[i]);
423 if(verbose>2) printf(
"samples_in_fit := %d\n", fitDataNr);
429 if(verbose>1) printf(
"allocating memory for fit parameters.\n");
433 fprintf(stderr,
"Error: cannot allocate memory for fit parameters.\n");
439 for(
int ri=0; ri<tac.
voiNr; ri++) {
440 if(sumn==2) fit.
voi[ri].
type=1312;
441 else if(sumn==4) fit.
voi[ri].
type=1314;
451 if(verbose>0) {printf(
"fitting\n"); fflush(stdout);}
452 double (*func)(
int parNr,
double *p,
void*);
454 if(dat_type==0) func=func_normal;
else func=func_integ;
456 if(dat_type==0) func=func_normal_direct;
else func=func_integ_direct;
462 for(
int ri=0; ri<tac.
voiNr; ri++) {
463 if(tac.
voiNr>1 && verbose>0) {printf(
"."); fflush(stdout);}
466 x=tac.
x; ymeas=tac.
voi[ri].
y; yfit=tac.
voi[ri].
y2; w=tac.
w;
471 double xmax=nan(
""), ymax=nan(
"");
473 double dt=fixed_delay;
474 double lambda1=nan(
""), a1=nan(
"");
480 ret=
dftMinMaxTAC(&tac, ri, NULL, &xmax, NULL, &ymax, NULL, NULL, NULL, &imax);
482 int n=dataNr/5;
if(n<2) n=2;
483 double xstart=0.0;
if(!isnan(fixed_delay)) xstart=fixed_delay;
486 double xdmin=1.0E+10; imax=0;
487 for(
int i=0; i<dataNr; i++) {
488 double xd=fabs(x[i]-xmax);
if(xd<xdmin) {imax=i; xdmin=xd;}
492 fprintf(stderr,
"Error: invalid TAC data in %s\n", tacfile);
495 if(verbose>2) printf(
" maxy=%g max_x=%g max_i=%d\n", ymax, xmax, imax);
496 if(isnan(fixed_delay)) {
498 int i;
for(i=imax-1; i>0; i--)
if(ymeas[i]<0.5*ymax)
break;
501 dt=xmax-2.0*ht;
if(!(dt>0.0)) dt=0.0;
502 if(verbose>2) printf(
" guessed dt=%g (ht=%g)\n", dt, ht);
505 lambda1=1.0/(xmax-dt);
507 if(verbose>2) printf(
" a1=%g lambda1=%g\n", a1, lambda1);
511 if(sumn==0 || sumn==2) {
515 pmin[0]=def_pmin[F_A1]; pmax[0]=def_pmax[F_A1];
516 pmin[1]=def_pmin[F_L1]; pmax[1]=def_pmax[F_L1];
517 pmin[2]=def_pmin[F_A2]; pmax[2]=def_pmax[F_A2];
518 pmin[3]=def_pmin[F_L2]; pmax[3]=def_pmax[F_L2];
519 pmin[4]=def_pmin[F_DT]; pmax[4]=def_pmax[F_DT];
521 pmin[0]=0.25*a1; pmax[0]=20.0*a1;
522 pmin[1]=0.25*lambda1; pmax[1]=10.0*lambda1;
523 pmin[2]=0.0000001*a1; pmax[2]=50.0*a1;
524 pmin[3]=0.0000001*lambda1; pmax[3]=20.0*lambda1;
526 if(!isnan(fixed_delay)) {
527 pmin[parNr-1]=pmax[parNr-1]=fixed_delay;
529 pmin[parNr-1]=0.25*dt; pmax[parNr-1]=0.5*(dt+xmax);
533 int tgo_nr=150*parNr;
534 int neigh_nr=3*parNr;
537 ret=
tgo(pmin, pmax, func, NULL, parNr, neigh_nr, &wss, p, tgo_nr, iter_nr, verbose-5);
539 fprintf(stderr,
"Error %d in TGO.\n", ret);
543 printf(
"fitted parameters:\n");
544 for(
int i=0; i<parNr; i++)
545 printf(
"\tp%d\t%g\t(%g - %g)\n", 1+i, p[i], pmin[i], pmax[i]);
546 printf(
"\tWSS := %g\n", wss);
551 if(verbose>1) printf(
"\tChecking the MRL.\n");
554 if(m>3 && m>dataNr/3) {
555 fprintf(stderr,
"Error: bad fit.\n");
556 fprintf(stderr,
"\tMRL := %d / %d\n", m, dataNr);
559 }
else if(m>2 && m>dataNr/4) {
560 fprintf(stderr,
"\tWarning: bad fit.\n");
561 fprintf(stderr,
"\tMRL := %d / %d\n", m, dataNr);
562 }
else if(verbose>0) {
563 printf(
"\tMRL test passed.\n");
564 if(verbose>1) fprintf(stderr,
"\tMRL := %d / %d\n", m, dataNr);
567 if(m>3 && m>dataNr/3) mrl_passed=0;
575 if(verbose>2) printf(
"\tAIC := %g\n", aic);
577 for(
int i=0; i<parNr; i++) fit.
voi[ri].
p[i]=p[i];
584 if(sumn==0 || sumn==3) {
588 pmin[0]=def_pmin[F_A1]; pmax[0]=def_pmax[F_A1];
589 pmin[1]=def_pmin[F_L1]; pmax[1]=def_pmax[F_L1];
590 pmin[2]=def_pmin[F_A2]; pmax[2]=def_pmax[F_A2];
591 pmin[3]=def_pmin[F_L2]; pmax[3]=def_pmax[F_L2];
592 pmin[4]=def_pmin[F_A3]; pmax[4]=def_pmax[F_A3];
593 pmin[5]=def_pmin[F_L3]; pmax[5]=def_pmax[F_L3];
594 pmin[6]=def_pmin[F_DT]; pmax[6]=def_pmax[F_DT];
596 pmin[0]=0.5*a1; pmax[0]=10.0*a1;
597 pmin[1]=0.5*lambda1; pmax[1]=5.0*lambda1;
598 pmin[2]=0.00001*a1; pmax[2]=20.0*a1;
599 pmin[3]=0.01*lambda1; pmax[3]=10.0*lambda1;
600 pmin[4]=0.00001*ymax; pmax[4]=0.9*ymax;
601 pmin[5]=0.0; pmax[5]=0.75;
if(steadystate) pmax[5]=0.0;
603 if(!isnan(fixed_delay)) {
604 pmin[parNr-1]=pmax[parNr-1]=fixed_delay;
606 pmin[parNr-1]=0.25*dt; pmax[parNr-1]=0.5*(dt+xmax);
610 int tgo_nr=250*parNr;
611 int neigh_nr=1+2*parNr;
614 ret=
tgo(pmin, pmax, func, NULL, parNr, neigh_nr, &wss, p, tgo_nr, iter_nr, verbose-5);
616 fprintf(stderr,
"Error %d in TGO.\n", ret);
620 printf(
"fitted parameters:\n");
621 for(
int i=0; i<parNr; i++)
622 printf(
"\tp%d\t%g\t(%g - %g)\n", 1+i, p[i], pmin[i], pmax[i]);
623 printf(
"\tWSS := %g\n", wss);
628 if(verbose>1) printf(
"\tChecking the MRL.\n");
631 if(m>3 && m>dataNr/3) {
632 fprintf(stderr,
"Error: bad fit.\n");
633 fprintf(stderr,
"\tMRL := %d / %d\n", m, dataNr);
636 }
else if(m>2 && m>dataNr/4) {
637 fprintf(stderr,
"\tWarning: bad fit.\n");
638 fprintf(stderr,
"\tMRL := %d / %d\n", m, dataNr);
639 }
else if(verbose>0) {
640 printf(
"\tMRL test passed.\n");
641 if(verbose>1) fprintf(stderr,
"\tMRL := %d / %d\n", m, dataNr);
644 if(m>3 && m>dataNr/3) mrl_passed=0;
651 double laic=
aicSS(wss/a, fitDataNr,
parFreeNr(parNr, pmin, pmax));
652 if(verbose>2) printf(
"\tAIC := %g\n", laic);
653 if(sumn==3 || laic<aic) {
656 for(
int i=0; i<parNr; i++) fit.
voi[ri].
p[i]=p[i];
664 if(sumn==0 || sumn==4) {
668 pmin[0]=def_pmin[F_A1]; pmax[0]=def_pmax[F_A1];
669 pmin[1]=def_pmin[F_L1]; pmax[1]=def_pmax[F_L1];
670 pmin[2]=def_pmin[F_A2]; pmax[2]=def_pmax[F_A2];
671 pmin[3]=def_pmin[F_L2]; pmax[3]=def_pmax[F_L2];
672 pmin[4]=def_pmin[F_A3]; pmax[4]=def_pmax[F_A3];
673 pmin[5]=def_pmin[F_L3]; pmax[5]=def_pmax[F_L3];
674 pmin[6]=def_pmin[F_A4]; pmax[6]=def_pmax[F_A4];
675 pmin[7]=def_pmin[F_L4]; pmax[7]=def_pmax[F_L4];
676 pmin[8]=def_pmin[F_DT]; pmax[8]=def_pmax[F_DT];
678 if(sumn==4 || aic>1.0E+10) {
679 pmin[0]=0.5*a1; pmax[0]=10.0*a1;
680 pmin[1]=0.5*lambda1; pmax[1]=10.0*lambda1;
681 pmin[2]=0.00001*a1; pmax[2]=20.0*a1;
682 pmin[3]=0.01*lambda1; pmax[3]=10.0*lambda1;
683 pmin[4]=0.00001*ymax; pmax[4]=0.9*ymax;
684 pmin[5]=0.0001; pmax[5]=1.25;
685 pmin[6]=0.0; pmax[6]=0.9*ymax;
686 pmin[7]=0.0; pmax[7]=0.50;
if(steadystate) pmax[7]=0.0;
688 if(!isnan(fixed_delay)) {
689 pmin[parNr-1]=pmax[parNr-1]=fixed_delay;
691 pmin[parNr-1]=0.25*dt; pmax[parNr-1]=0.5*(dt+xmax);
694 pmin[0]=0.5*fit.
voi[ri].
p[0]; pmax[0]=1.2*fit.
voi[ri].
p[0];
695 pmin[1]=0.9*fit.
voi[ri].
p[1]; pmax[1]=2.5*fit.
voi[ri].
p[1];
696 pmin[2]=0.5*fit.
voi[ri].
p[2]; pmax[2]=1.2*fit.
voi[ri].
p[2];
697 pmin[3]=0.9*fit.
voi[ri].
p[3]; pmax[3]=1.5*fit.
voi[ri].
p[3];
698 pmin[4]=0.9*fit.
voi[ri].
p[4]; pmax[4]=1.2*fit.
voi[ri].
p[4];
699 pmin[5]=0.01; pmax[5]=1.10;
700 pmin[6]=0.0; pmax[6]=0.5*ymax;
701 pmin[7]=0.0; pmax[7]=0.25;
if(steadystate) pmax[7]=0.0;
703 if(!isnan(fixed_delay)) {
704 pmin[parNr-1]=pmax[parNr-1]=fixed_delay;
706 pmin[parNr-1]=0.9*fit.
voi[ri].
p[6]; pmax[parNr-1]=1.1*fit.
voi[ri].
p[6];
711 int tgo_nr=300*parNr;
712 int neigh_nr=2+2*parNr;
715 ret=
tgo(pmin, pmax, func, NULL, parNr, neigh_nr, &wss, p, tgo_nr, iter_nr, verbose-5);
717 fprintf(stderr,
"Error %d in TGO.\n", ret);
721 printf(
"fitted parameters:\n");
722 for(
int i=0; i<parNr; i++)
723 printf(
"\tp%d\t%g\t(%g - %g)\n", 1+i, p[i], pmin[i], pmax[i]);
724 printf(
"\tWSS := %g\n", wss);
729 if(verbose>1) printf(
"\tChecking the MRL.\n");
732 if(m>3 && m>dataNr/3) {
733 fprintf(stderr,
"Error: bad fit.\n");
734 fprintf(stderr,
"\tMRL := %d / %d\n", m, dataNr);
737 }
else if(m>2 && m>dataNr/4) {
738 fprintf(stderr,
"\tWarning: bad fit.\n");
739 fprintf(stderr,
"\tMRL := %d / %d\n", m, dataNr);
740 }
else if(verbose>0) {
741 printf(
"\tMRL test passed.\n");
742 if(verbose>1) fprintf(stderr,
"\tMRL := %d / %d\n", m, dataNr);
745 if(m>3 && m>dataNr/3) mrl_passed=0;
752 double laic=
aicSS(wss/a, fitDataNr,
parFreeNr(parNr, pmin, pmax));
753 if(verbose>2) printf(
"\tAIC := %g\n", laic);
754 if(sumn==4 || laic<aic) {
757 for(
int i=0; i<parNr; i++) fit.
voi[ri].
p[i]=p[i];
765 fprintf(stderr,
"Error: fitting not successful.\n");
771 for(
int pi=5; pi<fit.
voi[ri].
parNr; pi+=2) fit.
voi[ri].
p[pi]*=fit.
voi[ri].
p[pi-2];
773 for(
int pi=1; pi<fit.
voi[ri].
parNr; pi+=2) fit.
voi[ri].
p[pi]*=-1.0;
778 if(verbose>3) printf(
"\tparNr := %d\n", fit.
voi[ri].
parNr);
780 n/=2;
if(verbose>2) printf(
"\tsumn := %d\n", n);
781 if(n==2) fit.
voi[ri].
type=1312;
782 else if(n==3) fit.
voi[ri].
type=1313;
787 printf(
"Sample\tX\tY\tYfit\tWeight\n");
788 for(
int i=0; i<dataNr; i++)
789 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]);
793 if(tac.
voiNr>1 && verbose>0) {printf(
"\n"); fflush(stdout);}
799 if(verbose>1) printf(
"saving results in %s\n", parfile);
800 ret=
fitWrite(&fit, parfile);
if(ret) {
801 fprintf(stderr,
"Error in writing '%s': %s\n", parfile,
fiterrmsg);
804 if(verbose>0) {printf(
"Function parameters written in %s\n", parfile); fflush(stdout);}
808 if(verbose>1) {printf(
"allocating memory for results.\n"); fflush(stdout);}
813 fprintf(stderr,
"Error in making results: %s\n", buf); fflush(stderr);
818 sumn--; sumn/=2;
if(verbose>3) {printf(
" sumn=%d\n", sumn); fflush(stdout);}
820 strcpy(res.
parname[n++],
"Function");
821 for(
int i=1; i<=sumn; i++) {
822 sprintf(res.
parname[n++],
"A%d", i);
823 sprintf(res.
parname[n++],
"L%d", i);
825 strcpy(res.
parname[n++],
"dT");
826 strcpy(res.
parname[n++],
"WSS");
828 sprintf(res.
datarange,
"%g - %g", tstart, tstop);
839 if(verbose>1) {printf(
"saving results in %s\n", resfile); fflush(stdout);}
840 if(
resWrite(&res, resfile, verbose-3)) {
841 fprintf(stderr,
"Error in writing '%s': %s\n", resfile,
reserrmsg);
845 if(verbose>1) {printf(
"Function parameters written in %s\n", resfile); fflush(stdout);}
853 if(svgfile[0] || svgfile1[0] || svgfile2[0]) {
855 if(verbose>1) printf(
"calculating fitted curve at automatically generated sample times\n");
859 fprintf(stderr,
"Error %d in memory allocation for fitted curves.\n", ret);
863 if(dat_type==1)
for(
int ri=0; ri<adft.
voiNr; ri++)
865 else for(
int ri=0; ri<adft.
voiNr; ri++)
868 fprintf(stderr,
"Error: cannot calculate fitted curve for '%s'.\n", svgfile);
877 if(verbose>1) printf(
"writing %s\n", svgfile);
878 ret=
plot_fitrange_svg(&tac, &adft, tmp, 0.0, nan(
""), 0.0, nan(
""), svgfile, verbose-10);
880 fprintf(stderr,
"Error (%d) in writing '%s'.\n", ret, svgfile);
884 if(verbose>0) printf(
"Plots written in %s\n", svgfile);
888 if(dat_type==0 && (svgfile1[0] || svgfile2[0]))
889 dftMinMaxTAC(&tac, 0, NULL, &tmax, NULL, NULL, NULL, NULL, NULL, NULL);
893 if(verbose>1) printf(
"writing %s\n", svgfile1);
894 ret=
plot_fitrange_svg(&tac, &adft, tmp, 0.0, 2.*tmax, 0.0, nan(
""), svgfile1, verbose-10);
896 fprintf(stderr,
"Error (%d) in writing '%s'.\n", ret, svgfile1);
900 if(verbose>0) printf(
"Plots written in %s\n", svgfile1);
904 if(verbose>1) printf(
"writing %s\n", svgfile2);
906 nan(
""), 0.0, nan(
""), svgfile2, verbose-10);
908 fprintf(stderr,
"Error (%d) in writing '%s'.\n", ret, svgfile2);
912 if(verbose>0) printf(
"Plots written in %s\n", svgfile2);
924 if(verbose>1) printf(
"writing fitted TAC(s)\n");
926 if(dat_type==1)
for(
int ri=0; ri<tac.
voiNr; ri++)
928 else for(
int ri=0; ri<tac.
voiNr; ri++)
931 fprintf(stderr,
"Error: cannot calculate fitted curve for '%s'.\n", fitfile);
939 fprintf(stderr,
"Error: cannot write '%s'.\n", fitfile);
957double func_normal(
int parNr,
double *p,
void *fdata)
960 double A1, A2, A3, A4, L1, L2, L3, L4;
963 double e1, e2, e3, e4;
970 if(parNr==5 || parNr==7 || parNr==9) dt=pa[parNr-1];
else dt=0.0;
972 if(parNr>=6) A3=pa[4];
else A3=0.0;
973 if(parNr>=8) A4=pa[6];
else A4=0.0;
975 if(parNr>=6) L3=L2*pa[5];
else L3=0.0;
976 if(parNr>=8) L4=L3*pa[7];
else L4=0.0;
977 L1*=-1.0; L2*=-1.0; L3*=-1.0; L4*=-1.0;
980 double d= A1 + A2*L2 + A3*L3 + A4*L4 - L1*(A2+A3+A4);
981 if(d<=0.0) penalty*=100.0;
984 for(i=0, wss=0.0; i<dataNr; i++) {
994 yfit[i]=(A1*xt -A2 - A3 - A4)*e1 + A2*e2 + A3*e3 + A4*e4;
996 double v=yfit[i]-ymeas[i]; wss+=w[i]*v*v;
1002double func_integ(
int parNr,
double *p,
void *fdata)
1005 double A1, A2, A3, A4, L1, L2, L3, L4;
1008 double e1, e2, e3, e4;
1015 if(parNr==5 || parNr==7 || parNr==9) dt=pa[parNr-1];
else dt=0.0;
1017 if(parNr>=6) A3=pa[4];
else A3=0.0;
1018 if(parNr>=8) A4=pa[6];
else A4=0.0;
1020 if(parNr>=6) L3=L2*pa[5];
else L3=0.0;
1021 if(parNr>=8) L4=L3*pa[7];
else L4=0.0;
1022 L1*=-1.0; L2*=-1.0; L3*=-1.0; L4*=-1.0;
1025 double d= A1 + A2*L2 + A3*L3 + A4*L4 - L1*(A2+A3+A4);
1026 if(d<=0.0) penalty*=100.0;
1029 for(i=0, wss=0.0; i<dataNr; i++) {
1036 yfit[i]+=(A2/L1)*(1.0-e1) + (A3/L1)*(1.0-e1) + (A4/L1)*(1.0-e1);
1037 yfit[i]+=(A1/(L1*L1))*(1.0 + e1*(L1*xt-1.0));
1041 yfit[i]+=(A2/L2)*(e2-1.0);
1044 yfit[i]+=(A3/L3)*(e3-1.0);
1047 yfit[i]+=(A4/L4)*(e4-1.0);
1049 double v=yfit[i]-ymeas[i]; wss+=w[i]*v*v;
1057double func_normal_direct(
int parNr,
double *p,
void *fdata)
1060 double A1, A2, A3, A4, L1, L2, L3, L4;
1063 double e1, e2, e3, e4;
1070 if(parNr==5 || parNr==7 || parNr==9) dt=pa[parNr-1];
else dt=0.0;
1072 if(parNr>=6) A3=pa[4];
else A3=0.0;
1073 if(parNr>=8) A4=pa[6];
else A4=0.0;
1075 if(parNr>=6) L3=pa[5];
else L3=0.0;
1076 if(parNr>=8) L4=pa[7];
else L4=0.0;
1079 double d= A1 + A2*L2 + A3*L3 + A4*L4 - L1*(A2+A3+A4);
1080 if(d<=0.0) penalty*=100.0;
1083 for(i=0, wss=0.0; i<dataNr; i++) {
1093 yfit[i]=(A1*xt -A2 - A3 - A4)*e1 + A2*e2 + A3*e3 + A4*e4;
1095 double v=yfit[i]-ymeas[i]; wss+=w[i]*v*v;
1101double func_integ_direct(
int parNr,
double *p,
void *fdata)
1104 double A1, A2, A3, A4, L1, L2, L3, L4;
1107 double e1, e2, e3, e4;
1114 if(parNr==5 || parNr==7 || parNr==9) dt=pa[parNr-1];
else dt=0.0;
1116 if(parNr>=6) A3=pa[4];
else A3=0.0;
1117 if(parNr>=8) A4=pa[6];
else A4=0.0;
1119 if(parNr>=6) L3=pa[5];
else L3=0.0;
1120 if(parNr>=8) L4=pa[7];
else L4=0.0;
1123 double d= A1 + A2*L2 + A3*L3 + A4*L4 - L1*(A2+A3+A4);
1124 if(d<=0.0) penalty*=100.0;
1127 for(i=0, wss=0.0; i<dataNr; i++) {
1134 yfit[i]+=(A2/L1)*(1.0-e1) + (A3/L1)*(1.0-e1) + (A4/L1)*(1.0-e1);
1135 yfit[i]+=(A1/(L1*L1))*(1.0 + e1*(L1*xt-1.0));
1139 yfit[i]+=(A2/L2)*(e2-1.0);
1142 yfit[i]+=(A3/L3)*(e3-1.0);
1145 yfit[i]+=(A4/L4)*(e4-1.0);
1147 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]