-
Notifications
You must be signed in to change notification settings - Fork 0
/
website.py
384 lines (274 loc) · 13.1 KB
/
website.py
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
from flask import Flask, render_template, url_for, request, send_file, flash, make_response, redirect, Markup
from flask_paginate import Pagination, get_page_parameter
from flask_caching import Cache
from settings import *
from io import StringIO
import csv
import json
import mediator
app = Flask(__name__)
# Used by "flash" for flashing comments or errors
app.secret_key = b'_5#y2L"F4Q8z\n\xec]/'
# tell Flask to use the config (defined in settings.py)
app.config.from_mapping(CACHE_CONFIG)
cache = Cache(app)
def run(**kwargs):
"""When called it starts the website"""
app.run(**kwargs)
@app.route('/')
def homepage():
"""A webpage which explains briefly the project and allows you to download the datasets or to go through them"""
return render_template('homepage.html')
@app.route('/download', methods=['POST'])
def download():
"""Allows to download the table computed as tsv file.
Steps:
1) Get what_to_download to know the name by which the table is stored in the cache. It will also be
the name of the file. If for some reason it can't find it, it flashes a popup and redirect to the previous page
2) Get the table from the cache. If the data is None, it's likely that the cache has exceeded the timout
defined in the config.py. You need to reload the page to compute again the table
3) Extract from "data_to_save" which is a dictionary the rows and the labels of the table
4) A csv.writer is instantiated. It needs StringIO
5) Write as the first row the labels of the columns, then write all the rows
6) Make a response which allows the .tsv file to be downloaded
7) Set some information of the file that will be downloaded like its name and filetype
"""
# Step 1)
name_file = request.form.get('name_file')
if name_file is None:
flash('Error in downloading the table, please try reloading the page.')
return redirect(request.referrer)
# Step 2)
data_to_save = cache.get(TABLE_CACHE_NAME)
if data_to_save is None:
flash('Timeout Error, please try reloading the page.')
# Step 3)
rows = data_to_save['rows']
labels = [data_to_save['labels']]
# Step 4)
si = StringIO()
cw = csv.writer(si, delimiter='\t')
# Step 5)
cw.writerows(labels)
cw.writerows(rows)
# Step 6)
output = make_response(si.getvalue())
# Step 7)
output.headers["Content-Disposition"] = f"attachment; filename={name_file}.tsv"
output.headers["Content-type"] = "text/tsv"
return output
@app.route('/tableGenesEvidences/', methods=['GET', 'POST'])
def genesTable():
"""A webpage which lets you go through gene data table.
To do the pagination it uses Pagination() from flask-paginate"""
# variables
gene_info, _ = mediator.getInfo()
nrows = gene_info['nrows']
per_page = 30
# Get the page from the form to let the user go to a specific page
page = int(request.args.get(get_page_parameter(), type=int, default=1))
if page < 1:
flash('You need to insert a positive number!')
# start and end index of the table
start = page * per_page
end = (page + 1) * per_page
# Returns a list of the rows from index start to index end
df_list = mediator.getGeneTableList(start, end)
# Prepares the pagination that allows you to click the number of the page and view it
pagination = Pagination(page=page, total=nrows, record_name="gene entries",
css_framework='bootstrap4', per_page=per_page)
return render_template('tableGenesEvidences.html',
rows=df_list,
labels=gene_info['labels'],
pagination=pagination)
@app.route('/tableDiseasesEvidences/')
def diseasesTable():
"""A webpage which lets you go through gene data table.
To do the pagination it uses Pagination() from flask-paginate"""
# variables
_, disease_info = mediator.getInfo()
nrows = disease_info['nrows']
per_page = 30
# Get the page from the form to let the user go to a specific page
# The value of "page" is taken with functions from flask-paginate otherwise it raises errors
page = int(request.args.get(get_page_parameter(), type=int, default=1))
if page < 1:
flash('You need to insert a positive number!')
# start and end index of the table
start = page * per_page
end = (page + 1) * per_page
# Returns a list of the rows from index start to index end
df_list = mediator.getDiseaseTableList(start, end)
# Prepares the pagination that allows you to click the number of the page and view it
pagination = Pagination(page=page, total=nrows, record_name="diseases entries",
css_framework='bootstrap4', bs_version=4, per_page=per_page)
return render_template('tableDiseasesEvidences.html',
labels=disease_info['labels'],
rows=df_list,
pagination=pagination)
@app.route('/downloadDiseases')
def diseasesTableDownload():
"""Let the user download the file"""
from os import path
# Compute the path to the databases
disease_evidences_path = path.join(DATASET_LOCATION, DISEASE_TABLE_NAME)
return send_file(disease_evidences_path, as_attachment=True)
@app.route('/downloadGenes')
def genesTableDownload():
"""Let the user download the file"""
from os import path
# Compute the path to the databases
gene_evidences_path = path.join(DATASET_LOCATION, GENE_TABLE_NAME)
return send_file(gene_evidences_path, as_attachment=True)
@app.route('/documentation', defaults={'file': 'homepage'})
@app.route('/documentation/<file>')
def documentation(file):
"""A webpage with the documentation of the project"""
docs = mediator.getDocumentation()
return render_template('documentation/%s.html' % file, docs=docs)
@app.route('/about')
def about():
"""A webpage with the member of the group"""
return render_template('about.html')
@app.route('/functions')
def functions():
"""A webpage which lets you select the operation you want to do with the datasets"""
return render_template('functions.html')
# for a and b objective
@app.route('/info')
def info():
"""Returns a webpage with all the information about the data tables and a preview of heads and tails"""
gene_data, disease_data = mediator.getInfo()
return render_template('operations/info.html', gene_data=gene_data, disease_data=disease_data)
# for c objective
@app.route('/distinctGenes')
def distinctGenes():
"""A webpage with all the unique distinct genes in the gene table"""
NAME_FUNCTION = 'distinct_genes'
data = mediator.getDistinctGenes()
cache.set(TABLE_CACHE_NAME, data)
return render_template('operations/distinctGenes.html', data=data, NAME_FUNCTION=NAME_FUNCTION)
# for e objective
@app.route('/distinctDiseases')
def distinctDiseases():
"""A webpage with all the unique distinct disease in the disease table"""
NAME_FUNCTION = 'distinct_diseases'
data = mediator.getDistinctDiseases()
cache.set(TABLE_CACHE_NAME, data)
return render_template('operations/distinctDiseases.html', data=data, NAME_FUNCTION=NAME_FUNCTION)
# for d objective
@app.route('/geneEvidences', methods=["POST", "GET"])
def geneEvidences():
"""The first time the user access "geneEvidences" it is requested with 'GET' method.
Then it returns a webpage which lets the user input a geneSymbol or a geneID.
It is then submitted back to "geneEvidences" but with 'POST' method.
Now it returns a webpage which lists all the evidences in literature of the gene"""
NAME_FUNCTION = '_evidences'
if request.method == "GET":
return render_template('operations/inputGeneEvidences.html')
else:
gene = request.form['gene']
data = mediator.getGeneEvidences(gene)
cache.set(TABLE_CACHE_NAME, data)
return render_template("operations/geneEvidences.html", gene=gene, data=data, NAME_FUNCTION=NAME_FUNCTION,
base_pmid_url=BASE_PMID_URL)
# for f objective
@app.route('/diseaseEvidences', methods=["POST", "GET"])
def diseaseEvidences():
"""The first time the user access "diseaseEvidences" it is requested with 'GET' method.
Then it returns a webpage which lets the user input a diseaseID or a diseaseName.
It is then submitted back to "diseaseEvidences" but with 'POST' method.
Now it returns a webpage which lists all the evidences in literature of the disease"""
NAME_FUNCTION = '_evidences'
if request.method == "GET":
return render_template('operations/inputDiseaseEvidences.html')
else:
disease = request.form['disease']
data = mediator.getDiseaseEvidences(disease)
cache.set(TABLE_CACHE_NAME, data)
return render_template('operations/diseaseEvidences.html', disease=disease, data=data,
base_pmid_url=BASE_PMID_URL, NAME_FUNCTION=NAME_FUNCTION)
# for g objective
@app.route('/correlation', methods=["POST", "GET"])
def correlation():
"""The webpage lists the correlations between genes and diseases.
It allows th user to customize the results, he can decide the number of correlations to show ("rows")
and the minimum number of occurrences a correlation need to have to be shown ("occurrences").
Occurrences ha priority over rows. In fact, if "occurrence" is given and the user hasn't written
anything in "rows" then it sets "rows" to 0 which means that all rows will be returned.
Also, if the user wants 50 rows, but the rows which meet the occurrence requirement are 30,
only 30 rows will be returned.
"""
# This is for the first time the user visits the page
if request.method == "GET":
nrows = 10
occurrences = 0
else:
try:
occurrences = request.form['occurrence']
occurrences = int(occurrences)
if occurrences < 0:
occurrences = 0
except ValueError:
# If it raise ValueError it means "occurrence" it's a string which cannot be converted to a number.
# It's either an empty string or a word. If it's an empty string it sets "occurrences" to the default value
if occurrences != '':
flash('You need to insert a number!')
return redirect(request.referrer)
else:
occurrences = 0
try:
nrows = request.form['rows']
nrows = int(nrows)
if nrows < 0:
flash('You need to insert a positive number!')
return redirect(request.referrer)
except ValueError:
# If it raise ValueError it means it's a string which cannot be converted to a number.
# It's either an empty string or a word. If it's an empty string it set "nrows" to the default value
if nrows != '':
flash('You need to insert a number!')
return redirect(request.referrer)
else:
if occurrences != 0:
nrows = 0
else:
nrows = 10
data = mediator.getCorrelation(nrows, occurrences)
NAME_FUNCTION = 'correlation'
cache.set(TABLE_CACHE_NAME, data)
return render_template('operations/correlation.html', data=data, NAME_FUNCTION=NAME_FUNCTION)
# for h objective
@app.route('/diseasesRelatedToGene', methods=["POST", "GET"])
def diseasesRelatedToGene():
"""The first time the user access "diseasesRelatedToGene" it is requested with 'GET' method.
Then it returns a webpage which lets the user input a geneSymbol or a geneID.
It is then submitted back to "diseasesRelatedToGene" but with 'POST' method.
Now it returns a webpage which lists all the diseases related to the gene found in literature"""
NAME_FUNCTION = 'diseases_rel_to_'
if request.method == "GET":
return render_template('operations/inputDiseasesRelatedToGene.html')
else:
gene = request.form['gene']
data = mediator.getDiseasesRelatedToGene(gene)
cache.set(TABLE_CACHE_NAME, data)
return render_template("operations/diseasesRelatedToGene.html", gene=gene, data=data, NAME_FUNCTION=NAME_FUNCTION)
# for i objective
@app.route('/genesRelatedToDisease', methods=["POST", "GET"])
def genesRelatedToDisease():
"""The first time the user access "genesRelatedToDisease" it is requested with 'GET' method.
Then it returns a webpage which lets the user input a diseaseName or a diseaseID.
It is then submitted back to "genesRelatedToDisease" but with 'POST' method.
Now it returns a webpage which lists all the genes related to the disease found in literature"""
NAME_FUNCTION = 'genes_rel_to_'
if request.method == "GET":
return render_template('operations/inputGenesRelatedToDisease.html')
else:
disease = request.form['disease']
data = mediator.getGenesRelatedToDisease(disease)
cache.set(TABLE_CACHE_NAME, data)
return render_template("operations/genesRelatedToDisease.html", data=data, disease=disease,
NAME_FUNCTION=NAME_FUNCTION)
if __name__ == '__main__':
import mediator
app.run(debug=True)