Experiments

PKScanExperiment

Model

Datasets

Figures

PKScanExperiment

fig1

fig_dose

Code

../../experiments/pkscan.py

  

"""
Dose-dependency of pharmacokinetic parameters.
"""
from typing import Dict
import pandas as pd
import numpy as np

from sbmlsim.experiment import ExperimentDict
from sbmlsim.data import DataSet, Data
from sbmlsim.result import XResult
from sbmlsim.result.datagenerator import DataGenerator
from sbmlsim.simulation import Timecourse, TimecourseSim, ScanSim, Dimension
from sbmlsim.plot.plotting_matplotlib import Figure, Axis

from . import MidazolamSimulationExperiment


class PKScanExperiment(MidazolamSimulationExperiment):
    def simulations(self) -> Dict[str, ScanSim]:
        """ Scanning dose-response of midazolam pharmacokinetics."""
        tend = 1000  # [min]
        steps = 2000
        Q_ = self.Q_
        scan_defs = {
            "po_scan": {'PODOSE_mid': Q_(np.logspace(-1, 1.61, num=20), 'mg')},
            "iv_scan": {'IVDOSE_mid': Q_(np.logspace(-1, 1.17, num=20), 'mg')},
        }

        tcscans = ExperimentDict()
        for key, changes in scan_defs.items():
            tcscans[key] = ScanSim(simulation=
                TimecourseSim([
                    Timecourse(start=0, end=tend, steps=steps,
                               changes={
                                   **self.default_changes(),
                               })
                ]),
                dimensions=[
                    Dimension("dim_dose", changes=changes),
                    Dimension("dim_bw", changes={
                        "BW": Q_(np.linspace(start=65, stop=100, num=10), "kg"),
                    })
                ]
            )

        return tcscans

    def datagenerators(self) -> Dict[str, DataGenerator]:
        self.add_selections(selections=[
            "time", "[Cve_mid]", "[Cve_mid1oh]", "IVDOSE_mid", "PODOSE_mid"
        ])

        """
        class DataGenerator1(DataGenerator):

            def __call__(self, xresults: Dict[str, XResult], dsets=None) -> Dict[str, XResult]:
                results = {}
                for key, xres in xresults.items():
                    xres_new = XResult(xdataset=xres.xds.isel("_time", 0), udict=xres.udict, ureg=xres.ureg)
                    results[key] = xres_new


                from matplotlib import pyplot as plt

                # plt.plot(res_first['res1']["IVDOSE_mid"], res_last['res1']["Cve_mid"], 'o')
                # plt.show()
                x = (res_first['res1']["IVDOSE_mid"]).mean(dim="dim_bw")
                y = (res_last['res1']['[Cve_mid]']).mean(dim="dim_bw")
                ystd = (res_last['res1']['[Cve_mid]']).std(dim="dim_bw")

        # add some custom data calculation
        """


    def figures(self) -> Dict[str, Figure]:
        return {
            **self.fig_timecourse(),
            **self.fig_dose(),
            # **self.Fig3(),
        }

    def fig_timecourse(self) -> Dict[str, Figure]:
        unit_time = "min"
        unit_mid = "nmol/ml"
        unit_mid1oh = "nmol/ml"

        fig = Figure(self, sid="Fig1",
                     num_rows=2, num_cols=2, name=self.sid)
        plots = fig.create_plots(
            Axis("time", unit=unit_time),
            legend=True
        )

        # set titles and labs
        plots[0].set_title("scan po")
        plots[1].set_title("scan iv")
        for k in (0, 1):
            plots[k].set_yaxis("midazolam", unit_mid)
            plots[k].xaxis.label_visible = False
        for k in (2, 3):
            plots[k].set_yaxis("1-hydroxymidazolam", unit_mid1oh)

        # simulation
        for k, key in enumerate(["po_scan", "iv_scan"]):
            task_id = f"task_{key}"
            # plot midazolam
            plots[k].add_data(task=task_id, xid='time', yid='[Cve_mid]',
                              color="black")
            # plot 1-hydroxymidazolam
            plots[k+2].add_data(task=task_id, xid='time', yid='[Cve_mid1oh]',
                                color="black")

        return ExperimentDict({"fig1": fig})

    def fig_dose(self) -> Dict[str, Figure]:
        fig_id = "fig_dose"
        unit_time = "min"
        unit_mid = "nmol/ml"
        unit_mid1oh = "nmol/ml"
        unit_dose = "mg"

        fig = Figure(self, sid=fig_id,
                     num_rows=1, num_cols=2, name=self.sid)
        plots = fig.create_plots(
            legend=True
        )

        # set titles and labs
        plots[0].set_title("scan po")
        plots[1].set_title("scan iv")
        for k in (0, 1):
            plots[k].set_xaxis("dose", unit_dose)
            plots[k].set_yaxis("concentration", unit_mid)

        # simulation
        for k, sim_id in enumerate(["po_scan", "iv_scan"]):
            task_id = f"task_{sim_id}"
            xid = f"{sim_id.split('_')[0].upper()}DOSE_mid"
            for sid in ["mid", "mid1oh"]:
                plots[k].add_data(task=task_id, xid=xid, yid=f'[Cve_{sid}]',
                                  color="black", linestyle="")

        return ExperimentDict({fig_id: fig})

    '''
    def Fig3(self) -> Dict[str, Figure]:
        Q_ = self.ureg.Quantity
        unit_dose = "mg"

        # calculate all pharmacokinetic parameters from scans
        dfs = {}
        for key in self._simulations.keys():
            xres = self.results[f"task_{key}"]
            if key.startswith("midpo"):
                dose_vec = Q_(xres["PODOSE_mid"].values[0], xres.udict["PODOSE_mid"])
            elif key.startswith("midiv"):
                dose_vec = Q_(xres["IVDOSE_mid"].values[0], xres.udict["IVDOSE_mid"])
            time_vec = xres.dim_mean('time')

            pk_dicts = []
            for k, dose in enumerate(dose_vec):
                dose = dose.to("mol", "chemistry", mw=self.Mr.mid)
                conc = Q_(xres["[Cve_mid]"].sel(dim_dose=k).values, xres.udict['[Cve_mid]'])
                tcpk = TimecoursePK(
                    time=time_vec,
                    concentration=conc,
                    substance="midazolam",
                    dose=dose,
                    ureg=self.ureg
                )
                pk_dicts.append(tcpk.pk.to_dict())

            df = pd.DataFrame(pk_dicts)
            # Fix for unsorted rows
            df = df.sort_values(by=["dose"])
            dfs[key] = df

        # TODO: calculate bioavailability from simulations (oral & iv simulation)

        # visualize pharmacokinetic parameters
        figures = {}
        for pkkey in ["auc", "aucinf", "tmax", "cmax", "kel", "thalf", "vd", "vdss", "cl"]:
            print("-" * 80)
            print(f"{pkkey}")
            print("-" * 80)

            f, (ax1, ax2) = plt.subplots(nrows=1, ncols=2, figsize=(10, 5))
            f.subplots_adjust(wspace=.3, hspace=.3)
            axes = (ax1, ax2)

            kwargs = {
                "linewidth": 2.0,
                "markersize": 8,
            }
            plot_kwargs = {
                "default": {**kwargs, "color": "black"},
                "inducer": {**kwargs, "color": "green"},
                "inhibitor": {**kwargs, "color": "magenta"}
            }

            # for all conditions
            for simkey, df in dfs.items():
                print(f"\t{simkey}")

                for ax in axes:
                    # simulation type
                    ax.set_title(pkkey)
                    sim_type = simkey.split("_")[1]

                    x = self.Q_(df['dose'].values, df['dose_unit'][0]) * self.Mr.mid
                    x = x.to(unit_dose)
                    y = df[pkkey]
                    print(y)

                    if simkey.startswith("midpo"):
                        marker = "o"
                        linestyle = "-"
                        alpha = 0.5
                        label = f"po, {sim_type}"
                    elif simkey.startswith("midiv"):
                        marker = "s"
                        linestyle = "--"
                        alpha = 1.0
                        label = f"iv, {sim_type}"

                    ax.plot(x, y, label=label, marker=marker, linestyle=linestyle, alpha=alpha,
                            **plot_kwargs[sim_type])
                    ax.set_xlabel(f"dose [{unit_dose}]")
                    yunit = df[f"{pkkey}_unit"][0]
                    ax.set_ylabel(f"{pkkey} [{yunit}]")
                    #ax.legend()

            ax2.set_yscale("log")
            figures[f'fig_{pkkey}'] = f

        return figures
    '''