diff --git a/pkpd/plots/__init__.py b/pkpd/plots/__init__.py
index 055e5f0..d251bd5 100644
--- a/pkpd/plots/__init__.py
+++ b/pkpd/plots/__init__.py
@@ -7,7 +7,8 @@
 
 from ._scatter import (  # noqa
     plot_measurements,
-    plot_measurements_and_predictions
+    plot_measurements_and_predictions,
+    plot_measurements_and_simulation
 )
 
 from ._box import (  # noqa
diff --git a/pkpd/plots/_scatter.py b/pkpd/plots/_scatter.py
index b7bc461..68852d1 100644
--- a/pkpd/plots/_scatter.py
+++ b/pkpd/plots/_scatter.py
@@ -33,13 +33,13 @@ def plot_measurements(data):
 
     if not isinstance(data, pd.DataFrame):
         raise ValueError(
-            'Input data <' + str(data) + '> has to be pandas.DataFrame.')
+            'Data has to be pandas.DataFrame.')
 
     keys = ['#ID', 'TIME in day', 'TUMOUR VOLUME in cm^3', 'BODY WEIGHT in g']
     for key in keys:
         if key not in data.keys():
             raise ValueError(
-                'Input data <' + str(data) + '> must have key <' + str(key) +
+                'Data must have key <' + str(key) +
                 '>.')
 
     # Get ids
@@ -211,13 +211,13 @@ def plot_measurements_and_predictions(data, model, parameters):
     # Check data has the correct type
     if not isinstance(data, pd.DataFrame):
         raise TypeError(
-            'Data <' + str(data) + '> has to be pandas.DataFrame.')
+            'Data has to be pandas.DataFrame.')
     # Check that data has the required keys
     keys = ['#ID', 'TIME in day', 'TUMOUR VOLUME in cm^3', 'BODY WEIGHT in g']
     for key in keys:
         if key not in data.keys():
             raise ValueError(
-                'Data <' + str(data) + '> must have key <' + str(key) +
+                'Data must have key <' + str(key) +
                 '>.')
     # Check that model has the correct type
     if not isinstance(model, pints.ForwardModel):
@@ -349,3 +349,316 @@ def plot_measurements_and_predictions(data, model, parameters):
     )
 
     return fig
