TPCCLIB
Loading...
Searching...
No Matches
simblood.c File Reference

Simulation of BTAC. More...

#include "tpcclibConfig.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <string.h>
#include "tpccm.h"

Go to the source code of this file.

Functions

void icmparcInit (ICMPARC *d)
int icmparcAddMetabolites (ICMPARC *d, unsigned const int mNr)
int icmparcAllocateTACs (ICMPARC *d, unsigned const int sNr, const int sub)
void icmparcFree (ICMPARC *d)
int simBTAC (double *t, const unsigned int nr, ICMPARC *p, double *c_BA)
int simBM1 (double *t, double *ct, const int nr, const double k, double *cp)

Detailed Description

Simulation of BTAC.

Definition in file simblood.c.

Function Documentation

◆ icmparcAddMetabolites()

int icmparcAddMetabolites ( ICMPARC * d,
unsigned const int mNr )

Add sub-structures for metabolite(s) in parent ICMPARC structure.

See also
ICMPARC, icmparcInit, icmparcFree, icmparcAllocateTACs
Returns
Function returns 0 when successful, else a value >= 1.
Parameters
dPointer to parent ICMPARC; can itself be a sub-structure.
mNrNumber of metabolites to add.

Definition at line 43 of file simblood.c.

48 {
49 if(d==NULL) return(1);
50 if(d->mNr>0 && d->metabolite!=NULL) { // delete any previous metabolite(s)
51 for(unsigned int i=0; i<d->mNr; i++) icmparcFree(&d->metabolite[i]);
52 free(d->metabolite); d->mNr=0; d->metabolite=(ICMPARC*)NULL;
53 }
54 if(mNr==0) return(0);
55
56 d->metabolite=(ICMPARC*)malloc(sizeof(ICMPARC)*mNr);
57 if(d->metabolite==NULL) return(3);
58 d->mNr=mNr;
59 for(unsigned int i=0; i<mNr; i++) {
60 icmparcInit(&d->metabolite[i]);
61 d->metabolite[i].parent=d;
62 }
63 return(0);
64}
void icmparcFree(ICMPARC *d)
Definition simblood.c:125
void icmparcInit(ICMPARC *d)
Definition simblood.c:20
struct ICMPARC * parent
Definition tpccm.h:215
unsigned int mNr
Definition tpccm.h:211
struct ICMPARC * metabolite
Definition tpccm.h:213

◆ icmparcAllocateTACs()

int icmparcAllocateTACs ( ICMPARC * d,
unsigned const int sNr,
const int sub )

Allocate space for optional TACs inside ICMPARC structure.

See also
ICMPARC, icmparcInit, icmparcAddMetabolites, icmparcFree
Returns
Function returns 0 when successful, else a value >= 1.
Parameters
dPointer to ICMPARC.
sNrNumber of TAC samples (array lengths); set to zero to just free previous data.
subAllocate (1) or do not allocate (0) space for TACs inside sub-structures.

Definition at line 72 of file simblood.c.

79 {
80 if(d==NULL) return(1);
81
82 /* Delete any existing TAC data */
83 if(d->ic_BV!=NULL) free(d->ic_BV);
84 if(d->ic_TS!=NULL) free(d->ic_TS);
85 if(d->ic_TF!=NULL) free(d->ic_TF);
86 d->ic_BV=d->ic_TS=d->ic_TF=(double*)NULL;
87 if(d->c_BA!=NULL) free(d->c_BA);
88 if(d->c_BV!=NULL) free(d->c_BV);
89 if(d->c_TS!=NULL) free(d->c_TS);
90 if(d->c_TF!=NULL) free(d->c_TF);
91 d->c_BA=d->c_BV=d->c_TS=d->c_TF=(double*)NULL;
92 if(sub!=0 && d->mNr>0 && d->metabolite!=NULL) {
93 for(unsigned int i=0; i<d->mNr; i++) icmparcAllocateTACs(&d->metabolite[i], 0, sub);
94 }
95 if(sNr==0) return(0);
96
97 /* Allocate space */
98 d->c_BA=(double*)malloc(sNr*sizeof(double));
99 d->c_BV=(double*)malloc(sNr*sizeof(double));
100 d->c_TS=(double*)malloc(sNr*sizeof(double));
101 d->c_TF=(double*)malloc(sNr*sizeof(double));
102 d->ic_BV=(double*)malloc(sNr*sizeof(double));
103 d->ic_TS=(double*)malloc(sNr*sizeof(double));
104 d->ic_TF=(double*)malloc(sNr*sizeof(double));
105 if(d->c_BA==NULL || d->c_BV==NULL || d->c_TS==NULL || d->c_TF==NULL ||
106 d->ic_BV==NULL || d->ic_TS==NULL || d->ic_TF==NULL) {
107 icmparcAllocateTACs(d, 0, sub); return(3);
108 }
109 if(sub!=0 && d->mNr>0 && d->metabolite!=NULL) {
110 int ret=0;
111 for(unsigned int i=0; i<d->mNr && !ret; i++)
112 ret=icmparcAllocateTACs(&d->metabolite[i], sNr, sub);
113 if(ret) return(ret);
114 }
115
116 return(0);
117}
int icmparcAllocateTACs(ICMPARC *d, unsigned const int sNr, const int sub)
Definition simblood.c:72
double * c_BA
Definition tpccm.h:229
double * c_TF
Definition tpccm.h:235
double * ic_BV
Definition tpccm.h:223
double * ic_TF
Definition tpccm.h:227
double * c_BV
Definition tpccm.h:231
double * c_TS
Definition tpccm.h:233
double * ic_TS
Definition tpccm.h:225

