TPCCLIB
Loading...
Searching...
No Matches
fitk2.c
Go to the documentation of this file.
1
7/*****************************************************************************/
8#include "tpcclibConfig.h"
9/*****************************************************************************/
10#include <stdio.h>
11#include <stdlib.h>
12#include <math.h>
13#include <unistd.h>
14#include <string.h>
15#include <time.h>
16/*****************************************************************************/
17#include "libtpcmisc.h"
18#include "libtpcmodel.h"
19#include "libtpccurveio.h"
20#include "libtpcsvg.h"
21#include "libtpcmodext.h"
22/*****************************************************************************/
23
24/*****************************************************************************/
25const int parNr=3;
26DFT input, dft;
27double *petmeas, *petsim;
28double fVb=-1.0;
29double pmin[MAX_PARAMETERS], pmax[MAX_PARAMETERS];
30int fitframeNr;
31double wss_wo_penalty=0.0;
32/*****************************************************************************/
33/* Local functions */
34double cm2Func(int parNr, double *p, void*);
35/*****************************************************************************/
36
37/*****************************************************************************/
38static char *info[] = {
39 "Non-linear fitting of one-tissue compartment model to plasma input, blood,",
40 "and tissue time-activity curves (PTAC, BTAC, and TTAC) to estimate",
41 "parameters K1, k2, and Vb. Sample times must be in minutes.",
42 " ",
43 "To fit only parameters K1 and Vb, assuming k2=0, create limit file (see options),",
44 "and set the lower and upper limit for K1/k2 to zero.",
45 " ",
46 " ______ ______ ",
47 " | | K1 | | ",
48 " | Ca | ---> | C1 | ",
49 " |______| |______| ",
50 " | k2 ",
51 " V ",
52 " ",
53 "Usage: @P [Options] ptacfile btacfile ttacfile endtime resultfile",
54 " ",
55 "Options:",
56 " -lim[=<filename>]",
57 " Specify the constraints for model parameters;",
58 " This file with default values can be created by giving this",
59 " option as the only command-line argument to this program.",
60 " Without filename the default values are printed on screen.",
61 " -SD[=<y|N>]",
62 " Standard deviations are calculated and saved in results (Y, default),",
63 " or not calculated (n).",
64 " Program runs a lot faster if SD and CL are not calculated.",
65 " -CL[=<y|N>]",
66 " 95% Confidence limits are calculated and saved in results (y), or",
67 " not calculated (N, default).",
68 " -Vb=<Vb(%)>",
69 " Enter a fixed Vb; fitted by default.",
70 " -<BPnd|BPp|DVR>=<Reference region id or filename>",
71 " Optional reference region is used to calculate BPnd, BPp, or DVR;",
72 " BPnd=DVroi/DVref-1, BPp=DVroi-DVref, and DVR=DVroi/DVref",
73 " -fit=<Filename>",
74 " Fitted regional TACs are written in DFT format.",
75 " -svg=<Filename>",
76 " Fitted and measured TACs are plotted in specified SVG file.",
77 " -stdoptions", // List standard options like --help, -v, etc
78 " ",
79 "Example 1: estimate K1, K1/k2 and Vb, with estimation of parameter SD",
80 " @P -sd=y a919ap.bld a919ab.bld a919.tac 60 a919k2.res",
81 " ",
82 "Example 2: estimate K1 and DV (=K1/k2); Vb is constrained to 0%;",
83 "DVRs are calculated by dividing DVs by the DV of region 'cer'",
84 " @P -Vb=0 -R=cer p25apc.bld none p25.tac 60 p25_k2.res",
85 " ",
86 "See also: logan, lhsoldv, fitk2di, fitk4, fit_h2o, p2t_v3c, tacweigh, taccbv",
87 " ",
88 "Keywords: TAC, modelling, distribution volume, reversible uptake, 1TCM",
89 0};
90/*****************************************************************************/
91
92/*****************************************************************************/
93/* Turn on the globbing of the command line, since it is disabled by default in
94 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
95 In Unix&Linux wildcard command line processing is enabled by default. */
96/*
97#undef _CRT_glob
98#define _CRT_glob -1
99*/
100int _dowildcard = -1;
101/*****************************************************************************/
102
103/*****************************************************************************/
107int main(int argc, char **argv)
108{
109 int ai, help=0, version=0, verbose=1;
110 int ri, fi, pi, m, n, ret;
111 int ref=-1, refAdded=0, inputtype;
112 int bp_type=0; // 0=no, 1=DVR, 2=BPnd, 3=BPp
113 char dfile[FILENAME_MAX], pfile[FILENAME_MAX], bfile[FILENAME_MAX],
114 rfile[FILENAME_MAX], ffile[FILENAME_MAX], limfile[FILENAME_MAX];
115 char svgfile[FILENAME_MAX];
116 char *cptr, refname[FILENAME_MAX], tmp[FILENAME_MAX];
117 double fitdur, wss, aic;
118 RES res;
119 IFT ift;
120 int doBootstrap=0, doSD=0, doCL=0; // 0=no, 1=yes
121 double *sd, *cl1, *cl2;
122 double def_pmin[MAX_PARAMETERS], def_pmax[MAX_PARAMETERS];
123
124
125
126 /* Set parameter initial values and constraints */
127 /* K1 */ def_pmin[0]=0.0; def_pmax[0]=10.0;
128 /* K1/k2 */ def_pmin[1]=0.0; def_pmax[1]=500.0;
129 /* Vb */ def_pmin[2]=0.0; def_pmax[2]=0.08;
130
131 /*
132 * Get arguments
133 */
134 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
135 dfile[0]=pfile[0]=bfile[0]=rfile[0]=ffile[0]=refname[0]=limfile[0]=(char)0;
136 svgfile[0]=(char)0;
137 fitdur=fVb=-1.0;
138 iftInit(&ift); resInit(&res); dftInit(&dft); dftInit(&input);
139 /* Get options first, because it affects what arguments are read */
140 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') {
141 cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(cptr==NULL) continue;
142 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
143 if(strncasecmp(cptr, "CL", 2)==0) {
144 if(strlen(cptr)==2) {doCL=1; continue;}
145 cptr+=2; if(*cptr=='=') {
146 cptr++;
147 if(*cptr=='Y' || *cptr=='y') {doCL=1; continue;}
148 if(*cptr=='N' || *cptr=='n') {doCL=0; continue;}
149 }
150 } else if(strncasecmp(cptr, "SD", 2)==0) {
151 if(strlen(cptr)==2) {doSD=1; continue;}
152 cptr+=2; if(*cptr=='=') {
153 cptr++;
154 if(*cptr=='Y' || *cptr=='y') {doSD=1; continue;}
155 if(*cptr=='N' || *cptr=='n') {doSD=0; continue;}
156 }
157 } else if(strncasecmp(cptr, "LIM=", 4)==0 && strlen(cptr)>4) {
158 strlcpy(limfile, cptr+4, FILENAME_MAX); continue;
159 } else if(strncasecmp(cptr, "I=", 2)==0 && strlen(cptr)>2) { // deprecated
160 strlcpy(limfile, cptr+2, FILENAME_MAX); continue;
161 } else if(strcasecmp(cptr, "LIM")==0) {
162 strcpy(limfile, "stdout"); continue;
163 } else if(strcasecmp(cptr, "I")==0) { // deprecated
164 strcpy(limfile, "stdout"); continue;
165 } else if(strncasecmp(cptr, "Vb=", 3)==0 && strlen(cptr)>3) {
166 fVb=0.01*atof_dpi(cptr+3);
167 if(fVb>=0.0 && fVb<1.0) {
168 if(fVb<0.01) fprintf(stderr, "Warning: Vb was set to %g%%\n", 100.*fVb);
169 def_pmin[2]=def_pmax[2]=fVb;
170 continue;
171 }
172 fVb=-1.0;
173 } else if(strncasecmp(cptr, "DVR=", 4)==0) {
174 bp_type=1; strlcpy(refname, cptr+4, FILENAME_MAX);
175 if(strlen(refname)>0.0) continue;
176 } else if(strncasecmp(cptr, "BPnd=", 5)==0) {
177 bp_type=2; strlcpy(refname, cptr+5, FILENAME_MAX);
178 if(strlen(refname)>0.0) continue;
179 } else if(strncasecmp(cptr, "BPp=", 4)==0) {
180 bp_type=3; strlcpy(refname, cptr+4, FILENAME_MAX);
181 if(strlen(refname)>0.0) continue;
182 } else if(strncasecmp(cptr, "FIT=", 4)==0) {
183 strlcpy(ffile, cptr+4, FILENAME_MAX); if(strlen(ffile)>0) continue;
184 } else if(strncasecmp(cptr, "SVG=", 4)==0) {
185 strlcpy(svgfile, cptr+4, FILENAME_MAX); if(strlen(svgfile)>0) continue;
186 }
187 fprintf(stderr, "Error: invalid option '%s'.\n", argv[ai]);
188 return(1);
189 } else break;
190
191 /* Print help or version? */
192 if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
193 if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
194 if(version) {tpcPrintBuild(argv[0], stdout); return(0);}
195
196 /* Process other arguments, starting from the first non-option */
197 for(; ai<argc; ai++) {
198 if(!pfile[0]) {
199 strlcpy(pfile, argv[ai], FILENAME_MAX); continue;
200 } else if(!bfile[0]) {
201 strlcpy(bfile, argv[ai], FILENAME_MAX); continue;
202 } else if(!dfile[0]) {
203 strlcpy(dfile, argv[ai], FILENAME_MAX); continue;
204 } else if(fitdur<0) {
205 if(!atof_with_check(argv[ai], &fitdur) && fitdur>=0.0) continue;
206 fprintf(stderr, "Error: invalid fit time '%s'.\n", argv[ai]);
207 return(1);
208 } else if(!rfile[0]) {
209 strlcpy(rfile, argv[ai], FILENAME_MAX); continue;
210 }
211 /* we should never get this far */
212 fprintf(stderr, "Error: too many arguments: '%s'.\n", argv[ai]);
213 return(1);
214 }
215 if(doSD || doCL) doBootstrap=1; else doBootstrap=0;
216
217 /* In verbose mode print arguments and options */
218 if(verbose>1) {
219 printf("pfile := %s\n", pfile);
220 printf("dfile :=%s\n", dfile);
221 printf("rfile := %s\n", rfile);
222 printf("ffile := %s\n", ffile);
223 printf("svgfile := %s\n", svgfile);
224 printf("limfile := %s\n", limfile);
225 printf("bp_type := %d\n", bp_type);
226 printf("refname := %s\n", refname);
227 printf("fitdur := %g\n", fitdur);
228 printf("doBootstrap := %d\n", doBootstrap);
229 printf("doSD := %d\n", doSD);
230 printf("doCL := %d\n", doCL);
231 }
232
233
234 /* If only filename for initial values was given, then write one
235 with default contents, and exit */
236 if(limfile[0] && !pfile[0]) {
237 /* Check that initial value file does not exist */
238 if(strcasecmp(limfile, "stdout")!=0 && access(limfile, 0) != -1) {
239 fprintf(stderr, "Error: parameter constraint file %s exists.\n", limfile);
240 return(9);
241 }
242 if(verbose>1) printf("writing parameter constraints file\n");
243 /* Create parameter file */
244 iftPutDouble(&ift, "K1_lower", def_pmin[0], NULL, 0);
245 iftPutDouble(&ift, "K1_upper", def_pmax[0], NULL, 0);
246 iftPutDouble(&ift, "K1k2_lower", def_pmin[1], NULL, 0);
247 iftPutDouble(&ift, "K1k2_upper", def_pmax[1], NULL, 0);
248 iftPutDouble(&ift, "Vb_lower", def_pmin[2], NULL, 0);
249 iftPutDouble(&ift, "Vb_upper", def_pmax[2], NULL, 0);
250 ret=iftWrite(&ift, limfile, 0);
251 if(ret) {
252 fprintf(stderr, "Error in writing '%s': %s\n", limfile, ift.status);
253 iftEmpty(&ift); return(9);
254 }
255 if(strcasecmp(limfile, "stdout")!=0)
256 fprintf(stdout, "Parameter file %s with initial values written.\n", limfile);
257 iftEmpty(&ift); return(0);
258 }
259
260 /* Did we get all the information from user that we need? */
261 if(fitdur==0) fitdur=1.0E+100;
262 else if(fitdur<0) {tpcPrintUsage(argv[0], info, stderr); return(1);}
263 if(!rfile[0]) {
264 fprintf(stderr, "Error: missing command-line argument; use option --help\n");
265 return(1);
266 }
267
268 /*
269 * Read model parameter initial values and upper and lower limits
270 * if file for that was given
271 */
272 if(limfile[0]) {
273 double v;
274 if(verbose>1) printf("reading %s\n", limfile);
275 ret=iftRead(&ift, limfile, 1, 0);
276 if(ret) {
277 fprintf(stderr, "Error in reading '%s': %s\n", limfile, ift.status);
278 return(9);
279 }
280 if(verbose>10) iftWrite(&ift, "stdout", 0);
281 int n=0;
282 /* K1 */
283 if(iftGetDoubleValue(&ift, 0, "K1_lower", &v, 0)>=0) {def_pmin[0]=v; n++;}
284 if(iftGetDoubleValue(&ift, 0, "K1_upper", &v, 0)>=0) {def_pmax[0]=v; n++;}
285 /* K1/k2 */
286 if(iftGetDoubleValue(&ift, 0, "K1k2_lower", &v, 0)>=0) {def_pmin[1]=v; n++;}
287 if(iftGetDoubleValue(&ift, 0, "K1k2_upper", &v, 0)>=0) {def_pmax[1]=v; n++;}
288 /* Vb */
289 if(iftGetDoubleValue(&ift, 0, "Vb_lower", &v, 0)>=0) {def_pmin[2]=v; n++;}
290 if(iftGetDoubleValue(&ift, 0, "Vb_upper", &v, 0)>=0) {def_pmax[2]=v; n++;}
291 iftEmpty(&ift);
292 if(n==0) {fprintf(stderr, "Error: invalid parameter file.\n"); return(9);}
293 }
294 /* Check that these are ok */
295 for(pi=n=0, ret=0; pi<parNr; pi++) {
296 if(def_pmin[pi]<0.0) ret++;
297 if(def_pmax[pi]<def_pmin[pi]) ret++;
298 if(def_pmax[pi]>def_pmin[pi]) n++;
299 }
300 if(ret) {
301 fprintf(stderr, "Error: invalid parameter constraints.\n");
302 return(9);
303 }
304 if(n==0) {
305 fprintf(stderr, "Error: no model parameters left free for fitting.\n");
306 return(9);
307 }
308
309 /* Fixed/fitted Vb */
310 if(fVb>=0.0) def_pmin[2]=def_pmax[2]=fVb;
311 if(def_pmin[2]==def_pmax[2]) fVb=def_pmin[2];
312 if(fVb==0.0) strcpy(bfile, "");
313 if(verbose>1) {
314 printf("bfile := %s\n", bfile);
315 if(fVb>=0.0) printf("fVb := %g\n", fVb);
316 }
317
318
319 /*
320 * Read tissue and input data
321 */
322 if(verbose>1) printf("reading tissue and input data\n");
323 ret=dftReadModelingData(dfile, pfile, bfile, NULL, &fitdur,
324 &fitframeNr, &dft, &input, stdout, verbose-2, tmp);
325 if(ret!=0) {
326 fprintf(stderr, "Error: %s\n", tmp);
327 return(2);
328 }
329 if(fitframeNr<4 || input.frameNr<4) {
330 fprintf(stderr, "Error: too few samples in specified fit duration.\n");
331 dftEmpty(&input); dftEmpty(&dft); return(2);
332 }
333 /* If there is no blood TAC, then create a zero blood TAC */
334 if(input.voiNr<2) {
335 if(verbose>2) printf("setting blood tac to zero\n");
336 ret=dftAddmem(&input, 1);
337 if(ret) {
338 fprintf(stderr, "Error: cannot allocate more memory.\n");
339 dftEmpty(&dft); dftEmpty(&input); return(3);
340 }
341 strcpy(input.voi[1].voiname, "blood");
342 strcpy(input.voi[1].name, input.voi[1].voiname);
343 for(fi=0; fi<input.frameNr; fi++) input.voi[1].y[fi]=0.0;
344 input.voiNr=2;
345 }
346 if(verbose>10) dftPrint(&dft);
347 if(verbose>10) dftPrint(&input);
348 /* Print the weights */
349 if(verbose>2) {
350 fprintf(stdout, "common_data_weights := %g", dft.w[0]);
351 for(fi=1; fi<dft.frameNr; fi++) fprintf(stdout, ", %g", dft.w[fi]);
352 fprintf(stdout, "\n");
353 }
354
355
356 /*
357 * Read reference TAC
358 */
359 /* Check if user even wants any reference region */
360 if(!refname[0]) {
361 if(verbose>1) printf("no reference region data\n");
362 ref=-1;
363 } else {
364 if(verbose>1) printf("reading reference region data\n");
365 if((n=dftReadReference(&dft, refname, &inputtype, &ref, tmp, verbose-3))<1) {
366 fprintf(stderr, "Error in reading '%s': %s\n", refname, tmp);
367 if(verbose>2) printf("dftReadReference()=%d\n", n);
368 dftEmpty(&dft); dftEmpty(&input); return(6);
369 }
370 if(verbose>30) dftPrint(&dft);
371 if(n>1)
372 fprintf(stderr, "Warning: %s selected of %d reference regions.\n",
373 dft.voi[ref].name, n);
374 if(verbose>1)
375 fprintf(stdout, "selected reference region := %s\n", dft.voi[ref].name);
376 if(inputtype==5) { // Reference region name was given
377 refAdded=0; strcpy(refname, "");
378 } else { // reference file was given; ref TACs may have to be deleted later
379 refAdded=1;
380 }
381 if(verbose>15) dftPrint(&dft);
382 if(verbose>1) printf("Reference region: %s\n", dft.voi[ref].name );
383 }
384
385 /* Allocate an extra TAC for the bootstrap */
386 if(doBootstrap) {
387 ret=dftAddmem(&dft, 1); if(ret) {
388 fprintf(stderr, "Error: cannot allocate more memory.\n");
389 dftEmpty(&dft); dftEmpty(&input); return(9);
390 }
391 strcpy(dft.voi[dft.voiNr].voiname, "BS");
392 strcpy(dft.voi[dft.voiNr].name, "BS");
393 }
394 if(verbose>10) dftPrint(&dft);
395
396
397 /*
398 * Prepare the room for the results
399 */
400 if(verbose>1) printf("initializing result data\n");
401 ret=res_allocate_with_dft(&res, &dft); if(ret!=0) {
402 fprintf(stderr, "Error: cannot setup memory for results.\n");
403 dftEmpty(&input); dftEmpty(&dft); return(7);
404 }
405 /* Copy titles & filenames */
406 tpcProgramName(argv[0], 1, 1, res.program, 256);
407 strcpy(res.datafile, dfile);
408 strcpy(res.plasmafile, pfile);
409 strcpy(res.bloodfile, bfile);
410 if(ref>=0) sprintf(res.refroi, "%s", dft.voi[ref].name);
411 if(refname[0]) strcpy(res.reffile, refname);
412 strcpy(res.fitmethod, "TGO");
413 /* Constants */
414 res.isweight=dft.isweight;
415 if(fVb>=0.0) res.Vb=100.0*fVb;
416 /* Set data range */
417 sprintf(res.datarange, "%g - %g %s", 0.0, fitdur, dftTimeunit(dft.timeunit));
418 res.datanr=fitframeNr;
419 /* Set current time to results */
420 res.time=time(NULL);
421 /* Set parameter number, including also the extra "parameters"
422 and the parameter names and units */
423 res.parNr=5; if(ref>=0) res.parNr++;
424 pi=0; strcpy(res.parname[pi], "K1"); strcpy(res.parunit[pi], "ml/(min*ml)");
425 pi++; strcpy(res.parname[pi], "K1/k2"); strcpy(res.parunit[pi], "ml/ml");
426 pi++; strcpy(res.parname[pi], "Vb"); strcpy(res.parunit[pi], "%");
427 if(bp_type>0) {
428 pi++;
429 if(bp_type==1) {
430 strcpy(res.parname[pi], "DVR"); strcpy(res.parunit[pi], "ml/ml");
431 } else if(bp_type==2) {
432 strcpy(res.parname[pi], "BPnd"); strcpy(res.parunit[pi], "");
433 } else {
434 strcpy(res.parname[pi], "BPp"); strcpy(res.parunit[pi], "");
435 }
436 }
437 pi++; strcpy(res.parname[pi], "WSS"); strcpy(res.parunit[pi], "");
438 pi++; strcpy(res.parname[pi], "AIC"); strcpy(res.parunit[pi], "");
439
440
441 /*
442 * Fit ROIs
443 */
444 if(verbose>0) {
445 fprintf(stdout, "fitting regional TACs: ");
446 if(verbose>1) fprintf(stdout, "\n");
447 }
448 fflush(stdout);
449 for(ri=0; ri<dft.voiNr; ri++) {
450 if(verbose>2) printf("\n %d %s:\n", ri, dft.voi[ri].name);
451
452 /* Initiate values */
453 petmeas=dft.voi[ri].y; petsim=dft.voi[ri].y2;
454
455 /* Set constraints */
456 pmin[0]=def_pmin[0]; pmax[0]=def_pmax[0]; /* K1 */
457 pmin[1]=def_pmin[1]; pmax[1]=def_pmax[1]; /* K1/k2 */
458 pmin[2]=def_pmin[2]; pmax[2]=def_pmax[2]; /* Vb */
459 if(verbose>3) {
460 printf(" constraints :=");
461 for(pi=0; pi<parNr; pi++) printf(" [%g,%g]", pmin[pi], pmax[pi]);
462 printf("\n");
463 }
464
465 /* Fit */
468 ret=tgo(
469 pmin, pmax, cm2Func, NULL, parNr, 8,
470 &wss, res.voi[ri].parameter, 100, 0, verbose-8);
471 if(ret>0) {
472 fprintf(stderr, "\nError in optimization (%d).\n", ret);
473 dftEmpty(&input); dftEmpty(&dft); resEmpty(&res); return(8);
474 }
475 if(verbose>4) {
476 printf(" fitted_parameters :=");
477 for(pi=0; pi<parNr; pi++) printf(" %g", res.voi[ri].parameter[pi]);
478 printf("\n");
479 }
480 /* Correct fitted parameters to match constraints like inside function */
481 (void)modelCheckParameters(parNr, pmin, pmax, res.voi[ri].parameter,
482 res.voi[ri].parameter, NULL);
483 wss=wss_wo_penalty;
484
485 /* Bootstrap */
486 if(doBootstrap) {
487 if(verbose>2) printf("\n bootstrapping\n");
488 /* bootstrap changes measured and simulated data, therefore use copies */
489 petmeas=dft.voi[dft.voiNr].y2; petsim=dft.voi[dft.voiNr].y3;
490 if(doSD) sd=res.voi[ri].sd; else sd=NULL;
491 if(doCL) {cl1=res.voi[ri].cl1; cl2=res.voi[ri].cl2;} else cl1=cl2=NULL;
492 ret=bootstrap(
493 0, cl1, cl2, sd,
494 res.voi[ri].parameter, pmin, pmax, fitframeNr,
495 // measured original TAC, not modified
496 dft.voi[ri].y,
497 // fitted TAC, not modified
498 dft.voi[ri].y2,
499 // tissue TAC noisy data is written to be used by objf
500 petmeas,
501 parNr, dft.w, cm2Func, tmp, verbose-4
502 );
503 if(ret) {
504 fprintf(stderr, "\nError in bootstrap: %s\n", tmp);
505 for(pi=0; pi<parNr; pi++) {
506 if(doSD) sd[pi]=nan("");
507 if(doCL) cl1[pi]=cl2[pi]=nan("");
508 }
509 }
510 }
511 /* Set very small parameter values to zero */
512 for(pi=0; pi<parNr; pi++)
513 if(fabs(res.voi[ri].parameter[pi])<1.0E-10) res.voi[ri].parameter[pi]=0.0;
514
515 /* Calculate AIC, based on nr of parameters that actually are fitted */
516 for(pi=n=0; pi<parNr; pi++) if(pmax[pi]>pmin[pi]) n++;
517 if(verbose>2) printf("nr_of_fitted_parameters := %d\n", n);
518 for(fi=m=0; fi<fitframeNr; fi++) if(dft.w[fi]>0.0) m++;
519 if(verbose>2) printf("nr_of_fitted_samples := %d\n", m);
520 aic=aicSS(wss, m, n);
521
522 /* Set results wss and aic */
523 res.voi[ri].parameter[res.parNr-2]=wss;
524 res.voi[ri].parameter[res.parNr-1]=aic;
525
526 /* done with this region */
527 if(dft.voiNr>2 && verbose==1) {fprintf(stdout, "."); fflush(stdout);}
528
529
530 } /* next region */
531 if(verbose>0) {fprintf(stdout, "\n"); fflush(stdout);}
532
533 /* Convert Vb fractions to percents */
534 for(ri=0; ri<res.voiNr; ri++){
535 res.voi[ri].parameter[2]*=100.0;
536 if(!isnan(res.voi[ri].cl1[2])) res.voi[ri].cl1[2]*=100.;
537 if(!isnan(res.voi[ri].cl2[2])) res.voi[ri].cl2[2]*=100.;
538 if(!isnan(res.voi[ri].sd[2])) res.voi[ri].sd[2]*=100.;
539 }
540 /* Calculate DVR, BPnd or BPp */
541 if(bp_type==1 || bp_type==2) {
542 if(fabs(res.voi[ref].parameter[1])>1.0E-10)
543 for(ri=0; ri<res.voiNr; ri++) {
544 res.voi[ri].parameter[res.parNr-3]=
545 res.voi[ri].parameter[1]/res.voi[ref].parameter[1];
546 if(bp_type==2) res.voi[ri].parameter[res.parNr-3]-=1.0;
547 }
548 else
549 for(ri=0; ri<res.voiNr; ri++)
550 res.voi[ri].parameter[res.parNr-3]=0.0;
551 }
552 if(bp_type==3) {
553 for(ri=0; ri<res.voiNr; ri++)
554 res.voi[ri].parameter[res.parNr-3]=
555 res.voi[ri].parameter[1]-res.voi[ref].parameter[1];
556 }
557
558 /*
559 * Print results on screen
560 */
561 if(verbose>0) {resPrint(&res); fprintf(stdout, "\n");}
562
563
564 /*
565 * Save results
566 */
567 if(verbose>1) printf("saving results\n");
568 ret=resWrite(&res, rfile, verbose-3);
569 if(ret) {
570 fprintf(stderr, "Error in writing '%s': %s\n", rfile, reserrmsg);
571 dftEmpty(&dft); dftEmpty(&input); resEmpty(&res);
572 return(11);
573 }
574 if(verbose>0) fprintf(stdout, "Model parameters written in %s\n", rfile);
575
576
577 /*
578 * Saving and/or plotting of fitted TACs
579 */
580 if(svgfile[0] || ffile[0]) {
581
582 /* Create a DFT containing fitted TACs */
583 char tmp[64];
584 DFT dft2;
585 dftInit(&dft2); ret=dftdup(&dft, &dft2);
586 if(ret) {
587 fprintf(stderr, "Error: cannot save fitted curves.\n");
588 dftEmpty(&dft); dftEmpty(&input); resEmpty(&res);
589 return(21);
590 }
591 for(ri=0; ri<dft.voiNr; ri++) for(fi=0; fi<fitframeNr; fi++)
592 dft2.voi[ri].y[fi]=dft2.voi[ri].y2[fi];
593 dft2.frameNr=fitframeNr;
594
595 /* Save SVG plot of fitted and original data */
596 if(svgfile[0]) {
597 if(verbose>1) printf("saving SVG plot\n");
598 sprintf(tmp, "1-tissue CM fit: ");
599 if(strlen(dft.studynr)>0) strcat(tmp, dft.studynr);
600 /*fi=dft.frameNr; dft.frameNr=fitframeNr; if(fi>dft.frameNr) dft.frameNr++;
601 ret=plot_fit_svg(&dft, &dft2, tmp, svgfile); dft.frameNr=fi;*/
602 ret=plot_fitrange_svg(&dft, &dft2, tmp, 0.0, 1.02*dft.x[fitframeNr-1],
603 0.0, nan(""), svgfile, verbose-8);
604 if(ret) {
605 fprintf(stderr, "Error (%d) in writing '%s'.\n", ret, svgfile);
606 dftEmpty(&dft2); dftEmpty(&dft); dftEmpty(&input); resEmpty(&res);
607 return(30+ret);
608 }
609 if(verbose>0) printf("Plots written in %s\n", svgfile);
610 }
611
612 /* Delete reference region(s) from the data */
613 if(refAdded!=0) {
614 for(ri=dft2.voiNr-1; ri>=0; ri--) if(dft2.voi[ri].sw!=0)
615 dftDelete(&dft2, ri);
616 }
617
618 /* Save fitted TACs */
619 if(ffile[0]) {
620 if(verbose>1) printf("saving fitted curves\n");
621 tpcProgramName(argv[0], 1, 0, tmp, 64);
622 sprintf(dft2.comments, "# program := %s\n", tmp);
623 if(dftWrite(&dft2, ffile)) {
624 fprintf(stderr, "Error in writing '%s': %s\n", ffile, dfterrmsg);
625 dftEmpty(&dft2); dftEmpty(&dft); dftEmpty(&input); resEmpty(&res);
626 return(22);
627 }
628 if(verbose>0) printf("Fitted TACs written in %s\n", ffile);
629 }
630
631 dftEmpty(&dft2);
632 }
633
634 dftEmpty(&dft); dftEmpty(&input); resEmpty(&res);
635 return(0);
636}
637/*****************************************************************************/
638
639/*****************************************************************************
640 *
641 * Functions to be minimized
642 *
643 *****************************************************************************/
644double cm2Func(int parNr, double *p, void *fdata)
645{
646 int fi, ret;
647 double k2, Vb, d, wss=0.0;
648 double pa[MAX_PARAMETERS], penalty=1.0;
649
650
651 /* Check parameters against the constraints */
652 ret=modelCheckParameters(parNr, pmin, pmax, p, pa, &penalty);
653 if(fdata) {}
654 /* Calculate k2 and Vb */
655 if(pa[1]>0.0) k2=pa[0]/pa[1]; else k2=0.0;
656 if(fVb>=0.0) Vb=fVb; else Vb=pa[2];
657
658 /* Simulate the tissue PET TAC */
659 ret=simC3vs(
660 input.x, input.voi[0].y, input.voi[1].y, input.frameNr,
661 pa[0], k2, 0, 0, 0, 0, 0.0, Vb, 1.0,
662 input.voi[0].y2, NULL, NULL, NULL, NULL, NULL);
663 if(ret) {
664 printf("error %d in simulation\n", ret);
665 return(nan(""));
666 }
667
668 /* Interpolate & integrate to measured PET frames */
670 ret=interpolate4pet(
671 input.x, input.voi[0].y2, input.frameNr,
672 dft.x1, dft.x2, petsim, NULL, NULL, fitframeNr);
673 else
674 ret=interpolate(
675 input.x, input.voi[0].y2, input.frameNr,
676 dft.x, petsim, NULL, NULL, fitframeNr);
677 if(ret) {
678 printf("error %d in interpolation\n", ret);
679 return(nan(""));
680 }
681
682 /* Calculate error */
683 for(fi=0; fi<fitframeNr; fi++) if(dft.w[fi]>0.0) {
684 d=petmeas[fi]-petsim[fi];
685 wss+=dft.w[fi]*d*d;
686 }
687 wss_wo_penalty=wss;
688 wss*=penalty;
689 if(0) printf("%g %g %g => %g\n", pa[0], k2, pa[2], wss);
690
691 return(wss);
692}
693/*****************************************************************************/
694
695/*****************************************************************************/
double aicSS(double ss, const int n, const int k)
Definition aic.c:20
int bootstrap(int iterNr, double *cLim1, double *cLim2, double *SD, double *parameter, double *lowlim, double *uplim, int frameNr, double *origTac, double *fitTac, double *bsTac, int parNr, double *weight, double(*objf)(int, double *, void *), char *status, int verbose)
Definition bootstrap.c:55
int modelCheckParameters(int par_nr, double *lower_p, double *upper_p, double *test_p, double *accept_p, double *penalty)
Definition constraints.c:15
int atof_with_check(char *double_as_string, double *result_value)
Definition decpoint.c:107
double atof_dpi(char *str)
Definition decpoint.c:59
void dftInit(DFT *data)
Definition dft.c:38
int dftdup(DFT *dft1, DFT *dft2)
Definition dft.c:655
char dfterrmsg[64]
Definition dft.c:6
int dftAddmem(DFT *dft, int voiNr)
Definition dft.c:107
int dftDelete(DFT *dft, int voi)
Definition dft.c:538
void dftEmpty(DFT *data)
Definition dft.c:20
int dftReadReference(DFT *tissue, char *filename, int *filetype, int *ref_index, char *status, int verbose)
Definition dftinput.c:204
int dftReadModelingData(char *tissuefile, char *inputfile1, char *inputfile2, char *inputfile3, double *fitdur, int *fitframeNr, DFT *tis, DFT *inp, FILE *loginfo, int verbose, char *status)
Definition dftinput.c:342
void dftPrint(DFT *data)
Definition dftio.c:538
int dftWrite(DFT *data, char *filename)
Definition dftio.c:594
int res_allocate_with_dft(RES *res, DFT *dft)
Definition dftres.c:14
int iftPutDouble(IFT *ift, char *key, double value, char *cmt_type, int verbose)
Definition ift.c:145
void iftEmpty(IFT *ift)
Definition ift.c:60
void iftInit(IFT *ift)
Definition ift.c:45
int iftRead(IFT *ift, char *filename, int is_key_required, int verbose)
Definition iftfile.c:24
int iftWrite(IFT *ift, char *filename, int verbose)
Definition iftfile.c:282
int iftGetDoubleValue(IFT *ift, int si, const char *key, double *value, int verbose)
Definition iftsrch.c:268
int interpolate(double *x, double *y, int nr, double *newx, double *newy, double *newyi, double *newyii, int newnr)
Linear interpolation and integration.
Definition integr.c:28
int interpolate4pet(double *x, double *y, int nr, double *newx1, double *newx2, double *newy, double *newyi, double *newyii, int newnr)
Interpolate and integrate TAC to PET frames.
Definition integr.c:510
Header file for libtpccurveio.
char reserrmsg[64]
Definition result.c:6
void resInit(RES *res)
Definition result.c:52
void resPrint(RES *res)
Definition result.c:186
int resWrite(RES *res, char *filename, int verbose)
Definition result.c:565
#define DFT_TIME_STARTEND
void resEmpty(RES *res)
Definition result.c:22
Header file for libtpcmisc.
int tpcProcessStdOptions(const char *s, int *print_usage, int *print_version, int *verbose_level)
Definition proginfo.c:40
size_t strlcpy(char *dst, const char *src, size_t dstsize)
Definition strext.c:245
void tpcProgramName(const char *program, int version, int copyright, char *prname, int n)
Definition proginfo.c:101
int tpcHtmlUsage(const char *program, char *text[], const char *path)
Definition proginfo.c:213
void tpcPrintBuild(const char *program, FILE *fp)
Definition proginfo.c:383
void tpcPrintUsage(const char *program, char *text[], FILE *fp)
Definition proginfo.c:158
Header file for libtpcmodel.
int simC3vs(double *t, double *ca, double *cb, int nr, double k1, double k2, double k3, double k4, double k5, double k6, double f, double vb, double fa, double *cpet, double *cta, double *ctb, double *ctc, double *ctab, double *ctvb)
Definition simulate.c:243
int tgo(double *lowlim, double *uplim, double(*objf)(int, double *, void *), void *objfData, int dim, int neighNr, double *fmin, double *gmin, int samNr, int tgoNr, int verbose)
Definition tgo.c:39
int TGO_LOCAL_INSIDE
Definition tgo.c:29
#define MAX_PARAMETERS
Definition libtpcmodel.h:31
int TGO_SQUARED_TRANSF
Definition tgo.c:27
Header file for libtpcmodext.
int plot_fitrange_svg(DFT *dft1, DFT *dft2, char *main_title, double x1, double x2, double y1, double y2, char *fname, int verbose)
Definition plotfit.c:16
Header file for libtpcsvg.
int timetype
Voi * voi
int timeunit
char studynr[MAX_STUDYNR_LEN+1]
double * w
double * x1
char comments[_DFT_COMMENT_LEN+1]
int voiNr
double * x2
int frameNr
int isweight
double * x
const char * status
Definition libtpcmisc.h:277
int parNr
char parname[MAX_RESPARAMS][MAX_RESPARNAME_LEN+1]
int voiNr
int datanr
ResVOI * voi
double Vb
char program[1024]
char plasmafile[FILENAME_MAX]
char datarange[128]
int isweight
char datafile[FILENAME_MAX]
char reffile[FILENAME_MAX]
char fitmethod[128]
char refroi[64]
char parunit[MAX_RESPARAMS][MAX_RESPARNAME_LEN+1]
char bloodfile[FILENAME_MAX]
time_t time
double parameter[MAX_RESPARAMS]
double cl2[MAX_RESPARAMS]
double cl1[MAX_RESPARAMS]
double sd[MAX_RESPARAMS]
double * y2
char voiname[MAX_REGIONSUBNAME_LEN+1]
char sw
double * y
char name[MAX_REGIONNAME_LEN+1]
double * y3