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
123
124 /*
125 * Get arguments
126 */
127 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
128 dftInit(&dft); fitInit(&fit);
129 dfile[0]=ffile[0]=svgfile[0]=(char)0;
130 /* Options */
131 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') {
132 cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(cptr==NULL) continue;
133 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
134 if(strcasecmp(cptr, "ND")==0) {
135 noDivide=1; continue;
136 } else if(strcasecmp(cptr, "MONO")==0) {
137 type=302; parNr=4; continue;
138 } else if(strcasecmp(cptr, "A=ZERO")==0 || strcasecmp(cptr, "A=0")==0) {
139 fixed0=1; continue;
140 } else if(strncasecmp(cptr, "A=", 2)==0) {
141 fixed_a=atof_dpi(cptr+2); if(fixed_a>0.0) continue;
142 } else if(strcasecmp(cptr, "W1")==0) {
143 weighting=1; continue;
144 } else if(strcasecmp(cptr, "WF")==0) {
145 weighting=2; continue;
146 } else if(strcasecmp(cptr, "WC")==0) {
147 last_col_is_weight=1; continue;
148 } else if(strcasecmp(cptr, "MRL")==0) {
149 MRL_check=1; continue;
150 } else if(strncasecmp(cptr, "SVG=", 4)==0 && strlen(cptr)>4) {
151 strlcpy(svgfile, cptr+4, FILENAME_MAX); continue;
152 }
153 /* we should never get this far */
154 fprintf(stderr, "Error: invalid option '%s'.\n", argv[ai]);
155 return(1);
156 } else break;
157
158 /* Print help or version? */
159 if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
160 if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
161 if(version) {tpcPrintBuild(argv[0], stdout); return(0);}
162
163 /* Process other arguments, starting from the first non-option */
164 if(ai<argc) strlcpy(dfile, argv[ai++], FILENAME_MAX);
165 if(ai<argc) strlcpy(ffile, argv[ai++], FILENAME_MAX);
166 if(ai<argc) {fprintf(stderr, "Error: too many arguments: '%s'.\n", argv[ai]); return(1);}
167
168 /* Is something missing? */
169 if(!dfile[0]) {
170 fprintf(stderr, "Error: missing command-line argument; use option --help\n");
171 return(1);
172 }
173 if(!ffile[0]) strcpy(ffile, "stdout");
174 if(verbose>6) MATHFUNC_TEST=verbose-6; else MATHFUNC_TEST=0;
175 if(verbose>6) CSV_TEST=verbose-6; else CSV_TEST=0;
176
177
178 /* In verbose mode print arguments and options */
179 if(verbose>1) {
180 printf("dfile := %s\n", dfile);
181 printf("ffile := %s\n", ffile);
182 printf("svgfile := %s\n", svgfile);
183 printf("noDivide := %d\n", noDivide);
184 printf("weighting := %d\n", weighting);
185 printf("last_col_is_weight := %d\n", last_col_is_weight);
186 printf("fixed0 := %d\n", fixed0);
187 printf("MRL_check := %d\n", MRL_check);
188 printf("type := %d\n", type);
189 printf("parNr := %d\n", parNr);
190 }
191
192
193 /*
194 * Read data
195 */
196 if(verbose>1) printf("reading %s\n", dfile);
197 if(dftRead(dfile, &dft)) {
198 fprintf(stderr, "Error in reading '%s': %s\n", dfile, dfterrmsg);
199 return(2);
200 }
201 if(dft.frameNr<2) { // More precise testing later
202 fprintf(stderr, "Error: too few samples for fitting in %s\n", dfile);
203 dftEmpty(&dft); return(2);
204 }
205 fitdataNr=dft.frameNr;
206
207 /* If required, set the last column as weights */
208 if(last_col_is_weight!=0) {
209 if(verbose>1) printf("reading weights from the last column.\n");
210 if(dft.voiNr<2) {
211 fprintf(stderr, "Error: no column for weights in %s\n", dfile);
212 dftEmpty(&dft); return(2);
213 }
214 for(fi=0; fi<dft.frameNr; fi++) {
215 dft.w[fi]=dft.voi[dft.voiNr-1].y[fi];
216 if(isnan(dft.w[fi])) dft.w[fi]=0.0;
217 }
218 dft.isweight=1; dft.voiNr--;
219 }
220
221 if(verbose>1) {
222 if(strlen(dft.studynr)>0 && strcmp(dft.studynr, ".")!=0)
223 printf("study_number := %s\n", dft.studynr);
224 printf("tacNr := %d\n", dft.voiNr);
225 }
226
227
228 /* Ignore extra columns */
229 if(dft.voiNr>1) {
230 fprintf(stderr, "Warning: extra columns in %s are ignored.\n", dfile);
231 dft.voiNr=1;
232 }
233
234 /* Sort the samples by time in case data is catenated from several curves */
235 (void)dftSortByFrame(&dft);
236
237 /* Make sure that times are in minutes */
238 if(dft.timeunit==TUNIT_SEC) {
239 if(verbose>1) printf("Sample times are converted to min\n");
240 dftSec2min(&dft);
241 }
242 if(dft.timeunit==TUNIT_UNKNOWN) {
243 dft.timeunit=TUNIT_MIN;
244 }
245
246 /* Set the names for TAC */
247 if(strlen(dft.voi[0].name)==0) {
248 strcpy(dft.voi[0].name, "Parent");
249 strcpy(dft.voi[0].voiname, dft.voi[0].name);
250 }
251
252 /* Get start and end times */
253 ret=dftMinMax(&dft, &tstart, &tstop, NULL, &maxfract);
254 if(ret!=0) {
255 fprintf(stderr, "Error: invalid contents in %s\n", dfile);
256 dftEmpty(&dft); return(2);
257 }
258 /* Check that x values are >=0 and that there is range in x values */
259 if(tstart<0.0 || !(tstop>tstart)) {
260 fprintf(stderr, "Error: invalid sample times.\n");
261 dftEmpty(&dft); return(2);
262 }
263 /* Check that y values are <=1 */
264 if(maxfract>100.0 || maxfract<0.001) {
265 fprintf(stderr, "Error: invalid fraction values.\n");
266 dftEmpty(&dft); return(2);
267 }
268 if(noDivide==0 && maxfract>1.0) {
269 fprintf(stderr, "Warning: converting percentages to fractions.\n");
270 for(fi=0; fi<dft.frameNr; fi++) for(ri=0; ri<dft.voiNr; ri++)
271 if(!isnan(dft.voi[ri].y[fi])) dft.voi[ri].y[fi]/=100.0;
272 /* make sure that units are not percentages any more */
273 dftUnitToDFT(&dft, CUNIT_UNITLESS);
274 }
275 if(verbose>9) dftPrint(&dft);
276
277 /* Check and set weights */
278 if(dft.isweight==0 || weighting==1) {
279 dft.isweight=1;
280 for(fi=0; fi<dft.frameNr; fi++) dft.w[fi]=1.0;
281 }
282 if(weighting==2) { // weighting by sample frequency
283 dftWeightByFreq(&dft); // must be sorted by time before this
284 }
285 /* Set sample weights to zero, if parent fraction is NaN */
286 for(fi=0; fi<dft.frameNr; fi++) if(isnan(dft.voi[0].y[fi])) dft.w[fi]=0;
287 if(verbose>1) {
288 printf("data_weights := %g", dft.w[0]);
289 for(fi=1; fi<dft.frameNr; fi++) printf(", %g", dft.w[fi]);
290 printf("\n");
291 }
292
293 /* If there is zero sample, then get its value */
294 double y0=nan("");
295 if(fabs(tstart)<1.0E-08) {
296 /* There might be more than one zero samples, thus get the mean */
297 int n=0; y0=0.0;
298 for(int i=0; i<fitdataNr; i++) if(fabs(dft.x[i])<1.0E-08) {y0+=dft.voi[0].y[i]; n++;}
299 if(n>1) y0/=(double)n;
300 if(y0>0.0 && y0<=1.0) {
301 if(verbose>1) {printf("initial_fraction := %g\n", y0); fflush(stdout);}
302 } else {
303 y0=nan("");
304 }
305 }
306
307
308 /*
309 * Allocate memory for fits
310 */
311 if(verbose>1) printf("allocating memory for fits.\n");
312 ret=fit_allocate_with_dft(&fit, &dft);
313 if(ret) {
314 fprintf(stderr, "Error: cannot allocate space for fit results (%d).\n", ret);
315 dftEmpty(&dft); fitEmpty(&fit); return(4);
316 }
317 /* Set necessary information in fit data structure */
318 fit.voiNr=dft.voiNr;
319 strlcpy(fit.datafile, dfile, FILENAME_MAX);
320 tpcProgramName(argv[0], 1, 1, fit.program, 256);
321 fit.time=time(NULL);
322 for(fi=n=0; fi<fitdataNr; fi++)
323 if(dft.x[fi]>=0.0 && !isnan(dft.voi[0].y[fi])) n++;
324 for(ri=0; ri<fit.voiNr; ri++) {
325 fit.voi[ri].type=type;
326 fit.voi[ri].parNr=parNr;
327 fit.voi[ri].start=tstart; fit.voi[ri].end=tstop;
328 fit.voi[ri].dataNr=n;
329 }
330
331
332 /*
333 * Fit
334 */
335 if(verbose>1) printf("fitting\n");
336 ri=0;
337 /* Set data pointers */
338 x=dft.x; ymeas=dft.voi[ri].y; yfit=dft.voi[ri].y2; w=dft.w;
339 /* Set the initial values for parameters */
340 fit.voi[ri].wss=3.402823e+38;
341
342 /* Set parameter constraints */
343 if(type==302) {
344 pmin[0]=0.0; pmax[0]=1.0;
345 pmin[1]=0.0; pmax[1]=1.0;
346 pmin[2]=0.0; pmax[2]=1.5;
347 if(!isnan(fixed_a)) {pmin[0]=pmax[0]=fixed_a; pmax[1]=fixed_a;}
348 else if(fixed0 && !isnan(y0)) {pmin[0]=pmax[0]=y0; pmax[1]=y0;}
349 } else {
350 pmin[0]=0.0; pmax[0]=0.5;
351 pmin[1]=0.0; pmax[1]=1.0;
352 pmin[2]=0.0; pmax[2]=0.5;
353 }
354 if(verbose>2) {
355 printf("Constraints for the 1st fit:\n");
356 for(pi=0; pi<parNr; pi++)
357 printf(" %g - %g\n", pmin[pi], pmax[pi]);
358 }
359
360
361 /*
362 * Check that sample number (not including NaNs) is at least one more
363 * than the number of actually fitted parameters.
364 */
365 for(fi=n=0; fi<fitdataNr; fi++) {
366 if(dft.x[fi]<0.0) continue;
367 if(dft.w[fi]>0.0) n++;
368 }
369 for(pi=m=0; pi<parNr; pi++) if(pmin[pi]<pmax[pi]) m++;
370 if(verbose>1) printf("Comparison of nr of samples and params to fit: %d / %d\n", n, m);
371 if((n-1)<m) {
372 fprintf(stderr, "Error: too few samples for fitting in %s\n", dfile);
373 if(verbose>0) printf("n := %d\nm := %d\n", n, m);
374 dftEmpty(&dft); fitEmpty(&fit); return(2);
375 }
376
377
378
379 /* fit */
381 TGO_LOCAL_OPT=0; // 0=Powell-Brent, 1=Bobyqa
383 int neighNr=5, iterNr=1, sampleNr=1000;
384 if(type==351)
385 ret=tgo(pmin, pmax, func351, NULL, parNr, neighNr, &fit.voi[ri].wss,
386 fit.voi[ri].p, sampleNr, iterNr, verbose-8);
387 else
388 ret=tgo(pmin, pmax, funcMono, NULL, parNr, neighNr, &fit.voi[ri].wss,
389 fit.voi[ri].p, sampleNr, iterNr, verbose-8);
390 if(ret) {
391 fprintf(stderr, "Error %d in TGO.\n", ret);
392 dftEmpty(&dft); fitEmpty(&fit);
393 return(4);
394 }
395 if(verbose>4) {
396 printf("Results from tgo():\n");
397 for(pi=0; pi<parNr; pi++)
398 printf(" parameter[%d] := %g\n", pi, fit.voi[ri].p[pi]);
399 printf("WSS := %g\n", fit.voi[ri].wss);
400 }
401 fit.voi[ri].wss=lastWSS; // remove penalty from reported WSS (do not use a)
402 if(verbose>5) printf("lastWSS := %g\n", lastWSS);
403 /* Correct fitted parameters to match constraints like inside the function */
404 (void)modelCheckParameters(parNr, pmin, pmax, fit.voi[ri].p, fit.voi[ri].p, NULL);
405
406 /* Further processing with bi-exponential */
407 if(type==351) {
408
409 /* Sort b and c */
410 if(fit.voi[ri].p[1]<fit.voi[ri].p[2]) {
411 a=fit.voi[ri].p[1]; fit.voi[ri].p[1]=fit.voi[ri].p[2]; fit.voi[ri].p[2]=a;
412 a=pmin[1]; pmin[1]=pmin[2]; pmin[2]=a;
413 a=pmax[1]; pmax[1]=pmax[2]; pmax[2]=a;
414 }
415
416 /* If b and c are about the same, fit again only a and b, with c=0 */
417 d=fabs(fit.voi[ri].p[1]-fit.voi[ri].p[2]);
418 a=0.5*(fit.voi[ri].p[1]+fit.voi[ri].p[2]);
419 if(verbose>1) printf("|b-c|=%g mean(b, c)=%g\n", d, a);
420 if(a>0.0 && d/a<0.01) {
421 if(verbose>1) printf("Fitting again with only one exponential...\n");
422 pmin[0]=0.0; pmax[0]=1.0;
423 pmin[1]=0.0; pmax[1]=1.5;
424 pmin[2]=0.0; pmax[2]=0.0;
425 if(verbose>2) {
426 printf("Constraints for the 2nd fit:\n");
427 for(pi=0; pi<parNr; pi++)
428 printf(" %g - %g\n", pmin[pi], pmax[pi]);
429 }
430 neighNr=4, iterNr=1, sampleNr=1000;
431 ret=tgo(pmin, pmax, func351, NULL, parNr, neighNr, &fit.voi[ri].wss,
432 fit.voi[ri].p, sampleNr, iterNr, verbose-8);
433 if(ret) {
434 fprintf(stderr, "Error %d in TGO.\n", ret);
435 dftEmpty(&dft); fitEmpty(&fit);
436 return(4);
437 }
438 fit.voi[ri].wss=lastWSS; // non-penalized WSS
439 /* Correct fitted parameters to match constraints like inside the function */
440 (void)modelCheckParameters(parNr, pmin, pmax, fit.voi[ri].p, fit.voi[ri].p, NULL);
441 }
442 /* Warn user about parameters that collide with limits */
443 if(verbose>1) {
444 ret=modelCheckLimits(parNr, pmin, pmax, fit.voi[ri].p);
445 if(ret==0) {if(verbose>2) fprintf(stdout, "ok\n");}
446 else fprintf(stderr, "warning, fit collided with the limits.\n");
447 }
448 if(verbose>1) fprintf(stdout, "WSS := %g\n", fit.voi[ri].wss);
449 }
450
451
452 /* Further processing with monoexponential */
453 if(type==302) {
454 // Function has four parameters, and order is not the same
455 // f(x)=(A-B)*exp(-C*x)+B
456 // f(x)=A*exp(B*x)+C*exp(D*x)
457 double a=fit.voi[ri].p[0]-fit.voi[ri].p[1];
458 double b=-fit.voi[ri].p[2];
459 double c=fit.voi[ri].p[1];
460 double d=0.0;
461 fit.voi[ri].p[0]=a;
462 fit.voi[ri].p[1]=b;
463 fit.voi[ri].p[2]=c;
464 fit.voi[ri].p[3]=d;
465 }
466
467 /* Print measured and fitted curve */
468 if(verbose>3) {
469 printf(" Measured Fitted:\n");
470 for(fi=0; fi<fitdataNr; fi++)
471 if(!isnan(ymeas[fi]))
472 printf(" %2d: %9.2e %9.2e %9.2e\n", fi+1, x[fi], ymeas[fi], yfit[fi]);
473 else
474 printf(" %2d: %9.2e %-9.9s %9.2e\n", fi+1, x[fi], ".", yfit[fi]);
475 printf(" fitted parameters:");
476 for(pi=0; pi<parNr; pi++) printf(" %g", fit.voi[ri].p[pi]);
477 printf("\n");
478 }
479
480 /* Check the MRL */
481 if(verbose>1) printf("Checking the MRL.\n");
482 fi=mrl_between_tacs(yfit, ymeas, fitdataNr);
483 if(fi>3 && fi>fitdataNr/3) {
484 if(MRL_check!=0) {
485 fprintf(stderr, "Error: bad fit.\n");
486 fprintf(stderr, "MRL := %d / %d\n", fi, fitdataNr);
487 dftEmpty(&dft); fitEmpty(&fit);
488 return(7);
489 }
490 }
491 if(fi>2 && fi>fitdataNr/4) {
492 fprintf(stderr, "Warning: bad fit.\n");
493 fprintf(stderr, "MRL := %d / %d\n", fi, fitdataNr);
494 } else if(verbose>1) {
495 printf("MRL test passed.\n");
496 if(verbose>2) fprintf(stderr, "MRL := %d / %d\n", fi, fitdataNr);
497 }
498
499
500 /* Calculate AIC */
501 if(verbose>1) {
502 int m;
503 for(fi=0, m=0; fi<fitdataNr; fi++) if(w[fi]>0.0) m++;
504 for(pi=0, n=0; pi<parNr; pi++) if(pmax[pi]>pmin[pi]) n++;
505 printf("nr_of_fitted_parameters := %d\n", n);
506 aic=aicSS(fit.voi[ri].wss, m, n);
507 printf("AIC := %g\n", aic);
508 }
509
510
511 /*
512 * Save fit results
513 */
514 if(verbose>1 && strcmp(ffile, "stdout")!=0) printf("saving results\n");
515 ret=fitWrite(&fit, ffile); if(ret) {
516 fprintf(stderr, "Error (%d) in writing '%s': %s\n", ret, ffile, fiterrmsg);
517 dftEmpty(&dft); fitEmpty(&fit); return(11);
518 }
519 if(strcmp(ffile, "stdout")!=0 && verbose>0)
520 printf("Function parameters written in %s\n", ffile);
521
522
523 /*
524 * Plot fitted curves
525 */
526 if(svgfile[0]) {
527 if(verbose>1) printf("creating SVG plot\n");
528 DFT adft;
529 char tmp[FILENAME_MAX];
530
531 if(verbose>1) printf("calculating fitted curve at automatically generated sample times\n");
532 dftInit(&adft);
533 ret=dftAutointerpolate(&dft, &adft, 1.10*dft.x[dft.frameNr-1], verbose-7);
534 if(ret) {
535 fprintf(stderr, "Error %d in memory allocation for fitted curves.\n", ret);
536 dftEmpty(&dft); fitEmpty(&fit); dftEmpty(&adft);
537 return(13);
538 }
539 for(fi=0; fi<adft.frameNr; fi++) adft.w[fi]=1.0;
540 for(ri=0, ret=0; ri<adft.voiNr; ri++) {
541 for(fi=0; fi<adft.frameNr; fi++) {
542 ret=fitEval(&fit.voi[ri], adft.x[fi], &a); if(ret!=0) break;
543 adft.voi[ri].y[fi]=a;
544 }
545 if(ret!=0) break;
546 }
547 if(ret!=0) {
548 fprintf(stderr, "Error: cannot calculate fitted curve for '%s'.\n", svgfile);
549 dftEmpty(&dft); dftEmpty(&adft); fitEmpty(&fit);
550 return(14);
551 }
552
553 /* Save SVG plot of fitted and original data */
554 if(verbose>1) printf("writing %s\n", svgfile);
555 tpcProgramName(argv[0], 0, 0, tmp, 64); strcat(tmp, " ");
556 if(strlen(adft.studynr)>1) strcat(tmp, adft.studynr);
557 ret=plot_fitrange_svg(&dft, &adft, tmp, 0.0, nan(""), 0.0, 1.0, svgfile, verbose-8);
558 if(ret) {
559 fprintf(stderr, "Error (%d) in writing '%s'.\n", ret, svgfile);
560 dftEmpty(&adft); dftEmpty(&dft); fitEmpty(&fit);
561 return(30+ret);
562 }
563 if(verbose>0) printf("Plots written in %s\n", svgfile);
564
565 dftEmpty(&adft);
566 }
567
568
569 /* Free memory */
570 dftEmpty(&dft); fitEmpty(&fit);
571
572 return(0);
573}
574/*****************************************************************************/
575
576/*****************************************************************************
577 *
578 * Functions to be minimized
579 *
580 *****************************************************************************/
581double func351(int parNr, double *p, void *fdata)
582{
583 int i;
584 double pa[MAX_PARAMETERS], a, b, c, v, wss, penalty=1.0;
585
586 /* Check parameters against the constraints */
587 if(0) {
588 for(i=0; i<parNr; i++) printf(" p[%d]=%g", i, p[i]);
589 printf("\n");
590 }
591 modelCheckParameters(parNr, pmin, pmax, p, pa, &penalty);
592 if(fdata) {}
593 a=pa[0]; b=pa[1]; c=pa[2];
594 /* Calculate the curve values and weighted SS */
595 for(i=0, wss=0.0; i<fitdataNr; i++) if(w[i]>0.0) {
596 yfit[i]= 1.0 - a*(2.0-exp(-b*x[i])-exp(-c*x[i]));
597 if(yfit[i]<0.0 || yfit[i]>1.0) penalty*=2.0;
598 v=yfit[i]-ymeas[i]; wss+=w[i]*v*v;
599 }
600 lastWSS=wss;
601 wss*=penalty;
602 if(0) printf("%g %g %g -> %g\n", a, b, c, wss);
603 return(wss);
604}
605
606
607
608double funcMono(int parNr, double *p, void *fdata)
609{
610 int i;
611 double pa[MAX_PARAMETERS], a, b, c, v, wss, penalty=1.0;
612
613 /* Check parameters against the constraints */
614 if(0) {
615 for(i=0; i<parNr; i++) printf(" p[%d]=%g", i, p[i]);
616 printf("\n");
617 }
618 modelCheckParameters(parNr, pmin, pmax, p, pa, &penalty);
619 if(fdata) {}
620 a=pa[0]; b=pa[1]; c=pa[2];
621 /* Calculate the curve values and weighted SS */
622 for(i=0, wss=0.0; i<fitdataNr; i++) if(w[i]>0.0) {
623 yfit[i]= (a-b)*exp(-c*x[i]) + b;
624 if(yfit[i]<0.0 || yfit[i]>1.0) penalty*=2.0;
625 v=yfit[i]-ymeas[i]; wss+=w[i]*v*v;
626 }
627 lastWSS=wss;
628 wss*=penalty;
629 if(0) printf("%g %g %g -> %g\n", a, b, c, wss);
630 return(wss);
631}
632/*****************************************************************************/
633
634/*****************************************************************************/
636
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:618
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]