API guide¶
Use AMDockVSRuntime as the public facade. A runtime owns the active MolSuite
project and its executors, so close it with shutdown() when the work is done.
from amdockvs import AMDockVSRuntime
Projects and jobs¶
runtime = AMDockVSRuntime()
runtime.create_or_open_project(name="demo", folder="./demo-project")
jobs = runtime.loader.load_ligands(["ligands.sdf"])
statuses = runtime.watch_jobs(jobs)
for status in statuses.values():
print(status.job_id, status.status)
Long operations submit MolSuite jobs. They return a job identifier, or a list
of identifiers for partitioned imports. watch_job() and watch_jobs() show
a tqdm progress bar in a terminal or notebook; wait_for_job() and
wait_for_jobs() wait without one. A job that reads what another one writes
waits for it, so a pipeline can be submitted at once and waited for at the end.
Where jobs run¶
Every job method takes executor_name:
- Left out, the job goes to the first active executor that can run it: the pool of processes of this machine unless another one was made the default.
"thread"runs it on threads of this process, which suits small jobs.- The name of an active executor sends it there.
print(runtime.run_destinations()) # [(name, label), ...] active now
job_id = runtime.docking.run(ligands=ligands, receptors=receptors, executor_name="lab-ray")
runtime.resume_job(job_id, "local") # stop it there and continue it here
Hosts and executors are kept by MolSuite and edited from the Hosts and
Executors pages of Settings, or through runtime.workspace (save_host, save_executor,
activate): see the ms_flow guide.
resume_job() also continues a job that was interrupted or canceled, without
running again what it had done.
Query molecules without loading everything¶
select() returns a lazy Selection[MoleculeRecord]; its .scope is the
serializable MoleculeScope used by jobs. A selection can be iterated,
counted, streamed, or saved as a stable set.
ligands = runtime.molecules.select(
role="ligand",
excluded=False,
)
print(ligands.count())
for molecule in ligands:
print(molecule.id, molecule.name)
training_set = runtime.molecules.create_set(ligands, name="training ligands")
Pass scopes to downstream APIs when the operation should follow a live query;
pass a MoleculeSetRef when reproducibility requires a saved snapshot.
Chemistry and QSAR¶
Chemistry operations are optional and composable:
job_id = runtime.chemistry.run_ligand_pipeline(
["standardize", "protonate", "generate_3d"],
ligands=ligands,
)
runtime.wait_for_job(job_id)
descriptor_job = runtime.qsar.compute_descriptors(molecule_set=ligands)
runtime.wait_for_job(descriptor_job)
Activities can be assigned directly or loaded from tabular data. Training and prediction consume molecule scopes or saved set references, and training needs at least two ligands with the activity:
runtime.qsar.set_activity(
ligand_id=42,
endpoint="IC50",
value=25.0,
unit="nM",
source="assay-1",
)
model = runtime.qsar.train(
molecule_set=training_set,
endpoint="IC50",
algorithm="random_forest",
)
predictions = runtime.qsar.predict(model=int(model.id), molecule_set=ligands)
Consult the generated reference for the complete signatures because available model options and return values are defined by the current implementation.
Binding sites¶
A binding site is a box on a receptor, drawn by hand or predicted:
receptors = runtime.molecules.select(role="receptor")
receptor = receptors.one()
runtime.binding_sites.save_site(
molecule_id=int(receptor.id),
name="active site",
center=(12.0, 13.0, 10.0),
size=(20.0, 20.0, 20.0),
)
P2Rank predicts them once it is installed through the tools facade:
status = runtime.tools.install("p2rank")
job_id = runtime.binding_sites.predict(receptor_ids=[int(receptor.id)])
runtime.watch_job(job_id)
sites = runtime.binding_sites.select(molecule_id=int(receptor.id), source="p2rank")
runtime.tools.status() lists every managed tool and whether it is ready.
Docking¶
A docking run needs prepared molecules and a grid on each receptor:
runtime.watch_jobs([
runtime.docking.prepare_ligands(ligands=ligands),
runtime.docking.prepare_receptors(receptors=receptors),
])
runtime.docking.set_grid(
receptor_id=int(receptor.id),
center=(12.0, 13.0, 10.0),
size=(20.0, 20.0, 20.0),
)
job_id = runtime.docking.run(ligands=ligands, receptors=receptors, exhaustiveness=8)
runtime.watch_job(job_id)
print(runtime.docking.result_stats())
program chooses the engine: vina (the default), qvina (QuickVina 2),
gnina or adgpu (AutoDock-GPU). The options of any engine go in
engine_config, which is validated against that engine's model; for engines
other than vina the keyword arguments exhaustiveness, num_modes and
vina_cpu are not read.
job_id = runtime.docking.run(
program="gnina",
ligands=ligands,
receptors=receptors,
engine_config={"exhaustiveness": 8, "num_modes": 9, "scoring_function": "rescore"},
)
| Program | engine_config keys |
|---|---|
vina |
exhaustiveness, num_modes, scoring_function (vina, vinardo, ad4), vina_cpu, ... |
qvina |
exhaustiveness, num_modes, vina_cpu, energy_range, seed |
gnina |
exhaustiveness, num_modes, vina_cpu, scoring_function (rescore, none, refinement, all), seed |
adgpu |
nrun, num_modes, parameter_file, derived_types, seed |
runtime.docking.list_programs() describes them. A pair already docked with
the same protocol is skipped unless skip_existing=False.
Complexes¶
A complex names a receptor-ligand pair explicitly, for redocking or rescoring a known pose:
complex_record = runtime.complexes.create(
receptor_molecule_id=int(receptor.id),
ligand_molecule_id=42,
purpose="redocking",
)
print(runtime.complexes.count(purpose="redocking"))
Diversity¶
Clustering runs once as a job; choosing what represents each cluster is a separate step that can be repeated on the stored run:
job_id = runtime.diversity.cluster_job(method="bitbirch", threshold=0.65)
runtime.watch_job(job_id)
run = runtime.diversity.list_runs()[0]
runtime.diversity.pick_representatives(run["cluster_run_id"], mode="medoid")
representatives = runtime.diversity.save_centroids_as_set(run["cluster_run_id"], name="diverse")
runtime.diversity.supported_methods() and representative_modes() list the
choices.
Cleanup¶
Always release executors and project resources:
runtime.shutdown()
For scripts, a try/finally block is the safest pattern.