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:

  • playmolecule installed with a working registry (default GCloud Docker registry, or your own PM_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.status tells you whether the run succeeded.

Next#