9#include "tpcclibConfig.h"
23static char *info[] = {
24 "Calculates the blood time-activity curves (BTACs) of labelled water and",
25 "oxygen from arterial blood TAC measured after [O-15]O2 bolus using",
26 "a dedicated [O-15]O2 metabolite model (1, 2, 3) to be used as input in",
29 "Usage: @P [Options] btacfile parameterfile obtacfile wtacfile",
34 "Model parameters for k3 model (k1, k1+k3, delay) or k4 model (k1, k3,",
35 "k3/k4, delay) can be given in a RES or IFT file made by program fit_o2bl.",
36 "Parameters and data units are assumed to be in seconds, in case units",
37 "are not given in the files.",
40 "1. Huang S-C et al. Modelling approach for separating blood time-activity",
41 " curves in positron emission tomographic studies.",
42 " Phys Med Biol. 1991;36(6):749-761.",
43 "2. Iida H et al. Modelling approach to eliminate the need to separate",
44 " arterial plasma in oxygen-15 inhalation positron emission tomography.",
45 " J Nucl Med. 1993;34:1333-1340.",
46 "3. Kudomi N et al. A physiologic model for recirculation water correction",
47 " in CMRO2 assessment with 15O2 inhalation PET.",
48 " J Cereb Blood Flow Metab. 2009;29(2):355-364.",
50 "See also: fit_o2bl, sim_o2bl, o2_p2w, fit_mo2, b2t_mo2, taccalc, tac2svg",
52 "Keywords: input, oxygen, blood, metabolite correction",
71int main(
int argc,
char **argv)
73 int ai, help=0, version=0, verbose=1;
75 char blofile[FILENAME_MAX], parfile[FILENAME_MAX],
76 oxyfile[FILENAME_MAX], watfile[FILENAME_MAX];
77 double k1, k2, k3, k4, delay, k3k4, k1k3;
86 if(argc==1) {
tpcPrintUsage(argv[0], info, stderr);
return(1);}
88 blofile[0]=parfile[0]=oxyfile[0]=watfile[0]=(char)0;
89 k1=k2=k3=k4=k3k4=k1k3=nan(
""); delay=0.0;
91 for(ai=1; ai<argc; ai++)
if(*argv[ai]==
'-') {
94 fprintf(stderr,
"Error: invalid option '%s'.\n", argv[ai]);
99 if(help==2) {
tpcHtmlUsage(argv[0], info,
"");
return(0);}
104 for(; ai<argc; ai++) {
105 if(!blofile[0]) {
strlcpy(blofile, argv[ai], FILENAME_MAX);
continue;}
106 if(!parfile[0]) {
strlcpy(parfile, argv[ai], FILENAME_MAX);
continue;}
107 if(!oxyfile[0]) {
strlcpy(oxyfile, argv[ai], FILENAME_MAX);
continue;}
108 if(!watfile[0]) {
strlcpy(watfile, argv[ai], FILENAME_MAX);
continue;}
109 fprintf(stderr,
"Error: too many arguments: '%s'.\n", argv[ai]);
115 fprintf(stderr,
"Error: missing command-line argument; use option --help\n");
121 printf(
"blofile := %s\n", blofile);
122 printf(
"parfile := %s\n", parfile);
123 printf(
"oxyfile := %s\n", oxyfile);
124 printf(
"watfile := %s\n", watfile);
128 if(verbose>1) printf(
"reading parameters in %s\n", parfile);
130 if(
resRead(parfile, &res, verbose-2)==0) {
131 if(verbose>2) printf(
"result format\n");
132 ret=
res2ift(&res, &ift, verbose-3);
135 fprintf(stderr,
"Error in converting results.\n");
140 }
else if(
iftRead(&ift, parfile, 1, 0)==0) {
141 if(verbose>2) printf(
"ift format\n");
143 fprintf(stderr,
"Error: cannot read '%s'\n", parfile);
148 int i, n;
char key[12];
double v;
int u;
char buf1[128], buf2[128];
150 strcpy(key,
"k1"); i=
iftGet(&ift, key, 0);
152 fprintf(stderr,
"Error: k1 not found in '%s'.\n", parfile);
156 n=sscanf(ift.
item[i].
value,
"%128s %128s", buf1, buf2);
158 fprintf(stderr,
"Error: valid k1 not found in '%s'.\n", parfile);
162 if(n>1) {u=
petCunitId(buf2);
if(u==CUNIT_PER_MIN) v/=60.0;}
163 k1=v;
if(verbose>2) printf(
"k1 := %g\n", k1);
165 strcpy(key,
"delay"); i=
iftGet(&ift, key, 0);
166 if(i<0) strcpy(key,
"delayt");
168 if(i<0) strcpy(key,
"timedelay");
171 n=sscanf(ift.
item[i].
value,
"%128s %128s", buf1, buf2);
173 fprintf(stderr,
"Error: valid delay not found in '%s'.\n", parfile);
177 if(n>1) {u=
petTunitId(buf2);
if(u==TUNIT_MIN) v*=60.0;}
178 delay=v;
if(verbose>2) printf(
"delay := %g\n", k1);
181 strcpy(key,
"k3"); i=
iftGet(&ift, key, 0);
183 n=sscanf(ift.
item[i].
value,
"%128s %128s", buf1, buf2);
185 if(n>1) {u=
petCunitId(buf2);
if(u==CUNIT_PER_MIN) v/=60.0;}
186 k3=v;
if(verbose>2) printf(
"k3 := %g\n", k3);
190 strcpy(key,
"k3/k4"); i=
iftGet(&ift, key, 0);
192 n=sscanf(ift.
item[i].
value,
"%128s %128s", buf1, buf2);
194 k3k4=v;
if(verbose>2) printf(
"k3/k4 := %g\n", k3k4);
198 strcpy(key,
"k1+k3"); i=
iftGet(&ift, key, 0);
200 n=sscanf(ift.
item[i].
value,
"%128s %128s", buf1, buf2);
202 if(n>1) {u=
petCunitId(buf2);
if(u==CUNIT_PER_MIN) v/=60.0;}
203 k1k3=v;
if(verbose>2) printf(
"k1+k3 := %g\n", k1k3);
208 if(isnan(k3) && isnan(k1k3)) {
209 fprintf(stderr,
"Error: missing k3 or k1+k3 in '%s'.\n", parfile);
215 fprintf(stderr,
"Error: missing k3/k4 in '%s'.\n", parfile);
219 if(k3k4<=1.0E-100) k4=0.0;
else k4=k3/k3k4;
221 if(isnan(k3)) {k3=k1k3-k1; k4=0.0;}
223 printf(
"k2 := %g\n", k2);
224 printf(
"k3 := %g\n", k3);
225 printf(
"k4 := %g\n", k4);
227 if(k1<0.0 || k3<0.0 || k4<0.0) {
228 fprintf(stderr,
"Error: invalid parameter value(s) in '%s'.\n", parfile);
238 if(verbose>1) printf(
"reading %s\n", blofile);
240 fprintf(stderr,
"Error in reading '%s': %s\n", blofile,
dfterrmsg);
245 fprintf(stderr,
"Warning: input file contains extra column(s).\n");
248 fprintf(stderr,
"Error: blood data not valid.\n");
255 fprintf(stderr,
"Warning: assuming that BTAC sample times are in minutes.\n");
266 if(
dftdup(&blood, &sim)) {
267 fprintf(stderr,
"Error: cannot allocate memory for simulated TACs.\n");
276 if(verbose>1) printf(
"simulating\n");
278 blood.
voi[0].
y2, blood.
voi[0].
y3, NULL, NULL);
280 fprintf(stderr,
"Error in simulation of metabolism (%d).\n", ret);
284 for(
int i=0; i<blood.
frameNr; i++) blood.
x1[i]=blood.
x[i]+delay;
289 fprintf(stderr,
"Error in simulation of delay (%d).\n", ret);
293 if(verbose>1) printf(
"writing O15-water TAC in %s\n", watfile);
298 fprintf(stderr,
"Error in writing '%s': %s\n", watfile,
dfterrmsg);
301 if(verbose==1) printf(
"O15-water BTAC written in %s\n", watfile);
307 for(
int i=0; i<sim.
frameNr; i++)
310 if(verbose>1) printf(
"writing O15-oxygen TAC in %s\n", oxyfile);
314 fprintf(stderr,
"Error in writing '%s': %s\n", oxyfile,
dfterrmsg);
317 if(verbose==1) printf(
"O15-oxygen BTAC written in %s\n", oxyfile);
int atof_with_check(char *double_as_string, double *result_value)
int dftdup(DFT *dft1, DFT *dft2)
int dftRead(char *filename, DFT *data)
int dftWrite(DFT *data, char *filename)
void dftSec2min(DFT *dft)
void dftMin2sec(DFT *dft)
int iftRead(IFT *ift, char *filename, int is_key_required, int verbose)
int iftGet(IFT *ift, char *key, int verbose)
int interpolate(double *x, double *y, int nr, double *newx, double *newy, double *newyi, double *newyii, int newnr)
Linear interpolation and integration.
Header file for libtpccurveio.
int resRead(char *filename, RES *res, int verbose)
int res2ift(RES *res, IFT *ift, int verbose)
Header file for libtpcmisc.
int tpcProcessStdOptions(const char *s, int *print_usage, int *print_version, int *verbose_level)
int petCunitId(const char *unit)
size_t strlcpy(char *dst, const char *src, size_t dstsize)
int tpcHtmlUsage(const char *program, char *text[], const char *path)
int petTunitId(const char *timeunit)
void tpcPrintBuild(const char *program, FILE *fp)
void tpcPrintUsage(const char *program, char *text[], FILE *fp)
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)
char voiname[MAX_REGIONSUBNAME_LEN+1]
char name[MAX_REGIONNAME_LEN+1]
char hemisphere[MAX_REGIONSUBNAME_LEN+1]
char place[MAX_REGIONSUBNAME_LEN+1]