Skip to main content

reactionstudio-python

Python client for ReactionStudio — run conformer searches, geometry optimisations and transition-path calculations from code.

pip install reactionstudio

Getting a key

Sign in to ReactionStudio, go to the compute platform, open Account → API keys, and generate one. The key is shown once. Put it in your environment:

export REACTIONSTUDIO_API_KEY=rs_live_...

A key can submit jobs and read their status and results. It cannot buy tokens, create further keys, or read your billing history — those need a browser session, so a leaked key can't escalate.

Quick start

import reactionstudio as rs

client = rs.Client()

conformers = client.generate_conformers( "CCO", force_field="gfn2-xtb" ).wait()

print(f"{len(conformers)} conformers")
print(f"lowest energy: {conformers.lowest_energy.energy:.2f} kJ/mol")

wait() blocks until the job finishes, polling with backoff, and raises if the computation fails.

The three experiments

Conformer generation

Takes a SMILES string, no chemistry packages required.

conformers = client.generate_conformers(
    "CC(=O)Oc1ccccc1C(=O)O",
    force_field="gfn2-xtb",
    n_initial_conformers=1000,   # embedded before pruning
).wait()

for c in conformers:
    print( c.energy, c.cluster_size )

best = conformers.molecule(0)    # reusable as input elsewhere

Geometry optimisation

mol = rs.Molecule.from_file( "ethanol.xyz" ) # Will infer bonds from atom distances.

result = client.stabilize_conformation( mol, force_field="gfn2-xtb" ).wait()

print(result.converged, result.final_energy)
print(result.energy_change)      # how far downhill it went, kJ/mol

Transition paths

path = client.transition_path(
    rs.Molecule.from_file("reactant.xyz"),
    rs.Molecule.from_file("product.xyz"), # should contain  atoms in the same order
    force_field="gfn2-xtb",
    n_images=20,
).wait()

print(f"barrier: {path.barrier:.1f} kJ/mol")
print(f"reaction energy: {path.reaction_energy:.1f} kJ/mol")

open("path.xyz", "w").write(path.to_xyz())      # multi-frame trajectory
ts = path.transition_state                      # a Molecule

Both structures must have their atoms in the same order — interpolation is per-atom, so the client checks and refuses a mismatch rather than letting you pay for a meaningless path.

Molecules

rs.Molecule.from_file("thing.xyz")     # .xyz, .mol, .sdf natively; .pdb via ase
rs.Molecule.from_xyz(text)
rs.Molecule.from_molfile(text)         # keeps the bond block
rs.Molecule.from_smiles("CCO")         # needs [rdkit]; does not use the API
rs.Molecule.from_ase(atoms)            # needs [ase]
rs.Molecule.from_rdkit(mol)            # needs [rdkit]
rs.Molecule.new([6, 8], [[0, 0, 0], [1.2, 0, 0]])

new() accepts element symbols instead of atomic numbers, and numpy arrays anywhere coordinates are expected. Supplying bonds lets the backend skip its own bond inference, which matters for .xyz input where connectivity is otherwise guessed from interatomic distances.

Chemistry interop

The core client has one dependency, httpx. Conversions are optional extras:

pip install 'reactionstudio[ase]'      # ASE
pip install 'reactionstudio[rdkit]'    # RDKit
pip install 'reactionstudio[all]'
atoms = result.to_ase()                # Atoms
images = path.to_ase()                 # list[Atoms], write with ase.io.write
frames = conformers.to_ase()           # list[Atoms], one per conformer

Long jobs

wait() is the common case. For anything long, drive the loop yourself:

job = client.transition_path(reactant, product, force_field="gfn2-xtb")
print("submitted", job.run_id)

try:
    path = job.wait(timeout=3600, on_progress=lambda s: print(s.status, s.progress))
except rs.RunTimeoutError:
    pass    # the run continues server-side

Or hand it off to a thread and carry on:

future = job.wait_async()        # concurrent.futures.Future
...
result = future.result()         # blocks only when you actually need it

Submitting a batch? Wait on them together — the backend runs them concurrently, so waiting one at a time just wastes wall-clock:

jobs = [client.generate_conformers(s, force_field="gfn2-xtb") for s in smiles]
results = rs.wait_all(jobs)                          # submission order
results = rs.wait_all(jobs, raise_on_failure=False)  # exceptions in place of results

A run_id is all you need to pick a job back up in another process. wait() returns immediately for a run that has already finished:

job = client.job("6f2a...")
result = job.wait()

Downloads

Jobs produce files alongside their structured results:

job.download("out/")                          # server picks the filename
job.download("conformers.zip")                # or specify it
job.download("in.mol", artifact_type="input_molecule")

artifact_type defaults to the experiment's main output — the optimised .mol, the conformer .zip, or the transition-path .xyz. Inputs are kept too, under input_molecule, reactant_input and product_input.

Tokens

Each run costs tokens, and submitting without enough raises before any compute starts:

print(client.token_balance())

try:
    job = client.transition_path(r, p, force_field="gfn2-xtb")
except rs.InsufficientTokensError as exc:
    print(f"needs {exc.required_tokens}, have {exc.current_balance}")

Force fields

for ff in client.force_fields(available_only=True):
    print(ff.id, ff.supports_transition_path)

force_field is required on every submission and has no default — picking one silently would be a good way to run a batch at the wrong level of theory. Not every method supports transition paths.

Errors

All of these subclass rs.ReactionStudioError.

Exception Meaning
AuthenticationError key missing, revoked, or expired
InsufficientTokensError not enough tokens; carries the numbers
NotFoundError no such run, or it isn't yours
RunFailedError the computation failed; carries the backend's message
RunTimeoutError wait() gave up; the run continues
APIError unexpected HTTP response
MissingDependencyError an extra is needed, e.g. [rdkit]

Reads are retried on transient failures. Submissions are never retried — the API has no idempotency key, so a retry could create a second run and spend a second lot of tokens.

Conventions

Energies are kJ/mol, coordinates Angström. Argument names match the HTTP API, so anything in the API docs maps onto a keyword here, and numeric defaults match the web app's, so a script and the UI give the same answer for the same input.

Development

pip install -e '.[test,all]'
pytest

Licence

Apache 2.0

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

reactionstudio-0.1.0.tar.gz (39.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

reactionstudio-0.1.0-py3-none-any.whl (32.7 kB view details)

Uploaded Python 3

File details

Details for the file reactionstudio-0.1.0.tar.gz.

File metadata

  • Download URL: reactionstudio-0.1.0.tar.gz
  • Upload date:
  • Size: 39.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.4

File hashes

Hashes for reactionstudio-0.1.0.tar.gz
Algorithm Hash digest
SHA256 fb31acc4decbb9193aad48f8f194787b08db2e1e0d50228ff53717593309bdde
MD5 556ee5e77c718abe9cb565ecbd30f122
BLAKE2b-256 cf4856cef0af411f065df9ef8f026766677b70f7dd8394357fba04f0c8899b3f

See more details on using hashes here.

File details

Details for the file reactionstudio-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: reactionstudio-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 32.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.4

File hashes

Hashes for reactionstudio-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 02f74afc06684b627f8395b366189661442b543a6041a7aa15cf34bc7db8646b
MD5 9230da76add2fb1f67d8dce3e8a0c4b1
BLAKE2b-256 9feb462cd9e5addb85d88021b308911ffda8e0e5f27ac5c3fec393093d7d5fc2

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page