Skip to content

Python API

Autogenerated from the xpict package with mkdocstrings.

Public surface

xpict

xpict — molecule depiction.

Two first-class APIs (same paint as JS / Rust):

Single molecule — mol / render / to_svg::

from xpict import mol, render, to_svg

benzene = mol("c1ccccc1")
rendered = render(benzene, {"color": "#0b6e4f"})
svg = to_svg(rendered.scene)

Declarative document — nested DepictSpec via Rust two-pass depict::

from xpict import depict, to_svg

rows = depict({"type": "mol", "smiles": "CCO"})
svg = to_svg(rows[0].scene)

MolSpec module-attribute

MolSpec = MolNode

__version__ module-attribute

__version__ = '0.3.0'

Mol dataclass

Mol(source: str, frame_molblock: str | None = None)

Input molecule — SMILES / CXSMILES / molfile plus optional align frame.

ensure_frame

ensure_frame() -> str

Materialize (and cache) a coord-bearing molblock for align_to.

Source code in python/xpict/client.py
def ensure_frame(self) -> str:
    """Materialize (and cache) a coord-bearing molblock for ``align_to``."""
    if not self.frame_molblock:
        _mol_in, pose, _meta = _layout_with_rdkit(self.source, template=None, id=None)
        del _mol_in
        self.frame_molblock = pose
    return self.frame_molblock

Rendered dataclass

Rendered(
    width: float,
    height: float,
    scene: Scene,
    molecule: dict[str, Any],
    source: str,
    frame_molblock: str,
    coords: list[SvgAtom],
    svg_coords: list[SvgAtom],
    bonds: list[SvgBond],
    mol: Mol | None = None,
)

Painted depiction — editable scene plus alignment frame.

frame

frame() -> str

Pose molblock for align_to.

Source code in python/xpict/client.py
def frame(self) -> str:
    """Pose molblock for ``align_to``."""
    return self.frame_molblock

MolRenderOptions dataclass

MolRenderOptions(
    id: str | None = None,
    color: str | None = None,
    atom_shade: list[float] | None = None,
    bond_shade: list[float] | None = None,
    mark_atoms: list[int] | None = None,
    mark_bonds: list[tuple[int, int]] | None = None,
    star_labels: list[str | None] | None = None,
    weight: float | None = None,
    scale: float | None = None,
    align_to: Mol | Rendered | None = None,
    atom_map: list[tuple[int, int]] | None = None,
)

Render options — parity with JS / Rust MolRenderOptions.

Pict

Pict(
    backend: str | None = None,
    *,
    format: OutputFormat = "svg",
)

Configured depiction engine.

Backend and output options are runtime config — not part of PictSpec JSON. Reaction / network diagrams render via the live Rust reaction_scheme path.

Source code in python/xpict/api.py
def __init__(
    self,
    backend: str | None = None,
    *,
    format: OutputFormat = "svg",
) -> None:
    self.backend = _resolve_backend_name(backend)
    self.format: OutputFormat = format

layout

layout(
    spec: PictSpec | LegacyPictSpec | dict[str, Any],
) -> list[MoleculeLayout]

Lay out molecules for the legacy Pict/draw path (internal helper).

Source code in python/xpict/api.py
def layout(
    self, spec: PictSpec | LegacyPictSpec | dict[str, Any]
) -> list[MoleculeLayout]:
    """Lay out molecules for the legacy Pict/draw path (internal helper)."""
    doc = _to_legacy(spec)
    backend = get_backend(self.backend)
    layouts = align_layouts(
        [backend.layout(m) for m in doc.molecules],
        enabled=doc.diagram.align,
        specs=doc.molecules,
    )
    return layouts

DepictSpec

Bases: DepictSpec

Live document root — generated wire model + host mols() helper.

mols

mols() -> list[MolNode]

Flatten mol nodes in document order (skips edge children).

Source code in python/xpict/contracts/__init__.py
def mols(self) -> list[MolNode]:
    """Flatten mol nodes in document order (skips edge children)."""
    root = self.root
    if isinstance(root, MolNode):
        return [root]
    if isinstance(root, ReactionSchemeNode):
        return [c for c in root.children if isinstance(c, MolNode)]
    return [c for c in root.children if isinstance(c, MolNode)]

Scene

Bases: StrictModel

Full drawable document before SVG/HTML serialization.

PictBackendWarning

Bases: UserWarning

Raised when a layout backend ignores or only partially supports an option.

mol

mol(smiles_or_molfile: str) -> Mol

Construct a Mol (JS / Rust xpict.mol).

