Example python code
The OpenStructure Actions API is intended to be used programatically for comparing structures, without the need to locally install OpenStructure.
Job submission and status checks are rate limited, if you send too many requests you will
receive a 429 response. The results should indicate the current submission rate. The submission
rate may change at any time, depending on demand of the service. Currently, the
rapid submission rate is 100/m
and the prolonged rate is set as 2000/6h
.
The API uses a token based authentication system, so the first step is to retrieve a token for your SWISS-MODEL user account. This token is to be placed in the header of subsequent API calls.
1: Obtain a token
This can be done from the command line, but the recommended method to discover (and regenerate) your API token is to visit your SWISS-MODEL account page.
2: Start a comparison
import requests, time token="YOURAPITOKEN" base_url="https://swissmodel.expasy.org/ost"
- The coordinate files and parameters must be uploaded with Content-Type=application/x-www-form-urlencoded. (When using python requests, use "data" not "json")
- The 'model' and 'reference' named file uploads are essential for both OST Actions
- For compare-ligand-structures, if the model or reference are in mmCIF format, the ligands will be extracted directly, thus model-ligands and / or reference ligands are not required. SDF files are only required if model and/or reference are in PDB format.
- SDF format may include single or multiple ligands.
- When uploading multiple model/reference ligands, note how python requests requries a list of tuples where each tuple includes the field name (repeated) and the file object.
with ( open("model.pdb") as mdl, open("reference.pdb") as ref ): response = requests.post( f"{base_url}/compare-structures", headers={ "Authorization": f"Token {token}" }, files=[ ("model", mdl), ("reference", ref) ], # add optional parameters as data data={ "lddt": True, "local-lddt": True } )
with ( open("model.pdb") as mdl, open("reference.pdb") as ref, open("modelLigand1.sdf") as mdlLig1, open("modelLigand2.sdf") as mdlLig2, open("referenceLigand1.sdf") as refLig1, open("referenceLigand2.sdf") as refLig2 ): response = requests.post( f"{ base_url }/compare-ligand-structures", headers={ "Authorization": f"Token {token}" }, files=[ ("model", mdl), ("reference", ref), ("model-ligands", mdlLig1), ("model-ligands", mdlLig2), ("reference-ligands", refLig1), ("reference-ligands", refLig2) ], # add optional parameters as data data={ "lddt-pli": True, "rmsd": True }, )
-
At this point, check that
response.ok==True
(status code < 400) -
Specifically, a
response.status_code==202
means that valid input was received and an OST Action job will be started when resources become available. -
A
response.status_code==200
means that the valid input has been seen before and so the project is already completed / failed.
project_id = response.json()["project_id"] print(project_id)
3: Fetch the results
# Obtain the project_id from the response created above project_id = response.json()["project_id"] # And loop until the project completes while True: # We wait for some time time.sleep(10) # Fetch the results for this specific project_id project_details = requests.get( f"{ base_url }/compare-results/?project_id={ project_id }", headers={ "Authorization": f"Token {token}" } ).json()["projects"][0] print("Job status is now", project_details["status"]) if project_details["status"] in ["COMPLETED", "FAILED"]: break print(project_details["results"])
- To return all projects, simply fetch the results with no query parameters.
- It is possible to fetch multiple results with a comma separated value for project_id.
- Adding queries based on project creation date ("from" and "to") are useful way to filter your projects. The datetime can be entered as a simple date if you prefer.
- Filtering by OST Action type ("action") is another possible query filter filter, the options being compare-structures or compare-ligand-structures.