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;
190 for(m=0; m<=MAX_METAB_NR; m++) frwgt[m]=1.0;
196 if(argc==1) {
tpcPrintUsage(argv[0], info, stderr);
return(1);}
198 dfile[0]=ffile[0]=svgfile[0]=(char)0;
200 for(ai=1; ai<argc; ai++)
if(*argv[ai]==
'-') {
201 cptr=argv[ai]+1;
if(*cptr==
'-') cptr++;
if(cptr==NULL)
continue;
203 if(strncasecmp(cptr,
"MODEL=", 6)==0) {
205 if(strncasecmp(cptr,
"PF", 1)==0) {model=MODEL_PF;
continue;}
206 if(strcasecmp(cptr,
"HILL2")==0) {model=MODEL_HILL; ffile_type=2;
continue;}
207 if(strncasecmp(cptr,
"HILL", 1)==0) {model=MODEL_HILL;
continue;}
208 if(strncasecmp(cptr,
"GCDF", 1)==0) {model=MODEL_GCDF;
continue;}
209 if(strcasecmp(cptr,
"EP")==0) {model=MODEL_EP;
continue;}
210 if(strncasecmp(cptr,
"MPF", 3)==0) {model=MODEL_MPF;
continue;}
211 if(strncasecmp(cptr,
"MHILL", 3)==0) {model=MODEL_MHILL;
continue;}
212 fprintf(stderr,
"Error: invalid model selection.\n");
return(1);
213 }
else if(strcasecmp(cptr,
"ND")==0) {
214 noDivide=1;
continue;
215 }
else if(strcasecmp(cptr,
"W1")==0) {
216 weighting=1;
continue;
217 }
else if(strcasecmp(cptr,
"WF")==0) {
218 weighting=2;
continue;
219 }
else if(strcasecmp(cptr,
"WC")==0) {
220 last_col_is_weight=1;
continue;
221 }
else if(strncasecmp(cptr,
"WP=", 3)==0) {
222 frwgt[0]=
atof_dpi(cptr+3);
if(frwgt[0]>=0.0)
continue;
223 }
else if(strncasecmp(cptr,
"WM1=", 4)==0) {
224 frwgt[1]=
atof_dpi(cptr+4);
if(frwgt[1]>=0.0)
continue;
225 }
else if(strncasecmp(cptr,
"WM2=", 4)==0) {
226 frwgt[2]=
atof_dpi(cptr+4);
if(frwgt[2]>=0.0)
continue;
227 }
else if(strncasecmp(cptr,
"WM3=", 4)==0) {
228 frwgt[3]=
atof_dpi(cptr+4);
if(frwgt[3]>=0.0)
continue;
229 }
else if(strncasecmp(cptr,
"A=", 2)==0) {
230 fixed_p[0]=
atof_dpi(cptr+2);
if(fixed_p[0]>=0.0)
continue;
231 }
else if(strncasecmp(cptr,
"B=", 2)==0) {
232 fixed_p[1]=
atof_dpi(cptr+2);
if(fixed_p[1]>=0.0)
continue;
233 }
else if(strncasecmp(cptr,
"C=", 2)==0) {
234 fixed_p[2]=
atof_dpi(cptr+2);
if(fixed_p[2]>=0.0)
continue;
235 }
else if(strncasecmp(cptr,
"D=", 2)==0) {
236 fixed_p[3]=
atof_dpi(cptr+2);
if(fixed_p[3]>=0.0)
continue;
237 }
else if(strncasecmp(cptr,
"E=", 2)==0) {
238 fixed_p[4]=
atof_dpi(cptr+2);
if(fixed_p[4]>=0.0)
continue;
239 }
else if(strncasecmp(cptr,
"F=", 2)==0) {
240 fixed_p[5]=
atof_dpi(cptr+2);
if(fixed_p[5]>=0.0)
continue;
241 }
else if(strncasecmp(cptr,
"DELAYMIN=", 9)==0) {
242 min_delay=
atof_dpi(cptr+9);
if(min_delay>=0.0)
continue;
243 }
else if(strcasecmp(cptr,
"FIX0")==0 || strcasecmp(cptr,
"FIXED0")==0) {
245 }
else if(strcasecmp(cptr,
"MRL")==0) {
246 MRL_check=1;
continue;
247 }
else if(strncasecmp(cptr,
"MDELAY=", 7)==0) {
249 if(strncasecmp(cptr,
"JOINT", 1)==0) {mdelay_joint=1;
continue;}
250 if(strncasecmp(cptr,
"SEPARATED", 1)==0) {mdelay_joint=0;
continue;}
251 fprintf(stderr,
"Error: invalid mdelay selection.\n");
return(1);
252 }
else if(strncasecmp(cptr,
"SVG=", 4)==0 && strlen(cptr)>4) {
253 strlcpy(svgfile, cptr+4, FILENAME_MAX);
continue;
254 }
else if(strncasecmp(cptr,
"MIN=", 4)==0) {
256 if(strcasecmp(cptr,
"OLS")==0 || strcasecmp(cptr,
"SS")==0 || strcasecmp(cptr,
"WSS")==0) {
257 min_meas=MINMEAS_OLS;
continue;}
258 if(strcasecmp(cptr,
"LAD")==0 || strcasecmp(cptr,
"ABS")==0 || strcasecmp(cptr,
"WABS")==0) {
259 min_meas=MINMEAS_LAD;
continue;}
260 if(strcasecmp(cptr,
"ODR")==0) {
261 min_meas=MINMEAS_ODR;
continue;}
262 fprintf(stderr,
"Error: invalid minimization measure.\n");
return(1);
264 fprintf(stderr,
"Error: invalid option '%s'.\n", argv[ai]);
269 if(help==2) {
tpcHtmlUsage(argv[0], info,
"");
return(0);}
274 if(ai<argc)
strlcpy(dfile, argv[ai++], FILENAME_MAX);
275 if(ai<argc)
strlcpy(ffile, argv[ai++], FILENAME_MAX);
276 if(ai<argc) {fprintf(stderr,
"Error: too many arguments: '%s'.\n", argv[ai]);
return(1);}
280 fprintf(stderr,
"Error: missing command-line argument; use option --help\n");
284 if(model==MODEL_UNKNOWN) model=MODEL_HILL;
285 if(min_meas==MINMEAS_UNKNOWN) min_meas=MINMEAS_OLS;
287 if(min_meas==MINMEAS_ODR) {
288 if(model!=MODEL_HILL && model!=MODEL_PF) {
289 fprintf(stderr,
"Warning: ODR is not available with selected model.\n");
290 fprintf(stderr,
"Note: using OLS instead of ODR.\n");
291 min_meas=MINMEAS_OLS;
295 type=func_type[model];
296 if(model==MODEL_HILL && ffile_type==2) type=MF_EHILL2_PAR;
297 parNr=func_par_nr[model];
298 delay_par_index=parNr-1;
299 if(model!=MODEL_GCDF) iscale_par_index=parNr-2;
300 if(model==MODEL_EP) {delay_par_index=0; iscale_par_index=1;}
301 for(pi=0, n=0; pi<parNr; pi++)
if(fixed_p[pi]>=0.0) n++;
303 fprintf(stderr,
"Error: too many parameters were fixed.\n");
306 if(fixed_p[delay_par_index]>=0.0 && mdelay_joint==0)
307 fprintf(stderr,
"Warning: option -mdelay is not effective with option -e\n");
308 if(!ffile[0]) strcpy(ffile,
"stdout");
313 printf(
"dfile := %s\n", dfile);
314 printf(
"ffile := %s\n", ffile);
315 printf(
"svgfile := %s\n", svgfile);
316 printf(
"noDivide := %d\n", noDivide);
317 printf(
"weighting := %d\n", weighting);
318 printf(
"mdelay_joint := %d\n", mdelay_joint);
319 printf(
"last_col_is_weight := %d\n", last_col_is_weight);
320 printf(
"model := %d\n", model);
321 printf(
"type := %d\n", type);
322 printf(
"parNr := %d\n", parNr);
323 printf(
"min_meas := %d\n", min_meas);
324 for(pi=0; pi<parNr; pi++)
if(fixed_p[pi]>=0.0) printf(
"fixed_p[%d] := %g\n", pi, fixed_p[pi]);
325 if(min_delay>=0.0) printf(
"min_delay := %g\n", min_delay);
326 printf(
"fixed0 := %d\n", fixed0);
327 printf(
"MRL_check := %d\n", MRL_check);
328 for(m=0; m<=MAX_METAB_NR; m++) printf(
"frwgt[%d] := %g\n", m, frwgt[m]);
336 if(verbose>1) printf(
"reading %s\n", dfile);
338 fprintf(stderr,
"Error in reading '%s': %s\n", dfile,
dfterrmsg);
344 if(last_col_is_weight!=0) {
345 if(verbose>1) printf(
"reading weights from the last column.\n");
347 fprintf(stderr,
"Error: no column for weights in %s\n", dfile);
350 for(fi=0; fi<dft.
frameNr; fi++) {
352 if(isnan(dft.
w[fi])) dft.
w[fi]=0.0;
359 printf(
"study_number := %s\n", dft.
studynr);
360 printf(
"tacNr := %d\n", dft.
voiNr);
368 if(verbose>1) printf(
"Sample times are converted to min\n");
376 if(model==MODEL_PF || model==MODEL_HILL || model==MODEL_GCDF || model==MODEL_EP) {
378 fprintf(stderr,
"Warning: extra columns in %s are ignored.\n", dfile);
383 if(verbose>1) printf(
"calculating metabolite fractions\n");
386 fprintf(stderr,
"Error: cannot allocate memory for metabolite.\n");
391 }
else if(dft.
voiNr>(1+MAX_METAB_NR)) {
393 for(fi=0; fi<dft.
frameNr; fi++)
for(ri=1+MAX_METAB_NR; ri<dft.
voiNr; ri++)
395 if(isnan(dft.
voi[ri].
y[fi]))
continue;
396 if(isnan(dft.
voi[MAX_METAB_NR].
y[fi])) {
397 dft.
voi[MAX_METAB_NR].
y[fi]=dft.
voi[ri].
y[fi];
continue;}
398 dft.
voi[MAX_METAB_NR].
y[fi]+=dft.
voi[ri].
y[fi];
400 fprintf(stderr,
"Warning: extra metabolite(s) are summed in Metab3.\n");
401 dft.
voiNr=1+MAX_METAB_NR;
404 metabNr=dft.
voiNr-1;
if(metabNr>MAX_METAB_NR) metabNr=MAX_METAB_NR;
405 if(verbose>1) printf(
"metabNr := %d\n", metabNr);
409 if(strlen(dft.
voi[0].
name)==0) {
410 strcpy(dft.
voi[0].
name,
"Parent");
413 for(ri=1; ri<dft.
voiNr; ri++)
if(strlen(dft.
voi[ri].
name)==0) {
414 strcpy(dft.
voi[ri].
name,
"Metab1");
420 fitdataNr=origdataNr;
422 fprintf(stderr,
"Error: too few samples for fitting in %s\n", dfile);
428 ret=
dftMinMax(&dft, &tstart, &tstop, NULL, &maxfract);
430 fprintf(stderr,
"Error: invalid contents in %s\n", dfile);
433 if(verbose>2) printf(
"max := %g\n", maxfract);
435 if(tstart<0.0 || !(tstop>tstart)) {
436 fprintf(stderr,
"Error: invalid sample times.\n");
440 if(maxfract>100.0 || maxfract<0.001) {
441 fprintf(stderr,
"Error: invalid fraction values.\n");
444 if(noDivide==0 && maxfract>1.0) {
445 fprintf(stderr,
"Warning: converting percentages to fractions.\n");
446 for(fi=0; fi<origdataNr; fi++)
for(ri=0; ri<dft.
voiNr; ri++)
447 if(!isnan(dft.
voi[ri].
y[fi])) dft.
voi[ri].
y[fi]/=100.0;
454 if(dft.
isweight==0 || weighting==1) {
456 for(fi=0; fi<dft.
frameNr; fi++) dft.
w[fi]=1.0;
462 for(fi=0; fi<dft.
frameNr; fi++)
if(isnan(dft.
voi[0].
y[fi])) dft.
w[fi]=0;
464 printf(
"data_weights := %g", dft.
w[0]);
465 for(fi=1; fi<dft.
frameNr; fi++) printf(
", %g", dft.
w[fi]);
473 if(verbose>1) printf(
"allocating memory for fits.\n");
476 fprintf(stderr,
"Error: cannot allocate space for fit results (%d).\n", ret);
481 strncpy(fit.
datafile, dfile, FILENAME_MAX);
484 for(fi=n=0; fi<fitdataNr; fi++)
if(dft.
x[fi]>=0.0 && !isnan(dft.
voi[0].
y[fi])) n++;
485 for(ri=0; ri<fit.
voiNr; ri++) {
488 if(model==MODEL_MPF || model==MODEL_MHILL) fit.
voi[ri].
parNr*=metabNr;
492 if(model==MODEL_MHILL) {
495 if(metabNr>1) fit.
voi[2].
type=MF_HILL3M_M2;
496 if(metabNr>2) fit.
voi[3].
type=MF_HILL3M_M3;
497 }
else if(model==MODEL_MPF) {
500 if(metabNr>1) fit.
voi[2].
type=MF_PF3M_M2;
501 if(metabNr>2) fit.
voi[3].
type=MF_PF3M_M3;
510 pmin[0]=1.0e-20; pmax[0]=1.0e+00;
511 pmin[1]=1.5; pmax[1]=5.0e+01;
512 pmin[2]=1.0e-20; pmax[2]=1.0e+00;
513 pmin[3]=1.0e-20; pmax[3]=1.0e+00;
517 pmin[0]=0.0; pmax[0]=1.0e+00;
518 pmin[1]=1.0; pmax[1]=1.5e+01;
519 pmin[2]=1.0e-06; pmax[2]=1.0e+05;
520 pmin[3]=1.0e-06; pmax[3]=1.0e+00;
523 pmin[0]=0.0; pmax[0]=1.0e+00;
524 pmin[1]=0.1; pmax[1]=1.0e+00;
525 pmin[2]=1.0e-06; pmax[2]=1.0e+01;
526 pmin[3]=1.0e-06; pmax[3]=1.0e+02;
529 pmin[0]=0.0; pmax[0]=1.0;
530 pmin[1]=0.1; pmax[1]=1.0;
531 pmin[2]=0.001; pmax[2]=1.0;
532 pmin[3]=0.001; pmax[3]=1.0;
533 pmin[4]=1.0; pmax[4]=1.0e+03;
534 pmin[5]=1.0e-06; pmax[5]=0.2;
539 if(min_delay>0.9*dft.
x[fitdataNr-1]) min_delay=0.9*dft.
x[fitdataNr-1];
540 pmin[delay_par_index]=min_delay;
542 if(fixed_p[iscale_par_index]==1.0) {
544 for(fi=0; fi<fitdataNr; fi++)
if(dft.
voi[0].
y[fi]>=1.0 && dft.
x[fi]>a) a=dft.
x[fi];
545 pmin[delay_par_index]=a;
547 pmin[delay_par_index]=0.0;
551 if(model==MODEL_PF || model==MODEL_HILL || model==MODEL_GCDF || model==MODEL_EP || mdelay_joint==1) {
554 if(fixed_p[iscale_par_index]==1.0) {
557 for(fi=0; fi<fitdataNr; fi++)
if(dft.
voi[0].
y[fi]<1.0 && dft.
x[fi]<a) a=dft.
x[fi];
558 pmax[delay_par_index]=a;
561 for(fi=0, n=fitdataNr-1, a=0.0; fi<fitdataNr; fi++)
562 if(dft.
voi[0].
y[fi]>=a) {a=dft.
voi[0].
y[fi]; n=fi;}
563 if(n<fitdataNr-1) n++;
564 pmax[delay_par_index]=dft.
x[n];
571 m=0; n=fitdataNr-1; a=dft.
voi[0].
y[m]; b=dft.
voi[0].
y[n];
572 for(fi=0; fi<fitdataNr; fi++) {
573 if(dft.
voi[0].
y[fi]>=a) {m=fi; a=dft.
voi[0].
y[m];}
574 if(dft.
voi[0].
y[fi]<b) {n=fi; b=dft.
voi[0].
y[n];}
577 printf(
"max parent fraction %g at %g\n", a, dft.
x[m]);
578 printf(
"min parent fraction %g at %g\n", b, dft.
x[n]);
581 for(fi=m; fi<=n; fi++)
if(dft.
voi[0].
y[fi]<=a)
break;
582 if(verbose>2) printf(
"parent fraction dropped to %g at %g\n", a, dft.
x[fi]);
583 pmax[delay_par_index]=dft.
x[fi];
585 if(min_delay>=0 && pmin[delay_par_index]==pmax[delay_par_index]) {
586 pmax[delay_par_index]=1.5*pmin[delay_par_index];
587 if(pmax[delay_par_index]>dft.
x[fitdataNr-1]) pmax[delay_par_index]=dft.
x[fitdataNr-1];
589 if(pmax[delay_par_index]<pmin[delay_par_index]) pmax[delay_par_index]=pmin[delay_par_index];
591 for(pi=0; pi<parNr; pi++) {
if(fixed_p[pi]>=0.0) pmin[pi]=pmax[pi]=fixed_p[pi];}
592 if(fixed0 && fabs(tstart)<1.0E-08) {
594 double y0=0.0;
int n=0;
595 for(
int i=0; i<fitdataNr; i++)
if(fabs(dft.
x[i])<1.0E-08) {y0+=dft.
voi[0].
y[i]; n++;}
596 if(n>1) y0/=(double)n;
598 fprintf(stderr,
"Warning: initial fraction is not fixed to sample zero.\n");
601 if(verbose>1) {printf(
"Note: initial fraction fixed to %g\n", y0); fflush(stdout);}
602 pmin[iscale_par_index]=pmax[iscale_par_index]=y0;
603 if(fixed_p[iscale_par_index]>0.0) {
604 fprintf(stderr,
"Warning: non-effective option -d for initial fraction.\n");
610 if(model==MODEL_MPF || model==MODEL_MHILL) {
612 for(m=1; m<metabNr; m++) {
613 for(pi=0; pi<parNr-1; pi++) {
614 pmin[m*parNr+pi]=pmin[pi]; pmax[m*parNr+pi]=pmax[pi];}
616 if(mdelay_joint==0) {
618 pmin[m*parNr+pi]=-0.5*a; pmax[m*parNr+pi]=+0.5*a;
620 pmin[m*parNr+pi]=0.0; pmax[m*parNr+pi]=0.0;
625 if(verbose>2) printf(
"final_parNr := %d\n", parNr);
628 printf(
"Constraints for the fit:\n");
629 for(pi=0; pi<parNr; pi++) printf(
" limit[%d]: %g - %g\n", pi+1, pmin[pi], pmax[pi]);
638 for(fi=n=0; fi<fitdataNr; fi++) {
639 if(dft.
x[fi]<0.0)
continue;
640 if(!isnan(dft.
voi[0].
y[fi])) n++;
642 for(pi=m=0; pi<parNr; pi++)
if(pmin[pi]<pmax[pi]) m++;
643 if(verbose>1) printf(
"Comparison of nr of samples and params to fit: %d / %d\n", n, m);
645 fprintf(stderr,
"Error: too few samples for fitting in %s\n", dfile);
646 if(verbose>0) printf(
"n := %d\nm := %d\n", n, m);
654 if(verbose>1) {printf(
"preparing to fit.\n"); fflush(stdout);}
657 x=dft.
x; w=dft.
w; ymeas[0]=dft.
voi[ri].
y; yfit[0]=dft.
voi[ri].
y2;
658 for(m=0; m<metabNr; m++) {
659 ymeas[m+1]=dft.
voi[m+1].
y; yfit[m+1]=dft.
voi[m+1].
y2;
662 fit.
voi[ri].
wss=3.402823e+38;
664 if(verbose>1) printf(
"fitting\n");
668 int neighNr=6, iterNr=1, sampleNr=800;
669 if(model==MODEL_MPF || model==MODEL_PF) {
673 neighNr=5; iterNr=1; sampleNr=800;
675 ret=
tgo(pmin, pmax, func_list[model], NULL, parNr, neighNr, &fit.
voi[ri].
wss,
676 fit.
voi[ri].
p, sampleNr, iterNr, verbose-8);
678 fprintf(stderr,
"Error %d in TGO.\n", ret);
683 printf(
"Results from tgo():\n");
684 for(pi=0; pi<parNr; pi++) printf(
" parameter[%d] := %g\n", pi, fit.
voi[ri].
p[pi]);
685 printf(
"WSS := %g\n", fit.
voi[ri].
wss);
689 if(verbose>5) {printf(
"lastWSS := %g\n", lastWSS); fflush(stdout);}
693 if(model==MODEL_HILL) {
695 }
else if(model==MODEL_MHILL) {
697 for(m=0; m<metabNr; m++)
698 if(fit.
voi[ri].
p[m*n]>fit.
voi[ri].
p[m*n+3])
699 fit.
voi[ri].
p[m*n]=fit.
voi[ri].
p[m*n+3];
701 if(model==MODEL_MPF || model==MODEL_MHILL) {
703 for(m=1; m<metabNr; m++)
704 if( (fit.
voi[ri].
p[n-1]+fit.
voi[ri].
p[(m+1)*n-1]) < 0.0)
705 fit.
voi[ri].
p[(m+1)*n-1] = -fit.
voi[ri].
p[n-1];
709 printf(
"Corrected parameters:\n");
710 for(pi=0; pi<parNr; pi++) printf(
" parameter[%d] := %g\n", pi, fit.
voi[ri].
p[pi]);
714 if(ret==0) {
if(verbose>2) fprintf(stdout,
"ok\n");}
715 else fprintf(stderr,
"warning, fit collided with the limits.\n");
717 if(verbose>1) {fprintf(stdout,
"WSS := %g\n", fit.
voi[ri].
wss); fflush(stdout);}
720 printf(
" Measured Fitted Weight\n");
721 for(fi=0; fi<fitdataNr; fi++)
722 if(!isnan(ymeas[0][fi]))
723 printf(
" %2d: %9.4e %9.4e %9.4e %7.1e\n", fi+1, x[fi], ymeas[0][fi], yfit[0][fi], w[fi]);
725 printf(
" %2d: %9.4e %-9.9s %9.4e %7.1e\n", fi+1, x[fi],
".", yfit[0][fi], w[fi]);
726 printf(
" fitted parameters:");
727 for(pi=0; pi<parNr; pi++) printf(
" %g", fit.
voi[ri].
p[pi]);
731 if(verbose>1) printf(
"Checking the MRL.\n");
733 if(fi>3 && fi>fitdataNr/3) {
735 fprintf(stderr,
"Error: bad fit.\n");
736 fprintf(stderr,
"MRL := %d / %d\n", fi, fitdataNr);
741 if(fi>2 && fi>fitdataNr/4) {
742 fprintf(stderr,
"Warning: bad fit.\n");
743 fprintf(stderr,
"MRL := %d / %d\n", fi, fitdataNr);
744 }
else if(verbose>1) {
745 printf(
"MRL test passed.\n");
746 if(verbose>2) fprintf(stderr,
"MRL := %d / %d\n", fi, fitdataNr);
750 double wss[1+metabNr], f=0.0;
751 for(ai=0; ai<=metabNr; ai++) {
753 for(fi=0; fi<fitdataNr; fi++) {
757 f+=wss[ai]; printf(
"WSS[%d] := %g\n", ai+1, wss[ai]);
759 printf(
"WSS[total] := %g\n", f);
764 for(ai=0, m=0; ai<=metabNr; ai++)
if(frwgt[ai]>0.0)
765 for(fi=0; fi<fitdataNr; fi++)
if(w[fi]>0.0) m++;
766 printf(
"nr_of_fitted_samples := %d\n", m);
767 for(pi=0, n=0; pi<parNr; pi++)
if(pmax[pi]>pmin[pi]) n++;
768 printf(
"nr_of_fitted_parameters := %d\n", n);
770 printf(
"AIC := %g\n", aic);
773 printf(
"Fitted parameters:\n");
775 for(pi=0; pi<parNr; pi++) printf(
" par[%d]: %g\n", pi+1, fit.
voi[ri].
p[pi]);
776 if(verbose>4)
for(pi=0; pi<parNr; pi++)
777 printf(
" par[%d]: %g [%g, %g]\n", pi+1, fit.
voi[ri].
p[pi], pmin[pi], pmax[pi]);
780 if(model==MODEL_MPF || model==MODEL_MHILL) {
783 for(m=1; m<metabNr; m++) {
784 fit.
voi[ri].
p[(m+1)*n-1]+=fit.
voi[ri].
p[n-1];
788 for(ri=1; ri<fit.
voiNr; ri++) {
793 if(model==MODEL_HILL && ffile_type==2) {
801 if((verbose>1) && strcmp(ffile,
"stdout")!=0) printf(
"saving results in %s\n", ffile);
802 ret=
fitWrite(&fit, ffile);
if(ret) {
803 fprintf(stderr,
"Error (%d) in writing '%s': %s\n", ret, ffile,
fiterrmsg);
806 if(strcmp(ffile,
"stdout")!=0 && verbose>0)
807 printf(
"Function parameters written in %s\n", ffile);
814 if(verbose>1) printf(
"creating SVG plot\n");
816 char tmp[FILENAME_MAX];
818 if(verbose>1) printf(
"calculating fitted curve at automatically generated sample times\n");
822 fprintf(stderr,
"Error %d in memory allocation for fitted curves.\n", ret);
826 for(fi=0; fi<adft.
frameNr; fi++) adft.
w[fi]=1.0;
828 for(ri=0; ri<adft.
voiNr; ri++) {
829 yfit[ri]=adft.
voi[ri].
y;
830 ymeas[ri]=adft.
voi[ri].
y2;
833 for(ri=0, ret=0; ri<adft.
voiNr; ri++) {
834 for(fi=0; fi<adft.
frameNr; fi++) {
835 ret=
fitEval(&fit.
voi[ri], adft.
x[fi], &a);
if(ret!=0)
break;
836 adft.
voi[ri].
y[fi]=a;
841 fprintf(stderr,
"Error: cannot calculate fitted curve for '%s'.\n", svgfile);
847 if(verbose>1) printf(
"writing %s\n", svgfile);
850 ret=
plot_fitrange_svg(&dft, &adft, tmp, 0.0, nan(
""), 0.0, 1.0, svgfile, verbose-8);
852 fprintf(stderr,
"Error (%d) in writing '%s'.\n", ret, svgfile);
856 if(verbose>0) printf(
"Plots written in %s\n", svgfile);
873double func_pf(
int parNr,
double *p,
void *fdata)
876 double a, b, c, d, dt, v, f, wss;
881 for(i=0; i<parNr; i++) printf(
" p[%d]=%g", i, p[i]);
886 a=pa[0]; b=pa[1]; c=pa[2]; d=pa[3]; dt=pa[4];
890 for(i=0, wss=0.0; i<fitdataNr; i++)
if(w[i]>0.0) {
891 if(x[i]<=dt) yfit[0][i]=d;
892 else yfit[0][i]=pow(f+pow(a*(x[i]-dt), b), -c);
893 v=yfit[0][i]-ymeas[0][i];
894 if(min_meas==MINMEAS_LAD) v=fabs(v);
895 else if(min_meas==MINMEAS_OLS) v*=v;
896 else if(min_meas==MINMEAS_ODR) {
899 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);
900 if(!isfinite(df)) df=0.0;
902 v*=v; v/=(1.0 + df*df);
906 lastWSS=wss; wss*=penalty;
907 if(0) printf(
"%g %g %g %g %g -> %g\n", a, b, c, d, dt, wss);
911double func_hill(
int parNr,
double *p,
void *fdata)
914 double a, b, c, d, dt, v, wss;
919 for(i=0; i<parNr; i++) printf(
" p[%d]=%g", i, p[i]);
924 a=pa[0]; b=pa[1]; c=pa[2]; d=pa[3]; dt=pa[4];
927 penalty+=100.0*(a/d);
932 for(i=0, wss=0.0; i<fitdataNr; i++)
if(w[i]>0.0) {
936 double f=pow(x[i]-dt, b);
937 yfit[0][i]= d + (a-d)*f/(c+f);
939 v=yfit[0][i]-ymeas[0][i];
940 if(min_meas==MINMEAS_LAD) v=fabs(v);
941 else if(min_meas==MINMEAS_OLS) v*=v;
942 else if(min_meas==MINMEAS_ODR) {
944 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);
945 if(!isfinite(df)) df=0.0;
947 v*=v; v/=(1.0 + df*df);
951 lastWSS=wss; wss*=penalty;
953 if(0) printf(
"%g %g %g %g %g -> %g\n", a, b, c, d, dt, wss);
957double func_gcdf(
int parNr,
double *p,
void *fdata)
960 double a, b, c, d, dt, v, wss;
965 for(i=0; i<parNr; i++) printf(
" p[%d]=%g", i, p[i]);
970 a=pa[0]; b=pa[1]; c=pa[2]; d=pa[3]; dt=pa[4];
972 for(i=0, wss=0.0; i<fitdataNr; i++)
if(w[i]>0.0) {
976 yfit[0][i]= a*(1.0-b*
igam(d, c*(x[i]-dt)));
978 v=yfit[0][i]-ymeas[0][i];
979 if(min_meas==MINMEAS_LAD) v=fabs(v);
984 lastWSS=wss; wss*=penalty;
986 if(0) printf(
"%g %g %g %g %g -> %g\n", a, b, c, d, dt, wss);
990double func_ep(
int parNr,
double *p,
void *fdata)
993 double a, b, c, d, dt, s, v, wss;
998 for(i=0; i<parNr; i++) printf(
" p[%d]=%g", i, p[i]);
1003 dt=pa[0]; s=pa[1]; a=pa[2]; b=pa[3]; c=pa[4]; d=pa[5];
1005 for(i=0, wss=0.0; i<fitdataNr; i++)
if(w[i]>0.0) {
1010 yfit[0][i]= a*exp(-b*xt*xt*xt/(xt*xt+c)) + (1.0-a)*exp(-d*xt);
1013 v=yfit[0][i]-ymeas[0][i];
1014 if(min_meas==MINMEAS_LAD) v=fabs(v);
1018 lastWSS=wss; wss*=penalty;
1022double func_mpf(
int parNr,
double *p,
void *fdata)
1025 double a[1+MAX_METAB_NR], b[1+MAX_METAB_NR], c[1+MAX_METAB_NR],
1026 d[1+MAX_METAB_NR], dt[1+MAX_METAB_NR];
1028 double mf[1+MAX_METAB_NR], g[1+MAX_METAB_NR], v, f, wss;
1032 for(i=0; i<parNr; i++) printf(
" p[%d]=%g", i, p[i]);
1038 for(m=0; m<metabNr; m++) {
1039 a[m]=pa[m*pn+0]; b[m]=pa[m*pn+1]; c[m]=pa[m*pn+2];
1040 d[m]=pa[m*pn+3]; dt[m]=pa[m*pn+4];
if(m>0) dt[m]+=dt[0];
1042 for(; m<MAX_METAB_NR; m++) a[m]=b[m]=c[m]=d[m]=dt[m]=0.0;
1044 for(m=1; m<metabNr; m++)
if(dt[m]<0.0) {
1045 penalty+=100.0*(-dt[m]); dt[m]=0.0;}
1048 for(m=0; m<metabNr; m++) g[m]=pow(d[m], -1.0/c[m]);
1049 for(i=0, wss=0.0; i<fitdataNr; i++)
if(w[i]>0.0) {
1050 for(m=0; m<metabNr && m<=MAX_METAB_NR; m++) {
1051 if(x[i]<=dt[m]) mf[m]=1.0 - d[m];
1052 else mf[m]=1.0 - pow(g[m]+pow(a[m]*(x[i]-dt[m]), b[m]), -c[m]);
1054 for(; m<MAX_METAB_NR; m++) mf[m]=0.0;
1056 f=1.0-mf[0]*mf[1]-mf[0]*mf[2]-mf[1]*mf[2]+2.0*mf[0]*mf[1]*mf[2];
1057 yfit[1][i]=mf[0]*(1.0-mf[1]-mf[2]+mf[1]*mf[2])/f; yfit[0][i]-=yfit[1][i];
1059 yfit[2][i]=mf[1]*(1.0-mf[0]-mf[2]+mf[0]*mf[2])/f; yfit[0][i]-=yfit[2][i];
1062 yfit[3][i]=mf[2]*(1.0-mf[0]-mf[1]+mf[0]*mf[1])/f; yfit[0][i]-=yfit[3][i];
1064 for(m=0; m<=metabNr && m<=MAX_METAB_NR; m++) {
1065 v=yfit[m][i]-ymeas[m][i];
1066 if(min_meas==MINMEAS_OLS) v*=v;
else v=fabs(v);
1067 wss+=w[i]*frwgt[m]*v;
1070 lastWSS=wss; wss*=penalty;
1075double func_mhill(
int parNr,
double *p,
void *fdata)
1078 double a[1+MAX_METAB_NR], b[1+MAX_METAB_NR], c[1+MAX_METAB_NR],
1079 d[1+MAX_METAB_NR], dt[1+MAX_METAB_NR];
1081 double mf[1+MAX_METAB_NR], v, f, wss;
1085 for(i=0; i<parNr; i++) printf(
" p[%d]=%g", i, p[i]);
1091 for(m=0; m<metabNr; m++) {
1092 a[m]=pa[m*pn+0]; b[m]=pa[m*pn+1]; c[m]=pa[m*pn+2];
1093 d[m]=pa[m*pn+3]; dt[m]=pa[m*pn+4];
if(m>0) dt[m]+=dt[0];
1096 penalty+=100.0*(a[m]/d[m]);
1100 for(; m<MAX_METAB_NR; m++) a[m]=b[m]=c[m]=d[m]=dt[m]=0.0;
1102 for(m=1; m<metabNr; m++)
if(dt[m]<0.0) {
1103 penalty+=100.0*(-dt[m]); dt[m]=0.0;}
1106 for(i=0, wss=0.0; i<fitdataNr; i++)
if(w[i]>0.0) {
1107 for(m=0; m<metabNr && m<=MAX_METAB_NR; m++) {
1111 f=pow(x[i]-dt[m], b[m]);
1112 mf[m]=1.0 - (d[m] + (a[m]-d[m])*f/(c[m]+f));
1115 for(; m<MAX_METAB_NR; m++) mf[m]=0.0;
1117 f=1.0-mf[0]*mf[1]-mf[0]*mf[2]-mf[1]*mf[2]+2.0*mf[0]*mf[1]*mf[2];
1118 yfit[1][i]=mf[0]*(1.0-mf[1]-mf[2]+mf[1]*mf[2])/f; yfit[0][i]-=yfit[1][i];
1120 yfit[2][i]=mf[1]*(1.0-mf[0]-mf[2]+mf[0]*mf[2])/f; yfit[0][i]-=yfit[2][i];
1123 yfit[3][i]=mf[2]*(1.0-mf[0]-mf[1]+mf[0]*mf[1])/f; yfit[0][i]-=yfit[3][i];
1125 for(m=0; m<=metabNr && m<=MAX_METAB_NR; m++) {
1126 v=yfit[m][i]-ymeas[m][i];
1127 if(min_meas==MINMEAS_OLS) v*=v;
else v=fabs(v);
1128 wss+=w[i]*frwgt[m]*v;
1131 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]