TPCCLIB
Loading...
Searching...
No Matches
fit_fexp.c
Go to the documentation of this file.
1
8/*****************************************************************************/
9#include "tpcclibConfig.h"
10/*****************************************************************************/
11#include <stdio.h>
12#include <stdlib.h>
13#include <math.h>
14#include <string.h>
15#include <time.h>
16/*****************************************************************************/
17#include "libtpcmisc.h"
18#include "libtpcmodel.h"
19#include "libtpccurveio.h"
20#include "libtpcsvg.h"
21#include "libtpcmodext.h"
22/*****************************************************************************/
23double *x, *ymeas, *yfit, *w;
24int fitdataNr=0, parNr=3;
25double pmin[MAX_PARAMETERS], pmax[MAX_PARAMETERS];
26double lastWSS;
27double func351(int parNr, double *p, void*);
28double funcMono(int parNr, double *p, void*);
29/*****************************************************************************/
30
31/*****************************************************************************/
32static char *info[] = {
33 "Fits the following exponential function to plasma parent (unchanged) tracer",
34 "fraction curve, where fractions are between 0 and 1 (1,2).",
35 " ",
36 " -B*x -C*x ",
37 " f(x) = 1 - A * (2 - e -e ) , where 0<A<=1 , B>0 , C>0 ",
38 " ",
39 "Optionally a monoexponential function, where fractions are between A and B,",
40 "can be applied instead:",
41 " -C*x ",
42 " f(x) = (A-B) * e + B , where 0<A<=1 , B>=0 , C>0 ",
43 " ",
44 "Usage: @P [Options] fractionfile [fitfile]",
45 " ",
46 "Options:",
47 " -mono",
48 " Use monoexponential function.",
49 " -a=<value> or -a=zero",
50 " Parent fraction at time zero (A) is fixed to given value, or to",
51 " the value of zero sample, if available.",
52 " Applicable only with monoexponential function.",
53 " -WC",
54 " The last data column contains sample weights.",
55 " -W1",
56 " All weights are set to 1.0 (no weighting)",
57 " -WF",
58 " Less frequent samples are given more weight.",
59 " -ND",
60 " Some fractions are known to exceed 1, not divided by 100.",
61 " -MRL",
62 " Error is returned if MRL check is not passed.",
63 " -svg=<Filename>",
64 " Fitted and measured TACs are plotted in specified SVG file.",
65 " -stdoptions", // List standard options like --help, -v, etc
66 " ",
67 "Fraction datafile must contain two columns, sample times (min) and fractions",
68 "of parent tracer. Weights can be specified as specified in DFT format (4);",
69 "any additional columns are ignored.",
70 "Lines that start with a '#' are not read from the datafile.",
71 "Program writes the fit start and end times, nr of points, WSS/n,",
72 "and parameters of the fitted function to the FIT file (5).",
73 " ",
74 "References:",
75 "1. Fitting the fractions of parent tracer in plasma.",
76 " https://www.turkupetcentre.net/petanalysis/input_parent_fitting.html",
77 "2. Kropholler MA, Boellaard R, Schuitemaker A, van Berckel BNM, Luurtsema G,",
78 " Windhorst AD, Lammertsma AA. Development of a tracer kinetic plasma input",
79 " model for (R)-[11C]PK11195 brain studies. J Cereb Blood Flow Metab. 2005;",
80 " 25(7): 842-851.",
81 "4. https://www.turkupetcentre.net/petanalysis/format_tpc_dft.html",
82 "5. https://www.turkupetcentre.net/petanalysis/format_tpc_fit.html",
83 " ",
84 "See also: fit2dat, metabcor, avgfract, fit_ppf, fit_dexp, tac2svg",
85 " ",
86 "Keywords: input, plasma, modelling, simulation, metabolite correction",
87 0};
88/*****************************************************************************/
89
90/*****************************************************************************/
91/* Turn on the globbing of the command line, since it is disabled by default in
92 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
93 In Unix&Linux wildcard command line processing is enabled by default. */
94/*
95#undef _CRT_glob
96#define _CRT_glob -1
97*/
98int _dowildcard = -1;
99/*****************************************************************************/
100
101/*****************************************************************************/
105int main(int argc, char **argv)
106{
107 int ai, help=0, version=0, verbose=1;
108 int fi, pi, ri, type=351, ret, m, n;
109 int noDivide=0;
110 int MRL_check=0; // 0=off, 1=on
111 double fixed_a=nan("");
112 int fixed0=0; // fix fraction at time zero to measured value at time zero, if available
113 char *cptr;
114 char dfile[FILENAME_MAX], ffile[FILENAME_MAX], svgfile[FILENAME_MAX];
115 DFT dft;
116 FIT fit;
117 double a, tstart, tstop, d, maxfract, aic;
118 // Weights: 0=left as it is in datafile, 1=set to 1, 2=sampling frequency
119 int weighting=0;
120 int last_col_is_weight=0;
121
122#ifdef MINGW
123 // Use Unix/Linux default of two-digit exponents in MinGW on Windows
124 _set_output_format(_TWO_DIGIT_EXPONENT);
125#endif
126
127
128
129 /*
130 * Get arguments
131 */
132 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
133 dftInit(&dft); fitInit(&fit);
134 dfile[0]=ffile[0]=svgfile[0]=(char)0;
135 /* Options */
136 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') {
137 cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(cptr==NULL) continue;
138 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
139 if(strcasecmp(cptr, "ND")==0) {
140 noDivide=1; continue;
141 } else if(strcasecmp(cptr, "MONO")==0) {
142 type=302; parNr=4; continue;
143 } else if(strcasecmp(cptr, "A=ZERO")==0 || strcasecmp(cptr, "A=0")==0) {
144 fixed0=1; continue;
145 } else if(strncasecmp(cptr, "A=", 2)==0) {
146 fixed_a=atof_dpi(cptr+2); if(fixed_a>0.0) continue;
147 } else if(strcasecmp(cptr, "W1")==0) {
148 weighting=1; continue;
149 } else if(strcasecmp(cptr, "WF")==0) {
150 weighting=2; continue;
151 } else if(strcasecmp(cptr, "WC")==0) {
152 last_col_is_weight=1; continue;
153 } else if(strcasecmp(cptr, "MRL")==0) {
154 MRL_check=1; continue;
155 } else if(strncasecmp(cptr, "SVG=", 4)==0 && strlen(cptr)>4) {
156 strlcpy(svgfile, cptr+4, FILENAME_MAX); continue;
157 }
158 /* we should never get this far */
159 fprintf(stderr, "Error: invalid option '%s'.\n", argv[ai]);
160 return(1);
161 } else break;
162
163 /* Print help or version? */
164 if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
165 if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
166 if(version) {tpcPrintBuild(argv[0], stdout); return(0);}
167
168 /* Process other arguments, starting from the first non-option */
169 if(ai<argc) strlcpy(dfile, argv[ai++], FILENAME_MAX);
170 if(ai<argc) strlcpy(ffile, argv[ai++], FILENAME_MAX);
171 if(ai<argc) {fprintf(stderr, "Error: too many arguments: '%s'.\n", argv[ai]); return(1);}
172
173 /* Is something missing? */
174 if(!dfile[0]) {
175 fprintf(stderr, "Error: missing command-line argument; use option --help\n");
176 return(1);
177 }
178 if(!ffile[0]) strcpy(ffile, "stdout");
179 if(verbose>6) MATHFUNC_TEST=verbose-6; else MATHFUNC_TEST=0;
180 if(verbose>6) CSV_TEST=verbose-6; else CSV_TEST=0;
181
182
183 /* In verbose mode print arguments and options */
184 if(verbose>1) {
185 printf("dfile := %s\n", dfile);
186 printf("ffile := %s\n", ffile);
187 printf("svgfile := %s\n", svgfile);
188 printf("noDivide := %d\n", noDivide);
189 printf("weighting := %d\n", weighting);
190 printf("last_col_is_weight := %d\n", last_col_is_weight);
191 printf("fixed0 := %d\n", fixed0);
192 printf("MRL_check := %d\n", MRL_check);
193 printf("type := %d\n", type);
194 printf("parNr := %d\n", parNr);
195 }
196
197
198 /*
199 * Read data
200 */
201 if(verbose>1) printf("reading %s\n", dfile);
202 if(dftRead(dfile, &dft)) {
203 fprintf(stderr, "Error in reading '%s': %s\n", dfile, dfterrmsg);
204 return(2);
205 }
206 if(dft.frameNr<2) { // More precise testing later
207 fprintf(stderr, "Error: too few samples for fitting in %s\n", dfile);
208 dftEmpty(&dft); return(2);
209 }
210 fitdataNr=dft.frameNr;
211
212 /* If required, set the last column as weights */
213 if(last_col_is_weight!=0) {
214 if(verbose>1) printf("reading weights from the last column.\n");
215 if(dft.voiNr<2) {
216 fprintf(stderr, "Error: no column for weights in %s\n", dfile);
217 dftEmpty(&dft); return(2);
218 }
219 for(fi=0; fi<dft.frameNr; fi++) {
220 dft.w[fi]=dft.voi[dft.voiNr-1].y[fi];
221 if(isnan(dft.w[fi])) dft.w[fi]=0.0;
222 }
223 dft.isweight=1; dft.voiNr--;
224 }
225
226 if(verbose>1) {
227 if(strlen(dft.studynr)>0 && strcmp(dft.studynr, ".")!=0)
228 printf("study_number := %s\n", dft.studynr);
229 printf("tacNr := %d\n", dft.voiNr);
230 }
231
232
233 /* Ignore extra columns */
234 if(dft.voiNr>1) {
235 fprintf(stderr, "Warning: extra columns in %s are ignored.\n", dfile);
236 dft.voiNr=1;
237 }
238
239 /* Sort the samples by time in case data is catenated from several curves */
240 (void)dftSortByFrame(&dft);
241
242 /* Make sure that times are in minutes */
243 if(dft.timeunit==TUNIT_SEC) {
244 if(verbose>1) printf("Sample times are converted to min\n");
245 dftSec2min(&dft);
246 }
247 if(dft.timeunit==TUNIT_UNKNOWN) {
248 dft.timeunit=TUNIT_MIN;
249 }
250
251 /* Set the names for TAC */
252 if(strlen(dft.voi[0].name)==0) {
253 strcpy(dft.voi[0].name, "Parent");
254 strcpy(dft.voi[0].voiname, dft.voi[0].name);
255 }
256
257 /* Get start and end times */
258 ret=dftMinMax(&dft, &tstart, &tstop, NULL, &maxfract);
259 if(ret!=0) {
260 fprintf(stderr, "Error: invalid contents in %s\n", dfile);
261 dftEmpty(&dft); return(2);
262 }
263 /* Check that x values are >=0 and that there is range in x values */
264 if(tstart<0.0 || !(tstop>tstart)) {
265 fprintf(stderr, "Error: invalid sample times.\n");
266 dftEmpty(&dft); return(2);
267 }
268 /* Check that y values are <=1 */
269 if(maxfract>100.0 || maxfract<0.001) {
270 fprintf(stderr, "Error: invalid fraction values.\n");
271 dftEmpty(&dft); return(2);
272 }
273 if(noDivide==0 && maxfract>1.0) {
274 fprintf(stderr, "Warning: converting percentages to fractions.\n");
275 for(fi=0; fi<dft.frameNr; fi++) for(ri=0; ri<dft.voiNr; ri++)
276 if(!isnan(dft.voi[ri].y[fi])) dft.voi[ri].y[fi]/=100.0;
277 /* make sure that units are not percentages any more */
278 dftUnitToDFT(&dft, CUNIT_UNITLESS);
279 }
280 if(verbose>9) dftPrint(&dft);
281
282 /* Check and set weights */
283 if(dft.isweight==0 || weighting==1) {
284 dft.isweight=1;
285 for(fi=0; fi<dft.frameNr; fi++) dft.w[fi]=1.0;
286 }
287 if(weighting==2) { // weighting by sample frequency
288 dftWeightByFreq(&dft); // must be sorted by time before this
289 }
290 /* Set sample weights to zero, if parent fraction is NaN */
291 for(fi=0; fi<dft.frameNr; fi++) if(isnan(dft.voi[0].y[fi])) dft.w[fi]=0;
292 if(verbose>1) {
293 printf("data_weights := %g", dft.w[0]);
294 for(fi=1; fi<dft.frameNr; fi++) printf(", %g", dft.w[fi]);
295 printf("\n");
296 }
297
298 /* If there is zero sample, then get its value */
299 double y0=nan("");
300 if(fabs(tstart)<1.0E-08) {
301 /* There might be more than one zero samples, thus get the mean */
302 int n=0; y0=0.0;
303 for(int i=0; i<fitdataNr; i++) if(fabs(dft.x[i])<1.0E-08) {y0+=dft.voi[0].y[i]; n++;}
304 if(n>1) y0/=(double)n;
305 if(y0>0.0 && y0<=1.0) {
306 if(verbose>1) {printf("initial_fraction := %g\n", y0); fflush(stdout);}
307 } else {
308 y0=nan("");
309 }
310 }
311
312
313 /*
314 * Allocate memory for fits
315 */
316 if(verbose>1) printf("allocating memory for fits.\n");
317 ret=fit_allocate_with_dft(&fit, &dft);
318 if(ret) {
319 fprintf(stderr, "Error: cannot allocate space for fit results (%d).\n", ret);
320 dftEmpty(&dft); fitEmpty(&fit); return(4);
321 }
322 /* Set necessary information in fit data structure */
323 fit.voiNr=dft.voiNr;
324 strlcpy(fit.datafile, dfile, FILENAME_MAX);
325 tpcProgramName(argv[0], 1, 1, fit.program, 256);
326 fit.time=time(NULL);
327 for(fi=n=0; fi<fitdataNr; fi++)
328 if(dft.x[fi]>=0.0 && !isnan(dft.voi[0].y[fi])) n++;
329 for(ri=0; ri<fit.voiNr; ri++) {
330 fit.voi[ri].type=type;
331 fit.voi[ri].parNr=parNr;
332 fit.voi[ri].start=tstart; fit.voi[ri].end=tstop;
333 fit.voi[ri].dataNr=n;
334 }
335
336
337 /*
338 * Fit
339 */
340 if(verbose>1) printf("fitting\n");
341 ri=0;
342 /* Set data pointers */
343 x=dft.x; ymeas=dft.voi[ri].y; yfit=dft.voi[ri].y2; w=dft.w;
344 /* Set the initial values for parameters */
345 fit.voi[ri].wss=3.402823e+38;
346
347 /* Set parameter constraints */
348 if(type==302) {
349 pmin[0]=0.0; pmax[0]=1.0;
350 pmin[1]=0.0; pmax[1]=1.0;
351 pmin[2]=0.0; pmax[2]=1.5;
352 if(!isnan(fixed_a)) {pmin[0]=pmax[0]=fixed_a; pmax[1]=fixed_a;}
353 else if(fixed0 && !isnan(y0)) {pmin[0]=pmax[0]=y0; pmax[1]=y0;}
354 } else {
355 pmin[0]=0.0; pmax[0]=0.5;
356 pmin[1]=0.0; pmax[1]=1.0;
357 pmin[2]=0.0; pmax[2]=0.5;
358 }
359 if(verbose>2) {
360 printf("Constraints for the 1st fit:\n");
361 for(pi=0; pi<parNr; pi++)
362 printf(" %g - %g\n", pmin[pi], pmax[pi]);
363 }
364
365
366 /*
367 * Check that sample number (not including NaNs) is at least one more
368 * than the number of actually fitted parameters.
369 */
370 for(fi=n=0; fi<fitdataNr; fi++) {
371 if(dft.x[fi]<0.0) continue;
372 if(dft.w[fi]>0.0) n++;
373 }
374 for(pi=m=0; pi<parNr; pi++) if(pmin[pi]<pmax[pi]) m++;
375 if(verbose>1) printf("Comparison of nr of samples and params to fit: %d / %d\n", n, m);
376 if((n-1)<m) {
377 fprintf(stderr, "Error: too few samples for fitting in %s\n", dfile);
378 if(verbose>0) printf("n := %d\nm := %d\n", n, m);
379 dftEmpty(&dft); fitEmpty(&fit); return(2);
380 }
381
382
383
384 /* fit */
386 TGO_LOCAL_OPT=0; // 0=Powell-Brent, 1=Bobyqa
388 int neighNr=5, iterNr=1, sampleNr=1000;
389 if(type==351)
390 ret=tgo(pmin, pmax, func351, NULL, parNr, neighNr, &fit.voi[ri].wss,
391 fit.voi[ri].p, sampleNr, iterNr, verbose-8);
392 else
393 ret=tgo(pmin, pmax, funcMono, NULL, parNr, neighNr, &fit.voi[ri].wss,
394 fit.voi[ri].p, sampleNr, iterNr, verbose-8);
395 if(ret) {
396 fprintf(stderr, "Error %d in TGO.\n", ret);
397 dftEmpty(&dft); fitEmpty(&fit);
398 return(4);
399 }
400 if(verbose>4) {
401 printf("Results from tgo():\n");
402 for(pi=0; pi<parNr; pi++)
403 printf(" parameter[%d] := %g\n", pi, fit.voi[ri].p[pi]);
404 printf("WSS := %g\n", fit.voi[ri].wss);
405 }
406 fit.voi[ri].wss=lastWSS; // remove penalty from reported WSS (do not use a)
407 if(verbose>5) printf("lastWSS := %g\n", lastWSS);
408 /* Correct fitted parameters to match constraints like inside the function */
409 (void)modelCheckParameters(parNr, pmin, pmax, fit.voi[ri].p, fit.voi[ri].p, NULL);
410
411 /* Further processing with bi-exponential */
412 if(type==351) {
413
414 /* Sort b and c */
415 if(fit.voi[ri].p[1]<fit.voi[ri].p[2]) {
416 a=fit.voi[ri].p[1]; fit.voi[ri].p[1]=fit.voi[ri].p[2]; fit.voi[ri].p[2]=a;
417 a=pmin[1]; pmin[1]=pmin[2]; pmin[2]=a;
418 a=pmax[1]; pmax[1]=pmax[2]; pmax[2]=a;
419 }
420
421 /* If b and c are about the same, fit again only a and b, with c=0 */
422 d=fabs(fit.voi[ri].p[1]-fit.voi[ri].p[2]);
423 a=0.5*(fit.voi[ri].p[1]+fit.voi[ri].p[2]);
424 if(verbose>1) printf("|b-c|=%g mean(b, c)=%g\n", d, a);
425 if(a>0.0 && d/a<0.01) {
426 if(verbose>1) printf("Fitting again with only one exponential...\n");
427 pmin[0]=0.0; pmax[0]=1.0;
428 pmin[1]=0.0; pmax[1]=1.5;
429 pmin[2]=0.0; pmax[2]=0.0;
430 if(verbose>2) {
431 printf("Constraints for the 2nd fit:\n");
432 for(pi=0; pi<parNr; pi++)
433 printf(" %g - %g\n", pmin[pi], pmax[pi]);
434 }
435 neighNr=4, iterNr=1, sampleNr=1000;
436 ret=tgo(pmin, pmax, func351, NULL, parNr, neighNr, &fit.voi[ri].wss,
437 fit.voi[ri].p, sampleNr, iterNr, verbose-8);
438 if(ret) {
439 fprintf(stderr, "Error %d in TGO.\n", ret);
440 dftEmpty(&dft); fitEmpty(&fit);
441 return(4);
442 }
443 fit.voi[ri].wss=lastWSS; // non-penalized WSS
444 /* Correct fitted parameters to match constraints like inside the function */
445 (void)modelCheckParameters(parNr, pmin, pmax, fit.voi[ri].p, fit.voi[ri].p, NULL);
446 }
447 /* Warn user about parameters that collide with limits */
448 if(verbose>1) {
449 ret=modelCheckLimits(parNr, pmin, pmax, fit.voi[ri].p);
450 if(ret==0) {if(verbose>2) fprintf(stdout, "ok\n");}
451 else fprintf(stderr, "warning, fit collided with the limits.\n");
452 }
453 if(verbose>1) fprintf(stdout, "WSS := %g\n", fit.voi[ri].wss);
454 }
455
456
457 /* Further processing with monoexponential */
458 if(type==302) {
459 // Function has four parameters, and order is not the same
460 // f(x)=(A-B)*exp(-C*x)+B
461 // f(x)=A*exp(B*x)+C*exp(D*x)
462 double a=fit.voi[ri].p[0]-fit.voi[ri].p[1];
463 double b=-fit.voi[ri].p[2];
464 double c=fit.voi[ri].p[1];
465 double d=0.0;
466 fit.voi[ri].p[0]=a;
467 fit.voi[ri].p[1]=b;
468 fit.voi[ri].p[2]=c;
469 fit.voi[ri].p[3]=d;
470 }
471
472 /* Print measured and fitted curve */
473 if(verbose>3) {
474 printf(" Measured Fitted:\n");
475 for(fi=0; fi<fitdataNr; fi++)
476 if(!isnan(ymeas[fi]))
477 printf(" %2d: %9.2e %9.2e %9.2e\n", fi+1, x[fi], ymeas[fi], yfit[fi]);
478 else
479 printf(" %2d: %9.2e %-9.9s %9.2e\n", fi+1, x[fi], ".", yfit[fi]);
480 printf(" fitted parameters:");
481 for(pi=0; pi<parNr; pi++) printf(" %g", fit.voi[ri].p[pi]);
482 printf("\n");
483 }
484
485 /* Check the MRL */
486 if(verbose>1) printf("Checking the MRL.\n");
487 fi=mrl_between_tacs(yfit, ymeas, fitdataNr);
488 if(fi>3 && fi>fitdataNr/3) {
489 if(MRL_check!=0) {
490 fprintf(stderr, "Error: bad fit.\n");
491 fprintf(stderr, "MRL := %d / %d\n", fi, fitdataNr);
492 dftEmpty(&dft); fitEmpty(&fit);
493 return(7);
494 }
495 }
496 if(fi>2 && fi>fitdataNr/4) {
497 fprintf(stderr, "Warning: bad fit.\n");
498 fprintf(stderr, "MRL := %d / %d\n", fi, fitdataNr);
499 } else if(verbose>1) {
500 printf("MRL test passed.\n");
501 if(verbose>2) fprintf(stderr, "MRL := %d / %d\n", fi, fitdataNr);
502 }
503
504
505 /* Calculate AIC */
506 if(verbose>1) {
507 int m;
508 for(fi=0, m=0; fi<fitdataNr; fi++) if(w[fi]>0.0) m++;
509 for(pi=0, n=0; pi<parNr; pi++) if(pmax[pi]>pmin[pi]) n++;
510 printf("nr_of_fitted_parameters := %d\n", n);
511 aic=aicSS(fit.voi[ri].wss, m, n);
512 printf("AIC := %g\n", aic);
513 }
514
515
516 /*
517 * Save fit results
518 */
519 if(verbose>1 && strcmp(ffile, "stdout")!=0) printf("saving results\n");
520 ret=fitWrite(&fit, ffile); if(ret) {
521 fprintf(stderr, "Error (%d) in writing '%s': %s\n", ret, ffile, fiterrmsg);
522 dftEmpty(&dft); fitEmpty(&fit); return(11);
523 }
524 if(strcmp(ffile, "stdout")!=0 && verbose>0)
525 printf("Function parameters written in %s\n", ffile);
526
527
528 /*
529 * Plot fitted curves
530 */
531 if(svgfile[0]) {
532 if(verbose>1) printf("creating SVG plot\n");
533 DFT adft;
534 char tmp[FILENAME_MAX];
535
536 if(verbose>1) printf("calculating fitted curve at automatically generated sample times\n");
537 dftInit(&adft);
538 ret=dftAutointerpolate(&dft, &adft, 1.10*dft.x[dft.frameNr-1], verbose-7);
539 if(ret) {
540 fprintf(stderr, "Error %d in memory allocation for fitted curves.\n", ret);
541 dftEmpty(&dft); fitEmpty(&fit); dftEmpty(&adft);
542 return(13);
543 }
544 for(fi=0; fi<adft.frameNr; fi++) adft.w[fi]=1.0;
545 for(ri=0, ret=0; ri<adft.voiNr; ri++) {
546 for(fi=0; fi<adft.frameNr; fi++) {
547 ret=fitEval(&fit.voi[ri], adft.x[fi], &a); if(ret!=0) break;
548 adft.voi[ri].y[fi]=a;
549 }
550 if(ret!=0) break;
551 }
552 if(ret!=0) {
553 fprintf(stderr, "Error: cannot calculate fitted curve for '%s'.\n", svgfile);
554 dftEmpty(&dft); dftEmpty(&adft); fitEmpty(&fit);
555 return(14);
556 }
557
558 /* Save SVG plot of fitted and original data */
559 if(verbose>1) printf("writing %s\n", svgfile);
560 tpcProgramName(argv[0], 0, 0, tmp, 64); strcat(tmp, " ");
561 if(strlen(adft.studynr)>1) strcat(tmp, adft.studynr);
562 ret=plot_fitrange_svg(&dft, &adft, tmp, 0.0, nan(""), 0.0, 1.0, svgfile, verbose-8);
563 if(ret) {
564 fprintf(stderr, "Error (%d) in writing '%s'.\n", ret, svgfile);
565 dftEmpty(&adft); dftEmpty(&dft); fitEmpty(&fit);
566 return(30+ret);
567 }
568 if(verbose>0) printf("Plots written in %s\n", svgfile);
569
570 dftEmpty(&adft);
571 }
572
573
574 /* Free memory */
575 dftEmpty(&dft); fitEmpty(&fit);
576
577 return(0);
578}
579/*****************************************************************************/
580
581/*****************************************************************************
582 *
583 * Functions to be minimized
584 *
585 *****************************************************************************/
586double func351(int parNr, double *p, void *fdata)
587{
588 int i;
589 double pa[MAX_PARAMETERS], a, b, c, v, wss, penalty=1.0;
590
591 /* Check parameters against the constraints */
592 if(0) {
593 for(i=0; i<parNr; i++) printf(" p[%d]=%g", i, p[i]);
594 printf("\n");
595 }
596 modelCheckParameters(parNr, pmin, pmax, p, pa, &penalty);
597 if(fdata) {}
598 a=pa[0]; b=pa[1]; c=pa[2];
599 /* Calculate the curve values and weighted SS */
600 for(i=0, wss=0.0; i<fitdataNr; i++) if(w[i]>0.0) {
601 yfit[i]= 1.0 - a*(2.0-exp(-b*x[i])-exp(-c*x[i]));
602 if(yfit[i]<0.0 || yfit[i]>1.0) penalty*=2.0;
603 v=yfit[i]-ymeas[i]; wss+=w[i]*v*v;
604 }
605 lastWSS=wss;
606 wss*=penalty;
607 if(0) printf("%g %g %g -> %g\n", a, b, c, wss);
608 return(wss);
609}
610
611
612
613double funcMono(int parNr, double *p, void *fdata)
614{
615 int i;
616 double pa[MAX_PARAMETERS], a, b, c, v, wss, penalty=1.0;
617
618 /* Check parameters against the constraints */
619 if(0) {
620 for(i=0; i<parNr; i++) printf(" p[%d]=%g", i, p[i]);
621 printf("\n");
622 }
623 modelCheckParameters(parNr, pmin, pmax, p, pa, &penalty);
624 if(fdata) {}
625 a=pa[0]; b=pa[1]; c=pa[2];
626 /* Calculate the curve values and weighted SS */
627 for(i=0, wss=0.0; i<fitdataNr; i++) if(w[i]>0.0) {
628 yfit[i]= (a-b)*exp(-c*x[i]) + b;
629 if(yfit[i]<0.0 || yfit[i]>1.0) penalty*=2.0;
630 v=yfit[i]-ymeas[i]; wss+=w[i]*v*v;
631 }
632 lastWSS=wss;
633 wss*=penalty;
634 if(0) printf("%g %g %g -> %g\n", a, b, c, wss);
635 return(wss);
636}
637/*****************************************************************************/
638
639/*****************************************************************************/
641
double aicSS(double ss, const int n, const int k)
Definition aic.c:20
int modelCheckParameters(int par_nr, double *lower_p, double *upper_p, double *test_p, double *accept_p, double *penalty)
Definition constraints.c:15
int modelCheckLimits(int par_nr, double *lower_p, double *upper_p, double *test_p)
Definition constraints.c:59
int CSV_TEST
Definition csv.c:6
double atof_dpi(char *str)
Definition decpoint.c:59
void dftInit(DFT *data)
Definition dft.c:38
char dfterrmsg[64]
Definition dft.c:6
int dftSortByFrame(DFT *dft)
Definition dft.c:1169
int dftMinMax(DFT *dft, double *minx, double *maxx, double *miny, double *maxy)
Definition dft.c:974
void dftEmpty(DFT *data)
Definition dft.c:20
int dftRead(char *filename, DFT *data)
Definition dftio.c:22
void dftPrint(DFT *data)
Definition dftio.c:538
void dftUnitToDFT(DFT *dft, int dunit)
Definition dftunit.c:11
void dftSec2min(DFT *dft)
Definition dftunit.c:160
int dftAutointerpolate(DFT *dft, DFT *dft2, double endtime, int verbose)
int fit_allocate_with_dft(FIT *fit, DFT *dft)
Definition fitres.c:14
Header file for libtpccurveio.
int fitEval(FitVOI *r, double x, double *y)
Definition mathfunc.c:645
void fitEmpty(FIT *fit)
Definition mathfunc.c:18
int fitWrite(FIT *fit, char *filename)
Definition mathfunc.c:54
int MATHFUNC_TEST
Definition mathfunc.c:5
char fiterrmsg[64]
Definition mathfunc.c:6
void fitInit(FIT *fit)
Definition mathfunc.c:38
Header file for libtpcmisc.
int tpcProcessStdOptions(const char *s, int *print_usage, int *print_version, int *verbose_level)
Definition proginfo.c:40
size_t strlcpy(char *dst, const char *src, size_t dstsize)
Definition strext.c:245
void tpcProgramName(const char *program, int version, int copyright, char *prname, int n)
Definition proginfo.c:101
int tpcHtmlUsage(const char *program, char *text[], const char *path)
Definition proginfo.c:213
void tpcPrintBuild(const char *program, FILE *fp)
Definition proginfo.c:383
void tpcPrintUsage(const char *program, char *text[], FILE *fp)
Definition proginfo.c:158
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)
Definition tgo.c:39
int TGO_LOCAL_INSIDE
Definition tgo.c:29
int mrl_between_tacs(double y1[], double y2[], int n)
Definition runs_test.c:103
#define MAX_PARAMETERS
Definition libtpcmodel.h:31
int TGO_LOCAL_OPT
Definition tgo.c:31
int TGO_SQUARED_TRANSF
Definition tgo.c:27
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)
Definition plotfit.c:16
Header file for libtpcsvg.
Voi * voi
int timeunit
char studynr[MAX_STUDYNR_LEN+1]
double * w
int voiNr
int frameNr
int isweight
double * x
int voiNr
char datafile[FILENAME_MAX]
char program[1024]
FitVOI * voi
time_t time
double wss
double end
double start
double p[MAX_FITPARAMS]
double * y2
char voiname[MAX_REGIONSUBNAME_LEN+1]
double * y
char name[MAX_REGIONNAME_LEN+1]