TPCCLIB
Loading...
Searching...
No Matches
fit_wpul.c
Go to the documentation of this file.
1
7/*****************************************************************************/
8#include "tpcclibConfig.h"
9/*****************************************************************************/
10#ifdef HAVE_OMP_H
11#include <omp.h>
12#endif
13/*****************************************************************************/
14#include <stdio.h>
15#include <stdlib.h>
16#include <string.h>
17#include <math.h>
18/*****************************************************************************/
19#include "tpcextensions.h"
20#include "tpcift.h"
21#include "tpctac.h"
22#include "tpcpar.h"
23#include "tpcli.h"
24#include "tpccm.h"
25#include "tpctacmod.h"
26#include "tpclinopt.h"
27#include "tpcrand.h"
28#include "tpcnlopt.h"
29#include "tpcbfm.h"
30/*****************************************************************************/
31
32/*****************************************************************************/
33/* Local functions */
34double func_wpul(int parNr, double *p, void*);
35/*****************************************************************************/
36typedef struct FITDATA {
38 unsigned int ni;
40 double *xi;
42 double *yi;
43
45 unsigned int nt;
47 double *xt1;
49 double *xt2;
51 double *xt;
53 double *yt;
55 double *w;
57 double *syt;
58
60 int verbose;
61} FITDATA;
62/*****************************************************************************/
63
64/*****************************************************************************/
65static char *info[] = {
66 "Non-linear fitting of the radiowater model to pulmonary TTACs using BTAC",
67 "from RV cavity as the input function. Small delay and dispersion of input",
68 "function prior to lungs is allowed and fitted by default. Regional",
69 "radioactivity concentration is modelled as Cpet(t) = Vb*Cb(t) + Ct(t),",
70 "and thus the estimated K1 = (1-Va-Vb)*f. Air volume fraction (Va) could",
71 "be estimated from transmission or CT scan.",
72 " ",
73 "Usage: @P [Options] btacfile ttacfile [parfile]",
74 " ",
75 "Options:",
76 " -tau=<value>",
77 " Dispersion time constant is constrained to given value (sec).",
78 " -Vb=<value>",
79 " Blood volume is constrained to given value (mL/mL of lung).",
80 " -w1 | -wf",
81 " All weights are set to 1.0 (no weighting), or based on TTAC frame",
82 " lengths; by default, weights in TTAC file are used, if available.",
83 " -svg=<Filename>",
84 " Fitted and measured TACs are plotted in specified SVG file.",
85 " -sim=<Filename>",
86 " Fitted TTACs at BTAC sample times are saved in specified TAC file.",
87 " -stdoptions", // List standard options like --help, -v, etc
88 " ",
89 "Sample times must be in seconds, unless units are specified in the file.",
90 " ",
91 "See also: fit_h2o, bfmh2o, fitk2, fit_wrlv, fit_disp",
92 " ",
93 "Keywords: TAC, modelling, perfusion, lungs, radiowater",
94 0};
95/*****************************************************************************/
96
97/*****************************************************************************/
98/* Turn on the globbing of the command line, since it is disabled by default in
99 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
100 In Unix&Linux wildcard command line processing is enabled by default. */
101/*
102#undef _CRT_glob
103#define _CRT_glob -1
104*/
105int _dowildcard = -1;
106/*****************************************************************************/
107
108/*****************************************************************************/
112int main(int argc, char **argv)
113{
114 int ai, help=0, version=0, verbose=1;
115 char btacfile[FILENAME_MAX], ttacfile[FILENAME_MAX], parfile[FILENAME_MAX],
116 svgfile[FILENAME_MAX], simfile[FILENAME_MAX];
117 int weights=0; // 0=default, 1=no weighting, 2=frequency
118 double fixed_tau=nan("");
119 double fixed_vb=nan("");
120
121 drandSeed(1);
122
123
124 /*
125 * Get arguments
126 */
127 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
128 btacfile[0]=ttacfile[0]=parfile[0]=svgfile[0]=simfile[0]=(char)0;
129 /* Options */
130 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') {
131 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
132 char *cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(!*cptr) continue;
133 if(strcasecmp(cptr, "W1")==0) {
134 weights=1; continue;
135 } else if(strcasecmp(cptr, "WF")==0) {
136 weights=2; continue;
137 } else if(strncasecmp(cptr, "TAU=", 4)==0 && strlen(cptr)>4) {
138 if(!atofCheck(cptr+4, &fixed_tau) && fixed_tau>=0.0) continue;
139 } else if(strncasecmp(cptr, "VB=", 3)==0 && strlen(cptr)>3) {
140 if(!atofCheck(cptr+3, &fixed_vb) && fixed_vb>=0.0 && fixed_vb<1.0) continue;
141 } else if(strncasecmp(cptr, "SVG=", 4)==0 && strlen(cptr)>4) {
142 strlcpy(svgfile, cptr+4, FILENAME_MAX); continue;
143 } else if(strncasecmp(cptr, "SIM=", 4)==0 && strlen(cptr)>4) {
144 strlcpy(simfile, cptr+4, FILENAME_MAX); continue;
145 }
146 fprintf(stderr, "Error: invalid option '%s'.\n", argv[ai]);
147 return(1);
148 } else break;
149
150 TPCSTATUS status; statusInit(&status);
151 statusSet(&status, __func__, __FILE__, __LINE__, TPCERROR_OK);
152 status.verbose=verbose-3;
153
154 /* Print help or version? */
155 if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
156 if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
157 if(version) {tpcPrintBuild(argv[0], stdout); return(0);}
158
159 /* Process other arguments, starting from the first non-option */
160 if(ai<argc) strlcpy(btacfile, argv[ai++], FILENAME_MAX);
161 if(ai<argc) strlcpy(ttacfile, argv[ai++], FILENAME_MAX);
162 if(ai<argc) strlcpy(parfile, argv[ai++], FILENAME_MAX);
163 if(ai<argc) {
164 fprintf(stderr, "Error: invalid argument '%s'.\n", argv[ai]);
165 return(1);
166 }
167 /* Did we get all the information that we need? */
168 if(!ttacfile[0]) { // note that parameter file is optional
169 fprintf(stderr, "Error: missing command-line argument; use option --help\n");
170 return(1);
171 }
172
173 /* In verbose mode print arguments and options */
174 if(verbose>1) {
175 printf("btacfile := %s\n", btacfile);
176 printf("ttacfile := %s\n", ttacfile);
177 if(parfile[0]) printf("parfile := %s\n", parfile);
178 if(svgfile[0]) printf("svgfile := %s\n", svgfile);
179 if(simfile[0]) printf("simfile := %s\n", simfile);
180 printf("weights := %d\n", weights);
181 if(!isnan(fixed_tau)) printf("fixed_tau := %g\n", fixed_tau);
182 if(!isnan(fixed_vb)) printf("fixed_vb := %g\n", fixed_vb);
183 fflush(stdout);
184 }
185
186
187 /*
188 * Read the data
189 */
190 if(verbose>1) printf("reading TACs\n");
191 statusSet(&status, __func__, __FILE__, __LINE__, TPCERROR_OK);
192 TAC ttac, btac; tacInit(&ttac); tacInit(&btac);
193
194 if(tacRead(&ttac, ttacfile, &status)!=TPCERROR_OK) {
195 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
196 tacFree(&ttac); tacFree(&btac); return(2);
197 }
198 if(verbose>2) {
199 printf("ttac.fileformat := %s\n", tacFormattxt(ttac.format));
200 printf("ttacNr := %d\n", ttac.tacNr);
201 printf("ttac.sampleNr := %d\n", ttac.sampleNr);
202 fflush(stdout);
203 }
204
205 if(tacRead(&btac, btacfile, &status)!=TPCERROR_OK) {
206 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
207 tacFree(&ttac); tacFree(&btac); return(2);
208 }
209 if(verbose>2) {
210 printf("btac.fileformat := %s\n", tacFormattxt(btac.format));
211 printf("btacNr := %d\n", btac.tacNr);
212 printf("btac.sampleNr := %d\n", btac.sampleNr);
213 fflush(stdout);
214 }
215 if(btac.tacNr==2) {
216 if(verbose>0) fprintf(stdout, "Note: BTAC file assumed to contain RV and LV BTACs.\n");
217 } else if(btac.tacNr>2) {
218 if(verbose>0) fprintf(stderr, "Warning: BTAC file contains more than two TACs.\n");
219 btac.tacNr=1;
220 }
221
222 if(ttac.sampleNr<7 || btac.sampleNr<7) {
223 fprintf(stderr, "Error: too few samples.\n");
224 tacFree(&ttac); tacFree(&btac); return(2);
225 }
226 /* Check NaNs */
227 if(tacNaNs(&ttac)>0 || tacNaNs(&btac)>0) {
228 fprintf(stderr, "Error: data contains missing values.\n");
229 tacFree(&ttac); tacFree(&btac); return(2);
230 }
231 /* Sort data by sample time */
232 tacSortByTime(&ttac, &status);
233 tacSortByTime(&btac, &status);
234 /* Fix any gaps and overlap in data if possible and if not then quit with error */
235 if(tacSetXContiguous(&ttac) || tacSetXContiguous(&btac)) {
236 fprintf(stderr, "Error: invalid data sample times.\n");
237 tacFree(&ttac); tacFree(&ttac); return(2);
238 }
239 /* Convert sample times into seconds */
240 if(tacXUnitConvert(&ttac, UNIT_SEC, &status)!=TPCERROR_OK ||
241 tacXUnitConvert(&btac, UNIT_SEC, &status)!=TPCERROR_OK)
242 {
243 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
244 tacFree(&ttac); tacFree(&ttac); return(2);
245 }
246 /* Convert BTAC concentrations into TTAC units */
247 if(tacYUnitConvert(&btac, ttac.cunit, &status)!=TPCERROR_OK) {
248 fprintf(stderr, "Error: check and set the data units.\n");
249 tacFree(&ttac); tacFree(&ttac); return(2);
250 }
251 /* Get x range */
252 double xmin, xmax;
253 if(tacXRange(&ttac, &xmin, &xmax)!=0) {
254 fprintf(stderr, "Error: invalid data sample times.\n");
255 tacFree(&ttac); tacFree(&btac); return(2);
256 }
257 if(verbose>1) {
258 printf("xmin := %g\n", xmin);
259 printf("xmax := %g\n", xmax);
260 }
261
262
263 /* Set places for fitted TACs */
264 statusSet(&status, __func__, __FILE__, __LINE__, TPCERROR_OK);
265 if(tacAllocateMore(&ttac, ttac.tacNr)!=TPCERROR_OK) {
266 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
267 tacFree(&ttac); tacFree(&ttac); return(2);
268 }
269
270 /* Check and set weights */
271 statusSet(&status, __func__, __FILE__, __LINE__, TPCERROR_OK);
272 if(weights==0) {
273 if(!tacIsWeighted(&ttac)) {
275 for(int i=0; i<ttac.sampleNr; i++) ttac.w[i]=1.0;
276 }
277 } else if(weights==1) {
279 for(int i=0; i<ttac.sampleNr; i++) ttac.w[i]=1.0;
280 } else if(weights==2) {
281 if(tacWByFreq(&ttac, ISOTOPE_UNKNOWN, &status)!=TPCERROR_OK) {
282 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
283 tacFree(&ttac); tacFree(&btac); return(2);
284 }
285 }
286
287
288#if(0)
289 if(btac.isframe) {
290 TAC tmp; tacInit(&tmp);
291 if(tacFramesToSteps(&btac, &tmp, 0.01)) {
292 fprintf(stderr, "Error: invalid input sample times.\n");
293 tacFree(&ttac); tacFree(&btac); return(2);
294 }
295 tacFree(&btac);
296 if(tacDuplicate(&tmp, &btac)) {
297 fprintf(stderr, "Error: invalid input sample times.\n");
298 tacFree(&ttac); tacFree(&btac); tacFree(&tmp); return(2);
299 }
300 tacFree(&tmp);
301 }
302#endif
303
304
305 /*
306 * If LV cavity BTAC is available, then add 5% of it to RV input, with delay.
307 * LV input should probably have its own compartment, but for now like this.
308 */
309 if(btac.tacNr==2) {
310 double x[btac.sampleNr], y[btac.sampleNr];
311 for(int i=0; i<btac.sampleNr; i++) x[i]=btac.x[i]+4.0;
312 if(liInterpolate(x, btac.c[1].y, btac.sampleNr, btac.x, y, NULL, NULL, btac.sampleNr, 3, 1, 0))
313 {
314 fprintf(stderr, "Error: invalid input sample times.\n");
315 tacFree(&ttac); tacFree(&btac); return(2);
316 }
317 for(int i=0; i<btac.sampleNr; i++) btac.c[0].y[i]=0.95*btac.c[0].y[i]+0.05*y[i];
318 }
319
320
321
322 /*
323 * Prepare PAR structure for printing and saving model parameters
324 */
325 if(verbose>1) printf("preparing space for parameters\n");
326 PAR par; parInit(&par);
327 if(parAllocateWithTAC(&par, &ttac, 6, &status)!=TPCERROR_OK) {
328 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
329 tacFree(&ttac); tacFree(&btac); parFree(&par); return(3);
330 }
331 iftFree(&par.h); // remove stupid header info
332 /* set time and program name */
333 {
334 char buf[256];
335 time_t t=time(NULL);
336 iftPut(&par.h, "analysis_time", ctime_r_int(&t, buf), 0, NULL);
337 tpcProgramName(argv[0], 1, 1, buf, 256);
338 iftPut(&par.h, "program", buf, 0, NULL);
339 }
340 par.tacNr=ttac.tacNr; par.parNr=6;
342 for(int i=0; i<par.tacNr; i++) {
343 par.r[i].model=modelCodeIndex("radiowater-lung");
344 par.r[i].dataNr=tacWSampleNr(&ttac);
345 par.r[i].start=xmin;
346 par.r[i].end=xmax;
347 }
348 /* Set parameter names */
349 strcpy(par.n[0].name, "tau"); par.n[0].unit=UNIT_SEC;
350 strcpy(par.n[1].name, "deltaT"); par.n[1].unit=UNIT_SEC;
351 strcpy(par.n[2].name, "Vb"); par.n[2].unit=UNIT_ML_PER_ML;
352 strcpy(par.n[3].name, "K1"); par.n[3].unit=UNIT_ML_PER_ML_MIN;
353 strcpy(par.n[4].name, "k2"); par.n[4].unit=UNIT_PER_MIN;
354 strcpy(par.n[5].name, "K1/k2"); par.n[5].unit=UNIT_ML_PER_ML;
355 /* set file names */
356 iftPut(&par.h, "inputfile", btacfile, 0, NULL);
357 iftPut(&par.h, "datafile", ttacfile, 0, NULL);
358
359
360 /*
361 * Fit radiowater model for the lung TTACs
362 */
363 if(verbose==1) {printf("\nfitting...\n"); fflush(stdout);}
364 int failed=0;
365//#pragma omp parallel for
366 for(int ri=0; ri<ttac.tacNr; ri++) {
367 if(verbose>1) {printf("\nfitting %s\n", ttac.c[ri].name); fflush(stdout);}
368 /* Set data pointers for the fit */
369 FITDATA fitdata;
370 fitdata.ni=btac.sampleNr;
371 fitdata.xi=btac.x;
372 fitdata.yi=btac.c[0].y;
373 fitdata.nt=ttac.sampleNr;
374 if(ttac.isframe) {
375 fitdata.xt1=ttac.x1;
376 fitdata.xt2=ttac.x2;
377 fitdata.xt=NULL;
378 } else {
379 fitdata.xt=ttac.x;
380 fitdata.xt1=NULL;
381 fitdata.xt2=NULL;
382 }
383 fitdata.yt=ttac.c[ri].y;
384 fitdata.w=ttac.w;
385 fitdata.syt=ttac.c[ttac.tacNr+ri].y;
386 if(verbose>10) fitdata.verbose=verbose-10; else fitdata.verbose=0;
387 /* Set NLLS options */
388 NLOPT nlo; nloptInit(&nlo);
389 if(nloptAllocate(&nlo, 5)!=TPCERROR_OK) {
390 fprintf(stderr, "Error: cannot initiate NLLS.\n"); fflush(stderr); failed++;
391 nloptFree(&nlo); continue;
392 }
393 nlo._fun=func_wpul; nlo.maxFunCalls=10000;
394 nlo.fundata=&fitdata;
395 nlo.totalNr=5;
396 /* Set initial values and limits */
397 // dispersion time tau
398 if(isnan(fixed_tau)) {
399 nlo.xlower[0]=0.0; nlo.xupper[0]=8.0; nlo.xfull[0]=2.0; nlo.xtol[0]=0.01;
400 } else {
401 nlo.xlower[0]=nlo.xupper[0]=nlo.xfull[0]=fixed_tau; nlo.xtol[0]=0.0;
402 }
403 // delay time deltaT
404 nlo.xlower[1]=0.0; nlo.xupper[1]=4.0; nlo.xfull[1]=2.0; nlo.xtol[1]=0.001;
405 // Vb (of total ROI volume including air)
406 if(isnan(fixed_vb)) {
407 nlo.xlower[2]=0.00; nlo.xupper[2]=0.20; nlo.xfull[2]=0.01; nlo.xtol[2]=0.00001;
408 } else {
409 nlo.xlower[2]=nlo.xupper[2]=nlo.xfull[2]=fixed_vb; nlo.xtol[2]=0.0;
410 }
411 // K1
412 nlo.xlower[3]=0.00; nlo.xupper[3]=5.0; nlo.xfull[3]=1.4; nlo.xtol[3]=0.00001;
413 // k2
414 nlo.xlower[4]=0.00; nlo.xupper[4]=20.0; nlo.xfull[4]=5.0; nlo.xtol[4]=0.00001;
415
416
417#if(0)
418 // call function for testing
419 fitdata.verbose=10;
420 double wss=func_wpul(nlo.totalNr, nlo.xfull, &fitdata);
421 if(verbose>1) {
422 printf("\nTime\tTTAC\tsimTTAC\n");
423 for(unsigned int i=0; i<fitdata.nt; i++)
424 printf("%g\t%g\t%g\n", ttac.x[i], ttac.c[ri].y[i], ttac.c[ri+ttac.tacNr].y[i]);
425 printf("\n"); fflush(stdout);
426 }
427 if(verbose>1) {printf("\twss := %g\n", wss); fflush(stdout);}
428
429#else
430 /* Fit */
431 if(verbose>2) {
432 printf("initial guess\n");
433 nlo.funval=nlo._fun(nlo.totalNr, nlo.xfull, nlo.fundata);
434 nloptWrite(&nlo, stdout);
435 fflush(stdout);
436 }
437
438 //status.verbose=10;
439 if(nloptSimplexARRS(&nlo, 30, &status)!=TPCERROR_OK) {
440// if(nloptIATGO(&nlo, 1, 50, 0.05, &status)!=TPCERROR_OK) {
441 fprintf(stderr, "Error: %s\n", errorMsg(status.error)); fflush(stderr); failed++;
442 nloptFree(&nlo); continue;
443 }
444 //status.verbose=1;
445 double wss=nlo._fun(nlo.totalNr, nlo.xfull, nlo.fundata);
446 if(verbose>6) {
447 printf("\nTime\tTTAC\tsimTTAC\n");
448 for(unsigned int i=0; i<fitdata.nt; i++)
449 printf("%g\t%g\t%g\n", ttac.x[i], ttac.c[ri].y[i], ttac.c[ri+ttac.tacNr].y[i]);
450 printf("\n"); fflush(stdout);
451 }
452 if(verbose>2) nloptWrite(&nlo, stdout);
453 if(verbose>2) printf(" wss := %g\n", wss);
454
455#endif
456
457
458 /* Copy parameters */
459 par.r[ri].p[0]=nlo.xfull[0];
460 par.r[ri].p[1]=nlo.xfull[1];
461 par.r[ri].p[2]=nlo.xfull[2];
462 par.r[ri].p[3]=nlo.xfull[3];
463 par.r[ri].p[4]=nlo.xfull[4];
464 par.r[ri].p[5]=par.r[ri].p[3]/par.r[ri].p[4];
465 par.r[ri].wss=wss;
466
467 nloptFree(&nlo);
468 }
469 if(failed>0) {tacFree(&ttac); tacFree(&btac); parFree(&par); return(5);}
470
471
472 /* Print and save the parameters */
473 if(verbose>0) parWrite(&par, stdout, PAR_FORMAT_TSV_UK, 1, NULL);
474 if(parfile[0]) {
475 par.format=parFormatFromExtension(parfile);
476 if(verbose>2) printf("parameter file format := %s\n", parFormattxt(par.format));
478 /* Save file */
479 if(verbose>1) printf(" saving %s\n", parfile);
480 FILE *fp=fopen(parfile, "w");
481 if(fp==NULL) {
482 fprintf(stderr, "Error: cannot open file for writing.\n");
483 tacFree(&ttac); tacFree(&btac); parFree(&par); return(11);
484 }
485 int ret=parWrite(&par, fp, PAR_FORMAT_UNKNOWN, 1, &status);
486 fclose(fp);
487 if(ret!=TPCERROR_OK) {
488 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
489 tacFree(&ttac); tacFree(&btac); parFree(&par); return(12);
490 }
491 if(verbose>0) printf("parameters saved in %s\n", parfile);
492 }
493
494
495 /*
496 * Plot measured and fitted data, if requested
497 */
498 if(svgfile[0]) {
499 if(verbose>1) printf("plotting measured and fitted data\n");
500 TAC fit; tacInit(&fit);
501 (void)tacDuplicate(&ttac, &fit);
502 for(int r=0; r<ttac.tacNr; r++)
503 for(int i=0; i<ttac.sampleNr; i++)
504 fit.c[r].y[i]=ttac.c[r+ttac.tacNr].y[i];
505 /* Plot */
506 if(tacPlotFitSVG(&ttac, &fit, "", nan(""), nan(""), nan(""), nan(""), svgfile, NULL)!=TPCERROR_OK)
507 {
508 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
509 tacFree(&ttac); tacFree(&btac); parFree(&par); tacFree(&fit);
510 return(21);
511 }
512 if(verbose>0) printf("Measured and fitted data plotted in %s\n", svgfile);
513 tacFree(&fit);
514 }
515
516
517 /*
518 * Compute and save fitted TTACs at BTAC sample times, if requested
519 */
520 if(simfile[0]) {
521 if(verbose>1) printf("calculating simulated TTACs\n");
522
523 /* Allocate memory for simulated TTACs */
524 TAC sim; tacInit(&sim);
525 if(tacDuplicate(&ttac, &sim) || tacAllocateMoreSamples(&sim, btac.sampleNr-ttac.sampleNr)) {
526 fprintf(stderr, "Error: cannot allocate space for simulated TTACs\n");
527 tacFree(&ttac); tacFree(&btac); parFree(&par); tacFree(&sim);
528 return(31);
529 }
530 sim.sampleNr=btac.sampleNr;
531 sim.isframe=btac.isframe;
532 (void)tacXCopy(&btac, &sim, 0, sim.sampleNr-1);
534
535 /* Set data pointers for the function data structure */
536 FITDATA fitdata;
537 fitdata.ni=btac.sampleNr;
538 fitdata.xi=btac.x;
539 fitdata.yi=btac.c[0].y;
540 fitdata.nt=btac.sampleNr;
541 if(btac.isframe) {
542 fitdata.xt1=btac.x1;
543 fitdata.xt2=btac.x2;
544 fitdata.xt=NULL;
545 } else {
546 fitdata.xt=btac.x;
547 fitdata.xt1=NULL;
548 fitdata.xt2=NULL;
549 }
550 fitdata.w=btac.w;
551
552 /* Simulate one TAC at a time */
553 for(int i=0; i<sim.tacNr; i++) {
554 fitdata.yt=fitdata.syt=sim.c[i].y;
555 func_wpul(5, par.r[i].p, &fitdata);
556 }
557
558 /* Save simulated TTACs */
559 if(verbose>1) printf("writing %s\n", simfile);
560 FILE *fp; fp=fopen(simfile, "w");
561 if(fp==NULL) {
562 fprintf(stderr, "Error: cannot open file for writing (%s)\n", simfile);
563 tacFree(&ttac); tacFree(&btac); parFree(&par); tacFree(&sim); return(32);
564 }
565 int ret=tacWrite(&sim, fp, TAC_FORMAT_PMOD, 1, &status);
566 fclose(fp); tacFree(&sim);
567 if(ret!=TPCERROR_OK) {
568 fprintf(stderr, "Error (%d): %s\n", ret, errorMsg(status.error));
569 tacFree(&ttac); tacFree(&btac); parFree(&par); return(33);
570 }
571 if(verbose>=0) {printf("%s saved.\n", simfile); fflush(stdout);}
572 }
573
574
575 tacFree(&ttac); tacFree(&btac); parFree(&par);
576 return(0);
577}
578/*****************************************************************************/
579
580/*****************************************************************************
581 *
582 * Functions to be minimized
583 *
584 *****************************************************************************/
585double func_wpul(int parNr, double *p, void *fdata)
586{
587 FITDATA *d=(FITDATA*)fdata;
588
589 if(d->verbose>0) {printf("%s()\n", __func__); fflush(stdout);}
590 if(parNr!=5 || p==NULL || fdata==NULL || d->ni<1 || d->nt<1) return(nan(""));
591 if(d->verbose>9) {
592 printf("p[]: %g", p[0]);
593 for(int i=1; i<parNr; i++) printf(" %g", p[i]);
594 printf("\n"); fflush(stdout);
595 }
596
597 /* Process parameters */
598 double tau=p[0]; if(tau<0.0) tau=0.0;
599 double deltaT=p[1];
600 double Vb=p[2]; if(Vb<0.0) Vb=0.0;
601 double K1=p[3]/60.0; if(K1<0.0) K1=0.0;
602 double k2=p[4]/60.0; if(k2<0.0) k2=0.0;
603
604 /* Make input TAC with delay and dispersion */
605 double x[d->ni], y[d->ni], sy[d->ni];
606 for(unsigned int i=0; i<d->ni; i++) x[i]=d->xi[i]+deltaT;
607 for(unsigned int i=0; i<d->ni; i++) y[i]=d->yi[i];
608 if(simDispersion(x, y, d->ni, tau, 0.0, sy)!=0) return(nan(""));
609
610 /* Simulate tissue curve at input sample times */
611 if(simC1(x, y, d->ni, K1, k2, sy)!=0) return(nan(""));
612 for(unsigned int i=0; i<d->ni; i++) sy[i]+=Vb*y[i];
613
614 /* Interpolate simulated tissue curve to the sample times of measured tissue */
615 if(d->xt1==NULL || d->xt2==NULL) {
616 if(liInterpolate(x, sy, d->ni, d->xt, d->syt, NULL, NULL, d->nt, 3, 1, 0))
617 return(nan(""));
618 } else {
619 if(liInterpolateForPET(x, sy, d->ni, d->xt1, d->xt2, d->syt, NULL, NULL, d->nt, 3, 1, 0))
620 return(nan(""));
621 }
622
623 /* Calculate the weighted SS */
624 if(d->verbose>2) {fprintf(stdout, "computing WSS...\n"); fflush(stdout);}
625 double wss=0.0;
626 for(unsigned i=0; i<d->nt; i++) {
627 double v=d->syt[i] - d->yt[i];
628 wss+=d->w[i]*v*v;
629 }
630
631 return(wss);
632}
633/*****************************************************************************/
634
635/*****************************************************************************/
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
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 liInterpolate(double *x, double *y, const int nr, double *newx, double *newy, double *newyi, double *newyii, const int newnr, const int se, const int ee, const int verbose)
Linear interpolation and/or integration with trapezoidal method.
int liInterpolateForPET(double *x, double *y, const int nr, double *newx1, double *newx2, double *newy, double *newyi, double *newyii, const int newnr, const int se, const int ee, const int verbose)
Linear TAC interpolation and/or integration to PET frames.
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
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 parFormatFromExtension(const char *s)
Definition pario.c:102
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 simC1(double *t, double *ca, const int nr, const double k1, const double k2, double *ct)
Definition sim1cm.c:93
int simDispersion(double *x, double *y, const int n, const double tau1, const double tau2, double *tmp)
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
int unit
Definition tpcpar.h:86
char name[MAX_PARNAME_LEN+1]
Definition tpcpar.h:82
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
double * x2
Definition tpctac.h:101
double * x1
Definition tpctac.h:99
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 tacDuplicate(TAC *tac1, TAC *tac2)
Make a duplicate of TAC structure.
Definition tac.c:356
void tacInit(TAC *tac)
Definition tac.c:24
int tacAllocateMoreSamples(TAC *tac, int addNr)
Allocate memory for more samples in TAC data.
Definition tac.c:435
int tacAllocateMore(TAC *tac, int tacNr)
Definition tac.c:178
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 tacYUnitConvert(TAC *tac, const int u, TPCSTATUS *status)
Definition tacunits.c:72
int tacXUnitConvert(TAC *tac, const int u, TPCSTATUS *status)
Definition tacunits.c:23
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 tacFramesToSteps(TAC *inp, TAC *out, TPCSTATUS *status)
Transform TAC with frames into TAC with frames represented with stepwise changing dot-to-dot data.
Definition tacx.c:942
int tacXCopy(TAC *tac1, TAC *tac2, int i1, int i2)
Definition tacx.c:24
int tacSetXContiguous(TAC *d)
Set PET TAC frame times contiguous, without even tiny overlap or gaps in between.
Definition tacx.c:1166
int tacXRange(TAC *d, double *xmin, double *xmax)
Get the range of x values (times) in TAC structure.
Definition tacx.c:124
Header file for libtpcbfm.
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).
@ UNIT_ML_PER_ML
mL/mL
@ UNIT_ML_PER_ML_MIN
mL/(mL*min)
@ UNIT_SEC
seconds
@ UNIT_PER_MIN
1/min
@ TPCERROR_OK
No error.
Header file for library libtpcift.
@ ISOTOPE_UNKNOWN
Unknown.
Definition tpcisotope.h:51
Header file for libtpcli.
Header file for libtpclinopt.
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_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_PMOD
PMOD TAC format.
Definition tpctac.h:33
Header file for libtpctacmod.