First app run#
You will learn: how to discover PlayMolecule apps, set up a job for one, run it locally, and find its outputs.
Prerequisites:
playmoleculeinstalled with a working registry (default GCloud Docker registry, or your ownPM_REGISTRIES).Docker (or Apptainer) available on your machine.
We’ll use proteinprepare, the app that protonates a protein at a chosen pH, as the running example. The recipe is the same for every app — they’re all just Python functions.
Setup#
from playmolecule import describe_apps
from playmolecule.apps import proteinprepare
describe_apps() is the entry point for discovery. playmolecule.apps is the namespace where every installed app appears as an importable submodule.
Step 1 — See what’s installed#
describe_apps()
You’ll see lines like:
ProteinPrepare playmolecule.apps.proteinprepare.v1.proteinprepare
ProteinPrepare despite it's name prepares proteins but also other systems including nucleic acids
DeepSite playmolecule.apps.deepsite.v1.deepsite
Predict ligand binding pockets in your protein of interest using a neural network-based predictor.
...
The first line has the human-readable name followed by the fully qualified import path; the indented second line is the one-sentence description from the app’s manifest. The qualified path looks like playmolecule.apps.<appname>.<version>.<function> — but you don’t need to type the version; the latest one is aliased at playmolecule.apps.<appname> (see Select an app version).
If you want the data as a dict instead of printed output:
apps = describe_apps(as_dict=True)
apps["playmolecule.apps.proteinprepare.v1.proteinprepare"]["description"]
Step 2 — Inspect a single app#
Every app is a normal Python function with a generated signature and docstring:
help(proteinprepare)
help shows the parameter list pulled from the app manifest — names, types, defaults, descriptions, expected outputs, and any built-in examples. In IPython, proteinprepare? is equivalent.
Step 3 — Set up the job#
Calling the app function does not run anything; it sets up an ExecutableDirectory:
ed = proteinprepare(outdir="out", pdbid="3ptb")
After this call, ./out/ exists on disk with everything the container needs to execute: a run_<timestamp>_<uuid>/ inputs directory, the rendered run script, and the manifest’s input JSON.
ed is just a handle on that directory. Nothing has executed yet — you can still tweak files in ./out/ if you want to.
Step 4 — Run the job#
ed.run()
This pulls the app’s container image if it isn’t cached, runs it against the inputs directory, and streams logs to stdout. When run() returns, the job is done. (Caveat: against an HTTP backend, run() submits asynchronously and returns immediately — see Log in to the HTTP backend and set PM_BLOCKING=1 if you want the call to wait.)
Step 5 — Check status and outputs#
print(ed.status)
You’ll see JobStatus.COMPLETED (or JobStatus.ERROR if something failed). The full list of states is in JobStatus.
The outputs are sitting in ./out/. For proteinprepare:
out/
├── output.pdb # the protonated structure
├── details.csv # residue-by-residue protonation report
├── pka_plot.png # pKa plot
└── run_<id>/ # input manifest + logs + run script
What lands in outdir is defined by the app’s manifest — help(proteinprepare) lists the Outputs section.
Step 6 — Shorter syntax#
You can chain the call and the run in one line:
proteinprepare(outdir="out", pdbid="3ptb").run()
This is fine for ad-hoc work. Keep the ed binding when you want to query status later, submit to SLURM, or batch several jobs together.
Recap#
describe_apps()lists everything available.Every app is a Python function that accepts manifest-defined parameters and returns an
ExecutableDirectory.Calling the app sets up a job; calling
run()executes it.ed.statustells you whether the run succeeded.