Referenced by icmparcAllocateTACs().

◆ icmparcFree()

void icmparcFree ( ICMPARC * d)

Free memory that is (optionally) allocated inside the ICMPARC structure or in its sub-structures. Field values are not changed, except for pointers to allocated memory that are set to NULL.

See also
ICMPARC, icmparcInit, icmparcAddMetabolites, icmparcAllocateTACs
Parameters
dPointer to ICMPARC.

Definition at line 125 of file simblood.c.

128 {
129 if(d==NULL) return;
130 /* Free sub-structures recursively */
131 if(d->mNr>0 && d->metabolite!=NULL) {
132 for(unsigned int i=0; i<d->mNr; i++) icmparcFree(&d->metabolite[i]);
133 free(d->metabolite); d->mNr=0; d->metabolite=(ICMPARC*)NULL;
134 }
135 /* Free optional TACs */
136 if(d->ic_BV!=NULL) free(d->ic_BV);
137 if(d->ic_TS!=NULL) free(d->ic_TS);
138 if(d->ic_TF!=NULL) free(d->ic_TF);
139 d->ic_BV=d->ic_TS=d->ic_TF=(double*)NULL;
140 if(d->c_BA!=NULL) free(d->c_BA);
141 if(d->c_BV!=NULL) free(d->c_BV);
142 if(d->c_TS!=NULL) free(d->c_TS);
143 if(d->c_TF!=NULL) free(d->c_TF);
144 d->c_BA=d->c_BV=d->c_TS=d->c_TF=(double*)NULL;
145}

Referenced by icmparcAddMetabolites(), and icmparcFree().

◆ icmparcInit()

void icmparcInit ( ICMPARC * d)

Initiate the ICMPARC structure before any use.

See also
ICMPARC, icmparcAddMetabolites, icmparcFree, icmparcAllocateTACs
Parameters
dPointer to ICMPARC.

Definition at line 20 of file simblood.c.

23 {
24 if(d==NULL) return;
25 d->name[0]=(char)0;
26 d->Ti=d->Tdur=d->Irate=0.0;
27 d->k_BV_BA=0.0;
28 d->k_BA_U=d->k_BA_TF=d->k_BA_TS=0.0;
29 d->k_TF_BV=d->k_TS_BV=0.0;
30 d->mNr=0; d->metabolite=(ICMPARC*)NULL;
31 d->parent=(ICMPARC*)NULL;
32 d->kp_BV=d->kp_TF=d->kp_TS=0.0;
33 d->ic_BV=d->ic_TS=d->ic_TF=(double*)NULL;
34 d->c_BA=d->c_BV=d->c_TS=d->c_TF=(double*)NULL;
35}
double k_TF_BV
Definition tpccm.h:207
double k_BA_TS
Definition tpccm.h:205
double Tdur
Definition tpccm.h:195
double Ti
Definition tpccm.h:193
double k_BV_BA
Definition tpccm.h:199
double k_TS_BV
Definition tpccm.h:209
double kp_TF
Definition tpccm.h:219
double k_BA_U
Definition tpccm.h:201
double kp_BV
Definition tpccm.h:217
double k_BA_TF
Definition tpccm.h:203
char name[256]
Definition tpccm.h:191
double kp_TS
Definition tpccm.h:221
double Irate
Definition tpccm.h:197

Referenced by icmparcAddMetabolites().

◆ simBM1()

int simBM1 ( double * t,
double * ct,
const int nr,
const double k,
double * cp )

