starling.structure.bme

Bayesian Maximum Entropy (BME) reweighting for ensemble refinement.

This module provides tools for reweighting molecular ensembles using experimental observables through the Bayesian Maximum Entropy framework.

The BME method optimally reweights ensemble conformations to match experimental data while minimizing the bias introduced (measured by relative entropy). This provides a principled way to integrate experimental constraints into molecular simulation ensembles.

Key Classes

ExperimentalObservabledataclass

Container for experimental data with value, uncertainty, and constraint type.

BMEclass

Main BME optimizer that performs the reweighting optimization.

BMEResultdataclass

Container for optimization results including weights, chi-squared, and metadata.

Example Usage

Integration with Ensemble

The BME functionality is integrated into the Ensemble class and is the recommended way to use BME with STARLING.

>>> # Using with Ensemble
>>> from starling import generate, load_ensemble
>>> ensemble = generate("GS"*30, conformations=200) # or load_ensemble("path/to/ensemble")
>>> # Calculate observables
>>> rg_values = ensemble.radius_of_gyration()
>>> ete_values = ensemble.end_to_end_distance()
>>> calculated = np.column_stack([rg_values, ete_values])
>>> # Define experimental constraints
>>> obs_rg = ExperimentalObservable(23.0, 2.0, name="Rg", constraint="equality")
>>> obs_ete = ExperimentalObservable(55.0, 5.0, name="End-to-end", constraint="upper")
>>>
>>> # Perform BME reweighting
>>> result = ensemble.reweight_bme([obs_rg, obs_ete], calculated)
>>>
>>> # Use BME weights in calculations
>>> reweighted_rg = ensemble.radius_of_gyration(return_mean=True, use_bme_weights=True)
>>> reweighted_ete = ensemble.end_to_end_distance(return_mean=True, use_bme_weights=True)

BME Standalone

The BME class can also be used standalone without the Ensemble class. This is useful for advanced workflows or when you want to apply BME to observables not directly supported by STARLING.

>>> from starling.structure.bme import BME, ExperimentalObservable
>>> import numpy as np
>>>
>>> # Define experimental observables with different constraint types
>>> # Only three valid constraint strings: "equality", "upper", "lower"
>>>
>>> # Equality constraint: Rg should match 25.0 ± 2.0 Å (default)
>>> obs_rg = ExperimentalObservable(
...     value=25.0,
...     uncertainty=2.0,
...     name="Radius of gyration"
... )
>>>
>>> # Upper bound: End-to-end distance should not exceed 70 Å
>>> obs_ete = ExperimentalObservable(
...     value=70.0,
...     uncertainty=5.0,
...     constraint="upper",
...     name="End-to-end distance"
... )
>>>
>>> # Calculated values from ensemble (n_frames x n_observables)
>>> calculated = np.random.randn(1000, 3) * 2 + np.array([24, 65, 0.25])
>>>
>>> # Create and fit BME model
>>> bme = BME([obs_rg, obs_ete, obs_helix], calculated, theta=0.5)
>>> result = bme.fit(verbose=True)
>>>
>>> # Use optimized weights
>>> reweighted_means = bme.predict(calculated)

Classes

BME

Bayesian Maximum Entropy reweighting.