API reference

Graph construction and descriptors

Fast, geometry-free molecular graph construction and descriptors.

class synde.graph.ComponentFrontier(component_id: 'int', nodes: 'tuple[Any, ...]', homo_energy: 'float | None', lumo_energy: 'float | None', homo_density: 'dict[Any, float]', lumo_density: 'dict[Any, float]')

Bases: object

component_id: int
homo_density: dict[Any, float]
homo_energy: float | None
lumo_density: dict[Any, float]
lumo_energy: float | None
nodes: tuple[Any, ...]
class synde.graph.DirectionalFMO(donor_component: 'int', acceptor_component: 'int', donor_atom: 'Any', acceptor_atom: 'Any', gap: 'float | None', regularized_gap: 'float | None', score: 'float', valid: 'bool', warning: 'str | None' = None)

Bases: object

acceptor_atom: Any
acceptor_component: int
donor_atom: Any
donor_component: int
gap: float | None
regularized_gap: float | None
score: float
valid: bool
warning: str | None = None
class synde.graph.GeneralizedHuckel(parameters: HuckelParameters | None = None)

Bases: object

Solve generalized Hückel systems built by synde.graph.pi_system.

frontier_subspaces(occupations: ndarray, energies: ndarray) tuple[tuple[int, ...], tuple[int, ...]]

Return degenerate HOMO and LUMO subspaces from explicit occupations.

static occupations(n_orbitals: int, electron_count: int) ndarray

Return an explicit occupation vector (two electrons then one, if needed).

solve(assignment: PiAssignmentResult) GeneralizedHuckelResult

Solve every assigned pi system using its explicit electron count.

static subspace_density(coefficients: ndarray, indices: tuple[int, ...]) ndarray

Return a basis-invariant local density summed over an orbital subspace.

class synde.graph.GeneralizedHuckelResult(systems: tuple[HuckelSystemResult, ...], parameter_set: str, status: str, warnings: tuple[str, ...])

Bases: object

Descriptor result for all pi systems in one normalized molecule graph.

parameter_set: str
property pi_stabilization: float
property raw_pi_energy: float
property reference_pi_energy: float
status: str
systems: tuple[HuckelSystemResult, ...]
warnings: tuple[str, ...]
class synde.graph.GraphBuilder

Bases: object

static from_graph(graph: Graph, *, strict: bool = True) NormalizedMolecularGraph
static from_smiles(smiles: str, *, strict: bool = True) NormalizedMolecularGraph
static from_synkit_graph(graph: Graph, *, strict: bool = True, canonical_smiles: str | None = None) NormalizedMolecularGraph
class synde.graph.GraphNormalizer(*, strict: bool = True)

Bases: object

Create a normalized copy of a NetworkX molecular graph.

In strict mode, missing element labels and malformed edge orders are input errors. Unsupported chemical environments remain structured partial results so callers can inspect the graph and decide whether to continue.

normalize(graph: Graph, *, canonical_smiles: str | None = None, source: str = 'networkx') NormalizedMolecularGraph

Return a normalized copy of graph.

The input graph is never mutated. MultiGraphs and directed graphs are rejected because SYN’s current molecular representation is an undirected simple graph.

class synde.graph.GraphPairScorer(config: PairScoringConfig | None = None, parameters: HuckelParameters | None = None)

Bases: object

Rank cross-component pi atom pairs; scores are not interaction energies.

rank(normalized: NormalizedMolecularGraph, *, top_k: int = 50, group_equivalence: bool = False) list[PairScoreResult] | list[PairScoreGroup]
exception synde.graph.GraphValidationError

Bases: ValueError

Raised for malformed graph input when strict validation is enabled.

class synde.graph.GraphWarning(code: str, message: str, nodes: tuple[Any, ...] = ())

Bases: object

A structured warning emitted while normalizing a molecular graph.

code: str
message: str
nodes: tuple[Any, ...] = ()
class synde.graph.HSABDescriptor(component_id: 'int', electronegativity: 'float | None', hardness: 'float | None', softness: 'float | None', local_nucleophilic_softness: 'dict[Any, float]', local_electrophilic_softness: 'dict[Any, float]')

Bases: object