+
+
+def plot_measurements_and_simulation(
+        data, model, default_parameters, min_parameters, max_parameters,
+        parameter_names=None, steps=50):
+    """
+    Returns a `plotly.graph_objects.Figure` containing the data and simulation
+    with interactive sliders.
+
+    This function assumes the following keys naming convention:
+        ids: '#ID'
+        time: 'TIME in day'
+        tumour volume: 'TUMOUR VOLUME in cm^3
+
+    The axis labels as well as the hoverinfo assume that time is measured in
+    day, volume is measured in cm^3.
+
+    Arguments:
+        data -- A pandas.DataFrame containing the measured time-series data of
+                the tumour volume and the mass.
+        model -- A `pints.ForwardModel`.
+        parameters -- An array-like object with the model parameters for each
+                      individual in the dataset.
+                      Shape: (n_individuals, n_parameters)
+    """
+    # Check data has the correct type
+    if not isinstance(data, pd.DataFrame):
+        raise TypeError(
+            'Data has to be pandas.DataFrame.')
+    # Check that data has the required keys
+    keys = ['#ID', 'TIME in day', 'TUMOUR VOLUME in cm^3', 'BODY WEIGHT in g']
+    for key in keys:
+        if key not in data.keys():
+            raise ValueError(
+                'Data must have key <' + str(key) +
+                '>.')
+    # Check that model has the correct type
+    if not isinstance(model, pints.ForwardModel):
+        raise TypeError(
+            'Model needs to be an instance of `pints.ForwardModel`.')
+    # Check that model has only one output dimension
+    if model.n_outputs() != 1:
+        raise ValueError(
+            'Model output dimension has to be 1.')
+    # Check that parameters have the correct dimensions
+    default_parameters = np.asarray(default_parameters)
+    if default_parameters.ndim != 1:
+        raise ValueError(
+            'Default parameters need to have dimension 1. `default_parameters`'
+            ' has dimension <' + str(default_parameters.ndim) + '>.')
+    min_parameters = np.asarray(min_parameters)
+    if min_parameters.ndim != 1:
+        raise ValueError(
+            'Minimum parameters need to have dimension 1. `min_parameters` has'
+            ' dimension <' + str(min_parameters.ndim) + '>.')
+    max_parameters = np.asarray(max_parameters)
+    if max_parameters.ndim != 1:
+        raise ValueError(
+            'Maximum parameters need to have dimension 1. `max_parameters` has'
+            ' dimension <' + str(max_parameters.ndim) + '>.')
+    # Check that parameters have the correct shape
+    if default_parameters.shape != (model.n_parameters(),):
+        raise ValueError(
+            'Default parameters do not have the correct shape. Expected '
+            'shape (n_parameters,) = ' + str((model.n_parameters(),)) + '.')
+    if min_parameters.shape != (model.n_parameters(),):
+        raise ValueError(
+            'Minimum parameters do not have the correct shape. Expected shape '
+            '(n_parameters,) = ' + str((model.n_parameters(),)) + '.')
+    if max_parameters.shape != (model.n_parameters(),):
+        raise ValueError(
+            'Maximum parameters do not have the correct shape. Expected shape '
+            '(n_parameters,) = ' + str((model.n_parameters(),)) + '.')
+
+    if parameter_names is None:
+        parameter_names = [
+            'Parameter %d' % n for n in range(model.n_parameters())]
+
+    # Check parameter names
+    if len(parameter_names) != model.n_parameters():
+        raise ValueError(
+            'Number of parameter names does not match number of parameters.')
+
+    # Define colorscheme
+    n_ids = len(data['#ID'].unique())
+    colors = plotly.colors.qualitative.Plotly[:n_ids]
+
+    # Create figure
+    fig = go.Figure()
+
+    # Plot simulation for each slider step
+    _add_slider_step_plots(
+        fig, data, model, default_parameters, min_parameters, max_parameters,
+        steps)
+
+    # Scatter plot of control growth data
+    _add_data(fig, data, colors)
+
+    # Set X, Y axis and figure size
+    fig.update_layout(
+        autosize=True,
+        xaxis_title=r'$\text{Time in day}$',
+        yaxis_title=r'$\text{Tumour volume in cm}^3$',
+        template="plotly_white")
+
+    # Create parameter sliders
+    sliders = _create_sliders(
+        parameter_names, min_parameters, max_parameters, steps, data)
+
+    # Add switch between linear and log y-scale
+    fig.update_layout(
+        sliders=sliders,
+        updatemenus=[
+            dict(
+                type="buttons",
+                direction="left",
+                buttons=list([
+                    dict(
+                        args=[{"yaxis.type": "linear"}],
+                        label="Linear y-scale",
+                        method="relayout"
+                    ),
+                    dict(
+                        args=[{"yaxis.type": "log"}],
+                        label="Log y-scale",
+                        method="relayout"
+                    )
+                ]),
+                pad={"r": 0, "t": -10},
+                showactive=True,
+                x=0.0,
+                xanchor="left",
+                y=1.15,
+                yanchor="top"
+            ),
+            dict(
+                type="buttons",
+                direction="down",
+                buttons=list([
+                    dict(
+                        args=[{
+                            "sliders[0].visible": True,
+                            "sliders[1].visible": False,
+                            "sliders[2].visible": False}],
+                        label="Initial volume",
+                        method="relayout"
+                    ),
+                    dict(
+                        args=[{
+                            "sliders[0].visible": False,
+                            "sliders[1].visible": True,
+                            "sliders[2].visible": False}],
+                        label="Exp. growth rate",
+                        method="relayout"
+                    ),
+                    dict(
+                        args=[{
+                            "sliders[0].visible": False,
+                            "sliders[1].visible": False,
+                            "sliders[2].visible": True}],
+                        label="Lin. growth rate",
+                        method="relayout"
+                    )
+                ]),
+                pad={"r": 0, "t": -10},
+                showactive=True,
+                x=1.07,
+                xanchor="left",
+                y=-0.1,
+                yanchor="top"
+            ),
+        ]
+    )
+
+    return fig
+
+
+def _add_data(fig, data, colors):
+    """
+    Adds a scatter plot of the data to the figure.
+    """
+    ids = data['#ID'].unique()
+    for index, id_m in enumerate(ids):
+        # Create mask for mouse
+        mask = data['#ID'] == id_m
+
+        # Get observed data for indiviudal
+        observed_times = data['TIME in day'][mask].to_numpy()
+        observed_data = data['TUMOUR VOLUME in cm^3'][mask]
+
+        # Plot data
+        fig.add_trace(go.Scatter(
+            x=observed_times,
+            y=observed_data,
+            legendgroup="ID: %d" % id_m,
+            name="ID: %d" % id_m,
+            showlegend=True,
+            hovertemplate=(
+                "<b>Measurement </b><br>" +
+                "ID: %d<br>" % id_m +
+                "Time: %{x:} day<br>" +
+                "Tumour volume: %{y:.02f} cm^3<br>" +
+                "Cancer type: LXF A677<br>" +
+                "<extra></extra>"),
+            mode="markers",
+            marker=dict(
+                symbol='circle',
+                opacity=0.7,
+                line=dict(color='black', width=1),
+                color=colors[index])
+        ))
+
+
+def _add_slider_step_plots(
+        fig, data, model, parameters, min_parameters, max_parameters, steps):
+    """
+    Add a plot for each slider step to the figure.
+    """
+    # Define time range based on data
+    start_experiment = data['TIME in day'].min()
+    end_experiment = data['TIME in day'].max()
+    simulated_times = np.linspace(
+        start=start_experiment, stop=end_experiment)
+
+    # Add plot for each slider step
+    for param_id in range(model.n_parameters()):
+        # Get default parameters
+        params = parameters.copy()
+
+        # Create line plot for each slider value
+        for value_id, value in enumerate(np.linspace(
+                start=min_parameters[param_id],
+                stop=max_parameters[param_id], num=steps)):
+            # Update parameters
+            params[param_id] = value
+
+            # Solve model
+            simulated_data = model.simulate(params, simulated_times)
+
+            # Show only first plot
+            visible = False
+            if param_id == 0 and value_id == 10:
+                visible = True
+
+            # Plot slider step
+            fig.add_trace(go.Scatter(
+                x=simulated_times,
+                y=simulated_data,
+                legendgroup="Model",
+                name="Model",
+                showlegend=True,
+                hovertemplate=(
+                    "<b>Simulation </b><br>" +
+                    "Time: %{x:.0f} day<br>" +
+                    "Tumour volume: %{y:.02f} cm^3<br>" +
+                    "Cancer type: LXF A677<br>" +
+                    "<br>" +
+                    "<b>Parameters </b><br>" +
+                    "Initial tumour volume: %.02f cm^3<br>" % params[0] +
+                    "Exp. growth rate: %.02f 1/day<br>" % params[1] +
+                    "Lin. growth rate: %.02f cm^3/day<br>" % params[2] +
+                    "<extra></extra>"),
+                visible=visible,
+                mode="lines",
+                line=dict(color='Black')
+            ))
+
+
+def _create_sliders(
+        parameter_names, min_parameters, max_parameters, steps, data):
+    """
+    Returns slider objects that can be used in plotly's `update_layout`.
+    """
+    # Get number of parameters and measured individuals
+    n_params = len(parameter_names)
+    n_ids = len(data['#ID'].unique())
+
+    # Create slider object for each parameter
+    sliders = []
+    for param_id in range(n_params):
+        # Compute parameter values
+        values = np.linspace(
+            start=min_parameters[param_id], stop=max_parameters[param_id],
+            num=steps)
+
+        # Display plot for slider position and data
+        slider_steps = []
+        for step in range(steps):
+            # All simulations False and data True
+            s = dict(
+                method="update",
+                args=[{
+                    "visible": [False] * (n_params * steps) +
+                    [True] * n_ids}],
+                label='%.02f' % values[step])
+
+            # Make correct simulation visible
+            s["args"][0]["visible"][param_id * steps + step] = True
+
+            # Safe slider steps
+            slider_steps.append(s)
+
+        # Save slider
+        sliders.append(
+            dict(
+                visible=True if param_id == 0 else False,
+                active=10,
+                currentvalue=dict(
+                    prefix=parameter_names[param_id] + ': '),
+                pad={"t": 50},
+                steps=slider_steps))
+
+    return sliders

