Skip to content

Commit

Permalink
Merge pull request #193 from tom-and-the-toothfairies/release-2
Browse files Browse the repository at this point in the history
Release 2
  • Loading branch information
houli authored Apr 9, 2017
2 parents e88e5cc + a6cf89d commit 0e5cc90
Show file tree
Hide file tree
Showing 32 changed files with 23,533 additions and 120 deletions.
31 changes: 15 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,38 +9,38 @@ maximum convenience - click-able links for example*
This file contains instructions on how to install and run the project, as well
as an overview of the project's design. The target platform is Ubuntu 16.04.

At the time of writing the current release is `1.3`
At the time of writing the current release is `2.0`

## Installing Dependencies

This project uses Docker and Docker Compose. For Ubuntu 16.04, an installation
script `install-docker.sh` is provided for convenience.
This project uses Docker and Docker Compose. An installation script,
`install-docker.sh`, is provided for Ubuntu 16.04.

```bash
$ ./install-docker.sh
```

For platforms other than Ubuntu, follow the installation instructions on
the [Docker Website][install docker ce]. Note - on other platforms, sudo is not
required for docker commands.
required for Docker commands.

You can test your docker installation by running docker's built in hello-world:
You can test your Docker installation by running Docker's built in hello-world:

```bash
$ sudo docker run hello-world
```

## Running

The project can be run with `docker compose`
The project can be run with Docker Compose:

```bash
$ sudo docker-compose up -d
```

