Skip to content

WARNING: this was LLM-generated and has not been fully reviewed yet.

Quickstart

This notebook walks through the basics of computing equilibrium concentrations with equiconc.

import equiconc
import matplotlib.pyplot as plt

Simple dimerization

Consider two strands A and B at 100 nM each that can form a heterodimer AB with \(\Delta G^\circ = -10\) kcal/mol at 25 °C.

eq = (
    equiconc.System()
    .monomer("A", 100e-9)
    .monomer("B", 100e-9)
    .complex("AB", [("A", 1), ("B", 1)], dg_st=-10.0)
    .equilibrium()
)

for name, conc in eq.items():
    print(f"{name:>3s}: {conc:.3e} M")
  A: 4.889e-08 M
  B: 4.889e-08 M
 AB: 5.111e-08 M

Exploring the result

The Equilibrium object supports dict-like access, iteration, and several convenience properties.

# Bracket access
print(f"[AB] = {eq['AB']:.3e} M")

# Membership test
print(f"'AB' in eq: {'AB' in eq}")
print(f"'XY' in eq: {'XY' in eq}")

# Named lookup
print(f"eq.concentration('AB') = {eq.concentration('AB'):.3e}")
[AB] = 5.111e-08 M
'AB' in eq: True
'XY' in eq: False
eq.concentration('AB') = 5.111e-08
# Properties
print("Monomer names:", eq.monomer_names)
print("Complex names:", eq.complex_names)
print("Converged fully:", eq.converged_fully)
Monomer names: ['A', 'B']
Complex names: ['AB']
Converged fully: True

Mass conservation check

The total concentration of each monomer is conserved: \([\text{A}]_\text{free} + [\text{AB}] = [\text{A}]_\text{total}\).

total_A = eq["A"] + eq["AB"]
print(f"Total [A] = {total_A:.3e} M  (expected 1.000e-07 M)")

total_B = eq["B"] + eq["AB"]
print(f"Total [B] = {total_B:.3e} M  (expected 1.000e-07 M)")
Total [A] = 1.000e-07 M  (expected 1.000e-07 M)
Total [B] = 1.000e-07 M  (expected 1.000e-07 M)

Multi-complex system

Now consider a system where strand A can bind B or C, forming heterodimers AB and AC with different affinities.

eq2 = (
    equiconc.System()
    .monomer("A", 1e-6)
    .monomer("B", 1e-6)
    .monomer("C", 1e-6)
    .complex("AB", [("A", 1), ("B", 1)], dg_st=-12.0)
    .complex("AC", [("A", 1), ("C", 1)], dg_st=-8.0)
    .equilibrium()
)

for name, conc in eq2.items():
    print(f"{name:>3s}: {conc:.3e} M")
  A: 2.974e-08 M
  B: 5.103e-08 M
  C: 9.787e-07 M
 AB: 9.490e-07 M
 AC: 2.129e-08 M

Visualizing concentrations

A simple bar chart of the equilibrium concentrations.

d = eq2.to_dict()

fig, ax = plt.subplots(figsize=(5, 3))
ax.bar(d.keys(), [v * 1e6 for v in d.values()], color="teal")
ax.set_ylabel("Concentration (uM)")
ax.set_title("Equilibrium concentrations")
fig.tight_layout()
plt.show()

png