10#include "tpcclibConfig.h"
26static char *info[] = {
27 "Simulation of PET tissue time-radioactivity concentration curve (TAC)",
28 "from arterial plasma (Ca) TAC, based on one-tissue compartment model,",
29 "using linear discrete time convolution:",
32 " | Ca | ----> | Ct | ",
33 " |____| <---- |____| ",
36 "Ct(T) = K1*Ca(T) (x) exp[-k2*T]",
37 ", where (x) denotes the operation of convolution.",
39 "Usage: @P [Options] plasmafile K1 k2 outputfile ",
43 " Sample time interval in convolution; by default the shortest interval",
44 " in the plasma data; too long interval as compared to k2 leads to bias.",
47 "The units of rate constants must be 1/min or 1/s depending on the time units",
48 "of the plasma file, min or s, respectively.",
49 "For accurate results, plasma TAC should have very short sampling intervals.",
50 "Frame durations are not used, even if available in the TAC file.",
53 " @P plasma.tac 0.4 0.5 simulated.tac",
55 "See also: sim_3tcm, fit2dat, tacadd, simdisp, simframe, svar4tac, fitk2",
57 "Keywords: TAC, simulation, modelling, compartmental model, convolution",
76int main(
int argc,
char **argv)
78 int ai, help=0, version=0, verbose=1;
79 char tacfile[FILENAME_MAX], simfile[FILENAME_MAX];
80 double k1=nan(
""), k2=nan(
""), interval=nan(
"");
86 if(argc==1) {
tpcPrintUsage(argv[0], info, stderr);
return(1);}
87 tacfile[0]=simfile[0]=(char)0;
89 for(ai=1; ai<argc; ai++)
if(*argv[ai]==
'-') {
91 char *cptr=argv[ai]+1;
if(*cptr==
'-') cptr++;
if(!*cptr)
continue;
92 if(strncasecmp(cptr,
"I=", 2)==0) {
93 interval=
atofVerified(cptr+2);
if(interval>0.0)
continue;
95 fprintf(stderr,
"Error: invalid option '%s'.\n", argv[ai]);
104 if(help==2) {
tpcHtmlUsage(argv[0], info,
"");
return(0);}
109 if(ai<argc) {
strlcpy(tacfile, argv[ai++], FILENAME_MAX);}
112 if(isnan(k1) || k1<0.0 || k1>1000.0) {
113 fprintf(stderr,
"Error: invalid K1 '%s'.\n", argv[ai]);
return(1);}
118 if(isnan(k2) || k1<=0.0 || k2>1000.0) {
119 fprintf(stderr,
"Error: invalid k2 '%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");
136 printf(
"tacfile := %s\n", tacfile);
137 printf(
"simfile := %s\n", simfile);
138 printf(
"K1 := %g\n", k1);
139 printf(
"k2 := %g\n", k2);
140 if(!isnan(interval)) printf(
"interval := %g\n", interval);
148 if(verbose>1) fprintf(stdout,
"reading %s\n", tacfile);
151 fprintf(stderr,
"Error: %s (%s)\n",
errorMsg(status.
error), tacfile);
156 printf(
"tacNr := %d\n", tac.
tacNr);
157 printf(
"sampleNr := %d\n", tac.
sampleNr);
164 fprintf(stderr,
"Error: missing frame times.\n");
169 fprintf(stderr,
"Error: missing concentrations.\n");
173 fprintf(stderr,
"Error: too few samples in plasma data.\n");
177 fprintf(stderr,
"Warning: only first TAC in %s is used.\n", tacfile);
181 fprintf(stderr,
"Error: invalid sample times.\n");
184 if(tac.
isframe!=0 && verbose>0) {
186 fprintf(stderr,
"Error: invalid sample times.\n");
189 fprintf(stderr,
"Warning: frame durations are ignored.\n");
192 fprintf(stderr,
"Error: too long interval time.\n");
195 if(interval>0.01*tac.
x[tac.
sampleNr-1]) {
196 if(verbose>0) fprintf(stderr,
"Warning: interval time may be too long.\n");
205 fprintf(stderr,
"Error: cannot interpolate data to even sample times.\n");
209 double freq=itac.
x2[0]-itac.
x1[0];
211 printf(
"sample_intervals_in_convolution := %g\n", freq);
212 printf(
"interpolated data range: %g - %g\n", itac.
x1[0], itac.
x2[itac.
sampleNr-1]);
216 if(verbose>0) fprintf(stdout,
"allocate memory for kernel...\n");
217 double *kernel=(
double*)malloc(2*itac.
sampleNr*
sizeof(
double));
219 fprintf(stderr,
"Error: out of memory.\n");
228 if(verbose>1) fprintf(stdout,
"computing the kernel...\n");
230 if(verbose>6) printf(
"\nData\tKernel:\n");
231 for(
int i=0; i<itac.
sampleNr; i++) {
232 kernel[i]=(exp(k2*freq) - 1.0) * exp(-k2*(itac.
x[i]+0.5*freq)) / k2;
234 if(verbose>4) printf(
"%g\t%g\n", itac.
c[0].
y[i], kernel[i]);
236 if(verbose>2) printf(
"Sum of response function := %g\n", ksum);
237 if(!isnormal(ksum)) {
238 fprintf(stderr,
"Error: invalid kernel contents.\n");
246 if(verbose>1) fprintf(stdout,
"convolution...\n");
248 fprintf(stderr,
"Error: cannot convolve the data.\n");
252 printf(
"\nData x\ty\tKernel\tConvolved\n");
254 printf(
"%g\t%g\t%g\t%g\n", itac.
x[i], itac.
c[0].
y[i], kernel[i], cy[i]);
260 for(
int i=0; i<itac.
sampleNr; i++) cy[i]*=k1;
263 for(
int i=0; i<itac.
sampleNr; i++) itac.
c[0].
y[i]=cy[i];
271 if(verbose>1) fprintf(stdout,
"interpolating to original sample times...\n");
279 NULL, NULL, tac.
sampleNr, 4, 1, verbose-10);
296 NULL, NULL, tac.
sampleNr, 0, 1, verbose-10);
300 fprintf(stderr,
"Error: cannot interpolate back.\n");
308 if(verbose>1) printf(
"writing simulated data in %s\n", simfile);
309 FILE *fp; fp=fopen(simfile,
"w");
311 fprintf(stderr,
"Error: cannot open file for writing (%s)\n", simfile);
320 if(verbose>=0) printf(
"Simulated 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 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.