define a plot function with allows model exploration with parameter sliders
diff --git a/pkpd/tests/test_plots_scatter.py b/pkpd/tests/test_plots_scatter.py
index 9e589c7..b9073e9 100644
--- a/pkpd/tests/test_plots_scatter.py
+++ b/pkpd/tests/test_plots_scatter.py
@@ -44,14 +44,16 @@ class TestPlotMeasurements(unittest.TestCase):
         data = np.ones(shape=(10, 4))
 
         self.assertRaisesRegex(
-            ValueError, 'Input data <', pkpd.plots.plot_measurements, data)
+            ValueError, 'Data has to be pandas.DataFrame.',
+            pkpd.plots.plot_measurements, data)
 
     def test_bad_column_keys(self):
 
         data = self.data.rename(columns={'TIME in day': 'SOMETHING ELSE'})
 
         self.assertRaisesRegex(
-            ValueError, 'Input data <', pkpd.plots.plot_measurements, data)
+            ValueError, 'Data must have key <',
+            pkpd.plots.plot_measurements, data)
 
     def test_create_figure(self):
 
@@ -90,7 +92,7 @@ class TestPlotMeasurementsAndPredictions(unittest.TestCase):
         data = np.ones(shape=(10, 4))
 
         self.assertRaisesRegex(
-            TypeError, 'Data <',
+            TypeError, 'Data has to be pandas.DataFrame.',
             pkpd.plots.plot_measurements_and_predictions, data, self.model,
             self.parameters)
 