The system is then accessible at [localhost:4000](http://localhost:4000).

To stop the project, run the following command
To stop the system, run the following command

```bash
$ sudo docker-compose down
Expand All @@ -60,50 +60,49 @@ document](./doc/FEATURES_RELEASE_1.md).

## Change Log

The change log for the project can be found [here](./doc/CHANGELOG.md)

Changes to the project are recorded in the [change log](./doc/CHANGELOG.md).

## Architecture Overview

The system is split into three distinct services; Panacea, Asclepius and Chiron.
The auxiliary service, Athloi, is used for automated testing.
They each run inside a docker container. The containers can be easily managed
They each run inside a Docker container. The containers can be easily managed
using `docker-compose` as mentioned earlier.

### Panacea

Panacea is responsible for the UI and PML analysis. It is a web application that
serves the UI and exposes an API for uploading PML files for analysis.

More information about Panacea can be found [here](./panacea/README.md).
More information about Panacea can be found [in the Panacea README](./panacea/README.md).

### Chiron

Chiron houses the DINTO data. The data is compiled into a triple store. Chiron
exposes a HTTP API for querying the triple store.

More information about Chiron can be found [here](./chiron/README.md).
More information about Chiron can be found [in the Chiron README](./chiron/README.md).

### Asclepius

Asclepius acts as an intermediary between Panacea and Chiron. It accepts
requests to identify DDIs from Panacea, creates the necessary SPARQL query and
passes it on to Chiron.

More information about Asclepius can be found [here](./asclepius/README.md).
More information about Asclepius can be found [in the Asclepius README](./asclepius/README.md).

### Athloi

Athloi is the service that runs our end to end tests.

More information about Athloi can be found [here](./athloi/README.md).
More information about Athloi can be found [in the Athloi README](./athloi/README.md).

## Building Manually

Docker compose will pull down the required versions of each service from [Docker
Docker Compose will pull down the required versions of each service from [Docker
Hub] when you run the project. If for some reason you wish to build these
services manually, instructions for doing so can be
found [here](./doc/BUILDING_MANUALLY.md).
found [in the manual build documentation](./doc/BUILDING_MANUALLY.md).



Expand Down
61 changes: 40 additions & 21 deletions asclepius/README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
Asclepius ⚕
===========

Flask endpoint for querying DINTO. Supports querying for all drugs listed, as well as finding all, or specific drug-drug interactions.
Flask endpoint for querying DINTO. Supports querying for all drugs listed, as
well as finding all, or specific drug-drug interactions.

This application acts as an adaptor to Chiron - an instance of Apache Fuseki, Chiron must be running before any queries can be served.
This application acts as an adaptor to Chiron - an instance of Apache Fuseki,
Chiron must be running before any queries can be served.

Endpoints
---------
CSV File Exporting
------------------

When run as a program, the `enrich` module will export DDIs, along with mock
timing and agonism/harmfulness information.

Run as `python3 enrich.py <harmful|agonism> > outfile.csv` to export to a CSV file.

HTTP Endpoints
-------------

### `/all_drugs`

Expand Down Expand Up @@ -44,12 +54,12 @@ Endpoints

### `/all_ddis`

| | |
|-------------|--------------------------------------------------------------------------------------------------------|
| Description | Find all drug-drug interactions (DDIs) in the DINTO ontology |
| Methods | `GET` |
| Parameters | None |
| Returns | A list containing pairs of the canonical URI for a drug-drug interaction, as well as its English Label |
| | |
|-------------|---------------------------------------------------------------------------------------------------------------------------------------------|
| Description | Find all drug-drug interactions (DDIs) in the DINTO ontology |
| Methods | `GET` |
| Parameters | None |
| Returns | A list containing pairs of the canonical URI for a drug-drug interaction, as well as its English label and the labels of the drugs involved |

#### Example

Expand All @@ -59,27 +69,34 @@ Endpoints
[
{
"label": "torasemide/trandolapril DDI",
"uri": "http://purl.obolibrary.org/obo/DINTO_11031"
"uri": "http://purl.obolibrary.org/obo/DINTO_11031",
"drug_a": "torasemide",
"drug_b": "trandolapril"
},
{
"label": "cimetidine/heroin DDI",
"uri": "http://purl.obolibrary.org/obo/DINTO_02733"
"uri": "http://purl.obolibrary.org/obo/DINTO_02733",
"drug_a": "cimetidine",
"drug_b": "heroin"
},
{
"label": "methylergonovine/telithromycin DDI",
"uri": "http://purl.obolibrary.org/obo/DINTO_10154"
"uri": "http://purl.obolibrary.org/obo/DINTO_10154",
"drug_a": "methylergonovine",
"drug_b": "telithromycin"
}
]
```

### `/ddis`

| | |
|--------------|--------------------------------------------------------------------------------------------------|
| Description | Find all drug-drug interactions (DDI) in the DINTO ontology which involve only the *given* drugs |
| Methods | `POST` |
| Request Body | An object containing a list of *DINTO URIs* |
| Returns | A list of DDI objects; its label, its URI, the identifiers of the two drugs involved, the spacing between dosages required to avoid the DDI (in days) as well as whether or not it is a harmful interaction |
| | |
|--------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Description | Find all drug-drug interactions (DDI) in the DINTO ontology which involve only the *given* drugs |
| Methods | `POST` |
| Request Body | An object containing a list of *DINTO URIs* |
| Returns | A list of DDI objects; its label, its URI, the identifiers of the two drugs involved, the spacing between dosages required to avoid the DDI as well as whether or not it is a harmful interaction and an agonism/antagonism |
| | |

#### Example
##### Request Body
Expand All @@ -101,8 +118,10 @@ Endpoints
"drug_b": "http://purl.obolibrary.org/obo/DINTO_DB00519",
"label": "torasemide/trandolapril DDI",
"uri": "http://purl.obolibrary.org/obo/DINTO_11031",
"harmful": false,
"spacing": 3
"harmful": true,
"spacing": 2,
"unit": "yr",
"agonism": true
}
]
```
Expand Down
15 changes: 12 additions & 3 deletions asclepius/asclepius/dinto.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,19 @@ def drugs(labels=None):
def all_ddis():
return f'''
{PREFIXES}
SELECT ?uri ?label
SELECT ?drug_a ?drug_b ?uri ?label
WHERE {{
?uri rdfs:subClassOf {DDI}.
?uri rdfs:label ?label
?drug_a_uri rdfs:label ?drug_a.
?drug_b_uri rdfs:label ?drug_b.
?uri rdfs:label ?label.
?uri rdfs:subClassOf {DDI} .
?uri owl:equivalentClass ?equivalance .
?equivalance owl:intersectionOf ?restrictions .
?restrictions rdf:first ?drug1Restriction .
?restrictions rdf:rest ?tail .
?tail rdf:first ?drug2Restriction .
?drug1Restriction owl:someValuesFrom ?drug_a_uri .
?drug2Restriction owl:someValuesFrom ?drug_b_uri .
}}
'''

Expand Down
86 changes: 80 additions & 6 deletions asclepius/asclepius/enrich.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,82 @@
def enrich(ddis):
def _enrich(ddi):
result = {'harmful': bool(hash(ddi['uri']) % 2),
'spacing': abs(hash(ddi['uri']))%14 + 1}
result.update(ddi)
return result
from hashlib import sha1
import csv
import sys
import dinto
import clize
import socket
import time
from clize.parameters import one_of

UNITS_INTERVAL = {
'sec': 60,
'min': 60,
'hr': 24,
'day': 7,
'week': 52,
'yr': 5,
}


def _sha_int(string):
return int(sha1(string.encode()).hexdigest()[-8:], 16)


def _enrich(ddi):
uri = ddi['uri']
sha = _sha_int(uri)
unit = tuple(UNITS_INTERVAL.keys())[sha % len(UNITS_INTERVAL)]
result = {
'harmful': bool(sha % 2),
'spacing': sha % UNITS_INTERVAL[unit] + 1,
'unit': unit,
'agonism': bool(_sha_int(''.join(sorted(uri))) % 2),
}

result.update(ddi)
return result


def enrich(ddis):
return [_enrich(ddi) for ddi in ddis]


def main(flavour: one_of('harmful', 'agonism')):
fieldnames = ('Drug 1', 'Drug 2', 'DDI Type', 'Time', 'Unit')

writer = csv.DictWriter(sys.stdout, fieldnames=fieldnames,
lineterminator='\n')
writer.writeheader()

for ddi in enrich(dinto.all_ddis()):
ddi['Drug 1'] = ddi['drug_a']
ddi['Drug 2'] = ddi['drug_b']
ddi['Time'] = ddi['spacing']
ddi['Unit'] = ddi['unit']

if flavour == 'harmful':
ddi['DDI Type'] = 'bad' if ddi[flavour] else 'good'
if flavour == 'agonism':
ddi['DDI Type'] = 'agonism' if ddi[flavour] else 'antagonism'

writer.writerow({k: ddi[k] for k in fieldnames})


def block_until_chiron():
goes = 10
while goes:
try:
sock = socket.socket()
time.sleep(1)
sock.connect(('chiron', 3030))
except Exception:
goes -= 1
continue
else:
return

sys.exit(1)


if __name__ == '__main__':
block_until_chiron()
clize.run(main)
3 changes: 3 additions & 0 deletions asclepius/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,6 @@ py==1.4.32
pytest==3.0.6
requests==2.13.0
Werkzeug==0.11.15
clize==3.1.0
sigtools==2.0.1
six==1.10.0
6 changes: 3 additions & 3 deletions athloi/features/file_upload.feature
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,9 @@ Feature: File upload
And I should see "2" in the warning number badge
And I should see the following warnings in the clashes panel:
| action clash1 on line 2 |
| action clash1 on line 8 |
| action clash2 on line 4 |
| action clash2 on line 6 |
| action clash1 on line 9 |
| action clash2 on line 5 |
| action clash2 on line 7 |

Scenario: uploading a binary file
When I select "example.png"
Expand Down
2 changes: 1 addition & 1 deletion athloi/features/fixtures/alternative_non_ddi.pml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
process alternative_non_ddis {
selection {
selection sel1 {
action s1 {
requires { drug { "trandolapril" } }
}
Expand Down
1 change: 1 addition & 0 deletions athloi/features/fixtures/analysis/clashes.pml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
process foo {
action clash1 {
requires { drug { "paracetamol" } }
}
action clash2 {
}
Expand Down
3 changes: 3 additions & 0 deletions athloi/features/fixtures/analysis/unnamed.pml
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
process foo {
task {
action boo {
requires { drug { "paracetamol" } }
}
}
}
2 changes: 1 addition & 1 deletion athloi/features/fixtures/parallel.pml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
process parallel_ddis {
branch {
branch br1 {
action b1 {
requires { drug { "trandolapril" } }
}
Expand Down
4 changes: 2 additions & 2 deletions athloi/features/fixtures/repeated_alternative.pml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
process repeated_alternative_ddis {
iteration {
selection {
iteration it1 {
selection sel1 {
action s1 {
requires { drug { "trandolapril" } }
}
Expand Down
2 changes: 1 addition & 1 deletion chiron/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

This service is an instance
of [Apache Jena Fuseki](https://jena.apache.org/index.html). It stores DINTO's
owl in a triple store and provides a HTTP API for querying the store using
OWL in a triple store and provides a HTTP API for querying the store using
SPARQL.

Asclepius and Panacea depend on this service.
4 changes: 2 additions & 2 deletions doc/BUILDING_MANUALLY.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Building Manually

There are DNS problems when running containers in *Ubuntu* within the *TCD
network*. This can be resolved while on the TCD network by editing the Docker
There are DNS problems when running containers in **Ubuntu** within the **TCD
network**. This can be resolved while on the TCD network by editing the Docker
DNS config.

```bash
Expand Down
Loading

0 comments on commit 0e5cc90

Please sign in to comment.