diff options
Diffstat (limited to 'gn3/api')
| -rw-r--r-- | gn3/api/general.py | 29 | ||||
| -rw-r--r-- | gn3/api/rqtl2.py | 61 |
2 files changed, 90 insertions, 0 deletions
diff --git a/gn3/api/general.py b/gn3/api/general.py index b984361..fcaf21b 100644 --- a/gn3/api/general.py +++ b/gn3/api/general.py @@ -1,5 +1,6 @@ """General API endpoints. Put endpoints that can't be grouped together nicely here.""" +import os from flask import Blueprint from flask import current_app from flask import jsonify @@ -68,3 +69,31 @@ def run_r_qtl(geno_filestr, pheno_filestr): cmd = (f"Rscript {rqtl_wrapper} " f"{geno_filestr} {pheno_filestr}") return jsonify(run_cmd(cmd)), 201 + + +@general.route("/stream ", methods=["GET"]) +def stream(): + """ + This endpoint streams the stdout content from a file. + It expects an identifier to be passed as a query parameter. + Example: `/stream?id=<identifier>` + The `id` will be used to locate the corresponding file. + You can also pass an optional `peak` parameter + to specify the file position to start reading from. + Query Parameters: + - `id` (required): The identifier used to locate the file. + - `peak` (optional): The position in the file to start reading from. + Returns: + - dict with data(stdout), run_id unique id for file, + pointer last read position for file + """ + run_id = request.args.get("id", "") + output_file = os.path.join(current_app.config.get("TMPDIR"), + f"{run_id}.txt") + seek_position = int(request.args.get("peak", 0)) + with open(output_file) as file_handler: + # read to the last position default to 0 + file_handler.seek(seek_position) + return jsonify({"data": file_handler.readlines(), + "run_id": run_id, + "pointer": file_handler.tell()}) diff --git a/gn3/api/rqtl2.py b/gn3/api/rqtl2.py new file mode 100644 index 0000000..ffa8755 --- /dev/null +++ b/gn3/api/rqtl2.py @@ -0,0 +1,61 @@ +""" File contains endpoints for rqlt2""" + +import subprocess +import uuid +import os +from flask import current_app +from flask import jsonify +from flask import Blueprint +from flask import request + +rqtl2 = Blueprint("rqtl2", __name__) + +@rqtl2.route("/compute", methods=["GET"]) +def compute(): + """Endpoint for computing QTL analysis using R/QTL2""" + # get the run id to act as file identifier default to output + run_id = request.args.get("id", "output") + output_file = os.path.join(current_app.config.get("TMPDIR"), + f"{run_id}.txt") + # this should be computed locally not via files + rscript_cmd = ( + f"Rscript ./scripts/rqtl2_wrapper.R " + f"-i /home/kabui/r_playground/meta_grav.json " + f"-d /home/kabui/r_playground " + f"-o /home/kabui/r_playground/rqtl_output.json " + f"--nperm 100 --threshold 1 --cores 0" + ) + process = subprocess.Popen( + rscript_cmd, shell=True, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT + ) + for line in iter(process.stdout.readline, b""): + # these allow endpoint stream to read the file since + # no read and write file same tiem + with open(output_file, "a+") as file_handler: + file_handler.write(line.decode("utf-8")) + process.stdout.close() + process.wait() + if process.returncode == 0: + return jsonify({"msg": "success", + "results": "file_here", + "run_id": run_id}) + return jsonify({"msg": "fail", + "error": "Process failed", + "run_id": run_id}) + + +@rqtl2.route("/stream/<identifier>", methods=["GET"]) +def stream(identifier="output"): + """ This endpoints streams stdout from a file expects + the indetifier to be the file """ + output_file = os.path.join(current_app.config.get("TMPDIR"), + f"{identifier}.txt") + seek_position = int(request.args.get("peak", 0)) + with open(output_file) as file_handler: + # read to the last position default to 0 + file_handler.seek(seek_position) + return jsonify({"data": file_handler.readlines(), + "run_id": identifier, + "pointer": file_handler.tell()}) |