component_id: int
electronegativity: float | None
hardness: float | None
local_electrophilic_softness: dict[Any, float]
local_nucleophilic_softness: dict[Any, float]
softness: float | None
class synde.graph.HuckelParameters(parameter_set: str = 'organic-v1', degeneracy_tolerance: float = 1e-08, beta_aromatic: float = -1.0, beta_double: float = -1.0, beta_conjugated: float = -0.8, hetero_beta_scale: float = 0.85, alpha: dict[str, float]=<factory>)

Bases: object

Initial versioned alpha/beta configuration for common organic pi systems.

alpha: dict[str, float]
beta_aromatic: float = -1.0
beta_conjugated: float = -0.8
beta_double: float = -1.0
degeneracy_tolerance: float = 1e-08
hetero_beta_scale: float = 0.85
parameter_set: str = 'organic-v1'
class synde.graph.HuckelSystemResult(nodes: tuple[Any, ...], electron_count: int, hamiltonian: ndarray, orbital_energies: ndarray, coefficients: ndarray, occupations: ndarray, alpha: dict[Any, float], raw_pi_energy: float, reference_pi_energy: float, pi_stabilization: float, pi_populations: ndarray, homo_indices: tuple[int, ...], lumo_indices: tuple[int, ...], homo_density: ndarray, lumo_density: ndarray | None)

Bases: object

Orbital and invariant descriptors for one connected pi system.

alpha: dict[Any, float]
coefficients: ndarray
electron_count: int
hamiltonian: ndarray
homo_density: ndarray
property homo_energy: float | None
homo_indices: tuple[int, ...]
lumo_density: ndarray | None
property lumo_energy: float | None
lumo_indices: tuple[int, ...]
nodes: tuple[Any, ...]
occupations: ndarray
orbital_energies: ndarray
pi_populations: ndarray
pi_stabilization: float
raw_pi_energy: float
reference_pi_energy: float
class synde.graph.ITSGraph(graph: Graph, reacting_atom_maps: tuple[int, ...], bond_changes: tuple[dict[str, Any], ...], reactant_graph: Graph, product_graph: Graph)

Bases: object

Mapped union graph whose edges retain reactant/product bond orders.

bond_changes: tuple[dict[str, Any], ...]
graph: Graph
product_graph: Graph
reactant_graph: Graph
reacting_atom_maps: tuple[int, ...]
class synde.graph.ITSGraphBuilder

Bases: object

Build an ITS graph only when atom mapping gives an unambiguous correspondence.

build(reactants: list[NormalizedMolecularGraph], products: list[NormalizedMolecularGraph]) ITSGraph
class synde.graph.NormalizedMolecularGraph(graph: Graph, identity: str, canonical_smiles: str | None, status: str, warnings: tuple[GraphWarning, ...], source: str)

Bases: object

Validated molecular graph plus identity, provenance, and warnings.

graph is a private copy of the input graph. Node identifiers are kept unchanged so atom-map and caller-level identities remain usable by later reaction modules.

canonical_smiles: str | None
graph: Graph
identity: str
source: str
status: str
to_dict() dict[str, Any]

Return serializable graph metadata; the NetworkX graph is omitted.

warning_codes() tuple[str, ...]

Return warning codes in encounter order.

warnings: tuple[GraphWarning, ...]
class synde.graph.PairScoreGroup(representative: PairScoreResult, pairs: tuple[tuple[Any, Any], ...], equivalence_key: tuple[Any, ...])

Bases: object

Symmetry-equivalent candidate pairs represented by one score row.

equivalence_key: tuple[Any, ...]
property equivalent_pairs: tuple[tuple[Any, Any], ...]

Backward-compatible alias for the grouped candidate pairs.

pairs: tuple[tuple[Any, Any], ...]
representative: PairScoreResult
class synde.graph.PairScoreResult(atom_a: 'Any', atom_b: 'Any', component_a: 'int', component_b: 'int', pair_compatibility_score: 'float', direction: 'str', components: 'dict[str, float]', warnings: 'tuple[str, ...]', equivalence_key: 'tuple[Any, ...]')

Bases: object

atom_a: Any
atom_b: Any
component_a: int
component_b: int
components: dict[str, float]
direction: str
equivalence_key: tuple[Any, ...]
pair_compatibility_score: float
warnings: tuple[str, ...]
class synde.graph.PairScoringConfig(gap_floor: 'float' = 0.05, fmo_weight: 'float' = 1.0, hsab_weight: 'float' = 0.25, charge_weight: 'float' = 0.05, accessibility_weight: 'float' = 0.1, proposed_bond_order: 'float' = 1.0)

Bases: object

accessibility_weight: float = 0.1
charge_weight: float = 0.05
fmo_weight: float = 1.0
gap_floor: float = 0.05
hsab_weight: float = 0.25
proposed_bond_order: float = 1.0
class synde.graph.PiAssignmentResult(pi_graph: Graph, atoms: tuple[PiAtom, ...], systems: tuple[PiSystem, ...], status: str, warnings: tuple[GraphWarning, ...])

Bases: object

Pi-system assignment for a normalized molecular graph.

atom_for(node: Any) PiAtom

Return the diagnostic record for node.

atoms: tuple[PiAtom, ...]
property electron_count: int

Return the total number of assigned pi electrons.

pi_graph: Graph
status: str
systems: tuple[PiSystem, ...]
warning_codes() tuple[str, ...]
warnings: tuple[GraphWarning, ...]
class synde.graph.PiAtom(node: Any, included: bool, electrons: int | None, reason: str, confidence: str)

Bases: object

Per-atom pi-orbital assignment diagnostic.

confidence: str
electrons: int | None
included: bool
node: Any
reason: str
class synde.graph.PiSystem(nodes: tuple[Any, ...], edges: tuple[tuple[Any, Any], ...], electron_count: int)

Bases: object

One connected system of coupled p orbitals.

edges: tuple[tuple[Any, Any], ...]
electron_count: int
nodes: tuple[Any, ...]
class synde.graph.PiSystemAssigner

Bases: object

Assign one-p-orbital Hückel systems for supported organic graphs.

The first v2 model intentionally supports one p orbital per atom. Triple bonds, radicals, and unsupported heteroatom environments are reported as diagnostics instead of being forced into an incorrect one-orbital model.

assign(normalized: NormalizedMolecularGraph) PiAssignmentResult

Build coupled pi systems and explicit electron counts.

synde.graph.assign_pi_systems(normalized: NormalizedMolecularGraph) PiAssignmentResult

Convenience wrapper around PiSystemAssigner.

synde.graph.directional_fmo(donor: ComponentFrontier, acceptor: ComponentFrontier, donor_atom: Any, acceptor_atom: Any, *, gap_floor: float = 0.05) DirectionalFMO

Return a graph-only donor-to-acceptor compatibility descriptor.

Non-positive gaps are invalid rather than replaced by an artificial tiny denominator. Small positive gaps are regularized and flagged.

synde.graph.hsab_descriptor(frontier: ComponentFrontier, *, hardness_floor: float = 0.05) HSABDescriptor

Build global and local HSAB features without claiming an energy value.

synde.graph.local_hsab_compatibility(donor: HSABDescriptor, acceptor: HSABDescriptor, donor_atom: Any, acceptor_atom: Any) float

Return a dimensionless local soft donor/acceptor compatibility feature.

synde.graph.normalize_graph(graph: Graph, *, strict: bool = True, canonical_smiles: str | None = None, source: str = 'networkx') NormalizedMolecularGraph

Convenience wrapper around GraphNormalizer.

synde.graph.solve_generalized_huckel(assignment: PiAssignmentResult, parameters: HuckelParameters | None = None) GeneralizedHuckelResult

Convenience wrapper for GeneralizedHuckel.

Graph-first scoring

Graph-derived molecular and reaction scoring, in explicit model units.

class synde.energy.CalibratedPrediction(value: 'float', units: 'str', target: 'str', uncertainty: 'float | None', applicability: 'float', model_card: 'ModelCard')

Bases: object

applicability: float
model_card: ModelCard
target: str
uncertainty: float | None
units: str
value: float
class synde.energy.CalibrationRecord(identifier: 'str', features: 'dict[str, float]', target: 'float', provenance: 'dict[str, Any]')

Bases: object

features: dict[str, float]
identifier: str
provenance: dict[str, Any]
target: float
class synde.energy.GraphEnergy

Bases: object

rank_pairs_from_smiles(smiles: str, *, top_k: int = 50)
score_its(reaction_smiles: str, *, config: ITSScoringConfig | None = None)

Return mapped reaction-centre feasibility terms in graph score units.