@@ -99,7 +101,7 @@ class TestPlotMeasurementsAndPredictions(unittest.TestCase):
         data = self.data.rename(columns={'TIME in day': 'SOMETHING ELSE'})
 
         self.assertRaisesRegex(
-            ValueError, 'Data <',
+            ValueError, 'Data must have key <',
             pkpd.plots.plot_measurements_and_predictions, data, self.model,
             self.parameters)
 
@@ -159,5 +161,159 @@ class TestPlotMeasurementsAndPredictions(unittest.TestCase):
         self.assertIsInstance(fig, go.Figure)
 
 
+class TestPlotMeasurementsAndSimulation(unittest.TestCase):
+    """
+    Tests the `pkpd.plots.plot_mesurements_and_simulation` function.
+    """
+
+    @classmethod
+    def setUpClass(cls):
+        # Create test dataset
+        ids = [0, 0, 0, 1, 1, 1, 2, 2]
+        times = [0, 1, 2, 2, np.nan, 4, 1, 3]
+        volumes = [np.nan, 0.3, 0.2, 0.5, 0.1, 0.2, 0.234, 0]
+        masses = [1, 1, 1, 1, 1, 1, 1, 1]
+        cls.data = pd.DataFrame({
+            '#ID': ids,
+            'TIME in day': times,
+            'TUMOUR VOLUME in cm^3': volumes,
+            'BODY WEIGHT in g': masses})
+
+        # Create test model
+        path = pkpd.ModelLibrary().get_path('Tumour growth without treatment')
+        cls.model = pkpd.PharmacodynamicModel(path)
+
+        # Create test parameters
+        cls.default_params = [0.1, 0.1, 0.1]
+        cls.min_params = [0.01, 0.02, 0.03]
+        cls.max_params = [1, 2, 3]
+
+    def test_bad_data_type(self):
+
+        data = np.ones(shape=(10, 4))
+
+        self.assertRaisesRegex(
+            TypeError, 'Data has to be pandas.DataFrame.',
+            pkpd.plots.plot_measurements_and_simulation, data, self.model,
+            self.default_params, self.min_params, self.max_params)
+
+    def test_bad_column_keys(self):
+
+        data = self.data.rename(columns={'TIME in day': 'SOMETHING ELSE'})
+
+        self.assertRaisesRegex(
+            ValueError, 'Data must have key <',
+            pkpd.plots.plot_measurements_and_simulation, data, self.model,
+            self.default_params, self.min_params, self.max_params)
+
+    def test_bad_model_type(self):
+
+        model = 'bad model'
+
+        self.assertRaisesRegex(
+            TypeError, 'Model needs to be an instance of',
+            pkpd.plots.plot_measurements_and_simulation, self.data, model,
+            self.default_params, self.min_params, self.max_params)
+
+    def test_bad_model_n_output(self):
+
+        # Create model
+        path = pkpd.ModelLibrary().get_path('Tumour growth without treatment')
+        model = pkpd.PharmacodynamicModel(path)
+
+        # Change to multi-output model
+        model.set_outputs(['myokit.tumour_volume', 'myokit.tumour_volume'])
+
+        self.assertRaisesRegex(
+            ValueError, 'Model output dimension has to be 1.',
+            pkpd.plots.plot_measurements_and_simulation, self.data, model,
+            self.default_params, self.min_params, self.max_params)
+
+    def test_bad_default_parameters_dimension(self):
+
+        parameters = np.ones(shape=(3, 3))
+
+        self.assertRaisesRegex(
+            ValueError, 'Default parameters need to have dimension 1.',
+            pkpd.plots.plot_measurements_and_simulation, self.data, self.model,
+            parameters, self.min_params, self.max_params)
+
+    def test_bad_min_parameters_dimension(self):
+
+        parameters = np.ones(shape=(3, 3))
+
+        self.assertRaisesRegex(
+            ValueError, 'Minimum parameters need to have dimension 1.',
+            pkpd.plots.plot_measurements_and_simulation, self.data, self.model,
+            self.default_params, parameters, self.max_params)
+
+    def test_bad_max_parameters_dimension(self):
+
+        parameters = np.ones(shape=(3, 3))
+
+        self.assertRaisesRegex(
+            ValueError, 'Maximum parameters need to have dimension 1.',
+            pkpd.plots.plot_measurements_and_simulation, self.data, self.model,
+            self.default_params, self.min_params, parameters)
+
+    def test_bad_default_parameters_shape(self):
+
+        parameters = np.ones(shape=(10,))
+
+        self.assertRaisesRegex(
+            ValueError, 'Default parameters do not have the correct shape.',
+            pkpd.plots.plot_measurements_and_simulation, self.data, self.model,
+            parameters, self.min_params, self.max_params)
+
+    def test_bad_min_parameters_shape(self):
+
+        parameters = np.ones(shape=(10,))
+
+        self.assertRaisesRegex(
+            ValueError, 'Minimum parameters do not have the correct shape.',
+            pkpd.plots.plot_measurements_and_simulation, self.data, self.model,
+            self.default_params, parameters, self.max_params)
+
+    def test_bad_max_parameters_shape(self):
+
+        parameters = np.ones(shape=(10,))
+
+        self.assertRaisesRegex(
+            ValueError, 'Maximum parameters do not have the correct shape.',
+            pkpd.plots.plot_measurements_and_simulation, self.data, self.model,
+            self.default_params, self.min_params, parameters)
+
+    def test_parameter_names(self):
+
+        # Test bad parameter names
+        param_names = ['param 1', 'param 2']
+
+        self.assertRaisesRegex(
+            ValueError, 'Number of parameter names does not match number of',
+            pkpd.plots.plot_measurements_and_simulation, self.data, self.model,
+            self.default_params, self.min_params, self.max_params, param_names)
+
+        # Good parameter names
+        param_names = ['param 1', 'param 2', 'param 3']
+        fig = pkpd.plots.plot_measurements_and_simulation(
+            self.data, self.model, self.default_params, self.min_params,
+            self.max_params, param_names)
+
+        # Check all labels
+        sliders = fig.layout.sliders
+        self.assertEqual(len(sliders), 3)
+        self.assertEqual(sliders[0].currentvalue.prefix, param_names[0] + ': ')
+        self.assertEqual(sliders[1].currentvalue.prefix, param_names[1] + ': ')
+        self.assertEqual(sliders[2].currentvalue.prefix, param_names[2] + ': ')
+
+    def test_create_figure(self):
+
+        fig = pkpd.plots.plot_measurements_and_simulation(
+            self.data, self.model, self.default_params, self.min_params,
+            self.max_params)
+
+        self.assertIsInstance(fig, go.Figure)
+
+
 if __name__ == '__main__':
     unittest.main()

