Borealis-BioModeling / pysb-units

PySB add-on providing utilities to add units to models and perform dimensional analysis.
BSD 2-Clause "Simplified" License
1 stars 0 forks source link
mechanistic-modeling physics-based-simulation pkpd-modelling pysb pysb-modeling reaction-models systems-biology

pysb-units

Python version badge PySB version badge license version release DOI

pysb-units streamlines unit management and helps ensure unit consistency in PySB models.

Table of Contents

  1. Install
    1. Dependencies
    2. pip install
    3. Manual install
  2. License
  3. Change Log
  4. Documentation and Usage
    1. Quick Overview
    2. Example
    3. units context manager
    4. Using units with pysb.macros
    5. Stochastic Simulation Units
    6. unit keyword for Parameter
    7. Accessing Model units
    8. Additional Examples
    9. Custom Units
  5. Contact
  6. Supporting
  7. Other Useful Tools

Install

! Note
psyb-units is still in version zero development so new versions may not be backwards compatible.

pysb-units installs as the pysb.units Python (namespace) package. It is has been developed with Python 3.11.3 and PySB 1.15.0.

Dependencies

Note that pysb-units has the following core dependencies:

pip install

You can install pysb-units version 0.3.0 with pip sourced from the GitHub repo:

with git installed:

Fresh install:

pip install git+https://github.com/Borealis-BioModeling/pysb-units@v0.4.0

Or to upgrade from an older version:

pip install --upgrade git+https://github.com/Borealis-BioModeling/pysb-units@v0.4.0
without git installed:

Fresh install:

pip install https://github.com/Borealis-BioModeling/pysb-units/archive/refs/tags/v0.4.0.zip

Or to upgrade from an older version:

pip install --upgrade https://github.com/Borealis-BioModeling/pysb-units/archive/refs/tags/v0.4.0.zip

Manual install

First, download the repository. Then from the pysb-units folder/directory run

pip install .

License

This project is licensed under the BSD 2-Clause License - see the LICENSE file for details


Change Log

See: CHANGELOG


Documentation and Usage

Quick Overview

pysb-units is an add-on for the PySB modeling framework that provides tools to manage units. The key features of pysb-units are a new Unit object derived from pysb annotations, a new SimulationUnits object, and drop-in replacements for core model components, including Model, Parameter, Expression, Rule, Initial, and Observable that include new features to help manage units. Additionally, pysb-units defines a couple of useful utility functions, including the unitize and check functions, which make it easier to add units to model and run additional unit checks (such as unit consistency).

pysb-units introduces two new objects for defining and managing units in a pysb model. They are:

Example

A simple model with one degradation reaction:

from pysb import Model, Parameter, Monomer, Initial, Observable, Expression

Initialize the PySB model:

Model()

Monomer(s):

Monomer('protein')

Model parameter(s):

Initial concentration of protein

Parameter('protein_0', 0.5) # uM

1st-order rate parameter for the degradation

Parameter('k_deg', 0.1) # 1/s

Initial concentration(s)

Initial(protein, protein_0)

Reaction rule(s)

Just the one degradation

Rule('degradation', protein() >> None, k_deg)

Observables

Time-dependent protein concentration:

Observable('protein_t', protein()) # uM

Expressions

The time-dependent degradation rate:

Expression('deg_rate', (protein_t * k_deg)) # uM/s


