TPCCLIB
Loading...
Searching...
No Matches
fit_pbr.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 "tpcfileutil.h"
17#include "tpcift.h"
18#include "tpctac.h"
19#include "tpcpar.h"
20#include "tpcli.h"
21#include "tpccm.h"
22#include "tpctacmod.h"
23#include "tpclinopt.h"
24#include "tpcrand.h"
25#include "tpcmodels.h"
26#include "tpcnlopt.h"
27/*****************************************************************************/
28
29/*****************************************************************************/
30/* Local functions */
31double func_pbr_src(int parNr, double *p, void*);
32double func_pbr_fm2(int parNr, double *p, void*);
33double func_pbr_rf(int parNr, double *p, void*);
34double func_pbr_hill(int parNr, double *p, void*);
35/*****************************************************************************/
36typedef struct FITDATA {
38 unsigned int n;
40 double *x;
42 double *ymeas;
44 double *ysim;
46 double *w;
50 int verbose;
51} FITDATA;
52/*****************************************************************************/
53
54/*****************************************************************************/
55static char *info[] = {
56 "Non-linear fitting of a function to sampled plasma-to-blood ratio (PBR) data.",
57 " ",
58 "Plasma-to-blood ratio is calculated from RBC-to-plasma ratio (RPC) as",
59 " PBR(t)=1/((1-HCT)+HCT*RPC(t))",
60 "and RBC-to-plasma ratio is modelled with function 1 (SRC)",
61 " RPC(t)=p1*t*exp(-p2*t) + p3*p1*(1-exp(-p2*t)*(1+p2*t))/(p2*p2)",
62 "function 2 (FM2)",
63 " RPC(t)=(p1*t-p3-p5)*exp(-p2*t) + p3*exp(-p4*t) + p5*exp(-p6*t)",
64 "function 3 (RF)",
65 " RPC(t)=(p1*t + p3*t^2 + p5*t^3) / (1 + p2*t + p4*t^2 + p6*t^3)",
66 "or function 4 (HILL)",
67 " RPC(t)=(p1*t^p2)/(t^p2 + p3)",
68 " ",
69 "Usage: @P [Options] datafile [parfile]",
70 " ",
71 "Options:",
72 " -HCT=<Haematocrit>",
73 " Constrain haematocrit to specified value; fitted by default.",
74 " -model=<SRC|FM2|RF|HILL>",
75 " Use function 1 (SCR, default), function 2 (FM2), function 3 (RF), or",
76 " function 4 (HILL).",
77 " -min=<OLS|LAD>",
78 " Sum-of-squares (OLS) is minimized by default, but optionally",
79 " sum of absolute deviations (LAD) can be selected.",
80 " -w1",
81 " All weights are set to 1.0 (no weighting); by default, weights in",
82 " data file are used, if available.",
83 " -wf",
84 " Weight by sampling interval.",
85 " -k=<value>",
86 " Parameter k is constrained to given value.",
87 " -lim[=<filename>]",
88 " Specify the constraints for function parameters;",
89 " This file with default values can be created by giving this option",
90 " as the only command-line argument to this program.",
91 " Without file name the default values are printed on screen.",
92 " -svg=<Filename>",
93 " Fitted and measured TACs are plotted in specified SVG file.",
94 " -stdoptions", // List standard options like --help, -v, etc
95 " ",
96 "Datafile must contain at least 2 columns, sample times and ratios,",
97 "possibly also weights as last column.",
98 " ",
99 "Example:",
100 " @P -svg=ia765pbrat.svg ia765pb.rat ia765pbrat.fit",
101 " ",
102 "See also: fit_bpr, tacinv, tacblend, b2rbc, bpr2cpr, fit_sigm, fit_hiad",
103 " ",
104 "Keywords: curve fitting, input, blood, plasma, modelling, simulation",
105 0};
106/*****************************************************************************/
107
108/*****************************************************************************/
109/* Turn on the globbing of the command line, since it is disabled by default in
110 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
111 In Unix&Linux wildcard command line processing is enabled by default. */
112/*
113#undef _CRT_glob
114#define _CRT_glob -1
115*/
116int _dowildcard = -1;
117/*****************************************************************************/
118
119/*****************************************************************************/
122/*****************************************************************************/
123
124/*****************************************************************************/
128int main(int argc, char **argv)
129{
130 int ai, help=0, version=0, verbose=1;
131 char pbrfile[FILENAME_MAX], parfile[FILENAME_MAX];
132 char limfile[FILENAME_MAX], svgfile[FILENAME_MAX];
133 int weights=0; // 0=default, 1=no weighting, 2=frequency
134 double fixed_hct=nan("");
135 double fixed_k=nan("");
137 unsigned int model=modelCodeIndex("p2bsrc");
138
139
140
141
142 /*
143 * Get arguments
144 */
145 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
146 pbrfile[0]=parfile[0]=svgfile[0]=limfile[0]=(char)0;
147 /* Options */
148 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') {
149 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
150 char *cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(!*cptr) continue;
151 if(strcasecmp(cptr, "W1")==0) {
152 weights=1; continue;
153 } else if(strcasecmp(cptr, "WF")==0) {
154 weights=2; continue;
155 } else if(strncasecmp(cptr, "MIN=", 4)==0 && strlen(cptr)>4) {
156 optcrit=optcritId(cptr+4); if(optcrit!=OPTCRIT_UNKNOWN) continue;
157 } else if(strncasecmp(cptr, "LIM=", 4)==0 && strlen(cptr)>4) {
158 strlcpy(limfile, cptr+4, FILENAME_MAX); continue;
159 } else if(strncasecmp(cptr, "SVG=", 4)==0 && strlen(cptr)>4) {
160 strlcpy(svgfile, cptr+4, FILENAME_MAX); continue;
161 } else if(strncasecmp(cptr, "K=", 2)==0 && strlen(cptr)>2) {
162 if(!atofCheck(cptr+2, &fixed_k) && fixed_k>=0.0) continue;
163 } else if(strncasecmp(cptr, "MODEL=", 6)==0 && strlen(cptr)>6) {
164 cptr+=6;
165 if(strcasecmp(cptr, "SRC")==0) {model=modelCodeIndex("p2bsrc"); continue;}
166 if(strcasecmp(cptr, "FM2")==0) {model=modelCodeIndex("p2bfm2"); continue;}
167 if(strcasecmp(cptr, "RF")==0) {model=modelCodeIndex("p2brf"); continue;}
168 if(strcasecmp(cptr, "HILL")==0) {model=modelCodeIndex("p2bhill"); continue;}
169 if(strcasecmp(cptr, "1")==0) {model=modelCodeIndex("p2bsrc"); continue;}
170 if(strcasecmp(cptr, "2")==0) {model=modelCodeIndex("p2bfm2"); continue;}
171 if(strcasecmp(cptr, "3")==0) {model=modelCodeIndex("p2brf"); continue;}
172 if(strcasecmp(cptr, "4")==0) {model=modelCodeIndex("p2bhill"); continue;}
173 } else if(strncasecmp(cptr, "HCT=", 4)==0 && strlen(cptr)>4) {
174 if(!atofCheck(cptr+4, &fixed_hct) && fixed_hct>0.0 && fixed_hct<1.0) continue;
175 }
176 fprintf(stderr, "Error: invalid option '%s'.\n", argv[ai]);
177 return(1);
178 } else break;
179
180 TPCSTATUS status; statusInit(&status);
181 statusSet(&status, __func__, __FILE__, __LINE__, TPCERROR_OK);
182 status.verbose=verbose-3;
183
184 /* Print help or version? */
185 if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
186 if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
187 if(version) {tpcPrintBuild(argv[0], stdout); return(0);}
188
189 /* Process other arguments, starting from the first non-option */
190 if(ai<argc) strlcpy(pbrfile, argv[ai++], FILENAME_MAX);
191 if(ai<argc) strlcpy(parfile, argv[ai++], FILENAME_MAX);
192 if(ai<argc) {fprintf(stderr, "Error: invalid argument '%s'.\n", argv[ai]); return(1);}
193
194 /* In verbose mode print arguments and options */
195 if(verbose>1) {
196 printf("pbrfile := %s\n", pbrfile);
197 if(parfile[0]) printf("parfile := %s\n", parfile);
198 if(limfile[0]) printf("limfile := %s\n", limfile);
199 if(svgfile[0]) printf("svgfile := %s\n", svgfile);
200 printf("weights := %d\n", weights);
201 if(!isnan(fixed_k)) printf("fixed_k := %g\n", fixed_k);
202 if(!isnan(fixed_hct)) printf("fixed_hct := %g\n", fixed_hct);
203 printf("optcrit := %s\n", optcritCode(optcrit));
204 printf("model := %s\n", modelDesc(model));
205 fflush(stdout);
206 }
207
208 /* Set parameter names and initial constraints */
209 PAR plim; parInit(&plim); if(parAllocate(&plim, modelParNr(model), 1)!=TPCERROR_OK) {
210 fprintf(stderr, "Error: cannot initiate parameter list.\n"); return(1);}
211 plim.parNr=modelParNr(model);
212 strcpy(plim.n[0].name, "HCT"); plim.n[0].lim1=0.36; plim.n[0].lim2=0.50;
213 if(model==modelCodeIndex("p2bsrc")) {
214 strcpy(plim.n[1].name, "A"); plim.n[1].lim1=1.0E-06; plim.n[1].lim2=1.0E+02;
215 strcpy(plim.n[2].name, "L"); plim.n[2].lim1=1.0E-06; plim.n[2].lim2=5.0;
216 strcpy(plim.n[3].name, "k"); plim.n[3].lim1=0.0; plim.n[3].lim2=2.0;
217 } else if(model==modelCodeIndex("p2brf")) {
218 strcpy(plim.n[1].name, "p1"); plim.n[1].lim1=0.0; plim.n[1].lim2=2.0;
219 strcpy(plim.n[2].name, "p2"); plim.n[2].lim1=0.0; plim.n[2].lim2=0.5;
220 strcpy(plim.n[3].name, "p3"); plim.n[3].lim1=0.0; plim.n[3].lim2=0.5;
221 strcpy(plim.n[4].name, "p4"); plim.n[4].lim1=0.0; plim.n[4].lim2=1.0;
222 strcpy(plim.n[5].name, "p5"); plim.n[5].lim1=0.0; plim.n[5].lim2=0.1;
223 strcpy(plim.n[6].name, "p6"); plim.n[6].lim1=0.0; plim.n[6].lim2=0.0;
224 } else if(model==modelCodeIndex("p2bfm2")) {
225 strcpy(plim.n[1].name, "A1"); plim.n[1].lim1=0.0; plim.n[1].lim2=10.0;
226 strcpy(plim.n[2].name, "L1"); plim.n[2].lim1=0.0; plim.n[2].lim2=5.0;
227 strcpy(plim.n[3].name, "A2"); plim.n[3].lim1=0.0; plim.n[3].lim2=10.0;
228 strcpy(plim.n[4].name, "L2"); plim.n[4].lim1=0.0; plim.n[4].lim2=0.5;
229 strcpy(plim.n[5].name, "A3"); plim.n[5].lim1=0.0; plim.n[5].lim2=5.0;
230 strcpy(plim.n[6].name, "L3"); plim.n[6].lim1=-0.1; plim.n[6].lim2=0.01;
231 } else { // if(model==modelCodeIndex("p2bhill"))
232 strcpy(plim.n[1].name, "p1"); plim.n[1].lim1=0.0; plim.n[1].lim2=20.0;
233 strcpy(plim.n[2].name, "p2"); plim.n[2].lim1=0.0; plim.n[2].lim2=5.0;
234 strcpy(plim.n[3].name, "p3"); plim.n[3].lim1=0.001; plim.n[3].lim2=5000.0;
235 }
236 /* If only file name for parameter constraints was given, then write one and exit */
237 if(limfile[0] && !pbrfile[0]) {
238 /* Check that initial value file does not exist */
239 if(strcasecmp(limfile, "stdout")!=0 && fileExist(limfile)) {
240 fprintf(stderr, "Error: parameter constraint file %s exists.\n", limfile);
241 parFree(&plim); return(1);
242 }
243 /* Create parameter file */
244 plim.parNr=modelParNr(model);
245 if(verbose>1 && strcasecmp(limfile, "stdout")!=0)
246 printf("writing parameter constraints file\n");
247 if(parWriteLimits(&plim, limfile, verbose-2)!=TPCERROR_OK) {
248 fprintf(stderr, "Error: cannot write constraints file.\n");
249 parFree(&plim); return(1);
250 }
251 if(strcasecmp(limfile, "stdout")!=0)
252 fprintf(stdout, "Parameter constraints written in %s\n", limfile);
253 parFree(&plim); return(0);
254 }
255
256 /* Did we get all the information that we need? */
257 if(!pbrfile[0]) { // note that parameter file is optional
258 fprintf(stderr, "Error: missing command-line argument; use option --help\n");
259 parFree(&plim); return(1);
260 }
261 if(optcrit!=OPTCRIT_OLS && optcrit!=OPTCRIT_LAD) {
262 fprintf(stderr, "Error: optimality criterion not supported.\n");
263 parFree(&plim); return(1);
264 }
265 if(strcasecmp(limfile, "stdout")==0) limfile[0]=(char)0;
266
267
268 /*
269 * Read parameter constraints if file for that was given
270 */
271 if(limfile[0]) {
272 if(parReadLimits(&plim, limfile, verbose-2)!=TPCERROR_OK) {
273 fprintf(stderr, "Error: cannot read constraints file.\n");
274 parFree(&plim); return(1);
275 }
276 if(verbose>1) parListLimits(&plim, stdout);
277 }
278 /* Set optional user-defined constraints */
279 if(!isnan(fixed_hct)) plim.n[0].lim1=plim.n[0].lim2=fixed_hct;
280 if(!isnan(fixed_k) && model==modelCodeIndex("p2bsrc")) plim.n[3].lim1=plim.n[3].lim2=fixed_k;
281 if(verbose>1) parListLimits(&plim, stdout);
282
283
284
285 /*
286 * Read TAC data
287 */
288 if(verbose>1) printf("reading %s\n", pbrfile);
289 TAC tac; tacInit(&tac);
290 if(tacRead(&tac, pbrfile, &status)!=TPCERROR_OK) {
291 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
292 tacFree(&tac); parFree(&plim); return(2);
293 }
294 if(verbose>1) {
295 printf("fileformat := %s\n", tacFormattxt(tac.format));
296 printf("tacNr := %d\n", tac.tacNr);
297 printf("sampleNr := %d\n", tac.sampleNr);
298 printf("xunit := %s\n", unitName(tac.tunit));
299 printf("yunit := %s\n", unitName(tac.cunit));
300 printf("isframe := %d\n", tac.isframe);
301 }
302 if(tac.tacNr<1) {
303 fprintf(stderr, "Error: file contains no data.\n");
304 tacFree(&tac); parFree(&plim); return(2);
305 } else if(tac.tacNr>1) {
306 if(verbose>0) fprintf(stderr, "Warning: file contains more than one curve.\n");
307 tac.tacNr=1;
308 }
309 if(tac.sampleNr<3) {
310 fprintf(stderr, "Error: too few samples.\n");
311 tacFree(&tac); parFree(&plim); return(2);
312 }
313 /* Check NaNs */
314 if(tacNaNs(&tac)>0) {
315 fprintf(stderr, "Error: data contains missing values.\n");
316 tacFree(&tac); parFree(&plim); return(2);
317 }
318 /* Sort data by sample time */
319 tacSortByTime(&tac, &status);
320 /* Get x range */
321 double xmin, xmax;
322 if(tacXRange(&tac, &xmin, &xmax)!=0) {
323 fprintf(stderr, "Error: invalid data sample times.\n");
324 tacFree(&tac); parFree(&plim); return(2);
325 }
326 if(verbose>1) {
327 printf("xmin := %g\n", xmin);
328 printf("xmax := %g\n", xmax);
329 }
330
331 /* Check and set weights */
332 if(weights==0) {
333 if(!tacIsWeighted(&tac)) {
335 for(int i=0; i<tac.sampleNr; i++) tac.w[i]=1.0;
336 }
337 } else if(weights==1) {
339 for(int i=0; i<tac.sampleNr; i++) tac.w[i]=1.0;
340 } else if(weights==2) {
341 if(tacWByFreq(&tac, ISOTOPE_UNKNOWN, &status)!=TPCERROR_OK) {
342 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
343 tacFree(&tac); parFree(&plim); return(2);
344 }
345 }
346
347
348 /*
349 * Copy function parameters into PAR structure for printing and saving
350 */
351 if(verbose>1) printf("preparing space for parameters\n");
352 PAR par; parInit(&par);
353 if(parAllocateWithTAC(&par, &tac, modelParNr(model), &status)!=TPCERROR_OK) {
354 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
355 tacFree(&tac); parFree(&plim); return(3);
356 }
357 iftFree(&par.h); // remove stupid header info
358 /* set time and program name */
359 {
360 char buf[256];
361 tpcProgramName(argv[0], 1, 1, buf, 256);
362 iftPut(&par.h, "program", buf, 0, NULL);
363 time_t t=time(NULL);
364 iftPut(&par.h, "analysis_time", ctime_r_int(&t, buf), 0, NULL);
365 }
366 par.tacNr=tac.tacNr; par.parNr=modelParNr(model);
368 for(int i=0; i<par.tacNr; i++) {
369 par.r[i].model=model;
370 par.r[i].dataNr=tacWSampleNr(&tac);
371 par.r[i].start=xmin;
372 par.r[i].end=xmax;
373 }
374 /* Set parameter names */
375 for(int i=0; i<par.parNr; i++) strcpy(par.n[i].name, plim.n[i].name);
376 /* set file names */
377 iftPut(&par.h, "datafile", pbrfile, 0, NULL);
378 /* copy study number */
379 {
380 int i=iftFindKey(&tac.h, "studynr", 0);
381 if(i<0) i=iftFindKey(&tac.h, "study_number", 0);
382 if(i>=0) iftPut(&par.h, tac.h.item[i].key, tac.h.item[i].value, 0, NULL);
383 }
384 /* set optimality criterion */
385 iftPut(&par.h, "optimality_criterion", optcritCode(optcrit), 0, NULL);
386
387
388 /*
389 * Fitting
390 */
391 if(verbose>1) printf("preparing for fitting\n");
392
393 drandSeed(1);
394
395 {
396 /* Set data pointers for the fit */
397 double yfit[tac.sampleNr];
398 FITDATA fitdata;
399 fitdata.n=tac.sampleNr;
400 fitdata.x=tac.x;
401 fitdata.ymeas=tac.c[0].y;
402 fitdata.ysim=yfit;
403 fitdata.w=tac.w;
404 fitdata.optcrit=optcrit;
405 if(verbose>10) fitdata.verbose=verbose-10; else fitdata.verbose=0;
406 /* Set NLLS options */
407 NLOPT nlo; nloptInit(&nlo);
408 if(nloptAllocate(&nlo, par.parNr)!=TPCERROR_OK) {
409 fprintf(stderr, "Error: cannot allocate memory.\n");
410 tacFree(&tac); parFree(&plim); parFree(&par); return(5);
411 }
412 if(model==modelCodeIndex("p2bsrc")) nlo._fun=func_pbr_src;
413 else if(model==modelCodeIndex("p2brf")) nlo._fun=func_pbr_rf;
414 else if(model==modelCodeIndex("p2bhill")) nlo._fun=func_pbr_hill;
415 else if(model==modelCodeIndex("p2bfm2")) nlo._fun=func_pbr_fm2;
416 nlo.fundata=&fitdata;
417 nlo.totalNr=par.parNr;
418 for(int i=0; i<par.parNr; i++) {
419 nlo.xlower[i]=plim.n[i].lim1;
420 nlo.xupper[i]=plim.n[i].lim2;
421 }
422 for(int i=0; i<par.parNr; i++) {
423 if(!(nlo.xupper[i]>nlo.xlower[i])) nlo.xtol[i]=0.0;
424 else nlo.xtol[i]=0.00001*(nlo.xupper[i]-nlo.xlower[i]);
425 }
426 nlo.maxFunCalls=500000;
427 /* Fit */
428 if(verbose>4) nloptWrite(&nlo, stdout);
429#if(0)
430 if(nloptITGO1(&nlo, 1, 0, 10000, 20, &status)!=TPCERROR_OK) {
431 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
432 tacFree(&tac); parFree(&plim); parFree(&par); nloptFree(&nlo); return(6);
433 }
434#else
435 if(nloptIATGO(&nlo, 1, 0, 0.15, &status)!=TPCERROR_OK) {
436 fprintf(stderr, "Error: %s\n", errorMsg(status.error)); fflush(stderr);
437 tacFree(&tac); parFree(&plim); parFree(&par); nloptFree(&nlo); return(6);
438 }
439#endif
440 nlo._fun(nlo.totalNr, nlo.xfull, nlo.fundata);
441 if(verbose>2) nloptWrite(&nlo, stdout);
442 if(verbose>6) {
443 printf("measured and fitted TAC:\n");
444 for(int i=0; i<tac.sampleNr; i++)
445 printf("\t%g\t%g\t%g\n", tac.x[i], tac.c[0].y[i], yfit[i]);
446 }
447 par.r[0].wss=nlo.funval;
448
449 /* Copy parameters */
450 for(int i=0; i<par.parNr; i++) par.r[0].p[i]=nlo.xfull[i];
451
452 nloptFree(&nlo);
453 }
454
455 /* Print and save parameters */
456 if(verbose>0 || !parfile[0]) parWrite(&par, stdout, PAR_FORMAT_TSV_UK, 1, NULL);
457 if(parfile[0]) {
458 par.format=parFormatFromExtension(parfile);
459 if(verbose>2) printf("parameter file format := %s\n", parFormattxt(par.format));
461 /* Save file */
462 if(verbose>1) printf(" saving %s\n", parfile);
463 FILE *fp=fopen(parfile, "w");
464 if(fp==NULL) {
465 fprintf(stderr, "Error: cannot open file for writing.\n"); fflush(stderr);
466 tacFree(&tac); parFree(&plim); parFree(&par); return(11);
467 }
468 int ret=parWrite(&par, fp, PAR_FORMAT_UNKNOWN, 1, &status);
469 fclose(fp);
470 if(ret!=TPCERROR_OK) {
471 fprintf(stderr, "Error: %s\n", errorMsg(status.error)); fflush(stderr);
472 tacFree(&tac); parFree(&plim); parFree(&par); return(12);
473 }
474 if(verbose>0) printf("parameters saved in %s\n", parfile);
475 }
476
477
478
479 /*
480 * Plot measured and fitted data, if requested
481 */
482 if(svgfile[0]) {
483 if(verbose>1) printf("plotting measured and fitted data\n");
484 /* Prepare place for function TAC */
485 double sdist;
486 tacGetSampleInterval(&tac, 1.0E-03, &sdist, NULL);
487 int snr=(int)simSamples(0.2*sdist, 0.0, par.r[0].end, 2, NULL);
488 TAC ftac; tacInit(&ftac);
489 int ret=tacAllocate(&ftac, snr, tac.tacNr);
490 if(ret!=TPCERROR_OK) {
491 fprintf(stderr, "Error: %s\n", errorMsg(status.error)); fflush(stderr);
492 tacFree(&tac); parFree(&plim); parFree(&par); return(21);
493 }
494 ftac.tacNr=tac.tacNr; ftac.sampleNr=snr;
495 ret=tacCopyHdr(&tac, &ftac);
496 for(int ci=0; ci<tac.tacNr && ret==0; ci++)
497 ret=tacCopyTacchdr(tac.c+ci, ftac.c+ci);
498 if(ret!=TPCERROR_OK) {
499 fprintf(stderr, "Error: %s\n", errorMsg(status.error)); fflush(stderr);
500 tacFree(&tac); parFree(&plim); parFree(&par); tacFree(&ftac);
501 return(22);
502 }
503 snr=(int)simSamples(0.2*sdist, 0.0, par.r[0].end, 2, ftac.x);
504 ftac.isframe=0;
505 /* Compute function values at sample times */
506 ret=0;
507 for(int ci=0; ci<tac.tacNr && ret==0; ci++) {
508 ret=mfEvalY(modelCode(par.r[ci].model), par.parNr, par.r[ci].p,
509 ftac.sampleNr, ftac.x, ftac.c[ci].y, verbose-5);
510 }
511 if(ret!=TPCERROR_OK) {
512 fprintf(stderr, "Error: cannot calculate function values.\n"); fflush(stderr);
513 tacFree(&tac); parFree(&plim); parFree(&par); tacFree(&ftac);
514 return(23);
515 }
516 if(verbose>10) tacWrite(&ftac, stdout, TAC_FORMAT_UNKNOWN, 1, NULL);
517 /* Plot */
518 ret=tacPlotFitSVG(&tac, &ftac, "", nan(""), nan(""), nan(""), nan(""), svgfile, &status);
519 if(ret!=TPCERROR_OK) {
520 fprintf(stderr, "Error: %s\n", errorMsg(status.error)); fflush(stderr);
521 tacFree(&tac); parFree(&plim); parFree(&par); tacFree(&ftac);
522 return(24);
523 }
524 tacFree(&ftac);
525 if(verbose>0) printf("Measured and fitted data plotted in %s\n", svgfile);
526 }
527
528
529
530 tacFree(&tac); parFree(&plim); parFree(&par);
531 return(0);
532}
533/*****************************************************************************/
534
535/*****************************************************************************
536 *
537 * Functions to be minimized
538 *
539 *****************************************************************************/
540double func_pbr_src(int parNr, double *p, void *fdata)
541{
542 FITDATA *d=(FITDATA*)fdata;
543
544 if(d->verbose>0) {printf("%s()\n", __func__); fflush(stdout);}
545 if(parNr!=4) return(nan(""));
546 if(d->verbose>20) printf("p[]: %g %g %g %g\n", p[0], p[1], p[2], p[3]);
547
548 /* Calculate the curve values and weighted SS */
549 double wss=0.0;
550 for(unsigned int i=0; i<d->n; i++) {
551 d->ysim[i]=nan("");
552 if(isnan(d->ymeas[i]) || isnan(d->x[i]) || d->x[i]<0.0) continue;
553 double et=exp(-p[2]*d->x[i]);
554 double rc=(1.0-p[3]/p[2])*d->x[i]*et + (p[3]/(p[2]*p[2]))*(1.0-et);
555 rc*=p[1];
556 d->ysim[i]=1.0/((1.0-p[0])+p[0]*rc);
557 double v=d->ysim[i]-d->ymeas[i];
558 if(d->optcrit==OPTCRIT_LAD)
559 wss+=d->w[i]*fabs(v);
560 else
561 wss+=d->w[i]*v*v;
562 }
563
564 return(wss);
565}
566/*****************************************************************************/
567double func_pbr_fm2(int parNr, double *p, void *fdata)
568{
569 FITDATA *d=(FITDATA*)fdata;
570
571 if(d->verbose>0) {printf("%s()\n", __func__); fflush(stdout);}
572 if(parNr!=7) return(nan(""));
573 if(d->verbose>20) printf("p[]: %g %g %g %g %g %g %g\n", p[0], p[1], p[2], p[3], p[4], p[5], p[6]);
574
575 /* Check that D(0)>0 */
576 double d0=p[1] - p[3]*p[4] - p[5]*p[6] + p[2]*(p[3]+p[5]);
577 if(d0<=0.0) return(nan(""));
578
579 /* Calculate the curve values and weighted SS */
580 double wss=0.0;
581 for(unsigned int i=0; i<d->n; i++) {
582 d->ysim[i]=nan("");
583 if(!isfinite(d->ymeas[i]) || !isfinite(d->x[i]) || d->x[i]<0.0) continue;
584 double rc=(p[1]*d->x[i]-p[3]-p[5])*exp(-p[2]*d->x[i])
585 + p[3]*exp(-p[4]*d->x[i]) + p[5]*exp(-p[6]*d->x[i]);
586 d->ysim[i]=1.0/((1.0-p[0])+p[0]*rc);
587 double v=d->ysim[i]-d->ymeas[i];
588 if(d->optcrit==OPTCRIT_LAD)
589 wss+=d->w[i]*fabs(v);
590 else
591 wss+=d->w[i]*v*v;
592 }
593
594 return(wss);
595}
596/*****************************************************************************/
597double func_pbr_rf(int parNr, double *p, void *fdata)
598{
599 FITDATA *d=(FITDATA*)fdata;
600
601 if(d->verbose>0) {printf("%s()\n", __func__); fflush(stdout);}
602 if(parNr!=7) return(nan(""));
603 if(d->verbose>20) printf("p[]: %g %g %g %g %g %g %g\n", p[0], p[1], p[2], p[3], p[4], p[5], p[6]);
604
605 /* Calculate the curve values and weighted SS */
606 double wss=0.0;
607 for(unsigned int i=0; i<d->n; i++) {
608 d->ysim[i]=nan("");
609 if(isnan(d->ymeas[i]) || isnan(d->x[i]) || d->x[i]<0.0) continue;
610 double a = p[1]*d->x[i] + p[3]*d->x[i]*d->x[i] + p[5]*d->x[i]*d->x[i]*d->x[i];
611 double b = 1.0 + p[2]*d->x[i] + p[4]*d->x[i]*d->x[i] + p[6]*d->x[i]*d->x[i]*d->x[i];
612 d->ysim[i]=1.0/((1.0-p[0])+p[0]*(a/b));
613 double v=d->ysim[i]-d->ymeas[i]; if(!isfinite(v)) return(nan(""));
614 if(d->optcrit==OPTCRIT_LAD)
615 wss+=d->w[i]*fabs(v);
616 else
617 wss+=d->w[i]*v*v;
618 }
619
620 return(wss);
621}
622/*****************************************************************************/
623double func_pbr_hill(int parNr, double *p, void *fdata)
624{
625 FITDATA *d=(FITDATA*)fdata;
626
627 if(d->verbose>0) {printf("%s()\n", __func__); fflush(stdout);}
628 if(parNr!=4) return(nan(""));
629 if(d->verbose>20) printf("p[]: %g %g %g %g\n", p[0], p[1], p[2], p[3]);
630
631 /* Calculate the curve values and weighted SS */
632 double wss=0.0;
633 for(unsigned int i=0; i<d->n; i++) {
634 d->ysim[i]=nan("");
635 if(isnan(d->ymeas[i]) || isnan(d->x[i]) || d->x[i]<0.0) continue;
636 double rc=p[1]*pow(d->x[i], p[2])/(p[3]+pow(d->x[i], p[2]));
637 d->ysim[i]=1.0/((1.0-p[0])+p[0]*rc);
638 double v=d->ysim[i]-d->ymeas[i]; if(!isfinite(v)) return(nan(""));
639 if(d->optcrit==OPTCRIT_LAD)
640 wss+=d->w[i]*fabs(v);
641 else
642 wss+=d->w[i]*v*v;
643 }
644
645 return(wss);
646}
647/*****************************************************************************/
648
649/*****************************************************************************/
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 fileExist(const char *filename)
Definition filexist.c:17
int mfEvalY(const char *fid, const int parNr, const double *p, const int sampleNr, const double *x, double *y, const int verbose)
Definition func.c:26
unsigned int drandSeed(short int seed)
Make and optionally set the seed for rand(), drand, drandRange, and drandGaussian().
Definition gaussdev.c:27
void iftFree(IFT *ift)
Definition ift.c:37
int iftPut(IFT *ift, const char *key, const char *value, char comment, TPCSTATUS *status)
Definition ift.c:63
int iftFindKey(IFT *ift, const char *key, int start_index)
Definition iftfind.c:30
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
char * modelDesc(const unsigned int i)
Definition modell.c:222
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
char * optcritCode(optimality_criterion id)
Definition optcrit.c:60
optimality_criterion optcritId(const char *s)
Definition optcrit.c:88
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
char * parFormattxt(parformat c)
Definition pario.c:59
int parWrite(PAR *par, FILE *fp, parformat format, int extra, TPCSTATUS *status)
Definition pario.c:148
int parReadLimits(PAR *par, const char *fname, const int verbose)
Definition pario.c:489
void parListLimits(PAR *par, FILE *fp)
Definition pario.c:406
int parFormatFromExtension(const char *s)
Definition pario.c:102
int parWriteLimits(PAR *par, const char *fname, const int verbose)
Definition pario.c:432
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
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
char * value
Definition tpcift.h:37
char * key
Definition tpcift.h:32
IFT_ITEM * item
Definition tpcift.h:57
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
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
IFT h
Optional (but often useful) header information.
Definition tpctac.h:141
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 tacNaNs(TAC *tac)
Definition tacnan.c:71
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 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 nloptIATGO(NLOPT *nlo, const int doLocal, unsigned int maxIterNr, double neighFract, TPCSTATUS *status)
Definition tgo.c:681
int nloptITGO1(NLOPT *nlo, const int doLocal, unsigned int tgoNr, unsigned int sampleNr, unsigned int neighNr, TPCSTATUS *status)
Definition tgo.c:59
Header file for libtpccm.
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 libtpcli.
Header file for libtpclinopt.
Header file for libtpcmodels.
optimality_criterion
Optimality Criterion for statistical optimizations.
Definition tpcmodels.h:67
@ OPTCRIT_OLS
Ordinary Least Squares (sum-of-squares, SS).
Definition tpcmodels.h:69
@ OPTCRIT_LAD
Least Absolute Deviations (sum of absolute deviations, LAE, LAV, LAR).
Definition tpcmodels.h:71
@ OPTCRIT_UNKNOWN
Unknown optimality criterion.
Definition tpcmodels.h:68
Header file for library libtpcnlopt.
Header file for libtpcpar.
@ PAR_FORMAT_UNKNOWN
Unknown format.
Definition tpcpar.h:28
@ 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.