def generate_heatmaps(homodimer_map_file: Path, heterodimer_map_file: Path, plot_steps: int = 800): pool = Pool(2) inhibitor_conc = 5.0 pbc_homodimer_breaking = pbc.BindingCurve("homodimer breaking") pbc_heterodimer_breaking = pbc.BindingCurve("competition") print("Building homdimer heatmap file") j1 = pool.apply_async( get_2D_grid_values, [ -3, 3, -3, 3, pbc_homodimer_breaking, { "p": 2, "i": inhibitor_conc }, "kdpp", "kdpi", f"heatmaphomo-{str(inhibitor_conc)}.pkl", plot_steps, ], ) print("Building heterodimer heatmap file") j2 = pool.apply_async( get_2D_grid_values, [ -3, 3, -3, 3, pbc_heterodimer_breaking, { "p": 1, "l": 1, "i": inhibitor_conc }, "kdpl", "kdpi", f"heatmaphetero-{str(inhibitor_conc)}.pkl", plot_steps, ], ) res = j1.get() res = j2.get()
def test_1_to_1_simulation_analytical(): my_system = pbc.BindingCurve("1:1analytical") assert np.sum( np.abs( my_system.query({ "p": np.linspace(0, 20), "l": 10, "kdpl": 1 }) - res_one_to_one)) < 1e-6
def test_1_to_1_simulation_default_approach(): my_system = pbc.BindingCurve("1:1") assert np.sum( np.abs( my_system.query({ "p": np.linspace(0, 20), "l": 10, "kdpl": 1 }) - res_one_to_one)) < 1e-6
def test_1_to_1_simulation_custom_definition(): my_system = pbc.BindingCurve("P+L<->PL*") assert np.sum( np.abs( my_system.query({ "p": np.linspace(0, 20), "l": 10, "kd_p_l_pl": 1 }) - res_one_to_one)) < 1e-6
def test_competition_simulation_custom_definition(): my_system = pbc.BindingCurve("p+l<->pl*,p+i<->pi") assert np.sum( np.abs( my_system.query({ "p": 12, "l": 10, "i": np.linspace(0, 25), "kd_p_i_pi": 1, "kd_p_l_pl": 10 }) - res_competition)) < 1e-6
def test_competition_simulation_kinetic(): my_system = pbc.BindingCurve("competitionkinetic") assert np.sum( np.abs( my_system.query({ "p": 12, "l": 10, "i": np.linspace(0, 25), "kdpi": 1, "kdpl": 10 }) - res_competition)) < 1e-6
def test_1_to_1_fit_analytical(): 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 = pbc.BindingCurve("1:1analytical") system_parameters = {"p": xcoords, "l": 10} fitted_system, fit_accuracy = my_system.fit(system_parameters, {"kdpl": 0}, ycoords) assert np.abs(fitted_system["kdpl"] - 16.371571968273663) < 1e-6
"""Simulation example 1:1 binding""" import numpy as np import pybindingcurve as pbc # Define our system, 1:1 binding has p and l which (usually) relate two protein # and ligand concentration, although can be any two species which bind. kdpl # is the dissociation constant between the two species. # We can choose to work in a common unit, typically nM, or uM, as long as all # numbers are in the same unit, the result is valid. We assume uM for all # concentrations bellow. system_parameters={'p':1, 'l':10,'kdpl':1} # Make a pbc BindingCurve defined by the simple 1:1 binding system mySystem = pbc.BindingCurve("1:1") print("Simulating 1:1 binding system with these parameters:") print(system_parameters) print("pl=",mySystem.query(system_parameters)) # Simulate and visualise a binding curve. # First, we redefine the system parameters so that one variable is changing # in this case, we choose protein, performing a titration from 0 to 10 uM. system_parameters = {"p": np.linspace(0, 20), "l": 10, "kdpl": 1} # We can now add the curve to the plot, name it with an optional name= value. mySystem.add_curve(system_parameters) # Lets change the KD present in the system parameters into something higher # affinity (lower KD) and add it to the curve system_parameters2 = {"p": np.linspace(0, 20), "l": 10, "kdpl": 0.5}
import numpy as np import pybindingcurve as pbc import sys # We can choose to work in a common unit, typically nM, or uM, as long as all # numbers are in the same unit, the result is valid. We assume uM for all # concentrations bellow. # Experimental data xcoords = np.array([0.0, 2, 4, 6, 8, 10]) ycoords = np.array([0.0, 0.22, 0.71, 1.24, 1.88, 2.48]) # Construct the PyBindingCurve object, operating on a homodimer formation # system and add experimental data to the plot my_system = pbc.BindingCurve("homodimer formation") my_system.add_scatter(xcoords, ycoords) # Known system parameters, kdpp will be added to this by fitting system_parameters = {"p": xcoords} # Now we call fit, passing the known parameters, followed by a dict of parameters to be fitted along # with an initial guess, pass the ycoords, and what the readout (ycoords) is fitted_system, fit_accuracy = my_system.fit(system_parameters, {"kdpp": 0}, ycoords) # Print out the fitted parameters for k, v in fit_accuracy.items(): print(f"Fit: {k}={fitted_system[k]} +/- {v}") # Assign more points to 'p' to make a smooth plot
"""Simulation example homodimer breaking""" import numpy as np import pybindingcurve as pbc import time # We can choose to work in a common unit, typically nM, or uM, as long as all # numbers are in the same unit, the result is valid. We assume uM for all # concentrations bellow. # Define our homodimer breaking system, titrating in inhibitor system_parameters = {"p": 30, "kdpp": 10, "i": np.linspace(0, 60), "kdpi": 1} # Create the PBC BindingCurve object, expecting a 'homodimer breaking' system. my_system = pbc.BindingCurve("homodimer breaking") # Add the system to PBC, generating a plot. my_system.add_curve(system_parameters) # Display the plot my_system.show_plot()
# A reviewer enquired as to why the x-axes of plots in figure 1 were not # using a log scale. In testing, we found this obscured the critical crossover # points discussed in the text. To enable this log scale on x-axes, set the # bellow variable to True, the most insightful figure is achieved with 'False' use_log_xaxis_scale = False # Calculate formation concentrations x_axis_formation = np.linspace(0, maximum_monomer_concentration, num=num_points) x_axis_breaking = np.linspace(0, max_inhibitor_concentration, num=num_points) homo_y_formation = np.empty((num_points)) hetero_y_formation = np.empty((num_points)) # Make the formation and breaking PBC binding curves that we will later query pbc_homodimer_formation = pbc.BindingCurve("homodimer formation") pbc_heterodimer_formation = pbc.BindingCurve( "1:1") # Heterodimer formation is just the same as 1:1, or P+L<->PL pbc_homodimer_breaking = pbc.BindingCurve("homodimer breaking") pbc_heterodimer_breaking = pbc.BindingCurve("competition") # Perform the calculations homodimer_formation_concs = pbc_homodimer_formation.query({ "kdpp": dimer_kd, "p": x_axis_formation * 2 }) homodimer_breaking_concs = pbc_homodimer_breaking.query({ "kdpi": inhibitor_kd, "kdpp": dimer_kd,
"""Simulation example 1:1:1 comptition binding""" import numpy as np import pybindingcurve as pbc # We can choose to work in a common unit, typically nM, or uM, as long as all # numbers are in the same unit, the result is valid. We assume uM for all # concentrations bellow. # Create the PBC BindingCurve object, expecting a 'competition' system. mySystem = pbc.BindingCurve("competition") # First, lets simulate a curve with no inhibitor present (essentially 1:1) mySystem.add_curve( {"p": np.linspace(0, 40, 20), "l": 10, "i": 0, "kdpi": 1, "kdpl": 10}, "No inhibitor" ) # Add curve with inhibitor (i) mySystem.add_curve( {"p": np.linspace(0, 40, 20), "l": 10, "i": 10, "kdpi": 1, "kdpl": 10}, "[i] = 10 µM" ) # Add curve with more inhibtor (i) mySystem.add_curve( {"p": np.linspace(0, 40, 20), "l": 10, "i": 25, "kdpi": 1, "kdpl": 10}, "[i] = 25 uM" ) # Display the plot mySystem.show_plot()
import pybindingcurve as pbc import random output_file = open("system_results.csv", "w", buffering=1) output_file.write("p,l,kdpp,kdpl,solution") analytical_system = pbc.BindingCurve( pbc.systems.System_analytical_homodimerbreaking_pp) kinetic_system = pbc.BindingCurve( pbc.systems.System_kinetic_homodimerbreaking_pp) while True: query_system = { "p": random.uniform(0.0, 1000.0) * 10**random.choice([0, -3, -6, -9, -12]), "l": random.uniform(0.0, 1000.0) * 10**random.choice([0, -3, -6, -9, -12]), "kdpl": random.uniform(0.0, 1000.0) * 10**random.choice([0, -3, -6, -9, -12]), "kdpp": random.uniform(0.0, 1000.0) * 10**random.choice([0, -3, -6, -9, -12]), } kinetic_result = kinetic_system.query(query_system) analytical_result = analytical_system.query(query_system) closest = min( range(len(analytical_result)), key=lambda i: abs(analytical_result[i] - kinetic_result), ) output_file.write( f"{query_system['p']},{query_system['l']},{query_system['kdpp']},{query_system['kdpl']},{closest}\n" )
"""Fitting example, determining Kd from 1:1:1 competition data""" import numpy as np import pybindingcurve as pbc import sys # We can choose to work in a common unit, typically nM, or uM, as long as all # numbers are in the same unit, the result is valid. We assume uM for all # concentrations bellow. # Experimental data xcoords = np.array([0.0, 4.2, 8.4, 16.8, 21.1, 31.6, 35.8, 40.0]) ycoords = np.array([150, 330, 1050, 3080, 4300, 6330, 6490, 6960]) # Construct the PyBindingCurve object, operating on a 1:1:1 (compeittion) system and add experimental data to the plot my_system = pbc.BindingCurve("1:1:1") my_system.add_scatter(xcoords, ycoords) # Known system parameters, kdpl will be added to this by fitting system_parameters = { "p": xcoords, "l": 10, "i": 10, "kdpl": 10, "ymin": np.min(ycoords), } # Now we call fit, passing the known parameters, followed by a dict of parameters to be fitted along # with an initial guess, pass the ycoords, and what the readout (ycoords) is fitted_system, fit_accuracy = my_system.fit(system_parameters, { "kdpi": 0,
10 µM (depending on standard unit used) KDs passed to custom systems use underscores to separate species and product and prefixed with kd. P+L<->PL would require the KD passed as kd_p_l_pl. Running with incomplete system parameters will prompt for the correct ones. The methods employed to solve the system will return a result accurate to 10 decimal places. """ import numpy as np import pybindingcurve as pbc # Define the custom system custom_system = "P+L<->PL*" # Make a pbc BindingCurve defined by the custom system string above my_system = pbc.BindingCurve(custom_system) # We interrogate the system to see which parameters/arguments are required # for calculation print("Required parameters/arguments are: ", my_system.get_system_arguments()) # We can choose to work in a common unit, typically nM, or uM, as long as all # numbers are in the same unit, the result is valid. We assume uM for all # concentrations bellow. system_parameters = {"p": np.linspace(0, 20), "l": 5, "kd_p_l_pl": 1.2} # We can now add the curve to the plot, name it with an optional name= value. my_system.add_curve(system_parameters) # Show the plot my_system.show_plot()