1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
"Handle inserting data into the database"
import os
import json
from functools import reduce
import requests
from redis import Redis
from MySQLdb.cursors import DictCursor
from flask import request, Blueprint, render_template, current_app as app
from . import jobs
from .db_utils import database_connection
dbinsertbp = Blueprint("dbinsert", __name__)
def render_error(error_msg):
"Render the generic error page"
return render_template("dbupdate_error.html", error_message=error_msg), 400
def make_menu_items_grouper(grouping_fn=lambda item: item):
"Build function to be used to group menu items."
def __grouper__(acc, row):
grouping = grouping_fn(row[2])
row_values = (row[0].strip(), row[1].strip())
if acc.get(grouping) is None:
return {**acc, grouping: (row_values,)}
return {**acc, grouping: (acc[grouping] + (row_values,))}
return __grouper__
def genechips():
"Retrieve the genechip information from the database"
def __organise_by_species__(acc, chip):
species = chip["species_name"]
if acc.get(species) is None:
return {**acc, species: (chip,)}
return {**acc, species: acc[species] + (chip,)}
with database_connection() as conn:
with conn.cursor(cursorclass=DictCursor) as cursor:
cursor.execute(
"SELECT GeneChip.*, LOWER(Species.Name) AS species_name "
"FROM GeneChip INNER JOIN Species "
"ON GeneChip.SpeciesId=Species.SpeciesId")
return reduce(__organise_by_species__, cursor.fetchall(), {})
return {}
@dbinsertbp.route("/select-dataset", methods=["POST"])
def select_dataset():
"Select the dataset to add the file contents against"
job_id = request.form["job_id"]
with Redis.from_url(app.config["REDIS_URL"], decode_responses=True) as rconn:
job = jobs.job(rconn, job_id)
if job:
filename = job["filename"]
filepath = f"{app.config['UPLOAD_FOLDER']}/{filename}"
if os.path.exists(filepath):
req = requests.get(
"https://genenetwork.org/api3/api/menu/generate/json")
menu_contents = req.json()
default_species = "mouse"
mouse_groups = reduce(
make_menu_items_grouper(
lambda item: item.strip()[7:].strip()),
menu_contents["groups"][default_species], {})
default_group = "BXD"
group_types = reduce(
make_menu_items_grouper(),
menu_contents["types"][default_species][default_group], {})
default_type = group_types[tuple(group_types)[0]][0][0]
datasets = menu_contents[
"datasets"][default_species][default_group][
default_type]
gchips = genechips()
return render_template(
"select_dataset.html", filename=filename,
species=menu_contents["species"],
default_species=default_species, groups=mouse_groups,
types=group_types, datasets=datasets,
menu_contents=json.dumps(menu_contents),
genechips_data=json.dumps(gchips),
genechips=gchips.get(default_species, []),
filetype=job["filetype"])
return render_error(f"File '{filename}' no longer exists.")
return render_error(f"Job '{job_id}' no longer exists.")
return render_error("Unknown error")
@dbinsertbp.route("/insert_data", methods=["POST"])
def insert_data():
"Preview the data before triggering entry into the database"
form = request.form
filename = form["filename"]
filepath = f"{app.config['UPLOAD_FOLDER']}/{filename}"
if os.path.exists(filepath):
try:
species = form["species"]
filetype = form["filetype"]
datasetid = int(form["dataset"])
genechipid = int(form["genechipid"])
return (f"Would insert '{species}' data in '{filetype}' file "
f"'{filepath}' into the database with the dataset "
f"'{datasetid}' and genechip '{genechipid}'.")
except ValueError as ve:
msg = "::".join(ve.args)
return render_error(f"Invalid value: {msg}")
return render_error(f"File '{filename}' no longer exists.")
|