pip install -e .[dev]
parse_log_pytest
pytest
pytest
apt-get update apt-get install -y gcc libsundials-dev
3.8
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
anyio==4.5.2
argon2-cffi==23.1.0
argon2-cffi-bindings==21.2.0
arrow==1.3.0
asttokens==3.0.0
async-lru==2.0.4
attrs==25.3.0
babel==2.17.0
backcall==0.2.0
beautifulsoup4==4.13.3
bleach==6.1.0
certifi==2025.1.31
cffi==1.17.1
charset-normalizer==3.4.1
cma==4.0.0
comm==0.2.2
configparser==7.1.0
contourpy==1.1.1
cycler==0.12.1
debugpy==1.8.13
decorator==5.2.1
defusedxml==0.7.1
exceptiongroup @ file:///croot/exceptiongroup_1706031385326/work
executing==2.2.0
fastjsonschema==2.21.1
fonttools==4.56.0
fqdn==1.5.1
h11==0.14.0
httpcore==1.0.7
httpx==0.28.1
idna==3.10
importlib_metadata==8.5.0
importlib_resources==6.4.5
iniconfig @ file:///home/linux1/recipes/ci/iniconfig_1610983019677/work
ipykernel==6.29.5
ipython==8.12.3
ipywidgets==8.1.5
isoduration==20.11.0
jedi==0.19.2
Jinja2==3.1.6
json5==0.10.0
jsonpointer==3.0.0
jsonschema==4.23.0
jsonschema-specifications==2023.12.1
jupyter==1.0.0
jupyter-console==6.6.3
jupyter-events==0.10.0
jupyter-lsp==2.2.5
jupyter_client==8.6.3
jupyter_core==5.7.2
jupyter_server==2.14.2
jupyter_server_terminals==0.5.3
jupyterlab==4.3.6
jupyterlab_pygments==0.3.0
jupyterlab_server==2.27.3
jupyterlab_widgets==3.0.13
kiwisolver==1.4.7
lxml==5.3.1
MarkupSafe==2.1.5
matplotlib==3.7.5
matplotlib-inline==0.1.7
mistune==3.1.3
myokit==1.37.3
nbclient==0.10.1
nbconvert==7.16.6
nbformat==5.10.4
nest-asyncio==1.6.0
notebook==7.3.3
notebook_shim==0.2.4
numpy==1.24.4
overrides==7.7.0
packaging @ file:///croot/packaging_1720101850331/work
pandas==2.0.3
pandocfilters==1.5.1
parso==0.8.4
pexpect==4.9.0
pickleshare==0.7.5
pillow==10.4.0
pints==0.5.0
pkgutil_resolve_name==1.3.10
-e git+https://github.com/DavAug/ErlotinibGefitinib.git@f6fe6ede9e62da9a78b1130efc12d2a2fe95af5f#egg=pkpd
platformdirs==4.3.6
plotly==4.8.1
pluggy @ file:///tmp/build/80754af9/pluggy_1648042571233/work
prometheus_client==0.21.1
prompt_toolkit==3.0.50
psutil==7.0.0
ptyprocess==0.7.0
pure_eval==0.2.3
pycparser==2.22
Pygments==2.19.1
pyparsing==3.1.4
pytest @ file:///croot/pytest_1717793244625/work
python-dateutil==2.9.0.post0
python-json-logger==3.3.0
pytz==2025.2
PyYAML==6.0.2
pyzmq==26.3.0
qtconsole==5.6.1
QtPy==2.4.3
referencing==0.35.1
requests==2.32.3
retrying==1.3.4
rfc3339-validator==0.1.4
rfc3986-validator==0.1.1
rpds-py==0.20.1
scipy==1.10.1
Send2Trash==1.8.3
six==1.17.0
sniffio==1.3.1
soupsieve==2.6
stack-data==0.6.3
tabulate==0.9.0
terminado==0.18.1
threadpoolctl==3.5.0
tinycss2==1.2.1
tomli @ file:///opt/conda/conda-bld/tomli_1657175507142/work
tornado==6.4.2
tqdm==4.46.1
traitlets==5.14.3
types-python-dateutil==2.9.0.20241206
typing_extensions==4.13.0
tzdata==2025.2
uri-template==1.3.0
urllib3==2.2.3
wcwidth==0.2.13
webcolors==24.8.0
webencodings==0.5.1
websocket-client==1.8.0
widgetsnbextension==4.0.13
zipp==3.20.2

name: ErlotinibGefitinib
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - exceptiongroup=1.2.0=py38h06a4308_0
  - iniconfig=1.1.1=pyhd3eb1b0_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=3.0.16=h5eee18b_0
  - packaging=24.1=py38h06a4308_0
  - pip=24.2=py38h06a4308_0
  - pluggy=1.0.0=py38h06a4308_1
  - pytest=7.4.4=py38h06a4308_0
  - python=3.8.20=he870216_0
  - readline=8.2=h5eee18b_0
  - setuptools=75.1.0=py38h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tomli=2.0.1=py38h06a4308_0
  - wheel=0.44.0=py38h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - anyio==4.5.2
      - argon2-cffi==23.1.0
      - argon2-cffi-bindings==21.2.0
      - arrow==1.3.0
      - asttokens==3.0.0
      - async-lru==2.0.4
      - attrs==25.3.0
      - babel==2.17.0
      - backcall==0.2.0
      - beautifulsoup4==4.13.3
      - bleach==6.1.0
      - certifi==2025.1.31
      - cffi==1.17.1
      - charset-normalizer==3.4.1
      - cma==4.0.0
      - comm==0.2.2
      - configparser==7.1.0
      - contourpy==1.1.1
      - cycler==0.12.1
      - debugpy==1.8.13
      - decorator==5.2.1
      - defusedxml==0.7.1
      - executing==2.2.0
      - fastjsonschema==2.21.1
      - fonttools==4.56.0
      - fqdn==1.5.1
      - h11==0.14.0
      - httpcore==1.0.7
      - httpx==0.28.1
      - idna==3.10
      - importlib-metadata==8.5.0
      - importlib-resources==6.4.5
      - ipykernel==6.29.5
      - ipython==8.12.3
      - ipywidgets==8.1.5
      - isoduration==20.11.0
      - jedi==0.19.2
      - jinja2==3.1.6
      - json5==0.10.0
      - jsonpointer==3.0.0
      - jsonschema==4.23.0
      - jsonschema-specifications==2023.12.1
      - jupyter==1.0.0
      - jupyter-client==8.6.3
      - jupyter-console==6.6.3
      - jupyter-core==5.7.2
      - jupyter-events==0.10.0
      - jupyter-lsp==2.2.5
      - jupyter-server==2.14.2
      - jupyter-server-terminals==0.5.3
      - jupyterlab==4.3.6
      - jupyterlab-pygments==0.3.0
      - jupyterlab-server==2.27.3
      - jupyterlab-widgets==3.0.13
      - kiwisolver==1.4.7
      - lxml==5.3.1
      - markupsafe==2.1.5
      - matplotlib==3.7.5
      - matplotlib-inline==0.1.7
      - mistune==3.1.3
      - myokit==1.37.3
      - nbclient==0.10.1
      - nbconvert==7.16.6
      - nbformat==5.10.4
      - nest-asyncio==1.6.0
      - notebook==7.3.3
      - notebook-shim==0.2.4
      - numpy==1.24.4
      - overrides==7.7.0
      - pandas==2.0.3
      - pandocfilters==1.5.1
      - parso==0.8.4
      - pexpect==4.9.0
      - pickleshare==0.7.5
      - pillow==10.4.0
      - pints==0.5.0
      - pkgutil-resolve-name==1.3.10
      - platformdirs==4.3.6
      - plotly==4.8.1
      - prometheus-client==0.21.1
      - prompt-toolkit==3.0.50
      - psutil==7.0.0
      - ptyprocess==0.7.0
      - pure-eval==0.2.3
      - pycparser==2.22
      - pygments==2.19.1
      - pyparsing==3.1.4
      - python-dateutil==2.9.0.post0
      - python-json-logger==3.3.0
      - pytz==2025.2
      - pyyaml==6.0.2
      - pyzmq==26.3.0
      - qtconsole==5.6.1
      - qtpy==2.4.3
      - referencing==0.35.1
      - requests==2.32.3
      - retrying==1.3.4
      - rfc3339-validator==0.1.4
      - rfc3986-validator==0.1.1
      - rpds-py==0.20.1
      - scipy==1.10.1
      - send2trash==1.8.3
      - six==1.17.0
      - sniffio==1.3.1
      - soupsieve==2.6
      - stack-data==0.6.3
      - tabulate==0.9.0
      - terminado==0.18.1
      - threadpoolctl==3.5.0
      - tinycss2==1.2.1
      - tornado==6.4.2
      - tqdm==4.46.1
      - traitlets==5.14.3
      - types-python-dateutil==2.9.0.20241206
      - typing-extensions==4.13.0
      - tzdata==2025.2
      - uri-template==1.3.0
      - urllib3==2.2.3
      - wcwidth==0.2.13
      - webcolors==24.8.0
      - webencodings==0.5.1
      - websocket-client==1.8.0
      - widgetsnbextension==4.0.13
      - zipp==3.20.2
