8#include "tpcclibConfig.h"
25static char *info[] = {
26 "Simulation of PET tissue time-radioactivity concentration curves (TACs)",
27 "from arterial blood (Ca) TACs, based on compartmental model for radiowater",
28 "kinetics in the liver. Liver has two inputs, hepatic artery and portal vein.",
29 "Portal vein input is simulated by assuming that GI tract can be modelled",
30 "with time delay and dispersion of the arterial input function.",
31 "Model has two parameters for the perfusion, represented by K1a and K1p for",
32 "the arterial and portal blood flow, respectively, and a single parameter p",
33 "for the partition coefficient of water (p).",
34 "There are two delay times, LdT, which is the delay between the Ca and liver,",
35 "and PdT, which is the additional delay in the portal vein blood.",
36 "Dispersion the the GI tract is accounted for by rate constant kGI.",
37 "The volume fraction of arterial blood (Vb) is assumed to contain arterial",
38 "and portal blood in proportion to their contribution to the total blood flow.",
40 "Usage: @P [options] parfile [bloodfile simfile]",
47 "To create a template parameter file, do not enter names for arterial input",
48 "and simulated TACs.",
49 "If parameter file does not contain units, then per min and per mL units",
50 "are assumed for K1a, K1p, p, kGI, and Vb, and seconds for deley times.",
51 "For accurate results, blood TAC should have very short sampling intervals.",
53 "See also: sim_h2o, fit_wliv, liverpv, simdisp, fit_h2o, tacadd, simframe",
55 "Keywords: liver, simulation, compartmental model, perfusion, radiowater",
74int main(
int argc,
char **argv)
76 int ai, help=0, version=0, verbose=1;
77 char blofile[FILENAME_MAX], simfile[FILENAME_MAX], parfile[FILENAME_MAX];
85 if(argc==1) {
tpcPrintUsage(argv[0], info, stderr);
return(1);}
86 blofile[0]=simfile[0]=parfile[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(strcasecmp(cptr,
"TTM")==0) {
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(parfile, argv[ai++], FILENAME_MAX);
110 if(ai<argc)
strlcpy(blofile, argv[ai++], FILENAME_MAX);
111 if(ai<argc)
strlcpy(simfile, argv[ai++], FILENAME_MAX);
113 fprintf(stderr,
"Error: invalid argument '%s'.\n", argv[ai]);
119 fprintf(stderr,
"Error: missing parameter file; use option --help\n");
123 if(!simfile[0]) {fprintf(stderr,
"Error: missing file name.\n");
return(1);}
124 if(!
fileExist(parfile)) {fprintf(stderr,
"Error: parameter file not found.\n");
return(1);}
126 if(
fileExist(parfile)) {fprintf(stderr,
"Error: parameter template exists.\n");
return(1);}
132 printf(
"parfile := %s\n", parfile);
133 printf(
"blofile := %s\n", blofile);
134 printf(
"simfile := %s\n", simfile);
135 printf(
"TTM := %d\n", TTM);
148 fprintf(stderr,
"Error: cannot allocate memory for parameters.\n");
159 for(
int i=0; i<par.
tacNr; i++) {
160 sprintf(par.
r[i].
name,
"tac%d", 1+i);
192 for(ri=0; ri<par.
tacNr; ri++) {
194 par.
r[ri].
p[5]=60.0*2.17;
198 if(verbose>1) {printf(
"writing %s\n", parfile); fflush(stdout);}
200 FILE *fp; fp=fopen(parfile,
"w");
202 fprintf(stderr,
"Error: cannot open file for writing (%s)\n", parfile); fflush(stderr);
208 fprintf(stderr,
"Error: cannot write %s\n", parfile);
211 if(verbose>=0) {printf(
"%s saved.\n", parfile); fflush(stdout);}
219 if(verbose>1) fprintf(stdout,
"reading %s\n", parfile);
220 if(
parRead(&par, parfile, &status)) {
221 fprintf(stderr,
"Error: %s (%s)\n",
errorMsg(status.
error), parfile);
227 unsigned int model=par.
r[0].
model;
229 fprintf(stderr,
"Error: invalid model in parameter file.\n");
232 for(
int i=0; i<par.
tacNr; i++) {
234 if(par.
r[i].
model!=model) {
235 fprintf(stderr,
"Error: different models in parameter file.\n");
240 fprintf(stderr,
"Error: invalid parameters for selected model.\n");
245 int i_LdT=-1, i_PdT=-1, i_kGI=-1, i_K1a=-1, i_K1p=-1, i_p=-1, i_Vb=-1, i_beta=-1;
256 fprintf(stderr,
"Error: required parameters not available.\n");
260 printf(
"parameter indices:\n");
261 printf(
" K1a=p[%d]\n", i_K1a);
262 printf(
" K1p=p[%d]\n", i_K1p);
263 printf(
" p=p[%d]\n", i_p);
264 printf(
" Vb=p[%d]\n", i_Vb);
265 printf(
" LdT=p[%d]\n", i_LdT);
266 printf(
" PdT=p[%d]\n", i_PdT);
267 printf(
" kGI=p[%d]\n", i_kGI);
278 fprintf(stderr,
"Error: required parameters not available.\n");
282 printf(
"parameter indices:\n");
283 printf(
" K1a=p[%d]\n", i_K1a);
284 printf(
" K1p=p[%d]\n", i_K1p);
285 printf(
" p=p[%d]\n", i_p);
286 printf(
" Vb=p[%d]\n", i_Vb);
287 printf(
" LdT=p[%d]\n", i_LdT);
288 printf(
" beta=p[%d]\n", i_beta);
296 if(verbose>1) fprintf(stdout,
"reading input TAC\n");
299 fprintf(stderr,
"Error: %s (input files)\n",
errorMsg(status.
error));
304 printf(
"tacNr := %d\n", input.
tacNr);
305 printf(
"sampleNr := %d\n", input.
sampleNr);
312 fprintf(stderr,
"Error: missing sample times.\n");
317 fprintf(stderr,
"Error: missing concentrations.\n");
321 fprintf(stderr,
"Error: too few samples in input TAC.\n");
325 fprintf(stderr,
"Warning: too few samples for reliable simulation.\n"); fflush(stderr);
332 fprintf(stderr,
"Error: invalid sample times.\n");
340 if(verbose>1) fprintf(stdout,
"allocating space for simulated TACs\n");
352 for(
int j=0; j<sim.
sampleNr; j++) sim.
x[j]=input.
x[j];
358 if(verbose>1) {printf(
"simulating...\n"); fflush(stdout);}
359 for(
int ri=0; ri<sim.
tacNr; ri++) {
360 if(verbose>2) {printf(
" %s\n", sim.
c[ri].
name); fflush(stdout);}
364 double LdT=par.
r[ri].
p[i_LdT];
366 if(verbose>4) printf(
" LdT := %g s\n", LdT);
368 if(fabs(LdT)<1.0E-08) {
369 for(
int i=0; i<sim.
sampleNr; i++) ca[i]=input.
c[0].
y[i];
371 double buf[sim.
sampleNr];
for(
int i=0; i<sim.
sampleNr; i++) buf[i]=input.
x[i]+LdT;
372 if(
liInterpolate(buf, input.
c[0].
y, sim.
sampleNr, sim.
x, ca, NULL, NULL, sim.
sampleNr, 3, 1, 0))
374 fprintf(stderr,
"Error: cannot simulate arterial delay.\n");
382 double PdT=par.
r[ri].
p[i_PdT];
384 if(verbose>4) printf(
" PdT := %g s\n", PdT);
385 if(fabs(PdT)<1.0E-08) {
386 for(
int i=0; i<sim.
sampleNr; i++) cp[i]=ca[i];
388 double buf[sim.
sampleNr];
for(
int i=0; i<sim.
sampleNr; i++) buf[i]=input.
x[i]+LdT+PdT;
389 if(
liInterpolate(buf, input.
c[0].
y, sim.
sampleNr, sim.
x, cp, NULL, NULL, sim.
sampleNr, 3, 1, 0))
391 fprintf(stderr,
"Error: cannot simulate portal delay.\n");
395 double kGI=par.
r[ri].
p[i_kGI];
398 if(isfinite(cf)) kGI*=cf;
else kGI/=60.0;
399 if(verbose>4) printf(
" kGI := %g 1/s\n", kGI);
400 double tau=0.0;
if(kGI>0.0) tau=1.0/kGI;
401 if(verbose>4) printf(
" tauGI := %g s\n", tau);
403 fprintf(stderr,
"Error: cannot simulate dispersion.\n");
407 double beta=par.
r[ri].
p[i_beta];
409 if(verbose>4) printf(
" beta := %g s\n", beta);
418 double K1a=par.
r[ri].
p[i_K1a];
420 if(isfinite(cf)) K1a*=cf;
else K1a/=60.0;
421 if(verbose>4) printf(
" K1a := %g mL/(s*mL)\n", K1a);
423 fprintf(stderr,
"Error: invalid K1a for '%s'.\n", sim.
c[ri].
name);
426 double K1p=par.
r[ri].
p[i_K1p];
428 if(isfinite(cf)) K1p*=cf;
else K1p/=60.0;
429 if(verbose>4) printf(
" K1p := %g mL/(s*mL)\n", K1p);
431 fprintf(stderr,
"Error: invalid K1p for '%s'.\n", sim.
c[ri].
name);
434 double p=par.
r[ri].
p[i_p];
435 if(!(p>0.0) && (K1a+K1p)>0.0) {
436 fprintf(stderr,
"Error: invalid p for '%s'.\n", sim.
c[ri].
name);
440 if(verbose>4) printf(
" p := %g mL/mL\n", p);
443 k2=(K1a+K1p)/p;
if(!(k2>=0.0)) {
444 fprintf(stderr,
"Error: invalid k2 for '%s'.\n", sim.
c[ri].
name);
448 if(verbose>4) printf(
" k2 := %g 1/s\n", k2);
451 fprintf(stderr,
"Error: cannot simulate '%s'.\n", sim.
c[ri].
name);
456 double Vb=par.
r[ri].
p[i_Vb];
458 if(verbose>4) printf(
" Vb := %g mL/mL\n", Vb);
459 if(!(Vb>=0.0) || Vb>1.0) {
460 fprintf(stderr,
"Error: invalid Vb for '%s'.\n", sim.
c[ri].
name);
464 for(
int i=0; i<sim.
sampleNr; i++) sim.
c[ri].
y[i]*=(1.0-Vb);
466 for(
int i=0; i<sim.
sampleNr; i++) sim.
c[ri].
y[i]+=Vb*(K1a*ca[i]+K1p*cp[i])/(K1a+K1p);
468 for(
int i=0; i<sim.
sampleNr; i++) sim.
c[ri].
y[i]+=Vb*ca[i];
480 if(verbose>1) printf(
"writing %s\n", simfile);
481 FILE *fp; fp=fopen(simfile,
"w");
483 fprintf(stderr,
"Error: cannot open file for writing (%s)\n", simfile);
489 fprintf(stderr,
"Error (%d): %s\n", ret,
errorMsg(status.
error));
492 if(verbose>=0) {printf(
"%s saved.\n", simfile); fflush(stdout);}
int fileExist(const char *filename)
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.
char * modelCode(const unsigned int i)
unsigned int modelParNr(const unsigned int code)
unsigned int modelCodeIndex(const char *s)
int parAllocate(PAR *par, int parNr, int tacNr)
int parWrite(PAR *par, FILE *fp, parformat format, int extra, TPCSTATUS *status)
int parRead(PAR *par, const char *fname, TPCSTATUS *status)
int parFindParameter(PAR *d, const char *par_name)
int tacAllocateWithPAR(TAC *tac, PAR *par, int sampleNr, TPCSTATUS *status)
Allocate TAC based on data in PAR.
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 simC1DI(double *t, double *cba, double *cbb, const int nr, const double k1a, const double k1b, const double k2, double *ct)
int simDispersion(double *x, double *y, const int n, const double tau1, const double tau2, double *tmp)
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_PARNAME_LEN+1]
char name[MAX_TACNAME_LEN+1]
char name[MAX_TACNAME_LEN+1]
int verbose
Verbose level, used by statusPrint() etc.
tpcerror error
Error code.
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 tacXUnitConvert(TAC *tac, const int u, TPCSTATUS *status)
Header file for libtpccm.
Header file for library libtpcextensions.
@ WEIGHTING_OFF
Not weighted or weights not available (weights for all included samples are 1.0).
@ UNIT_ML_PER_ML_MIN
mL/(mL*min)
@ UNIT_ML_PER_ML_SEC
mL/(mL*sec)
double unitConversionFactor(const int u1, const int u2)
char * unitName(int unit_code)
Header file for libtpcfileutil.
Header file for library libtpcift.
Header file for libtpcpar.
@ PAR_FORMAT_TSV_UK
UK TSV (point as decimal separator).
Header file for library libtpctac.
@ TAC_FORMAT_PMOD
PMOD TAC format.
Header file for libtpctacmod.