TPCCLIB
Loading...
Searching...
No Matches
b2t_mo2.c
Go to the documentation of this file.
1
8/*****************************************************************************/
9#include "tpcclibConfig.h"
10/*****************************************************************************/
11#include <stdio.h>
12#include <stdlib.h>
13#include <string.h>
14#include <math.h>
15/*****************************************************************************/
16#include "libtpcmisc.h"
17#include "libtpcmodel.h"
18#include "libtpccurveio.h"
19#include "libtpcmodext.h"
20/*****************************************************************************/
21
22/*****************************************************************************/
23static char *info[] = {
24 "Simulation of PET tissue time-radioactivity concentration curve (TTAC)",
25 "in skeletal muscle [O-15]O2 PET studies from decay corrected arterial blood",
26 "[O-15]O2 and [O-15]H2O curves (oxygen and water BTACs).",
27 "The compartmental model for [O-15]O2 in skeletal muscle is:",
28 " ",
29 " Blood Muscle ",
30 " _______________________________________ ",
31 " | K1 | | ",
32 " | O ----------> O + O -Mb | ",
33 " | 2 <---------- 2 2 | ",
34 " | k2 | ",
35 " | | | k3 | ",
36 " | | V | ",
37 " | K1 | | ",
38 " | H O ----------> H O | ",
39 " | 2 <---------- 2 | ",
40 " | | K1/pH2O | ",
41 " |______________|________________________| ",
42 " ",
43 "Model definitions:",
44 " K1=perfusion (f, mL/min/dL), OER=k3/(k2+k3),",
45 " Ki=f*OER (mL/min/dL), and",
46 " Metabolic rate of oxygen MRO2=Ki*[O2]a (mmol/min/dL)",
47 " ",
48 "Usage: @P [options] obtacfile wbtacfile f OER ttacfile",
49 " ",
50 "Options:",
51 " -sub | -nosub",
52 " TACs of sub-compartments are written (-sub)",
53 " or not written (-nosub, default) into the output file.",
54 " -add",
55 " Simulated TACs are added to an existing tissue data file.",
56 " By default, existing file is overwritten.",
57 " -Vb=<Blood volume (%)>",
58 " Set the simulated blood volume; default is 3.5%.",
59 " -Af=<Arterial proportion (%)>",
60 " Set the simulated arterial proportion of total blood volume;",
61 " default is 30%.",
62 " -pH2O=<value>",
63 " Set the partition coefficient of water; default is 0.99.",
64 " -K1k2=<value>",
65 " Set the K1/k2 for oxygen; by default the K1/k2 is estimated from",
66 " OER and saturation curves for hemoglobin and myoglobin.",
67 " -Sao2=<value>",
68 " Saturation of arterial blood hemoglobin; default is 0.97.",
69 " -p50Hb=<value>",
70 " Half-saturation pressure for hemoglobin; default is 3.6 kPa.",
71 " -p50Mb=<value>",
72 " Half-saturation pressure for myoglobin; default is 0.319 kPa.",
73 " -nHb=<value>",
74 " Hill coefficient for hemoglobin; default is 2.7.",
75 " -Mb=<value>",
76 " Concentration of myoglobin in muscle; default is 4.7 mg/g.",
77 " -Hb=<value>",
78 " Concentration of hemoglobin in blood; default is 150 mg/g.",
79 " -fpt",
80 " Blood flow (perfusion) is assumed to be given per perfusable tissue",
81 " volume excluding vascular volume. TTAC will still be simulated per",
82 " regional PET volume including vascular volume.",
83 " -voiname=<text>",
84 " Enter a name (1-6 chars without spaces) for the simulated TTAC.",
85 " -venao=<filename>",
86 " Save the simulated venous [O-15]O2 BTAC",
87 " -venaw=<filename>",
88 " Save the simulated venous [O-15]H2O BTAC",
89 " -stdoptions", // List standard options like --help, -v, etc
90 " ",
91 "For accurate results, input BTACs should be noiseless and have very",
92 "short sampling intervals. Simulated curves can thereafter be interpolated",
93 "to represent PET frames using program simframe.",
94 "Calculated tissue activities are written in the specified file with",
95 "these data columns. Columns 2-6 will be saved optionally (-sub):",
96 " 0) Time",
97 " 1) Total regional radioactivity concentration (2+3+4+5+6)",
98 " 2) Labelled [O2] component of TTAC",
99 " 3) Labelled [H2O] component of TTAC",
100 " 4) Arterial BTAC component of TTAC",
101 " 5) Venous labelled [O2] component of TTAC",
102 " 6) Venous labelled [H2O] component of TTAC",
103 " ",
104 "References:",
105 "1. Nuutila P, Peltoniemi P, Oikonen V, Larmola K, Kemppainen J, Takala T,",
106 " Sipila H, Oksanen A, Ruotsalainen U, Bolli GB, Yki-Jarvinen H.",
107 " Enhanced stimulation of glucose uptake by insulin increases",
108 " exercise-stimulated glucose uptake in skeletal muscle in humans: studies",
109 " using [15O]O2, [15O]H2O, [18F]fluoro-deoxy-glucose, and positron emission",
110 " tomography. Diabetes 2000; 49:1084-1091.",
111 "2. Oikonen V, Nuutila P, Sipila H, Tolvanen T, Peltoniemi P, Ruotsalainen U.",
112 " Quantification of oxygen consumption in skeletal muscle with PET and",
113 " oxygen-15 bolus. Eur J Nucl Med. 1998; 25: 1151.",
114 "3. Oikonen V. Modelling of low oxygen consumption. In: J. Knuuti, J. Rinne,",
115 " P.Tenhonen (ed.), Medical Applications of Cyclotrons VIII. Abstracts of",
116 " the VIII Symposium on the Medical Applications of Cyclotrons.",
117 " Annales Universitatis Turkuensis D346:16, 1999.",
118 " ",
119 "See also: fit_mo2, o2metab, o2_p2w, fit_o2bl, sim_o2bl, tacadd, simframe",
120 " ",
121 "Keywords: TAC, simulation, modelling, oxygen, skeletal muscle",
122 0};
123/*****************************************************************************/
124
125/*****************************************************************************/
126/* Turn on the globbing of the command line, since it is disabled by default in
127 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
128 In Unix&Linux wildcard command line processing is enabled by default. */
129/*
130#undef _CRT_glob
131#define _CRT_glob -1
132*/
133int _dowildcard = -1;
134/*****************************************************************************/
135
136/*****************************************************************************/
140int main(int argc, char **argv)
141{
142 int ai, help=0, version=0, verbose=1;
143 char ofile[FILENAME_MAX], wfile[FILENAME_MAX], dfile[FILENAME_MAX];
144 char vofile[FILENAME_MAX], vwfile[FILENAME_MAX];
145 char *cptr, voiname[MAX_REGIONNAME_LEN+1];
146 int save_only_total=1;
147 int flow_per_tissue=0;
148 int add_to_previous=0;
149 int K1k2_def_changed=0;
151 double fK1k2;
153 double Af=0.30;
155 double Vb=0.035;
157 double pH2O=0.99;
159 double Flow;
161 double OER;
163 double SaO2=DEFAULT_SAO2;
165 double p50Hb=DEFAULT_P50HB;
167 double p50Mb=DEFAULT_P50MB;
169 double nHb=DEFAULT_NHB;
171 double cHb=DEFAULT_CHB;
173 double cMb=DEFAULT_CMB;
174
175 DFT data, input;
176 int n, ret, times_changed=0;
177
178
179 /*
180 * Get arguments
181 */
182 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
183 ofile[0]=wfile[0]=dfile[0]=vofile[0]=vwfile[0]=(char)0;
184 strcpy(voiname, "Muscle");
185 fK1k2=Flow=OER=nan("");
186 dftInit(&input); dftInit(&data);
187 /* Options */
188 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') {
189 cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(cptr==NULL) continue;
190 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
191 if(strncasecmp(cptr, "NOSUB", 5)==0) {
192 save_only_total=1; continue;
193 } else if(strncasecmp(cptr, "SUB", 3)==0) {
194 save_only_total=0; continue;
195 } else if(strcasecmp(cptr, "FPT")==0) {
196 flow_per_tissue=1; continue;
197 } else if(strcasecmp(cptr, "ADD")==0) {
198 add_to_previous=1; continue;
199 } else if(strncasecmp(cptr, "VOINAME=", 8)==0) {
200 n=strlcpy(voiname, cptr+8, MAX_REGIONNAME_LEN);
201 if(n<1 || n>=MAX_REGIONNAME_LEN) {
202 fprintf(stderr, "Error: invalid VOI name '%s'.\n", cptr+8); return(1);}
203 continue;
204 } else if(strncasecmp(cptr, "VENAO=", 6)==0) {
205 n=strlcpy(vofile, cptr+6, FILENAME_MAX);
206 if(n>0 && n<FILENAME_MAX) continue;
207 } else if(strncasecmp(cptr, "VENAW=", 6)==0) {
208 n=strlcpy(vwfile, cptr+6, FILENAME_MAX);
209 if(n>0 && n<FILENAME_MAX) continue;
210 } else if(strncasecmp(cptr, "Vb=", 3)==0) {
211 if(!atof_with_check(cptr+3, &Vb)) {Vb*=0.01; continue;}
212 } else if(strncasecmp(cptr, "Af=", 3)==0) {
213 if(!atof_with_check(cptr+3, &Af)) {Af*=0.01; continue;}
214 } else if(strncasecmp(cptr, "pH2O=", 5)==0) {
215 if(!atof_with_check(cptr+5, &pH2O)) continue;
216 } else if(strncasecmp(cptr, "K1k2=", 5)==0) {
217 if(!atof_with_check(cptr+5, &fK1k2)) continue;
218 } else if(strncasecmp(cptr, "sao2=", 5)==0) {
219 if(!atof_with_check(cptr+5, &SaO2)) {K1k2_def_changed=1; continue;}
220 } else if(strncasecmp(cptr, "p50hb=", 6)==0) {
221 if(!atof_with_check(cptr+5, &p50Hb)) {K1k2_def_changed=1; continue;}
222 } else if(strncasecmp(cptr, "p50mb=", 6)==0) {
223 if(!atof_with_check(cptr+5, &p50Mb)) {K1k2_def_changed=1; continue;}
224 } else if(strncasecmp(cptr, "nhb=", 4)==0) {
225 if(!atof_with_check(cptr+5, &nHb)) {K1k2_def_changed=1; continue;}
226 } else if(strncasecmp(cptr, "hb=", 3)==0) {
227 if(!atof_with_check(cptr+5, &cHb)) {K1k2_def_changed=1; continue;}
228 } else if(strncasecmp(cptr, "mb=", 3)==0) {
229 if(!atof_with_check(cptr+5, &cMb)) {K1k2_def_changed=1; continue;}
230 }
231 fprintf(stderr, "Error: invalid option '%s'.\n", argv[ai]);
232 return(1);
233 } else break;
234
235 /* Print help or version? */
236 if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
237 if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
238 if(version) {tpcPrintBuild(argv[0], stdout); return(0);}
239
240 /* Process other arguments, starting from the first non-option */
241 for(; ai<argc; ai++) {
242 if(!ofile[0]) {strlcpy(ofile, argv[ai], FILENAME_MAX); continue;}
243 else if(!wfile[0]) {strlcpy(wfile, argv[ai], FILENAME_MAX); continue;}
244 else if(isnan(Flow)) {if(!atof_with_check(argv[ai], &Flow)) continue;}
245 else if(isnan(OER)) {if(!atof_with_check(argv[ai], &OER)) continue;}
246 else if(!dfile[0]) {strlcpy(dfile, argv[ai], FILENAME_MAX); continue;}
247 fprintf(stderr, "Error: invalid argument '%s'.\n", argv[ai]);
248 return(1);
249 }
250 Flow/=6000.;
251
252 /* Did we get all the information that we need? */
253 if(!dfile[0]) {
254 fprintf(stderr, "Error: missing command-line argument.\n\n");
255 tpcPrintUsage(argv[0], info, stdout); return(1);
256 }
257
258 /* Check parameters */
259 if(Af<0.0 || Af>1.0) {
260 fprintf(stderr, "Error: invalid arterial fraction.\n"); return(1);
261 }
262 if(Af>0.0 && Af<0.01) {
263 // check if user accidentally gave fraction instead of percentage
264 fprintf(stderr, "Warning: arterial fraction was set to %g%%.\n", 100.0*Af);
265 }
266 if(Vb<0.0 || Vb>=1.0) {
267 fprintf(stderr, "Error: invalid blood volume.\n"); return(1);
268 }
269 if(Vb>0.0 && Vb<0.01) {
270 // check if user accidentally gave fraction instead of percentage
271 fprintf(stderr, "Warning: arterial fraction was set to %g%%.\n", 100.0*Vb);
272 }
273 if(pH2O>1.0 || pH2O<=0.) {
274 fprintf(stderr, "Error: invalid partition constant for water.\n");
275 return(1);
276 }
277 if(OER>10.0 && OER<95.0) OER/=100.;
278 if(OER<=0.0 || OER>=1.0) {
279 fprintf(stderr, "Error: invalid OER.\n"); return(1);
280 }
281 if(K1k2_def_changed!=0 && fK1k2>0.0)
282 fprintf(stderr, "Warning: option(s) superseded by -K1k2.\n");
283 if(SaO2<=0.0 || SaO2>1.0) {
284 fprintf(stderr, "Error: invalid SaO2.\n"); return(1);
285 }
286 if(p50Hb<=0.0) {fprintf(stderr, "Error: invalid p50Hb.\n"); return(1);}
287 if(p50Mb<=0.0) {fprintf(stderr, "Error: invalid p50Mb.\n"); return(1);}
288 if(nHb<=0.0) {fprintf(stderr, "Error: invalid nHb.\n"); return(1);}
289 if(cMb<=0.0) {fprintf(stderr, "Error: invalid [Mb].\n"); return(1);}
290 if(cHb<=0.0) {fprintf(stderr, "Error: invalid [Hb].\n"); return(1);}
291
292
293 /* In verbose mode print arguments and options */
294 if(verbose>1) {
295 printf("save_only_total := %d\n", save_only_total);
296 printf("flow_per_tissue := %d\n", flow_per_tissue);
297 printf("add_to_previous := %d\n", add_to_previous);
298 printf("ofile := %s\n", ofile);
299 printf("wfile := %s\n", wfile);
300 printf("dfile := %s\n", dfile);
301 if(vofile[0]) printf("vofile := %s\n", vofile);
302 if(vwfile[0]) printf("vwfile := %s\n", vwfile);
303 printf("Vb := %g%%\n", 100.*Vb);
304 printf("Af := %g%%\n", 100.*Af);
305 printf("pH2O := %g\n", pH2O);
306 printf("Flow := %g mL/dL/min\n", 6000.*Flow);
307 printf("OER := %g\n", OER);
308 printf("SaO2 := %g\n", SaO2);
309 printf("p50Hb := %g\n", p50Hb);
310 printf("p50Mb := %g\n", p50Mb);
311 printf("nHb := %g\n", nHb);
312 printf("cMb := %g\n", cMb);
313 printf("cHb := %g\n", cHb);
314 if(!isnan(fK1k2)) printf("fK1k2 := %g\n", fK1k2);
315 if(voiname[0]) printf("voiname := %s\n", voiname);
316 }
317
318
319 /*
320 * Read input data
321 */
322 if(verbose>1) printf("reading '%s'\n", ofile);
323 if(dftRead(ofile, &input)) {
324 fprintf(stderr, "Error in reading '%s': %s\n", ofile, dfterrmsg);
325 return(2);
326 }
327 if(input.frameNr<3) {
328 fprintf(stderr, "Error: not enough input samples for decent simulation.\n");
329 dftEmpty(&input); return(2);
330 }
331 /* Sort the samples by time in case data is catenated from several curves */
332 (void)dftSortByFrame(&input);
333 /* Check for NA's */
334 if(dft_nr_of_NA(&input) > 0) {
335 fprintf(stderr, "Error: missing sample(s) in %s\n", ofile);
336 dftEmpty(&input); return(2);
337 }
338 if(input.voiNr>1) {
339 fprintf(stderr, "Warning: [O-15]O2 BTAC file may not be valid.\n");
340 input.voiNr=1;
341 }
342 /* If sample times are minutes, change them to sec */
343 if(input.timeunit!=TUNIT_SEC && input.timeunit!=TUNIT_MIN) {
344 if(input.x[input.frameNr-1]<20.) {
345 if(verbose>0) fprintf(stdout, "Note: sample times assumed to be in min.\n");
346 input.timeunit=TUNIT_MIN;
347 } else {
348 if(verbose>0) fprintf(stdout, "Note: sample times assumed to be in sec.\n");
349 input.timeunit=TUNIT_SEC;
350 }
351 }
352 if(input.timeunit==TUNIT_MIN) {
353 if(verbose>0)
354 fprintf(stderr, "Note: Oxygen BTAC sample times are converted to sec.\n");
355 dftMin2sec(&input);
356 times_changed=1;
357 }
358 /*
359 * Read H2O BTAC
360 */
361 if(verbose>1) printf("reading '%s'\n", wfile);
362 if(dftRead(wfile, &data)) {
363 fprintf(stderr, "Error in reading '%s': %s\n", wfile, dfterrmsg);
364 dftEmpty(&input); dftEmpty(&data); return(3);
365 }
366 if(data.frameNr<input.frameNr) {
367 fprintf(stderr, "Error: not enough samples for decent simulation.\n");
368 dftEmpty(&input); dftEmpty(&data); return(3);
369 }
370 /* Check for NA's */
371 if(dft_nr_of_NA(&data) > 0) {
372 fprintf(stderr, "Error: missing sample(s) in %s\n", wfile);
373 dftEmpty(&input); dftEmpty(&data); return(3);
374 }
375 /* Sort the samples by time in case data is catenated from several curves */
376 (void)dftSortByFrame(&data);
377 if(data.voiNr>1) {
378 fprintf(stderr, "Warning: [O-15]H2O BTAC file may not be valid.\n");
379 data.voiNr=1;
380 }
381 /* If sample times are minutes, change them to sec */
382 if(data.timeunit!=TUNIT_SEC && data.timeunit!=TUNIT_MIN) {
383 if(data.x[data.frameNr-1]<20.) {
384 if(verbose>0) fprintf(stdout, "Note: sample times assumed to be in min.\n");
385 data.timeunit=TUNIT_MIN;
386 } else {
387 if(verbose>0) fprintf(stdout, "Note: sample times assumed to be in sec.\n");
388 data.timeunit=TUNIT_SEC;
389 }
390 }
391 if(data.timeunit==TUNIT_MIN) {
392 if(verbose>0)
393 fprintf(stderr, "Note: Radiowater BTAC sample times are converted to sec.\n");
394 dftMin2sec(&data);
395 }
396 /* Check that water TAC is not much shorter than oxygen TAC */
397 if(data.x[data.frameNr-1]<0.75*input.x[input.frameNr-1]) {
398 fprintf(stderr, "Error: [O-15]H2O BTAC is shorter than [O-15]O2 BTAC.\n");
399 dftEmpty(&input); dftEmpty(&data); return(4);
400 }
401 if(data.x[data.frameNr-1]<0.95*input.x[input.frameNr-1])
402 fprintf(stderr, "Warning: [O-15]H2O BTAC is shorter than [O-15]O2 BTAC.\n");
403 /* Copy and interpolate water TAC to input TAC structure */
404 if(dftAddmem(&input, 1)) {
405 fprintf(stderr, "Error: cannot allocate more memory.\n");
406 dftEmpty(&input); dftEmpty(&data); return(4);
407 }
408 dftCopyvoihdr(&data, 0, &input, 1);
409 if(interpolate(data.x, data.voi[0].y, data.frameNr,
410 input.x, input.voi[1].y, NULL, NULL, input.frameNr))
411 {
412 fprintf(stderr, "Error: cannot interpolate [O-15]H2O BTAC.\n");
413 dftEmpty(&input); dftEmpty(&data); return(4);
414 }
415 input.voiNr=2;
416 /* Remove the originally read water data; pointer is re-used later */
417 dftEmpty(&data);
418 if(verbose>6) dftPrint(&input);
419
420
421 /* Integrate BTACs; integral will be more correct in case of frames */
422 ret=0;
423 for(int ri=0; ri<input.voiNr && !ret; ri++) {
424 if(input.timetype==DFT_TIME_STARTEND)
425 ret=petintegral(input.x1, input.x2, input.voi[ri].y,
426 input.frameNr, input.voi[ri].y2, NULL);
427 else
428 ret=integrate(input.x, input.voi[ri].y, input.frameNr, input.voi[ri].y2);
429 }
430 if(ret) {
431 fprintf(stderr, "Error: Cannot integrate input BTACs.\n");
432 dftEmpty(&input); return(5);
433 }
434
435
436 /*
437 * Allocate memory for tissue data
438 */
439 if(verbose>1) printf("allocating memory for simulated data\n");
440 if(dftSetmem(&data, input.frameNr, 6)) {
441 fprintf(stderr, "Error: cannot allocate memory for simulated TTACs.\n");
442 dftEmpty(&input); return(6);
443 }
444 data.frameNr=input.frameNr; data.voiNr=6;
445 dftCopymainhdr(&input, &data);
446 data._type=DFT_FORMAT_PMOD; // fileformat
447 strcpy(data.isotope, "O-15");
448 strcpy(data.radiopharmaceutical, "[O-15]O2");
449 strcpy(data.injectionTime, input.injectionTime);
450 strcpy(data.scanStartTime, input.scanStartTime);
452 /* Copy times */
453 for(int fi=0; fi<input.frameNr; fi++) {
454 data.x[fi]=input.x[fi];
455 data.x1[fi]=input.x1[fi]; data.x2[fi]=input.x2[fi];
456 }
457 /* Set TTAC names */
458 strcpy(data.voi[0].hemisphere, "Total");
459 strcpy(data.voi[1].hemisphere, "O2");
460 strcpy(data.voi[2].hemisphere, "H2O");
461 strcpy(data.voi[3].hemisphere, "artery");
462 strcpy(data.voi[4].hemisphere, "vena"); strcpy(data.voi[4].place, "O2");
463 strcpy(data.voi[5].hemisphere, "vena"); strcpy(data.voi[5].place, "H2O");
464 n=rnameSplit(voiname, data.voi[0].voiname, data.voi[0].hemisphere,
466 for(int ri=1; ri<data.voiNr; ri++) {
467 strcpy(data.voi[ri].voiname, data.voi[0].voiname);
468 if(n>1) strcpy(data.voi[ri].hemisphere, data.voi[0].hemisphere);
469 if(n>2) strcpy(data.voi[ri].place, data.voi[0].place);
470 }
471 for(int ri=0; ri<data.voiNr; ri++)
473 data.voi[ri].hemisphere, data.voi[ri].place, '_');
474
475
476 /*
477 * Simulate the TTACs
478 */
479 if(verbose>1) printf("simulating TTACs\n");
480 double k1=Flow; if(flow_per_tissue==0) k1/=(1.0-Vb);
481 double k2w=k1/pH2O;
482 double k1k2;
483 if(!isnan(fK1k2)) k1k2=fK1k2;
484 else k1k2=mo2k1k2(OER, SaO2, p50Hb, p50Mb, nHb, cHb, cMb, verbose-1);
485 double k2o=k1/k1k2;
486 double k3=k2o*OER/(1.0-OER);
487 if(verbose>0) {
488 double v;
489 if((k2o+k3)>0.0) {
490 printf("Vt_o := %g\n", k1/(k2o+k3));
491 v=k1*k3/(k2o+k3);
492 printf("K1*k3/(k2+k3) := %g\n", v);
493 } else {
494 v=0.0;
495 }
496 if(k2w>0.0) printf("Vt_w := %g\n", (v+k1)/k2w);
497 }
498 ret=simOxygen(
499 input.x, input.voi[0].y, input.voi[1].y, input.voi[0].y2, input.voi[1].y2,
500 input.frameNr, k1, k2o, k3, k1, k2w, Vb, Af,
501 data.voi[0].y, data.voi[1].y, data.voi[2].y, data.voi[3].y,
502 data.voi[4].y, data.voi[5].y, data.voi[4].y2, data.voi[5].y2,
503 verbose-1
504 );
505 dftEmpty(&input);
506 if(ret!=0) {
507 fprintf(stderr, "Error in simulation (%d).\n", ret);
508 dftEmpty(&data); return(9);
509 }
510
511
512
513
514 /*
515 * Save simulated tissue TAC
516 */
517 if(verbose>1) printf("saving simulated TTAC.\n");
518 if(times_changed) dftSec2min(&data);
520 if(save_only_total!=0) data.voiNr=1;
521 dftSetComments(&data);
522 if(add_to_previous!=0 && access(dfile, 0)!=-1) {
523 if(verbose>0) printf("adding to existing file\n");
524 DFT prevdft;
525 /* read previous file */
526 dftInit(&prevdft);
527 if(dftRead(dfile, &prevdft)) {
528 fprintf(stderr, "Error in reading '%s': %s\n", dfile, dfterrmsg);
529 dftEmpty(&prevdft); dftEmpty(&data); return(2);
530 }
531 if(verbose>2)
532 printf("existing %d TACs with %d frames\n",prevdft.voiNr,prevdft.frameNr);
533 /* add present simulations */
534 for(int ri=0; ri<data.voiNr; ri++) {
535 ret=dftAdd(&prevdft, &data, ri);
536 if(ret) {
537 fprintf(stderr, "Error: cannot add simulated TAC in %s\n", dfile);
538 dftEmpty(&prevdft); dftEmpty(&data); return(13);
539 }
540 }
541 /* save that */
542 ret=dftWrite(&prevdft, dfile);
543 /* Clear it from memory */
544 dftEmpty(&prevdft);
545 } else {
546 /* Set file format to PMOD, if extension is .tac */
547 if(!strcasecmp(filenameGetExtension(dfile), ".tac")) data._type=DFT_FORMAT_PMOD;
548 /* save only present simulations */
549 ret=dftWrite(&data, dfile);
550 }
551 if(ret) {
552 fprintf(stderr, "Error in writing '%s': %s\n", dfile, dfterrmsg);
553 dftEmpty(&data);
554 return(12);
555 }
556 if(verbose>=0) fprintf(stdout, "Simulated TTAC(s) written in %s\n", dfile);
557
558
559 /*
560 * Save simulated BTACs if requested
561 */
562 data.voi[0].voiname[0]=data.voi[0].hemisphere[0]=data.voi[0].place[0]=(char)0;
563 data.voiNr=1;
564 if(vofile[0]) {
565 for(int i=0; i<data.frameNr; i++) data.voi[0].y[i]=data.voi[4].y2[i];
566 strcpy(data.voi[0].name, "Venous_O2");
567 if(dftWrite(&data, vofile)) {
568 fprintf(stderr, "Error in writing '%s': %s\n", vofile, dfterrmsg);
569 dftEmpty(&data); return(21);
570 }
571 if(verbose>0)
572 fprintf(stdout, "Simulated venous [O-15]O2 BTAC written in %s\n", vofile);
573 }
574 if(vwfile[0]) {
575 for(int i=0; i<data.frameNr; i++) data.voi[0].y[i]=data.voi[5].y2[i];
576 strcpy(data.voi[0].name, "Venous_H2O");
577 if(dftWrite(&data, vwfile)) {
578 fprintf(stderr, "Error in writing '%s': %s\n", vwfile, dfterrmsg);
579 dftEmpty(&data); return(22);
580 }
581 if(verbose>0)
582 fprintf(stdout, "Simulated venous [O-15]H2O BTAC written in %s\n", vwfile);
583 }
584
585 dftEmpty(&data);
586 return(0);
587}
588/*****************************************************************************/
589
590/*****************************************************************************/
592
int atof_with_check(char *double_as_string, double *result_value)
Definition decpoint.c:107
int dftCopyvoihdr(DFT *dft1, int from, DFT *dft2, int to)
Definition dft.c:623
void dftInit(DFT *data)
Definition dft.c:38
char dfterrmsg[64]
Definition dft.c:6
int dftAddmem(DFT *dft, int voiNr)
Definition dft.c:107
void dftSetComments(DFT *dft)
Definition dft.c:1326
int dftSortByFrame(DFT *dft)
Definition dft.c:1169
int dftSetmem(DFT *data, int frameNr, int voiNr)
Definition dft.c:57
int dftAdd(DFT *data1, DFT *data2, int voi)
Definition dft.c:188
void dftEmpty(DFT *data)
Definition dft.c:20
int dft_nr_of_NA(DFT *dft)
Definition dft.c:905
int dftCopymainhdr(DFT *dft1, DFT *dft2)
Definition dft.c:561
int dftRead(char *filename, DFT *data)
Definition dftio.c:22
int DFT_NR_OF_DECIMALS
Definition dftio.c:13
void dftPrint(DFT *data)
Definition dftio.c:538
int dftWrite(DFT *data, char *filename)
Definition dftio.c:594
void dftSec2min(DFT *dft)
Definition dftunit.c:160
void dftMin2sec(DFT *dft)
Definition dftunit.c:145
char * filenameGetExtension(char *s)
Get the last extension of a filename.
Definition filename.c:139
int petintegral(double *x1, double *x2, double *y, int nr, double *ie, double *iie)
Integrate PET TAC data to frame mid times.
Definition integr.c:771
int integrate(double *x, double *y, int nr, double *yi)
Definition integr.c:271
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
Header file for libtpccurveio.
#define DFT_FORMAT_PMOD
#define DFT_DECAY_CORRECTED
#define DFT_TIME_STARTEND
Header file for libtpcmisc.
int tpcProcessStdOptions(const char *s, int *print_usage, int *print_version, int *verbose_level)
Definition proginfo.c:40
int rnameCatenate(char *rname, int max_rname_len, char *name1, char *name2, char *name3, char space)
Definition rname.c:189
int rnameSplit(char *rname, char *name1, char *name2, char *name3, int max_name_len)
Definition rname.c:14
#define MAX_REGIONNAME_LEN
Definition libtpcmisc.h:154
size_t strlcpy(char *dst, const char *src, size_t dstsize)
Definition strext.c:245
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
#define MAX_REGIONSUBNAME_LEN
Definition libtpcmisc.h:158
void tpcPrintUsage(const char *program, char *text[], FILE *fp)
Definition proginfo.c:158
Header file for libtpcmodel.
int simOxygen(double *t, double *ca1, double *ca2, double *ca1i, double *ca2i, const int n, const double k1a, const double k2a, const double km, const double k1b, const double k2b, const double vb, const double fa, double *scpet, double *sct1, double *sct2, double *sctab, double *sctvb1, double *sctvb2, double *scvb1, double *scvb2, const int verbose)
Definition simulate.c:1978
#define DEFAULT_NHB
#define DEFAULT_CMB
#define DEFAULT_CHB
double mo2k1k2(const double OER, const double SaO2, const double p50Hb, const double p50Mb, const double nHb, const double cHb, const double cMb, const int verbose)
Calculates K1/k2 ratio for [O-15]O2 in muscle, based on OER.
Definition o2.c:29
#define DEFAULT_P50HB
#define DEFAULT_P50MB
#define DEFAULT_SAO2
Header file for libtpcmodext.
double p50Mb
Definition o2.c:16
double nHb
Definition o2.c:18
double p50Hb
Definition o2.c:14
double cHb
Definition o2.c:20
double SaO2
Definition o2.c:12
double cMb
Definition o2.c:22
char scanStartTime[20]
char decayCorrected
int _type
int timetype
Voi * voi
int timeunit
double * x1
int voiNr
double * x2
char injectionTime[20]
int frameNr
char isotope[8]
double * x
char radiopharmaceutical[32]
double * y2
char voiname[MAX_REGIONSUBNAME_LEN+1]
double * y
char name[MAX_REGIONNAME_LEN+1]
char hemisphere[MAX_REGIONSUBNAME_LEN+1]
char place[MAX_REGIONSUBNAME_LEN+1]