TPCCLIB
Loading...
Searching...
No Matches
fit_gvar.c
Go to the documentation of this file.
1
7/*****************************************************************************/
8#include "tpcclibConfig.h"
9/*****************************************************************************/
10#include <stdio.h>
11#include <stdlib.h>
12#include <math.h>
13#include <string.h>
14#include <time.h>
15/*****************************************************************************/
16#include "libtpcmisc.h"
17#include "libtpcmodel.h"
18#include "libtpccurveio.h"
19#include "libtpcsvg.h"
20#include "libtpcmodext.h"
21/*****************************************************************************/
22double func_gvar(int parNr, double *p, void*);
23/*****************************************************************************/
24double *x, *ymeas, *yfit, *w;
25int dataNr=0, parNr=6;
26double pmin[MAX_PARAMETERS], pmax[MAX_PARAMETERS];
27/*****************************************************************************/
28
29/*****************************************************************************/
30static char *info[] = {
31 "Non-linear fitting of Gamma variate bolus plus recirculation function",
32 "with time delay term to plasma and tissue time-activity curves (TACs).",
33 " ",
34 "Function:",
35 " | 0 , t < p1 ",
36 " f(t) = | ",
37 " | p2*((t-p1)^p3)*exp(-(t-p1)/p4) , t >= p1 ",
38 " | + p5*(1-exp(-(t-p1)/p4))*exp(-(t-p1)/p6) ",
39 " ",
40 "Usage: @P [Options] tacfile [fitfile]",
41 " ",
42 "Options:",
43 " -recirc=<Y|n>",
44 " Fit recirculation terms p5 and p6 (y, default), or fit only",
45 " gamma variate function setting p5=p6=0 (n).",
46 " -lim[=<filename>]",
47 " Specify the constraints for function parameters;",
48 " This file with default values can be created by giving this",
49 " option as the only command-line argument to this program.",
50 " -w1",
51 " All weights are set to 1.0 (no weighting); by default, weights in",
52 " data file are used, if available.",
53 " -wf",
54 " Weight by sampling interval.",
55 " -stoptime=<Fit end time>",
56 " All data with sample time > stoptime is excluded from the fit.",
57 " -thr=<Threshold%>",
58 " If sample value after the peak is less than Threshold% of the peak,",
59 " then that sample and all samples after that are omitted from the fit.",
60 " Hint: try to set threshold close to 100, e.g. 99%, to get a good",
61 " estimate of tracer appearance time.",
62 " -auto",
63 " Automatically sets the fit range from 0 to peak + at least one",
64 " sample more, until WSS/(sum of weights) gets worse.",
65 " -svg=<Filename>",
66 " Fitted and measured TACs are plotted in specified SVG file.",
67 " -fit=<Filename>",
68 " Fitted TACs are written in TAC format.",
69 " -stdoptions", // List standard options like --help, -v, etc
70 " ",
71 "TAC file must contain at least 2 columns, sample times and",
72 "concentrations.",
73 "Weights can be specified as usual if data is in DFT format.",
74 " ",
75 "Program writes the fit start and end times, nr of points, WSS,",
76 "and parameters (p1, p2, ...) of the fitted function to the fit file.",
77 " ",
78 "See also: fit2dat, fit_sinf, fit_exp, fit_ratf, fit_hiad",
79 " ",
80 "Keywords: curve fitting, TAC, simulation",
81 0};
82/*****************************************************************************/
83
84/*****************************************************************************/
85/* Turn on the globbing of the command line, since it is disabled by default in
86 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
87 In Unix&Linux wildcard command line processing is enabled by default. */
88/*
89#undef _CRT_glob
90#define _CRT_glob -1
91*/
92int _dowildcard = -1;
93/*****************************************************************************/
94
95/*****************************************************************************/
99int main(int argc, char **argv)
100{
101 int ai, help=0, version=0, verbose=1;
102 double def_pmin[MAX_PARAMETERS], def_pmax[MAX_PARAMETERS];
103 char datfile[FILENAME_MAX], fitfile[FILENAME_MAX], parfile[FILENAME_MAX],
104 svgfile[FILENAME_MAX], limfile[FILENAME_MAX];
105 int weights=0; // 0=default, 1=no weighting, 2=frequency
106 int autoend=0; // 0=no, 1=yes
107 int recirc=1; // recirculation terms: 0=no, 1=yes
108 double threshold=0.0, stoptime=-1.0;
109 char *cptr;
110 char progname[256];
111 int ret;
112
113
114 /*
115 * Set defaults for parameter constraints; these will probably
116 * be refined before fitting.
117 */
118 /* delay */ def_pmin[0]=0.0; def_pmax[0]=100.0;
119 /* p2 */ def_pmin[1]=1.0E-06; def_pmax[1]=1.0E+06;
120 /* p3 */ def_pmin[2]=1.0E-03; def_pmax[2]=2.0;
121 /* p4 */ def_pmin[3]=1.0E-01; def_pmax[3]=1.0E+03;
122 /* p5 */ def_pmin[4]=1.0E-06; def_pmax[4]=1.0E+06;
123 /* p6 */ def_pmin[5]=1.0; def_pmax[5]=1.0E+06;
124
125 /*
126 * Get arguments
127 */
128 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
129 datfile[0]=fitfile[0]=parfile[0]=svgfile[0]=limfile[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, "W1")==0) {
135 weights=1; continue;
136 } else if(strcasecmp(cptr, "WF")==0) {
137 weights=2; continue;
138 } else if(strncasecmp(cptr, "LIM=", 4)==0) {
139 strlcpy(limfile, cptr+4, FILENAME_MAX); continue;
140 } else if(strncasecmp(cptr, "SVG=", 4)==0) {
141 strlcpy(svgfile, cptr+4, FILENAME_MAX); continue;
142 } else if(strncasecmp(cptr, "FIT=", 4)==0) {
143 strlcpy(fitfile, cptr+4, FILENAME_MAX); continue;
144 } else if(strncasecmp(cptr, "STOPTIME=", 9)==0) {
145 if(atof_with_check(cptr+9, &stoptime)==0 && stoptime>0.0) continue;
146 } else if(strncasecmp(cptr, "AUTO", 4)==0) {
147 autoend=1; continue;
148 } else if(strncasecmp(cptr, "THR=", 4)==0) {
149 if(atof_with_check(cptr+4, &threshold)==0) {
150 if(threshold<0.0) threshold=0.0;
151 else threshold/=100.0; // percentage to fraction
152 if(threshold<1.0) continue;
153 }
154 } else if(strncasecmp(cptr, "RECIRC=", 7)==0) {
155 if(strncasecmp(cptr+7, "YES", 1)==0) {recirc=1; continue;}
156 else if(strncasecmp(cptr+7, "NO", 1)==0) {recirc=0; continue;}
157 }
158 fprintf(stderr, "Error: invalid option '%s'\n", argv[ai]);
159 return(1);
160 } else break;
161
162 /* Change parameter number if NO recirculation terms */
163 if(recirc==0) {
164 parNr-=2;
165 def_pmax[4]=def_pmin[4]=def_pmax[5]=def_pmin[5]=0.0;
166 }
167
168 /* Print help or version? */
169 if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
170 if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
171 if(version) {tpcPrintBuild(argv[0], stdout); return(0);}
172
173 /* Process other arguments, starting from the first non-option */
174 if(ai<argc) {strlcpy(datfile, argv[ai++], FILENAME_MAX);}
175 if(ai<argc) {strlcpy(parfile, argv[ai++], FILENAME_MAX);}
176 if(ai<argc) {
177 fprintf(stderr, "Error: invalid argument '%s'\n", argv[ai]);
178 return(1);
179 }
180 if(!parfile[0]) strcpy(parfile, "stdout");
181
182 for(; ai<argc; ai++) {
183 if(!datfile[0]) {strcpy(datfile, argv[ai]); continue;}
184 else if(!parfile[0]) {strcpy(parfile, argv[ai]); continue;}
185 fprintf(stderr, "Error: invalid argument '%s'\n", argv[ai]);
186 return(1);
187 }
188 if(!parfile[0]) strcpy(parfile, "stdout");
189
190
191 /* If only filename for parameter constraints was given, then write one
192 with default contents, and exit */
193 if(limfile[0] && !datfile[0]) {
194 /* Check that initial value file does not exist */
195 if(strcasecmp(limfile, "stdout")!=0 && access(limfile, 0) != -1) {
196 fprintf(stderr, "Error: parameter constraint file %s exists.\n", limfile);
197 return(9);
198 }
199 if(verbose>1 && strcasecmp(limfile, "stdout")!=0)
200 printf("writing parameter constraints file\n");
201 /* Create parameter file */
202 IFT ift; iftInit(&ift);
203 char buf[32];
204 for(int i=0; i<parNr; i++) {
205 sprintf(buf, "p%d_lower", 1+i);
206 iftPutDouble(&ift, buf, def_pmin[i], NULL, 0);
207 sprintf(buf, "p%d_upper", 1+i);
208 iftPutDouble(&ift, buf, def_pmax[i], NULL, 0);
209 }
210 ret=iftWrite(&ift, limfile, 0);
211 if(ret) {
212 fprintf(stderr, "Error in writing '%s': %s\n", limfile, ift.status);
213 iftEmpty(&ift); return(9);
214 }
215 if(strcasecmp(limfile, "stdout")!=0)
216 fprintf(stdout, "Parameter file %s with initial values written.\n", limfile);
217 iftEmpty(&ift); return(0);
218 }
219
220
221 /* Is something missing? */
222 if(!datfile[0]) {
223 fprintf(stderr, "Error: missing command-line argument; use option --help\n");
224 return(1);
225 }
226
227 /* In verbose mode print arguments and options */
228 if(verbose>1) {
229 if(limfile[0]) printf("limfile := %s\n", limfile);
230 printf("datfile := %s\n", datfile);
231 printf("parfile := %s\n", parfile);
232 if(fitfile[0]) printf("fitfile := %s\n", fitfile);
233 if(svgfile[0]) printf("svgfile := %s\n", svgfile);
234 //printf("recirc := %d\n", recirc); // only later
235 printf("weights := %d\n", weights);
236 printf("threshold := %g\n", threshold);
237 printf("autoend := %d\n", autoend);
238 printf("stoptime := %g\n", stoptime);
239 fflush(stdout);
240 }
241
242
243 /*
244 * Read model parameter upper and lower limits
245 * if file for that was given
246 */
247 if(limfile[0]) {
248 if(verbose>1) printf("reading %s\n", limfile);
249 IFT ift; iftInit(&ift);
250 ret=iftRead(&ift, limfile, 1, 0);
251 if(ret) {
252 fprintf(stderr, "Error in reading '%s': %s\n", limfile, ift.status);
253 iftEmpty(&ift); return(9);
254 }
255 if(verbose>10) iftWrite(&ift, "stdout", 0);
256 double v;
257 char buf[32];
258 for(int i=0; i<6; i++) {
259 sprintf(buf, "p%d_lower", 1+i);
260 if(iftGetDoubleValue(&ift, 0, buf, &v, 0)>=0) def_pmin[i]=v;
261 sprintf(buf, "p%d_upper", 1+i);
262 if(iftGetDoubleValue(&ift, 0, buf, &v, 0)>=0) def_pmax[i]=v;
263 }
264 iftEmpty(&ift);
265 /* Check that these are ok */
266 int i, n=0;
267 for(i=0, ret=0; i<parNr; i++) {
268 if(def_pmin[i]<0.0) ret++;
269 if(def_pmax[i]<def_pmin[i]) ret++;
270 if(def_pmax[i]>def_pmin[i]) n++;
271 }
272 if(ret) {
273 fprintf(stderr, "Error: invalid parameter constraints.\n");
274 return(9);
275 }
276 if(n==0) {
277 fprintf(stderr, "Error: no model parameters left free for fitting.\n");
278 return(9);
279 }
280 /* Check if recirculation is turned off with limits */
281 if(parNr==6) {
282 if(def_pmax[4]<1.0E-10 && def_pmin[4]<1.0E-10) {
283 def_pmax[4]=def_pmin[4]=def_pmax[5]=def_pmin[5]=0.0;
284 recirc=0; parNr-=2;
285 }
286 }
287 }
288
289 /* In verbose mode print arguments and options */
290 if(verbose>1) {
291 printf("recirc := %d\n", recirc);
292 printf("parNr := %d\n", parNr);
293 fflush(stdout);
294 }
295 if(verbose>2) {
296 for(int i=0; i<parNr; i++) {
297 printf("def_pmin[%d] := %g\n", i, def_pmin[i]);
298 printf("def_pmax[%d] := %g\n", i, def_pmax[i]);
299 }
300 fflush(stdout);
301 }
302
303
304 /*
305 * Read data
306 */
307 if(verbose>1) {printf("reading %s\n", datfile); fflush(stdout);}
308 DFT dft; dftInit(&dft);
309 if(dftRead(datfile, &dft)) {
310 fprintf(stderr, "Error in reading '%s': %s\n", datfile, dfterrmsg);
311 fflush(stderr);
312 return(2);
313 }
314 //int origDataNr=dft.frameNr;
315 /* Sort the samples by time in case data is catenated from several curves */
316 (void)dftSortByFrame(&dft);
317 if(verbose>100) dftPrint(&dft);
318 /* Apply specified fit stoptime if necessary */
319 if(stoptime>0.0) {
320 int fi;
321 for(fi=1; fi<dft.frameNr; fi++) if(dft.x[fi]>stoptime) break;
322 dft.frameNr=fi;
323 }
324 if((dft.frameNr<4 && recirc==0) || (dft.frameNr<6 && recirc==1)) {
325 fprintf(stderr, "Error: not enough samples for decent fitting.\n");
326 dftEmpty(&dft); fflush(stderr); return(3);
327 }
328 /* Check for NA's (data after stoptime is now 'removed') */
329 if(dft_nr_of_NA(&dft) > 0) {
330 fprintf(stderr, "Error: missing sample(s) in %s\n", datfile);
331 dftEmpty(&dft); fflush(stderr); return(3);
332 }
333
334 /* Get min and max X and Y */
335 double tstart, tstop, miny, maxy;
336 ret=dftMinMax(&dft, &tstart, &tstop, &miny, &maxy);
337 if(ret!=0) {
338 fprintf(stderr, "Error: invalid contents in %s\n", datfile);
339 dftEmpty(&dft); return(3);
340 }
341 if(tstop<=0.0 || maxy<=0.0) {
342 fprintf(stderr, "Error: invalid contents in %s\n", datfile);
343 dftEmpty(&dft); fflush(stderr); return(3);
344 }
345 if(tstart<0.0) fprintf(stderr, "Warning: negative x value(s).\n");
346 if(miny<0.0) fprintf(stderr, "Warning: negative y value(s).\n");
347
348 /* Check and set weights */
349 if(weights==0) {
350 if(dft.isweight==0) {dft.isweight=1; for(int i=0; i<dft.frameNr; i++) dft.w[i]=1.0;}
351 } else if(weights==1) {
352 dft.isweight=1; for(int i=0; i<dft.frameNr; i++) dft.w[i]=1.0;
353 } else if(weights==2) {
354 dftWeightByFreq(&dft);
355 }
356
357
358
359 /*
360 * Allocate memory for fits
361 */
362 if(verbose>1) printf("allocating memory for fits.\n");
363 FIT fit; fitInit(&fit);
364 ret=fit_allocate_with_dft(&fit, &dft);
365 if(ret) {
366 fprintf(stderr, "Error: cannot allocate space for fit results (%d).\n", ret);
367 dftEmpty(&dft); return(4);
368 }
369 /* Set necessary information in fit data structure */
370 fit.voiNr=dft.voiNr;
371 strlcpy(fit.datafile, datfile, FILENAME_MAX);
372 tpcProgramName(argv[0], 1, 1, fit.program, 256);
373 strcpy(fit.unit, dft.unit);
374 fit.time=time(NULL);
375 for(int i=0; i<dft.voiNr; i++) {
376 fit.voi[i].type=MF_GAMMAVR; // 1403
377 fit.voi[i].parNr=6;
378 fit.voi[i].start=tstart; fit.voi[i].end=tstop;
379 fit.voi[i].dataNr=dft.frameNr;
380 }
381
382
383
384 /*
385 * Fit one TAC at a time
386 */
387 if(verbose>0) {printf("fitting\n"); fflush(stdout);}
388 for(int ri=0; ri<dft.voiNr; ri++) {
389 if(verbose>1) {printf("%d: %s\n", ri+1, dft.voi[ri].name); fflush(stdout);}
390 /* Set data pointers */
391 x=dft.x; ymeas=dft.voi[ri].y; yfit=dft.voi[ri].y2; w=dft.w;
392 dataNr=dft.frameNr;
393 /* Set the initial values for parameters */
394 fit.voi[ri].wss=3.402823e+38;
395
396 /* Get the peak value, time, and sample index */
397 double peakx, peaky;
398 int peaki;
399 ret=dftMinMaxTAC(&dft, ri, NULL, &peakx, NULL, &peaky, NULL, NULL, NULL, &peaki);
400 if(ret) {
401 fprintf(stderr, "Error: invalid TAC data for fitting.\n");
402 dftEmpty(&dft); fitEmpty(&fit); return(5);
403 }
404 if(verbose>4) printf(" peakx := %g\n peaky := %g\n", peakx, peaky);
405
406 /* If required, apply threshold to remove points after the peak */
407 if(threshold>0.0) {
408 /* 'Remove' samples starting from a post-peak value that is smaller than threshold */
409 double a=threshold*peaky;
410 int i=peaki+1;
411 for(; i<dft.frameNr; i++) if((ymeas[i])<a) {dataNr=i; break;}
412 if(dft.timetype==DFT_TIME_STARTEND) fit.voi[ri].end=dft.x2[dataNr-1];
413 else fit.voi[ri].end=dft.x[dataNr-1];
414 fit.voi[ri].dataNr=dataNr;
415 }
416
417
418 /* Set parameter constraints */
419 for(int pi=0; pi<6; pi++) {pmin[pi]=def_pmin[pi]; pmax[pi]=def_pmax[pi];}
420 /* If user did not specifically set limits, then refine the limits based on TAC */
421 if(!limfile[0]) {
422 if(verbose>3) printf(" refining limits\n");
423 /* delay */
424 pmin[0]=-0.05*fabs(peakx);
425 pmax[0]=0.95*fabs(peakx);
426 /* gaussian variate scale factor */
427 pmax[1]=10.0*peaky; if(pmin[1]>0.1*pmax[1]) pmin[1]=pmax[1]*1.0E-06;
428 /* recirculation scale factor */
429 if(parNr>4) {
430 pmax[4]=10.0*peaky; if(pmin[4]>0.1*pmax[4]) pmin[4]=pmax[4]*1.0E-06;
431 }
432 }
433 if(verbose>2) {
434 printf(" constraints\n");
435 for(int pi=0; pi<parNr; pi++) {
436 printf(" pmin[%d] := %g\n", pi, pmin[pi]);
437 printf(" pmax[%d] := %g\n", pi, pmax[pi]);
438 }
439 }
440
441
442
443 /* fit */
446 int neighNr=15;
447 int samNr=1000;
448 int tgoNr=3;
449 if(autoend==0) {
450 ret=tgo(pmin, pmax, func_gvar, NULL, parNr, neighNr, &fit.voi[ri].wss,
451 fit.voi[ri].p, samNr, tgoNr, verbose-8);
452 if(ret) {
453 fprintf(stderr, "Error: error %d in TGO.\n", ret);
454 dftEmpty(&dft); fitEmpty(&fit);
455 return(6);
456 }
457 } else {
458 double wsum=0.0;
459 int saveDataNr=dataNr;
460 /* Try to fit using different dataNr */
461 dataNr=peaki+2; // peak sample plus one
462 double lastRelWSS=3.402823e+38;
463 while(dataNr<=saveDataNr) {
464 ret=tgo(pmin, pmax, func_gvar, NULL, parNr, neighNr, &fit.voi[ri].wss,
465 fit.voi[ri].p, samNr, tgoNr, verbose-10);
466 if(ret) {
467 fprintf(stderr, "Error: error %d in TGO.\n", ret);
468 dftEmpty(&dft); fitEmpty(&fit); return(6);
469 }
470 /* Compare to previous fit */
471 wsum=doubleSum(w, (unsigned int)dataNr);
472 if((fit.voi[ri].wss/wsum)>lastRelWSS) { // worse, stop
473 /* Previous fit was better, but since it was not saved, fit it again */
474 dataNr--;
475 ret=tgo(pmin, pmax, func_gvar, NULL, parNr, neighNr, &fit.voi[ri].wss,
476 fit.voi[ri].p, samNr, tgoNr, verbose-10);
477 if(ret) {
478 fprintf(stderr, "Error: error %d in TGO.\n", ret);
479 dftEmpty(&dft); fitEmpty(&fit); return(6);
480 }
481 break;
482 }
483 lastRelWSS=fit.voi[ri].wss/wsum;
484 /* Try with one more sample */
485 dataNr++;
486 }
487
488 if(dft.timetype==DFT_TIME_STARTEND) fit.voi[ri].end=dft.x2[dataNr-1];
489 else fit.voi[ri].end=dft.x[dataNr-1];
490
491 }
492
493
494 /* Print measured and fitted curve */
495 if(verbose>5) {
496 printf("\n Frame Time Value Fitted Weight \n");
497 for(int i=0; i<dft.frameNr; i++)
498 printf(" %02d %8.3f %12.4f %12.4f %8.4f\n",
499 i+1, x[i], ymeas[i], yfit[i], w[i]);
500 }
501
502 /* Warn user about parameters that collide with limits */
503 ret=modelCheckLimits(parNr, pmin, pmax, fit.voi[ri].p);
504 if(ret!=0 && verbose>0)
505 fprintf(stderr, "Warning: fit collided with the limits.\n");
506
507 /* Force parameter values inside limits, as they are in the simulation */
508 double a;
509 modelCheckParameters(parNr, pmin, pmax, fit.voi[ri].p, fit.voi[ri].p, &a);
510 fit.voi[ri].wss/=a; // remove penalty from reported WSS
511
512 /* Set final sample nr into results, not counting samples with zero weight */
513 int n=0;
514 for(int i=0; i<dataNr; i++) if(w[i]>1.0E-10) n++;
515 fit.voi[ri].dataNr=n;
516
517 } /* next TAC */
518 if(verbose>0) fprintf(stdout, "\n");
519
520
521 /*
522 * Print fit results on screen
523 */
524 if(verbose>0 && fit.voiNr<=100) fitWrite(&fit, "stdout");
525
526
527 /*
528 * Save fit results, if file name was given by user
529 */
530 if(strcasecmp(parfile, "stdout")!=0) {
531 if(verbose>1) printf("saving results in %s\n", parfile);
532 if(fitWrite(&fit, parfile)) {
533 fprintf(stderr, "Error in writing '%s': %s\n", parfile, fiterrmsg);
534 dftEmpty(&dft); fitEmpty(&fit); return(11);
535 }
536 }
537
538
539 /*
540 * Plot fitted curves
541 */
542 if(svgfile[0]) {
543 if(verbose>1) printf("creating SVG plot\n");
544 DFT adft;
545 char tmp[FILENAME_MAX];
546 double a;
547
548 if(verbose>1)
549 printf("calculating fitted curve at automatically generated sample times\n");
550 dftInit(&adft);
551 ret=dftAutointerpolate(&dft, &adft, 1.05*tstop, verbose-10);
552 if(ret) {
553 fprintf(stderr, "Error: cannot allocate memory for fitted curves.\n");
554 dftEmpty(&dft); fitEmpty(&fit); dftEmpty(&adft);
555 return(13);
556 }
557 //for(fi=0; fi<adft.frameNr; fi++) adft.w[fi]=1.0;
558 for(int ri=0, ret=0; ri<adft.voiNr; ri++) {
559 for(int fi=0; fi<adft.frameNr; fi++) {
560 ret=fitEval(&fit.voi[ri], adft.x[fi], &a); if(ret!=0) break;
561 adft.voi[ri].y[fi]=a;
562 }
563 if(ret!=0) break;
564 }
565 if(ret!=0) {
566 fprintf(stderr, "Error: cannot calculate fitted TAC for '%s'.\n", svgfile);
567 dftEmpty(&dft); dftEmpty(&adft); fitEmpty(&fit);
568 return(14);
569 }
570
571 /* Save SVG plot of fitted and original data */
572 if(verbose>1) printf("writing %s\n", svgfile);
573 tpcProgramName(argv[0], 0, 0, tmp, 32);
574 if(strlen(adft.studynr)>1 && strlen(adft.studynr)<28) {
575 strlcat(tmp, " ", 64);
576 strlcat(tmp, adft.studynr, 64);
577 }
578 ret=plot_fitrange_svg(&dft, &adft, tmp, 0.0, nan(""), 0.0, nan(""),
579 svgfile, verbose-10);
580 if(ret) {
581 fprintf(stderr, "Error: cannot write '%s'.\n", svgfile);
582 dftEmpty(&adft); dftEmpty(&dft); fitEmpty(&fit);
583 return(30+ret);
584 }
585 if(verbose>0) printf("Plots written in %s\n", svgfile);
586
587 dftEmpty(&adft);
588 }
589
590 /*
591 * Save fitted TACs (original data is lost here, so do this in the end)
592 */
593 if(fitfile[0]) {
594 if(verbose>1) printf("saving fitted curves in %s\n", fitfile);
595 double a;
596 for(int ri=0, ret=0; ri<dft.voiNr; ri++) {
597 for(int fi=0; fi<dft.frameNr; fi++) {
598 ret=fitEval(&fit.voi[ri], dft.x[fi], &a); if(ret!=0) break;
599 dft.voi[ri].y[fi]=a;
600 }
601 if(ret!=0) break;
602 }
603 if(ret!=0) {
604 fprintf(stderr, "Error: cannot calculate fitted TACs for '%s'.\n", fitfile);
605 dftEmpty(&dft); fitEmpty(&fit);
606 return(21);
607 }
608 tpcProgramName(argv[0], 0, 0, progname, 32);
609 snprintf(dft.comments, 128, "# program := %s\n", progname);
610 dft.isweight=0;
611 if(dftWrite(&dft, fitfile)) {
612 fprintf(stderr, "Error in writing '%s': %s\n", fitfile, dfterrmsg);
613 dftEmpty(&dft); fitEmpty(&fit);
614 return(22);
615 }
616 if(verbose>0) printf("Fitted TACs written in %s\n", fitfile);
617 }
618
619
620 /* Free memory */
621 dftEmpty(&dft); fitEmpty(&fit);
622
623 return(0);
624}
625/*****************************************************************************/
626/* Functions to be minimized */
627/*****************************************************************************/
628double func_gvar(int parNr, double *p, void *fdata)
629{
630 int i;
631 double xt, et, v, wss;
632 double pa[MAX_PARAMETERS], penalty=1.0;
633
634 /* Check parameters against the constraints */
635 (void)modelCheckParameters(parNr, pmin, pmax, p, pa, &penalty);
636 if(fdata) {}
637 if(0) {
638 for(i=0; i<parNr; i++) printf(" p[%d]=%g", i, p[i]);
639 printf("\n");
640 }
641
642 /* Calculate the curve and WSS */
643 for(i=0, wss=0.0; i<dataNr; i++) {
644 xt=x[i]-pa[0];
645 yfit[i]=0.0;
646 if(xt>0.0) {
647 et=exp(-xt/pa[3]);
648 if(pa[1]>0.0) yfit[i]+=pa[1]*pow(xt, pa[2])*et;
649 if(parNr>5 && pa[4]>0.0) yfit[i]+=pa[4]*(1.0-et)*exp(-xt/pa[5]);
650 }
651 /* Calculate weighted SS */
652 v=yfit[i]-ymeas[i]; wss+=w[i]*v*v;
653 }
654 if(!isfinite(wss)) wss=nan("");
655 wss*=penalty;
656 if(0) printf(" wss=%g penalty=%g\n", wss, penalty);
657 return(wss);
658}
659/*****************************************************************************/
660
661/*****************************************************************************/
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 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
double doubleSum(double *a, const unsigned int n)
Definition doubleutil.c:130
int dftAutointerpolate(DFT *dft, DFT *dft2, double endtime, int verbose)
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.
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
char fiterrmsg[64]
Definition mathfunc.c:6
void fitInit(FIT *fit)
Definition mathfunc.c:38
#define DFT_TIME_STARTEND
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
size_t strlcat(char *dst, const char *src, size_t dstsize)
Definition strext.c:206
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
#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.
int timetype
Voi * voi
char studynr[MAX_STUDYNR_LEN+1]
double * w
char comments[_DFT_COMMENT_LEN+1]
int voiNr
double * x2
int frameNr
int isweight
double * x
char unit[MAX_UNITS_LEN+1]
int voiNr
char datafile[FILENAME_MAX]
char program[1024]
char unit[MAX_UNITS_LEN+1]
FitVOI * voi
time_t time
double wss
double end
double start
double p[MAX_FITPARAMS]
const char * status
Definition libtpcmisc.h:277
double * y2
double * y
char name[MAX_REGIONNAME_LEN+1]