RESTful URI

Aggrescan3D webserver may be operated throught RESTful services, using following URIs:

Submitting job from the command line

Submit job for 2PCY protein, using cURL, with default parameters (i.e. distance of aggregation = 10Å, without mutation of residues, without distance mode, without hiding project on the queue page, without email address and with default project name): curl -i {{url_for('rest_submit_job', pdbcode='2pcy', _external=True)}}.

Submit chain B of 1hui: curl -i {{url_for('rest_submit_job', pdbcode='1hui', chain='B', _external=True)}}

User should get output like:

HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 57
Server: Werkzeug/0.9.6 Python/2.7.8
Date: Wed, 12 Nov 2014 13:52:56 GMT

{
  "jobid": "a0ae2bb71feeaf0",
  "status": "submitted"
}
where jobid is job identifier assigned to the just submitted job. Otherwise (for example if pdbcode doesn't exists or input data doesn't fullfill requirements), user should get output similar to:
HTTP/1.0 404 NOT FOUND
Content-Type: text/html; charset=utf-8
Content-Length: 5521
Server: Werkzeug/0.9.6 Python/2.7.8
Date: Wed, 12 Nov 2014 13:56:48 GMT

  
<!doctype html>
<html lang='en'>
[...]

To override default parameters, user may post additional options, i.e.: curl -i -X POST -d '{"email": "john@doe.com", "dynamic": "True", "name": "some project name"}' -H 'Content-Type: application/json' {{url_for('rest_submit_job', pdbcode='2pcy', _external=True)}}. Specified parameters will override default parameters, not specified ones would left unchanged (in this example job will be submitted with distance of aggregation = 10Å, with dynamic mode, and with specified email and project name).

Submitting from the python script

The simplest Python script for submitting new job may looks like:

#!/usr/bin/env python
import requests

req = requests.post('{{url_for('rest_submit_job', pdbcode='2pcy', _external=True)}}')

print(req.status_code)
print(req.json())

Submitting with parameters (mutation) from Python script:

#!/usr/bin/env python
import requests
import json

# define which residues to mutate. If specified residues not exists within pdb
# job will not be submitted (got 404 error)
mutation_table = [{'idx': "1", 'chain': 'A', 'oldres': 'I', 'newres': 'W'},
                  {'idx': "2", 'chain': 'A', 'oldres': 'D', 'newres': 'W'}]

# specify additional options
options = {'dynamic': True,
           'distance': 5,
           'email': 'john@doe.gov',
           'name': 'some project name',
           'hide': True,
           'mutate': mutation_table}

req = requests.post('{{url_for('rest_submit_job', pdbcode='2pcy', _external=True)}}',
                    data=json.dumps(options),
                    headers={'content-type': 'application/json'})

print(req.status_code) # get HTTP code. If 200 = OK. Otherwise = problems
print(req.json()) # get query returned data

Submitting custom PDB file from the python script

The simplest Python script for submitting new job may looks like:

#!/usr/bin/env python
import requests

req = requests.post('{{url_for('rest_submit_userfile', _external=True)}}', files={'inputfile': open('some_file.pdb', 'rb')})

print(req.status_code)

Submitting user file with parameters (mutation) from Python script:

#!/usr/bin/env python
import requests
import json

# define which residues to mutate. If specified residues not exists within pdb
# job will not be submitted (got 404 error)
mutation_table = [{'idx': "1", 'chain': 'A', 'oldres': 'I', 'newres': 'W'},
                  {'idx': "2", 'chain': 'A', 'oldres': 'D', 'newres': 'W'}]

# specify additional options
options = {'dynamic': True,
           'distance': 5,
           'email': 'john@doe.gov',
           'name': 'some project name',
           'hide': True,
           'mutate': mutation_table}

req = requests.post('{{url_for('rest_submit_userfile', _external=True)}}', data=options, files={'inputfile': open('some_file.pdb', 'rb')})

print(req.status_code) # get HTTP code. If 200 = OK. Otherwise = problems

Get submitted job information

By running curl -i {{url_for('get_jobstatus', jobid='somejobidentifier', _external=True)}} user should get:

HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 19
Server: Werkzeug/0.9.6 Python/2.7.8
Date: Wed, 12 Nov 2014 14:27:49 GMT

{
  "done": false
}
if job is running/pending, or
HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 18
Server: Werkzeug/0.9.6 Python/2.7.8
Date: Wed, 12 Nov 2014 14:28:33 GMT

{
  "done": true
}
if job got done/error status.

To get protein structure with A3D values in the temperature factor column and save it to out file: curl -o out {{url_for('get_out_structure', jobid='somejobidentifier', _external=True)}}

To get full information about submitted job, user may create Python script like:

#!/usr/bin/env python
import requests

req = requests.get('{{url_for('get_job_info', jobid='somejobidentifier', _external=True)}}')

print(req.status_code)
data = req.json()
for k in data.keys():
    print("key: %s: %s" % (k, data[k]))
getting output similar to:
200
key: chain_sequence: A: GSFTMPGLVDSNPAPPESQEKKPLKPCCACPETKKARDACIIEKGEEHCGHLIEAHKECMRALGFKI
key: status: done
key: mutated_residues: None
key: dynamic_mode: 0
key: mutate_mode: 0
key: last_status_change_date: 2014-11-06 12:01:04
key: project_name: b530f472611c285
key: aggregation_distance: 10
key: aggrescan3Dscore: {u'max_value': 1.664, u'total_value': -95.41120000000001, u'min_value': -4.1893, u'average_value': -1.424, u'table': [{u'res_name': u'G', u'res_idx': u'1', u'chain': u'A', u'a3d': u'-0.3367'}, ...  ]}
key: submission_date: 2014-11-06 11:53:12
If user would like to get Aggrescan3D score table, she may use script like:
#!/usr/bin/env python
import requests

req = requests.get('{{url_for('get_job_info', jobid='somejobidentifier', _external=True)}}')

data = req.json()
a3d = data['aggrescan3Dscore']

print("AVG A3D: %s" % (a3d['average_value'])) # data is a dictionary
print("MIN A3D: %s" % (a3d['min_value']))

for row in a3d['table'][:6]:
    print(row['res_idx'], row['a3d'])
to get output like:
AVG A3D: -1.424
MIN A3D: -4.1893
(u'1', u'-0.3367')
(u'2', u'0.3541')
(u'3', u'1.6640')
(u'4', u'0.8468')
(u'5', u'1.2976')
(u'6', u'0.5633')

Combine two RESTful URI to wait until job is done:

#!/usr/bin/env python
import requests
import time

server = '{{url_for('index_page', _external=True)}}RESTful/job/'
jobid = "caaaffa24b4bcad"

v = False
while not v:
    req = requests.get(server+jobid+'/isdone/')
    v = req.json()['done']
    time.sleep(60)  # 1 min intervals

req = requests.get(server+jobid)
data = req.json()
a3d = data['aggrescan3Dscore']
print("AVG A3D: %s" % (a3d['average_value']))
Above script will print average A3D score as soon as job get 'done' status.

Some fun with RESTful and Bash scripting. Script below should say something as soon as job is completed:

#!/usr/bin/env bash

v="false"
while [ "$v" == "false" ]
do
    v=`curl -s {{url_for('get_jobstatus', jobid='somejobidentifier', _external=True)}} | grep 'done' |grep -o 'false'`
    sleep 6
done
mplayer -user-agent Mozilla  "http://translate.google.com/translate_tts?q=Job+completed.Aggrescan+3D+is+wonderful&tl=en"