8#include "tpcclibConfig.h"
24static char *info[] = {
25 "Convolution of PET time-activity curve (TAC) with response function h(t)",
26 "consisting of surge function",
27 " h(t) = a*t*exp(-b*t)",
28 "Surge function integral from 0 to infinity is a/(b*b).",
29 "Output TAC, Co(t), is calculated from input TAC, Ci(t), as",
30 "Co(T) = Ci(T) (x) h(T)",
31 ", where (x) denotes the operation of convolution.",
33 "Usage: @P [Options] tacfile a b outputfile ",
37 " Sample time interval in convolution; by default the shortest interval",
38 " in the plasma data; too long interval as compared to b's leads to bias.",
40 " Scale response function to have integral from 0 to infinity to unity;",
41 " that will lead to similar AUC for the input and output TACs.",
44 "The units of a and b must be compatible with units of the TAC, and",
45 "the optional sample interval.",
46 "For accurate results, input TAC should have very short sampling intervals.",
47 "Frame durations are not used, even if available in the TAC file.",
50 " @P -auc=1 plasma.tac 1 0.05 simulated.tac",
52 "See also: fit_xsur, convexpf, sim_av, fit2dat, tacadd, taccalc, interpol",
54 "Keywords: TAC, simulation, modelling, convolution",
73int main(
int argc,
char **argv)
75 int ai, help=0, version=0, verbose=1;
76 char tacfile[FILENAME_MAX], simfile[FILENAME_MAX];
77 double interval=nan(
""), auc=nan(
"");
78 double a=nan(
""), b=nan(
"");
84 if(argc==1) {
tpcPrintUsage(argv[0], info, stderr);
return(1);}
85 tacfile[0]=simfile[0]=(char)0;
87 for(ai=1; ai<argc; ai++)
if(*argv[ai]==
'-') {
89 char *cptr=argv[ai]+1;
if(*cptr==
'-') cptr++;
if(!*cptr)
continue;
90 if(strncasecmp(cptr,
"I=", 2)==0) {
91 interval=
atofVerified(cptr+2);
if(interval>0.0)
continue;
92 }
else if(strcasecmp(cptr,
"AUC=1")==0) {
94 }
else if(strncasecmp(cptr,
"AUC=", 4)==0) {
97 fprintf(stderr,
"Error: invalid option '%s'.\n", argv[ai]);
106 if(help==2) {
tpcHtmlUsage(argv[0], info,
"");
return(0);}
111 if(ai<argc) {
strlcpy(tacfile, argv[ai++], FILENAME_MAX);}
114 if(!(a>0.0)) {fprintf(stderr,
"Error: invalid a '%s'.\n", argv[ai]);
return(1);}
119 if(!(b>0.0)) {fprintf(stderr,
"Error: invalid b '%s'.\n", argv[ai]);
return(1);}
122 if(ai<argc) {
strlcpy(simfile, argv[ai++], FILENAME_MAX);}
124 fprintf(stderr,
"Error: invalid argument '%s'.\n", argv[ai]);
130 fprintf(stderr,
"Error: missing command-line argument; use option --help\n");
137 printf(
"tacfile := %s\n", tacfile);
138 printf(
"simfile := %s\n", simfile);
139 printf(
"a := %g\n", a); printf(
"b := %g\n", b);
140 if(!isnan(auc)) printf(
"auc := %g\n", auc);
141 if(!isnan(interval)) printf(
"interval := %g\n", interval);
149 if(verbose>1) fprintf(stdout,
"reading %s\n", tacfile);
152 fprintf(stderr,
"Error: %s (%s)\n",
errorMsg(status.
error), tacfile);
157 printf(
"tacNr := %d\n", tac.
tacNr);
158 printf(
"sampleNr := %d\n", tac.
sampleNr);
165 fprintf(stderr,
"Error: missing frame times.\n");
170 fprintf(stderr,
"Error: missing concentrations.\n");
174 fprintf(stderr,
"Error: too few samples in plasma data.\n");
178 fprintf(stderr,
"Warning: only first TAC in %s is used.\n", tacfile);
182 fprintf(stderr,
"Error: invalid sample times.\n");
185 if(tac.
isframe!=0 && verbose>0) {
187 fprintf(stderr,
"Error: invalid sample times.\n");
190 fprintf(stderr,
"Warning: frame durations are ignored.\n");
193 fprintf(stderr,
"Error: too long interval time.\n");
196 if(interval>0.01*tac.
x[tac.
sampleNr-1]) {
197 if(verbose>0) fprintf(stderr,
"Warning: interval time may be too long.\n");
206 fprintf(stderr,
"Error: cannot interpolate data to even sample times.\n");
210 double freq=itac.
x2[0]-itac.
x1[0];
212 printf(
"sample_intervals_in_convolution := %g\n", freq);
213 printf(
"interpolated data range: %g - %g\n", itac.
x1[0], itac.
x2[itac.
sampleNr-1]);
217 if(verbose>0) fprintf(stdout,
"allocate memory for kernel...\n");
218 double *kernel=(
double*)malloc(2*itac.
sampleNr*
sizeof(
double));
220 fprintf(stderr,
"Error: out of memory.\n");
229 if(verbose>1) fprintf(stdout,
"computing the kernel...\n");
231 if(verbose>6) printf(
"\nData\tKernel:\n");
232 for(
int i=0; i<itac.
sampleNr; i++) {
233 double t1=itac.
x[i]-0.5*freq;
234 double t2=itac.
x[i]+0.5*freq;
235 kernel[i] = (a/(b*b)) * ((1.0+b*t1)*exp(-b*t1) - (1.0+b*t2)*exp(-b*t2));
237 if(verbose>6) printf(
"%g\t%g\n", itac.
c[0].
y[i], kernel[i]);
239 if(verbose>2) printf(
"Sum of unscaled response function := %g\n", ksum);
240 if(!isnormal(ksum)) {
241 fprintf(stderr,
"Error: invalid kernel contents.\n");
246 double sc=auc/(a/(b*b));
248 if(verbose>7) printf(
"\nData\tKernel:\n");
249 for(
int i=0; i<itac.
sampleNr; i++) {
252 if(verbose>7) printf(
"%g\t%g\n", itac.
c[0].
y[i], kernel[i]);
254 if(verbose>2) printf(
"Sum of scaled response function := %g\n", ksum);
261 if(verbose>1) fprintf(stdout,
"convolution...\n");
263 fprintf(stderr,
"Error: cannot convolve the data.\n");
267 printf(
"\nData x\ty\tKernel\tConvolved\n");
269 printf(
"%g\t%g\t%g\t%g\n", itac.
x[i], itac.
c[0].
y[i], kernel[i], cy[i]);
273 for(
int i=0; i<itac.
sampleNr; i++) itac.
c[0].
y[i]=cy[i];
281 if(verbose>1) fprintf(stdout,
"interpolating to original sample times...\n");
288 NULL, NULL, tac.
sampleNr, 4, 1, verbose-10);
291 fprintf(stderr,
"Error: cannot interpolate back.\n");
299 if(verbose>1) printf(
"writing convolved data in %s\n", simfile);
300 FILE *fp; fp=fopen(simfile,
"w");
302 fprintf(stderr,
"Error: cannot open file for writing (%s)\n", simfile);
311 if(verbose>=0) printf(
"Convolved TAC saved in %s\n", simfile);
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 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)
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 tacIsWeighted(TAC *tac)
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.