Skip to content

Commit c169c6b

Browse files
authored
add sample validation page for wetlab (#3213)
* add sample validation page for wetlab * add unit tests for sample validation page * address comments * add comments to sample validation tests * address flake8 feedback
1 parent 17f25ed commit c169c6b

File tree

5 files changed

+132
-1
lines changed

5 files changed

+132
-1
lines changed

qiita_pet/handlers/admin_processing_job.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
from qiita_core.util import execute_as_transaction
1414

1515
from qiita_db.software import Software
16+
from qiita_db.study import Study
1617

1718
from json import dumps
1819

@@ -91,3 +92,40 @@ def get(self):
9192

9293
# return the json in compact form to save transmit size
9394
self.write(dumps(results, separators=(',', ':')))
95+
96+
97+
class SampleValidation(AdminProcessingJobBaseClass):
98+
@coroutine
99+
@execute_as_transaction
100+
def get(self):
101+
self._check_access()
102+
103+
self.render("sample_validation.html", input=True)
104+
105+
@execute_as_transaction
106+
def post(self):
107+
108+
# Get user-inputted qiita id and sample names
109+
qid = self.get_argument("qid")
110+
snames = self.get_argument("snames").split()
111+
112+
# Stripping leading qiita id from sample names
113+
# Example: 1.SKB1.640202 -> SKB1.640202
114+
qsnames = list(Study(qid).sample_template)
115+
for i, qsname in enumerate(qsnames):
116+
if qsname.startswith(qid):
117+
qsnames[i] = qsname.replace(f'{qid}.', "", 1)
118+
119+
# Remove blank samples from sample names
120+
blank = [x for x in snames if x.lower().startswith('blank')]
121+
snames = [x for x in snames if 'blank' not in x.lower()]
122+
123+
# Validate user's sample names against qiita study
124+
qsnames = set(qsnames)
125+
snames = set(snames)
126+
matching = qsnames.intersection(snames)
127+
missing = qsnames.difference(snames)
128+
extra = snames.difference(qsnames)
129+
130+
self.render("sample_validation.html", input=False, matching=matching,
131+
missing=missing, extra=extra, blank=blank)
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
{% extends sitebase.html %}
2+
{% block head %}
3+
<style>
4+
.column {
5+
float: left;
6+
width: 25%;
7+
}
8+
9+
.row:after {
10+
content: "";
11+
display: table;
12+
clear: both;
13+
}
14+
</style>
15+
{% end %}
16+
{% block content %}
17+
<h1>Sample Validation</h1><br>
18+
{% if input %}
19+
<form action="{% raw qiita_config.portal_dir %}/admin/sample_validation/" method="post" id="sample_validation_form">
20+
<label for="qid">Qiita id:</label><br>
21+
<input type="text" id="qid" name="qid"><br>
22+
<label for="snames">Sample names:</label><br>
23+
<textarea id="sname" name="snames"></textarea><br><br>
24+
<input type="submit" value="Submit">
25+
</form>
26+
{% else %}
27+
<div class="row">
28+
<div class="column">
29+
<h2>Matching</h2>
30+
<ul>
31+
{% for sample in matching %}
32+
<li>{{ sample }}</li>
33+
{% end %}
34+
</ul>
35+
</div>
36+
<div class="column">
37+
<h2>Missing</h2>
38+
<ul>
39+
{% for sample in missing %}
40+
<li>{{ sample }}</li>
41+
{% end %}
42+
</ul>
43+
</div>
44+
<div class="column">
45+
<h2>Blank</h2>
46+
<ul>
47+
{% for sample in blank %}
48+
<li>{{ sample }}</li>
49+
{% end %}
50+
</ul>
51+
</div>
52+
<div class="column">
53+
<h2>Extra</h2>
54+
<ul>
55+
{% for sample in extra %}
56+
<li>{{ sample }}</li>
57+
{% end %}
58+
</ul>
59+
</div>
60+
</div>
61+
<form action="{% raw qiita_config.portal_dir %}/admin/sample_validation/" method="get" id="return_to_sample_validation_form">
62+
<input type="submit" value="Validate more samples">
63+
</form>
64+
{% end %}
65+
{% end %}

qiita_pet/templates/sitebase.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,7 @@
383383
<li><a href="{% raw qiita_config.portal_dir %}/admin/error/">View Errors</a></li>
384384
<li><a href="{% raw qiita_config.portal_dir %}/admin/approval/">View Studies awaiting approval</a></li>
385385
<li><a href="{% raw qiita_config.portal_dir %}/admin/portals/studies/">Edit study portal connections</a></li>
386+
<li><a href="{% raw qiita_config.portal_dir %}/admin/sample_validation/">Sample Validation</a></li>
386387
{% end %}
387388
<li><a href="{% raw qiita_config.portal_dir %}/admin/processing_jobs/">Processing Jobs</a></li>
388389
{% else %}

qiita_pet/test/test_admin_processing_job_handlers.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,5 +45,31 @@ def test_get_missing_argument(self):
4545
response.body.decode('ascii'))
4646

4747

48+
class TestSampleValidation(BaseAdminTests):
49+
def test_get(self):
50+
response = self.get('/admin/sample_validation/')
51+
self.assertEqual(response.code, 200)
52+
53+
def test_post(self):
54+
# Check success
55+
post_args = {
56+
'qid': 1,
57+
'snames': 'SKB1.640202 SKB2.640194 BLANK.1A BLANK.1B'
58+
}
59+
response = self.post('/admin/sample_validation/', post_args)
60+
self.assertEqual(response.code, 200)
61+
snames = ['SKB1.640202', 'SKB2.640194', 'BLANK.1A', 'BLANK.1B']
62+
body = response.body.decode('ascii')
63+
for name in snames:
64+
self.assertIn(name, body)
65+
# Check failure: invalid qiita id
66+
post_args = {
67+
'qid': 2,
68+
'snames': 'SKB1.640202 SKB2.640194 BLANK.1A BLANK.1B'
69+
}
70+
response = self.post('/admin/sample_validation/', post_args)
71+
self.assertEqual(response.code, 500)
72+
73+
4874
if __name__ == "__main__":
4975
main()

qiita_pet/webserver.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
ChangeForgotPasswordHandler, ForgotPasswordHandler, UserProfileHandler,
2626
UserMessagesHander, UserJobs)
2727
from qiita_pet.handlers.admin_processing_job import (
28-
AdminProcessingJob, AJAXAdminProcessingJobListing)
28+
AdminProcessingJob, AJAXAdminProcessingJobListing, SampleValidation)
2929
from qiita_pet.handlers.analysis_handlers import (
3030
ListAnalysesHandler, AnalysisSummaryAJAX, SelectedSamplesHandler,
3131
AnalysisDescriptionHandler, AnalysisGraphHandler, CreateAnalysisHandler,
@@ -133,6 +133,7 @@ def __init__(self):
133133
(r"/admin/artifact/", ArtifactAdminAJAX),
134134
(r"/admin/processing_jobs/", AdminProcessingJob),
135135
(r"/admin/processing_jobs/list", AJAXAdminProcessingJobListing),
136+
(r"/admin/sample_validation/", SampleValidation),
136137
(r"/ebi_submission/(.*)", EBISubmitHandler),
137138
# Study handlers
138139
(r"/study/create/", StudyEditHandler),

0 commit comments

Comments
 (0)