TPCCLIB
Loading...
Searching...
No Matches
fit_blddr.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 <string.h>
13#include <math.h>
14/*****************************************************************************/
15#include "tpcextensions.h"
16#include "tpcift.h"
17#include "tpctac.h"
18#include "tpcpar.h"
19#include "tpctacmod.h"
20#include "tpcrand.h"
21#include "tpcnlopt.h"
22#include "tpcfileutil.h"
23/*****************************************************************************/
24
25/*****************************************************************************/
26/* Local functions */
27double func_ipop(int parNr, double *p, void*);
28double func_ifengm2(int parNr, double *p, void *);
29double func_ifengm2s(int parNr, double *p, void *);
30/*****************************************************************************/
31
32/*****************************************************************************/
33typedef struct FITDATA {
35 unsigned int n;
37 double *x;
39 double *ymeas;
41 double *ysim;
43 double *w;
45 int verbose;
46} FITDATA;
47const int maxParNr=7;
48/*****************************************************************************/
49
50/*****************************************************************************/
51static char *info[] = {
52 "Non-linear fitting of AIF integral function to bladder time-activity",
53 "curves (TACs). Bladder VOI must include all of the urine in the bladder when",
54 "it is largest in the last time frame.",
55 " ",
56 "Usage: @P [Options] tacfile [parfile]",
57 " ",
58 "Options:",
59 " -model=<M2S | M2 | LATEFDG>",
60 " Select the function; default is M2S.",
61 " M2S and M2 are the functions proposed by Feng et al (1993), including",
62 " two and three exponential terms, respectively.",
63 " LATEFDG is a simplified version, proposed by Phillips et al (1995),",
64 " which can only fit the late part of FDG input TAC, but is designed to",
65 " have two of its parameters fixed to population means.",
66 " -w1",
67 " All weights are set to 1.0 (no weighting); by default, weights in",
68 " data file are used, if available.",
69 " -wf",
70 " Weight by sampling interval.",
71 " -delay=<time>",
72 " Delay time (dT) is constrained to specified value (>=0); by default",
73 " delay time is fitted.",
74 " -start=<time>",
75 " Samples before specified time are set to zero for the fit.",
76 " -svg=<Filename>",
77 " Fitted and measured TACs are plotted in specified SVG file.",
78 " -m=<value>",
79 " Parameter m of LATEFDG function is constrained to given value.",
80 " -n=<value>",
81 " Parameter n of LATEFDG function is constrained to given value.",
82 " -stdoptions", // List standard options like --help, -v, etc
83 " ",
84 "See also: fit_sinf, fit_feng, fit2dat",
85 " ",
86 "Keywords: TAC, input, curve fitting",
87 0};
88/*****************************************************************************/
89
90/*****************************************************************************/
91/* Turn on the globbing of the command line, since it is disabled by default in
92 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
93 In Unix&Linux wildcard command line processing is enabled by default. */
94/*
95#undef _CRT_glob
96#define _CRT_glob -1
97*/
98int _dowildcard = -1;
99/*****************************************************************************/
100
101/*****************************************************************************/
105int main(int argc, char **argv)
106{
107 int ai, help=0, version=0, verbose=1;
108 char tacfile[FILENAME_MAX], parfile[FILENAME_MAX], svgfile[FILENAME_MAX];
109 int weights=0; // 0=default, 1=no weighting, 2=frequency
110 unsigned int model=0;
111 double fixed_delay=nan("");
112 double fixed_m=nan("");
113 double fixed_n=nan("");
114 double start_t=nan("");
115
116
117 /*
118 * Get arguments
119 */
120 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
121 tacfile[0]=parfile[0]=svgfile[0]=(char)0;
122 model=modelCodeIndex("feng2ms");
123 /* Options */
124 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') {
125 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
126 char *cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(!*cptr) continue;
127 if(strncasecmp(cptr, "MODEL=", 6)==0) {
128 cptr+=6;
129 if(strcasecmp(cptr, "M2")==0) {model=modelCodeIndex("fengm2"); continue;}
130 if(strcasecmp(cptr, "FENGM2")==0) {model=modelCodeIndex("fengm2"); continue;}
131 if(strcasecmp(cptr, "M2S")==0) {model=modelCodeIndex("fengm2s"); continue;}
132 if(strcasecmp(cptr, "FENG")==0) {model=modelCodeIndex("fengm2s"); continue;}
133 if(strcasecmp(cptr, "LATEFDG")==0) {model=modelCodeIndex("surgefdgaif"); continue;}
134 if(strcasecmp(cptr, "surgefdgaif")==0) {model=modelCodeIndex("surgefdgaif"); continue;}
135 fprintf(stderr, "Error: invalid model selection.\n"); return(1);
136 } else if(strcasecmp(cptr, "W1")==0) {
137 weights=1; continue;
138 } else if(strcasecmp(cptr, "WF")==0) {
139 weights=2; continue;
140 } else if(strncasecmp(cptr, "DELAY=", 6)==0 && strlen(cptr)>6) {
141 if(!atofCheck(cptr+6, &fixed_delay) && fixed_delay>=0.0) continue;
142 } else if(strncasecmp(cptr, "START=", 6)==0 && strlen(cptr)>6) {
143 if(!atofCheck(cptr+6, &start_t) && start_t>=0.0) continue;
144 } else if(strncasecmp(cptr, "DT=", 3)==0 && strlen(cptr)>3) {
145 if(!atofCheck(cptr+3, &fixed_delay) && fixed_delay>=0.0) continue;
146 } else if(strncasecmp(cptr, "M=", 2)==0 && strlen(cptr)>2) {
147 if(!atofCheck(cptr+2, &fixed_m) && fixed_m>0.0) continue;
148 } else if(strncasecmp(cptr, "N=", 2)==0 && strlen(cptr)>2) {
149 if(!atofCheck(cptr+2, &fixed_n) && fixed_n>0.0) continue;
150 } else if(strncasecmp(cptr, "SVG=", 4)==0 && strlen(cptr)>4) {
151 strlcpy(svgfile, cptr+4, FILENAME_MAX); continue;
152 }
153 fprintf(stderr, "Error: invalid option '%s'.\n", argv[ai]);
154 return(1);
155 } else break;
156
157 TPCSTATUS status; statusInit(&status);
158 statusSet(&status, __func__, __FILE__, __LINE__, TPCERROR_OK);
159 status.verbose=verbose-3;
160
161 /* Print help or version? */
162 if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
163 if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
164 if(version) {tpcPrintBuild(argv[0], stdout); return(0);}
165
166 /* Process other arguments, starting from the first non-option */
167 if(ai<argc) strlcpy(tacfile, argv[ai++], FILENAME_MAX);
168 if(ai<argc) strlcpy(parfile, argv[ai++], FILENAME_MAX);
169 if(ai<argc) {
170 fprintf(stderr, "Error: invalid argument '%s'.\n", argv[ai]);
171 return(1);
172 }
173
174 /* Did we get all the information that we need? */
175 if(!tacfile[0]) {
176 fprintf(stderr, "Error: missing command-line argument; use option --help\n");
177 return(1);
178 }
179
180 /* In verbose mode print arguments and options */
181 if(verbose>1) {
182 if(tacfile[0]) printf("tacfile := %s\n", tacfile);
183 if(parfile[0]) printf("parfile := %s\n", parfile);
184 if(svgfile[0]) printf("svgfile := %s\n", svgfile);
185 if(!isnan(fixed_m)) printf("fixed_m := %g\n", fixed_m);
186 if(!isnan(fixed_n)) printf("fixed_n := %g\n", fixed_n);
187 if(!isnan(fixed_delay)) printf("fixed_delay := %g\n", fixed_delay);
188 if(!isnan(start_t)) printf("start_t := %g\n", start_t);
189 printf("model := %s\n", modelCode(model));
190 printf("weights := %d\n", weights);
191 }
192
193 /* Set parameter names and initial constraints */
194 PAR plim; parInit(&plim); if(parAllocate(&plim, maxParNr, 1)!=TPCERROR_OK) {
195 fprintf(stderr, "Error: cannot initiate parameter list.\n"); return(1);}
196 if(model==modelCodeIndex("surgefdgaif")) {
197 plim.parNr=5;
198 strcpy(plim.n[0].name, "dT"); plim.n[0].lim1=0.0; plim.n[0].lim2=100.0;
199 strcpy(plim.n[1].name, "A"); plim.n[1].lim1=1.0E-08; plim.n[1].lim2=0.5;
200 strcpy(plim.n[2].name, "B"); plim.n[2].lim1=1.0E-06; plim.n[2].lim2=1.0E+06;
201 strcpy(plim.n[3].name, "M"); plim.n[3].lim1=1.0E-06; plim.n[3].lim2=1.0E+06;
202 strcpy(plim.n[4].name, "N"); plim.n[4].lim1=1.0E-08; plim.n[4].lim2=1.0E+01;
203 if(!isnan(fixed_delay)) plim.n[0].lim1=plim.n[0].lim2=fixed_delay;
204 if(!isnan(fixed_m)) plim.n[3].lim1=plim.n[3].lim2=fixed_m;
205 if(!isnan(fixed_n)) plim.n[4].lim1=plim.n[4].lim2=fixed_n;
206 } else if(model==modelCodeIndex("fengm2")) {
207 plim.parNr=7;
208 strcpy(plim.n[0].name, "dT"); plim.n[0].lim1=0.0; plim.n[0].lim2=100.0;
209 strcpy(plim.n[1].name, "A1"); plim.n[1].lim1=1.0E-06; plim.n[1].lim2=1.0E+06;
210 strcpy(plim.n[2].name, "L1"); plim.n[2].lim1=1.0E-02; plim.n[2].lim2=1.0E+00;
211 strcpy(plim.n[3].name, "A2"); plim.n[3].lim1=1.0E-06; plim.n[3].lim2=1.0E+06;
212 strcpy(plim.n[4].name, "L2"); plim.n[4].lim1=1.0E-03; plim.n[4].lim2=1.0E-01;
213 strcpy(plim.n[3].name, "A3"); plim.n[5].lim1=1.0E-06; plim.n[5].lim2=1.0E+06;
214 strcpy(plim.n[4].name, "L3"); plim.n[6].lim1=1.0E-08; plim.n[6].lim2=1.0E-02;
215 } else if(model==modelCodeIndex("fengm2s")) {
216 plim.parNr=5;
217 strcpy(plim.n[0].name, "dT"); plim.n[0].lim1=0.0; plim.n[0].lim2=100.0;
218 strcpy(plim.n[1].name, "A1"); plim.n[1].lim1=1.0E-06; plim.n[1].lim2=1.0E+06;
219 strcpy(plim.n[2].name, "L1"); plim.n[2].lim1=1.0E-02; plim.n[2].lim2=1.0E+00;
220 strcpy(plim.n[3].name, "A2"); plim.n[3].lim1=1.0E-06; plim.n[3].lim2=1.0E+06;
221 strcpy(plim.n[4].name, "L2"); plim.n[4].lim1=1.0E-06; plim.n[4].lim2=1.0E-01;
222 } else {
223 fprintf(stderr, "Error: invalid model.\n");
224 parFree(&plim); return(1);
225 }
226
227
228 /*
229 * Read TAC data
230 */
231 if(verbose>1) printf("reading %s\n", tacfile);
232 TAC tac; tacInit(&tac);
233 if(tacRead(&tac, tacfile, &status)!=TPCERROR_OK) {
234 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
235 tacFree(&tac); parFree(&plim); return(2);
236 }
237 if(verbose>1) {
238 printf("fileformat := %s\n", tacFormattxt(tac.format));
239 printf("tacNr := %d\n", tac.tacNr);
240 printf("sampleNr := %d\n", tac.sampleNr);
241 printf("xunit := %s\n", unitName(tac.tunit));
242 printf("yunit := %s\n", unitName(tac.cunit));
243 printf("isframe := %d\n", tac.isframe);
244 }
245 if(tac.tacNr<1) {
246 fprintf(stderr, "Error: file contains no data.\n");
247 tacFree(&tac); parFree(&plim); return(2);
248 }
249 /* Delete missing samples */
251 if(tac.sampleNr<3) {
252 fprintf(stderr, "Error: too few samples for fit.\n");
253 tacFree(&tac); parFree(&plim); return(2);
254 }
255 /* Sort data by sample time */
256 tacSortByTime(&tac, &status);
257 /* Get x range */
258 double xmin, xmax;
259 if(tacXRange(&tac, &xmin, &xmax)!=0) {
260 fprintf(stderr, "Error: invalid data sample times.\n");
261 tacFree(&tac); parFree(&plim); return(2);
262 }
263 if(verbose>1) {
264 printf("xmin := %g\n", xmin);
265 printf("xmax := %g\n", xmax);
266 }
267 /* Refine dT limits */
268 if(plim.n[0].lim2>plim.n[0].lim1 && plim.n[0].lim2>0.25*xmax) plim.n[0].lim2=0.25*xmax;
269
270 /* If start time was given, then set the earlier sample values to zero */
271 if(!isnan(start_t)) {
272 for(int i=0; i<tac.sampleNr; i++) if(tac.x[i]<start_t)
273 for(int j=0; j<tac.tacNr; j++) tac.c[j].y[i]=0.0;
274 }
275
276 /* Check and set weights */
277 if(weights==0) {
278 if(!tacIsWeighted(&tac)) {
280 for(int i=0; i<tac.sampleNr; i++) tac.w[i]=1.0;
281 }
282 } else if(weights==1) {
284 for(int i=0; i<tac.sampleNr; i++) tac.w[i]=1.0;
285 } else if(weights==2) {
286 if(tacWByFreq(&tac, ISOTOPE_UNKNOWN, &status)!=TPCERROR_OK) {
287 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
288 tacFree(&tac); parFree(&plim); return(2);
289 }
290 }
291
292
293 /*
294 * Copy function parameters into PAR structure for printing and saving
295 */
296 if(verbose>1) printf("preparing space for parameters\n");
297 PAR par; parInit(&par);
298 if(parAllocateWithTAC(&par, &tac, maxParNr, &status)!=TPCERROR_OK) {
299 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
300 tacFree(&tac); parFree(&plim); return(3);
301 }
302 par.tacNr=tac.tacNr; par.parNr=modelParNr(model);
304 for(int i=0; i<tac.tacNr; i++) {
305 par.r[i].model=model;
306 par.r[i].dataNr=tacWSampleNr(&tac);
307 par.r[i].start=xmin;
308 par.r[i].end=xmax;
309 }
310 /* Set parameter names */
311 for(int i=0; i<par.parNr; i++) strcpy(par.n[i].name, plim.n[i].name);
312 /* set time and program name */
313 {
314 char buf[256];
315 time_t t=time(NULL);
316 iftPut(&par.h, "analysis_time", ctime_r_int(&t, buf), 0, NULL);
317 tpcProgramName(argv[0], 1, 1, buf, 256);
318 iftPut(&par.h, "program", buf, 0, NULL);
319 }
320 /* set file names */
321 iftPut(&par.h, "datafile", tacfile, 0, NULL);
322
323
324 /*
325 * Fitting
326 */
327 if(verbose>1) printf("preparing for fitting\n");
328
329 drandSeed(1);
330
331 if(verbose>0) {printf("fitting...\n"); fflush(stdout);}
332 for(int ci=0; ci<tac.tacNr; ci++) {
333 if(verbose>1) printf("TAC %d: %s\n", 1+ci, tac.c[ci].name);
334 /* Get y range */
335 double ymax; int ymaxi;
336 if(tacYRange(&tac, ci, NULL, &ymax, NULL, &ymaxi, NULL, NULL)!=0) {
337 fprintf(stderr, "Error: invalid y (concentration) values.\n");
338 tacFree(&tac); parFree(&plim); parFree(&par); return(5);
339 }
340 if(verbose>3) printf(" ymax := %g\n", ymax);
341 if(model==modelCodeIndex("surgefdgaif")) {
342 /* Refine limits of b and m */
343 if(plim.n[2].lim2>plim.n[2].lim1) plim.n[2].lim2=2.0*ymax;
344 if(plim.n[3].lim2>plim.n[3].lim1) plim.n[3].lim2=2.0*ymax;
345 } else if(model==modelCodeIndex("fengm2")) {
346 /* Refine limits of a */
347 if(plim.n[1].lim2>plim.n[1].lim1) plim.n[1].lim2=ymax/2.2;
348 if(plim.n[3].lim2>plim.n[3].lim1) plim.n[3].lim2=0.2*ymax/2.2;
349 if(plim.n[5].lim2>plim.n[5].lim1) plim.n[5].lim2=0.2*ymax/2.2;
350 } else if(model==modelCodeIndex("fengm2s")) {
351 /* Refine limits of a */
352 if(plim.n[1].lim2>plim.n[1].lim1) plim.n[1].lim2=ymax/2.2;
353 if(plim.n[3].lim2>plim.n[3].lim1) plim.n[3].lim2=0.2*ymax/2.2;
354 }
355 /* Set data pointers for the fit */
356 double yfit[tac.sampleNr];
357 FITDATA fitdata;
358 fitdata.n=tac.sampleNr;
359 fitdata.x=tac.x;
360 fitdata.ymeas=tac.c[ci].y;
361 fitdata.ysim=yfit;
362 fitdata.w=tac.w;
363 if(verbose>10) fitdata.verbose=verbose-10; else fitdata.verbose=0;
364 /* Set NLLS options */
365 NLOPT nlo; nloptInit(&nlo);
366 if(nloptAllocate(&nlo, par.parNr)!=TPCERROR_OK) {
367 fprintf(stderr, "Error: cannot initiate NLLS.\n");
368 tacFree(&tac); parFree(&plim); parFree(&par); return(5);
369 }
370 if(model==modelCodeIndex("surgefdgaif")) nlo._fun=func_ipop;
371 else if(model==modelCodeIndex("fengm2")) nlo._fun=func_ifengm2;
372 else if(model==modelCodeIndex("fengm2s")) nlo._fun=func_ifengm2s;
373 nlo.fundata=&fitdata;
374 nlo.totalNr=par.parNr;
375 for(int i=0; i<par.parNr; i++) {
376 nlo.xlower[i]=plim.n[i].lim1;
377 nlo.xupper[i]=plim.n[i].lim2;
378 }
379 for(int i=0; i<par.parNr; i++) {
380 if(!(plim.n[i].lim2>plim.n[i].lim1)) nlo.xtol[i]=0.0;
381 else nlo.xtol[i]=0.0001*(plim.n[i].lim2-plim.n[i].lim1);
382 }
383 /* Initial guess */
384 if(model==modelCodeIndex("surgefdgaif")) {
385 nlo.xfull[0]=0.8*nlo.xlower[0]+0.2*nlo.xupper[0];
386 nlo.xfull[1]=0.7*nlo.xlower[1]+0.3*nlo.xupper[1];
387 nlo.xfull[2]=0.6*nlo.xlower[2]+0.4*nlo.xupper[2];
388 nlo.xfull[3]=0.6*nlo.xlower[3]+0.4*nlo.xupper[3];
389 nlo.xfull[4]=0.8*nlo.xlower[4]+0.2*nlo.xupper[4];
390 } else if(model==modelCodeIndex("fengm2")) {
391 nlo.xfull[0]=0.8*nlo.xlower[0]+0.2*nlo.xupper[0];
392 nlo.xfull[1]=0.5*ymax/6.6;
393 nlo.xfull[2]=0.5;
394 nlo.xfull[3]=0.5*ymax/6.6;
395 nlo.xfull[4]=0.05;
396 nlo.xfull[5]=0.02*ymax/6.6;
397 nlo.xfull[6]=0.005;
398 } else if(model==modelCodeIndex("fengm2s")) {
399 nlo.xfull[0]=0.8*nlo.xlower[0]+0.2*nlo.xupper[0];
400 nlo.xfull[1]=ymax/6.6;
401 nlo.xfull[2]=0.5;
402 nlo.xfull[3]=2.0*nlo.xfull[1]/15.0;
403 nlo.xfull[4]=0.05;
404 }
405 nlo.maxFunCalls=50000;
406 /* Fit */
407 if(verbose>4) nloptWrite(&nlo, stdout);
408 int orig_verbose=status.verbose; if(verbose>2) status.verbose=1; else status.verbose=0;
409#if(0)
410 if(nloptSimplexARRS(&nlo, 0, &status)!=TPCERROR_OK) {
411 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
412 tacFree(&tac); parFree(&plim); parFree(&par); nloptFree(&nlo); return(6);
413 }
414#else
415 if(nloptIATGO(&nlo, 1, 0, 0.25, &status)!=TPCERROR_OK) {
416 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
417 tacFree(&tac); parFree(&plim); parFree(&par); nloptFree(&nlo); return(6);
418 }
419#endif
420 status.verbose=orig_verbose;
421 nlo._fun(nlo.totalNr, nlo.xfull, nlo.fundata);
422 if(verbose>2) nloptWrite(&nlo, stdout);
423 if(verbose>3) {
424 printf("measured and fitted TAC:\n");
425 for(int i=0; i<tac.sampleNr; i++)
426 printf("\t%g\t%g\t%g\n", tac.x[i], tac.c[ci].y[i], yfit[i]);
427 }
428 //if(verbose>2) printf(" wss := %g\n", nlo.funval);
429
430 /* Copy parameters */
431 par.r[ci].wss=nlo.funval;
432 if(model==modelCodeIndex("surgefdgaif")) {
433 for(int i=0; i<par.parNr; i++) par.r[ci].p[i]=nlo.xfull[i];
434 } else if(model==modelCodeIndex("fengm2")) {
435 par.r[ci].p[0]=nlo.xfull[1];
436 par.r[ci].p[1]=-nlo.xfull[2];
437 par.r[ci].p[2]=nlo.xfull[3];
438 par.r[ci].p[3]=-nlo.xfull[4];
439 par.r[ci].p[4]=nlo.xfull[5];
440 par.r[ci].p[5]=-nlo.xfull[6];
441 par.r[ci].p[6]=nlo.xfull[0];
442 } else if(model==modelCodeIndex("fengm2s")) {
443 par.r[ci].p[0]=nlo.xfull[1];
444 par.r[ci].p[1]=-nlo.xfull[2];
445 par.r[ci].p[2]=nlo.xfull[3];
446 par.r[ci].p[3]=-nlo.xfull[4];
447 par.r[ci].p[4]=nlo.xfull[0];
448 }
449 nloptFree(&nlo);
450 } // next TAC
451
452 /* Print and save parameters */
453 if(verbose>0 || !parfile[0]) parWrite(&par, stdout, PAR_FORMAT_TSV_UK, 1, NULL);
454 if(parfile[0]) {
455 /* Save file */
456 if(verbose>1) printf(" saving %s\n", parfile);
457 FILE *fp=fopen(parfile, "w");
458 if(fp==NULL) {
459 fprintf(stderr, "Error: cannot open file for writing.\n");
460 tacFree(&tac); parFree(&plim); parFree(&par); return(11);
461 }
462 int ret=parWrite(&par, fp, PAR_FORMAT_FIT, 1, &status);
463 fclose(fp);
464 if(ret!=TPCERROR_OK) {
465 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
466 tacFree(&tac); parFree(&plim); parFree(&par); return(12);
467 }
468 if(verbose>0) printf("parameters saved in %s\n", parfile);
469 }
470
471
472
473 /*
474 * Plot measured and fitted data, if requested
475 */
476 if(svgfile[0]) {
477 if(verbose>1) {printf("plotting measured and fitted data\n"); fflush(stdout);}
478 /* Prepare place for function TAC */
479 double sdist;
480 tacGetSampleInterval(&tac, 1.0E-03, &sdist, NULL);
481 int snr=(int)simSamples(0.2*sdist, 0.0, par.r[0].end-par.r[0].start, 2, NULL);
482 TAC ftac; tacInit(&ftac);
483 if(verbose>3) {printf(" allocating memory for %d samples\n", snr); fflush(stdout);}
484 int ret=tacAllocate(&ftac, snr, tac.tacNr);
485 if(ret!=TPCERROR_OK) {
486 fprintf(stderr, "Error: %s\n", errorMsg(ret));
487 tacFree(&tac); parFree(&plim); parFree(&par); return(21);
488 }
489 ftac.tacNr=tac.tacNr; ftac.sampleNr=snr;
490 if(verbose>3) {printf(" copying TAC headers\n"); fflush(stdout);}
491 ret=tacCopyHdr(&tac, &ftac);
492 if(ret==TPCERROR_OK) for(int ci=0; ci<tac.tacNr && ret==0; ci++)
493 ret=tacCopyTacchdr(tac.c+ci, ftac.c+ci);
494 if(ret!=TPCERROR_OK) {
495 fprintf(stderr, "Error: %s\n", errorMsg(ret));
496 tacFree(&tac); parFree(&plim); parFree(&par); tacFree(&ftac);
497 return(22);
498 }
499 snr=(int)simSamples(0.2*sdist, 0.0, par.r[0].end-par.r[0].start, 2, ftac.x);
500 ftac.isframe=0;
501 for(int i=0; i<ftac.sampleNr; i++) ftac.x[i]+=par.r[0].start;
502 /* Compute function values at sample times; note that we are computing integral this time */
503 ret=0;
504 if(verbose>3) {printf(" computing function(s)\n"); fflush(stdout);}
505 for(int ci=0; ci<tac.tacNr && ret==0; ci++)
506 ret=mfEvalInt(modelCode(par.r[ci].model), par.parNr, par.r[ci].p,
507 ftac.sampleNr, ftac.x, ftac.c[ci].y, verbose-5);
508 if(ret!=TPCERROR_OK) {
509 fprintf(stderr, "Error: cannot calculate function values.\n");
510 tacFree(&tac); parFree(&plim); parFree(&par); tacFree(&ftac);
511 return(23);
512 }
513 if(verbose>10) tacWrite(&ftac, stdout, TAC_FORMAT_UNKNOWN, 1, NULL);
514 /* Plot */
515 if(verbose>3) {printf(" plotting function(s)\n"); fflush(stdout);}
516// ret=tacPlotFitSVG(&tac, &ftac, "", nan(""), nan(""), nan(""), nan(""), svgfile, NULL);
517 ret=tacPlotFitSVG(&tac, &ftac, "", nan(""), nan(""), nan(""), nan(""), svgfile, &status);
518 if(ret!=TPCERROR_OK) {
519 fprintf(stderr, "Error: %s\n", errorMsg(ret));
520 tacFree(&tac); parFree(&plim); parFree(&par); tacFree(&ftac);
521 return(24);
522 }
523 tacFree(&ftac);
524 if(verbose>0) printf("Measured and fitted data plotted in %s\n", svgfile);
525 }
526
527
528 tacFree(&tac);
529 parFree(&plim);
530 parFree(&par);
531 return(0);
532}
533/*****************************************************************************/
534
535/*****************************************************************************
536 *
537 * Functions to be minimized
538 *
539 *****************************************************************************/
540double func_ipop(int parNr, double *p, void *fdata)
541{
542 double v, wss=0.0;
543 FITDATA *d=(FITDATA*)fdata;
544 double a=p[1];
545 double b=p[2];
546 double m=p[3];
547 double n=p[4];
548
549 /* Calculate the curve values and weighted SS */
550 for(unsigned int i=0; i<d->n; i++) {
551 d->ysim[i]=0.0;
552 if(isnan(d->ymeas[i]) || isnan(d->x[i])) continue;
553 double x=d->x[i]-p[0];
554 if(x>0.0) {
555 d->ysim[i] = m*(1.0 - (n*a*x + 1.0)*exp(-n*a*x))/(n*n*a*a);
556 d->ysim[i] += (1.0 - exp(-a*x))/a;
557 d->ysim[i] *= b;
558 }
559 v=d->ysim[i]-d->ymeas[i];
560 wss+=d->w[i]*v*v;
561 }
562 if(d->verbose>0) {
563 for(unsigned int i=0; i<(unsigned int)parNr; i++) printf(" %g", p[i]);
564 printf(" -> %g\n", wss);
565 }
566 return(wss);
567}
568/*****************************************************************************/
569double func_ifengm2(int parNr, double *p, void *fdata)
570{
571 double v, wss=0.0;
572 FITDATA *d=(FITDATA*)fdata;
573 double A1=p[1];
574 double L1=p[2];
575 double A2=p[3];
576 double L2=p[4];
577 double A3=p[5];
578 double L3=p[6];
579
580 /* Calculate the curve values and weighted SS */
581 for(unsigned int i=0; i<d->n; i++) {
582 d->ysim[i]=0.0;
583 if(isnan(d->ymeas[i]) || isnan(d->x[i])) continue;
584 double x=d->x[i]-p[0];
585 if(x>0.0) {
586 v=0.0;
587 if(L1!=0.0) {
588 double a=exp(-L1*x);
589 v=(A1-L1*(A2+A3))*(1.0-a)/(L1*L1); if(isfinite(v)) d->ysim[i]+=v;
590 v=(A1/L1)*x*a; if(isfinite(v)) d->ysim[i]-=v;
591 }
592 if(L2!=0.0) v=(A2/L2)*(1.0-exp(-L2*x)); else v=A2*x;
593 if(isfinite(v)) d->ysim[i]+=v;
594 if(L3!=0.0) v=(A3/L3)*(1.0-exp(-L3*x)); else v=A3*x;
595 if(isfinite(v)) d->ysim[i]+=v;
596 }
597 v=d->ysim[i]-d->ymeas[i];
598 wss+=d->w[i]*v*v;
599 }
600 if(d->verbose>0) {
601 for(unsigned int i=0; i<(unsigned int)parNr; i++) printf(" %g", p[i]);
602 printf(" -> %g\n", wss);
603 }
604 return(wss);
605}
606/*****************************************************************************/
607double func_ifengm2s(int parNr, double *p, void *fdata)
608{
609 double v, wss=0.0;
610 FITDATA *d=(FITDATA*)fdata;
611 double A1=p[1];
612 double L1=p[2];
613 double A2=p[3];
614 double L2=p[4];
615
616 /* Calculate the curve values and weighted SS */
617 for(unsigned int i=0; i<d->n; i++) {
618 d->ysim[i]=0.0;
619 if(isnan(d->ymeas[i]) || isnan(d->x[i])) continue;
620 double x=d->x[i]-p[0];
621 if(x>0.0) {
622 v=0.0;
623 if(L1!=0.0) {
624 double a=exp(-L1*x);
625 v=(A1-L1*A2)*(1.0-a)/(L1*L1); if(isfinite(v)) d->ysim[i]+=v;
626 v=(A1/L1)*x*a; if(isfinite(v)) d->ysim[i]-=v;
627 }
628 if(L2!=0.0) v=(A2/L2)*(1.0-exp(-L2*x)); else v=A2*x;
629 if(isfinite(v)) d->ysim[i]+=v;
630 }
631 v=d->ysim[i]-d->ymeas[i];
632 wss+=d->w[i]*v*v;
633 }
634 if(d->verbose>0) {
635 for(unsigned int i=0; i<(unsigned int)parNr; i++) printf(" %g", p[i]);
636 printf(" -> %g\n", wss);
637 }
638 return(wss);
639}
640/*****************************************************************************/
641
642/*****************************************************************************/
char * ctime_r_int(const time_t *t, char *buf)
Convert calendar time t into a null-terminated string of the form YYYY-MM-DD hh:mm:ss,...
Definition datetime.c:119
int atofCheck(const char *s, double *v)
Definition decpoint.c:94
int mfEvalInt(const char *fid, const int parNr, const double *p, const int sampleNr, const double *x, double *v, const int verbose)
Definition func.c:436
unsigned int drandSeed(short int seed)
Make and optionally set the seed for rand(), drand, drandRange, and drandGaussian().
Definition gaussdev.c:27
int iftPut(IFT *ift, const char *key, const char *value, char comment, TPCSTATUS *status)
Definition ift.c:63
unsigned int simSamples(double initStep, double maxStep, double endTime, int mode, double *x)
Definition interpolate.c:50
char * modelCode(const unsigned int i)
Definition modell.c:176
unsigned int modelParNr(const unsigned int code)
Definition modell.c:256
unsigned int modelCodeIndex(const char *s)
Definition modell.c:237
void nloptInit(NLOPT *nlo)
Definition nlopt.c:25
int nloptAllocate(NLOPT *nlo, unsigned int parNr)
Definition nlopt.c:74
void nloptFree(NLOPT *nlo)
Definition nlopt.c:52
void nloptWrite(NLOPT *d, FILE *fp)
Definition nlopt.c:302
void parFree(PAR *par)
Definition par.c:75
int parAllocate(PAR *par, int parNr, int tacNr)
Definition par.c:108
void parInit(PAR *par)
Definition par.c:25
int parWrite(PAR *par, FILE *fp, parformat format, int extra, TPCSTATUS *status)
Definition pario.c:148
int parAllocateWithTAC(PAR *par, TAC *tac, int parNr, TPCSTATUS *status)
Allocate PAR based on data in TAC.
Definition partac.c:90
int tpcProcessStdOptions(const char *s, int *print_usage, int *print_version, int *verbose_level)
Definition proginfo.c:47
void tpcProgramName(const char *program, int version, int copyright, char *prname, int n)
Definition proginfo.c:406
int tpcHtmlUsage(const char *program, char *text[], const char *path)
Definition proginfo.c:169
void tpcPrintBuild(const char *program, FILE *fp)
Definition proginfo.c:339
void tpcPrintUsage(const char *program, char *text[], FILE *fp)
Definition proginfo.c:114
int nloptSimplexARRS(NLOPT *nlo, unsigned int maxIter, TPCSTATUS *status)
Definition simplex.c:373
void statusInit(TPCSTATUS *s)
Definition statusmsg.c:104
char * errorMsg(tpcerror e)
Definition statusmsg.c:68
void statusSet(TPCSTATUS *s, const char *func, const char *srcfile, int srcline, tpcerror error)
Definition statusmsg.c:142
size_t strlcpy(char *dst, const char *src, size_t dstsize)
Definition stringext.c:632
double(* _fun)(int, double *, void *)
Definition tpcnlopt.h:42
double funval
Definition tpcnlopt.h:50
unsigned int maxFunCalls
Definition tpcnlopt.h:46
double * xupper
Definition tpcnlopt.h:33
double * xlower
Definition tpcnlopt.h:31
void * fundata
Definition tpcnlopt.h:44
double * xfull
Definition tpcnlopt.h:29
double * xtol
Definition tpcnlopt.h:39
unsigned int totalNr
Definition tpcnlopt.h:27
Definition tpcpar.h:100
int format
Definition tpcpar.h:102
IFT h
Optional (but often useful) header information.
Definition tpcpar.h:147
int parNr
Definition tpcpar.h:108
int tacNr
Definition tpcpar.h:104
PARR * r
Definition tpcpar.h:114
PARN * n
Definition tpcpar.h:112
double lim2
Definition tpcpar.h:90
char name[MAX_PARNAME_LEN+1]
Definition tpcpar.h:82
double lim1
Definition tpcpar.h:88
double wss
Definition tpcpar.h:72
int dataNr
Definition tpcpar.h:62
unsigned int model
Definition tpcpar.h:48
double * p
Definition tpcpar.h:64
double start
Definition tpcpar.h:52
double end
Definition tpcpar.h:54
char name[MAX_TACNAME_LEN+1]
Definition tpctac.h:81
double * y
Definition tpctac.h:75
Definition tpctac.h:87
double * x
Definition tpctac.h:97
unit cunit
Definition tpctac.h:105
tacformat format
Definition tpctac.h:93
int sampleNr
Definition tpctac.h:89
double * w
Definition tpctac.h:111
int isframe
Definition tpctac.h:95
TACC * c
Definition tpctac.h:117
weights weighting
Definition tpctac.h:115
unit tunit
Definition tpctac.h:109
int tacNr
Definition tpctac.h:91
int verbose
Verbose level, used by statusPrint() etc.
tpcerror error
Error code.
void tacFree(TAC *tac)
Definition tac.c:106
int tacAllocate(TAC *tac, int sampleNr, int tacNr)
Definition tac.c:130
void tacInit(TAC *tac)
Definition tac.c:24
int tacCopyTacchdr(TACC *d1, TACC *d2)
Definition tac.c:282
int tacCopyHdr(TAC *tac1, TAC *tac2)
Copy TAC header data from tac1 to tac2.
Definition tac.c:310
int tacPlotFitSVG(TAC *tac1, TAC *tac2, const char *main_title, const double x1, const double x2, const double y1, const double y2, const char *fname, TPCSTATUS *status)
Definition tacfitplot.c:27
int tacRead(TAC *d, const char *fname, TPCSTATUS *status)
Definition tacio.c:413
char * tacFormattxt(tacformat c)
Definition tacio.c:98
int tacWrite(TAC *tac, FILE *fp, tacformat format, int extra, TPCSTATUS *status)
Definition tacio.c:332
int tacSortByTime(TAC *d, TPCSTATUS *status)
Definition tacorder.c:74
int tacIsWeighted(TAC *tac)
Definition tacw.c:24
unsigned int tacWSampleNr(TAC *tac)
Definition tacw.c:219
int tacWByFreq(TAC *tac, isotope isot, TPCSTATUS *status)
Definition tacw.c:134
int tacDeleteMissingSamples(TAC *d)
Delete those samples (time frames) from TAC structure, which contain only missing y values,...
Definition tacx.c:450
int tacGetSampleInterval(TAC *d, double ilimit, double *minfdur, double *maxfdur)
Get the shortest and longest sampling intervals or frame lengths in TAC structure.
Definition tacx.c:832
int tacXRange(TAC *d, double *xmin, double *xmax)
Get the range of x values (times) in TAC structure.
Definition tacx.c:124
int tacYRange(TAC *d, int i, double *ymin, double *ymax, int *smin, int *smax, int *imin, int *imax)
Get the range of y values (concentrations) in TAC struct.
Definition tacy.c:26
int nloptIATGO(NLOPT *nlo, const int doLocal, unsigned int maxIterNr, double neighFract, TPCSTATUS *status)
Definition tgo.c:681
Header file for library libtpcextensions.
weights
Is data weighted, or are weight factors available with data?
@ WEIGHTING_OFF
Not weighted or weights not available (weights for all included samples are 1.0).
@ TPCERROR_OK
No error.
char * unitName(int unit_code)
Definition units.c:143
Header file for libtpcfileutil.
Header file for library libtpcift.
@ ISOTOPE_UNKNOWN
Unknown.
Definition tpcisotope.h:51
Header file for library libtpcnlopt.
Header file for libtpcpar.
@ PAR_FORMAT_FIT
Function fit format of Turku PET Centre.
Definition tpcpar.h:30
@ PAR_FORMAT_TSV_UK
UK TSV (point as decimal separator).
Definition tpcpar.h:35
Header file for libtpcrand.
Header file for library libtpctac.
@ TAC_FORMAT_UNKNOWN
Unknown format.
Definition tpctac.h:28
Header file for libtpctacmod.