TPCCLIB
Loading...
Searching...
No Matches
fit_frtm.c
Go to the documentation of this file.
1
9/*****************************************************************************/
10#include "tpcclibConfig.h"
11/*****************************************************************************/
12#include <stdio.h>
13#include <stdlib.h>
14#include <math.h>
15#include <unistd.h>
16#include <string.h>
17#include <time.h>
18/*****************************************************************************/
19#include "libtpcmisc.h"
20#include "libtpcmodel.h"
21#include "libtpccurveio.h"
22#include "libtpcsvg.h"
23#include "libtpcmodext.h"
24/*****************************************************************************/
25
26/*****************************************************************************/
27const int parNr=4;
28int fitframeNr=0;
29double *t, *cr, *ct, *tis, *w; /* These are pointers, not allocated */
30double pmin[MAX_PARAMS], pmax[MAX_PARAMS];
31double wss_wo_penalty=0.0;
32/* Local functions */
33double frtmFunc(int parNr, double *p, void*);
34/*****************************************************************************/
35
36/*****************************************************************************/
37static char *info[] = {
38 "NLLSQ estimation of R1 (=K1/K1'), k2, k3, and BPnd (binding potential)",
39 "using the (full) reference tissue compartment model, FRTM/RTCM (1,3).",
40 "Assumption is that K1/k2 is the same in all brain regions, but 1TCM with",
41 "plasma input does not need to fit the tissue curves satisfactorily",
42 "as is assumed in SRTM (2), and Cref(t) is not assumed to be the same as",
43 "Cfree(t) as is assumed in the ratio methods.",
44 " ",
45 "Usage: @P [Options] ttacfile reference endtime resultfile",
46 " ",
47 "TTAC file can be in DFT or PMOD format. Sample times must be in minutes.",
48 "If TTAC file contains weights, those are used in the NLLSQ fitting.",
49 "Reference region TAC can be given separate TAC file or as the name or number",
50 "of the reference region in TTAC file.",
51 " ",
52 "Options:",
53 " -DVR",
54 " Instead of BPnd, program saves the DVR (=BPnd+1) values.",
55 " -lim=<filename>",
56 " Specify the constraints for model parameters;",
57 " This file with default values can be created by giving this option",
58 " as the only command-line argument to this program.",
59 " -SD[=<y|N>]",
60 " Standard deviations are calculated and saved in results (y), or",
61 " not calculated (n).",
62 " -CL[=<y|N>]",
63 " 95% Confidence limits are calculated and saved in results (y), or",
64 " not calculated (n).",
65 " -w1",
66 " All weights are set to 1.0 (no weighting); by default, weights in",
67 " TTAC file are used, if available.",
68 " -wf",
69 " Weight by sampling interval.",
70 " -fit=<Filename>",
71 " Fitted regional TACs are written in file.",
72 " -svg=<Filename>",
73 " Fitted and measured TACs are plotted in specified SVG file.",
74 " -stdoptions", // List standard options like --help, -v, etc
75 " ",
76 " ",
77 "Values of R1, k2, k3, and BPnd are written in the specified result file.",
78 "Fitted curves are written in DFT format, if file name is given.",
79 " ",
80 "Example 1: file a789.tac contains regions-of-interest and reference region,",
81 "with name 'cereb all'. The whole time range is used in the fit.",
82 " @P a789.tac 'cereb all' 999 a789.res",
83 " ",
84 "Example 2: Reference region TAC is in a separate file, a789ref.tac;",
85 "standard deviations and confidence limits are also estimated.",
86 " @P -SD=y -CL=y a789.tac a789ref.tac 999 a789.res",
87 " ",
88 "References:",
89 "1. Cunningham VJ, Hume SP, Price GR, Ahier RG, Cremer JE, Jones AKP.",
90 " Compartmental analysis of diprenorphine binding to opiate receptors",
91 " in the rat in vivo and its comparison with equilibrium data in vitro.",
92 " J Cereb Blood Flow Metab 1991;11:1-9.",
93 "2. Lammertsma AA, Hume SP. Simplified reference tissue model for PET",
94 " receptor studies. Neuroimage 1996;4:153-158.",
95 "3. Oikonen V, Sederholm K. TPCMOD0002: Model equations for reference tissue",
96 " compartmental models. https://www.turkupetcentre.net/reports/tpcmod0002.pdf",
97 " ",
98 "See also: bfmsrtm, tacweigh, rescoll, logan, fit_srtm, sim_rtcm",
99 " ",
100 "Keywords: TAC, modelling, binding potential, RTCM, reference input",
101 0};
102/*****************************************************************************/
103
104/*****************************************************************************/
105/* Turn on the globbing of the command line, since it is disabled by default in
106 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
107 In Unix&Linux wildcard command line processing is enabled by default. */
108/*
109#undef _CRT_glob
110#define _CRT_glob -1
111*/
112int _dowildcard = -1;
113/*****************************************************************************/
114
115/*****************************************************************************/
119int main(int argc, char **argv)
120{
121 int ai, help=0, version=0, verbose=1;
122 char rtacfile[FILENAME_MAX], ttacfile[FILENAME_MAX], resfile[FILENAME_MAX],
123 fitfile[FILENAME_MAX], svgfile[FILENAME_MAX], limfile[FILENAME_MAX];
124 char *cptr, tmp[256];
125 double fitdur=nan("");
126 int weights=0; // 0=default, 1=no weighting, 2=frequency
127 int doDVR=0;
128 int doBootstrap=0, doSD=0, doCL=0;
129 double *sd, *cl1, *cl2;
130 double def_pmin[MAX_PARAMETERS], def_pmax[MAX_PARAMETERS];
131 int ret, n;
132
133
134 /* Set parameter initial values and constraints */
135 /* R1 */ def_pmin[0]=0.001; def_pmax[0]=10.0;
136 /* k2 */ def_pmin[1]=0.000001; def_pmax[1]=1.0;
137 /* k3 */ def_pmin[2]=0.0; def_pmax[2]=1.0;
138 /* BP */ def_pmin[3]=0.0; def_pmax[3]=60.0; // may be reset later
139
140 /*
141 * Get arguments
142 */
143 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
144 rtacfile[0]=ttacfile[0]=resfile[0]=fitfile[0]=svgfile[0]=limfile[0]=(char)0;
145 /* Get options first, because it affects what arguments are read */
146 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') {
147 cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(cptr==NULL) continue;
148 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
149 if(strncasecmp(cptr, "CL", 2)==0) {
150 if(strlen(cptr)==2) {doCL=1; continue;}
151 cptr+=2; if(*cptr=='=') {
152 cptr++;
153 if(*cptr=='Y' || *cptr=='y') {doCL=1; continue;}
154 if(*cptr=='N' || *cptr=='n') {doCL=0; continue;}
155 }
156 } else if(strncasecmp(cptr, "SD", 2)==0) {
157 if(strlen(cptr)==2) {doSD=1; continue;}
158 cptr+=2; if(*cptr=='=') {
159 cptr++;
160 if(*cptr=='Y' || *cptr=='y') {doSD=1; continue;}
161 if(*cptr=='N' || *cptr=='n') {doSD=0; continue;}
162 }
163 } else if(strncasecmp(cptr, "LIM=", 4)==0 && strlen(cptr)>4) {
164 strlcpy(limfile, cptr+4, FILENAME_MAX); continue;
165 } else if(strcasecmp(cptr, "LIM")==0) {
166 strcpy(limfile, "stdout"); continue;
167 } else if(strcasecmp(cptr, "DVR")==0) {
168 doDVR=1; continue;
169 } else if(strcasecmp(cptr, "W1")==0) {
170 weights=1; continue;
171 } else if(strcasecmp(cptr, "WF")==0) {
172 weights=2; continue;
173 } else if(strncasecmp(cptr, "FIT=", 4)==0) {
174 strlcpy(fitfile, cptr+4, FILENAME_MAX); if(strlen(fitfile)>0) continue;
175 } else if(strncasecmp(cptr, "SVG=", 4)==0) {
176 strlcpy(svgfile, cptr+4, FILENAME_MAX); if(strlen(svgfile)>0) continue;
177 }
178 fprintf(stderr, "Error: invalid option '%s'.\n", argv[ai]);
179 return(1);
180 } else break;
181
182 /* Print help or version? */
183 if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
184 if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
185 if(version) {tpcPrintBuild(argv[0], stdout); return(0);}
186
187 /* Process other arguments, starting from the first non-option */
188 if(ai<argc) strlcpy(ttacfile, argv[ai++], FILENAME_MAX);
189 if(ai<argc) strlcpy(rtacfile, argv[ai++], FILENAME_MAX);
190 if(ai<argc) {
191 if(atof_with_check(argv[ai], &fitdur)!=0 || fitdur<0.0) {
192 fprintf(stderr, "Error: invalid fit time: '%s'.\n", argv[ai]);
193 return(1);
194 }
195 if(fitdur==0) fitdur=1.0E+10;
196 ai++;
197 }
198 if(ai<argc) strlcpy(resfile, argv[ai++], FILENAME_MAX);
199 if(ai<argc) {
200 fprintf(stderr, "Error: invalid argument '%s'.\n", argv[ai]);
201 return(1);
202 }
203 if(doSD || doCL) doBootstrap=1; else doBootstrap=0;
204
205 /* In verbose mode print arguments and options */
206 if(verbose>1) {
207 printf("ttacfile := %s\n", ttacfile);
208 printf("reference := %s\n", rtacfile);
209 printf("resfile := %s\n", resfile);
210 printf("fitfile := %s\n", fitfile);
211 printf("svgfile := %s\n", svgfile);
212 printf("limfile := %s\n", limfile);
213 printf("required_fittime := %g min\n", fitdur);
214 printf("weights := %d\n", weights);
215 printf("doDVR := %d\n", doDVR);
216 printf("doBootstrap := %d\n", doBootstrap);
217 printf("doSD := %d\n", doSD);
218 printf("doCL := %d\n", doCL);
219 }
220
221 /* If only file name for parameter constraints was given, then write one
222 with default contents, and exit */
223 if(limfile[0] && !ttacfile[0]) {
224 /* Check that initial value file does not exist */
225 if(strcasecmp(limfile, "stdout")!=0 && access(limfile, 0) != -1) {
226 fprintf(stderr, "Error: parameter constraint file %s exists.\n", limfile);
227 return(9);
228 }
229 if(verbose>1 && strcasecmp(limfile, "stdout")!=0)
230 printf("writing parameter constraints file\n");
231 /* Create parameter file */
232 IFT ift; iftInit(&ift);
233 iftPutDouble(&ift, "R1_lower", def_pmin[0], NULL, 0);
234 iftPutDouble(&ift, "R1_upper", def_pmax[0], NULL, 0);
235 iftPutDouble(&ift, "k2_lower", def_pmin[1], NULL, 0);
236 iftPutDouble(&ift, "k2_upper", def_pmax[1], NULL, 0);
237 iftPutDouble(&ift, "k3_lower", def_pmin[2], NULL, 0);
238 iftPutDouble(&ift, "k3_upper", def_pmax[2], NULL, 0);
239 iftPutDouble(&ift, "BP_lower", def_pmin[3], NULL, 0);
240 iftPutDouble(&ift, "BP_upper", def_pmax[3], NULL, 0);
241 ret=iftWrite(&ift, limfile, 0);
242 if(ret) {
243 fprintf(stderr, "Error in writing '%s': %s\n", limfile, ift.status);
244 iftEmpty(&ift); return(9);
245 }
246 if(strcasecmp(limfile, "stdout")!=0)
247 fprintf(stdout, "Parameter file %s with initial values written.\n", limfile);
248 iftEmpty(&ift); return(0);
249 }
250
251
252 /* Did we get all the information that we need? */
253 if(!resfile[0]) {
254 fprintf(stderr, "Error: missing command-line argument; use option --help\n");
255 return(1);
256 }
257
258 /*
259 * Read model parameter upper and lower limits
260 * if file for that was given
261 */
262 if(limfile[0]) {
263 if(verbose>1) printf("reading %s\n", limfile);
264 IFT ift; iftInit(&ift);
265 double v;
266 ret=iftRead(&ift, limfile, 1, 0);
267 if(ret) {
268 fprintf(stderr, "Error in reading '%s': %s\n", limfile, ift.status);
269 return(9);
270 }
271 if(verbose>10) iftWrite(&ift, "stdout", 0);
272 int n=0;
273 if(iftGetDoubleValue(&ift, 0, "R1_lower", &v, 0)>=0) {def_pmin[0]=v; n++;}
274 if(iftGetDoubleValue(&ift, 0, "R1_upper", &v, 0)>=0) {def_pmax[0]=v; n++;}
275 if(iftGetDoubleValue(&ift, 0, "k2_lower", &v, 0)>=0) {def_pmin[1]=v; n++;}
276 if(iftGetDoubleValue(&ift, 0, "k2_upper", &v, 0)>=0) {def_pmax[1]=v; n++;}
277 if(iftGetDoubleValue(&ift, 0, "k3_lower", &v, 0)>=0) {def_pmin[2]=v; n++;}
278 if(iftGetDoubleValue(&ift, 0, "k3_upper", &v, 0)>=0) {def_pmax[2]=v; n++;}
279 if(iftGetDoubleValue(&ift, 0, "BP_lower", &v, 0)>=0) {def_pmin[3]=v; n++;}
280 if(iftGetDoubleValue(&ift, 0, "BP_upper", &v, 0)>=0) {def_pmax[3]=v; n++;}
281 iftEmpty(&ift);
282 if(n==0) {fprintf(stderr, "Error: invalid parameter file.\n"); return(9);}
283 }
284 /* Check that these are ok */
285 n=0; ret=0;
286 for(int pi=0; pi<parNr; pi++) {
287 if(verbose>3) printf(" %d %g %g\n", pi+1, def_pmin[pi], def_pmax[pi]);
288 if(def_pmin[pi]<0.0 && pi!=3) ret++; // Lower limit for BP can be negative
289 if(def_pmax[pi]<def_pmin[pi]) ret++;
290 if(def_pmax[pi]>def_pmin[pi]) n++;
291 if(verbose>3 && ret>0) printf(" -> invalid\n");
292 }
293 if(ret!=0) {
294 fprintf(stderr, "Error: invalid parameter constraints.\n");
295 return(9);
296 }
297 if(n==0) {
298 fprintf(stderr, "Error: no model parameters left free for fitting.\n");
299 return(9);
300 }
301 if(verbose>1) {
302 printf("Parameter constraints:\n");
303 for(int pi=0; pi<parNr; pi++) {
304 printf("def_pmin[%d] := %g\n", pi+1, def_pmin[pi]);
305 printf("def_pmax[%d] := %g\n", pi+1, def_pmax[pi]);
306 }
307 }
308
309
310
311 /*
312 * Read TTAC file
313 */
314 if(verbose>1) printf("reading %s\n", ttacfile);
315 DFT dft; dftInit(&dft);
316 if(dftRead(ttacfile, &dft)) {
317 fprintf(stderr, "Error in reading '%s': %s\n", ttacfile, dfterrmsg);
318 return(2);
319 }
320 /* Check for NA's */
321 if(dft_nr_of_NA(&dft) > 0) {
322 fprintf(stderr, "Error: missing sample(s) in %s\n", ttacfile);
323 dftEmpty(&dft); return(2);
324 }
325 /* Sort the data by increasing sample times */
326 dftSortByFrame(&dft);
327 /* Set time unit to min */
328 ret=dftTimeunitConversion(&dft, TUNIT_MIN);
329 if(ret) fprintf(stderr, "Warning: check that regional data times are in minutes.\n");
330 /* Remove frame overlaps and gaps */
331 if(dft.timetype==DFT_TIME_STARTEND) {
332 if(verbose>2) fprintf(stdout, "checking frame overlap in %s\n", ttacfile);
333 ret=dftDeleteFrameOverlap(&dft);
334 if(ret) {
335 fprintf(stderr, "Error: %s has overlapping frame times.\n", ttacfile);
336 dftEmpty(&dft); return(2);
337 }
338 }
339 /* Set fit duration */
340 int first, last;
341 double starttime, endtime;
342 starttime=0.0; endtime=fitdur;
343 fitframeNr=fittime_from_dft(&dft, &starttime, &endtime, &first, &last, verbose-2);
344 if(fitframeNr<5) {
345 fprintf(stderr, "Error: too few data points for a decent fit.\n");
346 dftEmpty(&dft); return(2);
347 }
348 if(verbose>2) {
349 printf("dft.frameNr := %d\n", dft.frameNr);
350 printf("starttime := %g\n", starttime);
351 printf("endtime := %g\n", endtime);
352 printf("first := %d\n", first);
353 printf("last := %d\n", last);
354 printf("fitframeNr := %d\n", fitframeNr);
355 }
356 fitdur=endtime;
357 /* Check that there is not any significant delay in the beginning of the data */
358 if(dft.timetype==DFT_TIME_STARTEND) {
359 if(dft.x1[0]>0.45) {
360 fprintf(stderr, "Error: TACs must start at time zero.\n");
361 dftEmpty(&dft); return(2);
362 }
363 if(dft.x1[0]>0.0833333) {
364 fprintf(stderr, "Warning: TACs should start at time zero.\n");
365 }
366 }
367 if(verbose>2) printf("Tissue calibration unit := %s\n", dft.unit);
368
369 /* Add data weights, if requested */
370 if(weights==1) {
371 dft.isweight=0;
372 for(int i=0; i<dft.frameNr; i++) dft.w[i]=1.0;
373 } else if(weights==2) {
374 if(dftWeightByFreq(&dft)!=0) {
375 fprintf(stderr, "Error: cannot set data weights.\n");
376 dftEmpty(&dft); return(2);
377 }
378 } else if(dft.isweight==0) {
379 fprintf(stderr, "Warning: data is not weighted.\n");
380 }
381 /* Print the weights */
382 if(verbose>2) {
383 fprintf(stdout, "common_data_weights := %g", dft.w[0]);
384 for(int i=1; i<dft.frameNr; i++) fprintf(stdout, ", %g", dft.w[i]);
385 fprintf(stdout, "\n");
386 }
387
388
389 /*
390 * Read reference TAC
391 */
392 if(verbose>1) printf("\nreading reference\n");
393 int inputtype=-1, ref=-1;
394 ret=dftReadReference(&dft, rtacfile, &inputtype, &ref, tmp, verbose-1);
395 if(ret<=0) {
396 fprintf(stderr, "Error in reading reference input: %s\n", tmp);
397 dftEmpty(&dft); if(verbose>1) printf("ret := %d\n", ret);
398 return(3);
399 }
400 if(ret>1) {
401 fprintf(stderr, "Warning: several reference regions found: %s selected.\n", dft.voi[ref].name);
402 } else if(verbose>1) printf("reference_region := %s\n", dft.voi[ref].name);
403 if(verbose>2) printf("inputtype := %d\n", inputtype);
404
405 /* Calculate tissue integrals to determine TAC-based constraints for BP value */
406 if(!limfile[0]) {
408 for(int ri=0; ri<dft.voiNr; ri++)
409 petintegrate(dft.x1, dft.x2, dft.voi[ri].y, fitframeNr, dft.voi[ri].y3, NULL);
410 else
411 for(int ri=0; ri<dft.voiNr; ri++)
412 integrate(dft.x, dft.voi[ri].y, fitframeNr, dft.voi[ri].y3);
413 }
414
415 /* Allocate an extra TAC for the bootstrap */
416 int bsi=-1;
417 if(doBootstrap) {
418 ret=dftAddmem(&dft, 1); if(ret) {
419 fprintf(stderr, "Error: cannot allocate more memory.\n");
420 dftEmpty(&dft); return(4);
421 }
422 bsi=dft.voiNr;
423 strcpy(dft.voi[bsi].voiname, "BS");
424 strcpy(dft.voi[bsi].name, "BS");
425 }
426
427
428
429 /*
430 * Prepare the room for results
431 */
432 if(verbose>1) printf("initializing result data\n");
433 RES res; resInit(&res);
434 ret=res_allocate_with_dft(&res, &dft); if(ret!=0) {
435 fprintf(stderr, "Error: cannot set-up memory for results.\n");
436 dftEmpty(&dft); return(4);
437 }
438 /* Copy titles & filenames */
439 tpcProgramName(argv[0], 1, 1, res.program, 256);
440 strcpy(res.datafile, ttacfile);
441 if(inputtype!=5 && rtacfile[0]) strcpy(res.reffile, rtacfile);
442 if(ref>=0) strcpy(res.refroi, dft.voi[ref].name);
443 strcpy(res.fitmethod, "TGO");
444 /* Constants */
445 res.isweight=dft.isweight;
446 /* Set data range */
447 sprintf(res.datarange, "%g - %g %s", 0.0, fitdur, petTunit(dft.timeunit));
448 res.datanr=fitframeNr;
449 /* Set current time to results */
450 res.time=time(NULL);
451 /* Set parameter number, including also the extra "parameters"
452 and the parameter names and units */
453 res.parNr=5;
454 {
455 int pi;
456 pi=0; strcpy(res.parname[pi], "R1"); strcpy(res.parunit[pi], "");
457 pi++; strcpy(res.parname[pi], "k2"); strcpy(res.parunit[pi], "1/min");
458 pi++; strcpy(res.parname[pi], "k3"); strcpy(res.parunit[pi], "1/min");
459 pi++; if(doDVR==0) strcpy(res.parname[pi], "BP"); else strcpy(res.parname[pi], "DVR");
460 strcpy(res.parunit[pi], "");
461 pi++; strcpy(res.parname[pi], "WSS"); strcpy(res.parunit[pi], "");
462 }
463
464
465
466
467 /*
468 * Fit one VOI at a time
469 */
470 if(verbose>0) printf("\nfitting...\n");
471 int tgoNr=0, neighNr=0, iterNr=0;
472 double wss;
473 /* Set common data pointers */
474 t=dft.x; cr=dft.voi[ref].y;
475 double refIntegral=dft.voi[ref].y3[fitframeNr-1];
476 /* Fit model to one TAC at a time */
477 for(int ri=0; ri<dft.voiNr; ri++) if(ri!=ref) {
478
479 if(verbose>1) printf("Region %d %s\n", ri+1, dft.voi[ri].name);
480 /* Set data pointers */
481 tis=dft.voi[ri].y; ct=dft.voi[ri].y2; w=dft.w;
482 double *p=res.voi[ri].parameter;
483
484 /* Set common parameter constraints */
485 for(int pi=0; pi<parNr; pi++) {pmin[pi]=def_pmin[pi]; pmax[pi]=def_pmax[pi];}
486 /* Set BP limits based on the integrals of roi and ref TACs
487 if those were not given in limfile */
488 if(!limfile[0] && refIntegral>0.0) {
489 double a, b, c;
490 a=(dft.voi[ri].y3[fitframeNr-1]/refIntegral);
491 if(a<1.0) a=1.0;
492 b=0.0*a; c=5.0*a;
493 pmin[3]=b; pmax[3]=c;
494 }
495 if(verbose>3) {
496 printf("Parameter constraints:\n");
497 for(int pi=0; pi<parNr; pi++) printf(" %10.3E - %10.3E\n", pmin[pi], pmax[pi]);
498 }
499
500 /* Fit */
501 if(verbose>2) printf(" fitting curve...\n");
504 tgoNr=260;
505 neighNr=20;
506 ret=tgo(pmin, pmax, frtmFunc, NULL, parNr, neighNr, &wss, p, tgoNr, iterNr, verbose-8);
507 if(ret>0) {
508 fprintf(stderr, "Error in optimization (%d).\n", ret);
509 dftEmpty(&dft); resEmpty(&res); return(6);
510 }
511 if(verbose>3) {
512 for(int pi=0; pi<parNr; pi++) printf(" %g", p[pi]);
513 printf(" -> WSS=%g\n", p[parNr]); fflush(stdout);
514 }
515 /* Correct fitted parameters to match constraints like inside the function */
516 (void)modelCheckParameters(parNr, pmin, pmax, p, p, NULL);
517 p[parNr]=wss=wss_wo_penalty;
518 if(verbose>2) printf("wss := %g\nfitframeNr := %d\n", wss, fitframeNr);
519
520 /* Bootstrap */
521 if(doBootstrap) {
522 if(verbose>2) printf(" bootstrapping...\n");
523 /* bootstrap changes measured and simulated data, therefore use copies */
524 tis=dft.voi[bsi].y; ct=dft.voi[bsi].y2;
525 if(doSD) sd=res.voi[ri].sd; else sd=NULL;
526 if(doCL) {cl1=res.voi[ri].cl1; cl2=res.voi[ri].cl2;} else cl1=cl2=NULL;
527 ret=bootstrap(
528 0, cl1, cl2, sd, p, pmin, pmax, fitframeNr,
529 // measured and fitted original TAC, not modified
530 dft.voi[ri].y, dft.voi[ri].y2,
531 // tissue TAC noisy data is written to be used by objf
532 tis,
533 parNr, w, frtmFunc, tmp, verbose-5
534 );
535 if(ret) {
536 fprintf(stderr, "Error in bootstrap: %s\n", tmp);
537 for(int pi=0; pi<parNr; pi++) {
538 if(doSD) sd[pi]=nan("");
539 if(doCL) cl1[pi]=cl2[pi]=nan("");
540 }
541 }
542 // back to what pointers were
543 tis=dft.voi[ri].y; tis=dft.voi[ri].y2;
544 }
545
546 } /* Next VOI */
547 if(verbose>0) {fprintf(stdout, "\n"); fflush(stdout);}
548
549 /* Delete the reference region from the results */
550 resDelete(&res, ref);
551 /* If reference data file was given and it contained several TACs then delete those too */
552 if(inputtype!=5) {
553 for(int i=dft.voiNr-1; i>=0; i--) if(dft.voi[i].sw!=0) resDelete(&res, i);
554 }
555
556 /*
557 * Convert BP to DVR, if necessary
558 */
559 if(doDVR!=0) {
560 if(verbose>1) printf("converting BP to DVR\n");
561 for(int ri=0; ri<res.voiNr; ri++) {
562 res.voi[ri].parameter[3]+=1.0;
563 if(doCL && !isnan(res.voi[ri].cl1[3])) res.voi[ri].cl1[3]+=1.0;
564 if(doCL && !isnan(res.voi[ri].cl2[3])) res.voi[ri].cl2[3]+=1.0;
565 }
566 }
567
568 /*
569 * Print results on screen
570 */
571 if(verbose>0) {resPrint(&res); fprintf(stdout, "\n");}
572
573
574 /*
575 * Save results
576 */
577 if(verbose>1) printf("saving results in %s\n", resfile);
578 ret=resWrite(&res, resfile, verbose-5);
579 if(ret) {
580 fprintf(stderr, "Error in writing '%s': %s\n", resfile, reserrmsg);
581 resEmpty(&res); dftEmpty(&dft);
582 return(11);
583 }
584 if(verbose>0) fprintf(stdout, "Model parameters written in %s\n", resfile);
585
586
587
588 /*
589 * Saving and/or plotting of fitted TACs
590 */
591 if(svgfile[0] || fitfile[0]) {
592
593 /* Create a DFT containing fitted TACs */
594 char tmp[64];
595 DFT dft2;
596 dftInit(&dft2); ret=dftdup(&dft, &dft2);
597 if(ret) {
598 fprintf(stderr, "Error: cannot save fitted curves.\n");
599 dftEmpty(&dft); resEmpty(&res);
600 return(21);
601 }
602 for(int ri=0; ri<dft.voiNr; ri++)
603 if(ri!=ref)
604 for(int fi=0; fi<fitframeNr; fi++)
605 dft2.voi[ri].y[fi]=dft2.voi[ri].y2[fi];
606 dft2.frameNr=fitframeNr;
607
608 /* Save SVG plot of fitted and original data */
609 if(svgfile[0]) {
610 if(verbose>1) printf("saving SVG plot\n");
611 sprintf(tmp, "FRTM fit ");
612 if(strlen(dft.studynr)>0) strcat(tmp, dft.studynr);
613 ret=plot_fitrange_svg(&dft, &dft2, tmp, 0.0, 1.02*dft.x[fitframeNr-1],
614 0.0, nan(""), svgfile, verbose-8);
615 if(ret) {
616 fprintf(stderr, "Error (%d) in writing '%s'.\n", ret, svgfile);
617 dftEmpty(&dft2); dftEmpty(&dft); resEmpty(&res);
618 return(30+ret);
619 }
620 if(verbose>0) printf("Plots written in %s\n", svgfile);
621 }
622
623 /* Delete reference region(s) from the data, unless it already existed in data */
624 if(inputtype!=5) {
625 for(int i=dft2.voiNr-1; i>=0; i--) if(dft2.voi[i].sw!=0) dftDelete(&dft2, i);
626 }
627
628 /* Save fitted TACs */
629 if(fitfile[0]) {
630 if(verbose>1) printf("saving fitted curves\n");
631 tpcProgramName(argv[0], 1, 0, tmp, 128);
632 sprintf(dft2.comments, "# program := %s\n", tmp);
633 if(dftWrite(&dft2, fitfile)) {
634 fprintf(stderr, "Error in writing '%s': %s\n", fitfile, dfterrmsg);
635 dftEmpty(&dft2); dftEmpty(&dft); resEmpty(&res);
636 return(22);
637 }
638 if(verbose>0) printf("Fitted TACs written in %s\n", fitfile);
639 }
640
641 dftEmpty(&dft2);
642 }
643
644
645 resEmpty(&res);
646 dftEmpty(&dft);
647
648 return(0);
649}
650/*****************************************************************************/
651
652/*****************************************************************************
653 *
654 * Functions to be minimized
655 *
656 *****************************************************************************/
657double frtmFunc(int parNr, double *p, void *fdata)
658{
659 int ret;
660 double R1, k2, k3, k4, BP, d, wss=0.0;
661 double pa[MAX_PARAMETERS], penalty=1.0;
662
663
664 /* Check parameters against the constraints */
665 ret=modelCheckParameters(parNr, pmin, pmax, p, pa, &penalty);
666 if(fdata) {}
667 /* Get parameters */
668 R1=pa[0]; k2=pa[1]; k3=pa[2]; BP=pa[3];
669 if(BP>0.0) k4=k3/BP; else k4=0.0;
670
671 /* Simulate the tissue PET TAC */
672 ret=simRTCM(t, cr, fitframeNr, R1, k2, k3, k4, ct, NULL, NULL);
673 if(ret) {
674 fprintf(stderr, " error %d in simulation\n", ret);
675 return(nan(""));
676 }
677
678 /* Calculate error */
679 for(int i=0; i<fitframeNr; i++) if(w[i]>0.0) {
680 d=ct[i]-tis[i];
681 wss+=w[i]*d*d;
682 }
683 wss_wo_penalty=wss;
684 wss*=penalty;
685 if(0) printf("R1=%g k2=%g k3=%g BP=%g => %g\n", R1, k2, k3, BP, wss);
686
687 return(wss);
688}
689/*****************************************************************************/
690
691/*****************************************************************************/
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
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 dftDeleteFrameOverlap(DFT *dft)
Definition dft.c:1237
int dftAddmem(DFT *dft, int voiNr)
Definition dft.c:107
int dftSortByFrame(DFT *dft)
Definition dft.c:1169
int dftDelete(DFT *dft, int voi)
Definition dft.c:538
void dftEmpty(DFT *data)
Definition dft.c:20
int dft_nr_of_NA(DFT *dft)
Definition dft.c:905
int dftReadReference(DFT *tissue, char *filename, int *filetype, int *ref_index, char *status, int verbose)
Definition dftinput.c:204
int dftRead(char *filename, DFT *data)
Definition dftio.c:22
int dftWrite(DFT *data, char *filename)
Definition dftio.c:594
int res_allocate_with_dft(RES *res, DFT *dft)
Definition dftres.c:14
int dftTimeunitConversion(DFT *dft, int tunit)
Definition dftunit.c:119
int fittime_from_dft(DFT *dft, double *startTime, double *endTime, int *first, int *last, int verbose)
Definition fittime.c:16
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 petintegrate(double *x1, double *x2, double *y, int nr, double *newyi, double *newyii)
Definition integr.c:334
int integrate(double *x, double *y, int nr, double *yi)
Definition integr.c:271
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
int resDelete(RES *res, int voi)
Definition result.c:1342
#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
char * petTunit(int tunit)
Definition petunits.c:226
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 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
#define MAX_PARAMS
Definition libtpcmodel.h:35
int simRTCM(double *t, double *cr, int nr, double R1, double k2, double k3, double k4, double *ct, double *cta, double *ctb)
Definition simulate.c:835
Header file for libtpcmodext.
int dftWeightByFreq(DFT *dft)
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
char unit[MAX_UNITS_LEN+1]
const char * status
Definition libtpcmisc.h:277
int parNr
char parname[MAX_RESPARAMS][MAX_RESPARNAME_LEN+1]
int voiNr
int datanr
ResVOI * voi
char program[1024]
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]
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