Source code in python/xpict/client.py
def mol(smiles_or_molfile: str) -> Mol:
    """Construct a ``Mol`` (JS / Rust ``xpict.mol``)."""
    text = smiles_or_molfile.strip()
    if not text:
        raise ValueError("mol() requires a non-empty SMILES or molfile")
    return Mol(source=text)

to_svg

to_svg(scene: Scene | dict[str, Any]) -> str

Scene JSON / Scene → SVG string (JS xpict.toSvg).

Source code in python/xpict/client.py
def to_svg(scene: Scene | dict[str, Any]) -> str:
    """Scene JSON / ``Scene`` → SVG string (JS ``xpict.toSvg``)."""
    if isinstance(scene, dict):
        scene = Scene.model_validate(scene)
    return _scene_to_svg(scene)

depict

depict(
    spec: DepictSpec | dict[str, Any] | str,
) -> list[Rendered]

Declarative document → list[Rendered] via core plan/paint + RDKit edge.

reaction_scheme roots are composed into one Rendered (ELK layout + edge overlays in Rust). mol / group stay one row per molecule.

Source code in python/xpict/depict_spec.py
def depict(spec: DepictSpec | dict[str, Any] | str) -> list[Rendered]:
    """Declarative document → ``list[Rendered]`` via core plan/paint + RDKit edge.

    ``reaction_scheme`` roots are composed into **one** ``Rendered`` (ELK layout
    + edge overlays in Rust). ``mol`` / ``group`` stay one row per molecule.
    """
    doc = _as_depict_spec(spec)
    plan = plan_edge(doc)
    if plan is None:
        return []
    edge, frames = process_edge_plan_with_frames(plan)
    painted = render_doc(doc, edge)
    by_id = _node_by_id(doc)

    if _is_scheme(doc):
        composed = compose_scheme(doc, painted)
        # Prefer first mol as source identity for the composed document.
        first = painted[0] if painted else {"id": "scheme", "molecule": {}}
        return [
            _rendered_from_row(
                {
                    "id": str(first.get("id") or "scheme"),
                    "molecule": first.get("molecule") or {},
                    "scene": composed,
                },
                by_id=by_id,
                frames=frames,
                source_fallback="reaction_scheme",
            )
        ]

    out: list[Rendered] = []
    for row in painted:
        out.append(_rendered_from_row(row, by_id=by_id, frames=frames))
    return out

Single molecule

xpict.client

Single-molecule client — parity with JS xpict.mol / render / toSvg.

All three languages ship the same surface:

mol(source) → render(mol, opts?) → Rendered → to_svg(scene)

align_to accepts a prior Mol or Rendered (pose molblock under the hood). Layout + MCS align use RDKit at the language edge; paint is xpict._native.depict_molecule.

Mol dataclass

Mol(source: str, frame_molblock: str | None = None)

Input molecule — SMILES / CXSMILES / molfile plus optional align frame.

source instance-attribute

source: str

frame_molblock class-attribute instance-attribute

frame_molblock: str | None = None

render

render(opts: MolRenderOptions | None = None) -> Rendered
Source code in python/xpict/client.py
def render(self, opts: MolRenderOptions | None = None) -> Rendered:
    return render(self, opts)

ensure_frame

ensure_frame() -> str

Materialize (and cache) a coord-bearing molblock for align_to.

Source code in python/xpict/client.py
def ensure_frame(self) -> str:
    """Materialize (and cache) a coord-bearing molblock for ``align_to``."""
    if not self.frame_molblock:
        _mol_in, pose, _meta = _layout_with_rdkit(self.source, template=None, id=None)
        del _mol_in
        self.frame_molblock = pose
    return self.frame_molblock

Rendered dataclass

Rendered(
    width: float,
    height: float,
    scene: Scene,
    molecule: dict[str, Any],
    source: str,
    frame_molblock: str,
    coords: list[SvgAtom],
    svg_coords: list[SvgAtom],
    bonds: list[SvgBond],
    mol: Mol | None = None,
)

Painted depiction — editable scene plus alignment frame.

width instance-attribute

width: float

height instance-attribute

height: float

scene instance-attribute

scene: Scene

molecule instance-attribute

molecule: dict[str, Any]

source instance-attribute

source: str

frame_molblock instance-attribute

frame_molblock: str

coords instance-attribute

coords: list[SvgAtom]

svg_coords instance-attribute

svg_coords: list[SvgAtom]

bonds instance-attribute

bonds: list[SvgBond]

mol class-attribute instance-attribute

mol: Mol | None = None

to_svg

