Skip to content

deeporigin.drug_discovery.enumerator

Enumerator -- generate analogue libraries from a parent ligand (served, sync-only).

Backed by the served platform tool deeporigin.enumerator (a direct execution). One :class:Enumerator is configured with a single job_type and executed with a blocking :meth:run, which returns a :class:pandas.DataFrame.

The tool exposes four job_type values:

  • SCAFFOLD -- CReM matched-molecular-pair (MMP) enumeration that grows a fragment at a single attachment atom (one replace_ix index).
  • ANALOGUE -- CReM MMP enumeration that swaps a connected fragment (one or more replace_ix indices forming a connected substructure).
  • AVAILABLE_REACTIONS -- discovers named-reaction sites on the parent and returns their atom indices. Writes no CSV; the DataFrame is built from the inline result list.
  • REACTION -- enumerates products against the Enamine fragment library at explicit reaction_sites. Each site must match a hit returned by a prior AVAILABLE_REACTIONS run.

SCAFFOLD and ANALOGUE are the two MMP flavors.

Usage::

from deeporigin.drug_discovery import Enumerator, Ligand

parent = Ligand.from_smiles("Brc1ccccc1")

# MMP: grow a fragment at atom 0
df = Enumerator(ligand=parent, job_type="SCAFFOLD", replace_ix=0).run()

# Discover reaction sites, then enumerate against them
sites = Enumerator(ligand=parent, job_type="AVAILABLE_REACTIONS").run()
df = Enumerator(
    ligand=parent,
    job_type="REACTION",
    reaction_sites=[
        {"reaction_id": "suzuki", "reactant_role": "core_halide", "atom_indices": [0, 1]},
    ],
).run()

Attributes

Classes

Enumerator

Bases: Execution, SyncExecutableMixin

Enumerate analogues of a parent ligand via the served enumerator tool.

Configure the instance with a parent :class:~deeporigin.drug_discovery.structures.ligand.Ligand, a job_type, and its mode-specific parameters, then call :meth:run to execute synchronously and receive a :class:pandas.DataFrame.

For SCAFFOLD / ANALOGUE / REACTION the DataFrame is parsed from the tool's descriptor-enriched results.csv. For AVAILABLE_REACTIONS the DataFrame is built from the inline available_reactions list (no CSV is written).

Attributes:

Name Type Description
ligand Ligand

Parent ligand whose smiles (and optional id) is enumerated.

job_type str

One of SCAFFOLD, ANALOGUE, AVAILABLE_REACTIONS, REACTION.

replace_ix list[int] | None

RDKit atom indices marking the MMP enumeration site (MMP modes).

reaction_sites list[dict[str, Any]] | None

Named-reaction sites for REACTION enumeration.

radius int

CReM environment radius (MMP modes).

max_fragment_size int

Maximum heavy atoms in the added/replacement fragment (MMP modes).

cap_hit bool | None

Whether the last run hit the platform enumeration cap (MMP/REACTION), or None before a run or for AVAILABLE_REACTIONS.

Attributes

USER_LOG_COLUMNS class-attribute
USER_LOG_COLUMNS: list[str] = [
    "log_level",
    "tool_key",
    "timestamp",
    "message",
]
cap_hit property
cap_hit: bool | None

Whether the last MMP/REACTION run hit the platform enumeration cap.

None before :meth:run, or for AVAILABLE_REACTIONS (which has no cap).

client instance-attribute
client: DeepOriginClient = client
cost property
cost: float | None

Actual cost in dollars, set after execution completes.

This property cannot be set manually.

dto property
dto: dict[str, Any] | None

Last tools execution DTO from the platform, if any.

estimate property
estimate: float | None

Cost estimate in dollars, populated when the platform returns a quotation.

Set after run(quote=True), start(quote=True), or any call with approve_amount=0. None until a quotation result is received. This property cannot be set manually.

id property
id: str | None

Platform execution ID when set (read-only).

job_type property
job_type: str

Enumeration mode for this run (read-only).

ligand property
ligand: Ligand

Parent ligand targeted by this enumeration (read-only).

max_fragment_size property
max_fragment_size: int

Maximum heavy atoms in the added/replacement fragment (MMP modes, read-only).

name property writable
name: str | None

Optional user-defined label for this execution.

May be set or changed only while id is unset. After an execution ID exists, name is read-only.

radius property
radius: int

CReM environment radius used for MMP modes (read-only).

reaction_sites property
reaction_sites: list[dict[str, Any]] | None

Named-reaction sites for REACTION enumeration, if any (read-only).

