Prerequisites
WebMO's REST implementation requires the following:
- The webserver must support PUT, PATCH, and DELETE methods. For the Apache webserver, modify userdir.conf to add these as follows:
<Directory "/home/*/public_html">
AllowOverride FileInfo AuthConfig Limit
Options MultiViews SymLinksIfOwnerMatch IncludesNoExec
Require method GET POST OPTIONS PUT DELETE PATCH
</Directory> - The perl that is installed on the system must support CGI-Application, JSON, Exception-Class, Try-Tiny, Switch, and CGI-Application-Dispatch. These are often installed by default on newer systems, but frequently must be added to older systems. Thus, these perl modules are distributed with WebMO in <cgiBase>/lib, but system versions will be used if available.
REST Access to WebMO
WebMO Enterprise supports querying of WebMO though a REST (Representational State Transfer) interface. REST allows a user or administrator to submit queries and obtain data via HTTP(S) using specially crafted URL's. The REST response is a set of text characters, which could be data, the contents of a file, or the result of a program.
For example, parsed calculation results that typically appears on the Job Results page can also be accessed via a URL request by users. Job, folder, user, and group information can be queried by administrators. Some administrative actions, such as renaming or deleting jobs, can also be carried out using REST.
A REST query consist of several components:
- Method: GET and POST methods are most common, though PUT, PATCH, DELETE are also used
- Header: not used by WebMO
- Endpoint: a URL, consisting of a root, path, and frequently a query for GET methods
- Data: data associated with POST method
For example, a REST query could look like:
http://server.university.edu/cgi-bin/rest/students?class=seniors
where the method is GET (implied by the ?), the root is server.university.edu/cgi-bin/rest/, the path is students, and the query is class=seniors. The returned data from this URL would presumably be a list of senior students at the university.
A table of REST queries supported by WebMO follows. The following actions are defined in <cgiBase>/rest.cgi.
Path | Method | Query / Data | Description |
---|---|---|---|
jobs | GET | If requesting as an administrative user {user : smith}; Can optionally filter with {folderID, engine, status, jobname} | Request an enumeration of all jobs for the current user |
jobs/<jobNumber> | PATCH | Specify information to be changed {folderID, jobname} | Modify a job |
jobs/<jobNumber> | DELETE | Delete a job | |
jobs | POST | Specify local file name {outputFile} and parameters {jobname, engine} | Import a job from an existing local output file (regular users only) |
jobs | POST | Specify an input file contents {inputFile} and parameters {jobname, engine, queue [external batch queue only]} | Submit/execute a job given by the specified input file contents (regular users only) |
jobs/<jobNumber>/[|results|geometry|raw_output|archive] | GET | Request information about a specific job | |
folders | GET | If requesting as an administrative user, {user: smith} | Enumerate all folders for the current user |
users | GET | Enumerate all WebMO users on the system, or in the group if a sub-admin (administrative users only) | |
users/<username> | GET | Request information on a specific user | |
groups | GET | Enumerate all WebMO groups on the system (administrative users only) | |
groups/<groupname> | GET | Request information on a specific group, including enumeration of group members (administrative users only) | |
sessions | POST | {'username' : smith, 'password' : secret} | Obtain session token |
sessions | DELETE | Delete session token | |
engines | GET | Enumerate the available computational engines, along with associated server/queues and processor limits | |
templates/<engine> | GET | Enumerate the available job templates and associated template variables for the specified computational engine | |
templates/<engine>/<templateId> | GET | Must specify 'variables' parameter, which contains a JSON-formatted dictionary of template variables | Return an input file from the specified templateId, along with the provided JSON-formatted variables |
templates/rest/<templateName> | GET | authentication not required | Load Python program in REST/templates directory, with $jobNumber and $username variable substitution |
status | GET | authentication not required | Status of webmo server |
JSON Format of Returned Data
WebMO returns REST data queries in JSON (JavaScript Object Notation) format, which is a language-independent format of attribute-value pairs.
As an example, a geometry optimization job for water could result in the following response:
{"success":true,"molecular_multiplicity":1,"connectivity":[[1,2,1],[1,3,1]],"provenance":{"creator":"Gaussian"},"molecular_charge":0,"schema_name":"QC_JSON","properties":{"rhf_energy":{"value":-76.0107465155,"units":"Hartree"},"rotational_constants":[858.6603475,440.9401844,291.3340235],"route":" #N HF/6-31G(d) OPT Geom=Connectivity","scf_dipole_moment":[0,0,2.1989],"symmetry":"C2V","dipole_moment":[0,0,2.1989],"cpu_time":{"value":6.1,"units":"sec"},"stoichiometry":"H2O","basis":"6-31G(d)"},"comment":"H2O; Geometry Optimization","symbols":["O","H","H"],"geometry":[0,0,0.114681,0,0.754069,-0.458726,0,-0.754069,-0.458726],"schema_version":0}
which is more easily understood when formatted as:
{
"success": true,
"molecular_multiplicity": 1,
"connectivity": [[1,2,1],[1,3,1]],
"provenance": {
"creator": "Gaussian"
},
"molecular_charge": 0,
"schema_name": "QC_JSON",
"properties": {
"rhf_energy": {
"value": -76.01075,
"units": "Hartree"
},
"rotational_constants": [858.66034,440.9402,291.334],
"route": " #N HF/6-31G(d) OPT Geom=Connectivity",
"scf_dipole_moment": [0,0,2.1989],
"symmetry": "C2V",
"dipole_moment": [0,0,2.1989],
"cpu_time": {
"value": 6.1,
"units": "sec"
},
"stoichiometry": "H<sub>2<\/sub>O",
"basis": "6-31G(d)"
},
"comment": "H2O; Geometry Optimization",
"symbols": ["O","H","H"],
"geometry": [0,0,0.114681,0,0.754069,-0.458726,0,-0.754069,-0.458726],
"schema_version": 0
}
Most computer languages have libraries for reading JSON data, extracting values based on attribute, and assigning values to variables for use in subsequent calculations.
JSON formatted result data can also be directly downloaded from the Job Manager by selecting jobs and then choosing Download: JSON.
Issuing WebMO REST Requests from the Command Line
Curl (Client URL) is a command-line tool for transferring data using various protocols. REST queries can be issued manually from the command line with the curl utility. For example:
$ curl http://server.university.edu/~webmo/cgi-bin/webmo/rest.cgi/status
returns
{"url_cgi":"http://server.university.edu/~webmo/cgi-bin/webmo","jobs":302,"timestamp":"1/10/20 16:09","version":".0.002e"}
which gives the URL, total number of jobs run, time of last job, and version of the WebMO instance.
Job information is typically password protected. The following curl commands illustrate the creation of a token with a POST, use of the token to obtain user information and job information with GET's, and deletion of the token with a DELETE.
% bash
$ curl https://server.university.edu/~webmo/cgi-bin/webmo/rest.cgi/sessions -d "username=smith&password=secret" $ curl https://server.university.edu/~webmo/cgi-bin/webmo/rest.cgi/users/smith?token=PIcjs8PXGAw\&username=smith $ curl https://server.university.edu/~webmo/cgi-bin/webmo/rest.cgi/jobs/2/results?token=PIcjs8PXGAw\&username=smith $ curl -X DELETE https://server.university.edu/~webmo/cgi-bin/webmo/rest.cgi/sessions?token=PIcjs8PXGAw\&username=smith
{"token":"PIcjs8PXGAw","username":"smith"}
{"admin":false,"user":"smith","properties":{"archiveFormat":"tar","fullName":"John Smith","allowNewUsers":"1","enabledQueues":"all","jobTimeLimit":"-1","timeLimit":"-1","email":"smith@university.edu","viewJobInNewWindow":"0","enabledInterfaces":"all","emailNotification":"0","enabledServers":"all"}}
{"success":true,"molecular_multiplicity":1,"connectivity":[[1,2,1],[1,3,1]],"provenance":{"creator":"Gaussian"},"molecular_charge":0,"schema_name":"QC_JSON","properties":{"rhf_energy":{"value":-76.0107465155,"units":"Hartree"},"rotational_constants":[858.6603475,440.9401844,291.3340235],"route":" #N HF/6-31G(d) OPT Geom=Connectivity","scf_dipole_moment":[0,0,2.1989],"symmetry":"C2V","dipole_moment":[0,0,2.1989],"cpu_time":{"value":6.1,"units":"sec"},"stoichiometry":"H<sub>2</sub>O","basis":"6-31G(d)"},"comment":"H2O; Geometry Optimization","symbols":["O","H","H"],"geometry":[0,0,0.114681,0,0.754069,-0.458726,0,-0.754069,-0.458726],"schema_version":0}
{"results":"success"}
Issuing WebMO REST requests using Python
Results from WebMO calculations can be acessed programmatically view the REST interface. Although this can be done from any programming language with http communication capabilities, Python is widely available, very popular, and particularly convenient for this purpose.
An example of using REST within a Python program follows. It creates a REST session, obtains user information, obtains job information, and deletes the token. Rudimentary error checking is provided.
import requests
#Change the baseURL; should always be over https
baseURL = "https://server.university.edu/~webmo/cgi-bin/webmo/rest.cgi"
username=input('Enter WebMO username:')
password=input('Enter WebMO password:')
jobnum=input('Enter job number:')
#Obtain REST session token; include exception handling
try:
login={'username' : username, 'password' : password} #WebMO login information, used to retrieve a REST access token
r = requests.post(baseURL + "/sessions", data=login)
r.raise_for_status() #raise an exception if there is a problem with the request
token=r.json()["token"] #this is the REST access token used for all subsequent request
print("Obtained REST access token: %s" % token)
auth=r.json() #include both 'username' and 'token' parameters needed to authenticate further REST requests
#Example of how to access the 'users' resource
#Request information about the user
r = requests.get(baseURL + "/users/" + username, params=auth)
r.raise_for_status() #raise an exception if there is a problem with the request
userInfo=r.json()
print("User information: %s" % userInfo)
#Examples of how to access the 'jobs' resource
#Request information about a job
r = requests.get(baseURL + "/jobs/" + jobnum, params=auth)
r.raise_for_status() #raise an exception if there is a problem with the request
jobInfo=r.json()["properties"]
print("Job information: %s" % jobInfo)
#Request the parsed job results in QC JSON format
r = requests.get(baseURL + "/jobs/" + jobnum + "/results", params=auth)
r.raise_for_status() #raise an exception if there is a problem with the request
jobResults=r.json()
print("Job results: %s" % jobResults)
#Request the geometry of the job
r = requests.get(baseURL + "/jobs/" + jobnum + "/geometry", params=auth)
r.raise_for_status() #raise an exception if there is a problem with the request
xyzFormat=r.json()["xyz"]
print("Molecule geometry:\n%s" % xyzFormat)
# End the REST session
#End the REST session
r = requests.delete(baseURL + "/sessions", params=auth) # delete the session token
r.raise_for_status() #raise an exception if there is a problem with the request
print("Ended REST session")
#Catch any HTTP / REST exceptions and report the underlying cause
except requests.exceptions.HTTPError:
print("Error during REST request: %s" % r.json()["error"])
Enter WebMO username:smith
Enter WebMO password:secret
Enter job number:2
Obtained REST access token: 3BHdSzFLbE2
User information: {"admin":false,"user":"smith","properties":{"archiveFormat":"tar","fullName":"John Smith","allowNewUsers":"1","enabledQueues":"all","jobTimeLimit":"-1","timeLimit":"-1","email":"smith@university.edu","viewJobInNewWindow":"0","enabledInterfaces":"all","emailNotification":"0","enabledServers":"all"}}
Job information: {'jobEngine': 'gaussian', 'jobDate': '5/31/2024 17:04', 'jobNumber': 2, 'pid': 27315, 'jobUser': 'smith', 'folderID': 0, 'cpu_time': 5.59999990463257, 'server': 'server.university.edu', 'jobStatus': 'complete', 'jobGroup': 'webmo', 'jobDescription': 'Geometry Optimization', 'jobName': 'CH2O', 'failureCode': 0, 'checkpointFile': 0}
Job results: {'success': True, 'molecular_multiplicity': 1, 'connectivity': [[1, 2, 2], [1, 3, 1], [1, 4, 1]], 'provenance': {'creator': 'Gaussian'}, 'molecular_charge': 0, 'schema_name': 'QC_JSON', 'properties': {'rhf_energy': {'value': -113.866331244, 'units': 'Hartree'}, 'partial_charges': {'mulliken': [0.134657, -0.415652, 0.140497, 0.140497]}, 'rotational_constants': [293.6019141, 40.1410067, 35.3130379], 'geometry_sequence': {'units': 'Hartree', 'energies': [-113.853238892, -113.865860233, -113.866326832, -113.866331244], 'geometries': [[0, 0, -0.569375, 0, 0, 0.705625, 0, 0.943968, -1.114375, 0, -0.943968, -1.114375], [0, 0, -0.521715, 0, 0, 0.659434, 0, 0.931405, -1.072588, 0, -0.931405, -1.072588], [0, 0, -0.519869, 0, 0, 0.664385, 0, 0.92466, -1.097933, 0, -0.92466, -1.097933], [0, 0, -0.519493, 0, 0, 0.66477, 0, 0.924106, -1.100601, 0, -0.924106, -1.100601]]}, 'route': ' #N HF/6-31G(d) OPT Geom=Connectivity', 'scf_dipole_moment': [0, 0, 2.6658], 'symmetry': 'C2V', 'dipole_moment': [0, 0, 2.6658], 'cpu_time': {'value': 5.6, 'units': 'sec'}, 'quote': ' Change starts when someone sees the next step. -- William Drayton', 'stoichiometry': 'CH2O', 'basis': '6-31G(d)', 'method': 'HF'}, 'comment': 'CH2O; Geometry Optimization', 'symbols': ['C', 'O', 'H', 'H'], 'geometry': [0, 0, -0.519493, 0, 0, 0.66477, 0, 0.924106, -1.100601, 0, -0.924106, -1.100601], 'schema_version': 0}
Molecule geometry:
6 0.000000 0.000000 -0.519493
8 -0.000000 -0.000000 0.664770
1 0.000000 0.924106 -1.100601
1 -0.000000 -0.924106 -1.100601
Ended REST session
The use of REST within Python is greatly simplified by the use of the "webmo" Python library, which provides Python wrapper functions for making REST queries to access WebMO functionality. These are described in the Python Interface to WebMO.
Using the webmo Python library greatly simplifies making REST queries from within a Python program!