Calculate metabolite correct input curve from total input curve using simplistic 1K model dCmetabolite(t)/dt = k*Cparent(t) and since Ctotal(t) = Cparent(t) + Cmetabolite(t), we calculate metabolite corrected curve as dCparent(t)/dt = dCtotal(t)/dt - k*Cparent(t). Note that this model may result in negative parent values.

The units of rate constants must be related to the time unit; 1/min and min, or 1/sec and sec.

See also
simC1, simDispersion
Returns
Function returns 0 when successful, else a value >= 1.
Author
Vesa Oikonen
Parameters
tArray of time values.
ctArray of total activities.
nrNumber of values in TACs.
kRate constant of the model.
cpPointer for metabolite corrected data array to be simulated; must be allocated.

Definition at line 275 of file simblood.c.

286 {
287 int i;
288 double dt2;
289 double cp_last, t_last;
290 double cpi, cpi_last;
291
292
293 /* Check for data */
294 if(nr<2) return 1;
295 if(t==NULL || ct==NULL || cp==NULL) return 2;
296
297 /* Check actual parameter number */
298 if(!(k>=0.0)) return 3;
299
300 /* Calculate curves */
301 t_last=0.0; if(t[0]<t_last) t_last=t[0];
302 cp_last=0.0; cpi=0.0; cpi_last=0.0; cpi_last=0.0;
303 for(i=0; i<nr; i++) {
304 /* delta time / 2 */
305 dt2=0.5*(t[i]-t_last);
306 /* calculate values */
307 if(dt2<0.0) {
308 return 5;
309 } else if(dt2>0.0) {
310 cp[i] = (ct[i] - k*(cpi_last + dt2*cp_last)) / (1.0 + dt2*k);
311 cpi = cpi_last + dt2*(cp_last+cp[i]);
312 }
313 /* prepare to the next loop */
314 t_last=t[i]; cp_last=cp[i]; cpi_last=cpi;
315 }
316
317 return 0;
318}

◆ simBTAC()

int simBTAC ( double * t,
const unsigned int nr,
ICMPARC * p,
double * c_BA )

Simulate BTAC using compartmental model. NOT FUNCTIONAL!

See also
ICMPARC, icmparcInit, icmparcAddMetabolites, icmparcAllocateTACs, simDispersion, simSamples, parExampleTTACs, parExamplePerfectBolus, simDelay
Returns
Function returns 0 when successful, else a value >= 1.
Parameters
tArray of sample time values; must be non-negative and in increasing order.
nrNumber of values (samples) in TACs.
pPointer to data structure containing simulation parameters.
See also
icmparcInit, icmparcAddMetabolites, icmparcAllocateTACs
Parameters
c_BAPointer for arterial BTAC array to be simulated; must be allocated. NULL can be given, if TAC space is allocated inside p structure.

Definition at line 154 of file simblood.c.

