deeporigin.drug_discovery.secondary_pharma¶
SecondaryPharmacology drives platform tool deeporigin.secondary-pharma. It
scores ligands against a baked kinase panel, using either a served ligand-ML
path (method="ligand-ml", use run()) or an async docking workflow
(method="docking", use start()). See the
tool guide for the full explanation of why
these are separate execution modes on one class.
SecondaryPharmacology -- score ligands against a baked kinase panel.
Backed by the platform tool deeporigin.secondary-pharma, which supports two
mutually exclusive scoring methods selected at construction:
"ligand-ml"-- served, synchronous XGBoost booster scoring. Use :meth:run."docking"-- Argo workflow, asynchronous only. Use :meth:start(and :meth:watchin Jupyter).
The tool schema has no inputs.sync field (unlike deeporigin.docking), so
method alone determines execution modality -- there is no unified blocking/
non-blocking call across both paths. :meth:get_results always returns a
:class:pandas.DataFrame regardless of method (method-aware columns), but the
two paths load from different places: ligand-ml is served/sync, so results
come back in the same response's jobOutputs; docking is an async Argo
workflow, so results are only ever persisted to result-explorer (jobOutputs
on a polled execution is empty) -- same reason Docking.get_results() tries
result-explorer before jobOutputs. Use get_results()'s pose_score/
binding_energy columns for docking results -- pose visualization isn't
available yet (DDOS-7481).
Usage::
from deeporigin.drug_discovery import SecondaryPharmacology, Ligand
ligand = Ligand.from_smiles("CCO")
ml = SecondaryPharmacology(ligands=[ligand], method="ligand-ml")
df = ml.run()
dock = SecondaryPharmacology(ligands=[ligand], method="docking", effort=2)
dock.start()
dock.wait()
df = dock.get_results() # pose_score, binding_energy, etc.
Attributes¶
Classes¶
SecondaryPharmacology
¶
Bases: Execution, SyncExecutableMixin, AsyncExecutableMixin, NotebookWatchMixin
Score ligands against a baked secondary-pharmacology kinase panel.
Attributes:
| Name | Type | Description |
|---|---|---|
ligands |
list[Ligand]
|
Ligands to score. Empty only when :attr: |
method |
str
|
Scoring path for this instance -- |
uniprots |
list[str] | tuple[str, ...] | None
|
Panel accessions to restrict scoring to, or |
effort |
int
|
Docking effort level (1 = fastest, 5 = most thorough). Ignored on the ligand-ml path. |
batch_size |
int
|
Panel cells (ligand x target) packed per docking leaf -- a soft cap; a single target's cells are never split across leaves. Ignored on the ligand-ml path. |
self_test |
bool
|
When |
Attributes¶
USER_LOG_COLUMNS
class-attribute
¶
USER_LOG_COLUMNS: list[str] = [
"log_level",
"tool_key",
"timestamp",
"message",
]
batch_size
property
¶
batch_size: int
Panel cells packed per docking leaf (default 30). Read-only.
Ignored on the ligand-ml path.
cost
property
¶
cost: float | None
Actual cost in dollars, set after execution completes.
This property cannot be set manually.
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=-1. None until a quotation result is received.
This property cannot be set manually.
name
instance-attribute
¶
name = (
name
if name is not None
else _secondary_pharma_default_name(
method=self._method,
ligands=self._ligands,
uniprots=self._uniprots,
self_test=self._self_test,
)
)
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.
self_test
property
¶
self_test: bool
Whether this run scores the baked test ligand against the full panel.
tool_key
class-attribute
instance-attribute
¶
tool_key: str = TOOL_KEYS_AND_VERSIONS["secondary_pharma"][
"tool_key"
]
uniprots
property
writable
¶
uniprots: list[str] | tuple[str, ...] | None
Panel accessions this run is restricted to, or None for the whole panel.
A mutable list on a draft instance. After an execution id is set, a
tuple. None when unset or a rehydrated execution omitted the field.
Methods:¶
cancel
¶
cancel() -> None
Cancel a running or queued execution.
Raises:
| Type | Description |
|---|---|
ValueError
|
If the job has no execution ID. |
ValueError
|
If the job is not in a cancellable state. |
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
|
duplicate
¶
duplicate(
*, client: DeepOriginClient | None = None
) -> Self
Copy configuration into a new draft with a writable uniprots.
from_dto does not fetch the tool definition, so a rehydrated
instance has no allowlist. Fetch it here so the draft can assign
uniprots like a constructor-built instance.
from_dto
classmethod
¶
from_dto(
dto: dict[str, Any],
*,
client: DeepOriginClient | None = None
) -> Self
Construct a SecondaryPharmacology from a tools execution DTO.
Restores ligands, method, uniprots, effort, and self_test from
userInputs, and batch_size from the execution's top-level
batchSize field (or its metadata, for an older execution
record) -- like batch_size, batchSize is not a schema input,
so it doesn't live in userInputs. Does not fetch the live tool
definition, so a rehydrated instance's uniprots is read-only
until :meth:duplicate is called.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dto
|
dict[str, Any]
|
Execution payload (same shape as |
required |
client
|
DeepOriginClient | None
|
Optional API client. Uses the default if not provided. |
None
|
Returns:
| Type | Description |
|---|---|
Self
|
A |
Self
|
domain inputs set. |
from_id
classmethod
¶
from_id(
id: str,
*,
client: DeepOriginClient | None = None,
quiet: bool = True
) -> Self
Same as :meth:Execution.from_id, but quiet defaults to True.
Rebuilding ligands from stored inputs can emit chemistry
normalization warnings (naming the raw SMILES) -- not useful noise
when you're just reloading a run you already know about. Pass
quiet=False to see them.
from_last_run
classmethod
¶
from_last_run(
*,
client: DeepOriginClient | None = None,
quiet: bool = True
) -> Self
Same as :meth:Execution.from_last_run, but quiet defaults to True.
get_missing_pairs
¶
get_missing_pairs() -> list[tuple[Ligand, str]] | None
(ligand, uniprot) pairs with no docked pose, or None if complete.
Valid only when :attr:method is "docking".
get_panel
classmethod
¶
get_panel(
*,
full: bool = False,
tool_version: str = TOOL_KEYS_AND_VERSIONS[
"secondary_pharma"
]["tool_version"],
client: DeepOriginClient | None = None
) -> DataFrame
Return the current scoring panel, no ligand or instance required.
Both methods validate uniprots against this same panel today --
docking and ligand-ml are expected to grow independent, differently
sized catalogs later, which this method will need to account for then.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
full
|
bool
|
Return every member instead of just a preview. |
False
|
tool_version
|
str
|
Platform tool version to look up. Defaults to the
pinned major version in :data: |
TOOL_KEYS_AND_VERSIONS['secondary_pharma']['tool_version']
|
client
|
DeepOriginClient | None
|
Optional API client. Uses the default if not provided. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
A |
DataFrame
|
class: |
DataFrame
|
( |
get_results
¶
get_results(dto: dict[str, Any] | None = None) -> DataFrame
Return this execution's results as a :class:pandas.DataFrame.
Method-aware, and the two paths load from different places:
ligand-mlis served/sync, sojobOutputsis populated in the same response that completed the run -- read directly, like :meth:Admet.get_results <deeporigin.drug_discovery.admet.Admet.get_results>.dockingis an async Argo workflow with no synchronous response to embed results into, so it only ever persists rows to result-explorer;jobOutputson a polled execution is empty. Loaded via :func:_load_panel_pose_rows, mirroring :func:~deeporigin.drug_discovery.docking_common.load_docking_poses_from_execution's result-explorer-first,jobOutputs-fallback shape.
The docking-path DataFrame includes pose_score, binding_energy,
and file_path per pose. Every row also carries a method
column ("ligand-ml" or "docking").
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dto
|
dict[str, Any] | None
|
Optional execution payload ( |
None
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
A DataFrame of |
Raises:
| Type | Description |
|---|---|
ValueError
|
If :attr: |
DeepOriginException
|
If no rows could be loaded. |
get_undocked_ligands
¶
get_undocked_ligands() -> LigandSet | None
Ligands with zero docked poses, or None if none. Docking only.
A ligand with at least one docked pose won't appear here, even if
it's missing poses for other targets -- use :meth:get_missing_pairs
for that.
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 |
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 |
DataFrame | None
|
and |
DataFrame | None
|
|
DataFrame | None
|
if this instance has no execution id yet or the client has no |
DataFrame | None
|
|
list
classmethod
¶
list(
*,
client: DeepOriginClient | None = None,
status: list[str] | None = None,
quiet: bool = True
) -> list[Self]
Same as :meth:Execution.list, but quiet defaults to True.
plot
¶
plot(
*,
dto: dict[str, Any] | None = None,
metric: Literal[
"binding_energy", "pose_score"
] = "binding_energy",
clim: tuple[float, float] | None = None
) -> None
Visualize this run's results -- method-aware.
ligand-ml: heatmap colored by p_active.
docking: heatmap colored by metric.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dto
|
dict[str, Any] | None
|
Optional execution payload, forwarded to :meth: |
None
|
metric
|
Literal['binding_energy', 'pose_score']
|
Docking only. Which column to color the heatmap by. |
'binding_energy'
|
clim
|
tuple[float, float] | None
|
Override the default color range. A value outside the chosen range still renders, clipped to the nearest edge color. |
None
|
run
¶
run(
*,
quote: bool = False,
approve_amount: int | None = None
) -> DataFrame | SecondaryPharmacology
Execute the ligand-ml path synchronously and return predictions.
Valid only when :attr:method is "ligand-ml"; use :meth:start
for the docking path.
With quote=True (or approve_amount=0), requests a cost
estimate only, updates execution fields from the platform DTO, and
returns self without running inference.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
quote
|
bool
|
Shorthand for |
False
|
approve_amount
|
int | None
|
Spend cap forwarded as |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
A |
DataFrame | SecondaryPharmacology
|
class: |
DataFrame | SecondaryPharmacology
|
when quoting. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If :attr: |
DeepOriginException
|
If |
show
¶
show() -> None
Display the current execution in Jupyter using the execution card HTML view.
If no platform execution ID exists yet, shows the same card with a short notice
instead of raising (see :meth:~deeporigin.platform.execution_display.ExecutionDisplay.from_pending).
start
¶
start(
*,
quote: bool = False,
approve_amount: int | None = None,
**kwargs
) -> None
Submit a persisted async execution to the platform.
Only valid when status is None (no execution exists yet).
All other statuses raise immediately to prevent re-submission.
Pass quote=True or approve_amount=-1 to request a cost estimate
without running. If the platform returns a Quoted DTO the instance
is left in that state — call :meth:~deeporigin.drug_discovery.execution.Execution.confirm
explicitly to proceed.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
quote
|
bool
|
Shorthand for |
False
|
approve_amount
|
int | None
|
Spend cap passed to the platform as |
None
|
**kwargs
|
Forwarded verbatim to |
{}
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If the current status is not |
stop_watching
¶
stop_watching() -> None
Cancel an in-flight watch loop if one is running.
Safe to call when no watch is active. Does not cancel the caller's current task when invoked from inside the watch loop.
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 |
ValueError
|
If the returned DTO |
update_from_dto
¶
update_from_dto(dto: dict[str, Any]) -> None
Apply execution fields from dto and freeze uniprots.
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
|
Returns:
| Type | Description |
|---|---|
dict[str, Any] | None
|
The latest execution DTO, or |
Raises:
| Type | Description |
|---|---|
ValueError
|
If this instance has no execution id yet. |
TimeoutError
|
If |
watch
async
¶
watch(
*, interval: float = 5.0, blocking: bool = False
) -> Task | None
Live notebook updates for the docking path only.
Valid only when :attr:method is "docking" -- the ligand-ml path
is synchronous (:meth:run blocks until done), so there is never an
in-flight async job to poll.
See :meth:~deeporigin.drug_discovery.notebook_watch_mixin.NotebookWatchMixin.watch
for the full parameter/return contract.
Raises:
| Type | Description |
|---|---|
ValueError
|
If :attr: |