prefix: /opt/conda/envs/ErlotinibGefitinib

pkpd/tests/test_plots_scatter.py::TestPlotMeasurements::test_bad_column_keys pkpd/tests/test_plots_scatter.py::TestPlotMeasurements::test_bad_input pkpd/tests/test_plots_scatter.py::TestPlotMeasurementsAndPredictions::test_bad_column_keys pkpd/tests/test_plots_scatter.py::TestPlotMeasurementsAndPredictions::test_bad_data_type pkpd/tests/test_plots_scatter.py::TestPlotMeasurementsAndSimulation::test_bad_column_keys pkpd/tests/test_plots_scatter.py::TestPlotMeasurementsAndSimulation::test_bad_data_type pkpd/tests/test_plots_scatter.py::TestPlotMeasurementsAndSimulation::test_bad_default_parameters_dimension pkpd/tests/test_plots_scatter.py::TestPlotMeasurementsAndSimulation::test_bad_default_parameters_shape pkpd/tests/test_plots_scatter.py::TestPlotMeasurementsAndSimulation::test_bad_max_parameters_dimension pkpd/tests/test_plots_scatter.py::TestPlotMeasurementsAndSimulation::test_bad_max_parameters_shape pkpd/tests/test_plots_scatter.py::TestPlotMeasurementsAndSimulation::test_bad_min_parameters_dimension pkpd/tests/test_plots_scatter.py::TestPlotMeasurementsAndSimulation::test_bad_min_parameters_shape pkpd/tests/test_plots_scatter.py::TestPlotMeasurementsAndSimulation::test_bad_model_type pkpd/tests/test_plots_scatter.py::TestPlotMeasurementsAndSimulation::test_create_figure pkpd/tests/test_plots_scatter.py::TestPlotMeasurementsAndSimulation::test_parameter_names
pkpd/tests/test_plots_scatter.py::TestPlotMeasurementsAndPredictions::test_bad_model_n_output pkpd/tests/test_plots_scatter.py::TestPlotMeasurementsAndSimulation::test_bad_model_n_output
pkpd/tests/test_plots_scatter.py::TestPlotMeasurements::test_create_figure pkpd/tests/test_plots_scatter.py::TestPlotMeasurementsAndPredictions::test_bad_model_type pkpd/tests/test_plots_scatter.py::TestPlotMeasurementsAndPredictions::test_bad_parameter_shape pkpd/tests/test_plots_scatter.py::TestPlotMeasurementsAndPredictions::test_bad_parameters_dimension pkpd/tests/test_plots_scatter.py::TestPlotMeasurementsAndPredictions::test_create_figure
pkpd/plots/__init__.py pkpd/plots/_scatter.py
pkpd/plots/__init__.py pkpd/plots/_scatter.py