Source code for dcmri.kidney

import numpy as np
import dcmri.pk as pk


def params_kidney(kinetics) -> list:
    """Kidney model parameters

    Args:
        kinetics (str): kidney model. Options are: 2CF.

    Returns:
        list: Parameter short names
    """
    if kinetics == '2CF':
        return ['Fp', 'vp', 'FF', 'Tt']


[docs] def conc_kidney(ca: np.ndarray, *params, t=None, dt=1.0, sum=True, kinetics='2CF', **kwargs) -> np.ndarray: """Concentration in kidney tissues. Args: ca (array-like): concentration in the arterial input. params (tuple): free model parameters. t (array_like, optional): the time points in sec of the input function *ca*. If *t* is not provided, the time points are assumed to be uniformly spaced with spacing *dt*. Defaults to None. dt (float, optional): spacing in seconds between time points for uniformly spaced time points. This parameter is ignored if *t* is explicity provided. Defaults to 1.0. kinetics (str, optional): Kinetics of the tissue, either '2CF', 'FN' - see below for detail. Defaults to '2CF'. sum (bool, optional): For two-compartment tissues, set to True to return the total tissue concentration. Defaults to True. kwargs (dict, optional): any optional keyword parameters required by the kinetic model - see below for detail. Returns: numpy.ndarray: If sum=True, this is a 1D array with the total concentration at each time point. If sum=False this is the concentration in each compartment, and at each time point, as a 2D array with dimensions *(2,k)*, where *k* is the number of time points in *ca*. The concentration is returned in units of M. Notes: Currently implemented kinetic models are: - '2CF': two-compartment filtration model. params = (Fp, Tp, Ft, Tt,) - 'FN': free nephron model. params = (Fp, Tp, Ft, h, ). The model parameters are: - **Fp** (float, mL/sec/mL): Plasma flow. - **Tp** (float, sec): plasma mean transit time. - **Ft** (float, mL/sec/mL): tubular flow. - **Tt** (float, sec): tubular mean transit time. - **hh** (array-like, 1/sec): frequences of transit time histogram. The boundaries of the transit time bins can be provided as an array in a keyword parameter TT, which has to have one more element than h. If TT is not provided, the transit time bins are equally space in the range [0, tmax], where tmax is the largest acquisition time. Example: Plot concentration in cortex and medulla for typical values: .. plot:: :include-source: >>> import matplotlib.pyplot as plt >>> import numpy as np >>> import dcmri as dc Generate a population-average input function: >>> t = np.arange(0, 300, 1.5) >>> ca = dc.aif_parker(t, BAT=20) Define some parameters and generate plasma and tubular tissue concentrations with a 2-compartment filtration model: >>> Fp, Tp, Ft, Tt = 0.05, 10, 0.01, 120 >>> C = dc.conc_kidney(ca, Fp, Tp, Ft, Tt, t=t, sum=False, kinetics='2CF') Plot all concentrations: >>> fig, ax = plt.subplots(1,1,figsize=(6,5)) >>> ax.set_title('Kidney concentrations') >>> ax.plot(t/60, 1000*C[0,:], linestyle='--', linewidth=3.0, color='darkred', label='Plasma') >>> ax.plot(t/60, 1000*C[1,:], linestyle='--', linewidth=3.0, color='darkblue', label='Tubuli') >>> ax.plot(t/60, 1000*(C[0,:]+C[1,:]), linestyle='-', linewidth=3.0, color='grey', label='Whole kidney') >>> ax.set_xlabel('Time (min)') >>> ax.set_ylabel('Tissue concentration (mM)') >>> ax.legend() >>> plt.show() Use generate plasma and tubular tissue concentrations using the free nephron model for comparison. We assume 4 transit time bins with the following boundaries (in units of seconds): >>> TT = [0, 15, 30, 60, 120] with longest transit times most likely (note the frequences to not have to add up to 1): >>> h = [1, 2, 3, 4] >>> C = dc.conc_kidney(ca, Fp, Tp, Ft, h, t=t, sum=False, kinetics='FN', TT=TT) Plot all concentrations: >>> fig, ax = plt.subplots(1,1,figsize=(6,5)) >>> ax.set_title('Kidney concentrations') >>> ax.plot(t/60, 1000*C[0,:], linestyle='--', linewidth=3.0, color='darkred', label='Plasma') >>> ax.plot(t/60, 1000*C[1,:], linestyle='--', linewidth=3.0, color='darkblue', label='Tubuli') >>> ax.plot(t/60, 1000*(C[0,:]+C[1,:]), linestyle='-', linewidth=3.0, color='grey', label='Whole kidney') >>> ax.set_xlabel('Time (min)') >>> ax.set_ylabel('Tissue concentration (mM)') >>> ax.legend() >>> plt.show() """ if kinetics == '2CF': return _conc_kidney_2cf(ca, *params, t=t, dt=dt, sum=sum) elif kinetics == 'HF': return _conc_kidney_hf(ca, *params, t=t, dt=dt, sum=sum) elif kinetics == 'FN': # TT = [15,30,60,90,150,300,600] return _conc_kidney_fn(ca, *params, t=t, dt=dt, sum=sum, **kwargs) else: raise ValueError('Kinetic model ' + kinetics + ' is not currently implemented.')
def _conc_kidney_2cf(ca, Fp, vp, Ft, Tt, t=None, dt=1.0, sum=True): #vp = Tp*(Fp+Ft) Tp = vp/(Fp+Ft) Cp = pk.conc_comp(Fp*ca, Tp, t=t, dt=dt) cp = Cp/vp Ct = pk.conc_comp(Ft*cp, Tt, t=t, dt=dt) if sum: return Cp+Ct else: return np.stack((Cp, Ct)) def _conc_kidney_hf(ca, vp, Ft, Tt, t=None, dt=1.0, sum=True): Cp = vp*ca Ct = pk.conc_comp(Ft*ca, Tt, t=t, dt=dt) if sum: return Cp+Ct else: return np.stack((Cp, Ct)) def _conc_kidney_fn(ca, Fp, Tp, Ft, h, t=None, dt=1.0, sum=True, TT=None): if TT is None: if t is None: tmax = dt*np.size(ca) else: tmax = np.amax(t) nTT = 1+np.size(h) TT = np.linspace(0, tmax, nTT) vp = Tp*(Fp+Ft) Cp = pk.conc_plug(Fp*ca, Tp, t=t, dt=dt) cp = Cp/vp Ct = pk.conc_free(Ft*cp, h, dt=dt, TT=TT, solver='step') if sum: return Cp+Ct else: return np.stack((Cp, Ct))
[docs] def conc_kidney_cortex_medulla(ca: np.ndarray, *params, t=None, dt=1.0, sum=True, kinetics='7C'): """Concentration in kidney cortex and medulla tissues. Args: ca (array-like): concentration in the arterial input. params (tuple): free model parameters. t (array_like, optional): the time points in sec of the input function *ca*. If *t* is not provided, the time points are assumed to be uniformly spaced with spacing *dt*. Defaults to None. dt (float, optional): spacing in seconds between time points for uniformly spaced time points. This parameter is ignored if *t* is explicity provided. Defaults to 1.0. sum (bool, optional): For two-compartment tissues, set to True to return the total tissue concentration. Defaults to True. kinetics (str, optional): Kinetics of the tissue, currently only '7C' available - see below for detail. Defaults to '7F'. Returns: tuple[numpy.ndarray, numpy.ndarray]: If sum=True, each return value is a 1D array with the total concentration at each time point, in cortex and medulla, respectively. If sum=False each return value is the concentration in each compartment, and at each time point, of cortex and medulla as a 2D array with dimensions *(n,k)*, where n is the number of compartments and *k* is the number of time points in *ca*. The concentration is returned in units of M. Notes: Currently implemented kinetic models are: - '7CF': 7-compartment model. params = (Fp, Eg, fc, Tg, Tv, Tpt, Tlh, Tdt, Tcd,). Cortico-medullary model with 4 cortical compartments (glomeruli, peritubular capillaries & veins, proximal tubuli and distal tubuli) and 3 medullary compartments (peritubular capillaries & veins, list of Henle and collecting ducts). The 9 model parameters are: - **Fp** (float): Plasma flow into the tissue, in units of mL plasma per sec and per mL tissue (mL/sec/mL). - **Eg** (float): Glomerular extraction fraction - **fc** (float): Cortical flow fraction - **Tg** (float): Glomerular mean transit time in sec - **Tv** (float): Peritubular & venous mean transit time in sec - **Tpt** (float): Proximal tubuli mean transit time in sec - **Tlh** (float): Lis of Henle mean transit time in sec - **Tdt** (float): Distal tubuli mean transit time in sec - **Tcd** (float): Collecting duct mean transit time in sec Example: Plot concentration in cortex and medulla for typical values: .. plot:: :include-source: >>> import matplotlib.pyplot as plt >>> import numpy as np >>> import dcmri as dc Generate a population-average input function: >>> t = np.arange(0, 300, 1.5) >>> ca = dc.aif_parker(t, BAT=20) Use the function to generate total cortex and medulla tissue concentrations: >>> Fp, Eg, fc, Tg, Tv, Tpt, Tlh, Tdt, Tcd = 0.03, 0.15, 0.8, 4, 10, 60, 60, 30, 30 >>> Cc, Cm = dc.conc_kidney_cortex_medulla(ca, Fp, Eg, fc, Tg, Tv, Tpt, Tlh, Tdt, Tcd, t=t, kinetics='7C') Plot all concentrations: >>> fig, ax = plt.subplots(1,1,figsize=(6,5)) >>> ax.set_title('Kidney concentrations') >>> ax.plot(t/60, 1000*Cc, linestyle='-', linewidth=3.0, color='darkblue', label='Cortex') >>> ax.plot(t/60, 1000*Cm, linestyle='-', linewidth=3.0, color='darkgreen', label='Medulla') >>> ax.plot(t/60, 1000*(Cc+Cm), linestyle='-', linewidth=3.0, color='darkgrey', label='Whole kidney') >>> ax.set_xlabel('Time (min)') >>> ax.set_ylabel('Tissue concentration (mM)') >>> ax.legend() >>> plt.show() """ if kinetics == '7C': return _conc_kidney_cm9(ca, *params, t=t, dt=dt, sum=sum) else: raise ValueError('Kinetic model ' + kinetics + ' is not currently implemented.')
def _conc_kidney_cm9(ca, Fp, Eg, fc, Tg, Tv, Tpt, Tlh, Tdt, Tcd, t=None, dt=1.0, sum=True): # Flux out of the glomeruli and arterial tree Jg = pk.flux(Fp*ca, Tg, t=t, dt=dt, model='comp') # Flux out of the peritubular capillaries and venous system Jv = pk.flux((1-Eg)*Jg, Tv, t=t, dt=dt, model='comp') # Flux out of the proximal tubuli Jpt = pk.flux(Eg*Jg, Tpt, t=t, dt=dt, model='comp') # Flux out of the lis of Henle Jlh = pk.flux(Jpt, Tlh, t=t, dt=dt, model='comp') # Flux out of the distal tubuli Jdt = pk.flux(Jlh, Tdt, t=t, dt=dt, model='comp') # Flux out of the collecting ducts Jcd = pk.flux(Jdt, Tcd, t=t, dt=dt, model='comp') # Build cortical concentrations Cg = Tg*Jg # arteries/glomeruli Cv = fc*Tv*Jv # part of the peritubular capillaries Cpt = Tpt*Jpt # proximal tubuli Cdt = Tdt*Jdt # distal tubuli if sum: Ccor = Cg + Cv + Cpt + Cdt else: Ccor = np.stack((Cg, Cv, Cpt, Cdt)) # Build medullary concentrations Cv = (1-fc)*Tv*Jv # part of the peritubular capillaries Clh = Tlh*Jlh # Lis of Henle Ccd = Tcd*Jcd # collecting ducts if sum: Cmed = Cv + Clh + Ccd else: Cmed = np.stack((Cv, Clh, Ccd)) return Ccor, Cmed