to_svg() -> str
Source code in python/xpict/client.py
def to_svg(self) -> str:
    return to_svg(self.scene)

frame

frame() -> str

Pose molblock for align_to.

Source code in python/xpict/client.py
def frame(self) -> str:
    """Pose molblock for ``align_to``."""
    return self.frame_molblock

MolRenderOptions dataclass

MolRenderOptions(
    id: str | None = None,
    color: str | None = None,
    atom_shade: list[float] | None = None,
    bond_shade: list[float] | None = None,
    mark_atoms: list[int] | None = None,
    mark_bonds: list[tuple[int, int]] | None = None,
    star_labels: list[str | None] | None = None,
    weight: float | None = None,
    scale: float | None = None,
    align_to: Mol | Rendered | None = None,
    atom_map: list[tuple[int, int]] | None = None,
)

Render options — parity with JS / Rust MolRenderOptions.

id class-attribute instance-attribute

id: str | None = None

color class-attribute instance-attribute

color: str | None = None

atom_shade class-attribute instance-attribute

atom_shade: list[float] | None = None

bond_shade class-attribute instance-attribute

bond_shade: list[float] | None = None

mark_atoms class-attribute instance-attribute

mark_atoms: list[int] | None = None

mark_bonds class-attribute instance-attribute

mark_bonds: list[tuple[int, int]] | None = None

star_labels class-attribute instance-attribute

star_labels: list[str | None] | None = None

weight class-attribute instance-attribute

weight: float | None = None

scale class-attribute instance-attribute

scale: float | None = None

align_to class-attribute instance-attribute

align_to: Mol | Rendered | None = None

atom_map class-attribute instance-attribute

atom_map: list[tuple[int, int]] | None = None

mol

mol(smiles_or_molfile: str) -> Mol

Construct a Mol (JS / Rust xpict.mol).

Source code in python/xpict/client.py
def mol(smiles_or_molfile: str) -> Mol:
    """Construct a ``Mol`` (JS / Rust ``xpict.mol``)."""
    text = smiles_or_molfile.strip()
    if not text:
        raise ValueError("mol() requires a non-empty SMILES or molfile")
    return Mol(source=text)

render

render(
    input: Mol | str,
    opts: MolRenderOptions | dict[str, Any] | None = None,
) -> Rendered

Layout → native depict_molecule → Rendered (JS xpict.render).

Source code in python/xpict/client.py
def render(
    input: Mol | str,
    opts: MolRenderOptions | dict[str, Any] | None = None,
) -> Rendered:
    """Layout → native ``depict_molecule`` → ``Rendered`` (JS ``xpict.render``)."""
    m = mol(input) if isinstance(input, str) else input
    options = _coerce_opts(opts)

    template: str | None = None
    if options.align_to is not None:
        template = _ensure_frame(options.align_to)
    elif options.atom_map is not None:
        raise ValueError("atom_map requires align_to")

    laid, pose_mb, _meta = _layout_with_rdkit(
        m.source,
        template=template,
        id=options.id,
        atom_map=options.atom_map,
    )
    if m.frame_molblock is None and template is None:
        m.frame_molblock = pose_mb

    molecule = _apply_opts(laid, options, m.source)
    from xpict import _native

    scene = Scene.model_validate(
        json.loads(_native.depict_molecule(json.dumps(molecule)))
    )
    coords = _to_coord_list(molecule["atoms"])
    bonds = [
        SvgBond(
            index=int(b["index"]),
            begin=int(b["begin"]),
            end=int(b["end"]),
            order=float(b["order"]),
            stereo=b.get("stereo"),
        )
        for b in molecule["bonds"]
    ]
    return Rendered(
        width=float(scene.width),
        height=float(scene.height),
        scene=scene,
        molecule=molecule,
        source=m.source,
        frame_molblock=pose_mb,
        coords=coords,
        svg_coords=list(coords),
        bonds=bonds,
        mol=m,
    )

to_svg

to_svg(scene: Scene | dict[str, Any]) -> str

Scene JSON / Scene → SVG string (JS xpict.toSvg).

Source code in python/xpict/client.py
def to_svg(scene: Scene | dict[str, Any]) -> str:
    """Scene JSON / ``Scene`` → SVG string (JS ``xpict.toSvg``)."""
    if isinstance(scene, dict):
        scene = Scene.model_validate(scene)
    return _scene_to_svg(scene)

Contracts (document)

xpict.contracts.depict

DepictSpec — live document ABI from xpict-core (schemars).

DepictSpec

Bases: RootModel[DepictSpecRoot]

Declarative document (mol, group, or reaction_scheme root).