* pysb with pysb-units
```python
# Import the pysb components we need:
from pysb import Model, Parameter, Monomer, Initial, Observable, Expression
# Import pysb-units:
import pysb.units as units

# Activate units - replaces core model components
# with the appropriate versions from pysb.units:
units.unitize()

# Initialize the PySB model:
Model()

# The primary units needed for simulating the model are 
# concentration (or amount) and time. We can define those
# here with SimulationUnits:
SimulationUnits(concentration='uM', time='s')

# Monomer(s):
Monomer('protein')

# Model parameter(s):
# Initial concentration of protein:
Parameter('protein_0', 500.)
# Attach units to protein_0:
Unit(protein_0, 'nM')

# 1st-order rate parameter for the degradation
# defined with frequency (1/time) units - here, 
# we chain Unit and Parameter definitions:
Unit(Parameter('k_deg', 0.1), '1/s') 

# Initial concentration(s)
Initial(protein, protein_0)

# Reaction rule(s)
# Just the one degradation
Rule('degradation', protein() >> None, k_deg)

# Observables
# Time-dependent protein concentration:
Observable('protein_t', protein())

# Expressions
# The time-dependent degradation rate:
Expression('deg_rate', (protein_t * k_deg))

# Apply additional unit checks, including unit duplication
# and unit consistency checking:
units.check()

In the above unit-ed example, additional unit-based features and unit validation are applied:

units context manager

In the previous example we added explicit calls to the unitize and check functions. If you prefer, you can use the units context manager instead to achieve the same effects:

# Import the pysb components we need:
from pysb import Model, Parameter, Monomer, Initial, Observable, Expression
# Import the pysb-units context manager:
from pysb.units import units

# Activate units using the units context manager - 
# replaces core model components with the appropriate 
# versions from pysb.units (similar to unitize) and will 
# automatically call the check function when exiting the
# context:
with units():

    # Initialize the PySB model:
    Model()

    # The primary units needed for simulating the model are 
    # concentration (or amount) and time. We can define those
    # here with SimulationUnits:
    SimulationUnits(concentration='uM', time='s')

    # Monomer(s):
    Monomer('protein')

    # Model parameter(s):
    # Initial concentration of protein:
    Parameter('protein_0', 500.)
    # Attach units to protein_0:
    Unit(protein_0, 'nM')

    # 1st-order rate parameter for the degradation
    # defined with frequency (1/time) units - here, 
    # we chain Unit and Parameter definitions:
    Unit(Parameter('k_deg', 0.1), '1/s') 

    # Initial concentration(s)
    Initial(protein, protein_0)

    # Reaction rule(s)
    # Just the one degradation
    Rule('degradation', protein() >> None, k_deg)

    # Observables
    # Time-dependent protein concentration:
    Observable('protein_t', protein())

    # Expressions
    # The time-dependent degradation rate:
    Expression('deg_rate', (protein_t * k_deg))

Using units with pysb.macros

PySB contains some helpful macro functions, such as bind and degrade, that can be used to streamline rule creation for recurring motifs. To use these macros with the pysb.units add-on you can use the add_macro_units function as below:

# Import the pysb components we need:
from pysb import Model, Parameter, Monomer, Initial, Observable, Expression
# Import the module with the wanted macros:
from pysb import macros
# Import pysb-units:
import pysb.units as units

# Activate units - replaces core model components
# with the appropriate versions from pysb.units:
units.unitize()
# Apply the units to the macros module:
units.add_macro_units(macros)

# Initialize the PySB model:
Model()

# The core units used when simulating the model are 
# concentration (or amount) and time. We can define those
# here with SimulationUnits:
SimulationUnits(concentration='uM', time='s')

# Monomer(s):
Monomer('protein')

# Model parameter(s):
# Initial concentration of protein:
Parameter('protein_0', 500.)
# Attach units to protein_0:
Unit(protein_0, 'nM')

# 1st-order rate parameter for the degradation
# defined with frequency (1/time) units - here, 
# we chain Unit and Parameter definitions:
Unit(Parameter('k_deg', 0.1), '1/s') 

# Initial concentration(s)
Initial(protein, protein_0)

# Reaction rule(s)
# Just the one degradation - instead
# of defining a Rule that encodes the degradation reaction
# we can take advantage of degrade macro:
macros.degrade(protein(), k_deg)

# Observables
# Time-dependent protein concentration:
Observable('protein_t', protein())

# Expressions
# The time-dependent degradation rate:
Expression('deg_rate', (protein_t * k_deg))

# Apply additional unit checks, including unit duplication
# and unit consistency checking:
units.check()

Stochastic Simulation Units

pysb-units supports stochastic simulation units (number of molecules in place of a molar concentration) at the level of model definition via the set_molecule_volume function and the SimulationUnits object. To enforce automatic conversion from molar concentrations to number of molecules we can update our example model as follows:

# Import the pysb components we need:
from pysb import Model, Parameter, Monomer, Initial, Observable, Expression
# Import pysb-units:
import pysb.units as units

# Activate units - replaces core model components
# with the appropriate versions from pysb.units:
units.unitize()

# Initialize the PySB model:
Model()

# The primary units needed for simulating the model are 
# concentration (or amount) and time. We can define those
# here with SimulationUnits.
# In this case, we want stochastic units so we can
# set the concentration to 'molecules'
SimulationUnits(concentration='molecules', time='s')

# Next, for stochastic units we need to set the volume 
# for the molar concentration to number of molecules conversion. Let's
# Assume a cellular volume of 1 pL:
units.set_molecule_volume(1.0, 'pL')

# Monomer(s):
Monomer('protein')

# Model parameter(s):
# Initial concentration of protein:
Parameter('protein_0', 500.)
# Attach units to protein_0:
Unit(protein_0, 'nM')

# 1st-order rate parameter for the degradation
# defined with frequency (1/time) units - here, 
# we chain Unit and Parameter definitions:
Unit(Parameter('k_deg', 0.1), '1/s') 

# Initial concentration(s)
Initial(protein, protein_0)

# Reaction rule(s)
# Just the one degradation
Rule('degradation', protein() >> None, k_deg)

# Observables
# Time-dependent protein concentration:
Observable('protein_t', protein())

# Expressions
# The time-dependent degradation rate:
Expression('deg_rate', (protein_t * k_deg))

# Apply additional unit checks, including unit duplication
# and unit consistency checking:
units.check()

Now, when Unit(protein_0, 'uM) is evaluated the concentration of 500 micromolar will be automatically converted to the number of molecules ('molecules' unit).

Note that at the moment, this approach only works for non-compartmental models.

unit keyword for Parameter

The Parameter component can accept an optional keyword argument for the unit, which means you can define the unit along with the parameter without explicitly applying a Unit object to the parameter. So, you can define unit-ed parameters using something like (as of version 0.3.0)

Parameter('k_r', 0.1, unit="1/s")

instead of doing (earlier versions)

Unit(Parameter('k_r', 0.1), '1/s')

The outcome is the same either way, but the top version is a little more compact and easier to read.

Accessing all the Units for a model

You can get a list of Unit objects defined for a model with the Model.units property:

from my_model_with_units import model
print(model.units)

Additional Examples

Additional examples can be found in or imported from pysb.units.examples, including

Custom Units

pysb.units leverages the astropy.units package for unit parsing and as its physical units library, but adds the following custom units/unit-types for reaction model use:


Contact


Supporting

I'm very happy that you've chosen to use pysb-units. This add-on is a project that I develop and maintain on my own time, independently of the core PySB library, and without external funding. If you've found it helpful, here are a few ways you can support its ongoing development:

ko-fi


Other Useful Tools

Parameter estimation

Please see packages such as simplePSO, PyDREAM, Gleipnir, or GAlibrate for tools to do PySB model parameter estimation using stochastic optimization or Bayesian Monte Carlo approaches.

PKPD modeling with PySB

If you want to build PKPD models with PySB the pysb-pkpd add-on can help.

PD response models

If you want to separately fit response data independetly of PK data, then the pharmacodynamic-response-models package may also be useful.

PySB model visualization

pyvipr can be used for static and dynamic PySB model visualizations.