8#include "tpcclibConfig.h"
25static char *info[] = {
26 "Simulation of PET tissue time-radioactivity concentration curve (TAC)",
27 "based on two-tissue compartment model. Vascular volume is not considered.",
29 " dC1(t)/dt = K1*Ca(t) - (k2+k3)*C1(t) + k2*C2(t)",
30 " dC2(t)/dt = k3*C1(t) - k4*C2(t)",
31 " Ct(t) = C1(t) + C2(t) ",
33 "Usage: @P [options] inputfile simfile",
37 " If input file contains frame start and end times, simulated TAC is",
38 " either saved with frame start and end times and frame concentration",
39 " average (option -fa, default), or with start/end times and concentrations",
40 " at those times (option -fe).",
42 " Save simulated C1 and C2 curves; by default only their sum is saved.",
45 "Model parameters are specified as additional columns of the input file.",
46 "The first one or two columns must contain the times or frame start and end",
47 "times, and after that the input function concentrations.",
49 "See also: sim_3tcm, p2t_3c, tacadd, simframe, taccbv",
51 "Keywords: TAC, simulation, compartmental model",
70int main(
int argc,
char **argv)
72 int ai, help=0, version=0, verbose=1;
73 char inpfile[FILENAME_MAX], simfile[FILENAME_MAX];
84 if(argc==1) {
tpcPrintUsage(argv[0], info, stderr);
return(1);}
85 inpfile[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(strcasecmp(cptr,
"FA")==0) {
91 framemode=0;
continue;
92 }
else if(strcasecmp(cptr,
"FE")==0) {
93 framemode=1;
continue;
94 }
else if(strcasecmp(cptr,
"SUB")==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(inpfile, argv[ai++], FILENAME_MAX);
112 if(ai<argc)
strlcpy(simfile, argv[ai++], FILENAME_MAX);
113 if(ai<argc) {fprintf(stderr,
"Error: invalid argument '%s'.\n", argv[ai]);
return(1);}
116 if(!simfile[0]) {fprintf(stderr,
"Error: missing file name.\n");
return(1);}
121 printf(
"inpfile := %s\n", inpfile);
122 printf(
"simfile := %s\n", simfile);
123 printf(
"framemode := %d\n", framemode);
124 printf(
"savesub := %d\n", savesub);
133 if(verbose>1) fprintf(stdout,
"reading input TAC\n");
141 printf(
"tacNr := %d\n", tac.
tacNr);
142 printf(
"sampleNr := %d\n", tac.
sampleNr);
143 printf(
"frames := %d\n", tac.
isframe);
148 fprintf(stderr,
"Error: too few samples in input TAC.\n");
152 fprintf(stderr,
"Error: model parameters missing from input TAC.\n");
157 fprintf(stderr,
"Error: missing values in %s.\n", inpfile);
165 fprintf(stderr,
"Error: times frames not consecutive in %s.\n", inpfile);
174 int ik1, ik2, ik3, ik4;
181 fprintf(stderr,
"Error: missing K1 in %s.\n", inpfile);
186 printf(
"K1 column := %d\n", 1+ik1);
187 if(ik2>0) printf(
"k2 column := %d\n", 1+ik2);
188 if(ik3>0) printf(
"k3 column := %d\n", 1+ik3);
189 if(ik4>0) printf(
"k4 column := %d\n", 1+ik4);
201 strcpy(tac.
c[iCt].
name,
"Ct");
202 strcpy(tac.
c[iC1].
name,
"C1");
203 strcpy(tac.
c[iC2].
name,
"C2");
211 double K1=0.0, k2=0.0, k3=0.0, k4=0.0;
213 tac.
c[iCt].
y[0]=tac.
c[iC1].
y[0]=tac.
c[iC2].
y[0]=0.0;
216 K1=tac.
c[ik1].
y[i-1];
217 if(ik2>0) k2=tac.
c[ik2].
y[i-1];
218 if(ik3>0) k3=tac.
c[ik3].
y[i-1];
219 if(ik4>0) k4=tac.
c[ik4].
y[i-1];
220 double dt=(tac.
x[i]-tac.
x[i-1]);
222 tac.
c[iCt].
y[i]=tac.
c[iCt].
y[i-1];
223 tac.
c[iC1].
y[i]=tac.
c[iC1].
y[i-1];
224 tac.
c[iC2].
y[i]=tac.
c[iC2].
y[i-1];
229 K1*(1.0+k4*dt2)*dt2*(tac.
c[0].
y[i-1]+tac.
c[0].
y[i]) +
230 (1.0 - dt2*(k2+k3-k4+k2*k4*dt2))*tac.
c[iC1].
y[i-1] +
231 k4*dt*tac.
c[iC2].
y[i-1]
233 1.0 + dt2*(k2+k3+k4+k2*k4*dt2)
236 k3*dt2*(tac.
c[iC1].
y[i-1]+tac.
c[iC1].
y[i]) + (1.0 - k4*dt2)*tac.
c[iC2].
y[i-1]
240 tac.
c[iCt].
y[i]=tac.
c[iC1].
y[i];
if(finite(tac.
c[iC2].
y[i])) tac.
c[iCt].
y[i]+=tac.
c[iC2].
y[i];
241 if(verbose>3 && i==tac.
sampleNr-1) printf(
"K1=%g k2=%g k3=%g k4=%g\n", K1, k2, k3, k4);
245 double K1=0.0, k2=0.0, k3=0.0, k4=0.0;
247 if(ik2>0) k2=tac.
c[ik2].
y[i];
248 if(ik3>0) k3=tac.
c[ik3].
y[i];
249 if(ik4>0) k4=tac.
c[ik4].
y[i];
250 double dt=tac.
x2[i]-tac.
x1[i];
253 tac.
c[iCt].
y[0]=tac.
c[iC1].
y[0]=tac.
c[iC2].
y[0]=0.0;
255 tac.
c[iCt].
y[i]=tac.
c[iCt].
y[i-1];
256 tac.
c[iC1].
y[i]=tac.
c[iC1].
y[i-1];
257 tac.
c[iC2].
y[i]=tac.
c[iC2].
y[i-1];
264 K1*(1.0+k4*dt2)*dt*tac.
c[0].
y[i]
266 1.0 + dt2*(k2+k3+k4+k2*k4*dt2)
269 k3*dt2*(tac.
c[iC1].
y[i])
275 K1*(1.0+k4*dt2)*dt*tac.
c[0].
y[i] +
276 (1.0 - dt2*(k2+k3-k4+k2*k4*dt2))*tac.
c[iC1].
y[i-1] +
277 k4*dt*tac.
c[iC2].
y[i-1]
279 1.0 + dt2*(k2+k3+k4+k2*k4*dt2)
282 k3*dt2*(tac.
c[iC1].
y[i-1]+tac.
c[iC1].
y[i]) + (1.0 - k4*dt2)*tac.
c[iC2].
y[i-1]
287 tac.
c[iCt].
y[i]=tac.
c[iC1].
y[i];
if(finite(tac.
c[iC2].
y[i])) tac.
c[iCt].
y[i]+=tac.
c[iC2].
y[i];
288 if(verbose>3 && i==tac.
sampleNr-1) printf(
"K1=%g k2=%g k3=%g k4=%g\n", K1, k2, k3, k4);
294 for(
int i=tac.
sampleNr-1; i>0; i--) {
295 tac.
c[iCt].
y[i]=0.5*(tac.
c[iCt].
y[i-1]+tac.
c[iCt].
y[i]);
296 tac.
c[iC1].
y[i]=0.5*(tac.
c[iC1].
y[i-1]+tac.
c[iC1].
y[i]);
297 tac.
c[iC2].
y[i]=0.5*(tac.
c[iC2].
y[i-1]+tac.
c[iC2].
y[i]);
299 tac.
c[iCt].
y[0]*=0.5;
300 tac.
c[iC1].
y[0]*=0.5;
301 tac.
c[iC2].
y[0]*=0.5;
305 for(
int i=0; i<tac.
sampleNr; i++) tac.
x[i]=tac.
x2[i];
319 if(verbose>1) printf(
"writing %s\n", simfile);
327 FILE *fp; fp=fopen(simfile,
"w");
329 fprintf(stderr,
"Error: cannot open file for writing (%s)\n", simfile);
338 if(verbose>=0) {printf(
"%s saved.\n", simfile); fflush(stdout);}
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 name[MAX_TACNAME_LEN+1]
int verbose
Verbose level, used by statusPrint() etc.
tpcerror error
Error code.
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 tacMoveTACC(TAC *d, int from, int to)
int tacSelectTACs(TAC *d, const char *region_name, int reset, TPCSTATUS *status)
int tacFirstSelected(TAC *d)
int tacCorrectFrameOverlap(TAC *d, TPCSTATUS *status)
Correct PET frame start and end times if frames are slightly overlapping or have small gaps in betwee...
int tacAddZeroSample(TAC *d, TPCSTATUS *status)
Add an initial sample to TAC(s) with zero time and concentration.
Header file for libtpccm.
Header file for library libtpcextensions.
char * unitName(int unit_code)
Header file for libtpcfileutil.
Header file for library libtpcift.
Header file for libtpcpar.
Header file for library libtpctac.
@ TAC_FORMAT_PMOD
PMOD TAC format.
Header file for libtpctacmod.