score_molecule_from_graph(graph)
score_molecule_from_smiles(smiles: str)
score_molecule_with_geometry(smiles: str, *, config: GeometryScoringConfig | None = None, score_margin: float | None = None)
score_reaction(reaction_smiles: str)
class synde.energy.ITSScoreResult(status: str, its_score: float | None, state_delta_score: float | None, units: str, components: dict[str, float], bond_changes: tuple[dict[str, Any], ...], reacting_atom_maps: tuple[int, ...], warnings: tuple[str, ...], provenance: dict[str, Any], its_graph: Any | None = None)

Bases: object

Mapped reaction-centre feasibility result; not a physical TS energy.

bond_changes: tuple[dict[str, Any], ...]
components: dict[str, float]
its_graph: Any | None = None
its_score: float | None
provenance: dict[str, Any]
reacting_atom_maps: tuple[int, ...]
state_delta_score: float | None
status: str
to_dict() dict[str, Any]
units: str
warnings: tuple[str, ...]
class synde.energy.ITSScorer(molecule_scorer: MoleculeScorer | None = None, pair_scorer: GraphPairScorer | None = None, config: ITSScoringConfig | None = None)

Bases: object

Score mapped graph edits and actual formed-bond interaction descriptors.

Lower values indicate a more favourable initial heuristic. The score is a reaction-ranking feature, never an asserted transition-state energy.

score(reactants: list[NormalizedMolecularGraph], products: list[NormalizedMolecularGraph], reaction_smiles: str) ITSScoreResult
class synde.energy.ITSScoringConfig(state_delta_weight: float = 1.0, formed_bond_weight: float = 1.0, broken_bond_weight: float = 1.0, order_change_weight: float = 0.5, valence_reorganization_weight: float = 0.1, aromaticity_reorganization_weight: float = 0.2, fmo_weight: float = 1.0, hsab_weight: float = 0.25, charge_weight: float = 0.05)

Bases: object

Initial transparent weights for the barrier-like ITS heuristic.

aromaticity_reorganization_weight: float = 0.2
broken_bond_weight: float = 1.0
charge_weight: float = 0.05
fmo_weight: float = 1.0
formed_bond_weight: float = 1.0
hsab_weight: float = 0.25
order_change_weight: float = 0.5
state_delta_weight: float = 1.0
valence_reorganization_weight: float = 0.1
class synde.energy.ModelCard(model_name: 'str', target: 'str', units: 'str', feature_names: 'tuple[str, ...]', ridge_alpha: 'float', metrics: 'dict[str, float]', training_count: 'int', version: 'str' = '1')

Bases: object

feature_names: tuple[str, ...]
metrics: dict[str, float]
model_name: str
ridge_alpha: float
target: str
training_count: int
units: str
version: str = '1'
class synde.energy.MoleculeScoreResult(status: 'str', score: 'float | None', units: 'str', components: 'dict[str, float]', descriptors: 'dict[str, Any]', warnings: 'tuple[str, ...]', provenance: 'dict[str, Any]')

Bases: object

components: dict[str, float]
descriptors: dict[str, Any]
provenance: dict[str, Any]
score: float | None
status: str
to_dict() dict[str, Any]
units: str
warnings: tuple[str, ...]
class synde.energy.MoleculeScorer(config: MoleculeScoringConfig | None = None, parameters: HuckelParameters | None = None)

Bases: object

score(normalized: NormalizedMolecularGraph) MoleculeScoreResult
class synde.energy.MoleculeScoringConfig(pi_weight: 'float' = 1.0)

Bases: object

pi_weight: float = 1.0
class synde.energy.ReactionScoreResult(status: 'str', reaction_delta_score: 'float | None', units: 'str', reactant_score: 'float | None', product_score: 'float | None', bond_changes: 'tuple[dict[str, Any], ...]', components: 'dict[str, float]', warnings: 'tuple[str, ...]', provenance: 'dict[str, Any]')

Bases: object

bond_changes: tuple[dict[str, Any], ...]
components: dict[str, float]
product_score: float | None
provenance: dict[str, Any]
reactant_score: float | None
reaction_delta_score: float | None
status: str
to_dict() dict[str, Any]
units: str
warnings: tuple[str, ...]
class synde.energy.ReactionScorer(molecule_scorer: MoleculeScorer | None = None, config: ReactionScoringConfig | None = None)

Bases: object

score(reactants: list[NormalizedMolecularGraph], products: list[NormalizedMolecularGraph], reaction_smiles: str) ReactionScoreResult
class synde.energy.ReactionScoringConfig(require_atom_mapping: 'bool' = True)

Bases: object

require_atom_mapping: bool = True
class synde.energy.RidgeCalibrator(*, alpha: float = 1e-06, target: str, units: str = 'kcal/mol')

Bases: object

NumPy-only ridge baseline; suitable for transparent first calibration.

card: ModelCard | None
feature_names: tuple[str, ...]
fit(records: Iterable[CalibrationRecord]) ModelCard
mean: ndarray | None
predict(features: dict[str, float]) CalibratedPrediction
residual_std: float | None
save(path: Path) None
scale: ndarray | None
weights: ndarray | None
synde.energy.deterministic_split(records: Iterable[CalibrationRecord], *, train_fraction: float = 0.8) tuple[list[CalibrationRecord], list[CalibrationRecord]]

Geometry and workflow integrations

Optional conformer-aware scoring utilities.

class synde.geometry.GeometryScoreResult(status: 'str', geometry_corrected_score: 'float | None', force_field_energy_kcal_mol: 'float | None', components: 'dict[str, float]', warnings: 'tuple[str, ...]', provenance: 'dict[str, Any]')

Bases: object

components: dict[str, float]
force_field_energy_kcal_mol: float | None
geometry_corrected_score: float | None
provenance: dict[str, Any]
status: str
to_dict() dict[str, Any]
warnings: tuple[str, ...]
class synde.geometry.GeometryScorer(config: GeometryScoringConfig | None = None, molecule_scorer: MoleculeScorer | None = None)

Bases: object

static nonbonded_terms_for_positions(graph, positions: dict[int, tuple[float, float, float]]) dict[str, float]

Distance-term helper for deterministic tests and supplied poses.

score_smiles(smiles: str) GeometryScoreResult
should_run(normalized, *, score_margin: float | None = None) bool

Apply explicit user/uncertainty/flexibility gating without embedding.

class synde.geometry.GeometryScoringConfig(num_conformers: 'int | str' = 'auto', force_field: 'str' = 'MMFF94', random_seed: 'int' = 42, gate: 'str' = 'always')

Bases: object

force_field: str = 'MMFF94'
gate: str = 'always'
num_conformers: int | str = 'auto'
random_seed: int = 42

Adapters joining SynDE graph scores to higher-level workflows.

class synde.integration.CascadeReport(rows: 'tuple[CascadeRow, ...]', shortlist_size: 'int', graph_seconds: 'float', xtb_seconds: 'float')

Bases: object

graph_seconds: float
rows: tuple[CascadeRow, ...]
shortlist_size: int
xtb_seconds: float
class synde.integration.CascadeRow(reaction_smiles: 'str', graph_score: 'float | None', xtb_delta_e: 'float | None', selected: 'bool', status: 'str')

Bases: object

graph_score: float | None
reaction_smiles: str
selected: bool
status: str
xtb_delta_e: float | None
class synde.integration.GraphXTBCascade(graph_energy: GraphEnergy | None = None)

Bases: object

Use graph scores to choose reactions for a named xTB evaluator.

screen(reactions: list[str], *, top_k: int = 10, level: str = 'loose', xtb_evaluator: Callable[[str, str], float] | None = None) CascadeReport
class synde.integration.SFEnergy(energy_type: str = 'XTB', num_threads: int = 4, verbose: int = 0, random_seed: int = 42)

Bases: object

sort_reactions(reactions: List[str], num_conformers: str = 'auto', embedding_method: str = 'ETKDGv3', random_coords_threshold: int = 100, force_field_method: str = 'MMFF94', max_iter: str = 'auto', sort: bool | None = True) Tuple[List[str], List[float]]

Processes and sorts a list of reaction SMILES strings based on their calculated energy values.

Parameters: - reactions (List[str]): List of reaction SMILES strings. - num_conformers (str): Strategy for determining the number of conformers. Default ‘auto’. - embedding_method (str): Embedding method. Default ‘ETKDGv3’. - random_coords_threshold (int): Threshold for using random coordinates. Default 100. - force_field_method (str): Force field method used for energy calculations. Default ‘MMFF94’. - max_iter (str): Maximum number of iterations during calculation. Default ‘auto’. - sort (bool, optional): Whether to sort the results by energy in ascending order. Default True.

Returns: - Tuple[List[str], List[float]]: Sorted list of reaction SMILES and their corresponding energy values.