diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..acdd4d5 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,12 @@ +FROM openjdk:8-jdk as buildContainer + +RUN apt-get update +RUN apt-get install -y maven + +WORKDIR /opt/app +COPY . /opt/app + +RUN chmod +x ./make.sh +RUN bash ./make.sh + +CMD bash \ No newline at end of file diff --git a/README.md b/README.md index c6e00ea..3a06723 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ target/lychi-0.5.1-jar-with-dependencies.jar The self-contained jar file can be invoked directly. For example: ``` -java -jar target/lychi-0.5.1-jar-with-dependencies.jar tests/standardizer_case1.smi +java -jar target/lychi-0.7.1-jar-with-dependencies.jar tests/standardizer_case1.smi ``` diff --git a/api/api.py b/api/api.py new file mode 100644 index 0000000..d17b068 --- /dev/null +++ b/api/api.py @@ -0,0 +1,55 @@ +from flask import Flask, request, jsonify, render_template +import subprocess +import tempfile +import os + +lychify = Flask("lychify") + +@lychify.route('/') +def index(): + return render_template('index.html') + +@lychify.route('/standardize', methods=['POST']) +def standardize(): + # Get the list of SMILES objects from the request + smiles_list = request.json['smiles_list'] + counter = 0 + if len(smiles_list) == 0: + return jsonify({'result': []}) + # Write the SMILES objects to a temporary file + with tempfile.NamedTemporaryFile(delete=False, mode='w') as f: + for obj in smiles_list: + if ("id" in obj): + f.write(obj['smiles'] + '\t' + str(obj['id']) + '\n') + else: + counter += 1 + f.write(obj["smiles"] + '\t' + "no_id:" + str(counter) + '\n') + filepath = f.name + + # Create the command to call the Java application with the input file + command = ['java', '-jar', 'lychi-0.7.1-jar-with-dependencies.jar', filepath] + + # Call the Java application using subprocess + process = subprocess.run(command, capture_output=True, text=True) + + # Remove the temporary file + os.remove(filepath) + + # Check if the command completed successfully + if process.returncode != 0: + return jsonify({'error': 'Failed to run Java application', + 'output': process.stdout.strip().split('\n')}) + + # Parse the output from the Java application and format the response + output = process.stdout.strip().split('\n') + formatted_output = [] + for i, line in enumerate(output): + smiles, id, lychi = line.split('\t') + formatted_output.append({'smiles': smiles, 'id': id, 'lychi': lychi}) + + # Return the formatted output as a JSON response + return jsonify({'result': formatted_output}) + + +if __name__ == '__main__': + lychify.run(debug=True) diff --git a/api/lychi-0.7.1-jar-with-dependencies.jar b/api/lychi-0.7.1-jar-with-dependencies.jar new file mode 100644 index 0000000..9389281 Binary files /dev/null and b/api/lychi-0.7.1-jar-with-dependencies.jar differ diff --git a/api/templates/index.html b/api/templates/index.html new file mode 100644 index 0000000..49594fb --- /dev/null +++ b/api/templates/index.html @@ -0,0 +1,18 @@ + + + + lychify + + +

Welcome to lychify!

+

This is a web service to calculate lychi keys for any given chemical structure. See the repo here: https://github.com/ncats/lychi.

+

To use this application, send a POST request to /standardize with a JSON payload containing a list of SMILES strings. The response will contain a JSON payload with the standardized SMILES strings.

+

Here's an example payload:

+
{
+  "smiles_list": [
+    {"smiles": "CCO", "id": "1"},
+    {"smiles": "COC", "id": "2"}
+  ]
+}
+ + diff --git a/api/testapi.py b/api/testapi.py new file mode 100644 index 0000000..3699780 --- /dev/null +++ b/api/testapi.py @@ -0,0 +1,31 @@ +import requests + +url = 'http://localhost:5000/standardize' + +response = requests.post(url, json={'smiles_list': []}) +print (response.json()) + +long_smiles = "".join(['C' for i in range(10)]) +response = requests.post(url, json={'smiles_list': [{"smiles": long_smiles}]}) +print(response.json()) + +invalid_list = [ + {'smiles':'invalid','id':'1'}, + {'smiles':'SMILES','id':'2'}, + {'smiles':'strings','id':'3'} +] +response = requests.post(url, json={'smiles_list': invalid_list}) +print(response.json()) # Should return an error message or an empty result + +duplicate_list = [ + {"smiles": "C", "id": "1"}, + {"smiles": "CC", "id": "2"}, + {"smiles": "C", "id": "3"}, + {"smiles": "CCC", "id": "4"} +] +response = requests.post(url, json={'smiles_list': duplicate_list}) +print(response.json()) + +aminophylline = [{"smiles":"Cn1c2nc[nH]c2c(=O)n(C)c1=O", "id": "aminophylline"}] +response = requests.post(url, json={'smiles_list': aminophylline}) +print(response.json()) diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..88786f3 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,7 @@ +version: '3' +services: + dev: + build: + context: . + dockerfile: Dockerfile + tty: true \ No newline at end of file