10#include "tpcclibConfig.h"
25static char *info[] = {
26 "Calculation of perfusion look-up table from [O-15]H2O blood curve",
27 "for usage with PET in vivo autoradiographic (ARG) method.",
29 "Usage: @P [options] BTAC p fMax start dur lkupfile",
33 " The look-up table integral can be corrected for physical decay as",
34 " single frame when static PET scan was performed (y), or dynamically",
37 " Set the size of look-up table; 5000 by default.",
40 "Blood TAC (BTAC) must be calibrated and corrected for decay. Sample times",
41 "must be in sec unless correctly specified inside the BTAC file.",
42 "Concentrations must be in the same units as the units of PET tissue data.",
43 "Partition coefficient of water (p) must be given in units mL/mL,",
44 "and maximal perfusion (fMax) in units mL/(min*100mL).",
45 "Integration start time and duration is given in sec.",
47 "Look-up table will contain 2 columns: TTAC integral [sec*kBq/mL] and",
48 "blood flow [mL/(min*100mL)].",
51 " @P -nr=2000 s1456_blo.fit 0.8 50 0 120 s1456.lkup",
54 "1. Raichle ME. Quantitative in vivo autoradiography with positron emission",
55 " tomography. Brain Res Rev. 1979;1:47-68.",
56 "2. Herscovitch P, Markham J, Raichle ME. Brain blood flow measured with",
57 " intravenous H215O. I. Theory and error analysis.",
58 " J Nucl Med. 1983;24:782-789.",
59 "3. Raichle ME, Martin WRW, Herscovitch P, Mintun MA, Markham J. Brain blood",
60 " flow measured with intravenous H215O. II. Implementation and validation.",
61 " J Nucl Med. 1983;24:790-798.",
62 "4. Ruotsalainen U, Raitakari M, Nuutila P, Oikonen V, Sipila H, Teras M,",
63 " Knuuti J, Bloomfield PM, Iida H. Quantitative blood flow measurement of",
64 " skeletal muscle using oxygen-15-water and PET. ",
65 " J Nucl Med. 1997; 38:314-319.",
67 "See also: fitdelay, imginteg, imglkup, taclkup, tacunit, imgbfbp, imgflow",
69 "Keywords: perfusion, blood flow, radiowater, autoradiography, ARG, look-up table",
88int main(
int argc,
char **argv)
90 int ai, help=0, version=0, verbose=1;
91 char btacfile[FILENAME_MAX], lkupfile[FILENAME_MAX];
93 double pWater, maxFlow, start, dur, end;
102 if(argc==1) {
tpcPrintUsage(argv[0], info, stderr);
return(1);}
103 btacfile[0]=lkupfile[0]=(char)0;
105 for(ai=1; ai<argc; ai++)
if(*argv[ai]==
'-') {
107 cptr=argv[ai]+1;
if(*cptr==
'-') cptr++;
if(!*cptr)
continue;
108 if(strncasecmp(cptr,
"NR=", 3)==0) {
109 if(
atoiCheck(cptr+3, &tableSize)==0 && tableSize>5)
continue;
110 }
else if(strncasecmp(cptr,
"STATIC=", 7)==0) {
112 if(strncasecmp(cptr,
"YES", 1)==0) {singleFrame=1;
continue;}
113 else if(strncasecmp(cptr,
"NO", 1)==0) {singleFrame=0;
continue;}
115 fprintf(stderr,
"Error: invalid option '%s'.\n", argv[ai]);
124 if(help==2) {
tpcHtmlUsage(argv[0], info,
"");
return(0);}
129 if(ai<argc)
strlcpy(btacfile, argv[ai++], FILENAME_MAX);
131 if(
atofCheck(argv[ai], &pWater) || pWater<=0.0 || pWater>1.25) {
132 fprintf(stderr,
"Error: invalid partition coefficient '%s'.\n", argv[ai]);
138 if(
atofCheck(argv[ai], &maxFlow) || maxFlow<=0.0) {
139 fprintf(stderr,
"Error: invalid maximum blood flow '%s'.\n", argv[ai]);
146 fprintf(stderr,
"Error: invalid integration start time '%s'.\n", argv[ai]);
152 if(
atofCheck(argv[ai], &dur) || dur<=0.0) {
153 fprintf(stderr,
"Error: invalid integration duration '%s'.\n", argv[ai]);
158 if(ai<argc)
strlcpy(lkupfile, argv[ai++], FILENAME_MAX);
160 fprintf(stderr,
"Error: invalid argument '%s'.\n", argv[ai]);
165 fprintf(stderr,
"Error: missing command-line argument; use option --help\n");
170 fprintf(stderr,
"Error: invalid integration times.\n");
175 "Warning: look-up table may be too small to provide accurate results.\n");
181 printf(
"btacfile := %s\n", btacfile);
182 printf(
"pWater := %g\n", pWater);
183 printf(
"maxFlow := %g\n", maxFlow);
184 printf(
"start := %g\n", start);
185 printf(
"dur := %g\n", dur);
186 printf(
"end := %g\n", end);
187 printf(
"tableSize := %d\n", tableSize);
188 printf(
"lkupfile := %s\n", lkupfile);
189 printf(
"singleFrame := %d\n", singleFrame);
196 if(verbose>1) printf(
"reading %s\n", btacfile);
198 ret=
tacRead(&btac, btacfile, &status);
205 printf(
"tacNr := %d\n", btac.
tacNr);
206 printf(
"sampleNr := %d\n", btac.
sampleNr);
211 fprintf(stderr,
"Warning: only first TAC in input file is used.\n");
221 if(verbose>1) printf(
"missing blood concentrations.\n");
225 fprintf(stderr,
"Error: missing concentrations in %s.\n", btacfile);
235 fprintf(stderr,
"Error: invalid time range in btac file.\n");
239 printf(
"btac.xmin := %g\n", xmin);
240 printf(
"btac.xmax := %g\n", xmax);
243 if(verbose>0) printf(
"Note: time units had to be guessed.\n");
249 fprintf(stderr,
"Error: invalid time units.\n");
254 fprintf(stderr,
"Error: blood data only upto %g s.\n", xmax);
259 fprintf(stderr,
"Error: invalid integration time.\n");
262 if(end<(0.25*xmin+0.75*xmax)) {
263 fprintf(stderr,
"Warning: integration time is short compared to BTAC.\n");
266 fprintf(stderr,
"Error: only %d samples in %s\n", btac.
sampleNr, btacfile);
270 fprintf(stderr,
"Warning: small blood sample nr in %s\n", btacfile);
276 ret=
tacYRange(&btac, 0, &ymin, &ymax, NULL, NULL, NULL, NULL);
278 fprintf(stderr,
"Error: invalid concentration range in btac file.\n");
282 printf(
"btac.ymin := %g\n", ymin);
283 printf(
"btac.ymax := %g\n", ymax);
286 fprintf(stderr,
"Warning: concentration units are not known.\n");
292 fprintf(stderr,
"Error: cannot allocate memory.\n");
302 if(verbose>1) printf(
"allocating memory for table\n");
306 fprintf(stderr,
"Error: %s\n",
errorMsg(ret));
318 if(verbose>1) printf(
"setting the perfusion in look-up table\n");
320 double K1step=maxFlow/(double)(tableSize-1);
321 if(verbose>2) printf(
"K1step := %E\n", K1step);
323 for(
int i=1; i<tableSize; i++) lkup.
c[0].
y[i]=lkup.
c[0].
y[i-1]+K1step;
324 if(verbose>2) printf(
"K1 range: %g - %g\n",
329 if(verbose>1) printf(
"calculating the tissue integrals in look-up table\n");
338 double K1, k2, intx[2], inty[2];
339 intx[0]=start; intx[1]=end;
342 for(
int i=1; i<tableSize && !ret; i++) {
343 K1=lkup.
c[0].
y[i]/6000.0;
356 intx, NULL, inty, NULL, 2, 4, 1, 0);
359 lkup.
x[i]=inty[1]-inty[0];
361 if(singleFrame!=0) lkup.
x[i]*=dc;
364 fprintf(stderr,
"Error: cannot compute simulated tissue AUC.\n");
376 if(verbose>1) printf(
"writing %s\n", lkupfile);
377 FILE *fp; fp=fopen(lkupfile,
"w");
379 fprintf(stderr,
"Error: cannot open file for writing (%s)\n", lkupfile);
388 if(verbose>0) printf(
"Look-up table saved in %s.\n", lkupfile);
double decayCorrectionFactorFromIsotope(int isotope, double starttime, double duration)
int atofCheck(const char *s, double *v)
int liInterpolate(double *x, double *y, const int nr, double *newx, double *newy, double *newyi, double *newyii, const int newnr, const int se, const int ee, const int verbose)
Linear interpolation and/or integration with trapezoidal method.
int atoiCheck(const char *s, int *v)
int tpcProcessStdOptions(const char *s, int *print_usage, int *print_version, int *verbose_level)
int tpcHtmlUsage(const char *program, char *text[], const char *path)
void tpcPrintBuild(const char *program, FILE *fp)
void tpcPrintUsage(const char *program, char *text[], FILE *fp)
int simC1(double *t, double *ca, const int nr, const double k1, const double k2, double *ct)
void statusInit(TPCSTATUS *s)
char * errorMsg(tpcerror e)
void statusSet(TPCSTATUS *s, const char *func, const char *srcfile, int srcline, tpcerror error)
size_t strlcpy(char *dst, const char *src, size_t dstsize)
int verbose
Verbose level, used by statusPrint() etc.
tpcerror error
Error code.
int tacAllocate(TAC *tac, int sampleNr, int tacNr)
int tacAllocateMore(TAC *tac, int tacNr)
int tacRead(TAC *d, const char *fname, TPCSTATUS *status)
char * tacFormattxt(tacformat c)
int tacWrite(TAC *tac, FILE *fp, tacformat format, int extra, TPCSTATUS *status)
int tacSortByTime(TAC *d, TPCSTATUS *status)
int tacXUnitConvert(TAC *tac, const int u, TPCSTATUS *status)
int tacXRange(TAC *d, double *xmin, double *xmax)
Get the range of x values (times) in TAC structure.
int tacYRange(TAC *d, int i, double *ymin, double *ymax, int *smin, int *smax, int *imin, int *imax)
Get the range of y values (concentrations) in TAC struct.
Header file for libtpccm.
Header file for library libtpcextensions.
@ UNIT_UNKNOWN
Unknown unit.
@ UNIT_SEC_BQ_PER_ML
s*Bq/mL
@ UNIT_ML_PER_DL_MIN
mL/(dL*min)
@ UNIT_SEC_KBQ_PER_ML
s*kBq/mL
char * unitName(int unit_code)
Header file for library libtpcift.
Header file for libtpcli.
Header file for library libtpctac.
@ TAC_FORMAT_PMOD
PMOD TAC format.