9#include "tpcclibConfig.h"
27enum {MODEL_UNKNOWN, MODEL_PF, MODEL_HILL, MODEL_GCDF, MODEL_EP, MODEL_MPF, MODEL_MHILL};
28int model=MODEL_UNKNOWN;
29int func_par_nr[MAX_FUNC_NR]={0,5,5,5,6,5,5};
30int func_type[MAX_FUNC_NR]={0,MF_EMAYER_PAR,MF_EHILL_PAR,MF_PPFIGAM,MF_PF_MU,MF_PF3M_PAR,MF_HILL3M_PAR};
31double func_pf(
int parNr,
double *p,
void*);
32double func_hill(
int parNr,
double *p,
void*);
33double func_gcdf(
int parNr,
double *p,
void*);
34double func_ep(
int parNr,
double *p,
void*);
35double func_mpf(
int parNr,
double *p,
void*);
36double func_mhill(
int parNr,
double *p,
void*);
37double (*func_list[MAX_FUNC_NR])(
int parNr,
double *p,
void*)=
38 {NULL,func_pf,func_hill,func_gcdf,func_ep,func_mpf,func_mhill};
40#define MAX_MINMEAS_NR 4
41enum {MINMEAS_UNKNOWN, MINMEAS_OLS, MINMEAS_LAD, MINMEAS_ODR};
42int min_meas=MINMEAS_UNKNOWN;
44double *x, *ymeas[1+MAX_METAB_NR], *yfit[1+MAX_METAB_NR], *w;
45int origdataNr=0, fitdataNr=0, parNr=5, metabNr=0;
46double frwgt[1+MAX_METAB_NR];
52static char *info[] = {
53 "Fits an empirical function to plasma parent (unchanged) tracer",
54 "fraction curve (1), where the fractions are between 0 and 1.",
56 "Usage: @P [Options] fractionfile [fitfile]",
59 " -model=<PF | HILL | GCDF | EP | MPF | MHILL>",
60 " Select the function (see descriptions below); default is HILL.",
61 " Use MPF or MHILL to fit functions to 2-3 metabolite fraction curves",
62 " instead of parent fraction curve.",
67 " -min=<OLS|LAD|ODR>",
68 " Sum-of-squares (ordinal least squares, OLS) is minimized by default,",
69 " but optionally, sum of absolute deviations (LAD), or",
70 " sum-of-squares of Akaho distances (orthogonal distances, ODR) ",
71 " can be selected. ODR can be used only with PF and HILL.",
73 " Set the lower limit for delay parameter.",
74 " -mdelay=<separated | joint>",
75 " Delay parameter for each metabolite is fitted separately, or",
76 " all metabolites are assumed to share common delay time (default).",
78 " Parent fraction at time zero is fixed to zero sample, if available.",
79 " -a=<value>, -b=<value>, -c=<value>, ...",
80 " Specified parameter is fixed to given (population mean) value.",
81 " Option -fix0 overrides other options when possible.",
83 " The last data column contains sample weights.",
85 " All weights are set to 1.0 (no weighting)",
87 " Less frequent samples are given more weight.",
88 " -WP=<weight>, -WM1=<weight>, -WM2=<weight>, -WM3=<weight>",
89 " Put additional or less weight to parent and/or metabolite fractions.",
91 " Some fractions are known to exceed 1, not divided by 100.",
93 " Error is returned if MRL check is not passed.",
95 " Fitted and measured TACs are plotted in specified SVG file.",
98 "Fraction datafile must contain at least two columns: sample times (min) and",
99 "fractions of parent tracer. Fractions of 1-3 metabolites can be given in",
100 "additional columns. Weights column can be given as specified in",
101 "DFT format (2) or with option -wc.",
102 "Program writes the fit start and end times, nr of points, WSS,",
103 "and parameters of the fitted function to the FIT file (3).",
105 "Available functions:",
106 "PF - extended power function (1,4,5)",
107 " f(x) = {D^(-1/C) + (A*(x-E))^B }^-C , when x>E,",
108 " f(x) = D , when x<=E ,",
109 " where 0<A<=1, B>1.5, C>0, 0<D<=1, 0<=E.",
110 " With option -d=1 this is essentially the same function as proposed in (4)",
111 " or with options -b=2 -d=1 -e=0 the same as suggested in (5).",
112 "HILL - Extended Hill type function (1,6)",
113 " f(x) = D - {(D-A)(x-E)^B}/{C+(x-E)^B} , when x>E,",
114 " f(x) = D , when x<=E ,",
115 " where 0<=A<=D, 1<=B, 0<C, 0<D<=1, 0<=E.",
116 " With options -d=1 -e=0 this is the traditional Hill type function (6)",
117 " f(x) = 1 - {(1-A)x^B}/(C+x^B)",
118 " where C>0<=A<=D, 1<=B, 0<C, 0<D<=1, 0<=E.",
119 "GCDF - Inverted Gamma CDF (7)",
120 " f(x) = A{1-B*gcdf(C(x-E),D)}, where 0<A<=1,0<=B<=1,C>0,D>0.",
121 "EP - Exponential/Power function based on Mu et al (8)",
122 " f(x) = B*(C*exp(-D*(x-A)^3/(E+(x-A)^2)) + (1-C)*exp(-F*(x-A))), when x>A,",
123 " f(x) = B , when x<=A ,",
124 "MPF - Extended power function is fitted to 1-3 metabolite fractions.",
125 "MHILL - Extended Hill type function is fitted to 1-3 metabolite fractions.",
128 "1. Fitting the fractions of parent tracer in plasma.",
129 " https://www.turkupetcentre.net/petanalysis/input_parent_fitting.html",
130 "2. https://www.turkupetcentre.net/petanalysis/format_tpc_dft.html",
131 "3. https://www.turkupetcentre.net/petanalysis/format_tpc_fit.html",
132 "4. Meyer PT, et al. J Cereb Blood Flow Metab. 2004;24(3):323-333.",
133 " https://doi.org/10.1097/01.wcb.0000110531.48786.9d",
134 "5. Watabe H, et al. J Cereb Blood Flow Metab 2000;20:899-909.",
135 " https://doi.org/10.1097/00004647-200006000-00002",
136 "6. Wu S, et al. J Nucl Med 2007;48:926-931.",
137 " https://doi.org/10.2967/jnumed.106.038075",
138 "7. Naganawa M, et al. J Cereb Blood Flow Metab. 2014;34:1818-1825.",
139 " https://doi.org/10.1038/jcbfm.2014.150",
140 "8. Mu L et al. EJNMMI Res. 2020;10:114.",
141 " https://doi.org/10.1186/s13550-020-00700-7",
143 "See also: fit2dat, metabcor, avgfract, fitedit, fit_fexp, fith2met, tac2svg",
145 "Keywords: input, plasma, modelling, simulation, metabolite correction",
164int main(
int argc,
char **argv)
166 int ai, help=0, version=0, verbose=1;
167 int fi, pi, ri, type=0, ret, m, n;
168 int noDivide=0, last_col_is_weight=0;
171 double min_delay=-1.0;
173 int delay_par_index=0;
174 int iscale_par_index=0;
178 char *cptr, dfile[FILENAME_MAX], ffile[FILENAME_MAX],
179 svgfile[FILENAME_MAX];
182 double a, b, tstart, tstop, maxfract, aic;
188 _set_output_format(_TWO_DIGIT_EXPONENT);
195 for(m=0; m<=MAX_METAB_NR; m++) frwgt[m]=1.0;
201 if(argc==1) {
tpcPrintUsage(argv[0], info, stderr);
return(1);}
203 dfile[0]=ffile[0]=svgfile[0]=(char)0;
205 for(ai=1; ai<argc; ai++)
if(*argv[ai]==
'-') {
206 cptr=argv[ai]+1;
if(*cptr==
'-') cptr++;
if(cptr==NULL)
continue;
208 if(strncasecmp(cptr,
"MODEL=", 6)==0) {
210 if(strncasecmp(cptr,
"PF", 1)==0) {model=MODEL_PF;
continue;}
211 if(strcasecmp(cptr,
"HILL2")==0) {model=MODEL_HILL; ffile_type=2;
continue;}
212 if(strncasecmp(cptr,
"HILL", 1)==0) {model=MODEL_HILL;
continue;}
213 if(strncasecmp(cptr,
"GCDF", 1)==0) {model=MODEL_GCDF;
continue;}
214 if(strcasecmp(cptr,
"EP")==0) {model=MODEL_EP;
continue;}
215 if(strncasecmp(cptr,
"MPF", 3)==0) {model=MODEL_MPF;
continue;}
216 if(strncasecmp(cptr,
"MHILL", 3)==0) {model=MODEL_MHILL;
continue;}
217 fprintf(stderr,
"Error: invalid model selection.\n");
return(1);
218 }
else if(strcasecmp(cptr,
"ND")==0) {
219 noDivide=1;
continue;
220 }
else if(strcasecmp(cptr,
"W1")==0) {
221 weighting=1;
continue;
222 }
else if(strcasecmp(cptr,
"WF")==0) {
223 weighting=2;
continue;
224 }
else if(strcasecmp(cptr,
"WC")==0) {
225 last_col_is_weight=1;
continue;
226 }
else if(strncasecmp(cptr,
"WP=", 3)==0) {
227 frwgt[0]=
atof_dpi(cptr+3);
if(frwgt[0]>=0.0)
continue;
228 }
else if(strncasecmp(cptr,
"WM1=", 4)==0) {
229 frwgt[1]=
atof_dpi(cptr+4);
if(frwgt[1]>=0.0)
continue;
230 }
else if(strncasecmp(cptr,
"WM2=", 4)==0) {
231 frwgt[2]=
atof_dpi(cptr+4);
if(frwgt[2]>=0.0)
continue;
232 }
else if(strncasecmp(cptr,
"WM3=", 4)==0) {
233 frwgt[3]=
atof_dpi(cptr+4);
if(frwgt[3]>=0.0)
continue;
234 }
else if(strncasecmp(cptr,
"A=", 2)==0) {
235 fixed_p[0]=
atof_dpi(cptr+2);
if(fixed_p[0]>=0.0)
continue;
236 }
else if(strncasecmp(cptr,
"B=", 2)==0) {
237 fixed_p[1]=
atof_dpi(cptr+2);
if(fixed_p[1]>=0.0)
continue;
238 }
else if(strncasecmp(cptr,
"C=", 2)==0) {
239 fixed_p[2]=
atof_dpi(cptr+2);
if(fixed_p[2]>=0.0)
continue;
240 }
else if(strncasecmp(cptr,
"D=", 2)==0) {
241 fixed_p[3]=
atof_dpi(cptr+2);
if(fixed_p[3]>=0.0)
continue;
242 }
else if(strncasecmp(cptr,
"E=", 2)==0) {
243 fixed_p[4]=
atof_dpi(cptr+2);
if(fixed_p[4]>=0.0)
continue;
244 }
else if(strncasecmp(cptr,
"F=", 2)==0) {
245 fixed_p[5]=
atof_dpi(cptr+2);
if(fixed_p[5]>=0.0)
continue;
246 }
else if(strncasecmp(cptr,
"DELAYMIN=", 9)==0) {
247 min_delay=
atof_dpi(cptr+9);
if(min_delay>=0.0)
continue;
248 }
else if(strcasecmp(cptr,
"FIX0")==0 || strcasecmp(cptr,
"FIXED0")==0) {
250 }
else if(strcasecmp(cptr,
"MRL")==0) {
251 MRL_check=1;
continue;
252 }
else if(strncasecmp(cptr,
"MDELAY=", 7)==0) {
254 if(strncasecmp(cptr,
"JOINT", 1)==0) {mdelay_joint=1;
continue;}
255 if(strncasecmp(cptr,
"SEPARATED", 1)==0) {mdelay_joint=0;
continue;}
256 fprintf(stderr,
"Error: invalid mdelay selection.\n");
return(1);
257 }
else if(strncasecmp(cptr,
"SVG=", 4)==0 && strlen(cptr)>4) {
258 strlcpy(svgfile, cptr+4, FILENAME_MAX);
continue;
259 }
else if(strncasecmp(cptr,
"MIN=", 4)==0) {
261 if(strcasecmp(cptr,
"OLS")==0 || strcasecmp(cptr,
"SS")==0 || strcasecmp(cptr,
"WSS")==0) {
262 min_meas=MINMEAS_OLS;
continue;}
263 if(strcasecmp(cptr,
"LAD")==0 || strcasecmp(cptr,
"ABS")==0 || strcasecmp(cptr,
"WABS")==0) {
264 min_meas=MINMEAS_LAD;
continue;}
265 if(strcasecmp(cptr,
"ODR")==0) {
266 min_meas=MINMEAS_ODR;
continue;}
267 fprintf(stderr,
"Error: invalid minimization measure.\n");
return(1);
269 fprintf(stderr,
"Error: invalid option '%s'.\n", argv[ai]);
274 if(help==2) {
tpcHtmlUsage(argv[0], info,
"");
return(0);}
279 if(ai<argc)
strlcpy(dfile, argv[ai++], FILENAME_MAX);
280 if(ai<argc)
strlcpy(ffile, argv[ai++], FILENAME_MAX);
281 if(ai<argc) {fprintf(stderr,
"Error: too many arguments: '%s'.\n", argv[ai]);
return(1);}
285 fprintf(stderr,
"Error: missing command-line argument; use option --help\n");
289 if(model==MODEL_UNKNOWN) model=MODEL_HILL;
290 if(min_meas==MINMEAS_UNKNOWN) min_meas=MINMEAS_OLS;
292 if(min_meas==MINMEAS_ODR) {
293 if(model!=MODEL_HILL && model!=MODEL_PF) {
294 fprintf(stderr,
"Warning: ODR is not available with selected model.\n");
295 fprintf(stderr,
"Note: using OLS instead of ODR.\n");
296 min_meas=MINMEAS_OLS;
300 type=func_type[model];
301 if(model==MODEL_HILL && ffile_type==2) type=MF_EHILL2_PAR;
302 parNr=func_par_nr[model];
303 delay_par_index=parNr-1;
304 if(model!=MODEL_GCDF) iscale_par_index=parNr-2;
305 if(model==MODEL_EP) {delay_par_index=0; iscale_par_index=1;}
306 for(pi=0, n=0; pi<parNr; pi++)
if(fixed_p[pi]>=0.0) n++;
308 fprintf(stderr,
"Error: too many parameters were fixed.\n");
311 if(fixed_p[delay_par_index]>=0.0 && mdelay_joint==0)
312 fprintf(stderr,
"Warning: option -mdelay is not effective with option -e\n");
313 if(!ffile[0]) strcpy(ffile,
"stdout");
318 printf(
"dfile := %s\n", dfile);
319 printf(
"ffile := %s\n", ffile);
320 printf(
"svgfile := %s\n", svgfile);
321 printf(
"noDivide := %d\n", noDivide);
322 printf(
"weighting := %d\n", weighting);
323 printf(
"mdelay_joint := %d\n", mdelay_joint);
324 printf(
"last_col_is_weight := %d\n", last_col_is_weight);
325 printf(
"model := %d\n", model);
326 printf(
"type := %d\n", type);
327 printf(
"parNr := %d\n", parNr);
328 printf(
"min_meas := %d\n", min_meas);
329 for(pi=0; pi<parNr; pi++)
if(fixed_p[pi]>=0.0) printf(
"fixed_p[%d] := %g\n", pi, fixed_p[pi]);
330 if(min_delay>=0.0) printf(
"min_delay := %g\n", min_delay);
331 printf(
"fixed0 := %d\n", fixed0);
332 printf(
"MRL_check := %d\n", MRL_check);
333 for(m=0; m<=MAX_METAB_NR; m++) printf(
"frwgt[%d] := %g\n", m, frwgt[m]);
341 if(verbose>1) printf(
"reading %s\n", dfile);
343 fprintf(stderr,
"Error in reading '%s': %s\n", dfile,
dfterrmsg);
349 if(last_col_is_weight!=0) {
350 if(verbose>1) printf(
"reading weights from the last column.\n");
352 fprintf(stderr,
"Error: no column for weights in %s\n", dfile);
355 for(fi=0; fi<dft.
frameNr; fi++) {
357 if(isnan(dft.
w[fi])) dft.
w[fi]=0.0;
364 printf(
"study_number := %s\n", dft.
studynr);
365 printf(
"tacNr := %d\n", dft.
voiNr);
373 if(verbose>1) printf(
"Sample times are converted to min\n");
381 if(model==MODEL_PF || model==MODEL_HILL || model==MODEL_GCDF || model==MODEL_EP) {
383 fprintf(stderr,
"Warning: extra columns in %s are ignored.\n", dfile);
388 if(verbose>1) printf(
"calculating metabolite fractions\n");
391 fprintf(stderr,
"Error: cannot allocate memory for metabolite.\n");
396 }
else if(dft.
voiNr>(1+MAX_METAB_NR)) {
398 for(fi=0; fi<dft.
frameNr; fi++)
for(ri=1+MAX_METAB_NR; ri<dft.
voiNr; ri++)
400 if(isnan(dft.
voi[ri].
y[fi]))
continue;
401 if(isnan(dft.
voi[MAX_METAB_NR].
y[fi])) {
402 dft.
voi[MAX_METAB_NR].
y[fi]=dft.
voi[ri].
y[fi];
continue;}
403 dft.
voi[MAX_METAB_NR].
y[fi]+=dft.
voi[ri].
y[fi];
405 fprintf(stderr,
"Warning: extra metabolite(s) are summed in Metab3.\n");
406 dft.
voiNr=1+MAX_METAB_NR;
409 metabNr=dft.
voiNr-1;
if(metabNr>MAX_METAB_NR) metabNr=MAX_METAB_NR;
410 if(verbose>1) printf(
"metabNr := %d\n", metabNr);
414 if(strlen(dft.
voi[0].
name)==0) {
415 strcpy(dft.
voi[0].
name,
"Parent");
418 for(ri=1; ri<dft.
voiNr; ri++)
if(strlen(dft.
voi[ri].
name)==0) {
419 strcpy(dft.
voi[ri].
name,
"Metab1");
425 fitdataNr=origdataNr;
427 fprintf(stderr,
"Error: too few samples for fitting in %s\n", dfile);
433 ret=
dftMinMax(&dft, &tstart, &tstop, NULL, &maxfract);
435 fprintf(stderr,
"Error: invalid contents in %s\n", dfile);
438 if(verbose>2) printf(
"max := %g\n", maxfract);
440 if(tstart<0.0 || !(tstop>tstart)) {
441 fprintf(stderr,
"Error: invalid sample times.\n");
445 if(maxfract>100.0 || maxfract<0.001) {
446 fprintf(stderr,
"Error: invalid fraction values.\n");
449 if(noDivide==0 && maxfract>1.0) {
450 fprintf(stderr,
"Warning: converting percentages to fractions.\n");
451 for(fi=0; fi<origdataNr; fi++)
for(ri=0; ri<dft.
voiNr; ri++)
452 if(!isnan(dft.
voi[ri].
y[fi])) dft.
voi[ri].
y[fi]/=100.0;
459 if(dft.
isweight==0 || weighting==1) {
461 for(fi=0; fi<dft.
frameNr; fi++) dft.
w[fi]=1.0;
467 for(fi=0; fi<dft.
frameNr; fi++)
if(isnan(dft.
voi[0].
y[fi])) dft.
w[fi]=0;
469 printf(
"data_weights := %g", dft.
w[0]);
470 for(fi=1; fi<dft.
frameNr; fi++) printf(
", %g", dft.
w[fi]);
478 if(verbose>1) printf(
"allocating memory for fits.\n");
481 fprintf(stderr,
"Error: cannot allocate space for fit results (%d).\n", ret);
486 strncpy(fit.
datafile, dfile, FILENAME_MAX);
489 for(fi=n=0; fi<fitdataNr; fi++)
if(dft.
x[fi]>=0.0 && !isnan(dft.
voi[0].
y[fi])) n++;
490 for(ri=0; ri<fit.
voiNr; ri++) {
493 if(model==MODEL_MPF || model==MODEL_MHILL) fit.
voi[ri].
parNr*=metabNr;
497 if(model==MODEL_MHILL) {
500 if(metabNr>1) fit.
voi[2].
type=MF_HILL3M_M2;
501 if(metabNr>2) fit.
voi[3].
type=MF_HILL3M_M3;
502 }
else if(model==MODEL_MPF) {
505 if(metabNr>1) fit.
voi[2].
type=MF_PF3M_M2;
506 if(metabNr>2) fit.
voi[3].
type=MF_PF3M_M3;
515 pmin[0]=1.0e-20; pmax[0]=1.0e+00;
516 pmin[1]=1.5; pmax[1]=5.0e+01;
517 pmin[2]=1.0e-20; pmax[2]=1.0e+00;
518 pmin[3]=1.0e-20; pmax[3]=1.0e+00;
522 pmin[0]=0.0; pmax[0]=1.0e+00;
523 pmin[1]=1.0; pmax[1]=1.5e+01;
524 pmin[2]=1.0e-06; pmax[2]=1.0e+05;
525 pmin[3]=1.0e-06; pmax[3]=1.0e+00;
528 pmin[0]=0.0; pmax[0]=1.0e+00;
529 pmin[1]=0.1; pmax[1]=1.0e+00;
530 pmin[2]=1.0e-06; pmax[2]=1.0e+01;
531 pmin[3]=1.0e-06; pmax[3]=1.0e+02;
534 pmin[0]=0.0; pmax[0]=1.0;
535 pmin[1]=0.1; pmax[1]=1.0;
536 pmin[2]=0.001; pmax[2]=1.0;
537 pmin[3]=0.001; pmax[3]=1.0;
538 pmin[4]=1.0; pmax[4]=1.0e+03;
539 pmin[5]=1.0e-06; pmax[5]=0.2;
544 if(min_delay>0.9*dft.
x[fitdataNr-1]) min_delay=0.9*dft.
x[fitdataNr-1];
545 pmin[delay_par_index]=min_delay;
547 if(fixed_p[iscale_par_index]==1.0) {
549 for(fi=0; fi<fitdataNr; fi++)
if(dft.
voi[0].
y[fi]>=1.0 && dft.
x[fi]>a) a=dft.
x[fi];
550 pmin[delay_par_index]=a;
552 pmin[delay_par_index]=0.0;
556 if(model==MODEL_PF || model==MODEL_HILL || model==MODEL_GCDF || model==MODEL_EP || mdelay_joint==1) {
559 if(fixed_p[iscale_par_index]==1.0) {
562 for(fi=0; fi<fitdataNr; fi++)
if(dft.
voi[0].
y[fi]<1.0 && dft.
x[fi]<a) a=dft.
x[fi];
563 pmax[delay_par_index]=a;
566 for(fi=0, n=fitdataNr-1, a=0.0; fi<fitdataNr; fi++)
567 if(dft.
voi[0].
y[fi]>=a) {a=dft.
voi[0].
y[fi]; n=fi;}
568 if(n<fitdataNr-1) n++;
569 pmax[delay_par_index]=dft.
x[n];
576 m=0; n=fitdataNr-1; a=dft.
voi[0].
y[m]; b=dft.
voi[0].
y[n];
577 for(fi=0; fi<fitdataNr; fi++) {
578 if(dft.
voi[0].
y[fi]>=a) {m=fi; a=dft.
voi[0].
y[m];}
579 if(dft.
voi[0].
y[fi]<b) {n=fi; b=dft.
voi[0].
y[n];}
582 printf(
"max parent fraction %g at %g\n", a, dft.
x[m]);
583 printf(
"min parent fraction %g at %g\n", b, dft.
x[n]);
586 for(fi=m; fi<=n; fi++)
if(dft.
voi[0].
y[fi]<=a)
break;
587 if(verbose>2) printf(
"parent fraction dropped to %g at %g\n", a, dft.
x[fi]);
588 pmax[delay_par_index]=dft.
x[fi];
590 if(min_delay>=0 && pmin[delay_par_index]==pmax[delay_par_index]) {
591 pmax[delay_par_index]=1.5*pmin[delay_par_index];
592 if(pmax[delay_par_index]>dft.
x[fitdataNr-1]) pmax[delay_par_index]=dft.
x[fitdataNr-1];
594 if(pmax[delay_par_index]<pmin[delay_par_index]) pmax[delay_par_index]=pmin[delay_par_index];
596 for(pi=0; pi<parNr; pi++) {
if(fixed_p[pi]>=0.0) pmin[pi]=pmax[pi]=fixed_p[pi];}
597 if(fixed0 && fabs(tstart)<1.0E-08) {
599 double y0=0.0;
int n=0;
600 for(
int i=0; i<fitdataNr; i++)
if(fabs(dft.
x[i])<1.0E-08) {y0+=dft.
voi[0].
y[i]; n++;}
601 if(n>1) y0/=(double)n;
603 fprintf(stderr,
"Warning: initial fraction is not fixed to sample zero.\n");
606 if(verbose>1) {printf(
"Note: initial fraction fixed to %g\n", y0); fflush(stdout);}
607 pmin[iscale_par_index]=pmax[iscale_par_index]=y0;
608 if(fixed_p[iscale_par_index]>0.0) {
609 fprintf(stderr,
"Warning: non-effective option -d for initial fraction.\n");
615 if(model==MODEL_MPF || model==MODEL_MHILL) {
617 for(m=1; m<metabNr; m++) {
618 for(pi=0; pi<parNr-1; pi++) {
619 pmin[m*parNr+pi]=pmin[pi]; pmax[m*parNr+pi]=pmax[pi];}
621 if(mdelay_joint==0) {
623 pmin[m*parNr+pi]=-0.5*a; pmax[m*parNr+pi]=+0.5*a;
625 pmin[m*parNr+pi]=0.0; pmax[m*parNr+pi]=0.0;
630 if(verbose>2) printf(
"final_parNr := %d\n", parNr);
633 printf(
"Constraints for the fit:\n");
634 for(pi=0; pi<parNr; pi++) printf(
" limit[%d]: %g - %g\n", pi+1, pmin[pi], pmax[pi]);
643 for(fi=n=0; fi<fitdataNr; fi++) {
644 if(dft.
x[fi]<0.0)
continue;
645 if(!isnan(dft.
voi[0].
y[fi])) n++;
647 for(pi=m=0; pi<parNr; pi++)
if(pmin[pi]<pmax[pi]) m++;
648 if(verbose>1) printf(
"Comparison of nr of samples and params to fit: %d / %d\n", n, m);
650 fprintf(stderr,
"Error: too few samples for fitting in %s\n", dfile);
651 if(verbose>0) printf(
"n := %d\nm := %d\n", n, m);
659 if(verbose>1) {printf(
"preparing to fit.\n"); fflush(stdout);}
662 x=dft.
x; w=dft.
w; ymeas[0]=dft.
voi[ri].
y; yfit[0]=dft.
voi[ri].
y2;
663 for(m=0; m<metabNr; m++) {
664 ymeas[m+1]=dft.
voi[m+1].
y; yfit[m+1]=dft.
voi[m+1].
y2;
667 fit.
voi[ri].
wss=3.402823e+38;
669 if(verbose>1) printf(
"fitting\n");
673 int neighNr=6, iterNr=1, sampleNr=800;
674 if(model==MODEL_MPF || model==MODEL_PF) {
678 neighNr=5; iterNr=1; sampleNr=800;
680 ret=
tgo(pmin, pmax, func_list[model], NULL, parNr, neighNr, &fit.
voi[ri].
wss,
681 fit.
voi[ri].
p, sampleNr, iterNr, verbose-8);
683 fprintf(stderr,
"Error %d in TGO.\n", ret);
688 printf(
"Results from tgo():\n");
689 for(pi=0; pi<parNr; pi++) printf(
" parameter[%d] := %g\n", pi, fit.
voi[ri].
p[pi]);
690 printf(
"WSS := %g\n", fit.
voi[ri].
wss);
694 if(verbose>5) {printf(
"lastWSS := %g\n", lastWSS); fflush(stdout);}
698 if(model==MODEL_HILL) {
700 }
else if(model==MODEL_MHILL) {
702 for(m=0; m<metabNr; m++)
703 if(fit.
voi[ri].
p[m*n]>fit.
voi[ri].
p[m*n+3])
704 fit.
voi[ri].
p[m*n]=fit.
voi[ri].
p[m*n+3];
706 if(model==MODEL_MPF || model==MODEL_MHILL) {
708 for(m=1; m<metabNr; m++)
709 if( (fit.
voi[ri].
p[n-1]+fit.
voi[ri].
p[(m+1)*n-1]) < 0.0)
710 fit.
voi[ri].
p[(m+1)*n-1] = -fit.
voi[ri].
p[n-1];
714 printf(
"Corrected parameters:\n");
715 for(pi=0; pi<parNr; pi++) printf(
" parameter[%d] := %g\n", pi, fit.
voi[ri].
p[pi]);
719 if(ret==0) {
if(verbose>2) fprintf(stdout,
"ok\n");}
720 else fprintf(stderr,
"warning, fit collided with the limits.\n");
722 if(verbose>1) {fprintf(stdout,
"WSS := %g\n", fit.
voi[ri].
wss); fflush(stdout);}
725 printf(
" Measured Fitted Weight\n");
726 for(fi=0; fi<fitdataNr; fi++)
727 if(!isnan(ymeas[0][fi]))
728 printf(
" %2d: %9.4e %9.4e %9.4e %7.1e\n", fi+1, x[fi], ymeas[0][fi], yfit[0][fi], w[fi]);
730 printf(
" %2d: %9.4e %-9.9s %9.4e %7.1e\n", fi+1, x[fi],
".", yfit[0][fi], w[fi]);
731 printf(
" fitted parameters:");
732 for(pi=0; pi<parNr; pi++) printf(
" %g", fit.
voi[ri].
p[pi]);
736 if(verbose>1) printf(
"Checking the MRL.\n");
738 if(fi>3 && fi>fitdataNr/3) {
740 fprintf(stderr,
"Error: bad fit.\n");
741 fprintf(stderr,
"MRL := %d / %d\n", fi, fitdataNr);
746 if(fi>2 && fi>fitdataNr/4) {
747 fprintf(stderr,
"Warning: bad fit.\n");
748 fprintf(stderr,
"MRL := %d / %d\n", fi, fitdataNr);
749 }
else if(verbose>1) {
750 printf(
"MRL test passed.\n");
751 if(verbose>2) fprintf(stderr,
"MRL := %d / %d\n", fi, fitdataNr);
755 double wss[1+metabNr], f=0.0;
756 for(ai=0; ai<=metabNr; ai++) {
758 for(fi=0; fi<fitdataNr; fi++) {
762 f+=wss[ai]; printf(
"WSS[%d] := %g\n", ai+1, wss[ai]);
764 printf(
"WSS[total] := %g\n", f);
769 for(ai=0, m=0; ai<=metabNr; ai++)
if(frwgt[ai]>0.0)
770 for(fi=0; fi<fitdataNr; fi++)
if(w[fi]>0.0) m++;
771 printf(
"nr_of_fitted_samples := %d\n", m);
772 for(pi=0, n=0; pi<parNr; pi++)
if(pmax[pi]>pmin[pi]) n++;
773 printf(
"nr_of_fitted_parameters := %d\n", n);
775 printf(
"AIC := %g\n", aic);
778 printf(
"Fitted parameters:\n");
780 for(pi=0; pi<parNr; pi++) printf(
" par[%d]: %g\n", pi+1, fit.
voi[ri].
p[pi]);
781 if(verbose>4)
for(pi=0; pi<parNr; pi++)
782 printf(
" par[%d]: %g [%g, %g]\n", pi+1, fit.
voi[ri].
p[pi], pmin[pi], pmax[pi]);
785 if(model==MODEL_MPF || model==MODEL_MHILL) {
788 for(m=1; m<metabNr; m++) {
789 fit.
voi[ri].
p[(m+1)*n-1]+=fit.
voi[ri].
p[n-1];
793 for(ri=1; ri<fit.
voiNr; ri++) {
798 if(model==MODEL_HILL && ffile_type==2) {
806 if((verbose>1) && strcmp(ffile,
"stdout")!=0) printf(
"saving results in %s\n", ffile);
807 ret=
fitWrite(&fit, ffile);
if(ret) {
808 fprintf(stderr,
"Error (%d) in writing '%s': %s\n", ret, ffile,
fiterrmsg);
811 if(strcmp(ffile,
"stdout")!=0 && verbose>0)
812 printf(
"Function parameters written in %s\n", ffile);
819 if(verbose>1) printf(
"creating SVG plot\n");
821 char tmp[FILENAME_MAX];
823 if(verbose>1) printf(
"calculating fitted curve at automatically generated sample times\n");
827 fprintf(stderr,
"Error %d in memory allocation for fitted curves.\n", ret);
831 for(fi=0; fi<adft.
frameNr; fi++) adft.
w[fi]=1.0;
833 for(ri=0; ri<adft.
voiNr; ri++) {
834 yfit[ri]=adft.
voi[ri].
y;
835 ymeas[ri]=adft.
voi[ri].
y2;
838 for(ri=0, ret=0; ri<adft.
voiNr; ri++) {
839 for(fi=0; fi<adft.
frameNr; fi++) {
840 ret=
fitEval(&fit.
voi[ri], adft.
x[fi], &a);
if(ret!=0)
break;
841 adft.
voi[ri].
y[fi]=a;
846 fprintf(stderr,
"Error: cannot calculate fitted curve for '%s'.\n", svgfile);
852 if(verbose>1) printf(
"writing %s\n", svgfile);
855 ret=
plot_fitrange_svg(&dft, &adft, tmp, 0.0, nan(
""), 0.0, 1.0, svgfile, verbose-8);
857 fprintf(stderr,
"Error (%d) in writing '%s'.\n", ret, svgfile);
861 if(verbose>0) printf(
"Plots written in %s\n", svgfile);
878double func_pf(
int parNr,
double *p,
void *fdata)
881 double a, b, c, d, dt, v, f, wss;
886 for(i=0; i<parNr; i++) printf(
" p[%d]=%g", i, p[i]);
891 a=pa[0]; b=pa[1]; c=pa[2]; d=pa[3]; dt=pa[4];
895 for(i=0, wss=0.0; i<fitdataNr; i++)
if(w[i]>0.0) {
896 if(x[i]<=dt) yfit[0][i]=d;
897 else yfit[0][i]=pow(f+pow(a*(x[i]-dt), b), -c);
898 v=yfit[0][i]-ymeas[0][i];
899 if(min_meas==MINMEAS_LAD) v=fabs(v);
900 else if(min_meas==MINMEAS_OLS) v*=v;
901 else if(min_meas==MINMEAS_ODR) {
904 if(x[i]>dt) df=-(b*c*pow(a*(x[i]-dt),b)/(x[i]-dt)) * pow(pow(d,-1.0/c)+pow(a*(x[i]-dt),b),-c-1.0);
905 if(!isfinite(df)) df=0.0;
907 v*=v; v/=(1.0 + df*df);
911 lastWSS=wss; wss*=penalty;
912 if(0) printf(
"%g %g %g %g %g -> %g\n", a, b, c, d, dt, wss);
916double func_hill(
int parNr,
double *p,
void *fdata)
919 double a, b, c, d, dt, v, wss;
924 for(i=0; i<parNr; i++) printf(
" p[%d]=%g", i, p[i]);
929 a=pa[0]; b=pa[1]; c=pa[2]; d=pa[3]; dt=pa[4];
932 penalty+=100.0*(a/d);
937 for(i=0, wss=0.0; i<fitdataNr; i++)
if(w[i]>0.0) {
941 double f=pow(x[i]-dt, b);
942 yfit[0][i]= d + (a-d)*f/(c+f);
944 v=yfit[0][i]-ymeas[0][i];
945 if(min_meas==MINMEAS_LAD) v=fabs(v);
946 else if(min_meas==MINMEAS_OLS) v*=v;
947 else if(min_meas==MINMEAS_ODR) {
949 double df=0.0;
if(x[i]>dt) df=-b*c*(d-a)*pow(x[i]-dt,b-1.0)/pow(c+pow(x[i]-dt,b),2);
950 if(!isfinite(df)) df=0.0;
952 v*=v; v/=(1.0 + df*df);
956 lastWSS=wss; wss*=penalty;
958 if(0) printf(
"%g %g %g %g %g -> %g\n", a, b, c, d, dt, wss);
962double func_gcdf(
int parNr,
double *p,
void *fdata)
965 double a, b, c, d, dt, v, wss;
970 for(i=0; i<parNr; i++) printf(
" p[%d]=%g", i, p[i]);
975 a=pa[0]; b=pa[1]; c=pa[2]; d=pa[3]; dt=pa[4];
977 for(i=0, wss=0.0; i<fitdataNr; i++)
if(w[i]>0.0) {
981 yfit[0][i]= a*(1.0-b*
igam(d, c*(x[i]-dt)));
983 v=yfit[0][i]-ymeas[0][i];
984 if(min_meas==MINMEAS_LAD) v=fabs(v);
989 lastWSS=wss; wss*=penalty;
991 if(0) printf(
"%g %g %g %g %g -> %g\n", a, b, c, d, dt, wss);
995double func_ep(
int parNr,
double *p,
void *fdata)
998 double a, b, c, d, dt, s, v, wss;
1003 for(i=0; i<parNr; i++) printf(
" p[%d]=%g", i, p[i]);
1008 dt=pa[0]; s=pa[1]; a=pa[2]; b=pa[3]; c=pa[4]; d=pa[5];
1010 for(i=0, wss=0.0; i<fitdataNr; i++)
if(w[i]>0.0) {
1015 yfit[0][i]= a*exp(-b*xt*xt*xt/(xt*xt+c)) + (1.0-a)*exp(-d*xt);
1018 v=yfit[0][i]-ymeas[0][i];
1019 if(min_meas==MINMEAS_LAD) v=fabs(v);
1023 lastWSS=wss; wss*=penalty;
1027double func_mpf(
int parNr,
double *p,
void *fdata)
1030 double a[1+MAX_METAB_NR], b[1+MAX_METAB_NR], c[1+MAX_METAB_NR],
1031 d[1+MAX_METAB_NR], dt[1+MAX_METAB_NR];
1033 double mf[1+MAX_METAB_NR], g[1+MAX_METAB_NR], v, f, wss;
1037 for(i=0; i<parNr; i++) printf(
" p[%d]=%g", i, p[i]);
1043 for(m=0; m<metabNr; m++) {
1044 a[m]=pa[m*pn+0]; b[m]=pa[m*pn+1]; c[m]=pa[m*pn+2];
1045 d[m]=pa[m*pn+3]; dt[m]=pa[m*pn+4];
if(m>0) dt[m]+=dt[0];
1047 for(; m<MAX_METAB_NR; m++) a[m]=b[m]=c[m]=d[m]=dt[m]=0.0;
1049 for(m=1; m<metabNr; m++)
if(dt[m]<0.0) {
1050 penalty+=100.0*(-dt[m]); dt[m]=0.0;}
1053 for(m=0; m<metabNr; m++) g[m]=pow(d[m], -1.0/c[m]);
1054 for(i=0, wss=0.0; i<fitdataNr; i++)
if(w[i]>0.0) {
1055 for(m=0; m<metabNr && m<=MAX_METAB_NR; m++) {
1056 if(x[i]<=dt[m]) mf[m]=1.0 - d[m];
1057 else mf[m]=1.0 - pow(g[m]+pow(a[m]*(x[i]-dt[m]), b[m]), -c[m]);
1059 for(; m<MAX_METAB_NR; m++) mf[m]=0.0;
1061 f=1.0-mf[0]*mf[1]-mf[0]*mf[2]-mf[1]*mf[2]+2.0*mf[0]*mf[1]*mf[2];
1062 yfit[1][i]=mf[0]*(1.0-mf[1]-mf[2]+mf[1]*mf[2])/f; yfit[0][i]-=yfit[1][i];
1064 yfit[2][i]=mf[1]*(1.0-mf[0]-mf[2]+mf[0]*mf[2])/f; yfit[0][i]-=yfit[2][i];
1067 yfit[3][i]=mf[2]*(1.0-mf[0]-mf[1]+mf[0]*mf[1])/f; yfit[0][i]-=yfit[3][i];
1069 for(m=0; m<=metabNr && m<=MAX_METAB_NR; m++) {
1070 v=yfit[m][i]-ymeas[m][i];
1071 if(min_meas==MINMEAS_OLS) v*=v;
else v=fabs(v);
1072 wss+=w[i]*frwgt[m]*v;
1075 lastWSS=wss; wss*=penalty;
1080double func_mhill(
int parNr,
double *p,
void *fdata)
1083 double a[1+MAX_METAB_NR], b[1+MAX_METAB_NR], c[1+MAX_METAB_NR],
1084 d[1+MAX_METAB_NR], dt[1+MAX_METAB_NR];
1086 double mf[1+MAX_METAB_NR], v, f, wss;
1090 for(i=0; i<parNr; i++) printf(
" p[%d]=%g", i, p[i]);
1096 for(m=0; m<metabNr; m++) {
1097 a[m]=pa[m*pn+0]; b[m]=pa[m*pn+1]; c[m]=pa[m*pn+2];
1098 d[m]=pa[m*pn+3]; dt[m]=pa[m*pn+4];
if(m>0) dt[m]+=dt[0];
1101 penalty+=100.0*(a[m]/d[m]);
1105 for(; m<MAX_METAB_NR; m++) a[m]=b[m]=c[m]=d[m]=dt[m]=0.0;
1107 for(m=1; m<metabNr; m++)
if(dt[m]<0.0) {
1108 penalty+=100.0*(-dt[m]); dt[m]=0.0;}
1111 for(i=0, wss=0.0; i<fitdataNr; i++)
if(w[i]>0.0) {
1112 for(m=0; m<metabNr && m<=MAX_METAB_NR; m++) {
1116 f=pow(x[i]-dt[m], b[m]);
1117 mf[m]=1.0 - (d[m] + (a[m]-d[m])*f/(c[m]+f));
1120 for(; m<MAX_METAB_NR; m++) mf[m]=0.0;
1122 f=1.0-mf[0]*mf[1]-mf[0]*mf[2]-mf[1]*mf[2]+2.0*mf[0]*mf[1]*mf[2];
1123 yfit[1][i]=mf[0]*(1.0-mf[1]-mf[2]+mf[1]*mf[2])/f; yfit[0][i]-=yfit[1][i];
1125 yfit[2][i]=mf[1]*(1.0-mf[0]-mf[2]+mf[0]*mf[2])/f; yfit[0][i]-=yfit[2][i];
1128 yfit[3][i]=mf[2]*(1.0-mf[0]-mf[1]+mf[0]*mf[1])/f; yfit[0][i]-=yfit[3][i];
1130 for(m=0; m<=metabNr && m<=MAX_METAB_NR; m++) {
1131 v=yfit[m][i]-ymeas[m][i];
1132 if(min_meas==MINMEAS_OLS) v*=v;
else v=fabs(v);
1133 wss+=w[i]*frwgt[m]*v;
1136 lastWSS=wss; wss*=penalty;
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 modelCheckLimits(int par_nr, double *lower_p, double *upper_p, double *test_p)
double atof_dpi(char *str)
int dftAddmem(DFT *dft, int voiNr)
int dftSortByFrame(DFT *dft)
int dftMinMax(DFT *dft, double *minx, double *maxx, double *miny, double *maxy)
int dftRead(char *filename, DFT *data)
void dftUnitToDFT(DFT *dft, int dunit)
void dftSec2min(DFT *dft)
int fit_allocate_with_dft(FIT *fit, DFT *dft)
Header file for libtpccurveio.
double igam(double a, double x)
int fitEval(FitVOI *r, double x, double *y)
int fitWrite(FIT *fit, char *filename)
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 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 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 voiname[MAX_REGIONSUBNAME_LEN+1]
char name[MAX_REGIONNAME_LEN+1]