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