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