model_dump

model_dump(*args, **kwargs)
Source code in python/xpict/contracts/depict.py
def model_dump(self, *args, **kwargs):
    kwargs.setdefault('exclude_none', True)
    return super().model_dump(*args, **kwargs)

model_dump_json

model_dump_json(*args, **kwargs)
Source code in python/xpict/contracts/depict.py
def model_dump_json(self, *args, **kwargs):
    kwargs.setdefault('exclude_none', True)
    return super().model_dump_json(*args, **kwargs)

MolNode

Bases: StrictModel

Mol node — [MolOpts] fields + non-cascading identity / scores / align.

type class-attribute instance-attribute

type: Literal['mol'] = 'mol'

align_to class-attribute instance-attribute

align_to: Annotated[
    AlignTo | None,
    Field(
        description='Template id string, or `{ "ref", "atom_map"?, "min_atoms"? }`.'
    ),
] = None

color class-attribute instance-attribute

color: str | None = None

cxsmiles class-attribute instance-attribute

cxsmiles: str | None = None

halo class-attribute instance-attribute

halo: bool | None = None

id class-attribute instance-attribute

id: str | None = None

label class-attribute instance-attribute

label: Annotated[
    Label | None,
    Field(
        description="Caption: [`Label`] (string id, list, or `{id, pos?}` — text-node refs)."
    ),
] = None

molfile class-attribute instance-attribute

molfile: str | None = None

opts class-attribute instance-attribute

opts: Annotated[
    Opts | None,
    Field(
        description="Cascade patches for this node (list or singleton)."
    ),
] = None

scale class-attribute instance-attribute

scale: float | None = None

shade class-attribute instance-attribute

shade: Annotated[
    ShadeSpec | None,
    Field(
        description="Shade **scores** (+ legacy window); window also cascades via [`Opts`]."
    ),
] = None

smiles class-attribute instance-attribute

smiles: str | None = None

star_labels class-attribute instance-attribute

star_labels: list[str | None] | None = None

weight class-attribute instance-attribute

weight: float | None = None

GroupNode

Bases: StrictModel

type class-attribute instance-attribute

type: Literal['group'] = 'group'

align class-attribute instance-attribute

align: bool = Field(
    default=False,
    description="When true, later children align onto the first (or each `align_to`).",
)

children class-attribute instance-attribute

children: list[Node] = Field(
    default_factory=list,
    description="Child **nodes** — mol | text (no edges).",
)

color class-attribute instance-attribute

color: str | None = None

id class-attribute instance-attribute

id: str | None = None

opts class-attribute instance-attribute

opts: Annotated[
    Opts | None,
    Field(
        description="Group-level cascade bag (list container for child inheritance)."
    ),
] = None

scale class-attribute instance-attribute

scale: float | None = None

Engine

xpict.api

Public Pict / render API.

Pict

Pict(
    backend: str | None = None,
    *,
    format: OutputFormat = "svg",
)

Configured depiction engine.

Backend and output options are runtime config — not part of PictSpec JSON. Reaction / network diagrams render via the live Rust reaction_scheme path.

Source code in python/xpict/api.py
def __init__(
    self,
    backend: str | None = None,
    *,
    format: OutputFormat = "svg",
) -> None:
    self.backend = _resolve_backend_name(backend)
    self.format: OutputFormat = format

layout

layout(
    spec: PictSpec | LegacyPictSpec | dict[str, Any],
) -> list[MoleculeLayout]

Lay out molecules for the legacy Pict/draw path (internal helper).

Source code in python/xpict/api.py
def layout(
    self, spec: PictSpec | LegacyPictSpec | dict[str, Any]
) -> list[MoleculeLayout]:
    """Lay out molecules for the legacy Pict/draw path (internal helper)."""
    doc = _to_legacy(spec)
    backend = get_backend(self.backend)
    layouts = align_layouts(
        [backend.layout(m) for m in doc.molecules],
        enabled=doc.diagram.align,
        specs=doc.molecules,
    )
    return layouts

render

render(
    spec: PictSpec | LegacyPictSpec | dict[str, Any],
    *,
    backend: str | None = None,
    format: OutputFormat = "svg",
) -> str

Shorthand for Pict(backend=...).render(spec).

Source code in python/xpict/api.py
def render(
    spec: PictSpec | LegacyPictSpec | dict[str, Any],
    *,
    backend: str | None = None,
    format: OutputFormat = "svg",
) -> str:
    """Shorthand for ``Pict(backend=...).render(spec)``."""
    return Pict(backend=backend, format=format).render(spec)