8#include "tpcclibConfig.h"
24static char *info[] = {
25 "Simulation of venous BTAC (Cv) from arterial BTAC (Ca), based on",
26 "three-tissue compartmental model:",
28 " ____ K1 ____ k3 ____ k5 ____ ",
29 " | Ca | ----> | C1 | ----> | C2 | ----> | C3 | ",
30 " |____| <---- |____| <---- |____| <---- |____| ",
33 " dC1(t)/dt = K1*Ca(T) - (k2+k3)*C1(T) + k4*C2(T) ",
34 " dC2(t)/dt = k3*C1(T) - (k4+k5)*C2(T) + k6*C3(T) ",
35 " dC3(t)/dt = k5*C2(T) - k6*C3(T) ",
36 " Ct(T) = C1(T) + C2(T) + C3(T) ",
37 " Cv(T) = Ca(T) - dCt(t)/dt / f ",
39 "Usage: @P [options] parfile [abtacfile simfile]",
43 " Simulated tissue curve is written in specified file.",
46 "To create a template parameter file, do not enter names for input and",
47 "simulated TACs. Obligatory parameters are f, K1, K1/k2, k3, k3/k4.",
48 "Parameters k5 and k5/k6 are optional.",
49 "If parameter file does not contain units, then per min and per mL units",
51 "For accurate results, BTAC should have very short sampling intervals.",
52 "To reduce the model, k3 or k3/k4 can be set to 0, to apply one-tissue or",
53 "irreversible two-tissue model, respectively, or k5 or k5/k6 can be set to 0,",
54 "to apply two-tissue or irreversible three-tissue model, respectively.",
56 "See also: sim_3tcm, tacadd, taccalc, tac2svg, convexpf, fit_xexp",
58 "Keywords: input, simulation, modelling, compartmental model",
115 double b, c, d, w, z, dt2;
116 double cai, ca_last, t_last;
117 double ct1, ct1_last, ct2, ct2_last, ct3, ct3_last;
118 double ct1i, ct1i_last, ct2i, ct2i_last, ct3i, ct3i_last;
123 if(cvb==NULL)
return 2;
126 if(!(f>=0.0) || !(k1>=0.0) || k1>f)
return 3;
127 if(k3<=0.0) {k3=0.0;
if(k2<=0.0) k2=0.0;}
128 else if(k5<=0.0) {k5=0.0;
if(k4<=0.0) k4=0.0;}
129 else {
if(k6<=0.0) k6=0.0;}
132 t_last=0.0;
if(t[0]<t_last) t_last=t[0];
134 ct1_last=ct2_last=ct3_last=ct1i_last=ct2i_last=ct3i_last=0.0;
135 ct1=ct2=ct3=ct1i=ct2i=ct3i=0.0;
136 for(i=0; i<nr; i++) {
138 dt2=0.5*(t[i]-t_last);
144 cai+=(cab[i]+ca_last)*dt2;
146 b=ct1i_last+dt2*ct1_last;
147 c=ct2i_last+dt2*ct2_last;
148 d=ct3i_last+dt2*ct3_last;
149 w=k4 + k5 - (k5*k6*dt2)/(1.0+k6*dt2);
153 + k1*z*cai + (k3*k4*dt2 - (k2+k3)*z)*b
154 + k4*c + k4*k6*dt2*d/(1.0+k6*dt2)
155 ) / ( z*(1.0 + dt2*(k2+k3)) - k3*k4*dt2*dt2 );
156 ct1i = ct1i_last + dt2*(ct1_last+ct1);
158 ct2 = (k3*ct1i - w*c + k6*d/(1.0+k6*dt2)) / z;
159 ct2i = ct2i_last + dt2*(ct2_last+ct2);
161 ct3 = (k5*ct2i - k6*d) / (1.0 + k6*dt2);
162 ct3i = ct3i_last + dt2*(ct3_last+ct3);
165 double dct = k1*cab[i] - k2*ct1;
166 cvb[i] = cab[i] - dct/f;
171 if(ct!=NULL) {ct[i]=ct1+ct2+ct3;
if(fabs(ct[i])<1.0e-12) ct[i]=0.0;}
174 t_last=t[i]; ca_last=cab[i];
175 ct1_last=ct1; ct1i_last=ct1i;
176 ct2_last=ct2; ct2i_last=ct2i;
177 ct3_last=ct3; ct3i_last=ct3i;
189int main(
int argc,
char **argv)
191 int ai, help=0, version=0, verbose=1;
192 char blofile[FILENAME_MAX], simfile[FILENAME_MAX], parfile[FILENAME_MAX];
193 char tisfile[FILENAME_MAX];
194 unsigned int parNr=0;
202 if(argc==1) {
tpcPrintUsage(argv[0], info, stderr);
return(1);}
203 blofile[0]=simfile[0]=parfile[0]=tisfile[0]=(char)0;
206 for(ai=1; ai<argc; ai++)
if(*argv[ai]==
'-') {
208 char *cptr=argv[ai]+1;
if(*cptr==
'-') cptr++;
if(!*cptr)
continue;
209 if(strncasecmp(cptr,
"TTAC=", 5)==0 && strlen(cptr)>5) {
210 strlcpy(tisfile, cptr+5, FILENAME_MAX);
continue;
212 fprintf(stderr,
"Error: invalid option '%s'.\n", argv[ai]);
221 if(help==2) {
tpcHtmlUsage(argv[0], info,
"");
return(0);}
226 if(ai<argc)
strlcpy(parfile, argv[ai++], FILENAME_MAX);
227 if(ai<argc)
strlcpy(blofile, argv[ai++], FILENAME_MAX);
228 if(ai<argc)
strlcpy(simfile, argv[ai++], FILENAME_MAX);
230 fprintf(stderr,
"Error: invalid argument '%s'.\n", argv[ai]);
236 fprintf(stderr,
"Error: missing parameter file; use option --help\n");
239 if(blofile[0] && !simfile[0]) {
240 fprintf(stderr,
"Error: missing filename.\n");
243 if(tisfile[0] && (strcasecmp(tisfile, blofile)==0 || strcasecmp(tisfile, simfile)==0)) {
244 fprintf(stderr,
"Error: invalid file name for simulated TTAC.\n");
251 printf(
"parfile := %s\n", parfile);
252 printf(
"abtacfile := %s\n", blofile);
253 printf(
"simfile := %s\n", simfile);
254 if(!tisfile[0]) printf(
"ttacfile := %s\n", tisfile);
264 fprintf(stderr,
"Error: cannot allocate memory for parameters.\n");
275 for(
int i=0; i<par.
tacNr; i++) {
276 sprintf(par.
r[i].
name,
"btac%d", 1+i);
296 if(verbose>1) printf(
"writing %s\n", parfile);
297 FILE *fp; fp=fopen(parfile,
"w");
299 fprintf(stderr,
"Error: cannot open file for writing (%s)\n", parfile);
304 if(ret!=
TPCERROR_OK) {fprintf(stderr,
"Error: cannot write %s\n", parfile);
return(11);}
313 if(verbose>1) fprintf(stdout,
"reading %s\n", parfile);
314 if(
parRead(&par, parfile, &status)) {
315 fprintf(stderr,
"Error: %s (%s)\n",
errorMsg(status.
error), parfile);
321 for(
int i=0; i<par.
tacNr; i++) {
323 if((
unsigned int)par.
parNr<5) {
324 fprintf(stderr,
"Error: invalid parameters for selected model.\n");
335 fprintf(stderr,
"Error: required parameters not available.\n");
343 if(verbose>1) fprintf(stdout,
"reading input TAC\n");
347 fprintf(stderr,
"Error: %s (input files)\n",
errorMsg(status.
error));
352 printf(
"tacNr := %d\n", input.
tacNr);
353 printf(
"sampleNr := %d\n", input.
sampleNr);
359 fprintf(stderr,
"Error: too few samples in input TAC.\n");
363 fprintf(stderr,
"Warning: too few samples for reliable simulation.\n");
377 if(verbose>1) printf(
"Note: converting f from per dL to per mL.\n");
379 for(
int j=0; j<par.
tacNr; j++) par.
r[j].
p[i]*=0.01;
382 if(verbose>1) printf(
"Note: converting f from per sec to per min.\n");
385 for(
int j=0; j<par.
tacNr; j++) par.
r[j].
p[i]*=60.;
387 if(verbose>1) printf(
"Note: converting f from per min to per sec.\n");
390 for(
int j=0; j<par.
tacNr; j++) par.
r[j].
p[i]/=60.;
394 for(
int ri=1; ri<=6; ri++) {
395 char rcname[3]; sprintf(rcname,
"k%d", ri);
399 if(verbose>1) printf(
"Note: converting %s from per sec to per min.\n", rcname);
402 for(
int j=0; j<par.
tacNr; j++) par.
r[j].
p[i]*=60.;
404 if(verbose>1) printf(
"Note: converting %s from per min to per sec.\n", rcname);
407 for(
int j=0; j<par.
tacNr; j++) par.
r[j].
p[i]/=60.;
417 if(verbose>1) fprintf(stdout,
"allocating space for simulated BTACs\n");
430 for(
int j=0; j<sim.
sampleNr; j++) sim.
x[j]=input.
x[j];
434 if(verbose>1) fprintf(stdout,
"allocating space for simulated TTACs\n");
446 if(verbose>1) printf(
"simulating\n");
448 double *py=input.
c[0].
y;
449 double K1, k2, k3, k4, k5, k6, Flow;
451 for(i=0; i<par.
tacNr; i++) {
452 if(verbose>2) printf(
"simulating %s\n", sim.
c[i].
name);
454 double *pcvb=sim.
c[i].
y;
455 double *pct=NULL;
if(tisfile[0]) pct=ttac.
c[i].
y;
457 K1=k2=k3=k4=Flow=nan(
"");
464 if(!(r>0.0)) k2=nan(
"");
else k2=K1/r;
470 if(!(r>0.0)) k4=nan(
"");
else k4=k3/r;
476 if(!(r>0.0)) k6=nan(
"");
else k6=k5/r;
479 if(!(Flow>=0.0) || !(K1>=0.0) || k2<0 || k3<0 || k4<0 || k5<0 || k6<0) {
480 fprintf(stderr,
"Error: invalid rate constant.\n");
484 fprintf(stderr,
"Error: K1 cannot be higher than f.\n");
487 if(Flow==0.0) {K1=k2=k3=k4=k5=k6=0.0;}
488 if(K1==0.0) {k2=k3=k4=k5=k6=0.0;}
489 if(k3==0.0) {k4=k5=k6=0.0;}
492 printf(
"f := %g\n", Flow);
493 printf(
"K1 := %g\n", K1);
494 printf(
"k2 := %g\n", k2);
495 if(!isnan(k3)) printf(
"k3 := %g\n", k3);
496 if(!isnan(k4)) printf(
"k4 := %g\n", k4);
497 if(!isnan(k5)) printf(
"k5 := %g\n", k5);
498 if(!isnan(k6)) printf(
"k6 := %g\n", k6);
501 if(isnan(Flow)) Flow=0.0;
502 if(isnan(K1)) K1=0.0;
503 if(isnan(k2)) k2=0.0;
504 if(isnan(k3)) k3=0.0;
505 if(isnan(k4)) k4=0.0;
506 if(isnan(k5)) k5=0.0;
507 if(isnan(k6)) k6=0.0;
508 ret=
simC3vb(px, py, sim.
sampleNr, Flow, K1, k2, k3, k4, k5, k6, pcvb, pct);
510 fprintf(stderr,
"Error: invalid data for simulation.\n");
511 if(verbose>1) printf(
"sim_return_code := %d\n", ret);
523 if(verbose>1) printf(
"writing %s\n", simfile);
524 FILE *fp; fp=fopen(simfile,
"w");
526 fprintf(stderr,
"Error: cannot open file for writing (%s)\n", simfile);
532 fprintf(stderr,
"Error (%d): %s\n", ret,
errorMsg(status.
error));
535 if(verbose>=0) printf(
"%s saved.\n", simfile);
538 if(verbose>1) printf(
"writing %s\n", tisfile);
539 FILE *fp; fp=fopen(tisfile,
"w");
541 fprintf(stderr,
"Error: cannot open file for writing (%s)\n", tisfile);
547 fprintf(stderr,
"Error (%d): %s\n", ret,
errorMsg(status.
error));
550 if(verbose>=0) printf(
"%s saved.\n", tisfile);
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)
double parGetParameter(PAR *d, const char *par_name, const int ti)
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 simC3vb(double *t, double *cab, const int nr, double f, double k1, double k2, double k3, double k4, double k5, double k6, double *cvb, double *ct)
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.
int tacDuplicate(TAC *tac1, TAC *tac2)
Make a duplicate of TAC structure.
char * tacFormattxt(tacformat c)
int tacWrite(TAC *tac, FILE *fp, tacformat format, int extra, 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_DL_MIN
mL/(dL*min)
@ UNIT_ML_PER_ML_SEC
mL/(mL*sec)
char * unitName(int unit_code)
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.