165 {
166 /* Check for data */
167 if(nr<2 || t==NULL) return(1);
168 if(p==NULL || (c_BA==NULL && p->c_BA==NULL)) return(2);
169 if(!(t[0]>=0.0)) return(3);
170 if(p->mNr>0 && p->metabolite==NULL) return(4);
171
172 /* Calculate sum rates of metabolism */
173 double km_BV=0.0, km_TS=0.0, km_TF=0.0;
174 for(unsigned int i=0; i<p->mNr; i++) {
175 if(p->metabolite[i].kp_BV>0.0) km_BV+=p->metabolite[i].kp_BV;
176 if(p->metabolite[i].kp_TS>0.0) km_TS+=p->metabolite[i].kp_TS;
177 if(p->metabolite[i].kp_TF>0.0) km_TF+=p->metabolite[i].kp_TF;
178 }
179
180 /* Calculate compartmental TACs */
181 double t_last=0.0;
182 double ic_BA_last=0.0, c_BA_last=0.0;
183 double ic_BV_last=0.0, c_BV_last=0.0;
184 double ic_TS_last=0.0, c_TS_last=0.0;
185 double ic_TF_last=0.0, c_TF_last=0.0;
186 for(unsigned int i=0; i<nr; i++) {
187 double dt2=0.5*(t[i]-t_last); // delta time / 2
188 if(!(dt2>=0.0)) return(3);
189 else if(dt2==0.0) {
190 if(c_BA!=NULL) c_BA[i]=c_BA_last;
191 if(p->ic_BV!=NULL) p->ic_BV[i]=ic_BV_last;
192 if(p->ic_TS!=NULL) p->ic_TS[i]=ic_TS_last;
193 if(p->ic_TF!=NULL) p->ic_TF[i]=ic_TF_last;
194 if(p->c_BA!=NULL) p->c_BA[i]=c_BA_last;
195 if(p->c_BV!=NULL) p->c_BV[i]=c_BV_last;
196 if(p->c_TS!=NULL) p->c_TS[i]=c_TS_last;
197 if(p->c_TF!=NULL) p->c_TF[i]=c_TF_last;
198 continue;
199 }
200 /* Infusion integral; before infusion start 0; during infusion: time*level;
201 thereafter (infusion time)*level and level is set to 1. */
202 double ii=0.0;
203 if(p->Ti>=0.0 && p->Tdur>0.0 && t[i]>p->Ti) {
204 if(t[i] <= p->Ti + p->Tdur) ii=p->Irate*(t[i]-p->Ti); else ii=p->Irate*p->Tdur;
205 }
206 /* Helpers */
207 double rBA=1.0/(1.0+dt2*(p->k_BA_TS+p->k_BA_TF+p->k_BA_U));
208 double rTS=1.0/(1.0+dt2*(p->k_TS_BV+km_TS));
209 double rTF=1.0/(1.0+dt2*(p->k_TF_BV+km_TF));
210 double eBA=ic_BA_last+dt2*c_BA_last;
211 double eBV=ic_BV_last+dt2*c_BV_last;
212 double eTS=ic_TS_last+dt2*c_TS_last;
213 double eTF=ic_TF_last+dt2*c_TF_last;
214if(0) {
215 printf("dt2=%g\n", dt2);
216 printf("%g %g %g %g %g %g %g\n", rBA, rTS, rTF, eBA, eBV, eTS, eTF);
217}
218 /* Get integral of parent compound (if available) in compartments where it could be transformed
219 into current compound */
220 double icp_BV=0.0, icp_TS=0.0, icp_TF=0.0;
221 if(p->parent!=NULL) {
222 // copy pre-calculated values
223 if(p->parent->ic_BV!=NULL) icp_BV=p->parent->ic_BV[i];
224 if(p->parent->ic_TS!=NULL) icp_TS=p->parent->ic_TS[i];
225 if(p->parent->ic_TF!=NULL) icp_TF=p->parent->ic_TF[i];
226 }
227 /* Calculate integral of BV TAC */
228 double ic_BV;
229 ic_BV = eBV + dt2*ii - p->kp_BV*dt2*icp_BV
230 + dt2*dt2*rBA*eBA*(p->k_TS_BV*p->k_BA_TS*rTS + p->k_TF_BV*p->k_BA_TF*rTF)
231 + p->k_TS_BV*dt2*rTS*(dt2*icp_TS + eTS) + p->k_TF_BV*dt2*rTF*(dt2*icp_TF + eTF);
232 ic_BV /= 1.0 + dt2*(p->k_BV_BA + km_BV - dt2*dt2*rBA*p->k_BV_BA*(p->k_TS_BV*p->k_BA_TS*rTS + p->k_TF_BV*p->k_BA_TF*rTF));
233 /* Calculate integral of BA TAC */
234 double ic_BA = rBA * (dt2*p->k_BV_BA*ic_BV + eBA);
235 /* Calculate integrals of TTACs */
236 double ic_TS = rTS * (dt2*p->k_BA_TS*ic_BA + dt2*p->kp_TS*icp_TS + eTS);
237 double ic_TF = rTF * (dt2*p->k_BA_TF*ic_BA + dt2*p->kp_TF*icp_TF + eTF);
238 /* Prepare for the next sample */
239 t_last=t[i];
240 ic_BV_last=ic_BV; c_BV_last=(ic_BV-eBV)/dt2;
241 ic_BA_last=ic_BA; c_BA_last=(ic_BA-eBA)/dt2;
242 ic_TS_last=ic_TS; c_TS_last=(ic_TS-eTS)/dt2;
243 ic_TF_last=ic_TF; c_TF_last=(ic_TF-eTF)/dt2;
244 /* Copy sample concentration to output TAC */
245 if(c_BA!=NULL) c_BA[i]=c_BA_last;
246 /* If requested for metabolite calculations, copy also the compartmental TAC integrals */
247 if(p->ic_BV!=NULL) p->ic_BV[i]=ic_BV;
248 if(p->ic_TS!=NULL) p->ic_TS[i]=ic_TS;
249 if(p->ic_TF!=NULL) p->ic_TF[i]=ic_TF;
250 /* If requested, copy also the compartmental TACs */
251 if(p->c_BA!=NULL) p->c_BA[i]=c_BA_last;
252 if(p->c_BV!=NULL) p->c_BV[i]=c_BV_last;
253 if(p->c_TS!=NULL) p->c_TS[i]=c_TS_last;
254 if(p->c_TF!=NULL) p->c_TF[i]=c_TF_last;
255 }
256 return(0);
257}