TPCCLIB
Loading...
Searching...
No Matches
sim_o2bl.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 <unistd.h>
13#include <string.h>
14#include <math.h>
15/*****************************************************************************/
16#include "libtpcmisc.h"
17#include "libtpcmodel.h"
18#include "libtpccurveio.h"
19/*****************************************************************************/
20
21/*****************************************************************************/
22static char *info[] = {
23 "Simulates the [O-15]H2O BTAC from [O-15]O2 BTAC applying a dedicated",
24 "[O-15]O2 metabolite model (1, 2, 3).",
25 " ",
26 "Usage: @P [Options] otacfile parameterfile wtacfile",
27 " ",
28 "Options:",
29 " -stdoptions", // List standard options like --help, -v, etc
30 " ",
31 "Model parameters for k3 model (k1, k1+k3, delay) or k4 model (k1, k3,",
32 "k3/k4, delay) can be given in a RES or IFT file made by program fit_o2bl.",
33 "Parameters and data units are assumed to be in seconds, in case units",
34 "are not given in the files.",
35 " ",
36 " ",
37 "References:",
38 "1. Huang S-C et al. Modelling approach for separating blood time-activity",
39 " curves in positron emission tomographic studies.",
40 " Phys Med Biol. 1991;36(6):749-761.",
41 "2. Iida H et al. Modelling approach to eliminate the need to separate",
42 " arterial plasma in oxygen-15 inhalation positron emission tomography.",
43 " J Nucl Med. 1993;34:1333-1340.",
44 "3. Kudomi N et al. A physiologic model for recirculation water correction",
45 " in CMRO2 assessment with 15O2 inhalation PET.",
46 " J Cereb Blood Flow Metab. 2009;29(2):355-364.",
47 " ",
48 "See also: fit_o2bl, o2metab, o2_p2w, fit_mo2, b2t_mo2, taccalc, tac2svg",
49 " ",
50 "Keywords: input, oxygen, blood, metabolite correction",
51 0};
52/*****************************************************************************/
53
54/*****************************************************************************/
55/* Turn on the globbing of the command line, since it is disabled by default in
56 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
57 In Unix&Linux wildcard command line processing is enabled by default. */
58/*
59#undef _CRT_glob
60#define _CRT_glob -1
61*/
62int _dowildcard = -1;
63/*****************************************************************************/
64
65/*****************************************************************************/
69int main(int argc, char **argv)
70{
71 int ai, help=0, version=0, verbose=1;
72 int ret;
73 char oxyfile[FILENAME_MAX], parfile[FILENAME_MAX], watfile[FILENAME_MAX];
74 double k1, k2, k3, k4, delay, k3k4, k1k3;
75 DFT blood, sim;
76 RES res;
77 IFT ift;
78
79
80 /*
81 * Get arguments
82 */
83 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
84 dftInit(&blood); dftInit(&sim); resInit(&res); iftInit(&ift);
85 parfile[0]=oxyfile[0]=watfile[0]=(char)0;
86 k1=k2=k3=k4=k3k4=k1k3=nan(""); delay=0.0;
87 /* Options */
88 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') {
89 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
90 //cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(cptr==NULL) continue;
91 fprintf(stderr, "Error: invalid option '%s'.\n", argv[ai]);
92 return(1);
93 } else break;
94
95 /* Print help or version? */
96 if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
97 if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
98 if(version) {tpcPrintBuild(argv[0], stdout); return(0);}
99
100 /* Process other arguments, starting from the first non-option */
101 for(; ai<argc; ai++) {
102 if(!oxyfile[0]) {strlcpy(oxyfile, argv[ai], FILENAME_MAX); continue;}
103 if(!parfile[0]) {strlcpy(parfile, argv[ai], FILENAME_MAX); continue;}
104 if(!watfile[0]) {strlcpy(watfile, argv[ai], FILENAME_MAX); continue;}
105 fprintf(stderr, "Error: too many arguments: '%s'.\n", argv[ai]);
106 return(1);
107 }
108
109 /* Is something missing? */
110 if(!watfile[0]) {
111 fprintf(stderr, "Error: missing command-line argument; use option --help\n");
112 return(1);
113 }
114
115 /* In verbose mode print arguments and options */
116 if(verbose>1) {
117 printf("oxyfile := %s\n", oxyfile);
118 printf("parfile := %s\n", parfile);
119 printf("watfile := %s\n", watfile);
120 }
121
122 /* Read parameter file */
123 if(verbose>1) printf("reading parameters in %s\n", parfile);
124 /* First, try RES format */
125 if(resRead(parfile, &res, verbose-2)==0) {
126 if(verbose>2) printf("result format\n");
127 ret=res2ift(&res, &ift, verbose-3);
128 resEmpty(&res);
129 if(ret) {
130 fprintf(stderr, "Error in converting results.\n");
131 dftEmpty(&blood); dftEmpty(&sim); iftEmpty(&ift);
132 return(3);
133 }
134 /* If not RES then try IFT */
135 } else if(iftRead(&ift, parfile, 1, 0)==0) {
136 if(verbose>2) printf("ift format\n");
137 } else {
138 fprintf(stderr, "Error: cannot read '%s'\n", parfile);
139 dftEmpty(&blood); dftEmpty(&sim); iftEmpty(&ift);
140 return(2);
141 }
142 /* Now try to find the required parameters */
143 int i, n; char key[12]; double v; int u; char buf1[128], buf2[128];
144 /* k1 */
145 strcpy(key, "k1"); i=iftGet(&ift, key, 0);
146 if(i<0) {
147 fprintf(stderr, "Error: k1 not found in '%s'.\n", parfile);
148 dftEmpty(&blood); dftEmpty(&sim); iftEmpty(&ift);
149 return(4);
150 }
151 n=sscanf(ift.item[i].value, "%128s %128s", buf1, buf2);
152 if(n==0 || atof_with_check(buf1, &v)) {
153 fprintf(stderr, "Error: valid k1 not found in '%s'.\n", parfile);
154 dftEmpty(&blood); dftEmpty(&sim); iftEmpty(&ift);
155 return(4);
156 }
157 if(n>1) {u=petCunitId(buf2); if(u==CUNIT_PER_MIN) v/=60.0;}
158 k1=v; if(verbose>2) printf("k1 := %g\n", k1);
159 /* delay; if not found, keep it at zero */
160 strcpy(key, "delay"); i=iftGet(&ift, key, 0);
161 if(i<0) {strcpy(key, "delayt"); i=iftGet(&ift, key, 0);}
162 if(i<0) {strcpy(key, "timedelay"); i=iftGet(&ift, key, 0);}
163 if(i>=0) {
164 n=sscanf(ift.item[i].value, "%128s %128s", buf1, buf2);
165 if(n==0 || atof_with_check(buf1, &v)) {
166 fprintf(stderr, "Error: valid delay not found in '%s'.\n", parfile);
167 dftEmpty(&blood); dftEmpty(&sim); iftEmpty(&ift);
168 return(4);
169 }
170 if(n>1) {u=petTunitId(buf2); if(u==TUNIT_MIN) v*=60.0;}
171 delay=v; if(verbose>2) printf("delay := %g\n", k1);
172 }
173 /* k3 */
174 strcpy(key, "k3"); i=iftGet(&ift, key, 0);
175 if(i>=0) {
176 n=sscanf(ift.item[i].value, "%128s %128s", buf1, buf2);
177 if(n>0 && !atof_with_check(buf1, &v)) {
178 if(n>1) {u=petCunitId(buf2); if(u==CUNIT_PER_MIN) v/=60.0;}
179 k3=v; if(verbose>2) printf("k3 := %g\n", k3);
180 }
181 }
182 /* k3/k4 */
183 strcpy(key, "k3/k4"); i=iftGet(&ift, key, 0);
184 if(i>=0) {
185 n=sscanf(ift.item[i].value, "%128s %128s", buf1, buf2);
186 if(n>0 && !atof_with_check(buf1, &v)) {
187 k3k4=v; if(verbose>2) printf("k3/k4 := %g\n", k3k4);
188 }
189 }
190 /* k1+k3 */
191 strcpy(key, "k1+k3"); i=iftGet(&ift, key, 0);
192 if(i>=0) {
193 n=sscanf(ift.item[i].value, "%128s %128s", buf1, buf2);
194 if(n>0 && !atof_with_check(buf1, &v)) {
195 if(n>1) {u=petCunitId(buf2); if(u==CUNIT_PER_MIN) v/=60.0;}
196 k1k3=v; if(verbose>2) printf("k1+k3 := %g\n", k1k3);
197 }
198 }
199 /* check what we got */
200 k2=0.0;
201 if(isnan(k3) && isnan(k1k3)) {
202 fprintf(stderr, "Error: missing k3 or k1+k3 in '%s'.\n", parfile);
203 dftEmpty(&blood); dftEmpty(&sim); iftEmpty(&ift);
204 return(4);
205 }
206 if(!isnan(k3)) {
207 if(isnan(k3k4)) {
208 fprintf(stderr, "Error: missing k3/k4 in '%s'.\n", parfile);
209 dftEmpty(&blood); dftEmpty(&sim); iftEmpty(&ift);
210 return(4);
211 }
212 if(k3k4<=1.0E-100) k4=0.0; else k4=k3/k3k4;
213 }
214 if(isnan(k3)) {k3=k1k3-k1; k4=0.0;}
215 if(verbose>1) {
216 printf("k2 := %g\n", k2);
217 printf("k3 := %g\n", k3);
218 printf("k4 := %g\n", k4);
219 }
220 if(k1<0.0 || k3<0.0 || k4<0.0) {
221 fprintf(stderr, "Error: invalid parameter value(s) in '%s'.\n", parfile);
222 dftEmpty(&blood); dftEmpty(&sim); iftEmpty(&ift);
223 return(4);
224 }
225 iftEmpty(&ift);
226
227
228 /*
229 * Read [O-15]O2 blood file
230 */
231 if(verbose>1) printf("reading %s\n", oxyfile);
232 if(dftRead(oxyfile, &blood)) {
233 fprintf(stderr, "Error in reading '%s': %s\n", oxyfile, dfterrmsg);
234 return(5);
235 }
236 if(blood.voiNr>1) {
237 blood.voiNr=1;
238 fprintf(stderr, "Warning: input file contains extra column(s).\n");
239 }
240 if(blood.frameNr<3) {
241 fprintf(stderr, "Error: blood data not valid.\n");
242 dftEmpty(&blood); dftEmpty(&sim);
243 return(5);
244 }
245 /* Make sure that sample times are in seconds */
246 int times_changed=0;
247 if(blood.timeunit==TUNIT_UNKNOWN && blood.x[blood.frameNr-1]<15.0) {
248 fprintf(stderr, "Warning: assuming that BTAC sample times are in minutes.\n");
249 blood.timeunit=TUNIT_MIN;
250 }
251 if(blood.timeunit==TUNIT_MIN) {
252 dftMin2sec(&blood); times_changed=1;
253 }
254
255
256 /*
257 * Allocate memory for simulated water TACs
258 */
259 if(dftdup(&blood, &sim)) {
260 fprintf(stderr, "Error: cannot allocate memory for simulated TACs.\n");
261 dftEmpty(&blood); dftEmpty(&sim);
262 return(6);
263 }
264 strcpy(sim.voi[0].hemisphere, ""); strcpy(sim.voi[0].place, "");
265
266 /*
267 * Simulate the water TAC
268 */
269 if(verbose>1) printf("simulating\n");
270 ret=simC3s(blood.x, blood.voi[0].y, blood.frameNr, k1, k2, k3, k4, 0, 0,
271 blood.voi[0].y2, blood.voi[0].y3, NULL, NULL);
272 if(ret) {
273 fprintf(stderr, "Error in simulation of metabolism (%d).\n", ret);
274 dftEmpty(&blood); dftEmpty(&sim); return(7);
275 }
276 /* Correct simulated water TAC for delay */
277 for(int i=0; i<blood.frameNr; i++) blood.x1[i]=blood.x[i]+delay;
279 ret=interpolate(blood.x1, blood.voi[0].y3, blood.frameNr, sim.x,
280 sim.voi[0].y, sim.voi[0].y2, NULL, sim.frameNr);
281 if(ret) {
282 fprintf(stderr, "Error in simulation of delay (%d).\n", ret);
283 dftEmpty(&blood); dftEmpty(&sim); return(8);
284 }
285 /* Write the file */
286 if(verbose>1) printf("writing O15-water TAC in %s\n", watfile);
287 if(times_changed) dftSec2min(&sim);
288 strcpy(sim.voi[0].voiname, "Water");
289 strcpy(sim.voi[0].name, sim.voi[0].voiname);
290 if(dftWrite(&sim, watfile)) {
291 fprintf(stderr, "Error in writing '%s': %s\n", watfile, dfterrmsg);
292 dftEmpty(&blood); dftEmpty(&sim); return(11);
293 }
294 if(verbose==1) printf("O15-water BTAC written in %s\n", watfile);
295
296
297 dftEmpty(&blood); dftEmpty(&sim);
298 return(0);
299}
300/*****************************************************************************/
301
302/*****************************************************************************/
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
void dftEmpty(DFT *data)
Definition dft.c:20
int dftRead(char *filename, DFT *data)
Definition dftio.c:22
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
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 iftGet(IFT *ift, char *key, int verbose)
Definition iftsrch.c:15
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.
void resInit(RES *res)
Definition result.c:52
#define DFT_TIME_MIDDLE
int resRead(char *filename, RES *res, int verbose)
Definition result.c:199
int res2ift(RES *res, IFT *ift, int verbose)
Definition resift.c:14
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
int petCunitId(const char *unit)
Definition petunits.c:74
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
int petTunitId(const char *timeunit)
Definition petunits.c:187
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 simC3s(double *t, double *ca, int nr, double k1, double k2, double k3, double k4, double k5, double k6, double *ct, double *cta, double *ctb, double *ctc)
Definition simulate.c:27
int timetype
Voi * voi
int timeunit
double * x1
int voiNr
int frameNr
double * x
IFT_KEY_AND_VALUE * item
Definition libtpcmisc.h:279
double * y2
char voiname[MAX_REGIONSUBNAME_LEN+1]
double * y
char name[MAX_REGIONNAME_LEN+1]
double * y3
char hemisphere[MAX_REGIONSUBNAME_LEN+1]
char place[MAX_REGIONSUBNAME_LEN+1]