Skip to content

Commit 1715bf2

Browse files
authored
MRG: more upgrades! (#16)
* add basic uptime script * fix bugs, add/adjust language * add some upload tests * upd gitignore * upd testing mode * bump version
1 parent 23b5d20 commit 1715bf2

File tree

8 files changed

+120
-11
lines changed

8 files changed

+120
-11
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,5 @@
66
*.rocksdb
77
chill_filter.egg-info/
88
dist/
9+
build/
10+
chill-data/

chill_filter_web/__init__.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@
1919

2020
default_settings = dict(
2121
UPLOAD_FOLDER = os.path.join(os.path.dirname(__file__), '../chill-data'),
22-
EXAMPLES_DIR = os.path.join(os.path.dirname(__file__), "examples/")
22+
EXAMPLES_DIR = os.path.join(os.path.dirname(__file__), "examples/"),
23+
MAX_CONTENT_LENGTH = 10*1000*1000,
2324
)
2425

2526

@@ -66,6 +67,8 @@ def create_app():
6667
### actual Web site stuff
6768
###
6869

70+
71+
# handles default index, plus upload of precalculated sketch.
6972
@app.route("/", methods=["GET", "POST"])
7073
def index():
7174
if request.method == "POST":
@@ -95,28 +98,33 @@ def index():
9598
return render_template("index.html")
9699

97100

101+
# handles client-side sketch w/JSON sig
98102
@app.route("/sketch", methods=["GET", "POST"])
99103
def sketch():
100104
if request.method == "POST":
101105
# check if the post request has the file part
102106
if "signature" not in request.form:
103-
flash("No file part")
107+
flash("No file part") # @CTB
104108
return redirect(request.url)
105109

106110
# take uploaded file and save
107111
sig_json = request.form["signature"]
108112
success = False
109113
filename = f"t{int(time.time())}.sig.gz"
110-
outpath = os.path.join(UPLOAD_FOLDER, filename)
114+
outpath = os.path.join(app.config['UPLOAD_FOLDER'], filename)
111115
with gzip.open(outpath, "wt") as fp:
112116
fp.write(f"[{sig_json}]")
113117

114118
ss = load_sig(outpath)
115119
if ss:
116120
# success? build URL & redirect
117121
md5 = ss.md5sum()[:8]
122+
if app.config['TESTING']:
123+
return "TESTING MODE: upload successful"
118124
return redirect(f"/{md5}/{filename}/search")
119125

126+
print('fallthru')
127+
120128
# default: redirect to /
121129
return redirect(url_for("index"))
122130

chill_filter_web/templates/guide.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
{% filter markdownify %}
99
# The chill-filter user guide
1010

11+
[Home page](/) | [Frequently Asked questions](/faq)
12+
1113
chill-filter is a rapid sample-screening Web application that comprehensively
1214
determines the composition of a shotgun sequence data set. It should take
1315
about 10 seconds to process an uploaded sample.
@@ -20,7 +22,7 @@ You could use it to:
2022

2123
chill-filter will sensitively detect the presence of large genomes
2224
(500kb and up) at sequencing depths as low as 0.1x. It searches your entire
23-
sample: it does not select a subset of the data set.
25+
sample: it does not select a subset of your data.
2426

2527
The main value of chill-filter is that it is fast, sensitive, and
2628
_comprehensive_. Within the limits of the available reference database,
@@ -38,7 +40,7 @@ data sets (ChIP-seq or ATAC-seq) or RNA data.
3840
**<font style="color:red">chill-filter is a research service and should not be relied upon for
3941
clinical diagnostics or confirmatory analyses.</font>**
4042

41-
## What does chill-filter aim to do?
43+
## What are chill-filter's goals?
4244

4345
chill-filter aims to be a sensitive, specific, and comprehensive
4446
approach to figuring out what is in your sample. It will always

chill_filter_web/templates/index.html

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,12 @@
88
<img src="/static/alembic-small.jpg" align="right">
99
<h2 style="margin: 10px">chill-filter: What's in my sample?</h2>
1010
<p style="margin: 10px">
11-
Quite fast sample screening.
11+
Quite fast sample screening - see <a href="/guide">user guide</a> and <A href="#examples">examples</a>.
12+
<hr style="border-width: 3px; border-color: black">
1213
</p>
1314

1415
<h4>
15-
Choose a large genome or shotgun sequencing FASTA/FASTQ file, and click submit to compress it and send it for screening!
16+
Choose a large genome or shotgun sequencing FASTA/FASTQ file, and click submit to compress and screen it!
1617
</h4>
1718

1819
<div style="margin: 50px">
@@ -45,7 +46,8 @@ <h4>
4546
<hr style="border-width: 3px; border-color: black">
4647

4748
<main class="container">
48-
<h4>Examples:</h4>
49+
<a id="examples"></a>
50+
<h4>Examples:</h4>
4951
<ul>
5052
<li><a href="/example?filename=SRR606249.k51.s100_000.sig.zip">SRR606249: A mock microbial community</a>
5153
<li><a href="/example?filename=SRR5650070.k51.s100_000.sig.zip">SRR5650070: A human gut metagenome from the iHMP</a>

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
name = "chill-filter"
33
description = "rapid sample screening for shotgun DNA sequencing data sets"
44
readme = "README.md"
5-
version = "0.3.0"
5+
version = "0.3.1"
66
authors = [
77
{ name="C. Titus Brown" },
88
]

scripts/check-site.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#! /usr/bin/env python
2+
import sys
3+
import argparse
4+
import requests
5+
6+
7+
def main():
8+
p = argparse.ArgumentParser()
9+
p.add_argument('--host', default='https://chill-filter.sourmash.bio')
10+
args = p.parse_args()
11+
12+
url = args.host + '/'
13+
print('getting:', url)
14+
r = requests.get(url)
15+
assert r.status_code == 200
16+
assert '<title>chill-filter sample screening - home page</title>' in r.text
17+
18+
url = args.host + '/example?filename=SRR606249.k51.s100_000.sig.zip'
19+
print('getting:', url)
20+
r = requests.get(url)
21+
assert r.status_code == 200, r.status_code
22+
assert '95.0% (5.1 Gbp)' in r.text
23+
24+
url = args.host + '/ee6adb3e/SRR606249.k51.s100_000.sig.zip/delete'
25+
print('getting:', url)
26+
r = requests.get(url)
27+
assert r.status_code == 200, r.status_code
28+
29+
url = args.host + '/example?filename=SRR606249.k51.s100_000.sig.zip'
30+
print('getting:', url)
31+
r = requests.get(url)
32+
assert r.status_code == 200
33+
assert '95.0% (5.1 Gbp)' in r.text
34+
35+
36+
if __name__ == '__main__':
37+
sys.exit(main())

tests/test_basic.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,5 +118,3 @@ def test_sample_download_csv(client):
118118
data = response.get_data()
119119
print(data)
120120
assert data.startswith(b'intersect_bp,f_orig_query,f_match,')
121-
122-

tests/test_upload.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import os
2+
import shutil
3+
import json
4+
5+
import pytest
6+
7+
import sourmash
8+
from chill_filter_web import utils
9+
10+
11+
def test_sample_upload_precalc(app):
12+
# test upload of precalculated sketch via POST to /
13+
#
14+
# NOTE: this does not actually run the search, since there is a precalc
15+
# .csv in the test upload directory.
16+
with app.app_context():
17+
client = app.test_client()
18+
19+
sigfile = os.path.join(app.config['EXAMPLES_DIR'],
20+
'Bu5.abund.k51.s100_000.sig.zip')
21+
22+
form_d = dict(sketch=(open(sigfile, 'rb'),
23+
'Bu5.abund.k51.s100_000.sig.zip',
24+
'application/zip'))
25+
26+
response = client.post('/', data=form_d,
27+
follow_redirects=True)
28+
29+
30+
print(response.data)
31+
assert b'18.5% unknown' in response.data
32+
33+
34+
def test_sample_upload_sketch(app):
35+
# test upload of client-side sketch via POST to /sketch
36+
#
37+
# uses testing mode to avoid running the actual search.
38+
with app.app_context():
39+
client = app.test_client()
40+
41+
sigfile = os.path.join(app.config['EXAMPLES_DIR'],
42+
'no-matches.sig.zip')
43+
ss = utils.load_sig(sigfile)
44+
assert ss
45+
46+
sig_json = sourmash.save_signatures_to_json([ss])
47+
48+
# this returns an array, and the upload needs a single encoded
49+
# signature. So pull off the first element and re-encode.
50+
sig2 = json.loads(sig_json)
51+
sig2 = sig2[0]
52+
sig2_json = json.dumps(sig2)
53+
54+
# submit!
55+
form_d = dict(signature=sig2_json)
56+
response = client.post('/sketch', data=form_d,
57+
follow_redirects=True)
58+
59+
print(response.data)
60+
assert b'TESTING MODE: upload successful'

0 commit comments

Comments
 (0)