Backend of MOLEonline: loads protein structures, computes cavities, tunnels and pores with MOLE 2 and serves the results.
The container contains:
- the API (Python, FastAPI,
src/mole_api), with the .NET runtime for MOLE, - the pores tool (
src/mole_api/pores, part of the API, run as a process of its own): the membrane position for pore computations, from OPM or predicted by MEMEMBED, - MOLE 2, from the image
sbncbr/mole2, - MEMEMBED, built from source (GPL v2, its source and licence
are in
/opt/memembedin the image).
docker network create moleonline # once, shared with the web's compose project
docker compose up -d --buildThe API has no port on the host. It listens on port 8080 in the Docker network moleonline, as the
service api, for the web's nginx container. Startup checks the configuration: if a path is wrong, the
container stops and its log says what is wrong.
docker compose logs -f api # one line per event; requests are not logged, errors with the request pathTo reach the API from the host, e.g. for debugging, publish the port in compose.override.yaml
(compose reads it next to compose.yaml):
services:
api:
ports:
- "127.0.0.1:8080:8080"The web's nginx container (moleonline-web, docker/nginx.site.conf) serves the API under /api and
proxies it to api:8080 over the network moleonline. The network has to exist before either project
starts. The API takes the client address from X-Forwarded-For when the request comes from loopback or
a private network, as the Docker network is (the IP log, see below). The API runs with --root-path /api, so its
documentation (/api/docs) and "Try it out" use the proxy's URLs; on a port published for debugging the endpoints
work, the documentation does not.
location /api/ {
proxy_pass http://api:8080/;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
client_max_body_size 31m; # uploaded structures, the API accepts files up to 30 MB, also when unpacked
}Everything is in the volume data, mounted at /data:
| Path | Content |
|---|---|
/data/computations/<id>/ |
one computation: the structure, _object.json (status), one folder per submission |
/data/computations/Mole_api_IP_log.csv |
every load and submission request, also refused ones: time (UTC), Init or Submit, client address, PDB, Upload, Mole or Pores, computation id (- when none was created) |
/data/opm-cache/ |
membrane files downloaded from OPM, reused for 30 days |
Usage per month or year (computations, PDB entries and uploads, submissions and their outcome, distinct client addresses), from the status files and the IP log:
docker compose exec -T api /app/.venv/bin/python -I - /data/computations month < tools/stats.pyComputations running during a restart are reported as failed ("interrupted by a restart"); the user can submit them again.
Settings are environment variables, the defaults are the container's (src/mole_api/config.py):
| Setting | Default | |
|---|---|---|
WORKING_DIRECTORY |
/data/computations |
computations, must be writable |
MAX_CONCURRENT_COMPUTATIONS |
4 |
MOLE and pore runs at once (loads included), others wait in a queue |
MAX_COMPUTATION_MINUTES |
30 |
a run taking longer is stopped and reported as an error (a ribosome takes about 2 minutes) |
MOLE |
/opt/mole2/mole2 |
full path |
MEMEMBED |
/opt/memembed/memembed |
full path, the membrane of pore computations without OPM's |
OPM_CACHE |
/data/opm-cache |
membrane files downloaded from OPM, must be writable |
All times the API stores are in UTC.
The container's memory, all computations together, is limited to API_MEMORY_LIMIT (compose, default 24g, e.g. in
.env next to compose.yaml). Above it the kernel stops the largest process, a computation, which is reported as
having run out of memory; the API keeps running.
The OpenAPI documentation is at /docs (/openapi.json). Endpoint names match in any case and a trailing slash
is ignored, as in the former C# API (the web uses /Compinfo/ and /Init/). All responses are JSON. A request that fails has an HTTP error status and a report with Status: "Error" and ErrorMsg:
400 invalid request (parameters, file type, data format), 404 no such computation, submission or data, 409 the computation
is busy or could not be loaded, 410 deleted, 413 upload too large, 503 all slots busy, 500 server error. A report about a
computation that failed (e.g. Status of a failed submission) is a successful request, 200.
| Endpoint | |
|---|---|
POST /Init/{pdbId}?assembly= |
load a PDB entry from PDBe and compute its cavities; assembly: preferred (default, PDBe's preferred biological assembly, the one OPM has; the asymmetric unit when PDBe cannot tell which one it is, e.g. when it is not reachable), asymmetric (the asymmetric unit) or an assembly id |
POST /Init |
load an uploaded structure (multipart/form-data, .pdb, .cif, .pdb.gz, .cif.gz); a gzipped file is unpacked and stored as .pdb or .cif |
POST /Submit/Mole/{id} |
compute tunnels, body: MOLE parameters |
POST /Submit/Pores/{id} |
compute a pore across the membrane, body: InMembrane, IsBetaBarrel, Chains (list of chain names, empty: all), ProbeRadius, InteriorThreshold (null: the default) |
GET /Status/{id}?submitId= |
status of a computation or one submission |
GET /CompInfo/{id} |
the computation and the parameters of all submissions |
GET /Data/{id}?submitId=&format= |
results: json, report (zip), molecule, pymol, chimera, vmd, pdb, membrane |
GET /CSA/{id} |
catalytic active sites of the PDB entry from M-CSA, one per copy, starting points for tunnels |
POST /Kill/{id} |
stop the running submission |
DELETE /Delete/{id} |
delete the computation |
GET /Version |
versions of the API (also of the pores tool) and MOLE |
The active sites of /CSA come from M-CSA (Ribeiro et al., Nucleic
Acids Research 2018, CC BY 4.0), converted by tools/mcsa/convert.py into src/mole_api/resources/mcsa_sites.csv.gz.
The example inputs (/inputs/) are in src/mole_api/static/; / redirects to the documentation, /docs.
A structure has at most 30 MB, uploaded (also when unpacked) or downloaded from PDBe: a single ribosome fits (4V6X, 238,000 atoms, 23 MB), larger complexes do not. A larger upload is refused with 413, a larger PDBe entry fails to load.
uv sync
WORKING_DIRECTORY=/tmp/mole OPM_CACHE=/tmp/opm-cache MOLE=/path/to/mole2 MEMEMBED=/path/to/memembed \
uv run uvicorn mole_api.main:app
uv run pytest # with a fake MOLE and pores tool in the API's tests, and a fake PDBe
MOLE2=/path/to/mole2 MEMEMBED=/path/to/memembed uv run pytest # also the tests needing them, skipped withoutThe pores tool (src/mole_api/pores) runs as python -m mole_api.pores <pores.json>, its input is described in
cli.py. Its tests (tests/pores) compare with production results of the original Pores, in tests/pores/data/
(see its README).
MIT, see LICENSE. MEMEMBED in the container image is GPL v2.