Skip to content

Quick Start

Python

"""RENKIN Python quickstart. Runs as part of CI so this example can never
silently drift from the real API (see .github/workflows/ci.yml)."""

import json

import renkin

result = json.loads(
    renkin.find_routes(
        target="CC(=O)Oc1ccccc1C(=O)O",  # Aspirin
        depth=5,
        max_routes=3,
    )
)

print(f"Routes found: {result['routes_found']}")
for route in result["routes"]:
    print(f"Route (depth {route['depth']}):")
    for step in route["steps"]:
        print(f"  {step['target']} -> {' + '.join(step['precursors'])}")
        print(f"  via {step['rule']}")

The included example is executed in CI. find_routes returns a JSON string; call json.loads() before accessing fields. Route counts can change with the stock and rules. See the Python API for options and output.

Custom Building Blocks

You can supply your own building block library:

import renkin, json

my_stock = [
    "CC(=O)O",       # acetic acid
    "Oc1ccccc1",     # phenol
    "c1ccccc1",      # benzene
    "Brc1ccccc1",    # bromobenzene
    "OB(O)c1ccccc1", # phenylboronic acid
]

result = json.loads(renkin.find_routes(
    target="c1ccc(-c2ccccc2)cc1",  # biphenyl
    building_blocks=my_stock,
    depth=3,
))
print(f"Routes found: {result['routes_found']}")

Rust

//! RENKIN Rust quickstart. Compiled and run as part of CI (see
//! .github/workflows/ci.yml) so this example can never silently drift from
//! the real `find_routes` API.

use renkin::chem_env::{ChemEnv, default_rules};
use renkin::search::{SearchConfig, find_routes};

fn main() -> anyhow::Result<()> {
    let env = ChemEnv::load("data/building_blocks.smi")?;
    let rules = default_rules();
    let config = SearchConfig {
        max_depth: 5,
        max_routes: 3,
        ..Default::default()
    };

    let (routes, _stats) = find_routes("CC(=O)Oc1ccccc1C(=O)O", &env, &rules, &config)?;
    println!("Routes found: {}", routes.len());
    for route in &routes {
        println!("Route (depth {}):", route.depth);
        for step in &route.steps {
            println!("  {} -> {}", step.target, step.precursors.join(" + "));
            println!("  via {}", step.rule);
        }
    }
    Ok(())
}

find_routes returns Result<(Vec<Route>, SearchStats)> — destructure the tuple, and note route.depth/route.steps are plain fields, not methods. See Rust API for the full signature and SearchConfig fields.

CLI Benchmark

# Run retrosynthesis on a list of targets
renkin-bench \
    --input targets.smi \
    --building-blocks data/building_blocks.smi \
    --depth 3 \
    --beam-width 50 \
    > results.json

The input file should be a SMILES file (one SMILES per line, optional name after whitespace).

SMILES File Format

Building blocks and target files use the standard .smi format:

CC(=O)O         acetic_acid
c1ccccc1        benzene
# Comments start with #
Brc1ccccc1      bromobenzene