Skip to main content
Skip table of contents

PSA With User-Defined Input Data

This example creates and executes PSA run with user-defined set of variables data points. The script utilizes the GastroPlusAPI package to communicate with the GastroPlus X 10.2 service.

The output from the PSA run is then used to create a 3D plot between two input variables and one output variable and a correlation plot between the input variables and the pharmacokinetic output variables.

To customize your study with this script for a different simulation / project / variables, please make changes to the “Set Input Information” section.

Load required libraries

PY
import gastroplus_api as gp
import pandas as pd
import os

from pprint import pprint

Start the GastroPlus service

start_service() starts the GastroPlus service and stores the port the service is listening on. Alternatively, you can start the service externally and set the port variable below.

PY
try:
    gastroplus_service = gp.start_service(verbose=False)
except Exception as e:
    print(f"Error starting GastroPlus service: {e}")
CODE
GastroPlus Service configured. Listening on port: 8700

Configure and create the gastroplus client instance. The gastroplus object will used to interact with the GastroPlus Service.

If not using start_service() to start the GastroPlus service (i.e., starting externally from this script), adjust the port variable below to match the port of the GastroPlus Service instance

The port set here must match the listening port of the running GastroPlus Service.

PY
#port=8700
port = gastroplus_service.port
host = f"http://localhost:{port}"
client = gp.ApiClient(gp.Configuration(host = host))
gastroplus = gp.GpxApiWrapper(client)

Setup Input Information

Make modification to the variables in this cell to customize your analysis.

  • PROJECT_DIRECTORY: Location of the GastroPlus project

  • PROJECT_NAME: Name of the project where the PSA project will be created

  • SIMULATION_NAME: Name of the simulation for the PSA run

  • PSA_ANALYSIS_MODE: Analysis mode for the PSA Run

  • RUN_NAME: Name of the PSA run that will be created

  • NUMBER_OF_USER_DEFINED_SIMULATIONS: Number of user defined points for each variable

  • INPUT_VARIABLES_DF: Pandas dataframe containing the variable information required to setup the PSA run.

The specified user-defined variable values will be used in each simulation of the PSA run.

PY
PROJECT_DIRECTORY = os.path.abspath("../../ProjectFiles/")
PROJECT_NAME = "GPX Library"
PROJECT_FILE_NAME = os.path.join(PROJECT_DIRECTORY, PROJECT_NAME + ".gpproject")
SIMULATION_NAME = "Atenolol 100mg PO tablet"
RUN_NAME = "userdefined_psa"
RUN_TYPE = gp.RunType.ParameterSensitivityAnalysis
PSA_ANALYSIS_MODE = gp.ParameterSensitivityAnalysisMode.UserDefined
INPUT_VARIABLES_DF = pd.DataFrame({
    "Name": ["Strength", "Solubility", "Stomach | Lumen | pH"],
    "Values": [
        [100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
        10, 25, 50, 75, 125, 150, 200, 250, 500, 1000],
        [2700, 2700, 2700, 2700, 2700, 2700, 2700, 2700, 2700, 2700,
         10, 100, 1000, 2500, 5000, 2700, 2700, 2700, 2700, 2700, 2700, 2700, 2700, 2700, 2700],
        [0.1, 0.2, 0.6, 0.8, 1.0, 1.5, 2.0, 2.5, 3.0, 5.0, 1.3, 1.3, 1.3, 1.3, 1.3,
         1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3]
    ],
    "Unit": ["milligram", "gram/meters cubed", ""]
})

NUMBER_OF_USER_DEFINED_SIMULATIONS = len(INPUT_VARIABLES_DF["Values"].iloc[0])
INPUT_VARIABLES_DF

Name

Values

Unit

0

Strength

[100, 100, 100, 100, 100, 100, 100, 100, 100, ...

milligram

1

Solubility

[2700, 2700, 2700, 2700, 2700, 2700, 2700, 270...

gram/meters cubed

2

Stomach | Lumen | pH

[0.1, 0.2, 0.6, 0.8, 1.0, 1.5, 2.0, 2.5, 3.0, ...

Configure and Execute the PSA Run

Based on the variables mentioned in the previous code chunk, the PSA run will be configured and executed

PY
# Load the project
gastroplus.open_project(PROJECT_FILE_NAME)

# Create new PSA run
gastroplus.create_run(run_name=RUN_NAME, run_type=RUN_TYPE)
gastroplus.add_simulations(RUN_NAME, [SIMULATION_NAME])

Retrieve the variable information from the simulation for the variables we want to use in the PSA run. This will be used in the following cell to create the PSA parameters.

PY
variable_information = gastroplus.get_variable_information(RUN_NAME, SIMULATION_NAME, INPUT_VARIABLES_DF["Name"].to_list(), False)
var_info = pd.json_normalize(variable_information.to_dict()["variable_information"])
var_info

scalar_type

variable_name

input_variable_name

variable_value.value

variable_value.unit

0

ScalarType.CONCENTRATION

pharma::SmallMolecule-Atenolol|chem::Molecule|...

Solubility

27000.0

g/m³

1

ScalarType.UNITLESS

pharma::PhysiologyRegimen-78kg HumanFasted Phy...

Stomach | Lumen | pH

1.3

[no units]

2

ScalarType.MASS

pharma::DoseRegimen-100mg PO tablet 25um|pharm...

Strength

100.0

mg

Create PSA parameters, PSA settings and combine them into a PSA and Run configuration and then execute the PSA run.

PY
psa_parameters = []

# iterate of the variables to create the PSA parameters
for row in INPUT_VARIABLES_DF.itertuples():
    # get the corresponding var_info row as a dictionary
    info = var_info.loc[var_info["input_variable_name"] == row.Name].to_dict(orient='records')[0]

    # create list of ScalarValue objects from the values in 'Values'
    scalar_values = [gp.ScalarValue(value=value, unit=row.Unit) for value in row.Values]
    #pprint(scalar_values)
    psa_parameter = gp.PSAParameter(
        variable_name=row.Name,
        baseline_value=info["variable_value.value"],
        unit=info["variable_value.unit"],
        scalar_type=info["scalar_type"],
        number_of_tests=NUMBER_OF_USER_DEFINED_SIMULATIONS,
        user_defined_values=scalar_values
    )
    
    psa_parameters.append(psa_parameter)


# create the PSA setting
psa_setting = gp.PSASetting(
    analysis_mode=PSA_ANALYSIS_MODE,
    simulate_baseline= False,
    update_Kp = False,
    number_of_user_defined_simulations = NUMBER_OF_USER_DEFINED_SIMULATIONS
)

# create the PSA configuration
psa_config = gp.PSAConfiguration(
    PSA_Parameters=psa_parameters,
    PSA_Setting=psa_setting
)

# create the run configuration
run_config = gp.RunConfigurationRunConfiguration(
    PSA_Configuration=psa_config
)

run_configuration = gp.RunConfiguration(
    run_name=RUN_NAME,
    run_configuration=run_config,
    use_full_variable_name=False
)

# Configure and execute the run
configure_response = gastroplus.configure_run(run_configuration)
run_response = gastroplus.execute_run(RUN_NAME)

Process run output

Get summary output and iteration records from the run just executed and create a dataframe that can be used for visualization of results

PY

simulation_keys = gastroplus.available_simulation_iteration_keys(RUN_NAME).simulation_iteration_keys
sim_keys = [key.simulation_iteration_key_name for key in simulation_keys]

summary_output = gastroplus.summary_output(RUN_NAME, gp.SummaryOutputRequest(simulation_iteration_key_names= sim_keys))
sum_df = pd.json_normalize(summary_output.to_dict()["summary_output"])
# Add the simulation iteration keys to the DataFrame, we'll using it later to combine with the iteration records
sum_df['simulation_iteration_key'] = sim_keys

Retrieve the iteration records and append the variable values and their units to the summary dataframe. Note, while the table does not render well in this online documentation, it will render properly is VSCode or when rendered to html.

PY
iteration_records_request_body = gp.IterationRecordsRequest(simulation_iteration_key_names= sim_keys, variable_names=INPUT_VARIABLES_DF["Name"].to_list() )

iteration_records = gastroplus.iteration_records(RUN_NAME, iteration_records_request_body)
iteration_df = pd.json_normalize(iteration_records.to_dict()["iteration_records"])

long_df = iteration_df.explode('variable_values')

long_df = pd.concat([
        long_df.drop(['variable_values'], axis=1),
        long_df['variable_values'].apply(pd.Series)
    ], axis=1)
long_df = pd.concat([
        long_df.drop(['variable_value'], axis=1),
        long_df['variable_value'].apply(pd.Series)
    ], axis=1) 
pivoted_df = long_df.pivot(
        index='simulation_iteration_key',
        columns='variable',
        values=['value', 'unit']
    ) 
pivoted_df.columns = [f"{var}.{col}" for col, var in pivoted_df.columns]
pivoted_df = pivoted_df.reset_index()
pivoted_df

merged_df = pd.merge(sum_df, pivoted_df, on='simulation_iteration_key', how='inner')
merged_df

compound

absorbed

bioavailable

portal_vein

run_simulation_iteration_key

simulation_iteration_key_name

simulation_iteration_key_name_2

iteration

clearance.value

clearance.unit

...

total_dose.unit

total_exposure.value

total_exposure.unit

simulation_iteration_key

Solubility.value

Stomach | Lumen | pH.value

Strength.value

Solubility.unit

Stomach | Lumen | pH.unit

Strength.unit

0

Atenolol

0.410565

0.399227

0.399227

userdefined_psa - Atenolol 100mg PO tablet | D...

Atenolol 100mg PO tablet 0

Atenolol 100mg PO tablet | Dose: 0.1mg | Solub...

0

27.680189

L/h

...

mg

3456.081716

(ng/mL)*h

Atenolol 100mg PO tablet | Dose: 0.1mg | Solub...

2700.0

0.1

0.1

g/m³

[no units]

g

1

Atenolol

0.410533

0.399195

0.399195

userdefined_psa - Atenolol 100mg PO tablet | D...

Atenolol 100mg PO tablet 1

Atenolol 100mg PO tablet | Dose: 0.1mg | Solub...

1

27.691223

L/h

...

mg

3454.489059

(ng/mL)*h

Atenolol 100mg PO tablet | Dose: 0.1mg | Solub...

2700.0

0.2

0.1

g/m³

[no units]

g

2

Atenolol

0.410533

0.399195

0.399195

userdefined_psa - Atenolol 100mg PO tablet | D...

Atenolol 100mg PO tablet 2

Atenolol 100mg PO tablet | Dose: 0.1mg | Solub...

2

27.684446

L/h

...

mg

3455.435771

(ng/mL)*h

Atenolol 100mg PO tablet | Dose: 0.1mg | Solub...

2700.0

0.6

0.1

g/m³

[no units]

g

3

Atenolol

0.410536

0.399198

0.399198

userdefined_psa - Atenolol 100mg PO tablet | D...

Atenolol 100mg PO tablet 3

Atenolol 100mg PO tablet | Dose: 0.1mg | Solub...

3

27.692797

L/h

...

mg

3453.833819

(ng/mL)*h

Atenolol 100mg PO tablet | Dose: 0.1mg | Solub...

2700.0

0.8

0.1

g/m³

[no units]

g

4

Atenolol

0.410533

0.399195

0.399195

userdefined_psa - Atenolol 100mg PO tablet | D...

Atenolol 100mg PO tablet 4

Atenolol 100mg PO tablet | Dose: 0.1mg | Solub...

4

27.674114

L/h

...

mg

3457.707796

(ng/mL)*h

Atenolol 100mg PO tablet | Dose: 0.1mg | Solub...

2700.0

1.0

0.1

g/m³

[no units]

g

5

Atenolol

0.410533

0.399196

0.399196

userdefined_psa - Atenolol 100mg PO tablet | D...

Atenolol 100mg PO tablet 5

Atenolol 100mg PO tablet | Dose: 0.1mg | Solub...

5

27.685797

L/h

...

mg

3455.356437

(ng/mL)*h

Atenolol 100mg PO tablet | Dose: 0.1mg | Solub...

2700.0

1.5

0.1

g/m³

[no units]

g

6

Atenolol

0.410533

0.399195

0.399195

userdefined_psa - Atenolol 100mg PO tablet | D...

Atenolol 100mg PO tablet 6

Atenolol 100mg PO tablet | Dose: 0.1mg | Solub...

6

27.687610

L/h

...

mg

3454.454944

(ng/mL)*h

Atenolol 100mg PO tablet | Dose: 0.1mg | Solub...

2700.0

2.0

0.1

g/m³

[no units]

g

7

Atenolol

0.410534

0.399197

0.399197

userdefined_psa - Atenolol 100mg PO tablet | D...

Atenolol 100mg PO tablet 7

Atenolol 100mg PO tablet | Dose: 0.1mg | Solub...

7

27.692637

L/h

...

mg

3453.231281

(ng/mL)*h

Atenolol 100mg PO tablet | Dose: 0.1mg | Solub...

2700.0

2.5

0.1

g/m³

[no units]

g

8

Atenolol

0.410533

0.399195

0.399195

userdefined_psa - Atenolol 100mg PO tablet | D...

Atenolol 100mg PO tablet 8

Atenolol 100mg PO tablet | Dose: 0.1mg | Solub...

8

27.666622

L/h

...

mg

3459.035315

(ng/mL)*h

Atenolol 100mg PO tablet | Dose: 0.1mg | Solub...

2700.0

3.0

0.1

g/m³

[no units]

g

9

Atenolol

0.410533

0.399195

0.399195

userdefined_psa - Atenolol 100mg PO tablet | D...

Atenolol 100mg PO tablet 9

Atenolol 100mg PO tablet | Dose: 0.1mg | Solub...

9

27.691636

L/h

...

mg

3454.281499

(ng/mL)*h

Atenolol 100mg PO tablet | Dose: 0.1mg | Solub...

2700.0

5.0

0.1

g/m³

[no units]

g

10

Atenolol

0.259672

0.255476

0.255476

userdefined_psa - Atenolol 100mg PO tablet | D...

Atenolol 100mg PO tablet 10

Atenolol 100mg PO tablet | Dose: 0.1mg | Solub...

10

43.338476

L/h

...

mg

2199.918021

(ng/mL)*h

Atenolol 100mg PO tablet | Dose: 0.1mg | Solub...

10.0

1.3

0.1

g/m³

[no units]

g

11

Atenolol

0.409335

0.397973

0.397973

userdefined_psa - Atenolol 100mg PO tablet | D...

Atenolol 100mg PO tablet 11

Atenolol 100mg PO tablet | Dose: 0.1mg | Solub...

11

27.761301

L/h

...

mg

3446.662835

(ng/mL)*h

Atenolol 100mg PO tablet | Dose: 0.1mg | Solub...

100.0

1.3

0.1

g/m³

[no units]

g

12

Atenolol

0.410529

0.399189

0.399189

userdefined_psa - Atenolol 100mg PO tablet | D...

Atenolol 100mg PO tablet 12

Atenolol 100mg PO tablet | Dose: 0.1mg | Solub...

12

27.705661

L/h

...

mg

3452.359106

(ng/mL)*h

Atenolol 100mg PO tablet | Dose: 0.1mg | Solub...

1000.0

1.3

0.1

g/m³

[no units]

g

13

Atenolol

0.410533

0.399196

0.399196

userdefined_psa - Atenolol 100mg PO tablet | D...

Atenolol 100mg PO tablet 13

Atenolol 100mg PO tablet | Dose: 0.1mg | Solub...

13

27.670259

L/h

...

mg

3458.305498

(ng/mL)*h

Atenolol 100mg PO tablet | Dose: 0.1mg | Solub...

2500.0

1.3

0.1

g/m³

[no units]

g

14

Atenolol

0.410536

0.399198

0.399198

userdefined_psa - Atenolol 100mg PO tablet | D...

Atenolol 100mg PO tablet 14

Atenolol 100mg PO tablet | Dose: 0.1mg | Solub...

14

27.682014

L/h

...

mg

3456.177532

(ng/mL)*h

Atenolol 100mg PO tablet | Dose: 0.1mg | Solub...

5000.0

1.3

0.1

g/m³

[no units]

g

15

Atenolol

0.410533

0.399196

0.399196

userdefined_psa - Atenolol 100mg PO tablet | D...

Atenolol 100mg PO tablet 15

Atenolol 100mg PO tablet | Dose: 0.01mg | Solu...

15

27.702988

L/h

...

mg

345.392617

(ng/mL)*h

Atenolol 100mg PO tablet | Dose: 0.01mg | Solu...

2700.0

1.3

0.01

g/m³

[no units]

g

16

Atenolol

0.410549

0.399206

0.399206

userdefined_psa - Atenolol 100mg PO tablet | D...

Atenolol 100mg PO tablet 16

Atenolol 100mg PO tablet | Dose: 0.025mg | Sol...

16

27.672448

L/h

...

mg

864.580236

(ng/mL)*h

Atenolol 100mg PO tablet | Dose: 0.025mg | Sol...

2700.0

1.3

0.025

g/m³

[no units]

g

17

Atenolol

0.410549

0.399209

0.399209

userdefined_psa - Atenolol 100mg PO tablet | D...

Atenolol 100mg PO tablet 17

Atenolol 100mg PO tablet | Dose: 0.05mg | Solu...

17

27.703775

L/h

...

mg

1725.998829

(ng/mL)*h

Atenolol 100mg PO tablet | Dose: 0.05mg | Solu...

2700.0

1.3

0.05

g/m³

[no units]

g

18

Atenolol

0.410535

0.399197

0.399197

userdefined_psa - Atenolol 100mg PO tablet | D...

Atenolol 100mg PO tablet 18

Atenolol 100mg PO tablet | Dose: 0.075mg | Sol...

18

27.691480

L/h

...

mg

2590.686281

(ng/mL)*h

Atenolol 100mg PO tablet | Dose: 0.075mg | Sol...

2700.0

1.3

0.075

g/m³

[no units]

g

19

Atenolol

0.410534

0.399196

0.399196

userdefined_psa - Atenolol 100mg PO tablet | D...

Atenolol 100mg PO tablet 19

Atenolol 100mg PO tablet | Dose: 0.125mg | Sol...

19

27.675969

L/h

...

mg

4321.655892

(ng/mL)*h

Atenolol 100mg PO tablet | Dose: 0.125mg | Sol...

2700.0

1.3

0.125

g/m³

[no units]

g

20

Atenolol

0.410533

0.399195

0.399195

userdefined_psa - Atenolol 100mg PO tablet | D...

Atenolol 100mg PO tablet 20

Atenolol 100mg PO tablet | Dose: 0.15mg | Solu...

20

27.690890

L/h

...

mg

5180.773419

(ng/mL)*h

Atenolol 100mg PO tablet | Dose: 0.15mg | Solu...

2700.0

1.3

0.15

g/m³

[no units]

g

21

Atenolol

0.410536

0.399198

0.399198

userdefined_psa - Atenolol 100mg PO tablet | D...

Atenolol 100mg PO tablet 21

Atenolol 100mg PO tablet | Dose: 0.2mg | Solub...

21

27.681784

L/h

...

mg

6912.823425

(ng/mL)*h

Atenolol 100mg PO tablet | Dose: 0.2mg | Solub...

2700.0

1.3

0.2

g/m³

[no units]

g

22

Atenolol

0.410535

0.399197

0.399197

userdefined_psa - Atenolol 100mg PO tablet | D...

Atenolol 100mg PO tablet 22

Atenolol 100mg PO tablet | Dose: 0.25mg | Solu...

22

27.684051

L/h

...

mg

8640.382330

(ng/mL)*h

Atenolol 100mg PO tablet | Dose: 0.25mg | Solu...

2700.0

1.3

0.25

g/m³

[no units]

g

23

Atenolol

0.410533

0.399195

0.399195

userdefined_psa - Atenolol 100mg PO tablet | D...

Atenolol 100mg PO tablet 23

Atenolol 100mg PO tablet | Dose: 0.5mg | Solub...

23

27.692355

L/h

...

mg

17272.443863

(ng/mL)*h

Atenolol 100mg PO tablet | Dose: 0.5mg | Solub...

2700.0

1.3

0.5

g/m³

[no units]

g

24

Atenolol

0.410533

0.399195

0.399195

userdefined_psa - Atenolol 100mg PO tablet | D...

Atenolol 100mg PO tablet 24

Atenolol 100mg PO tablet | Dose: 1mg | Solubil...

24

27.695230

L/h

...

mg

34541.847106

(ng/mL)*h

Atenolol 100mg PO tablet | Dose: 1mg | Solubil...

2700.0

1.3

1.0

g/m³

[no units]

g

Correlation plot

PY
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np

numeric_cols = merged_df.select_dtypes(include='number').columns
df_numeric = merged_df.set_index('simulation_iteration_key')[numeric_cols]

corr = df_numeric.corr()
sns.set_theme(style="white")
cmap = sns.diverging_palette(220, 20, as_cmap=True)
mask = np.logical_xor(np.tril(np.ones_like(corr, dtype=bool)),
                      np.eye(*corr.shape, dtype=bool))
sns.heatmap(corr, annot=False, cmap=cmap, mask=mask, vmin=-1, vmax=1, center=0, linecolor='white', linewidths=0.5, cbar_kws={"shrink": .8})

plt.show()
cell-11-output-1.png

Plot results in 3D plot

PY
import plotly

# Create `values` and `units` dataframe of the data to be plotted
variables_names = dict(x='Strength', y='Solubility', z='bioavailable', color = 'Stomach | Lumen | pH')
values = merged_df[[f"{variables_names['x']}.value",
                              f"{variables_names['y']}.value",
                                f"{variables_names['z']}",
                                f"{variables_names['color']}.value",
 ]]

units = dict(x=merged_df[f"{variables_names['x']}.unit"].iloc[0],
             y=merged_df[f"{variables_names['y']}.unit"].iloc[0],
             z="",
             color="pH")

# Create 3D scatter plot
fig = plotly.graph_objs.Figure(
  data=[plotly.graph_objs.Scatter3d(
    x=values[f"{variables_names['x']}.value"],
    y=values[f"{variables_names['y']}.value"],
    z=values[f"{variables_names['z']}"],
    mode='markers',
    marker=dict(
      size=6,
      color=values[f"{variables_names['color']}.value"],
      colorbar=dict(title=variables_names['color']),
      colorscale='Viridis'
    ),
    text=sim_keys
  )]
)
fig.update_layout(
  scene=dict(
    xaxis_title=f"{variables_names['x']} ({units['x']})",
    yaxis_title=f"{variables_names['y']} ({units['y']})",
    zaxis_title=f"{variables_names['z']}"
  )
)
fig.show()
CODE
Unable to display output for mime type(s): text/html
CODE
Unable to display output for mime type(s): text/html
image-20250926-190459.png

JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.