Skip to content

Python Library Guide

Antonio Marinho edited this page Sep 30, 2026 · 5 revisions

Python Library Guide

FleXgeo2 can be used as a Python library when you want to run analyses inside notebooks, inspect data frames in memory, or integrate geometry descriptors into another workflow.

High-level API

The main entry point is FlexGeo2App.

from flexgeo2 import AnalysisConfig, FlexGeo2App

result = FlexGeo2App().run(
    AnalysisConfig(pdb_file="path/to/ensemble.pdb")
)

The top-level configuration objects are:

  • AnalysisConfig: full analysis settings
  • OutputConfig: output directory and file-writing policy
  • ReferenceConfig: reference-state comparison settings
  • ClusteringConfig: per-residue and residue-range clustering settings

AnalysisConfig

from flexgeo2 import AnalysisConfig, ClusteringConfig, OutputConfig, ReferenceConfig

config = AnalysisConfig(
    pdb_file="path/to/ensemble.pdb",
    chains=["A"],
    n_jobs=4,
    max_models_in_plot=12,
    hide_model_traces=False,
    dmax_outlier_fraction=0.01,
    reference=ReferenceConfig(model_id="1"),
    clustering=ClusteringConfig(
        cluster_residues=True,
        cluster_residue_ranges=["45-54"],
        min_cluster_size=8,
        min_samples=4,
    ),
    output=OutputConfig(output_dir="path/to/results", distance_matrices=True),
)

OutputConfig

  • output_dir: where to write the results; default None, which writes no files
  • overwrite: allow writing into a folder that already has files, replacing an earlier run's outputs (other files are kept); default False
  • distance_matrices: also write reference/matrices/<chain>.csv; needs a reference

Configuration mistakes (an unknown chain or model, a residue range that is not in the structure, a non-empty output folder without overwrite=True) raise an error before Melodia runs.

Running without writing files

Without an output_dir (the default), FleXgeo2 writes no files and returns the results in memory. Write the output folder later with result.save(): it uses the run's other output settings (plot format, residue plots, distance matrices) and, like a run, refuses a folder that already has files unless overwrite=True.

from flexgeo2 import AnalysisConfig, FlexGeo2App

result = FlexGeo2App().run(AnalysisConfig(pdb_file="path/to/ensemble.pdb"))
result.save("path/to/results")

Result objects

FlexGeo2App().run(config) returns an AnalysisResult with:

  • pdb_file: resolved input path
  • raw_df: normalized Melodia descriptor table
  • residue_summary_df: per-residue curvature, torsion, and dmax summary
  • model_summary_df: per-chain model summary
  • overall_model_summary_df: model summary across selected chains
  • distance_result: optional DistanceResult
  • residue_clustering: optional ResidueClusteringResult
  • residue_range_clustering: optional ResidueRangeClusteringResult
  • outputs: OutputArtifacts with paths to written files, including readme and run_manifest
  • config: the AnalysisConfig that produced the result

DistanceResult contains long_df, summary_df, and reference_label.

ResidueClusteringResult and ResidueRangeClusteringResult each contain assignments_df and summary_df.

Tables with one row per model and residue (raw_df, DistanceResult.long_df, the per-residue assignments_df) start with chain, model, order, name, residue_label, so they can be joined on those columns. model is the PDB MODEL number.

Figures

Every figure FleXgeo2 writes can also be drawn from a result, without writing files. Each method returns a matplotlib Figure:

Method Figure Needs
result.plot_overview(chains=None) overview.png
result.plot_distance_heatmap(chains=None) reference/heatmap.png a reference
result.plot_cluster_map(chains=None) clusters/clusters.png cluster_residues=True
result.plot_residue("A:45") residue_plots/...
result.plot_residue_range("A:10-20") range_clusters/... that range in cluster_residue_ranges

chains takes a chain ID or a list of them. plot_residue takes a residue number, or "CHAIN:NUMBER" when several chains have that number. The overview uses the run's max_models_in_plot and hide_model_traces.

Save a figure with save_figure, which saves it as FleXgeo2 saves its own: PDFs embed TrueType fonts and SVGs keep text as text, so the figure stays editable. fig.savefig() uses your session's matplotlib settings instead (Type 3 fonts in PDF by default).

from flexgeo2 import save_figure

fig = result.plot_residue("A:71")
save_figure(fig, "leu71.pdf")

Drawing a figure does not change your matplotlib settings, and your settings do not change FleXgeo2's figures.

CLI to Python examples

Basic run:

flexgeo2 path/to/ensemble.pdb
AnalysisConfig(pdb_file="path/to/ensemble.pdb")

Chain filtering:

flexgeo2 path/to/ensemble.pdb --chain A --n-jobs 4
AnalysisConfig(
    pdb_file="path/to/ensemble.pdb",
    chains=["A"],
    n_jobs=4,
)

Reference model comparison:

flexgeo2 path/to/ensemble.pdb --reference-model 1
AnalysisConfig(
    pdb_file="path/to/ensemble.pdb",
    reference=ReferenceConfig(model_id="1"),
)

External reference PDB:

flexgeo2 path/to/ensemble.pdb \
  --reference-pdb path/to/reference.pdb \
  --reference-pdb-model 1
AnalysisConfig(
    pdb_file="path/to/ensemble.pdb",
    reference=ReferenceConfig(
        pdb_file="path/to/reference.pdb",
        pdb_model_id="1",
    ),
)

Residue clustering:

flexgeo2 path/to/ensemble.pdb \
  --cluster-residues \
  --cluster-min-size 8 \
  --cluster-min-samples 4
AnalysisConfig(
    pdb_file="path/to/ensemble.pdb",
    clustering=ClusteringConfig(
        cluster_residues=True,
        min_cluster_size=8,
        min_samples=4,
    ),
)

Residue-range clustering:

flexgeo2 path/to/ensemble.pdb \
  --chain A \
  --cluster-residue-range 45-54 \
  --cluster-residue-range 90-99
AnalysisConfig(
    pdb_file="path/to/ensemble.pdb",
    chains=["A"],
    clustering=ClusteringConfig(
        cluster_residue_ranges=["45-54", "90-99"],
    ),
)

For a notebook dedicated to these mappings, see notebooks/05_cli_to_python_mapping.ipynb.

Service-level API

Advanced users can call services directly.

from flexgeo2.geometry import GeometryService

geometry = GeometryService()
raw_df = geometry.load_structure("path/to/ensemble.pdb", n_jobs=4)
raw_df = geometry.filter_chains(raw_df, ["A"])
raw_df = geometry.normalize(raw_df)
summary_df = geometry.summarize(raw_df, dmax_outlier_fraction=0.01)
from flexgeo2.clustering import ClusteringService

clusters = ClusteringService()
# None: the defaults (smallest cluster 5% of the models, at least 5; min_samples 5)
assignments_df, cluster_summary_df = clusters.cluster_residues(
    raw_df,
    min_cluster_size=None,
    min_samples=None,
)
from flexgeo2.config import OutputConfig
from flexgeo2.outputs import OutputWriter

writer = OutputWriter(OutputConfig(output_dir="path/to/results"))
artifacts = writer.write(
    result,
    max_models_in_plot=12,
    hide_model_traces=False,
)

Clone this wiki locally