TPCCLIB
Loading...
Searching...
No Matches
fit_sinf.c
Go to the documentation of this file.
1
9/*****************************************************************************/
10#include "tpcclibConfig.h"
11/*****************************************************************************/
12#include <stdio.h>
13#include <stdlib.h>
14#include <math.h>
15#include <string.h>
16#include <time.h>
17/*****************************************************************************/
18#include "libtpcmisc.h"
19#include "libtpcmodel.h"
20#include "libtpccurveio.h"
21#include "libtpcsvg.h"
22#include "libtpcmodext.h"
23/*****************************************************************************/
24
25/*****************************************************************************/
26static char *info[] = {
27 "Non-linear fitting of the exponential based function (Wagner, 1976)",
28 "to the PET plasma or blood time-activity curve (TAC). This function can",
29 "be used when PET tracer is introduced into venous blood as a short infusion.",
30 "Function: f(t)=",
31 " if t<=Ta :",
32 " 0",
33 " if t>Ta and t<Ta+Ti :",
34 " (1/Ti)*Sum[i=1..n, (Ai/Li)*(1-exp(-Li*(t-Ta)))]",
35 " if t>=Ta+Ti :",
36 " (1/Ti)*Sum[i=1..n, (Ai/Li)*(exp(-Li*(t-Ta-Ti)) - exp(-Li*(t-Ta)))]",
37 " ",
38 "Usage: @P [Options] tacfile [parfile]",
39 " ",
40 "Options:",
41/*" -lim=<filename>",
42 " Specify the constraints for model parameters;",
43 " This file with default values can be created by giving this",
44 " option as the only command-line argument to this program.",*/
45 " -Ti=<infusion time>",
46 " Duration of tracer infusion; 0, if short bolus.",
47 " -Ta=<appearance time>",
48 " Time when tracer concentration starts ascending.",
49 " -tau1=<Dispersion time constant (s)>",
50 " -tau2=<2nd dispersion time constant (s)>",
51 " Dispersion is added to function, also to saved curve and plot.",
52 " -n=<1|2|3|4|5|A>",
53 " The nr of summed functions; A=determined automatically (default).",
54 " Changing the default may lead to a bad fit.",
55 " -wf",
56 " Weight by sampling interval.",
57 " -MRL",
58 " Error is returned if MRL check is not passed.",
59 " -res=<Filename>",
60 " Fitted parameters are also written in result file format.",
61 " -svg=<Filename>",
62 " Fitted and measured TACs are plotted in specified SVG file.",
63 " -svg1=<Filename>",
64 " Initial part of fitted and measured TACs are plotted in SVG file",
65 " -svg2=<Filename>",
66 " Lower part of fitted and measured TACs are plotted in SVG file",
67 " -fit=<Filename>",
68 " Fitted TACs are written in TAC format.",
69 " -dcfit=<Filename>",
70 " Fitted dispersion corrected TAC is written in given file;",
71 " same output as with -fit when tau1 and tau2 are not set.",
72 " -stdoptions", // List standard options like --help, -v, etc
73 " ",
74 "TAC file must contain two columns, sample times (x) and concentrations (y);",
75 "any additional columns are ignored. For a good fit, TAC should be corrected",
76 "for physical decay and circulating metabolites.",
77 "Function parameters (Ta, Ti, A1, L1, ...) will be written in the parfile.",
78 " ",
79 "References:",
80 "1. Wagner JG. J Pharmacokin Biopharm. 1976;4:443-467.",
81 "2. Kudomi N et al. Eur J Nucl Med Mol Imaging 2008;35:1899-1911.",
82 " ",
83 "See also: fit2dat, fit_feng, fit_exp, fit_ratf, extrapol, disp4dft",
84 " ",
85 "Keywords: curve fitting, input, modelling, simulation, dispersion",
86 0};
87/*****************************************************************************/
88
89/*****************************************************************************/
90/* Turn on the globbing of the command line, since it is disabled by default in
91 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
92 In Unix&Linux wildcard command line processing is enabled by default. */
93/*
94#undef _CRT_glob
95#define _CRT_glob -1
96*/
97int _dowildcard = -1;
98/*****************************************************************************/
99
100/*****************************************************************************/
101#define MAX_FUNC_NR 5
102double tau1=0.0, tau2=0.0;
103double pmin[MAX_PARAMETERS], pmax[MAX_PARAMETERS];
104int dataNr=0;
105double *x, *ymeas, *yfit, *w, *ytmp;
106double func331(int parNr, double *p, void*);
107/*****************************************************************************/
108
109/*****************************************************************************/
113int main(int argc, char **argv)
114{
115 int ai, help=0, version=0, verbose=1;
116 int ret;
117 char *cptr, progname[256];
118 char tacfile[FILENAME_MAX], fitfile[FILENAME_MAX], limfile[FILENAME_MAX],
119 parfile[FILENAME_MAX], resfile[FILENAME_MAX], svgfile[FILENAME_MAX];
120 char svgfile1[FILENAME_MAX], svgfile2[FILENAME_MAX], dcfile[FILENAME_MAX];
121 int weights=0; // 0=default, 1=no weighting, 2=frequency
122 int MRL_check=0; // 0=off, 1=on
123 double fixedTi, fixedTa;
124 int sumn=0; // Nr of summed functions: 0=automatic, otherwise 1-5.
125 DFT tac;
126 double (*func)(int parNr, double *p, void*);
127
128
129 /*
130 * Get arguments
131 */
132 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
133 tacfile[0]=fitfile[0]=dcfile[0]=limfile[0]=parfile[0]=resfile[0]=(char)0;
134 svgfile[0]=svgfile1[0]=svgfile2[0]=(char)0;
135 fixedTa=fixedTi=nan("");
136 dftInit(&tac); //fitInit(&fit);
137 tpcProgramName(argv[0], 1, 1, progname, 256);
138 /* Options */
139 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') {
140 cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(cptr==NULL) continue;
141 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
142 if(strcasecmp(cptr, "W1")==0) {
143 weights=1; continue;
144 } else if(strcasecmp(cptr, "WF")==0) {
145 weights=2; continue;
146 } else if(strcasecmp(cptr, "MRL")==0) {
147 MRL_check=1; continue;
148 } else if(strncasecmp(cptr, "SVG=", 4)==0) {
149 if(strlcpy(svgfile, cptr+4, FILENAME_MAX)>0) continue;
150 } else if(strncasecmp(cptr, "SVG1=", 5)==0) {
151 if(strlcpy(svgfile1, cptr+5, FILENAME_MAX)>0) continue;
152 } else if(strncasecmp(cptr, "SVG2=", 5)==0) {
153 if(strlcpy(svgfile2, cptr+5, FILENAME_MAX)>0) continue;
154 } else if(strncasecmp(cptr, "FIT=", 4)==0 && strlen(cptr)>4) {
155 strlcpy(fitfile, cptr+4, FILENAME_MAX); continue;
156 } else if(strncasecmp(cptr, "DCFIT=", 6)==0 && strlen(cptr)>4) {
157 strlcpy(dcfile, cptr+6, FILENAME_MAX); continue;
158 } else if(strncasecmp(cptr, "RES=", 4)==0 && strlen(cptr)>4) {
159 strlcpy(resfile, cptr+4, FILENAME_MAX); continue;
160 } else if(strncasecmp(cptr, "N=", 2)==0) {
161 cptr+=2; if(strcasecmp(cptr, "A")==0) {sumn=0; continue;}
162 sumn=atoi(cptr); if(sumn>=1 && sumn<=MAX_FUNC_NR) continue;
163 } else if(strncasecmp(cptr, "tau=", 4)==0) {
164 if(!atof_with_check(cptr+4, &tau1) && tau1>=0.0) continue;
165 } else if(strncasecmp(cptr, "tau1=", 5)==0) {
166 if(!atof_with_check(cptr+5, &tau1) && tau1>=0.0) continue;
167 } else if(strncasecmp(cptr, "tau2=", 5)==0) {
168 if(!atof_with_check(cptr+5, &tau2) && tau2>=0.0) continue;
169 } else if(strncasecmp(cptr, "Ta=", 3)==0) {
170 if(!atof_with_check(cptr+3, &fixedTa) && fixedTa>=0.0) continue;
171 } else if(strncasecmp(cptr, "Ti=", 3)==0) {
172 if(!atof_with_check(cptr+3, &fixedTi) && fixedTi>=0.0) continue;
173 }
174 fprintf(stderr, "Error: invalid option '%s'.\n", argv[ai]);
175 return(1);
176 } else break;
177
178 /* Print help or version? */
179 if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
180 if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
181 if(version) {tpcPrintBuild(argv[0], stdout); return(0);}
182
183 /* Process other arguments, starting from the first non-option */
184 if(ai<argc) {strlcpy(tacfile, argv[ai], FILENAME_MAX); ai++;}
185 if(ai<argc) {strlcpy(parfile, argv[ai], FILENAME_MAX); ai++;}
186 if(ai<argc) {
187 fprintf(stderr, "Error: invalid argument '%s'.\n", argv[ai]);
188 return(1);
189 }
190 if(!parfile[0]) strcpy(parfile, "stdout");
191
192 /* Is something missing? */
193 if(!tacfile[0]) {
194 fprintf(stderr, "Error: missing command-line argument; use option --help\n");
195 return(1);
196 }
197
198 /* In verbose mode print arguments and options */
199 if(verbose>1) {
200 printf("tacfile := %s\n", tacfile);
201 printf("parfile := %s\n", parfile);
202 printf("fitfile := %s\n", fitfile);
203 printf("dcfile := %s\n", dcfile);
204 printf("resfile := %s\n", resfile);
205 printf("svgfile := %s\n", svgfile);
206 printf("svgfile1 := %s\n", svgfile1);
207 printf("svgfile2 := %s\n", svgfile2);
208 printf("MRL_check := %d\n", MRL_check);
209 printf("weights := %d\n", weights);
210 if(sumn>0) printf("sumn := %d\n", sumn);
211 if(!isnan(fixedTa)) printf("fixedTa := %g\n", fixedTa);
212 if(!isnan(fixedTi)) printf("fixedTi := %g\n", fixedTi);
213 }
214
215
216
217 /*
218 * Read data file
219 */
220 if(verbose>1) printf("reading %s\n", tacfile);
221 if(dftRead(tacfile, &tac)) {
222 fprintf(stderr, "Error in reading '%s': %s\n", tacfile, dfterrmsg);
223 return(2);
224 }
225 if(verbose>1) printf("checking %s\n", tacfile);
226
227 /* Check voiNr */
228 if(tac.voiNr>1) {
229 fprintf(stderr, "Warning: %s contains more than one TAC; first is used.\n", tacfile);
230 tac.voiNr=1;
231 }
232
233 /* Sort the samples by time in case data is catenated from several curves */
234 (void)dftSortByFrame(&tac);
235 if(verbose>30) dftPrint(&tac);
236
237 /* Get min and max X and Y */
238 double tstart, tstop, miny, maxy;
239 ret=dftMinMax(&tac, &tstart, &tstop, &miny, &maxy);
240 if(ret!=0) {
241 fprintf(stderr, "Error: invalid contents in %s\n", tacfile);
242 dftEmpty(&tac); return(2);
243 }
244 if(tstop<=0.0 || maxy<=0.0) {
245 fprintf(stderr, "Error: invalid contents in %s\n", tacfile);
246 dftEmpty(&tac); return(2);
247 }
248 if(tstart<0.0) fprintf(stderr, "Warning: negative x value(s).\n");
249 if(miny<0.0) fprintf(stderr, "Warning: negative y value(s).\n");
250 if(verbose>1) {
251 printf("x_range := %g - %g\n", tstart, tstop);
252 printf("sample_number := %d\n", tac.frameNr);
253 }
254
255 /* Check for NA's */
256 if(dft_nr_of_NA(&tac) > 0) {
257 fprintf(stderr, "Error: missing sample(s) in %s\n", tacfile);
258 dftEmpty(&tac); return(2);
259 }
260 /* Remove negative or zero values from the end of data, if only one TAC; */
261 /* this is often needed to process a TAC measured using blood pump */
262 if(tac.voiNr==1) {
263 int i; for(i=tac.frameNr-1; i>=0; i--) if(tac.voi[0].y[i]>0.0) break;
264 tac.frameNr=i+1;
265 }
266 /* Check frameNr */
267 if(tac.frameNr<4) {
268 fprintf(stderr, "Error: %s does not contain enough valid samples.\n", tacfile);
269 dftEmpty(&tac); return(3);
270 }
271
272 /* Set study number, if not yet available */
273 if(!tac.studynr[0]) studynr_from_fname(tacfile, tac.studynr);
274 if(verbose>29) dftPrint(&tac);
275
276 /* Check and set weights */
277 if(weights==0) {
278 if(tac.isweight==0) {
279 tac.isweight=1; for(int i=0; i<tac.frameNr; i++) tac.w[i]=1.0;}
280 } else if(weights==1) {
281 tac.isweight=1; for(int i=0; i<tac.frameNr; i++) tac.w[i]=1.0;
282 } else if(weights==2) {
283 dftWeightByFreq(&tac);
284 }
285 if(verbose>2) {
286 printf("data_weights := %g", tac.w[0]);
287 for(int i=1; i<tac.frameNr; i++) printf(", %g", tac.w[i]);
288 printf("\n");
289 }
290
291
292 /*
293 * Convert dispersion time constants to the same units as sample times
294 */
295 if(tau1>0.0 || tau2>0.0) {
296 if(tac.timeunit==TUNIT_SEC) {
297 if(verbose>3) printf("data and tau's are in the same units.\n");
298 } else if(tac.timeunit==TUNIT_MIN) {
299 tau1/=60.0; tau2/=60.0;
300 if(verbose>2) printf("tau's are converted to minutes.\n");
301 } else {
302 fprintf(stderr, "Warning: tau's could not be converted to sample units.\n");
303 }
304 }
305 if(verbose>1) {
306 printf("tau1 := %g\n", tau1);
307 printf("tau2 := %g\n", tau2);
308 }
309
310
311
312 /*
313 * Find the sample time and index of max concentration
314 */
315 double tmax; int imax;
316 ret=dftMinMaxTAC(&tac, 0, NULL, &tmax, NULL, NULL, NULL, NULL, NULL, &imax);
317 if(ret!=0) {
318 fprintf(stderr, "Error: invalid contents in %s\n", tacfile);
319 dftEmpty(&tac); return(2);
320 }
321 if(verbose>1) {
322 printf("peak_x := %g\n", tmax);
323 printf("peak_y := %g\n", maxy);
324 printf("peak_index := %d\n", imax);
325 }
326 if((tac.frameNr-imax)<2) {
327 fprintf(stderr, "Error: invalid TAC shape in %s\n", tacfile);
328 dftEmpty(&tac); return(2);
329 }
330
331
332
333 /*
334 * Determine the nr of sum functions and/or parameter constraints, unless
335 * already set by the user.
336 */
337 double p1[MAX_FUNC_NR], p2[MAX_FUNC_NR];
338 int proposed_sumn;
339 {
340 int i, j, n;
341 /* Make copy of the data starting from the peak, without any missing values */
342 n=tac.frameNr-imax;
343 double *x, *y;
344 x=(double*)malloc(2*n*sizeof(double));
345 if(x==NULL) {
346 fprintf(stderr, "Error: out of memory.\n");
347 dftEmpty(&tac); return(3);
348 }
349 y=x+n;
350 for(i=imax, j=0; i<tac.frameNr && j<n; i++) {
351 x[j]=tac.x[i]-tmax; y[j]=tac.voi[0].y[i];
352 if(!isnan(x[j]) && !isnan(y[j])) j++;
353 }
354 n=j;
355 if(n<2) {
356 fprintf(stderr, "Error: invalid contents in %s\n", tacfile);
357 dftEmpty(&tac); free(x); return(3);
358 }
359 ret=fitExpDecayNNLS(x, y, n, -1.0, 1.0E-06, 5.0E+01, MAX_FUNC_NR, p1, p2, &n, verbose-2);
360 if(ret || n<1) {
361 fprintf(stderr, "Error: cannot determine constraints from the data.\n");
362 dftEmpty(&tac); free(x); return(3);
363 }
364 free(x);
365 if(verbose>1) {
366 printf("Initial guesses for exp parameters:\n");
367 for(i=0; i<n; i++) printf("\t%g\t%g\n", p1[i], p2[i]);
368 }
369 proposed_sumn=n;
370 if(sumn==0) sumn=n; // user accepted automatic setting of sumn
371 }
372
373
374 /*
375 * Allocate memory for the fit parameters
376 */
377 if(verbose>1) printf("allocating memory for fit parameters.\n");
378 FIT fit; fitInit(&fit);
379 ret=fit_allocate_with_dft(&fit, &tac);
380 if(ret) {
381 fprintf(stderr, "Error: cannot allocate memory for fit parameters.\n");
382 dftEmpty(&tac); return(4);
383 }
384 tpcProgramName(argv[0], 1, 1, fit.program, 1024);
385 strlcpy(fit.datafile, tacfile, FILENAME_MAX);
386 fit.time=time(NULL);
387 fit.voi[0].type=331;
388 fit.voi[0].start=tstart; fit.voi[0].end=tstop;
389 fit.voi[0].dataNr=tac.frameNr;
390
391
392
393 /*
394 * Set parameter constraints
395 */
396 int parNr=2*sumn+2;
397 fit.voi[0].parNr=parNr;
398 /* Set Ta */
399 if(isnan(fixedTa)) {
400 pmin[0]=0.0; pmax[0]=tmax;
401 } else {
402 pmin[0]=pmax[0]=fixedTa;
403 }
404 /* Set Ti */
405 if(isnan(fixedTi)) {
406 pmin[1]=0.02*tmax; pmax[1]=1.5*tmax;
407 } else {
408 pmin[1]=pmax[1]=fixedTi;
409 }
410 /* Set the rest of the parameters */
411 if(sumn==proposed_sumn) {
412 /* User lets we set as many constraints as we feel right */
413 int i, pi;
414 for(i=0, pi=2; i<sumn; i++, pi+=2) {
415 pmin[pi]=0.25*p1[i]; pmax[pi]=2.5*p1[i];
416 //pmin[pi]=0.25*p1[i]*(-p2[i]); pmax[pi]=2.5*p1[i]*(-p2[i])*tmax;
417 pmin[pi+1]=0.15*(-p2[i]); pmax[pi+1]=2.0*(-p2[i]);
418 }
419 pmin[3]=1.0E-10;
420 } else if(sumn>proposed_sumn) {
421 /* User wants us to add more functions */
422 int i, j, pi;
423 for(i=0, pi=2; i<proposed_sumn; i++, pi+=2) {
424 pmin[pi]=0.25*p1[i]; pmax[pi]=2.5*p1[i];
425 pmin[pi+1]=0.15*(-p2[i]); pmax[pi+1]=2.0*(-p2[i]);
426 }
427 for(j=1; i<sumn; i++, j++) {
428 pmin[pi]=0.0; pmax[pi]=0.2*maxy*(double)j;
429 pmin[pi+1]=1.0E-10; pmax[pi+1]=0.1*(double)j;
430 }
431 } else {
432 /* User wants us to use fewer functions */
433 int i, pi;
434 for(i=0, pi=2; i<sumn; i++, pi+=2) {
435 pmin[pi]=0.05*p1[i]; pmax[pi]=10.0*p1[i];
436 pmin[pi+1]=0.05*(-p2[i]); pmax[pi+1]=5.0*(-p2[i]);
437 }
438 pmin[3]=1.0E-10;
439 }
440
441
442
443 /*
444 * Fit
445 */
446 {
447 if(verbose>2) printf("fitting\n");
448 dataNr=tac.frameNr;
449 x=tac.x; ymeas=tac.voi[0].y; yfit=tac.voi[0].y2; ytmp=tac.voi[0].y3; w=tac.w;
450 int iter_nr=1;
451 int tgo_nr=400;
452 int neigh_nr=8;
455 func=func331;
456 double wss, p[MAX_PARAMETERS];
457 ret=tgo(pmin, pmax, func, NULL, parNr, neigh_nr, &wss, p, tgo_nr, iter_nr, verbose-5);
458 if(ret) {
459 fprintf(stderr, "Error %d in TGO.\n", ret);
460 dftEmpty(&tac); fitEmpty(&fit);
461 return(6);
462 }
463 if(verbose>2) {
464 printf("fitted parameters:\n");
465 for(int i=0; i<parNr; i++)
466 printf("\tp%d\t%g\t(%g - %g)\n", 1+i, p[i], pmin[i], pmax[i]);
467 printf("\tWSS\t:=\t%g\n", wss);
468 }
469 if(verbose>3) {
470 printf("Sample\tX\tY\tYfit\tWeight\n");
471 for(int i=0; i<dataNr; i++) printf("%d\t%9.2e\t%9.2e\t%9.2e\t%7.1e\n",
472 1+i, x[i], ymeas[i], yfit[i], w[i]);
473 }
474 /* Check the MRL */
475 if(MRL_check) {
476 if(verbose>1) printf("Checking the MRL.\n");
477 int m=mrl_between_tacs(yfit, ymeas, dataNr);
478 if(m>3 && m>dataNr/3) {
479 fprintf(stderr, "Error: bad fit.\n");
480 fprintf(stderr, "MRL := %d / %d\n", m, dataNr);
481 dftEmpty(&tac); fitEmpty(&fit);
482 return(7);
483 } else if(m>2 && m>dataNr/4) {
484 fprintf(stderr, "Warning: bad fit.\n");
485 fprintf(stderr, "MRL := %d / %d\n", m, dataNr);
486 } else if(verbose>0) {
487 printf("MRL test passed.\n");
488 if(verbose>1) fprintf(stderr, "MRL := %d / %d\n", m, dataNr);
489 }
490 }
491 /* Force parameter values inside limits, as they are in the simulation */
492 double a;
493 modelCheckParameters(parNr, pmin, pmax, p, fit.voi[0].p, &a);
494 fit.voi[0].wss=wss/a; // remove penalty from reported WSS
495 for(int i=0; i<parNr; i++) fit.voi[0].p[i]=p[i];
496 }
497
498 /*
499 * Save fit results
500 */
501 if(verbose>1) printf("saving results in %s\n", parfile);
502 ret=fitWrite(&fit, parfile); if(ret) {
503 fprintf(stderr, "Error (%d) in writing '%s': %s\n", ret, parfile, fiterrmsg);
504 dftEmpty(&tac); fitEmpty(&fit); return(11);
505 }
506 if(verbose>0) printf("Function parameters written in %s\n", parfile);
507
508 /* Also allocate memory for result file, if needed */
509 if(resfile[0]) {
510 if(verbose>1) printf("allocating memory for results.\n");
511 int n;
512 RES res; resInit(&res);
513 char buf[256];
514 ret=fitToResult(&fit, &res, buf);
515 if(ret!=0) {
516 fprintf(stderr, "Error in making results: %s\n", buf);
517 dftEmpty(&tac); fitEmpty(&fit); resEmpty(&res); return(12);
518 }
519 n=0; strcpy(res.parname[n++], "Function");
520 if(1 /*type==331*/) {
521 strcpy(res.parname[n++], "Ta");
522 strcpy(res.parname[n++], "Ti");
523 for(int i=1; i<=sumn; i++) {
524 sprintf(res.parname[n++], "A%d", i);
525 sprintf(res.parname[n++], "L%d", i);
526 }
527 }
528 strcpy(res.parname[n++], "WSS");
529 strcpy(res.program, fit.program);
530 sprintf(res.datarange, "%g - %g", tstart, tstop);
531 strcpy(res.studynr, tac.studynr);
532 if(verbose>1) resPrint(&res);
533 if(verbose>1) printf("saving results in %s\n", resfile);
534 if(resWrite(&res, resfile, verbose-3)) {
535 fprintf(stderr, "Error in writing '%s': %s\n", resfile, reserrmsg);
536 dftEmpty(&tac); fitEmpty(&fit); resEmpty(&res); return(11);
537 }
538 resEmpty(&res);
539 if(verbose>1) printf("Function parameters written in %s\n", resfile);
540 }
541
542
543
544
545 /*
546 * Plotting of fitted TACs
547 */
548 if(svgfile[0] || svgfile1[0] || svgfile2[0]) {
549
550 if(verbose>1)
551 printf("calculating fitted curve at automatically generated sample times\n");
552 DFT adft; dftInit(&adft);
553 ret=dftAutointerpolate(&tac, &adft, 1.02*tac.x[tac.frameNr-1], verbose-10);
554 if(ret) {
555 fprintf(stderr, "Error %d in memory allocation for fitted curves.\n", ret);
556 dftEmpty(&tac); fitEmpty(&fit); dftEmpty(&adft);
557 return(13);
558 }
559 double a;
560 for(int i=0; i<adft.frameNr; i++) {
561 ret=fitEval(&fit.voi[0], adft.x[i], &a);
562 if(ret!=0) break;
563 adft.voi[0].y[i]=a;
564 }
565 if(ret!=0) {
566 fprintf(stderr, "Error: cannot calculate fitted curve for '%s'.\n", svgfile);
567 dftEmpty(&tac); dftEmpty(&adft); fitEmpty(&fit);
568 return(14);
569 }
570 /* Add dispersion if required */
571 if(tau1>0.0 || tau2>0.0) {
572 ret=simDispersion(adft.x, adft.voi[0].y, adft.frameNr, tau1, tau2, adft.voi[0].y3);
573 if(ret!=0) {
574 fprintf(stderr, "Error: cannot add dispersion to fitted curve for '%s'.\n", svgfile);
575 dftEmpty(&tac); dftEmpty(&adft); fitEmpty(&fit);
576 return(14);
577 }
578 }
579 /* Save SVG plot of fitted and original data */
580 char tmp[256];
581 tpcProgramName(argv[0], 0, 0, tmp, 128); strcat(tmp, " ");
582 if(strlen(adft.studynr)>1) strcat(tmp, adft.studynr);
583 if(svgfile[0]) {
584 if(verbose>1) printf("writing %s\n", svgfile);
585 ret=plot_fitrange_svg(&tac, &adft, tmp, 0.0, nan(""), 0.0, nan(""), svgfile, verbose-10);
586 if(ret) {
587 fprintf(stderr, "Error (%d) in writing '%s'.\n", ret, svgfile);
588 dftEmpty(&adft); dftEmpty(&tac); fitEmpty(&fit);
589 return(30+ret);
590 }
591 if(verbose>0) printf("Plots written in %s\n", svgfile);
592 }
593 /* Save SVG plot of first part of fitted and original data */
594 if(svgfile1[0]) {
595 if(verbose>1) printf("writing %s\n", svgfile1);
596 ret=plot_fitrange_svg(&tac, &adft, tmp, 0.0, 2.*tmax, 0.0, nan(""), svgfile1, verbose-10);
597 if(ret) {
598 fprintf(stderr, "Error (%d) in writing '%s'.\n", ret, svgfile1);
599 dftEmpty(&adft); dftEmpty(&tac); fitEmpty(&fit);
600 return(30+ret);
601 }
602 if(verbose>0) printf("Plots written in %s\n", svgfile1);
603 }
604 /* Save SVG plot of lower part of fitted and original data */
605 if(svgfile2[0]) {
606 if(verbose>1) printf("writing %s\n", svgfile2);
607 ret=plot_fitrange_svg(&tac, &adft, tmp, 0.8*tmax+0.2*tac.x[tac.frameNr-1],
608 nan(""), 0.0, nan(""), svgfile2, verbose-10);
609 if(ret) {
610 fprintf(stderr, "Error (%d) in writing '%s'.\n", ret, svgfile2);
611 dftEmpty(&adft); dftEmpty(&tac); fitEmpty(&fit);
612 return(30+ret);
613 }
614 if(verbose>0) printf("Plots written in %s\n", svgfile2);
615 }
616 dftEmpty(&adft);
617 }
618
619
620
621 /*
622 * Save fitted TAC with original sample times;
623 * this destroys the original sample values
624 */
625 if(fitfile[0] || dcfile[0]) {
626 if(verbose>1) printf("writing fitted TAC(s)\n");
627
628 double a;
629 for(int i=0; i<tac.frameNr; i++) {
630 ret=fitEval(&fit.voi[0], tac.x[i], &a);
631 if(ret!=0) break;
632 tac.voi[0].y[i]=a;
633 }
634 if(ret!=0) {
635 fprintf(stderr, "Error: cannot calculate fitted curve for '%s'.\n", fitfile);
636 dftEmpty(&tac); fitEmpty(&fit);
637 return(17);
638 }
639
640 if(dcfile[0]) {
641 if(verbose>1) printf("writing %s\n", dcfile);
642 ret=dftWrite(&tac, dcfile);
643 if(ret) {
644 fprintf(stderr, "Error: cannot write '%s'.\n", dcfile);
645 dftEmpty(&tac); fitEmpty(&fit);
646 return(18);
647 }
648 }
649
650 if(fitfile[0]) {
651 if(tau1>0.0 || tau2>0.0) {
652 if(verbose>1) printf(" adding dispersion...\n");
653 ret=simDispersion(tac.x, tac.voi[0].y, tac.frameNr, tau1, tau2, tac.voi[0].y3);
654 if(ret!=0) {
655 fprintf(stderr, "Error: cannot add dispersion to fitted curve for '%s'.\n", fitfile);
656 dftEmpty(&tac); fitEmpty(&fit);
657 return(17);
658 }
659 }
660 if(verbose>1) printf("writing %s\n", fitfile);
661 ret=dftWrite(&tac, fitfile);
662 if(ret) {
663 fprintf(stderr, "Error: cannot write '%s'.\n", fitfile);
664 dftEmpty(&tac); fitEmpty(&fit);
665 return(18);
666 }
667 }
668 }
669
670 dftEmpty(&tac); fitEmpty(&fit);
671 return(0);
672}
673/*****************************************************************************/
674
675/*****************************************************************************
676 *
677 * Functions to be minimized
678 *
679 *****************************************************************************/
680
681double func331(int parNr, double *p, void *fdata)
682{
683 int fi, n, i;
684 double d, wss=0.0, f, t, e1, e2;
685 double Ta, Ti, one_per_Ti, A[MAX_FUNC_NR], L[MAX_FUNC_NR], AL[MAX_FUNC_NR];
686 double pa[MAX_PARAMETERS], penalty=1.0;
687 if(fdata) {/*prevent compiler warning*/}
688
689 /* Check parameters against the constraints */
690 (void)modelCheckParameters(parNr, pmin, pmax, p, pa, &penalty);
691
692 /* Interpretation of parameters */
693 n=(parNr-2)/2;
694 Ta=pa[0];
695 Ti=pa[1]; if(Ti>0.0) one_per_Ti=1.0/Ti; else one_per_Ti=1.0;
696 for(i=0; i<n; i++) {
697 A[i]=pa[2*i+2];
698 L[i]=pa[2*i+3];
699 }
700 for(i=0; i<n; i++) if(L[i]>1.0E-12) AL[i]=A[i]/L[i]; else AL[i]=A[i];
701
702 /* Compute function value at each sample time */
703 for(fi=0; fi<dataNr; fi++) {
704 t=x[fi];
705 if(t<=Ta) {
706 yfit[fi]=0.0;
707 } else if(t<Ta+Ti) {
708 for(i=0, f=0.0; i<n; i++) {
709 e2=-L[i]*(t-Ta);
710 if(e2>-0.000001) e2=1.0; else if(e2<-50) e2=0.0; else e2=exp(e2);
711 f+=AL[i]*(1.0-e2);
712 }
713 if(Ti>0.0) f*=one_per_Ti;
714 yfit[fi]=f;
715 } else {
716 for(i=0, f=0.0; i<n; i++) {
717 e1=-L[i]*(t-Ta-Ti);
718 if(e1>-0.000001) e1=1.0; else if(e1<-50) e1=0.0; else e1=exp(e1);
719 e2=-L[i]*(t-Ta);
720 if(e2>-0.000001) e2=1.0; else if(e2<-50) e2=0.0; else e2=exp(e2);
721 f+=AL[i]*(e1-e2);
722 }
723 if(Ti>0.0) f*=one_per_Ti;
724 yfit[fi]=f;
725 }
726 }
727
728 /* Add dispersion if required */
729 if(tau1>0.0 || tau2>0.0)
730 (void)simDispersion(x, yfit, dataNr, tau1, tau2, ytmp);
731
732 /* Compute weighted SS */
733 for(fi=0; fi<dataNr; fi++) {
734 d=ymeas[fi]-yfit[fi]; if(isnan(ymeas[fi])) continue;
735 //if(min_meas==MINMEAS_SS) d*=d; else d=fabs(d);
736 wss+=w[fi]*d*d;
737 //printf("yfit=%g ymeas=%g d=%g wss=%g\n", yfit[fi], ymeas[fi], d, wss);
738 }
739 wss*=penalty;
740 //printf(" -> %g\n", wss);
741
742 return(wss);
743}
744/*****************************************************************************/
745
746/*****************************************************************************/
int fitExpDecayNNLS(double *x, double *y, int n, double fittime, double kmin, double kmax, int pnr, double *a, double *k, int *fnr, int verbose)
Estimate initial values for sum of exponentials to be fitted on decaying x,y-data.
int modelCheckParameters(int par_nr, double *lower_p, double *upper_p, double *test_p, double *accept_p, double *penalty)
Definition constraints.c:15
int atof_with_check(char *double_as_string, double *result_value)
Definition decpoint.c:107
void dftInit(DFT *data)
Definition dft.c:38
int dftMinMaxTAC(DFT *dft, int tacindex, double *minx, double *maxx, double *miny, double *maxy, int *mini, int *maxi, int *mins, int *maxs)
Definition dft.c:1024
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 dft_nr_of_NA(DFT *dft)
Definition dft.c:905
int dftRead(char *filename, DFT *data)
Definition dftio.c:22
void dftPrint(DFT *data)
Definition dftio.c:538
int dftWrite(DFT *data, char *filename)
Definition dftio.c:594
int dftAutointerpolate(DFT *dft, DFT *dft2, double endtime, int verbose)
int fitToResult(FIT *fit, RES *res, char *status)
Definition fitres.c:56
int fit_allocate_with_dft(FIT *fit, DFT *dft)
Definition fitres.c:14
Header file for libtpccurveio.
char reserrmsg[64]
Definition result.c:6
void resInit(RES *res)
Definition result.c:52
void resPrint(RES *res)
Definition result.c:186
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 resWrite(RES *res, char *filename, int verbose)
Definition result.c:565
char fiterrmsg[64]
Definition mathfunc.c:6
void fitInit(FIT *fit)
Definition mathfunc.c:38
void resEmpty(RES *res)
Definition result.c:22
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
int studynr_from_fname(char *fname, char *studynr)
Definition studynr.c:119
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 simDispersion(double *x, double *y, int n, double tau1, double tau2, double *tmp)
Definition simulate.c:1911
int mrl_between_tacs(double y1[], double y2[], int n)
Definition runs_test.c:103
#define MAX_PARAMETERS
Definition libtpcmodel.h: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
char datafile[FILENAME_MAX]
char program[1024]
FitVOI * voi
time_t time
double wss
double end
double start
double p[MAX_FITPARAMS]
char studynr[MAX_STUDYNR_LEN+1]
char parname[MAX_RESPARAMS][MAX_RESPARNAME_LEN+1]
char program[1024]
char datarange[128]
double * y2
double * y
double * y3