replace_ix property
replace_ix: list[int] | None

RDKit atom indices marking the MMP enumeration site, if any (read-only).

runtime property
runtime: float | None

Seconds from DTO startedAt to completedAt or current UTC time.

Uses :attr:dto (same shape as client.executions.get). When completedAt is present, it is the end time; otherwise the end time is datetime.now(timezone.utc). Returns None if there is no DTO or startedAt is missing or empty.

tool_key class-attribute instance-attribute
tool_key: str = TOOL_KEYS_AND_VERSIONS["enumerator"][
    "tool_key"
]
tool_version instance-attribute
tool_version = tool_version

Methods:

confirm
confirm() -> None

Confirm a quoted tools execution on the platform.

Requires :attr:id and status equal to "Quoted". Uses :meth:~deeporigin.platform.executions.Executions.confirm with :data:~deeporigin.utils.constants.TOOL_EXECUTION_POST_TIMEOUT_SECONDS (10 minutes) and retry=False, then applies the returned DTO via :meth:update_from_dto so status, :attr:cost, and :attr:dto reflect the platform response. For direct (blocking) tools the response is typically terminal (Completed); for async tools it may be Created or Running — call :meth:sync until the job finishes.

Raises:

Type Description
ValueError

If there is no platform execution id or status is not "Quoted".

duplicate
duplicate(
    *, client: DeepOriginClient | None = None
) -> Self

Create a fresh copy with the same configuration but no execution state.

Useful after from_id() to re-run the same calculation. The returned instance has no id, status, estimate, or cost — it is ready for run() / start().

Parameters:

Name Type Description Default
client DeepOriginClient | None

Optional API client for the new instance. Falls back to the current instance's client.

None

Returns:

Type Description
Self

A new instance sharing the same domain-specific configuration.

from_dto classmethod
from_dto(
    dto: dict[str, Any],
    *,
    client: DeepOriginClient | None = None
) -> Self

Construct an Enumerator from a tools execution DTO.

Rehydrates the parent ligand and mode-specific inputs from userInputs (falling back to inputs for older payloads).

Parameters:

Name Type Description Default
dto dict[str, Any]

Execution payload (same shape as client.executions.get).

required
client DeepOriginClient | None

Optional API client. Uses the default if not provided.

None

Returns:

Type Description
Self

An Enumerator with id, pricing fields, and domain inputs set.

Raises:

Type Description
ValueError

If the stored inputs are missing a ligand SMILES or carry a missing/unknown job_type.

from_id classmethod
from_id(
    id: str, *, client: DeepOriginClient | None = None
) -> Self

Construct an instance from an existing platform execution ID.

Fetches the execution DTO via client.executions.get and delegates to :meth:from_dto. Concrete subclasses override :meth:from_dto to attach domain state from userInputs.

Parameters:

Name Type Description Default
id str

Platform execution ID.

required
client DeepOriginClient | None

Optional API client. Uses the default if not provided.

None

Returns:

Type Description
Self

A partially-hydrated instance with common fields populated.

Raises:

Type Description
NotImplementedError

If cls has no tool_key (bare :class:Execution).

from_last_run classmethod
from_last_run(
    *, client: DeepOriginClient | None = None
) -> Self

Construct an instance from the most recently created execution of this tool.

Calls client.executions.list with tool_key, order set to :data:~deeporigin.utils.constants.EXECUTION_LIST_ORDER_CREATED_DESC, and page_size=1, then delegates to :meth:from_dto. Concrete subclasses inherit this method; domain state is restored via their from_dto overrides.

Parameters:

Name Type Description Default
client DeepOriginClient | None

Optional API client. Uses the default if not provided.

None

Returns:

Type Description
Self

A partially-hydrated instance for the newest execution by

Self

createdAt.

Raises:

Type Description
NotImplementedError

If cls has no tool_key (bare :class:Execution).

ValueError

If no executions exist for this tool type.

get_results
get_results(dto: dict[str, Any] | None = None) -> DataFrame

Return this execution's results as a :class:pandas.DataFrame.

Reads jobOutputs from dto (or fetches it via client.executions.get when omitted, e.g. after :meth:~deeporigin.drug_discovery.execution.Execution.from_id).

Parameters:

Name Type Description Default
dto dict[str, Any] | None

Optional execution payload from executions.create / executions.get. Passing it avoids an extra GET.

None

Returns:

Type Description
DataFrame

A DataFrame of enumeration products (MMP / REACTION) or discovered

DataFrame

reaction sites (AVAILABLE_REACTIONS).

