SynDE
Interpretable 2D prediction of protocol-defined GFN2-xTB molecular energies, with constitutional-isomer ranking as the connectivity stress test.
Online documentation is hosted at synde.readthedocs.io.
Contents — Overview · Command-line example · Installation · Usage · Scope and domain constraints · Reproducibility · Package structure · Citation
Overview
SynDE predicts a protocol-defined molecular-energy coordinate from a two-dimensional molecular graph without conformer generation or xTB execution at inference time. The validated 633-term connectivity equation ranks constitutional isomers. The active energy workflow fits an extensive element-count baseline around those unchanged weights using training data only; the resulting complete predictor is then evaluated globally and within formula on one external cohort.
- Two complementary tasks: Predict total energies across formulas or rank constitutional isomers within one formula.
- Connectivity stress test: Same-formula ranking removes atom-count signal exactly and tests whether a model resolves bonding and topology.
- Interpretable terms: Each prediction decomposes into exact signed linear components that sum to the total score.
- Self-contained ranking: The validated connectivity weights are bundled; no external semiempirical quantum binary is required for graph scoring.
- Provenance tracking: Includes model cards, validation records, and feature-distance diagnostic warnings.
- Usable from the shell: A
syndeconsole script predicts, explains, and ranks, with JSON and CSV output, parallel scoring, and shell completion. - Lazy imports:
import syndedoes not load RDKit, NetworkX, or NumPy until an exported symbol needs one of them.
Every prediction is reported as the sum of its composition and connectivity blocks:
predicted_energy = composition_total + connectivity_total
Command-line example
Predicting across formulas, and ranking constitutional isomers within one:
$ synde predict CCO 'CC(=O)O' c1ccccc1
structure formula energy (eV) composition connectivity
--------- ------- ----------- ----------- ------------
CCO C2H6O -310.0180 -304.0719 -5.9462
CC(=O)O C2H4O2 -393.3796 -386.3469 -7.0327
c1ccccc1 C6H6 -432.0563 -422.7000 -9.3563
$ synde rank CCCCC 'CC(C)CC' 'CC(C)(C)C'
C5H12 3 candidates, lowest predicted energy first
──────────────────────────────────────────────────────────────
# structure energy (eV) Δ vs best connectivity
- --------- ----------- --------- ------------
1 CC(C)(C)C -458.0003 +0.0000 -11.0020
2 CC(C)CC -457.9810 +0.0193 -10.9827
3 CCCCC -457.9317 +0.0685 -10.9335
Install below, then see Usage for the full command set and the Python API.
Installation
Standard installation
git clone https://github.com/TieuLongPhan/SynDE.git
cd SynDE
python -m pip install -e .
This installs the synde command and the packaged predictor. The default
frozen 2D scorer needs no thermo, no tblite, and no xTB executable.
Verify the install:
synde --version
synde predict CCO
Development dependencies
The supplied Conda environment includes optional empirical, semiempirical, experiment, test, and documentation dependencies, including the xTB executable:
conda env create -f env.yml
conda activate synde
python -m pip install -e .
Optional Python backends can instead be installed individually:
python -m pip install -e '.[empirical]' # Joback terms via thermo
python -m pip install -e '.[semiempirical]' # GFN2 single points via tblite
python -m pip install -e '.[experiment,dev]' # calibration and developer tools
--jobs parallel scoring uses joblib from the experiment extra. Without it
SynDE scores serially and says so; nothing fails.
Usage
Which entry point do I need?
| Goal | Python | Command line |
|---|---|---|
| Energy of one molecule | predictor.predict_smiles(s) |
synde predict SMILES |
| Energies of many molecules | predictor.predict_many_smiles([...]) |
synde predict --input FILE |
| Why is this value what it is? | prediction.summary() |
synde explain SMILES |
| Order constitutional isomers | predictor.rank_smiles([...]) |
synde rank SMILES... |
| What can this model accept? | predictor.summary() |
synde card |
The *_smiles helpers parse with GraphBuilder and then call the graph-level
predict(), predict_many(), and rank_group() methods, which remain
available when a normalized graph is already in hand.
From the command line
synde predict CCO 'CC(=O)O' # energies across formulas
synde explain 'CC(=O)NC' --top 5 # signed contribution breakdown
synde rank CCCCC 'CC(C)CC' 'CC(C)(C)C' # order isomers
synde card # provenance and domain limits
Reading input and writing machine-readable output:
synde predict --input molecules.smi --format csv > energies.csv
synde predict --input big.smi --jobs 8 --format json
cat molecules.smi | synde predict --input -
synde completion zsh >> ~/.zshrc
--input skips blank lines and # comments and reads only the first
whitespace-separated field, so ordinary .smi files work unchanged. By default
a structure outside the model domain stops the run; --keep-going scores the
rest and reports skips on stderr, still exiting non-zero. See the
CLI documentation for the full option list.
1. Predict energy across formula groups
from synde.energy import SynDEEnergyPredictor
from synde.graph import GraphBuilder
predictor = SynDEEnergyPredictor.load_default()
molecules = [
GraphBuilder.from_smiles("CCO"),
GraphBuilder.from_smiles("CC(=O)O"),
]
for molecule, output in zip(molecules, predictor.predict_many(molecules)):
print(molecule.canonical_smiles, output.predicted_energy, output.units)
print(output.composition_total, output.connectivity_total)
The packaged default artifact was generated by
bash Experiment/run_global_comparators.sh from the active training cohort.
These predictions estimate the raw optimized total energy produced by the
model's declared GFN2-xTB reference protocol. They are comparable across
formula groups only within that same protocol and chemical domain; they are
not experimental energies, free energies, or conformer-ensemble energies.
2. Rank isomer groups with the same model
ranking = predictor.rank_smiles(["CCCCC", "CC(C)CC", "CC(C)(C)C"])
for position, (input_index, output) in enumerate(ranking, start=1):
print(position, output.canonical_smiles, output.predicted_energy)
print(ranking.summary()) # or just `ranking` in a Jupyter cell
Lower predictions indicate lower model energy. All candidates passed to
rank_group() and rank_smiles() must share the exact same molecular formula
and formal charge. Their composition totals are identical, so only connectivity
changes the ordering.
3. Inspect a prediction
output = predictor.predict_smiles("CC(=O)NC")
print(output) # one-line headline
print(output.summary()) # full signed breakdown
output.top_contributions(5) # largest active connectivity terms
print("Status:", output.status)
print("Energy:", output.predicted_energy, output.units)
print("Composition:", output.composition_contributions)
print("Connectivity:", output.connectivity_contributions)
print("Warnings:", output.warnings)
print("Provenance:", output.provenance)
data_dict = output.to_dict()
Predictions, rankings, and the predictor itself render as HTML tables in
Jupyter. summary() takes color=False for log files and precision for the
displayed digits.
4. Understand a rejection
Structures outside the applicability domain raise SynDEDomainError, which
names the input, the rule it violated, and a concrete next step:
>>> predictor.predict_smiles("[Na+].[Cl-]")
SynDEDomainError: SynDE energy prediction requires one connected molecule;
this input has 2 disconnected fragments. (input: [Cl-].[Na+])
Hint: Split the input on '.' and score each neutral component separately;
salts and solvates are not single molecules.
Model domain: elements [B Br C Cl F H I N O P S Si]; total formal charge [0];
connected, closed-shell, non-isotopic structures
Every SynDE exception subclasses ValueError, so existing except ValueError
handlers keep working. error.details carries the same facts in
machine-readable form.
Scope and domain constraints
- Supported model elements: determined from the active training cohort;
external molecules containing unseen elements are rejected. Run
synde cardto print the list carried by the artifact you have installed. - Electronic domain: Connected, neutral, closed-shell structures.
- Isomer Class: Constitutional isomers (same formula, different atom connectivity).
- Cross-formula target: Single-conformer, gas-phase GFN2-xTB 6.7.1 optimized total energy in eV under the declared reference protocol.
- Ranking target: Formula-relative ordering under the same declared target protocol.
- Interpretation: Both are statistical graph projections, not physical conformer populations, experimental energies, or free energies.
Use SynDEEnergyPredictor for both tasks: predict()/predict_many() globally
and predict_group()/rank_group() locally. SynDEScorer remains available
only as a compatibility interface to the original connectivity-validation
record; its raw subtotal must not be compared across formulas.
Reproducibility
Use the synde Conda environment for every command below:
conda activate synde
Validate the published records and packaged model without retraining:
python Experiment/scripts/13_validate.py
Regenerate the fitted artifacts and external-evaluation outputs:
bash Experiment/run_global_comparators.sh
Run the repository quality gates and strict documentation build:
bash scripts/lint.sh
bash scripts/pytest.sh -q
bash scripts/build_doc.sh
Build and inspect the installable distributions:
python -m build
python scripts/check_package_artifacts.py dist
Package structure
| Directory | Description |
|---|---|
synde/graph/ |
Graph normalization, topological invariants, and $\pi$-system assignments. |
synde/energy/ |
Cross-formula predictor, frozen ranking scorer, model cards, attribution, and result dataclasses. |
synde/geometry/ |
Conformer generation and semiempirical xTB workflow utilities. |
synde/integration/ |
Workflow adapters and reaction/ITS scoring tools. |
synde/models/ |
Bundled default model resources and weights. |
synde/cli.py |
The synde console script. |
synde/report.py |
Rendering shared by the CLI, __repr__, and Jupyter output. |
synde/formatting.py |
Dependency-free table, colour, and number formatting. |
synde/errors.py |
Structured, actionable exception types. |
doc/ |
Sphinx documentation source files. |
scripts/ |
Repository lint, test, documentation, and package checks. |
Citation
If SynDE contributes to work you publish, please cite the software:
@software{phan_synde,
author = {Phan, Tieu Long},
title = {SynDE: Interpretable 2D GFN2-xTB energy prediction and isomer ranking},
version = {0.5.0},
url = {https://github.com/TieuLongPhan/SynDE},
license = {MIT}
}
Please also report the model_name and model_sha256 from the model card of
the artifact you used, which synde card prints, so results stay traceable to
an exact set of weights.
Documentation
License
SynDE is distributed under the MIT License. See LICENSE.
Acknowledgments
This project received funding from the European Union's Horizon Europe Doctoral Network programme under Marie Skłodowska-Curie grant agreement No. 101072930 (TACsy).
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file synde-0.5.0.tar.gz.
File metadata
- Download URL: synde-0.5.0.tar.gz
- Upload date:
- Size: 26.4 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5ecf759ab3d975669c4ddefd946379925a1f6364d8fe4e7dcacfdf9d002e3d9a
|
|
| MD5 |
1bcb5c58e469bd9febe839ca3ca1e31d
|
|
| BLAKE2b-256 |
bdea7051da1a05c56cd794dcb7747339a80c5c67da44d07a069cca1541f7afa1
|
Provenance
The following attestation bundles were made for synde-0.5.0.tar.gz:
Publisher:
publish-package.yml on TieuLongPhan/SynDE
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
synde-0.5.0.tar.gz -
Subject digest:
5ecf759ab3d975669c4ddefd946379925a1f6364d8fe4e7dcacfdf9d002e3d9a - Sigstore transparency entry: 2614942655
- Sigstore integration time:
-
Permalink:
TieuLongPhan/SynDE@1637d901975beb12663acb00a9421f34fb2277d9 -
Branch / Tag:
refs/tags/v0.5.0 - Owner: https://github.com/TieuLongPhan
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-package.yml@1637d901975beb12663acb00a9421f34fb2277d9 -
Trigger Event:
release
-
Statement type:
File details
Details for the file synde-0.5.0-py3-none-any.whl.
File metadata
- Download URL: synde-0.5.0-py3-none-any.whl
- Upload date:
- Size: 240.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0473bc06a6a6ff0db52ce461f39bdf2b95ef69cf4a51e94cc450b4420eb3ce89
|
|
| MD5 |
163725079c9901a76c6b86fa58613633
|
|
| BLAKE2b-256 |
849804d55228cc861fb4ec63aeabe7e17a6dde073dafa9bbfcd292251ebd0d85
|
Provenance
The following attestation bundles were made for synde-0.5.0-py3-none-any.whl:
Publisher:
publish-package.yml on TieuLongPhan/SynDE
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
synde-0.5.0-py3-none-any.whl -
Subject digest:
0473bc06a6a6ff0db52ce461f39bdf2b95ef69cf4a51e94cc450b4420eb3ce89 - Sigstore transparency entry: 2614942780
- Sigstore integration time:
-
Permalink:
TieuLongPhan/SynDE@1637d901975beb12663acb00a9421f34fb2277d9 -
Branch / Tag:
refs/tags/v0.5.0 - Owner: https://github.com/TieuLongPhan
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-package.yml@1637d901975beb12663acb00a9421f34fb2277d9 -
Trigger Event:
release
-
Statement type: