PyBindingCurve API reference
Documentation and API Full PyBindingCurve source code can be found here: https://github.com/stevenshave/pybindingcurve
Overview
Conventionally, the standard import utilised in a run of PyBindingCurve (PBC) are defined as follows: import pybindingcurve as pbc import numpy as np PyBindingCurve is imported with the short name ‘pbc’, and then NumPy as ‘np’ to enable easy specification of ranged system parameters, evenly spaced across intervals mimicking titrations. Next, we initialise a PBC BindingCurve object. Upon initialisation, either a string or BindingSystem object is used to define the system to be simulated. Simple strings such as “1:1”, “competition”, “homodimer breaking” can be used as an easy way to define the type of binding system that should be mathematically modelled. See the list of available system shortcut strings bellow in the ‘pbc.systems and shortcut strings’ section bellow. Custom objects may also be created of type pybindingcurve.BindingSystem, of which there exist a large choice within pybindingcurve.systems, or the user may create a custom BindingSystem to initialise PBC objects: my_system=pbc.BindingCurve(“1:1”) There are three main modes of operation within PyBindingCurve; 1) Visualisation of protein-ligand behaviour within a titration, simulating a range of conditions. 2) Simulation of a single system state with discrete parameters. 3) Fitting of experimental data. A description of these follows:
- Simulation with visualisation: pass a dictionary containing system parameters to the add_curve function of the BindingCurve object (my_system). Required system parameters depend on the system being modelled. In the case of 1:1 binding, we require p (protein concentration), l (ligand concentration), kdpl (dissociation constant between p and l), and optionally, a ymax and/or ymin variable if dealing with simulation of a signal. add_curve expects one changing parameter, which will be the x-axis. By default, complex concentration will be the readout of a system, but that can be changed by passing different readout options to add_curve. See the ‘pbc.Readout’ section bellow for further information. With one curve added, we can add more curves, or simply display the plot by calling the show_plot function.
system_parameters={‘p’:np.linspace(0,20), ‘l’:20, ‘kdpl’:10)
my_system.add_curve(system_parameters)
my_system.show_plot()
- Single point simulation: if you require not a simulation with a curve, but a single point with set concentrations and KDs, then query may be called with a dictionary of system parameters and data returned. Additionally, if the dictionary contains a NumPy array, representing a titration (for example, the system parameters above), then a NumPy array of the readout is returned instead of a single value:
complex_conc = my_system.query({‘p’:10, ‘l’:20, ‘kdpl’:10})
- Fit experimental data to a system to obtain experimental parameters, such as KD. A common situation is determining KD from measurements obtained from experimental data. We can perform this as follows, with x- and y-coordinates, we add the experimental points to the plot, define system parameters that we do know (protein concentrations, and the amount of ligand), and then call fit on the system passing in parameters to fit and an initial guess (1), along with the known parameters. We then iterate and print the fitted parameters.
xcoords = np.array([0.0, 20.0, 40.0, 60.0, 80.0, 100.0, 120.0, 140.0, 160.0, 180.0, 200.0])
ycoords = np.array([0.544, 4.832, 6.367, 7.093, 7.987, 9.005, 9.079, 8.906, 9.010, 10.046, 9.225])
my_system.add_scatter(xcoords, ycoords)
system_parameters = {"p": xcoords, "l": 10}
fitted_system, fit_accuracy = my_system.fit(system_parameters, {"kdpl": 1}, ycoords)
for k, v in fit_accuracy.items():
print(f"Fit: {k}={fitted_system[k]} +/- {v}")
pbc.BindingCurve
The BindingCurve object allows the user to work with a specific system, supplying tools for simulation and visualisation (plotting), querying of single point values, and fitting of experimental parameters to observation data.
Initialisation
When initialising this main class of PBC, we may supply either a pbc.BindingSystem, a human readable shortcut string such as “1:1”, “competition”, “homodimer formation”, etc, or a system definition string. For a full list of systems, shortcuts, and custom systems definition strings, please refer to the ‘pbc.systems and shortcut strings’ section.
Initialisation of a BindingCurve object takes the following arguments:
"""
BindingCurve class, used to simulate systems
BindingCurve objects are governed by their underlying system, defining the
(usually) protein-ligand binding system being represented. It also
provides the main interface for simulation, visualisation, querying and
the fitting of system parameters.
Parameters
----------
binding_system : BindingSystem or str
Define the binding system which will govern this BindingCurve object.
Can either be a BindingSystem object, a shortcut string describing a
system (such as '1:1' or 'competition', etc), or a custom binding
system definition string.
"""
Once intitialised with a pbc.BindingSystem, we may perform the following utilising its member functions.
add_curve
The add curve function is the main way of simulating a binding curve with PBC. Once a BindingCurve object is initialised,
"""
Add a curve to the plot
Add a curve as specified by the system parameters to the
pbc.BindingSystem's internal plot using the underlying binding system
specified on intitialisation.
Parameters
----------
parameters : dict
Parameters defining the system to be simulated
name : str or None, optional
Name of curve to appear in plot legends
readout : Readout.function, optional
Change the system readout to one described by a custom readout
function. Predefined standard readouts can be found in the static
pbc.Readout class.
""" ### query When simulation with visualisation (plotting) is not required, we can use the query function to interrogate a system, returning either singular values, or arrays of values if one of the input parameters is an array or list.
"""
Query a binding system
Get the readout from from a set of system parameters
Parameters
----------
parameters : dict
System parameters defining the system being queried. Will usually
contain protein, ligand etc concentrations, and KDs
readout : func or None
Change the readout of the system, can be None for unmodified
(usually complex concentration), a static member function from
the pbc.Readout class, or a custom written function following the
the same defininition as those in pbc.Readout.
Returns
-------
Single floating point, or array-like
Response/signal of the system
""" ### fit With a system defined, we may fit experimental data to the system.
"""
Fit the parameters of a system to a set of data points
Fit the system to a set of (usually) experimental datapoints.
The fitted parameters are stored in the system_parameters dict
which may be accessed after running this function. It is
possible to fit multiple parameters at once and define bounds
for the parameters. The function returns a dictionary of the
accuracy of fitted parameters, which may be captured, or not.
Parameters:
system_parameters : dict
Dictionary containing system parameters, will be used as arguments
to the systems equations.
to_fit : dict
Dictionary containing system parameters to fit.
xcoords : np.array
X coordinates of data the system parameters should be fit to
ycoords : np.array
Y coordinates of data the system parameters should be fit to
bounds : dict
Dictionary of tuples, indexed by system parameters denoting the
lower and upper bounds of a system parameter being fit, optional,
default = None
Returns
-------
tuple (dict, dict)
Tuple containing a dictionary of best fit systems parameters,
then a dictionary containing the accuracy for fitted variables.
""" ### add_scatter Experimental data can be added plots with the add_scatter command, taking a simple list of x and y coordinates
"""
Add scatterpoints to a plot, useful to represent real measurement data
X and Y coordinates may be added to the internal plot, useful when
fitting to experimental data, and wanting to plot the true experimental
values alongside a curve generated with fitted parameters.
Parameters
----------
xcoords : list or array-like
x-coordinates
ycoords : list or array-like
y-coordinates
"""
show_plot
With curves, scatterpoints and fits applied, we may display the plot.
"""
Show the PyBindingCurve plot
Function to display the internal state of the pbc BindingCurve objects
plot.
Parameters
----------
title : str
The title of the plot (default = "System simulation")
xlabel: str
X-axis label (default = None)
ylabel : str
Y-axis label (default = None, causing label to be "[Complex]")
min_x : float
X-axis minimum (default = None)
max_x : float
X-axis maximum (default = None)
min_y : float
Y-axis minimum (default = None)
max_y : float
Y-axis maximum (default = None)
log_x_axis : bool
Log scale on X-axis (default = False)
log_y_axis : bool
Log scale on Y-axis (default = False)
ma_style : bool
Apply MA styling, making plots appear like GraFit plots
png_filename : str
File name/location where png will be written
svg_filename : str
File name/location where svg will be written
"""
pbc.systems
pbc.systems contains all default systems supplied with PBC, and exports them to the PBC namespace. Systems may be passed as arguments to pbc.BindingCurve objects upon initialization to define the underlying system governing simulation, queries, and fitting. Additionally, the following shortcut strings may be used as shortcuts, all spaces are removed from the input string, and so are represented without whitespace bellow:
Shortcut string list | pbc.systems equivalent |
---|---|
simple, 1:1, 1:1analytical | System_analytical_one_to_one__pl |
1:1min, 1:1minimizer, 1:1minimiser | System_minimizer_one_to_one__pl |
simplelagrange, 1:1lagrange | System_lagrange_one_to_one__pl |
simplekinetic, 1:1kinetic | System_kinetic_one_to_one__pl |
homodimerformation | System_analytical_homodimerformation__pp |
homodimerformationmin, homodimerformationminimiser, homodimerformationminimizer, homodimermin, homodimerminimiser, homodimerminimizer | System_minimizer_homodimerformation__pp |
homodimerformationlagrange | System_lagrange_homodimerformation__pp |
homodimerformationkinetic | System_kinetic_homodimerformation__pp |
competition, 1:1:1 | System_analytical_competition__pl |
competitionmin, competitionminimiser, competitionminimizer, 1:1:1min, 1:1:1minimiser, 1:1:1minimizer | System_minimizer_competition__pl |
competitionlagrange | System_lagrange_competition__pl |
homodimerbreaking, homodimerbreakingmin, homodimerbreakingminimiser, homodimerbreakingminimizer | System_minimizer_homodimerbreaking__pp |
homodimerbreakinglagrange | System_lagrange_homodimerbreaking__pp |
homodimerbreakingkinetic | System_kinetic_homodimerbreaking__pp |
homodimerbreakinganalytical | System_analytical_homodimerbreaking__pp |
1:2, 1:2min, 1:2minimizer, 1:2minimiser | System_minimizer_1_to_2__pl12 |
1:2lagrange | System_lagrange_1_to_2__pl12 |
1:3, 1:3min, 1:3minimizer, 1:3minimiser | System_minimizer_1_to_3__pl123 |
1:3lagrange | System_lagrange_1_to_3__pl123 |
1:4, 1:4lagrange | System_lagrange_1_to_4__pl1234 |
1:5, 1:5lagrange | System_lagrange_1_to_5__pl12345 |
Custom systems can be passed allowing the use of custom binding systems derived from a simple syntax. This is in the form of a string with reactions separated either on newlines, commas, or a combination of the two. Reactions take the form:
- r1+r2<->p
Denoting reactant1 + reactant2 form the product. PBC will generate and solve custom defined constrained systems. Readouts are signified by inclusion of a star (*) on a species. If no star is found, then the first seen product is used. Some system examples follow:
- “P+L<->PL” - standard protein-ligand binding
- “P+L<->PL, P+I<->PI” - competition binding
- “P+P<->PP” - dimer formation
- “monomer+monomer<->dimer” - dimer formation
- “P+L<->PL1, P+L<->PL2, PL1+L<->PL1L2, PL2+L<->PL1L2” - 1:2 site binding
KDs passed to custom systems use underscores to separate species and products. P+L<->PL would require the KD passed as kd_p_l_pl. Running with incomplete system parameters will prompt for the correct ones.
pbc.BindingSystem
Custom binding systems may be defined through inheritance from the base class pbc.BindingSystem. This provides basic functionality through a standard interface to PBC, allowing simulation, querying and fitting. It expects the child class to provide a constructor which passes a function for querying the system and a query method. An example pbc.BindingSystem for 1:1 binding solved analytically is defined as follows:
class System_analytical_one_to_one_pl(BindingSystem):
def __init__(self):
super().__init__(
analyticalsystems.system01_one_to_one__p_l_kd__pl, analytical=True
)
self.default_readout = "pl"
def query(self, parameters: dict):
if self._are_ymin_ymax_present(parameters):
parameters_no_min_max = self._remove_ymin_ymax_keys_from_dict_return_new(
parameters
)
value = super().query(parameters_no_min_max)
with np.errstate(divide="ignore", invalid="ignore"):
return (
parameters["ymin"]
+ ((parameters["ymax"] - parameters["ymin"]) * value)
/ parameters["l"]
)
else:
return super().query(parameters)
Here, we see the parent class constructor called upon initialisation of the object with two arguments, the first is a python function which calculates the complex concentration present in a 1:1 binding system, which itself takes the appropriate parameters to calculate this. In addition, a flag is set to define when the solution is solved analytically. The query method examines the content of the system and deals with the presence of ymin and ymax to denote a signal is being simulated. Query should ultimately end up calling query on the parent class, which has been set to return the result of the previously assigned function in the constructor.
pbc.Readout
The pbc.Readout class contains three static methods, not requiring object initialisation for use. These methods all take in a system parameters dictionary describing the system, and the y_values resulting from system query calls (either through simulation of querying for singular values). These readout functions offer a convenient way to transform results. For example, the readout function to transform complex concentration into fraction ligand bound is defined as follows:
def fraction_l(system_parameters: dict, y):
""" Readout as fraction ligand bound """
return "Fraction l bound", y / system_parameters["l"]
This returns a tuple, with the first value being used in labelling of the plot y-axis, and the second the y-values to be plotted; in this case, the original y values divided by the overall starting ligand concentration. Similar functions can be defined and used interchangeably with those found in pbc.Readout.