TPCCLIB
Loading...
Searching...
No Matches
fit_feng.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 suggested by",
28 "Feng et al (1993) to the PET plasma or blood time-activity curve (TAC).",
29 " ",
30 "Function:",
31 " when t<=dt : f(t) = 0 ",
32 " when t>dt : f(t) = (p1*(t-dt)-p3-p5)*exp(p2*(t-dt)) ",
33 " + p3*exp(p4*(t-dt)) + p5*exp(p6*(t-dt))",
34 " ",
35 "Usage: @P [Options] tacfile [parfile]",
36 " ",
37 "Options:",
38 " -lim[=<filename>]",
39 " Specify the constraints for function parameters;",
40 " This file with default values can be created by giving this",
41 " option as the only command-line argument to this program.",
42 " Without file name the default values are printed on screen.",
43 " -integ[ral]",
44 " Given datafile contains the AUC of TAC as function of time.",
45 " -wf",
46 " Weight by sampling interval.",
47// " -ext[ended] or -simpl[ified]", // deprecated
48// " Apply extended model (one extra exponential term with two more",
49// " parameters) or simplified model (p5 and p6 fixed to zero).",
50 " -n=<2|3|4|A>",
51 " The nr of exponential functions; A=determined automatically.",
52 " Default is 3; changing the default may lead to a bad fit.",
53 " -ss",
54 " Function approaches steady level; last exponent term is a constant,",
55 " i.e. either p6 or p8 is 0.",
56 " -delay=<time>",
57 " Delay time (dt) is constrained to specified value (>=0).",
58 " -MRL",
59 " Error is returned if MRL check is not passed.",
60 " -fast or -safe",
61 " Speed up the fitting but increase the chance of failure, or",
62 " increase the reliability at the cost of computing time",
63 " -res=<Filename>",
64 " Fitted parameters are also written in result file format.",
65 " -svg=<Filename>",
66 " Fitted and measured TACs are plotted in specified SVG file.",
67 " -svg1=<Filename>",
68 " Initial part of fitted and measured TACs are plotted in SVG file",
69 " -svg2=<Filename>",
70 " Lower part of fitted and measured TACs are plotted in SVG file",
71 " -fit=<Filename>",
72 " Fitted TACs are written in TAC format.",
73 " -stdoptions", // List standard options like --help, -v, etc
74 " ",
75 "TAC file must contain at least two columns, sample times in the first,",
76 "and concentrations of TACs in the following columns.",
77 "To obtain a good fit, TAC should be corrected for physical decay and any",
78 "circulating metabolites.",
79 "Function parameters (p1, ..., dt) will be written in the parfile.",
80 " ",
81 "References:",
82 "1. Feng D, Huang S-C, Wang X. Models for computer simulation studies of input",
83 " functions for tracer kinetic modeling with positron emission tomography.",
84 " Int J Biomed Comput. 1993;32:95-110.",
85 " ",
86 "See also: fit2dat, fit_sinf, fit_exp, fit_dexp, fit_ratf, extrapol",
87 " ",
88 "Keywords: curve fitting, input, modelling, simulation",
89 0};
90/*****************************************************************************/
91
92/*****************************************************************************/
93/* Turn on the globbing of the command line, since it is disabled by default in
94 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
95 In Unix&Linux wildcard command line processing is enabled by default. */
96/*
97#undef _CRT_glob
98#define _CRT_glob -1
99*/
100int _dowildcard = -1;
101/*****************************************************************************/
102
103/*****************************************************************************/
105enum parameter {
106 F_A1, F_A2, F_A3, F_A4, F_L1, F_L2, F_L3, F_L4, F_DT
107};
108double pmin[MAX_PARAMETERS], pmax[MAX_PARAMETERS];
109int dataNr=0;
110int parNr=7;
111double *x, *ymeas, *yfit, *w, *ytmp;
112double func_normal(int parNr, double *p, void*);
113double func_integ(int parNr, double *p, void*);
114double func_normal_direct(int parNr, double *p, void*);
115double func_integ_direct(int parNr, double *p, void*);
116/*****************************************************************************/
117
118/*****************************************************************************/
122int main(int argc, char **argv)
123{
124 int ai, help=0, version=0, verbose=1;
125 int ret;
126 char tacfile[FILENAME_MAX], fitfile[FILENAME_MAX], limfile[FILENAME_MAX],
127 parfile[FILENAME_MAX], resfile[FILENAME_MAX], svgfile[FILENAME_MAX];
128 char svgfile1[FILENAME_MAX], svgfile2[FILENAME_MAX];
129 int dat_type=0; /* 0=normal; 1=integral */
130 int weights=0; // 0=default, 1=no weighting, 2=frequency
131 int iter_nr=2; // TGO iteration number
132 int steadystate=0;
133 int MRL_check=0; // 0=off, 1=on
134 int sumn=3; // Nr of exponentials: 0=automatic, otherwise 2-4.
135 double fixed_delay=nan("");
136 int pTransform=1; // 0=no transform, 1=transforms.
137
138#ifdef MINGW
139 // Use Unix/Linux default of two-digit exponents in MinGW on Windows
140 _set_output_format(_TWO_DIGIT_EXPONENT);
141#endif
142
143 /* Set parameter initial values and constraints */
144 double def_pmin[MAX_PARAMETERS], def_pmax[MAX_PARAMETERS];
145 def_pmin[F_A1]=0.0; def_pmax[F_A1]=1.0E+09;
146 def_pmin[F_A2]=0.0; def_pmax[F_A2]=1.0E+09;
147 def_pmin[F_A3]=0.0; def_pmax[F_A3]=1.0E+09;
148 def_pmin[F_A4]=0.0; def_pmax[F_A4]=1.0E+09;
149 def_pmin[F_L1]=-5.0; def_pmax[F_L1]=-0.001;
150 def_pmin[F_L2]=-5.0; def_pmax[F_L2]=-0.001;
151 def_pmin[F_L3]=-0.5; def_pmax[F_L3]=0.0;
152 def_pmin[F_L4]=-0.01; def_pmax[F_L4]=0.0;
153 def_pmin[F_DT]=0.0; def_pmax[F_DT]=5.0;
154
155
156 /*
157 * Get arguments
158 */
159 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
160 tacfile[0]=fitfile[0]=limfile[0]=parfile[0]=resfile[0]=(char)0;
161 svgfile[0]=svgfile1[0]=svgfile2[0]=(char)0;
162 /* Options */
163 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') {
164 char *cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(cptr==NULL) continue;
165 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
166 if(strcasecmp(cptr, "W1")==0) {
167 weights=1; continue;
168 } else if(strcasecmp(cptr, "WF")==0) {
169 weights=2; continue;
170 } else if(strncasecmp(cptr, "INTEGRAL", 5)==0 || strcasecmp(cptr, "AUC")==0) {
171 dat_type=1; continue;
172 } else if(strcasecmp(cptr, "MRL")==0) {
173 MRL_check=1; continue;
174 } else if(strncasecmp(cptr, "SVG=", 4)==0) {
175 if(strlcpy(svgfile, cptr+4, FILENAME_MAX)>0) continue;
176 } else if(strncasecmp(cptr, "SVG1=", 5)==0) {
177 if(strlcpy(svgfile1, cptr+5, FILENAME_MAX)>0) continue;
178 } else if(strncasecmp(cptr, "SVG2=", 5)==0) {
179 if(strlcpy(svgfile2, cptr+5, FILENAME_MAX)>0) continue;
180 } else if(strncasecmp(cptr, "FIT=", 4)==0 && strlen(cptr)>4) {
181 strlcpy(fitfile, cptr+4, FILENAME_MAX); continue;
182 } else if(strncasecmp(cptr, "RES=", 4)==0 && strlen(cptr)>4) {
183 strlcpy(resfile, cptr+4, FILENAME_MAX); continue;
184 } else if(strncasecmp(cptr, "EXTENDED", 1)==0) {
185 sumn=4; continue;
186 } else if(strncasecmp(cptr, "SIMPLIFIED", 5)==0) {
187 sumn=2; continue;
188 } else if(strcasecmp(cptr, "SS")==0) {
189 steadystate=1; continue;
190 } else if(strncasecmp(cptr, "N=", 2)==0) {
191 cptr+=2; if(strcasecmp(cptr, "A")==0) {sumn=0; continue;}
192 sumn=atoi(cptr); if(sumn>=2 && sumn<=4) continue;
193 } else if(strncasecmp(cptr, "DELAY=", 6)==0 && strlen(cptr)>6) {
194 if(!atof_with_check(cptr+6, &fixed_delay) && fixed_delay>=0.0) continue;
195 } else if(strncasecmp(cptr, "LIM=", 4)==0 && strlen(cptr)>4) {
196 strlcpy(limfile, cptr+4, FILENAME_MAX); continue;
197 } else if(strcasecmp(cptr, "LIM")==0) {
198 strcpy(limfile, "stdout"); continue;
199 } else if(strcasecmp(cptr, "SAFE")==0) {
200 iter_nr=5; continue;
201 } else if(strcasecmp(cptr, "NORMAL")==0) {
202 iter_nr=2; continue;
203 } else if(strcasecmp(cptr, "FAST")==0) {
204 iter_nr=1; continue;
205 }
206 fprintf(stderr, "Error: invalid option '%s'.\n", argv[ai]);
207 return(1);
208 } else break;
209
210 /* Print help or version? */
211 if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
212 if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
213 if(version) {tpcPrintBuild(argv[0], stdout); return(0);}
214
215 /* Process other arguments, starting from the first non-option */
216 if(ai<argc) {strlcpy(tacfile, argv[ai], FILENAME_MAX); ai++;}
217 if(ai<argc) {strlcpy(parfile, argv[ai], FILENAME_MAX); ai++;}
218 if(ai<argc) {
219 fprintf(stderr, "Error: invalid argument '%s'.\n", argv[ai]);
220 return(1);
221 }
222 if(!parfile[0]) strcpy(parfile, "stdout");
223
224
225 /* In verbose mode print arguments and options */
226 if(verbose>1) {
227 if(limfile[0]) printf("limfile := %s\n", limfile);
228 printf("tacfile := %s\n", tacfile);
229 printf("parfile := %s\n", parfile);
230 printf("fitfile := %s\n", fitfile);
231 printf("resfile := %s\n", resfile);
232 printf("svgfile := %s\n", svgfile);
233 printf("svgfile1 := %s\n", svgfile1);
234 printf("svgfile2 := %s\n", svgfile2);
235 printf("MRL_check := %d\n", MRL_check);
236 printf("weights := %d\n", weights);
237 if(sumn>0) printf("sumn := %d\n", sumn);
238 printf("dat_type := %d\n", dat_type);
239 if(!isnan(fixed_delay)) printf("fixed_delay := %g\n", fixed_delay);
240 printf("tgo_iter_nr := %d\n", iter_nr);
241 }
242
243
244 /* If only file name for parameter constraints was given, then write one
245 with default contents, and exit */
246 if(limfile[0] && !tacfile[0]) {
247 /* Check that initial value file does not exist */
248 if(strcasecmp(limfile, "stdout")!=0 && access(limfile, 0) != -1) {
249 fprintf(stderr, "Error: parameter constraint file %s exists.\n", limfile);
250 return(9);
251 }
252 if(verbose>1 && strcasecmp(limfile, "stdout")!=0)
253 printf("writing parameter constraints file\n");
254 /* Create parameter file */
255 IFT ift; iftInit(&ift);
256 iftPutDouble(&ift, "A1_lower", def_pmin[F_A1], NULL, 0);
257 iftPutDouble(&ift, "A1_upper", def_pmax[F_A1], NULL, 0);
258 iftPutDouble(&ift, "L1_lower", def_pmin[F_L1], NULL, 0);
259 iftPutDouble(&ift, "L1_upper", def_pmax[F_L1], NULL, 0);
260 iftPutDouble(&ift, "A2_lower", def_pmin[F_A2], NULL, 0);
261 iftPutDouble(&ift, "A2_upper", def_pmax[F_A2], NULL, 0);
262 iftPutDouble(&ift, "L2_lower", def_pmin[F_L2], NULL, 0);
263 iftPutDouble(&ift, "L2_upper", def_pmax[F_L2], NULL, 0);
264 iftPutDouble(&ift, "A3_lower", def_pmin[F_A3], NULL, 0);
265 iftPutDouble(&ift, "A3_upper", def_pmax[F_A3], NULL, 0);
266 iftPutDouble(&ift, "L3_lower", def_pmin[F_L3], NULL, 0);
267 iftPutDouble(&ift, "L3_upper", def_pmax[F_L3], NULL, 0);
268 iftPutDouble(&ift, "A4_lower", def_pmin[F_A4], NULL, 0);
269 iftPutDouble(&ift, "A4_upper", def_pmax[F_A4], NULL, 0);
270 iftPutDouble(&ift, "L4_lower", def_pmin[F_L4], NULL, 0);
271 iftPutDouble(&ift, "L4_upper", def_pmax[F_L4], NULL, 0);
272 iftPutDouble(&ift, "DT_lower", def_pmin[F_DT], NULL, 0);
273 iftPutDouble(&ift, "DT_upper", def_pmax[F_DT], NULL, 0);
274 ret=iftWrite(&ift, limfile, 0);
275 if(ret) {
276 fprintf(stderr, "Error in writing '%s': %s\n", limfile, ift.status);
277 iftEmpty(&ift); return(9);
278 }
279 if(strcasecmp(limfile, "stdout")!=0)
280 fprintf(stdout, "Parameter file %s with initial values written.\n", limfile);
281 iftEmpty(&ift); return(0);
282 }
283
284
285 /* Is something missing? */
286 if(!tacfile[0]) {
287 fprintf(stderr, "Error: missing command-line argument; use option --help\n");
288 return(1);
289 }
290
291
292 /*
293 * Read model parameter upper and lower limits if file for that was given
294 */
295 if(limfile[0]) {
296 pTransform=0;
297 IFT ift; iftInit(&ift);
298 if(verbose>1) printf("reading %s\n", limfile);
299 ret=iftRead(&ift, limfile, 1, 0);
300 if(ret) {
301 fprintf(stderr, "Error in reading '%s': %s\n", limfile, ift.status);
302 return(9);
303 }
304 if(verbose>10) iftWrite(&ift, "stdout", 0);
305 int n=0;
306 if(iftGetDoubleValue(&ift, 0, "A1_lower", &def_pmin[F_A1], 0)>=0) n++;
307 if(iftGetDoubleValue(&ift, 0, "A1_upper", &def_pmax[F_A1], 0)>=0) n++;
308 if(iftGetDoubleValue(&ift, 0, "A2_lower", &def_pmin[F_A2], 0)>=0) n++;
309 if(iftGetDoubleValue(&ift, 0, "A2_upper", &def_pmax[F_A2], 0)>=0) n++;
310 if(iftGetDoubleValue(&ift, 0, "A3_lower", &def_pmin[F_A3], 0)>=0) n++;
311 if(iftGetDoubleValue(&ift, 0, "A3_upper", &def_pmax[F_A3], 0)>=0) n++;
312 if(iftGetDoubleValue(&ift, 0, "A4_lower", &def_pmin[F_A4], 0)>=0) n++;
313 if(iftGetDoubleValue(&ift, 0, "A4_upper", &def_pmax[F_A4], 0)>=0) n++;
314 if(iftGetDoubleValue(&ift, 0, "L1_lower", &def_pmin[F_L1], 0)>=0) n++;
315 if(iftGetDoubleValue(&ift, 0, "L1_upper", &def_pmax[F_L1], 0)>=0) n++;
316 if(iftGetDoubleValue(&ift, 0, "L2_lower", &def_pmin[F_L2], 0)>=0) n++;
317 if(iftGetDoubleValue(&ift, 0, "L2_upper", &def_pmax[F_L2], 0)>=0) n++;
318 if(iftGetDoubleValue(&ift, 0, "L3_lower", &def_pmin[F_L3], 0)>=0) n++;
319 if(iftGetDoubleValue(&ift, 0, "L3_upper", &def_pmax[F_L3], 0)>=0) n++;
320 if(iftGetDoubleValue(&ift, 0, "L4_lower", &def_pmin[F_L4], 0)>=0) n++;
321 if(iftGetDoubleValue(&ift, 0, "L4_upper", &def_pmax[F_L4], 0)>=0) n++;
322 if(iftGetDoubleValue(&ift, 0, "DT_lower", &def_pmin[F_DT], 0)>=0) n++;
323 if(iftGetDoubleValue(&ift, 0, "DT_upper", &def_pmax[F_DT], 0)>=0) n++;
324 iftEmpty(&ift);
325 if(n==0) {fprintf(stderr, "Error: invalid parameter file.\n"); return(9);}
326 /* Change the order if necessary */
327 for(int pi=0; pi<parNr; pi++) if(def_pmax[pi]<def_pmin[pi]) {
328 double v=def_pmax[pi]; def_pmax[pi]=def_pmin[pi]; def_pmin[pi]=v;
329 }
330 /* Check that not all are constrained */
331 n=parFreeNr(9, def_pmin, def_pmax);
332 if(n==0) {
333 fprintf(stderr, "Error: no model parameters left free for fitting.\n");
334 return(9);
335 }
336 /* What about delay time? */
337 if(isnan(fixed_delay)) {
338 /* not fixed with option, thus check if fixed with lim file */
339 if(fabs(def_pmax[F_DT]-def_pmin[F_DT])<1.0E-10) fixed_delay=def_pmin[F_DT];
340 } else {
341 /* fixed with option, which overwrites lim file */
342 def_pmax[F_DT]=def_pmin[F_DT]=fixed_delay;
343 }
344 if(verbose>1) {
345 printf("constraints :=");
346 for(int pi=0; pi<9; pi++) printf(" [%g,%g]", def_pmin[pi], def_pmax[pi]);
347 printf("\n");
348 }
349 }
350
351
352 /*
353 * Read data file
354 */
355 if(verbose>1) printf("reading %s\n", tacfile);
356 DFT tac; dftInit(&tac);
357 if(dftRead(tacfile, &tac)) {
358 fprintf(stderr, "Error in reading '%s': %s\n", tacfile, dfterrmsg);
359 return(2);
360 }
361 if(verbose>1) printf("checking %s\n", tacfile);
362 if(verbose>1 && tac.voiNr>1) printf("tacNr := %d\n", tac.voiNr);
363
364 /* Sort the samples by time in case data is catenated from several curves */
365 (void)dftSortByFrame(&tac);
366 if(verbose>50) dftPrint(&tac);
367
368 /* Get min and max X and Y */
369 double tstart, tstop, miny, maxy;
370 ret=dftMinMax(&tac, &tstart, &tstop, &miny, &maxy);
371 if(ret!=0) {
372 fprintf(stderr, "Error: invalid contents in %s\n", tacfile);
373 dftEmpty(&tac); return(2);
374 }
375 if(tstop<=0.0 || maxy<=0.0) {
376 fprintf(stderr, "Error: invalid contents in %s\n", tacfile);
377 dftEmpty(&tac); return(2);
378 }
379 if(tstart<0.0 && verbose>0) fprintf(stderr, "Warning: negative x value(s).\n");
380 if(miny<0.0 && verbose>0) fprintf(stderr, "Warning: negative y value(s).\n");
381 if(verbose>1) {
382 printf("x_range := %g - %g\n", tstart, tstop);
383 printf("sample_number := %d\n", tac.frameNr);
384 }
385
386 /* Check for NA's */
387 if(dft_nr_of_NA(&tac) > 0) {
388 fprintf(stderr, "Error: missing sample(s) in %s\n", tacfile);
389 dftEmpty(&tac); return(2);
390 }
391 /* Remove negative or zero values from the end of data, if only one TAC; */
392 /* this is often needed to process a TAC measured using blood pump */
393 if(tac.voiNr==1) {
394 int i; for(i=tac.frameNr-1; i>=0; i--) if(tac.voi[0].y[i]>0.0) break;
395 tac.frameNr=i+1;
396 }
397 /* Check frameNr */
398 if(tac.frameNr<8) {
399 fprintf(stderr, "Error: %s does not contain enough valid samples.\n", tacfile);
400 dftEmpty(&tac); return(2);
401 }
402
403 /* Set study number, if not yet available */
404 if(!tac.studynr[0]) studynr_from_fname(tacfile, tac.studynr);
405
406 /* Check and set weights */
407 if(weights==0) {
408 if(tac.isweight==0) {
409 tac.isweight=1; for(int i=0; i<tac.frameNr; i++) tac.w[i]=1.0;}
410 } else if(weights==1) {
411 tac.isweight=1; for(int i=0; i<tac.frameNr; i++) tac.w[i]=1.0;
412 } else if(weights==2) {
413 dftWeightByFreq(&tac);
414 }
415 if(verbose>20) {
416 printf("data_weights := %g", tac.w[0]);
417 for(int i=1; i<tac.frameNr; i++) printf(", %g", tac.w[i]);
418 printf("\n");
419 }
420
421 /* Get the number of samples with weight > 0 */
422 int fitDataNr=dftWSampleNr(&tac);
423 if(verbose>2) printf("samples_in_fit := %d\n", fitDataNr);
424
425
426 /*
427 * Allocate memory for the fit parameters
428 */
429 if(verbose>1) printf("allocating memory for fit parameters.\n");
430 FIT fit; fitInit(&fit);
431 ret=fit_allocate_with_dft(&fit, &tac);
432 if(ret) {
433 fprintf(stderr, "Error: cannot allocate memory for fit parameters.\n");
434 dftEmpty(&tac); return(3);
435 }
436 tpcProgramName(argv[0], 1, 1, fit.program, 1024);
437 strlcpy(fit.datafile, tacfile, FILENAME_MAX);
438 fit.time=time(NULL);
439 for(int ri=0; ri<tac.voiNr; ri++) {
440 if(sumn==2) fit.voi[ri].type=1312;
441 else if(sumn==4) fit.voi[ri].type=1314;
442 else fit.voi[ri].type=1313;
443 fit.voi[ri].start=tstart; fit.voi[ri].end=tstop;
444 fit.voi[ri].dataNr=fitDataNr;
445 }
446
447
448 /*
449 * Fit each TAC
450 */
451 if(verbose>0) {printf("fitting\n"); fflush(stdout);}
452 double (*func)(int parNr, double *p, void*);
453 if(pTransform) {
454 if(dat_type==0) func=func_normal; else func=func_integ;
455 } else {
456 if(dat_type==0) func=func_normal_direct; else func=func_integ_direct;
457 }
459 if(pTransform) TGO_SQUARED_TRANSF=0; else TGO_SQUARED_TRANSF=1;
460
461 /* Fit one TAC at a time */
462 for(int ri=0; ri<tac.voiNr; ri++) {
463 if(tac.voiNr>1 && verbose>0) {printf("."); fflush(stdout);}
464
465 /* Set data pointers */
466 x=tac.x; ymeas=tac.voi[ri].y; yfit=tac.voi[ri].y2; w=tac.w;
467 dataNr=tac.frameNr;
468
469 double aic=1.0E+100;
470
471 double xmax=nan(""), ymax=nan("");
472 int imax=0;
473 double dt=fixed_delay;
474 double lambda1=nan(""), a1=nan("");
475
476 if(!limfile[0]) { // Limits not given by user
477 /* Determine reasonable guess for parameters of the surge function and delay:
478 L1=1/(xmax-dt) , A1=ymax*L1*exp(1) */
479 if(dat_type==0) { // TAC
480 ret=dftMinMaxTAC(&tac, ri, NULL, &xmax, NULL, &ymax, NULL, NULL, NULL, &imax);
481 } else { // TAC AUC: max value is the highest slope
482 int n=dataNr/5; if(n<2) n=2;
483 double xstart=0.0; if(!isnan(fixed_delay)) xstart=fixed_delay;
484 ret=highest_slope_after(x, ymeas, dataNr, n, xstart, &ymax, NULL, NULL, &xmax);
485 /* Search the sample index for max */
486 double xdmin=1.0E+10; imax=0;
487 for(int i=0; i<dataNr; i++) {
488 double xd=fabs(x[i]-xmax); if(xd<xdmin) {imax=i; xdmin=xd;}
489 }
490 }
491 if(ret!=0) {
492 fprintf(stderr, "Error: invalid TAC data in %s\n", tacfile);
493 dftEmpty(&tac); fitEmpty(&fit); return(2);
494 }
495 if(verbose>2) printf(" maxy=%g max_x=%g max_i=%d\n", ymax, xmax, imax);
496 if(isnan(fixed_delay)) {
497 /* How long time (ht) before the peak do we have to go to get y<ymax/50 ? */
498 int i; for(i=imax-1; i>0; i--) if(ymeas[i]<0.5*ymax) break;
499 /* assume that activity start time dt=xmax-2*ht */
500 double ht=xmax-x[i];
501 dt=xmax-2.0*ht; if(!(dt>0.0)) dt=0.0;
502 if(verbose>2) printf(" guessed dt=%g (ht=%g)\n", dt, ht);
503 }
504 /* Guess for the surge function */
505 lambda1=1.0/(xmax-dt);
506 a1=ymax*lambda1*M_E;
507 if(verbose>2) printf(" a1=%g lambda1=%g\n", a1, lambda1);
508 }
509
510 /* Fit with surge function and one exponential function, if requested */
511 if(sumn==0 || sumn==2) {
512 parNr=5; //if(isnan(fixed_delay)) parNr++;
513 /* Limits for the surge and exp functions */
514 if(limfile[0]) {
515 pmin[0]=def_pmin[F_A1]; pmax[0]=def_pmax[F_A1];
516 pmin[1]=def_pmin[F_L1]; pmax[1]=def_pmax[F_L1];
517 pmin[2]=def_pmin[F_A2]; pmax[2]=def_pmax[F_A2];
518 pmin[3]=def_pmin[F_L2]; pmax[3]=def_pmax[F_L2];
519 pmin[4]=def_pmin[F_DT]; pmax[4]=def_pmax[F_DT];
520 } else {
521 pmin[0]=0.25*a1; pmax[0]=20.0*a1;
522 pmin[1]=0.25*lambda1; pmax[1]=10.0*lambda1;
523 pmin[2]=0.0000001*a1; pmax[2]=50.0*a1;
524 pmin[3]=0.0000001*lambda1; pmax[3]=20.0*lambda1;
525 /* Limits for delay time */
526 if(!isnan(fixed_delay)) {
527 pmin[parNr-1]=pmax[parNr-1]=fixed_delay;
528 } else {
529 pmin[parNr-1]=0.25*dt; pmax[parNr-1]=0.5*(dt+xmax);
530 }
531 }
532 /* Fit */
533 int tgo_nr=150*parNr;
534 int neigh_nr=3*parNr;
535 double wss, p[MAX_PARAMETERS];
536 for(int i=0; i<MAX_PARAMETERS; i++) p[i]=0.0;
537 ret=tgo(pmin, pmax, func, NULL, parNr, neigh_nr, &wss, p, tgo_nr, iter_nr, verbose-5);
538 if(ret) {
539 fprintf(stderr, "Error %d in TGO.\n", ret);
540 dftEmpty(&tac); fitEmpty(&fit); return(4);
541 }
542 if(verbose>2) {
543 printf("fitted parameters:\n");
544 for(int i=0; i<parNr; i++)
545 printf("\tp%d\t%g\t(%g - %g)\n", 1+i, p[i], pmin[i], pmax[i]);
546 printf("\tWSS := %g\n", wss);
547 }
548 /* Check the MRL */
549 int mrl_passed=1;
550 if(MRL_check) {
551 if(verbose>1) printf("\tChecking the MRL.\n");
552 int m=mrl_between_tacs(yfit, ymeas, dataNr);
553 if(sumn==2) {
554 if(m>3 && m>dataNr/3) {
555 fprintf(stderr, "Error: bad fit.\n");
556 fprintf(stderr, "\tMRL := %d / %d\n", m, dataNr);
557 dftEmpty(&tac); fitEmpty(&fit);
558 return(7);
559 } else if(m>2 && m>dataNr/4) {
560 fprintf(stderr, "\tWarning: bad fit.\n");
561 fprintf(stderr, "\tMRL := %d / %d\n", m, dataNr);
562 } else if(verbose>0) {
563 printf("\tMRL test passed.\n");
564 if(verbose>1) fprintf(stderr, "\tMRL := %d / %d\n", m, dataNr);
565 }
566 }
567 if(m>3 && m>dataNr/3) mrl_passed=0;
568 }
569 if(mrl_passed) {
570 /* Force parameter values inside limits, as they are in the simulation */
571 double a;
572 modelCheckParameters(parNr, pmin, pmax, p, p, &a);
573 /* Calculate AIC */
574 aic=aicSS(wss/a, fitDataNr, parFreeNr(parNr, pmin, pmax));
575 if(verbose>2) printf("\tAIC := %g\n", aic);
576 /* Copy parameter values into results data structure */
577 for(int i=0; i<parNr; i++) fit.voi[ri].p[i]=p[i];
578 fit.voi[ri].wss=wss/a; // remove penalty from reported WSS
579 fit.voi[ri].parNr=parNr;
580 }
581 }
582
583 /* Fit with surge function and two exponential functions, if requested */
584 if(sumn==0 || sumn==3) {
585 parNr=7; //if(isnan(fixed_delay)) parNr++;
586 /* Limits for the surge and exp functions */
587 if(limfile[0]) {
588 pmin[0]=def_pmin[F_A1]; pmax[0]=def_pmax[F_A1];
589 pmin[1]=def_pmin[F_L1]; pmax[1]=def_pmax[F_L1];
590 pmin[2]=def_pmin[F_A2]; pmax[2]=def_pmax[F_A2];
591 pmin[3]=def_pmin[F_L2]; pmax[3]=def_pmax[F_L2];
592 pmin[4]=def_pmin[F_A3]; pmax[4]=def_pmax[F_A3];
593 pmin[5]=def_pmin[F_L3]; pmax[5]=def_pmax[F_L3];
594 pmin[6]=def_pmin[F_DT]; pmax[6]=def_pmax[F_DT];
595 } else {
596 pmin[0]=0.5*a1; pmax[0]=10.0*a1;
597 pmin[1]=0.5*lambda1; pmax[1]=5.0*lambda1;
598 pmin[2]=0.00001*a1; pmax[2]=20.0*a1;
599 pmin[3]=0.01*lambda1; pmax[3]=10.0*lambda1;
600 pmin[4]=0.00001*ymax; pmax[4]=0.9*ymax;
601 pmin[5]=0.0; pmax[5]=0.75; if(steadystate) pmax[5]=0.0;
602 /* Limits for delay time */
603 if(!isnan(fixed_delay)) {
604 pmin[parNr-1]=pmax[parNr-1]=fixed_delay;
605 } else {
606 pmin[parNr-1]=0.25*dt; pmax[parNr-1]=0.5*(dt+xmax);
607 }
608 }
609 /* Fit */
610 int tgo_nr=250*parNr;
611 int neigh_nr=1+2*parNr;
612 double wss, p[MAX_PARAMETERS];
613 for(int i=0; i<MAX_PARAMETERS; i++) p[i]=0.0;
614 ret=tgo(pmin, pmax, func, NULL, parNr, neigh_nr, &wss, p, tgo_nr, iter_nr, verbose-5);
615 if(ret) {
616 fprintf(stderr, "Error %d in TGO.\n", ret);
617 dftEmpty(&tac); fitEmpty(&fit); return(4);
618 }
619 if(verbose>2) {
620 printf("fitted parameters:\n");
621 for(int i=0; i<parNr; i++)
622 printf("\tp%d\t%g\t(%g - %g)\n", 1+i, p[i], pmin[i], pmax[i]);
623 printf("\tWSS := %g\n", wss);
624 }
625 /* Check the MRL */
626 int mrl_passed=1;
627 if(MRL_check) {
628 if(verbose>1) printf("\tChecking the MRL.\n");
629 int m=mrl_between_tacs(yfit, ymeas, dataNr);
630 if(sumn==3) {
631 if(m>3 && m>dataNr/3) {
632 fprintf(stderr, "Error: bad fit.\n");
633 fprintf(stderr, "\tMRL := %d / %d\n", m, dataNr);
634 dftEmpty(&tac); fitEmpty(&fit);
635 return(7);
636 } else if(m>2 && m>dataNr/4) {
637 fprintf(stderr, "\tWarning: bad fit.\n");
638 fprintf(stderr, "\tMRL := %d / %d\n", m, dataNr);
639 } else if(verbose>0) {
640 printf("\tMRL test passed.\n");
641 if(verbose>1) fprintf(stderr, "\tMRL := %d / %d\n", m, dataNr);
642 }
643 }
644 if(m>3 && m>dataNr/3) mrl_passed=0;
645 }
646 if(mrl_passed) {
647 /* Force parameter values inside limits, as they are in the simulation */
648 double a;
649 modelCheckParameters(parNr, pmin, pmax, p, p, &a);
650 /* Calculate AIC */
651 double laic=aicSS(wss/a, fitDataNr, parFreeNr(parNr, pmin, pmax));
652 if(verbose>2) printf("\tAIC := %g\n", laic);
653 if(sumn==3 || laic<aic) {
654 aic=laic;
655 /* Copy parameter values into results data structure */
656 for(int i=0; i<parNr; i++) fit.voi[ri].p[i]=p[i];
657 fit.voi[ri].wss=wss/a; // remove penalty from reported WSS
658 fit.voi[ri].parNr=parNr;
659 }
660 }
661 }
662
663 /* Fit with surge function and three exponential functions, if requested */
664 if(sumn==0 || sumn==4) {
665 parNr=9; //if(isnan(fixed_delay)) parNr++;
666 /* Limits for the surge and exp functions */
667 if(limfile[0]) {
668 pmin[0]=def_pmin[F_A1]; pmax[0]=def_pmax[F_A1];
669 pmin[1]=def_pmin[F_L1]; pmax[1]=def_pmax[F_L1];
670 pmin[2]=def_pmin[F_A2]; pmax[2]=def_pmax[F_A2];
671 pmin[3]=def_pmin[F_L2]; pmax[3]=def_pmax[F_L2];
672 pmin[4]=def_pmin[F_A3]; pmax[4]=def_pmax[F_A3];
673 pmin[5]=def_pmin[F_L3]; pmax[5]=def_pmax[F_L3];
674 pmin[6]=def_pmin[F_A4]; pmax[6]=def_pmax[F_A4];
675 pmin[7]=def_pmin[F_L4]; pmax[7]=def_pmax[F_L4];
676 pmin[8]=def_pmin[F_DT]; pmax[8]=def_pmax[F_DT];
677 } else {
678 if(sumn==4 || aic>1.0E+10) {
679 pmin[0]=0.5*a1; pmax[0]=10.0*a1;
680 pmin[1]=0.5*lambda1; pmax[1]=10.0*lambda1;
681 pmin[2]=0.00001*a1; pmax[2]=20.0*a1;
682 pmin[3]=0.01*lambda1; pmax[3]=10.0*lambda1;
683 pmin[4]=0.00001*ymax; pmax[4]=0.9*ymax;
684 pmin[5]=0.0001; pmax[5]=1.25;
685 pmin[6]=0.0; pmax[6]=0.9*ymax;
686 pmin[7]=0.0; pmax[7]=0.50; if(steadystate) pmax[7]=0.0;
687 /* Limits for delay time */
688 if(!isnan(fixed_delay)) {
689 pmin[parNr-1]=pmax[parNr-1]=fixed_delay;
690 } else {
691 pmin[parNr-1]=0.25*dt; pmax[parNr-1]=0.5*(dt+xmax);
692 }
693 } else {
694 pmin[0]=0.5*fit.voi[ri].p[0]; pmax[0]=1.2*fit.voi[ri].p[0];
695 pmin[1]=0.9*fit.voi[ri].p[1]; pmax[1]=2.5*fit.voi[ri].p[1];
696 pmin[2]=0.5*fit.voi[ri].p[2]; pmax[2]=1.2*fit.voi[ri].p[2];
697 pmin[3]=0.9*fit.voi[ri].p[3]; pmax[3]=1.5*fit.voi[ri].p[3];
698 pmin[4]=0.9*fit.voi[ri].p[4]; pmax[4]=1.2*fit.voi[ri].p[4];
699 pmin[5]=0.01; pmax[5]=1.10;
700 pmin[6]=0.0; pmax[6]=0.5*ymax;
701 pmin[7]=0.0; pmax[7]=0.25; if(steadystate) pmax[7]=0.0;
702 /* Limits for delay time */
703 if(!isnan(fixed_delay)) {
704 pmin[parNr-1]=pmax[parNr-1]=fixed_delay;
705 } else {
706 pmin[parNr-1]=0.9*fit.voi[ri].p[6]; pmax[parNr-1]=1.1*fit.voi[ri].p[6];
707 }
708 }
709 }
710 /* Fit */
711 int tgo_nr=300*parNr;
712 int neigh_nr=2+2*parNr;
713 double wss, p[MAX_PARAMETERS];
714 for(int i=0; i<MAX_PARAMETERS; i++) p[i]=0.0;
715 ret=tgo(pmin, pmax, func, NULL, parNr, neigh_nr, &wss, p, tgo_nr, iter_nr, verbose-5);
716 if(ret) {
717 fprintf(stderr, "Error %d in TGO.\n", ret);
718 dftEmpty(&tac); fitEmpty(&fit); return(4);
719 }
720 if(verbose>2) {
721 printf("fitted parameters:\n");
722 for(int i=0; i<parNr; i++)
723 printf("\tp%d\t%g\t(%g - %g)\n", 1+i, p[i], pmin[i], pmax[i]);
724 printf("\tWSS := %g\n", wss);
725 }
726 /* Check the MRL */
727 int mrl_passed=1;
728 if(MRL_check) {
729 if(verbose>1) printf("\tChecking the MRL.\n");
730 int m=mrl_between_tacs(yfit, ymeas, dataNr);
731 if(sumn==4) {
732 if(m>3 && m>dataNr/3) {
733 fprintf(stderr, "Error: bad fit.\n");
734 fprintf(stderr, "\tMRL := %d / %d\n", m, dataNr);
735 dftEmpty(&tac); fitEmpty(&fit);
736 return(7);
737 } else if(m>2 && m>dataNr/4) {
738 fprintf(stderr, "\tWarning: bad fit.\n");
739 fprintf(stderr, "\tMRL := %d / %d\n", m, dataNr);
740 } else if(verbose>0) {
741 printf("\tMRL test passed.\n");
742 if(verbose>1) fprintf(stderr, "\tMRL := %d / %d\n", m, dataNr);
743 }
744 }
745 if(m>3 && m>dataNr/3) mrl_passed=0;
746 }
747 if(mrl_passed) {
748 /* Force parameter values inside limits, as they are in the simulation */
749 double a;
750 modelCheckParameters(parNr, pmin, pmax, p, p, &a);
751 /* Calculate AIC */
752 double laic=aicSS(wss/a, fitDataNr, parFreeNr(parNr, pmin, pmax));
753 if(verbose>2) printf("\tAIC := %g\n", laic);
754 if(sumn==4 || laic<aic) {
755 aic=laic;
756 /* Copy parameter values into results data structure */
757 for(int i=0; i<parNr; i++) fit.voi[ri].p[i]=p[i];
758 fit.voi[ri].wss=wss/a; // remove penalty from reported WSS
759 fit.voi[ri].parNr=parNr;
760 }
761 }
762 }
763
764 if(aic>1.0E+10) {
765 fprintf(stderr, "Error: fitting not successful.\n");
766 dftEmpty(&tac); fitEmpty(&fit); return(5);
767 }
768
769 if(pTransform) {
770 /* Separate exponential terms to independent values */
771 for(int pi=5; pi<fit.voi[ri].parNr; pi+=2) fit.voi[ri].p[pi]*=fit.voi[ri].p[pi-2];
772 /* Switch the sign of exponential terms */
773 for(int pi=1; pi<fit.voi[ri].parNr; pi+=2) fit.voi[ri].p[pi]*=-1.0;
774 }
775
776 /* Compute fitted TAC again with final sumn, if sumn was not predetermined */
777 if(sumn==0) {
778 if(verbose>3) printf("\tparNr := %d\n", fit.voi[ri].parNr);
779 int n=fit.voi[ri].parNr-1; //if(!isnan(fixed_delay)) n--;
780 n/=2; if(verbose>2) printf("\tsumn := %d\n", n);
781 if(n==2) fit.voi[ri].type=1312;
782 else if(n==3) fit.voi[ri].type=1313;
783 else fit.voi[ri].type=1314;
784 fitEvaltac(&fit.voi[ri], x, yfit, tac.frameNr);
785 }
786 if(verbose>3) {
787 printf("Sample\tX\tY\tYfit\tWeight\n");
788 for(int i=0; i<dataNr; i++)
789 printf("%d\t%9.2e\t%9.2e\t%9.2e\t%7.1e\n", 1+i, x[i], ymeas[i], yfit[i], w[i]);
790 }
791
792 } // next TAC
793 if(tac.voiNr>1 && verbose>0) {printf("\n"); fflush(stdout);}
794
795
796 /*
797 * Save fit results
798 */
799 if(verbose>1) printf("saving results in %s\n", parfile);
800 ret=fitWrite(&fit, parfile); if(ret) {
801 fprintf(stderr, "Error in writing '%s': %s\n", parfile, fiterrmsg);
802 dftEmpty(&tac); fitEmpty(&fit); return(11);
803 }
804 if(verbose>0) {printf("Function parameters written in %s\n", parfile); fflush(stdout);}
805
806 /* Also allocate memory for result file, if needed */
807 if(resfile[0]) {
808 if(verbose>1) {printf("allocating memory for results.\n"); fflush(stdout);}
809 RES res; resInit(&res);
810 char buf[256];
811 ret=fitToResult(&fit, &res, buf);
812 if(ret!=0) {
813 fprintf(stderr, "Error in making results: %s\n", buf); fflush(stderr);
814 dftEmpty(&tac); fitEmpty(&fit); resEmpty(&res); return(12);
815 }
816 int sumn=0;
817 for(int i=0; i<fit.voiNr; i++) if(fit.voi[i].parNr>sumn) sumn=fit.voi[i].parNr;
818 sumn--; sumn/=2; if(verbose>3) {printf(" sumn=%d\n", sumn); fflush(stdout);}
819 int n=0;
820 strcpy(res.parname[n++], "Function");
821 for(int i=1; i<=sumn; i++) {
822 sprintf(res.parname[n++], "A%d", i);
823 sprintf(res.parname[n++], "L%d", i);
824 }
825 strcpy(res.parname[n++], "dT");
826 strcpy(res.parname[n++], "WSS");
827 strcpy(res.program, fit.program);
828 sprintf(res.datarange, "%g - %g", tstart, tstop);
829 strcpy(res.studynr, tac.studynr);
830 /* Move dT parameter into correct place in case parameter number is variable */
831 for(int ri=0; ri<fit.voiNr; ri++) if(fit.voi[ri].parNr!=res.parNr-2) {
832 int imv=res.parNr-2-fit.voi[ri].parNr;
833 int i2=res.parNr-2;
834 int i1=i2-imv;
835 res.voi[ri].parameter[i2]=res.voi[ri].parameter[i1];
836 res.voi[ri].parameter[i1]=0.0;
837 }
838 if(verbose>1) resPrint(&res);
839 if(verbose>1) {printf("saving results in %s\n", resfile); fflush(stdout);}
840 if(resWrite(&res, resfile, verbose-3)) {
841 fprintf(stderr, "Error in writing '%s': %s\n", resfile, reserrmsg);
842 dftEmpty(&tac); fitEmpty(&fit); resEmpty(&res); return(11);
843 }
844 resEmpty(&res);
845 if(verbose>1) {printf("Function parameters written in %s\n", resfile); fflush(stdout);}
846 }
847
848
849
850 /*
851 * Plotting of fitted TACs
852 */
853 if(svgfile[0] || svgfile1[0] || svgfile2[0]) {
854
855 if(verbose>1) printf("calculating fitted curve at automatically generated sample times\n");
856 DFT adft; dftInit(&adft);
857 ret=dftAutointerpolate(&tac, &adft, 1.02*tac.x[tac.frameNr-1], verbose-10);
858 if(ret) {
859 fprintf(stderr, "Error %d in memory allocation for fitted curves.\n", ret);
860 dftEmpty(&tac); fitEmpty(&fit); dftEmpty(&adft);
861 return(13);
862 }
863 if(dat_type==1) for(int ri=0; ri<adft.voiNr; ri++)
864 ret=fitIntegralEvaltac(&fit.voi[ri], adft.x, adft.voi[ri].y, adft.frameNr);
865 else for(int ri=0; ri<adft.voiNr; ri++)
866 ret=fitEvaltac(&fit.voi[ri], adft.x, adft.voi[ri].y, adft.frameNr);
867 if(ret!=0) {
868 fprintf(stderr, "Error: cannot calculate fitted curve for '%s'.\n", svgfile);
869 dftEmpty(&tac); dftEmpty(&adft); fitEmpty(&fit);
870 return(14);
871 }
872 /* Save SVG plot of fitted and original data */
873 char tmp[256];
874 tpcProgramName(argv[0], 0, 0, tmp, 128); strcat(tmp, " ");
875 if(strlen(adft.studynr)>1) strcat(tmp, adft.studynr);
876 if(svgfile[0]) {
877 if(verbose>1) printf("writing %s\n", svgfile);
878 ret=plot_fitrange_svg(&tac, &adft, tmp, 0.0, nan(""), 0.0, nan(""), svgfile, verbose-10);
879 if(ret) {
880 fprintf(stderr, "Error (%d) in writing '%s'.\n", ret, svgfile);
881 dftEmpty(&adft); dftEmpty(&tac); fitEmpty(&fit);
882 return(30+ret);
883 }
884 if(verbose>0) printf("Plots written in %s\n", svgfile);
885 }
886
887 double tmax=tac.x[tac.frameNr/2];
888 if(dat_type==0 && (svgfile1[0] || svgfile2[0]))
889 dftMinMaxTAC(&tac, 0, NULL, &tmax, NULL, NULL, NULL, NULL, NULL, NULL);
890
891 /* Save SVG plot of first part of fitted and original data */
892 if(svgfile1[0]) {
893 if(verbose>1) printf("writing %s\n", svgfile1);
894 ret=plot_fitrange_svg(&tac, &adft, tmp, 0.0, 2.*tmax, 0.0, nan(""), svgfile1, verbose-10);
895 if(ret) {
896 fprintf(stderr, "Error (%d) in writing '%s'.\n", ret, svgfile1);
897 dftEmpty(&adft); dftEmpty(&tac); fitEmpty(&fit);
898 return(30+ret);
899 }
900 if(verbose>0) printf("Plots written in %s\n", svgfile1);
901 }
902 /* Save SVG plot of lower part of fitted and original data */
903 if(svgfile2[0]) {
904 if(verbose>1) printf("writing %s\n", svgfile2);
905 ret=plot_fitrange_svg(&tac, &adft, tmp, 0.8*tmax+0.2*tac.x[tac.frameNr-1],
906 nan(""), 0.0, nan(""), svgfile2, verbose-10);
907 if(ret) {
908 fprintf(stderr, "Error (%d) in writing '%s'.\n", ret, svgfile2);
909 dftEmpty(&adft); dftEmpty(&tac); fitEmpty(&fit);
910 return(30+ret);
911 }
912 if(verbose>0) printf("Plots written in %s\n", svgfile2);
913 }
914 dftEmpty(&adft);
915 }
916
917
918
919 /*
920 * Save fitted TAC with original sample times;
921 * this destroys the original sample values
922 */
923 if(fitfile[0]) {
924 if(verbose>1) printf("writing fitted TAC(s)\n");
925
926 if(dat_type==1) for(int ri=0; ri<tac.voiNr; ri++)
927 ret=fitIntegralEvaltac(&fit.voi[ri], tac.x, tac.voi[ri].y, tac.frameNr);
928 else for(int ri=0; ri<tac.voiNr; ri++)
929 ret=fitEvaltac(&fit.voi[ri], tac.x, tac.voi[ri].y, tac.frameNr);
930 if(ret!=0) {
931 fprintf(stderr, "Error: cannot calculate fitted curve for '%s'.\n", fitfile);
932 dftEmpty(&tac); fitEmpty(&fit);
933 return(17);
934 }
935 tac.isweight=0;
936
937 ret=dftWrite(&tac, fitfile);
938 if(ret) {
939 fprintf(stderr, "Error: cannot write '%s'.\n", fitfile);
940 dftEmpty(&tac); fitEmpty(&fit);
941 return(18);
942 }
943 }
944
945
946 dftEmpty(&tac); fitEmpty(&fit);
947 return(0);
948}
949/*****************************************************************************/
950
951/*****************************************************************************
952 *
953 * Functions to be minimized
954 *
955 *****************************************************************************/
956
957double func_normal(int parNr, double *p, void *fdata)
958{
959 int i;
960 double A1, A2, A3, A4, L1, L2, L3, L4;
961 double dt, xt, wss;
962 double pa[MAX_PARAMETERS], penalty=1.0;
963 double e1, e2, e3, e4;
964
965 /* Check parameters against the constraints */
966 (void)modelCheckParameters(parNr, pmin, pmax, p, pa, &penalty);
967
968 /* Get parameters */
969 if(fdata) {/*prevent compiler warning*/}
970 if(parNr==5 || parNr==7 || parNr==9) dt=pa[parNr-1]; else dt=0.0;
971 A1=pa[0]; A2=pa[2];
972 if(parNr>=6) A3=pa[4]; else A3=0.0;
973 if(parNr>=8) A4=pa[6]; else A4=0.0;
974 L1=pa[1]; L2=pa[3];
975 if(parNr>=6) L3=L2*pa[5]; else L3=0.0;
976 if(parNr>=8) L4=L3*pa[7]; else L4=0.0;
977 L1*=-1.0; L2*=-1.0; L3*=-1.0; L4*=-1.0;
978
979 /* Check that D(0)>0 */
980 double d= A1 + A2*L2 + A3*L3 + A4*L4 - L1*(A2+A3+A4);
981 if(d<=0.0) penalty*=100.0; // penalty*=(1.0-v)*1.0E+03;
982
983 /* Calculate the curve values and weighted SS */
984 for(i=0, wss=0.0; i<dataNr; i++) {
985 xt=x[i]-dt;
986 if(xt<=0.0)
987 yfit[i]=0.0;
988 else {
989 e1=exp(L1*xt);
990 e2=exp(L2*xt);
991 e3=exp(L3*xt);
992 e4=exp(L4*xt);
993 // evaluate the function value at xt
994 yfit[i]=(A1*xt -A2 - A3 - A4)*e1 + A2*e2 + A3*e3 + A4*e4;
995 }
996 double v=yfit[i]-ymeas[i]; wss+=w[i]*v*v;
997 }
998 wss*=penalty;
999 return(wss);
1000}
1001
1002double func_integ(int parNr, double *p, void *fdata)
1003{
1004 int i;
1005 double A1, A2, A3, A4, L1, L2, L3, L4;
1006 double dt, xt, wss;
1007 double pa[MAX_PARAMETERS], penalty=1.0;
1008 double e1, e2, e3, e4;
1009
1010 /* Check parameters against the constraints */
1011 (void)modelCheckParameters(parNr, pmin, pmax, p, pa, &penalty);
1012
1013 /* Get parameters */
1014 if(fdata) {/*prevent compiler warning*/}
1015 if(parNr==5 || parNr==7 || parNr==9) dt=pa[parNr-1]; else dt=0.0;
1016 A1=pa[0]; A2=pa[2];
1017 if(parNr>=6) A3=pa[4]; else A3=0.0;
1018 if(parNr>=8) A4=pa[6]; else A4=0.0;
1019 L1=pa[1]; L2=pa[3];
1020 if(parNr>=6) L3=L2*pa[5]; else L3=0.0;
1021 if(parNr>=8) L4=L3*pa[7]; else L4=0.0;
1022 L1*=-1.0; L2*=-1.0; L3*=-1.0; L4*=-1.0;
1023
1024 /* Check that D(0)>0 */
1025 double d= A1 + A2*L2 + A3*L3 + A4*L4 - L1*(A2+A3+A4);
1026 if(d<=0.0) penalty*=100.0; //penalty*=(1.0-v)*1.0E+03;
1027
1028 /* Calculate the integral curve values and weighted SS */
1029 for(i=0, wss=0.0; i<dataNr; i++) {
1030 xt=x[i]-dt;
1031 yfit[i]=0.0;
1032 if(xt>0.0) {
1033 // evaluate the function value at xt
1034 e1=exp(L1*xt);
1035 if(L1!=0.0) {
1036 yfit[i]+=(A2/L1)*(1.0-e1) + (A3/L1)*(1.0-e1) + (A4/L1)*(1.0-e1);
1037 yfit[i]+=(A1/(L1*L1))*(1.0 + e1*(L1*xt-1.0));
1038 }
1039 e2=exp(L2*xt);
1040 if(L2!=0.0)
1041 yfit[i]+=(A2/L2)*(e2-1.0);
1042 e3=exp(L3*xt);
1043 if(L3!=0.0)
1044 yfit[i]+=(A3/L3)*(e3-1.0);
1045 e4=exp(L4*xt);
1046 if(L4!=0.0)
1047 yfit[i]+=(A4/L4)*(e4-1.0);
1048 }
1049 double v=yfit[i]-ymeas[i]; wss+=w[i]*v*v;
1050 }
1051 wss*=penalty;
1052 return(wss);
1053}
1054
1055/* Functions with parameters that are used directly without any transformations */
1056
1057double func_normal_direct(int parNr, double *p, void *fdata)
1058{
1059 int i;
1060 double A1, A2, A3, A4, L1, L2, L3, L4;
1061 double dt, xt, wss;
1062 double pa[MAX_PARAMETERS], penalty=1.0;
1063 double e1, e2, e3, e4;
1064
1065 /* Check parameters against the constraints */
1066 (void)modelCheckParameters(parNr, pmin, pmax, p, pa, &penalty);
1067
1068 /* Get parameters */
1069 if(fdata) {/*prevent compiler warning*/}
1070 if(parNr==5 || parNr==7 || parNr==9) dt=pa[parNr-1]; else dt=0.0;
1071 A1=pa[0]; A2=pa[2];
1072 if(parNr>=6) A3=pa[4]; else A3=0.0;
1073 if(parNr>=8) A4=pa[6]; else A4=0.0;
1074 L1=pa[1]; L2=pa[3];
1075 if(parNr>=6) L3=pa[5]; else L3=0.0;
1076 if(parNr>=8) L4=pa[7]; else L4=0.0;
1077
1078 /* Check that D(0)>0 */
1079 double d= A1 + A2*L2 + A3*L3 + A4*L4 - L1*(A2+A3+A4);
1080 if(d<=0.0) penalty*=100.0; // penalty*=(1.0-v)*1.0E+03;
1081
1082 /* Calculate the curve values and weighted SS */
1083 for(i=0, wss=0.0; i<dataNr; i++) {
1084 xt=x[i]-dt;
1085 if(xt<=0.0)
1086 yfit[i]=0.0;
1087 else {
1088 e1=exp(L1*xt);
1089 e2=exp(L2*xt);
1090 e3=exp(L3*xt);
1091 e4=exp(L4*xt);
1092 // evaluate the function value at xt
1093 yfit[i]=(A1*xt -A2 - A3 - A4)*e1 + A2*e2 + A3*e3 + A4*e4;
1094 }
1095 double v=yfit[i]-ymeas[i]; wss+=w[i]*v*v;
1096 }
1097 wss*=penalty;
1098 return(wss);
1099}
1100
1101double func_integ_direct(int parNr, double *p, void *fdata)
1102{
1103 int i;
1104 double A1, A2, A3, A4, L1, L2, L3, L4;
1105 double dt, xt, wss;
1106 double pa[MAX_PARAMETERS], penalty=1.0;
1107 double e1, e2, e3, e4;
1108
1109 /* Check parameters against the constraints */
1110 (void)modelCheckParameters(parNr, pmin, pmax, p, pa, &penalty);
1111
1112 /* Get parameters */
1113 if(fdata) {/*prevent compiler warning*/}
1114 if(parNr==5 || parNr==7 || parNr==9) dt=pa[parNr-1]; else dt=0.0;
1115 A1=pa[0]; A2=pa[2];
1116 if(parNr>=6) A3=pa[4]; else A3=0.0;
1117 if(parNr>=8) A4=pa[6]; else A4=0.0;
1118 L1=pa[1]; L2=pa[3];
1119 if(parNr>=6) L3=pa[5]; else L3=0.0;
1120 if(parNr>=8) L4=pa[7]; else L4=0.0;
1121
1122 /* Check that D(0)>0 */
1123 double d= A1 + A2*L2 + A3*L3 + A4*L4 - L1*(A2+A3+A4);
1124 if(d<=0.0) penalty*=100.0; //penalty*=(1.0-v)*1.0E+03;
1125
1126 /* Calculate the integral curve values and weighted SS */
1127 for(i=0, wss=0.0; i<dataNr; i++) {
1128 xt=x[i]-dt;
1129 yfit[i]=0.0;
1130 if(xt>0.0) {
1131 // evaluate the function value at xt
1132 e1=exp(L1*xt);
1133 if(L1!=0.0) {
1134 yfit[i]+=(A2/L1)*(1.0-e1) + (A3/L1)*(1.0-e1) + (A4/L1)*(1.0-e1);
1135 yfit[i]+=(A1/(L1*L1))*(1.0 + e1*(L1*xt-1.0));
1136 }
1137 e2=exp(L2*xt);
1138 if(L2!=0.0)
1139 yfit[i]+=(A2/L2)*(e2-1.0);
1140 e3=exp(L3*xt);
1141 if(L3!=0.0)
1142 yfit[i]+=(A3/L3)*(e3-1.0);
1143 e4=exp(L4*xt);
1144 if(L4!=0.0)
1145 yfit[i]+=(A4/L4)*(e4-1.0);
1146 }
1147 double v=yfit[i]-ymeas[i]; wss+=w[i]*v*v;
1148 }
1149 wss*=penalty;
1150 return(wss);
1151}
1152/*****************************************************************************/
1153
1154/*****************************************************************************/
int parFreeNr(const int n, double *pLower, double *pUpper)
Calculate the number of free parameters.
Definition aic.c:50
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 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
int iftPutDouble(IFT *ift, char *key, double value, char *cmt_type, int verbose)
Definition ift.c:145
void iftEmpty(IFT *ift)
Definition ift.c:60
void iftInit(IFT *ift)
Definition ift.c:45
int iftRead(IFT *ift, char *filename, int is_key_required, int verbose)
Definition iftfile.c:24
int iftWrite(IFT *ift, char *filename, int verbose)
Definition iftfile.c:282
int iftGetDoubleValue(IFT *ift, int si, const char *key, double *value, int verbose)
Definition iftsrch.c:268
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 fitEvaltac(FitVOI *r, double *x, double *y, int dataNr)
Definition mathfunc.c:1252
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
int fitIntegralEvaltac(FitVOI *r, double *x, double *yi, int dataNr)
Definition mathfunc.c:1517
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 highest_slope_after(double *x, double *y, int n, int slope_n, double x_start, double *m, double *c, double *xi, double *xh)
Definition pearson.c:475
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_SQUARED_TRANSF
Definition tgo.c:27
Header file for libtpcmodext.
int dftWSampleNr(DFT *tac)
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
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]
const char * status
Definition libtpcmisc.h:277
char studynr[MAX_STUDYNR_LEN+1]
int parNr
char parname[MAX_RESPARAMS][MAX_RESPARNAME_LEN+1]
ResVOI * voi
char program[1024]
char datarange[128]
double parameter[MAX_RESPARAMS]
double * y2
double * y