8#include "tpcclibConfig.h"
24static char *info[] = {
25 "Input for liver models consists of two parts: portal vein and hepatic artery.",
26 "This program generates portal vein TAC from arterial TAC using the model",
27 "proposed by Munk et al. (2003).",
28 "In a pig study, Winterdahl et al. (2011) measured beta values for",
29 "[F-18]FDG (0.50), [O-15]H2O (2.17), [O-15]CO (0.10), [C-11]methylglucose",
30 "(0.57), and [F-18]FDGal (0.82).",
32 "Usage: @P [Options] arteryfile beta outputfile",
36 " Sample time interval in convolution; by default the shortest interval",
37 " in the data, but restricted to range 0.0001*beta - 0.02*beta;",
38 " too long interval leads to bias.",
40 " Output is written with sample intervals used in convolution; by default",
41 " data is interpolated back to the sample times of the artery data.",
44 "Beta must be given in minutes, and optional interval in seconds.",
47 " @P ue65ap.bld 0.50 ue65pv.bld",
50 "1. Munk OL, Keiding S, Bass L. Impulse-response function of splanchnic",
51 " circulation with model-independent constraints: theory and experimental",
52 " validation. Am J Physiol Gastrointest Liver Physiol. 2003;285:G671-G680.",
53 "2. Winterdahl M, Keiding S, Sorensen M, Mortensen FV, Alstrup AKO, Munk AL.",
54 " Tracer input for kinetic modelling of liver physiology determined without",
55 " sampling portal venous blood in pigs.",
56 " Eur J Nucl Med Mol Imaging 2011;38:263-270.",
58 "See also: liverinp, taccalc, taccat, b2plasma",
60 "Keywords: input, blood, TAC, modelling, simulation, liver",
79int main(
int argc,
char **argv)
81 int ai, help=0, version=0, verbose=1;
82 char pfile[FILENAME_MAX], afile[FILENAME_MAX];
84 double interval=nan(
"");
85 int output_sampling=0;
91 if(argc==1) {
tpcPrintUsage(argv[0], info, stderr);
return(1);}
92 pfile[0]=afile[0]=(char)0;
94 for(ai=1; ai<argc; ai++)
if(*argv[ai]==
'-') {
96 char *cptr=argv[ai]+1;
if(*cptr==
'-') cptr++;
if(!*cptr)
continue;
97 if(strncasecmp(cptr,
"I=", 2)==0) {
98 interval=
atofVerified(cptr+2);
if(interval>0.0)
continue;
99 }
else if(strcasecmp(cptr,
"SI")==0) {
100 output_sampling=1;
continue;
102 fprintf(stderr,
"Error: invalid option '%s'.\n", argv[ai]);
111 if(help==2) {
tpcHtmlUsage(argv[0], info,
"");
return(0);}
116 if(ai<argc) {
strlcpy(afile, argv[ai++], FILENAME_MAX);}
118 if(
atofCheck(argv[ai], &beta)!=0 || beta<=0.0) {
119 fprintf(stderr,
"Error: invalid beta value.\n");
124 if(ai<argc) {
strlcpy(pfile, argv[ai++], FILENAME_MAX);}
125 if(ai<argc) {fprintf(stderr,
"Error: invalid argument '%s'.\n", argv[ai]);
return(1);}
129 fprintf(stderr,
"Error: missing command-line argument; use option --help\n");
136 for(ai=0; ai<argc; ai++) printf(
"%s ", argv[ai]);
138 printf(
"afile := %s\n", afile);
139 printf(
"beta := %g\n", beta);
140 printf(
"pfile := %s\n", pfile);
141 printf(
"output_sampling := %d\n", output_sampling);
142 if(!isnan(interval)) printf(
"interval := %g\n", interval);
152 if(verbose>0) printf(
"reading %s\n", afile);
160 printf(
"tacNr := %d\n", atac.
tacNr);
161 printf(
"sampleNr := %d\n", atac.
sampleNr);
166 fprintf(stderr,
"Warning: only first TAC in arterial data is used.\n");
171 fprintf(stderr,
"Error: missing frame times.\n");
176 fprintf(stderr,
"Error: missing concentrations.\n");
180 fprintf(stderr,
"Error: too few samples in plasma data.\n");
186 fprintf(stderr,
"Error: invalid sample times.\n");
189 if(atac.
isframe!=0 && verbose>0) {
191 fprintf(stderr,
"Error: invalid sample times.\n");
194 fprintf(stderr,
"Warning: frame durations are ignored.\n");
203 if(verbose>1) printf(
"beta is converted to %g s.\n", beta);
205 if(!isnan(interval) && interval>0.0) {
207 if(verbose>1) printf(
"interval is converted to %g min.\n", interval);
210 fprintf(stderr,
"Warning: time units are assumed to be in minutes.\n");
211 if(!isnan(interval) && interval>0.0) {
213 if(verbose>1) printf(
"interval is converted to %g min.\n", interval);
218 if(!isnan(interval) && interval>0.0) {
219 if(interval>0.01*atac.
x[atac.
sampleNr-1] || interval>0.2*beta) {
220 fprintf(stderr,
"Error: too long interval time.\n");
223 if(interval>0.001*atac.
x[atac.
sampleNr-1] || interval>0.05*beta) {
224 if(verbose>0) fprintf(stderr,
"Warning: interval time may be too long.\n");
231 if(verbose>1) printf(
"kernel integral at end of data: %g\n", kernel_integral);
235 double kernel_time=999.*beta;
236 double kernel_integral=kernel_time/(kernel_time+beta);
237 if(verbose>1) printf(
"kernel integral at %g: %g\n", kernel_time, kernel_integral);
243 if(!isnan(interval)) {
255 double freq=itac.
x2[0]-itac.
x1[0];
257 printf(
"sample_intervals_in_convolution := %g\n", freq);
258 printf(
"interpolated data range: %g - %g\n", itac.
x1[0], itac.
x2[itac.
sampleNr-1]);
271 if(verbose>0) fprintf(stdout,
"allocate memory for kernel...\n");
272 double *kernel=(
double*)malloc(2*itac.
sampleNr*
sizeof(
double));
274 fprintf(stderr,
"Error: out of memory.\n");
279 if(verbose>0) fprintf(stdout,
"computing the kernel...\n");
281 if(verbose>6) printf(
"\nData\tKernel:\n");
282 for(
int i=0; i<itac.
sampleNr; i++) {
283 kernel[i]=beta*freq/((beta+itac.
x1[i])*(beta+itac.
x2[i]));
285 if(verbose>6) printf(
"%g\t%g\n", itac.
c[0].
y[i], kernel[i]);
287 if(verbose>4) printf(
"last_kernel_value := %g\n", kernel[itac.
sampleNr-1]);
288 if(verbose>2) printf(
"Sum of response function := %g\n", ksum);
289 if(!isnormal(ksum)) {
290 fprintf(stderr,
"Error: invalid kernel contents.\n");
298 if(verbose>0) {fprintf(stdout,
"convolution...\n"); fflush(stdout);}
301 fprintf(stderr,
"Error: cannot convolve the data.\n");
305 printf(
"\nData x\ty\tKernel\tConvolved\n");
307 printf(
"%g\t%g\t%g\t%g\n", itac.
x[i], itac.
c[0].
y[i], kernel[i], cy[i]);
311 for(
int i=0; i<itac.
sampleNr; i++) itac.
c[0].
y[i]=cy[i];
318 if(output_sampling==1) {
327 strcpy(itac.
c[0].
name,
"PV");
329 strcpy(itac.
c[0].
name,
"Cpv");
332 if(verbose>1) printf(
"writing portal vein data in %s\n", pfile);
333 FILE *fp; fp=fopen(pfile,
"w");
335 fprintf(stderr,
"Error: cannot open file for writing (%s)\n", pfile);
344 if(verbose>=0) printf(
"Portal vein TAC saved in %s\n", pfile);
352 if(verbose>1) fprintf(stdout,
"interpolating to original sample times...\n");
366 NULL, NULL, atac.
sampleNr, 0, 1, verbose-10);
369 fprintf(stderr,
"Error: cannot interpolate back.\n");
380 strcpy(atac.
c[0].
name,
"PV");
382 strcpy(atac.
c[0].
name,
"Cpv");
388 if(verbose>1) printf(
"writing portal vein data in %s\n", pfile);
389 FILE *fp; fp=fopen(pfile,
"w");
391 fprintf(stderr,
"Error: cannot open file for writing (%s)\n", pfile);
400 if(verbose>=0) printf(
"Portal vein TAC saved in %s\n", pfile);
int convolve1D(double *data, const int n, double *kernel, const int m, double *out)
Calculates the convolution sum of a discrete real data set data[0..n-1] and a discretized response fu...
double atofVerified(const char *s)
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 liInterpolateForPET(double *x, double *y, const int nr, double *newx1, double *newx2, double *newy, double *newyi, double *newyii, const int newnr, const int se, const int ee, const int verbose)
Linear TAC interpolation and/or integration to PET frames.
int tacInterpolateToEqualLengthFrames(TAC *inp, double minfdur, double maxfdur, TAC *tac, TPCSTATUS *status)
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)
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)
char * strcasestr(const char *haystack, const char *needle)
char name[MAX_TACNAME_LEN+1]
int verbose
Verbose level, used by statusPrint() etc.
tpcerror error
Error code.
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 tacYNaNs(TAC *tac, const int i)
int tacSortByTime(TAC *d, TPCSTATUS *status)
int tacFramesToSteps(TAC *inp, TAC *out, TPCSTATUS *status)
Transform TAC with frames into TAC with frames represented with stepwise changing dot-to-dot data.
int tacSetX(TAC *d, TPCSTATUS *status)
Set TAC x values based on x1 and x2 values, or guess x1 and x2 values based on x values.
Header file for libtpccm.
Header file for library libtpcextensions.
char * unitName(int unit_code)
Header file for library libtpcift.
Header file for libtpcli.
Header file for library libtpctac.
@ TAC_FORMAT_UNKNOWN
Unknown format.
Header file for libtpctacmod.