Commit 40c030b9 authored by Davide Lagoa's avatar Davide Lagoa
Browse files

manager ready

parent 77b4c658
Pipeline #487 failed with stages
......@@ -3,6 +3,5 @@ RUN mkdir /configs
COPY ./configs /configs
COPY ./code /home
WORKDIR /workdir
RUN pip install neo4j-driver==1.3.1
EXPOSE 80
CMD ["python", "/home/workersManager.py"]
......@@ -9,7 +9,6 @@ import logging
import re
import time
import requests
from transyt_request import database_retriever_by_id
CONFIGURATIONS = FilesUtilities.read_conf_file('/configs/docker_config.conf')
......@@ -56,51 +55,42 @@ def after_request(response):
@app.route("/")
def index():
logger.info('Welcome page rendering...')
return render_template("home.html")
logger.info('Welcome page...')
@app.route("/submit", methods=["POST"])
def submit():
logger.info('HTML submission')
logger.info('New submission')
files = request.files.getlist("file")
taxonomyId = request.form["text"]
validInput = verifyInput(taxonomyId)
option = request.form["option"]
dbs = str(request.form["database"])
ontologies = str(request.form["ontologies"])
choices = request.form["choices"]
if not validInput:
return jsonify({"Genome": "Input genome must be in .faa or .fasta format",
"Model": "Model must be in .xml format or a list of metabolites in .txt format (one metabolite per line)",
"Taxonomy ID": "Input must only contain digits"}), 406
eValue = request.form["eValue"]
return run(files, taxonomyId, dbs, ontologies, False)
bitScore = request.form["bitScore"]
queryCoverage = request.form["queryCoverage"]
@app.route("/submitMerlinPlugin/<taxonomyId>/<dbs>/<ontologies>", methods=["POST"])
def submitMerlinPlugin(taxonomyId, dbs, ontologies):
return run(files, option, choices, eValue, bitScore, queryCoverage, False)
@app.route("/submitMerlinPlugin/<option>/<choices>", methods=["POST"])
def submitMerlinPlugin(taxonomyId, option, choices):
logger.info('Merlin plugin submission')
files = request.files.getlist("file")
logger.info("files in submission " + str(files))
validInput = verifyInput(taxonomyId)
if not validInput:
return jsonify({"Genome": "Input genome must be in .faa or .fasta format",
"Model": "Model must be in .xml format or a list of metabolites in .txt format (one metabolite per line)",
"Taxonomy ID": "Input must only contain digits"}), 406
return run(files, option, choices, True)
return run(files, taxonomyId, dbs, ontologies, True)
def run(files, taxonomyId, dbs, ontologies, isRest):
def run(files, option, choices, eValue, bitScore, queryCoverage, isRest):
logger.info('New submission in progress...')
logger.info("Taxonomy identifier: " + taxonomyId)
logger.info("Database: " + dbs)
logger.info("Ontologies: " + ontologies)
logger.info("Option: " + option)
logger.info("Choices: " + choices)
total = len(os.listdir(SUBMISSIONS_PATH))
......@@ -123,10 +113,10 @@ def run(files, taxonomyId, dbs, ontologies, isRest):
logger.debug("Submission " + str(last_submission_ID) + " folder created!")
inputCheck = []
for file in files:
formats = {".faa": "genome.faa", ".fasta": "genome.faa", ".xml": "model.xml"}
formats = {".faa": "queryGenome.faa", ".fasta": "queryGenome.faa"}
fileName = file.filename
inFormats = False
......@@ -136,47 +126,33 @@ def run(files, taxonomyId, dbs, ontologies, isRest):
inFormats = True
inputCheck.append(formats[key])
if not inFormats and "genome.faa" in inputCheck and fileName.endswith(".txt"):
fileName = "metabolites.txt"
inputCheck.append("metabolites.txt")
destination = "/".join([submission_path, fileName])
logger.debug('Saving file ' + fileName + ' at ' + destination)
file.save(destination)
validInput = ["genome.faa", "model.xml"]
validInput2 = ["genome.faa", "metabolites.txt"]
validInputs = [validInput, validInput2]
validInputs = [["queryGenome.faa"]]
logger.info("taxID -> " + taxonomyId)
logger.info("option -> " + option)
logger.info("inputCheck -> " + str(inputCheck))
# taxonomy = taxonomy + '#' + dbs + '#' + ontologies
# with open("/".join([submission_path, "databases.txt"]), "w") as dbsFile:
# dbsFile.write(dbs) # write databases file
# with open("/".join([submission_path, "ontologies.txt"]), "w") as ontoFile:
# ontoFile.write(ontologies) # write ontologies file
if inputCheck in validInputs:
with open("/".join([submission_path, "params.txt"]), "w") as paramsFile:
paramsFile.write(taxonomyId + "\n") # write TaxonomyID to file
paramsFile.write(dbs + "\n") # write databases to file
paramsFile.write(ontologies) # write ontologies to file
paramsFile.write(option + "\n") # write option to file
paramsFile.write(choices + "\n") # write choices to file
paramsFile.write(eValue + "\n") # write eValue to file
paramsFile.write(bitScore + "\n") # write bitScore to file
paramsFile.write(queryCoverage + "\n") # write queryCoverage to file
else:
return jsonify({"Genome": "Input genome must be in .faa or .fasta format",
"Model": "Model must be in .xml format or a list of metabolites in .txt format (one metabolite per line)",
"Taxonomy ID": "Input must only contain digits"}), 415
return jsonify({"Genome": "Input genome must be in .faa or .fasta format"}), 415
with open(submission_path + "/submissionComplete", "w") as f:
f.write("Submission of files complete: ")
if len(os.listdir(submission_path)) < 4:
if len(os.listdir(submission_path)) < 1:
shutil.rmtree(submission_path)
return jsonify({"result": "rejected",
"message": "fewer files than needed submitted! Submission rejected!", }), 400
"message": "Needed file not submitted! Submission rejected!", }), 400
if isRest:
return jsonify({"result": "submitted",
......@@ -184,7 +160,6 @@ def run(files, taxonomyId, dbs, ontologies, isRest):
"queue": total,
"submissionID": str(last_submission_ID)}), 201
# return render_template("status.html", subId = str(last_submission_ID))
return display_msg(str(last_submission_ID), isRest)
......@@ -210,11 +185,6 @@ def display_msg(submissionID, isRest):
"message": "Waiting in queue with " + str(total + 1) + " submissions!",
"queue": str(inQueue)}), 201
subStatus = {"result": "queued",
"message": "Waiting in queue",
"queue": "There are " + str(inQueue) + " submissions ahead of yours"}
return render_template("status.html", subId=submissionID, status=subStatus)
folders = os.listdir(PROCESSING_PATH)
logger.info("processing " + str(folders))
......@@ -224,9 +194,6 @@ def display_msg(submissionID, isRest):
if isRest:
return jsonify({"result": "processing", "message": "accepted but process still running, please wait."}), 202
subStatus = {"result": "processing", "message": "accepted but process still running, please wait."}
return render_template("status.html", subId=submissionID, status=subStatus), 202
folders = os.listdir(RESULTS_PATH)
logger.info("results " + str(folders))
......@@ -257,9 +224,6 @@ def display_msg(submissionID, isRest):
{"result": result,
"message": message}), code
# return download(submissionID)
return render_template("download.html", subId=submissionID), 200
return jsonify({"result": "Server error",
"message": "Something went wrong while processing the request, please try again", }), 500
......@@ -359,58 +323,13 @@ def getWorkersLogs(savePath):
logger.debug("Logs not retrieved. Response code: " + str(response.status_code))
else:
logger.debug("Worker " + host + " not alive!")
@app.route('/reactions/<reactionId>')
def reactions(reactionId):
pattern = re.compile("^T[A-Z]\d{7}")
patternFound = bool(pattern.match(reactionId))
if patternFound:
results_dict = result_parser(reactionId)
if results_dict:
return render_template("record.html", subId=reactionId, dictt=results_dict), 200
return render_template("noresutls.html", subId=reactionId), 200
@app.template_filter('enumerate_items')
def enumerate_items(*args, **kwargs):
return enumerate(*args, **kwargs)
def result_parser(id):
url = CONFIGURATIONS["database"]
user = CONFIGURATIONS["dbusername"]
password = CONFIGURATIONS["dbpassword"]
databases, tc_systems, reactionID, metaID, reaction, metabolites = database_retriever_by_id(id, url, user, password)
if not metabolites:
return None
tc_systems2 = {}
for tc in tc_systems:
tc_elements = tc.split('@')
if tc_elements[0] in tc_systems2:
tc_systems2[tc_elements[0]].append(tc_elements[1])
else:
tc_systems2[tc_elements[0]] = [tc_elements[1]]
res_dict = {'databases': databases,
'tc_systems': tc_systems2,
'reactionID': reactionID,
'metaID': metaID,
'reaction': reaction,
'metabolites': metabolites}
return res_dict
def countEntriesBelow(l, id):
id = int(id)
res = 0
......@@ -422,22 +341,6 @@ def countEntriesBelow(l, id):
return res
def verifyInput(userInput):
userInput = str(userInput)
validTaxID = False
if userInput:
validTaxID = True
digits = "0123456789"
for character in userInput:
if character not in digits:
validTaxID = False
return validTaxID
logger.info('Server running!')
if __name__ == "__main__":
......
from neo4j.v1 import GraphDatabase
class neo4jPythonDriver:
###### CONSTRUCTOR ######
def __init__(self, uri, user, password):
self.__uri = uri
self.__user = user
self.__password = password
self.__driver = self.__initDriver()
def __initDriver(self):
return GraphDatabase.driver(self.__getUri(), auth=(self.__getUser(), self.__getPassword()))
def initSession(self):
return self.__driver.session()
def __getUri(self):
return self.__uri
def __getUser(self):
return self.__user
def __getPassword(self):
return self.__password
def __getDriver(self):
return self.__driver
def __setUri(self, value):
self.__uri = value
def __setUser(self, value):
self.__user = value
def __setPassword(self, value):
self.__password = value
def __setDriver(self, value):
self.__driver = value
#aspect-content {
margin: 10px 10px 0px 10px;
font-family: 'Oxygen';
}
.tab-element {
position: relative;
width: 90%;
margin: 0 auto 10px;
border-radius: 4px;
background-color: #ffffff;
box-shadow: 3px -1px 5px 3px #bdc3c7;
opacity: 1;
transition: box-shadow .2s, opacity .4s;
}
.tab-element:hover {
box-shadow: 0 4px 10px 0 rgba(0, 0, 0, .11);
}
.inner-tab-element {
position: relative;
width: 100%;
border-radius: 4px;
background-color: #34495e;
box-shadow: 3px -1px 5px 3px #bdc3c7;
opacity: 1;
transition: box-shadow .2s, opacity .4s;
}
.inner-tab-element:hover {
box-shadow: 0 4px 10px 0 rgba(0, 0, 0, .11);
}
.outer-input {
display: none;
}
.inner-input {
display: none;
}
.outer-input:checked ~ .outer-label-content + .dropdown-content-outer-wrapper {
max-height: 8000px;
}
.outer-input:checked ~ .outer-label-content:after {
transform: rotate(0);
}
.inner-input:checked ~ .outer-label-content + .dropdown-content-outer-wrapper {
max-height: 8000px;
}
.inner-input:checked ~ .outer-label-content:after {
transform: rotate(0);
}
.outer-input:checked ~ .inner-label-content + .dropdown-content-outer-wrapper {
max-height: 8000px;
}
.outer-input:checked ~ .inner-label-content:after {
transform: rotate(0);
}
.inner-input:checked ~ .inner-label-content + .dropdown-content-outer-wrapper {
max-height: 8000px;
}
.inner-input:checked ~ .inner-label-content:after {
transform: rotate(0);
}
.outer-label {
position: absolute;
top: 0;
left: 0;
height: 100%;
max-height: 50px;
width: 100%;
margin: 0;
padding: 0;
font-size: 0;
z-index: 1;
cursor: pointer;
}
.inner-label {
position: absolute;
top: 0;
left: 0;
height: 100%;
max-height: 50px;
width: 100%;
margin: 0;
padding: 0;
font-size: 0;
z-index: 1;
cursor: pointer;
}
.outer-label-content {
position: relative;
display: block;
height: 50px;
margin: 0;
padding: 0;
font-size: 0;
white-space: nowrap;
cursor: pointer;
}
.outer-label-content:before {
content: '';
display: inline-block;
vertical-align: middle;
height: 100%;
}
.outer-label-content:after {
content: '';
display: inline-block;
vertical-align: middle;
position: absolute;
width: 24px;
height: 100%;
right: 30px;
background-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICAgIDxnIGZpbGw9Im5vbmUiIGZpbGwtcnVsZT0iZXZlbm9kZCI+CiAgICAgICAgPHBhdGggZD0iTTI0IDI0SDBWMGgyNHoiIG9wYWNpdHk9Ii44NyIvPgogICAgICAgIDxwYXRoIGZpbGw9IiNBOUFDQUYiIGZpbGwtcnVsZT0ibm9uemVybyIgZD0iTTE1Ljg4IDE1LjI5TDEyIDExLjQxbC0zLjg4IDMuODhhLjk5Ni45OTYgMCAxIDEtMS40MS0xLjQxbDQuNTktNC41OWEuOTk2Ljk5NiAwIDAgMSAxLjQxIDBsNC41OSA0LjU5Yy4zOS4zOS4zOSAxLjAyIDAgMS40MS0uMzkuMzgtMS4wMy4zOS0xLjQyIDB6Ii8+CiAgICA8L2c+Cjwvc3ZnPgo=');
background-repeat: no-repeat;
background-position: center;
transform: rotate(180deg);
}
.outer-label-content + .dropdown-content-outer-wrapper {
max-height: 0;
overflow: hidden;
transition: max-height .3s;
}
.outer-label-content > div {
display: inline-block;
vertical-align: middle;
}
.inner-label-content {
position: relative;
display: block;
height: 50px;
margin: 0;
padding: 0;
font-size: 0;
white-space: nowrap;
cursor: pointer;
}
.inner-label-content:before {
content: '';
display: inline-block;
vertical-align: middle;
height: 100%;
}
.inner-label-content:after {
content: '';
display: inline-block;
vertical-align: middle;
position: absolute;
width: 24px;
height: 100%;
right: 30px;
background-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICAgIDxnIGZpbGw9Im5vbmUiIGZpbGwtcnVsZT0iZXZlbm9kZCI+CiAgICAgICAgPHBhdGggZD0iTTI0IDI0SDBWMGgyNHoiIG9wYWNpdHk9Ii44NyIvPgogICAgICAgIDxwYXRoIGZpbGw9IiNBOUFDQUYiIGZpbGwtcnVsZT0ibm9uemVybyIgZD0iTTE1Ljg4IDE1LjI5TDEyIDExLjQxbC0zLjg4IDMuODhhLjk5Ni45OTYgMCAxIDEtMS40MS0xLjQxbDQuNTktNC41OWEuOTk2Ljk5NiAwIDAgMSAxLjQxIDBsNC41OSA0LjU5Yy4zOS4zOS4zOSAxLjAyIDAgMS40MS0uMzkuMzgtMS4wMy4zOS0xLjQyIDB6Ii8+CiAgICA8L2c+Cjwvc3ZnPgo=');
background-repeat: no-repeat;
background-position: center;
transform: rotate(180deg);
}
.inner-label-content + .dropdown-content-outer-wrapper {
max-height: 0;
overflow: hidden;
transition: max-height .3s;
}
.inner-label-content > div {
display: inline-block;
vertical-align: middle;
}
.aspect-info {
width: 100%;
white-space: nowrap;
font-size: 0;
}
.aspect-info:before {
content: '';
display: inline-block;
vertical-align: middle;
}
.aspect-name {
display: inline-block;
width: 33%;
max-height: 22px;
color: #000000;
text-align: left;
vertical-align: middle;
font-size: 16px;
margin: 0 0 0 20px;
}
.aspect-name > p {
display: inline-block;
font-size: 16px;
}
.aspect-name > a {
display: inline-block;
}
.dropdown-content-outer-wrapper {
background-color: #ecf0f1;
font-size: 0;
text-align: justify;
}
.inner-tab-element-wrapper {
padding: 10px 10px 10px 10px;
}
.inner-inner-tab-element-wrapper {
padding: 10px 10px 10px 10px;
display: flex;
flex-wrap: wrap;
}
.inner-inner-tab-element-wrapper > div {
display: inline-block;
width: 100%;
height: 100%;
flex: 0 0 20%
}
.inner-inner-tab-element-wrapper > div > div {
width: 100%;
height: 100%;
padding: 10px 10px 10px 10px;
background-color: #ecf0f1;
text-align: left;
}
.content {
position: relative;
width: 100%;
font-size: 13px;
color: #2c3e50;
}
.external-links-button {
display: inline-block;
background: none;
padding: 10px;
margin: 10px;
cursor:pointer;