Use Studio in a workflow¶
Use the editing library for Python code and the HTTP API when another process owns the document. Neither interface needs a browser, Qt, a model runtime, or a GPU. Both currently install AtomWorks 3’s ML dependencies, including Torch.
Python primitives¶
pip install atomworks-studio provides the editing library
(atomworks_studio_editing) for base AtomWorks conditions and the RFD4 adapter
(atomworks_studio_rfd4) for the same hotspot, group, and other condition
definitions that the full Studio installation uses.
from pathlib import Path
from atomworks_studio_editing.document import StudioDocument
from atomworks_studio_editing.providers import load_providers
providers = load_providers()
document = StudioDocument.from_cif(
Path("input.cif").read_text(),
condition_provider=providers.condition_provider,
validation_provider=providers.validation_provider,
)
indices = document.query_indices("sel('*/*/*/CA')").tolist()
document.set_condition("sequence", indices)
Path("annotated.cif").write_text(document.to_cif())
StudioDocument(array, ...) also accepts an AtomWorks AtomArrayPlus directly.
Use one document per request or workflow. Mutations validate and create Undo
steps; document.undo() reverses the last one. document.protonate(ph=7.4)
updates hydrogens and formal charges. to_cif() serializes the current array.
Call document.validate(full_pipeline=True) and inspect its returned issues
when preparing model inputs; serialization alone is not a validation check.
The executable annotation example uses these same calls. From the repository:
python examples/annotate.py packages/api/annotation_studio/examples/protein_binder.cif annotated.cif \
--query "sel('*/*/*/CA')" --condition hotspot
HTTP and embedded editing¶
Start atomworks-studio. Create a session by uploading an annotated CIF to
POST /api/v1/sessions as multipart field file. The response contains a
session_id and an editor_path, such as /?session=…&embed=1. Open that path
on the same Studio server to edit the uploaded structure.
curl --fail -F file=@input.cif http://127.0.0.1:8000/api/v1/sessions
For that session, use:
Method and path after |
Use |
|---|---|
|
Resolve an AtomWorks expression or selection path. |
|
Apply an annotation to explicit atom indices. |
|
Assign hydrogens and formal charges at a given pH. |
|
Revert the last edit. |
|
Serialize the current annotated CIF. |
|
Validate and serialize one snapshot; return the CIF and validation issues. |
The running server exposes request schemas at /docs and /openapi.json.
For an iframe, allow the parent’s exact origin with
ANNOTATION_STUDIO_FRAME_ANCESTORS. Sessions are bounded, expire, and use one
server process. Export files before submitting a long-running inference job.
Embedding Studio in a page¶
An iframe host drives Studio over postMessage and the HTTP API, as above. A host
that runs in the same page — a model running in the browser, a notebook, a Space
that streams results — uses window.atomworksStudio instead. It appears once the
editor has started, and every call goes through the same path as the UI, so an edit
is one Undo step and the document on the server stays the source of truth.
Call |
What it does |
|---|---|
|
Show one frame of a structure you are producing. Successive calls replace it in place, so the scene does not flash. |
|
Show a display-only structure beside the document; |
|
Trade picture quality for frame rate while streaming frames; restores the previous look exactly. |
|
Go back to the open document after frames or a failed run. |
|
Open a session you created, optionally with a trajectory to scrub. |
|
Open a file you already have, or a bundled example. |
|
Apply a document mutation by API path, e.g. |
|
The selection, as document atom indices. |
|
The colour Studio draws a chain in, so your own UI can match. |
|
The Studio release the page was built from. |
A host that serves the bundle itself usually does not want Studio’s offline cache pinning its assets. Turn it off in the composed page:
<meta name="atomworks-studio-service-worker" content="off" />
Same-page hosts receive the ready, changed and example notifications an iframe
host gets over postMessage, as an atomworks-studio window event carrying the same
payload (source, type, session_id), plus selection with a count whenever the
selection changes.
window.addEventListener("atomworks-studio", (event) => {
if (event.detail.type === "changed") refreshMyPanel(event.detail.sessionId);
});
await window.atomworksStudio.openExample("motif_scaffolding");
await window.atomworksStudio.renderFrame(cif, "step 12", { keepCamera: true });
Hugging Face Spaces¶
The Docker Space example serves the existing editor on port 7860, including this guide. It uses built wheels, so the deployed container needs no Node, Rust, PyMOL, or separate frontend build. It is an editor-only CPU recipe; it does not execute inference. Docker Spaces can host a custom server and use GPU hardware.
Model-enabled Gradio host¶
Install atomworks-studio[gradio] for the optional shared generation UI. The base
editor installation does not require Gradio. Studio owns the embedded editor,
queued Generate action, current-document export, result selection and CIF/ZIP
downloads. Model-specific controls and validation live in the model’s provider.
The deployment supplies one synchronous callback: (annotated_cif, options) to
a list of output CIF strings. It runs off the API event loop with one queued worker.
from annotation_studio.gradio import create_app
from atomworks_studio_rfd4.generation import RFD4GenerationProvider
# generate(cif: str, options: dict) -> list[str] is supplied by your deployment.
app = create_app(
provider=RFD4GenerationProvider(k_defaults=(16.0, 4.0)),
generate_fn=generate,
)
Serve this app with Uvicorn using one process. /design/ is the generation UI;
the existing editor and versioned HTTP API remain on the same origin. The callback
receives a validated snapshot of the current edits. Its output becomes separate
Studio documents; failed requests preserve the input. Download files before
sessions expire. This in-memory queue does not persist or cancel running jobs.
The same Gradio host exposes /generate_cif for scripts. It accepts an annotated
CIF string and the provider’s options, validates the CIF through Studio, and
returns designs (CIF strings) and warnings. For a private Space:
import os
from pathlib import Path
from gradio_client import Client
client = Client("https://<space>.hf.space/design/", token=os.environ["HF_TOKEN"])
result = client.predict(
Path("input.cif").read_text(),
{"thinking": "medium", "samples": 1, "seed": 42},
api_name="/generate_cif",
)
Path("design.cif").write_text(result["designs"][0])
The editor button and this endpoint call the same validated model callback.
Task conditioning, inverse folding included, comes from the annotated CIF: which
residues are held, which are new and what is marked a hotspot already say what is
being designed, so there is no task option to keep in step with the document.
RFD4 partial diffusion is controlled by partial_diffusion, off by default. With
partial_diffusion: true, partial_diffusion_percent ranges from 1 to 100 and
defaults to 70; the deployment maps it to
generation.args.partial_trajectory_fraction_steps by dividing by 100.
A provider may implement three optional members, each read with a default so
providers written against earlier releases keep working: default_example, an
example id Studio opens on instead of an empty editor; css, appended to
Studio’s own so provider element ids stay out of the host; and
validate_input(snapshot, options), which rejects an input the chosen options
cannot run on before any GPU time is spent. The RFD4 provider uses the last of
these to refuse partial diffusion on expandable segments, reading
has_expandable_segments from the same exported snapshot — this includes
realized segments whose residues are still undefined. Generate a fully defined
input first, or use the partial diffusion example.
Run python scripts/preview_generation.py to see this UI locally with a
simulated model, including the generation and failure states.
The deployment owns model weights, CUDA dependencies and execution. Pass native
tsr_k defaults from its inference configuration to the RFD4 provider. No Torch
model, model download, GPU provisioning or job-provider registry is added to
Studio. Other model providers implement the small GenerationProvider interface
in annotation_studio.gradio. Gradio and model generation remain optional for
PyMOL, VS Code and the standalone browser editor.
ZeroGPU requires a Gradio Space;
the model deployment wraps its callback in spaces.GPU. The editor-only Docker
Space remains a CPU recipe. A Studio handoff check does not validate GPU inference;
run the actual model on its intended host before releasing a deployment.
RFD4-Proteina deployment¶
The RFD4 deployment uses the shared host and RFD4 provider above.
Install Studio in RFD4’s supported Python/CUDA environment, using the model repository’s installation guide. The adapter loads a pinned Hugging Face checkpoint bundle once and invokes RFD4’s native generation entry point for each request. The provider supplies task, recycling preset, design count, seed and noise controls.
Keep model and Space repositories private during qualification. Store
HF_TOKEN as a Space secret and pin RFD4_MODEL_REVISION to the verified model
commit. The deployment guide in the model repository owns the exact environment
and launch instructions.
The Studio adapter hands annotated CIFs to the model deployment and imports its result CIFs. The deployment owns eager or compiled execution, progress, trajectories, and refolding metrics. Test generation on the intended GPU; editor handoff tests use a test callback.
NIM and other inference services¶
Use Studio before and after inference: export an input, call the service from your backend, then import its structure output. Keep endpoint credentials on the server. NIM APIs are model-specific; convert the input to the documented schema and check which annotations the model actually consumes. Arbitrary annotated CIF fields are not universally supported.
For example, consult the OpenFold3 request examples or Boltz-2 inference guide for the chosen service. Studio does not need an NVIDIA or Hugging Face SDK just to prepare structures or inspect their outputs.
Trajectory playback¶
A model host can attach a multi-model CIF to an output session with
?session=SESSION_ID&trajectory=ENCODED_URL. URL-encode a file URL on the same
Studio origin. Studio fetches it when the user selects Show trajectory and
provides Play/Pause and a frame slider in the existing viewer. Both Patinae
and Mol* render the frames; no model code is included in Studio.
RFD4’s lightweight trajectories contain only Cα atoms. Mol* automatically estimates helix and strand assignments from each frame’s Cα geometry using its Zhang–Skolnick method. These are approximate assignments, not full-backbone DSSP results. Patinae currently shows these trajectories as a backbone trace; its secondary-structure assignment requires N, Cα, C, and O atoms. Neither viewer needs extra model inference for playback.
Playback is view-only. Back to design restores the session’s editable final structure. Opening a different document or editing the result removes the old trajectory association. Model hosts control whether snapshots are recorded, their retention, and access to the trajectory file.