Raises:

Type Description
ValueError

If :attr:id is unset.

DeepOriginException

If no results could be parsed.

get_user_logs
get_user_logs(
    *,
    limit: int | None = None,
    offset: int | None = None,
    select: list[str] | None = None,
    with_total_count: bool = False
) -> DataFrame | None

Search data-platform user_logs rows for this execution.

Uses :meth:deeporigin.platform.user_logs.UserLogs.search with this execution's id (tools executionId), stored as execution_id on user_logs rows — the same string passed to :meth:get_results as compute_job_id.

When no execution id is assigned yet, returns None without calling the API.

Parameters:

Name Type Description Default
limit int | None

Max rows to return (forwarded to UserLogs.search).

None
offset int | None

Skip offset (forwarded).

None
select list[str] | None

Columns to select (forwarded).

None
with_total_count bool

Request total count from the server (forwarded).

False

Returns:

Type Description
DataFrame | None

A DataFrame with columns log_level, tool_key, timestamp,

DataFrame | None

and message. tool_key omits the deeporigin. prefix;

DataFrame | None

timestamp is a compact humanized relative time. Returns None

DataFrame | None

if this instance has no execution id yet or the client has no

DataFrame | None

user_logs API.

list classmethod
list(
    *,
    client: DeepOriginClient | None = None,
    status: list[str] | None = None
) -> list[Self]

List executions of this tool type from the platform.

Calls client.executions.list(fetch_all_pages=True, tool_key=...), then builds instances via :meth:from_dto. Optional status filters hydrated instances by instance.status.

Parameters:

Name Type Description Default
client DeepOriginClient | None

Optional API client. Uses the default if not provided.

None
status list[str] | None

Optional list of statuses to keep (membership test).

None

Returns:

Type Description
list[Self]

Instances of this class, one per matching execution.

Raises:

Type Description
NotImplementedError

If cls has no tool_key (bare :class:Execution).

run
run() -> DataFrame

Execute the enumeration synchronously (blocking) and return a DataFrame.

Submits one synchronous execution (sync=True), applies the response via :meth:~deeporigin.drug_discovery.execution.Execution.update_from_dto, and returns results via :meth:get_results.

Returns:

Name Type Description
A DataFrame

class:pandas.DataFrame. For SCAFFOLD / ANALOGUE /

DataFrame

REACTION it is the descriptor-enriched results.csv; for

DataFrame

AVAILABLE_REACTIONS it has columns

DataFrame

data:~deeporigin.utils.constants.ENUMERATOR_AVAILABLE_REACTIONS_COLUMNS.

Raises:

Type Description
DeepOriginException

If the execution did not complete successfully or no results could be parsed.

sync
sync() -> None

Fetch the latest tools execution from the platform and refresh fields.

Calls client.executions.get for :attr:id and applies the response with :meth:update_from_dto. Use when the job may have changed outside this process (for example after submission from the web UI), to poll lifecycle state, or to refresh an instance built from an older DTO. Available on sync-only and async execution types alike.

If executions.get returns a falsy value, this instance is left unchanged.

Raises:

Type Description
ValueError

If this instance has no execution id yet.

NotImplementedError

If type(self).tool_key is empty (bare :class:Execution).

ValueError

If the returned DTO tool.key does not match this class (see :meth:update_from_dto).

update_from_dto
update_from_dto(dto: dict[str, Any]) -> None

Apply tools execution fields from dto onto this instance.

Updates id, pricing, lifecycle fields, and _dto the same way as :meth:from_dto for a newly created instance. Use after a live executions.create / sync() response to refresh state without constructing a new object (domain inputs on self are unchanged).

Parameters:

Name Type Description Default
dto dict[str, Any]

Execution payload (same shape as client.executions.get).

required

Raises:

Type Description
NotImplementedError

If type(self) has no tool_key (bare :class:Execution).

ValueError

If the DTO tool.key does not match tool_key.

wait
wait(
    *,
    poll_interval: float = 5.0,
    timeout: float | None = None
) -> dict[str, Any] | None

Block until this execution reaches a terminal state.

Parameters:

Name Type Description Default
poll_interval float

Seconds to sleep between polling cycles.

5.0
timeout float | None

Maximum total seconds to wait. If None, waits indefinitely.

None

Returns:

Type Description
dict[str, Any] | None

The latest execution DTO, or None if the platform returned no DTO.

Raises:

Type Description
ValueError

If this instance has no execution id yet.

TimeoutError

If timeout elapses before the execution terminates.

Functions: