Skip to content

Commit ed20ab9

Browse files
committed
Merge branch 'release/0.6.1'
2 parents 5a9a8bd + b7ec60d commit ed20ab9

8 files changed

Lines changed: 109 additions & 73 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
1212

1313
### Fixed
1414

15+
## [0.6.1] - 2019-10-10
16+
17+
### Fixed
18+
19+
- Fixed bug with get_track_type.
20+
1521
## [0.6.0] - 2019-09-11
1622

1723
### Added

genomepy/__about__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
"""Metadata"""
2-
__version__ = '0.6.0'
2+
__version__ = '0.6.1'
33
__author__ = "Simon van Heeringen"

genomepy/functions.py

Lines changed: 70 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import random
66
import re
77
import subprocess as sp
8+
from collections.abc import Iterable
89

910
from appdirs import user_config_dir
1011
from pyfaidx import Fasta, Sequence
@@ -31,9 +32,7 @@ def manage_config(cmd, *args):
3132
with open(config.config_file) as f:
3233
print(f.read())
3334
elif cmd == "generate":
34-
fname = os.path.join(
35-
user_config_dir("genomepy"), "{}.yaml".format("genomepy")
36-
)
35+
fname = os.path.join(user_config_dir("genomepy"), "{}.yaml".format("genomepy"))
3736

3837
if not os.path.exists(user_config_dir("genomepy")):
3938
os.makedirs(user_config_dir("genomepy"))
@@ -62,8 +61,7 @@ def list_available_genomes(provider=None):
6261
providers = [ProviderBase.create(provider)]
6362
else:
6463
# if provider is not specified search all providers
65-
providers = [ProviderBase.create(p) for
66-
p in ProviderBase.list_providers()]
64+
providers = [ProviderBase.create(p) for p in ProviderBase.list_providers()]
6765

6866
for p in providers:
6967
for row in p.list_available_genomes():
@@ -113,12 +111,10 @@ def list_installed_genomes(genome_dir=None):
113111
if not genome_dir:
114112
genome_dir = config.get("genome_dir", None)
115113
if not genome_dir:
116-
raise norns.exceptions.ConfigError(
117-
"Please provide or configure a genome_dir")
114+
raise norns.exceptions.ConfigError("Please provide or configure a genome_dir")
118115
genome_dir = os.path.expanduser(genome_dir)
119116

120-
return [f for f in os.listdir(genome_dir) if
121-
_is_genome_dir(genome_dir + "/" + f)]
117+
return [f for f in os.listdir(genome_dir) if _is_genome_dir(genome_dir + "/" + f)]
122118

123119

124120
def search(term, provider=None):
@@ -146,16 +142,24 @@ def search(term, provider=None):
146142
providers = [ProviderBase.create(provider)]
147143
else:
148144
# if provider is not specified search all providers
149-
providers = [ProviderBase.create(p) for
150-
p in ProviderBase.list_providers()]
145+
providers = [ProviderBase.create(p) for p in ProviderBase.list_providers()]
151146
for p in providers:
152147
for row in p.search(term):
153-
yield [x.encode('latin-1') for x in [p.name] + list(row)]
154-
155-
156-
def install_genome(name, provider, version=None, genome_dir=None,
157-
localname=None, mask="soft", regex=None, invert_match=False,
158-
annotation=False, bgzip=None):
148+
yield [x.encode("latin-1") for x in [p.name] + list(row)]
149+
150+
151+
def install_genome(
152+
name,
153+
provider,
154+
version=None,
155+
genome_dir=None,
156+
localname=None,
157+
mask="soft",
158+
regex=None,
159+
invert_match=False,
160+
annotation=False,
161+
bgzip=None,
162+
):
159163
"""
160164
Install a genome.
161165
@@ -195,8 +199,7 @@ def install_genome(name, provider, version=None, genome_dir=None,
195199
if not genome_dir:
196200
genome_dir = config.get("genome_dir", None)
197201
if not genome_dir:
198-
raise norns.exceptions.ConfigError(
199-
"Please provide or configure a genome_dir")
202+
raise norns.exceptions.ConfigError("Please provide or configure a genome_dir")
200203

201204
genome_dir = os.path.expanduser(genome_dir)
202205
localname = get_localname(name, localname)
@@ -211,12 +214,12 @@ def install_genome(name, provider, version=None, genome_dir=None,
211214
localname=localname,
212215
regex=regex,
213216
invert_match=invert_match,
214-
bgzip=bgzip)
217+
bgzip=bgzip,
218+
)
215219

216220
if annotation:
217221
# Download annotation from provider
218-
p.download_annotation(
219-
name, genome_dir, localname=localname, version=version)
222+
p.download_annotation(name, genome_dir, localname=localname, version=version)
220223

221224
g = Genome(localname, genome_dir=genome_dir)
222225

@@ -227,11 +230,10 @@ def install_genome(name, provider, version=None, genome_dir=None,
227230

228231

229232
def get_track_type(track):
230-
region_p = re.compile(r'^(.+):(\d+)-(\d+)$')
231-
if isinstance(track, []):
232-
if region_p.search(track[0]):
233+
region_p = re.compile(r"^(.+):(\d+)-(\d+)$")
234+
if not isinstance(track, (str, bytes)) and isinstance(track, Iterable):
235+
if isinstance(track[0], (str, bytes)) and region_p.search(track[0]):
233236
return "interval"
234-
235237
with open(track) as fin:
236238
line = fin.readline().strip()
237239
if region_p.search(line):
@@ -252,7 +254,9 @@ def _weighted_selection(l, n):
252254
cuml.append(total_weight)
253255
items.append(item)
254256

255-
return [items[bisect.bisect(cuml, random.random()*total_weight)] for _ in range(n)]
257+
return [
258+
items[bisect.bisect(cuml, random.random() * total_weight)] for _ in range(n)
259+
]
256260

257261

258262
def generate_exports():
@@ -262,7 +266,7 @@ def generate_exports():
262266
for name in list_installed_genomes():
263267
try:
264268
g = Genome(name)
265-
env_name = re.sub(r'[^\w]+', "_", name).upper()
269+
env_name = re.sub(r"[^\w]+", "_", name).upper()
266270
env.append("export {}={}".format(env_name, g.filename))
267271
except Exception:
268272
pass
@@ -327,40 +331,44 @@ def __init__(self, name, genome_dir=None):
327331
super(Genome, self).__init__(name)
328332
self.name = os.path.basename(name)
329333
except Exception:
330-
if (os.path.isdir(name) and
331-
len(glob_fa_files(name)) == 1 and
332-
genome_dir is not None):
334+
if (
335+
os.path.isdir(name)
336+
and len(glob_fa_files(name)) == 1
337+
and genome_dir is not None
338+
):
333339
fname = glob_fa_files(name)[0]
334340
name = os.path.basename(fname)
335341
else:
336342
if not genome_dir:
337343
genome_dir = config.get("genome_dir", None)
338344
if not genome_dir:
339345
raise norns.exceptions.ConfigError(
340-
"Please provide or configure a genome_dir")
346+
"Please provide or configure a genome_dir"
347+
)
341348
genome_dir = os.path.expanduser(genome_dir)
342-
349+
343350
if not os.path.exists(genome_dir):
344351
raise FileNotFoundError(
345352
"genome_dir {} does not exist".format(genome_dir)
346353
)
347354

348-
fnames = glob_fa_files(os.path.join(
349-
genome_dir, name.replace('.gz', '')))
355+
fnames = glob_fa_files(
356+
os.path.join(genome_dir, name.replace(".gz", ""))
357+
)
350358
if len(fnames) == 0:
351359
raise FileNotFoundError(
352360
"no *.fa files found in genome_dir {}".format(
353361
os.path.join(genome_dir, name)
354362
)
355363
)
356364
elif len(fnames) > 1:
357-
fname = os.path.join(
358-
genome_dir, name, "{}.fa".format(name))
365+
fname = os.path.join(genome_dir, name, "{}.fa".format(name))
359366
if fname not in fnames:
360367
fname += ".gz"
361368
if fname not in fnames:
362369
raise Exception(
363-
"More than one FASTA file found, no {}.fa!".format(name))
370+
"More than one FASTA file found, no {}.fa!".format(name)
371+
)
364372
else:
365373
fname = fnames[0]
366374

@@ -406,8 +414,7 @@ def _bed_to_seqs(self, track, stranded=False, extend_up=0, extend_down=0):
406414
starts = [int(x) for x in vals[11].split(",")[:-1]]
407415
sizes = [int(x) for x in vals[10].split(",")[:-1]]
408416
starts = [start + x for x in starts]
409-
ends = [start + size for start,
410-
size in zip(starts, sizes)]
417+
ends = [start + size for start, size in zip(starts, sizes)]
411418
name = "{}:{}-{}".format(chrom, start, end)
412419
try:
413420
name = " ".join((name, vals[3]))
@@ -461,18 +468,18 @@ def _region_to_seqs(self, track, extend_up=0, extend_down=0):
461468

462469
lines = fin.readlines(BUFSIZE)
463470

464-
def track2fasta(self, track, fastafile=None, stranded=False, extend_up=0,
465-
extend_down=0):
471+
def track2fasta(
472+
self, track, fastafile=None, stranded=False, extend_up=0, extend_down=0
473+
):
466474
track_type = get_track_type(track)
467475
if track_type == "interval":
468476
seqqer = self._region_to_seqs(
469-
track, extend_up=extend_up, extend_down=extend_down)
477+
track, extend_up=extend_up, extend_down=extend_down
478+
)
470479
else:
471480
seqqer = self._bed_to_seqs(
472-
track,
473-
stranded=stranded,
474-
extend_up=extend_up,
475-
extend_down=extend_down)
481+
track, stranded=stranded, extend_up=extend_up, extend_down=extend_down
482+
)
476483

477484
if fastafile:
478485
with open(fastafile, "w") as fout:
@@ -497,8 +504,7 @@ def gap_sizes(self):
497504
for line in f:
498505
chrom, start, end = line.strip().split("\t")
499506
start, end = int(start), int(end)
500-
self._gap_sizes[chrom] = self._gap_sizes.get(
501-
chrom, 0) + end - start
507+
self._gap_sizes[chrom] = self._gap_sizes.get(chrom, 0) + end - start
502508
return self._gap_sizes
503509

504510
def get_random_sequences(self, n=10, length=200, chroms=None, max_n=0.1):
@@ -532,11 +538,15 @@ def get_random_sequences(self, n=10, length=200, chroms=None, max_n=0.1):
532538
gap_sizes = self.gap_sizes()
533539
except Exception:
534540
gap_sizes = {}
535-
sizes = dict([(chrom, len(self[chrom]) - gap_sizes.get(chrom, 0))
536-
for chrom in chroms])
541+
sizes = dict(
542+
[(chrom, len(self[chrom]) - gap_sizes.get(chrom, 0)) for chrom in chroms]
543+
)
537544

538-
lengths = [(sizes[x], x) for x in chroms if
539-
sizes[x] / len(self[x]) > 0.1 and sizes[x] > 10 * length]
545+
lengths = [
546+
(sizes[x], x)
547+
for x in chroms
548+
if sizes[x] / len(self[x]) > 0.1 and sizes[x] > 10 * length
549+
]
540550
chroms = _weighted_selection(lengths, n)
541551
coords = []
542552

@@ -556,7 +566,8 @@ def get_random_sequences(self, n=10, length=200, chroms=None, max_n=0.1):
556566
break
557567
if count_n > cutoff:
558568
raise ValueError(
559-
"Failed to find suitable non-N sequence for {}".format(chrom))
569+
"Failed to find suitable non-N sequence for {}".format(chrom)
570+
)
560571

561572
coords.append([chrom, start, end])
562573

@@ -583,8 +594,11 @@ def manage_plugins(command, plugin_names=None):
583594
elif command == "list":
584595
print("{:20}{}".format("plugin", "enabled"))
585596
for plugin in sorted(plugins):
586-
print("{:20}{}".format(
587-
plugin, {False: "", True: "*"}[plugin in active_plugins]))
597+
print(
598+
"{:20}{}".format(
599+
plugin, {False: "", True: "*"}[plugin in active_plugins]
600+
)
601+
)
588602
else:
589603
raise ValueError("Invalid plugin command")
590604
config["plugin"] = active_plugins

tests/data/regions.bed

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
chr1 10 20
2+
chr2 20 30

tests/data/regions.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
chr1:10-20
2+
chr2:20-30

tests/test_annotation.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ def test_ensembl_annotation():
6262
tmp = mkdtemp()
6363
p = genomepy.provider.ProviderBase.create("Ensembl")
6464

65-
for name, version in [("GRCh38.p12", 92)]:
65+
for name, version in [("GRCh38.p13", 98)]:
6666
p.download_annotation(name, tmp, localname=name)
6767

6868
gtf = os.path.join(tmp, name, name + ".annotation.gtf.gz")

tests/test_genomepy.py

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,19 @@ def test_no_fasta_files():
2929
genomepy.Genome("empty", "tests/data/genome")
3030

3131

32+
def test_track_type():
33+
tracks = [
34+
(("chr1:10-20", "chr2:10-20"), "interval"),
35+
(["chr1:10-20", "chr2:10-20"], "interval"),
36+
("tests/data/regions.txt", "interval"),
37+
("tests/data/regions.bed", "bed"),
38+
]
39+
40+
for track, track_type in tracks:
41+
result = genomepy.functions.get_track_type(track)
42+
assert result == track_type
43+
44+
3245
@pytest.mark.parametrize("bgzip", [True, False])
3346
def test_ucsc_genome(bgzip):
3447
"""Test UCSC.
@@ -43,6 +56,7 @@ def test_ucsc_genome(bgzip):
4356
assert str(seq) == "TTTGGTTGTTCCTCTTCCTT"
4457
shutil.rmtree(tmp)
4558

59+
4660
# 2019-05-08 BDGP6 currently fails on Ensembl
4761
@pytest.mark.xfail()
4862
def test_ensembl_genome():
@@ -66,19 +80,19 @@ def test_ensembl_genome_download_links():
6680
"""
6781
p = genomepy.provider.ProviderBase.create("Ensembl")
6882

69-
for genome in ['WBcel235', "GRCz11", "GRCh38.p12"]:
83+
for genome in ["GRCz11", "GRCh38.p13"]:
7084
p.get_genome_download_link(genome)
7185

72-
@pytest.mark.skipif(travis,
73-
reason="FTP does not work on Travis")
86+
87+
@pytest.mark.skipif(travis, reason="FTP does not work on Travis")
7488
def test_ensemblgenomes_genome_download_links():
7589
"""Test Ensembl FTP links for various genomes
7690
7791
These genomes are hosted on ftp.ensemblgenomes.org.
7892
"""
7993
p = genomepy.provider.ProviderBase.create("Ensembl")
8094

81-
for genome in ['AgamP4', 'WBcel235', 'R64-1-1']:
95+
for genome in ["AgamP4", "WBcel235", "R64-1-1"]:
8296
p.get_genome_download_link(genome)
8397

8498

@@ -100,18 +114,16 @@ def test_regexp_filter():
100114
fname = "tests/data/regexp/regexp.fa"
101115

102116
regexps = [
103-
('Chr.*', 2, 15),
104-
('Scaffold.*', 1, 16),
105-
('scaffold_.*', 3, 14),
106-
(r'^\d+$', 4, 13),
107-
('chr.*', 4, 13),
117+
("Chr.*", 2, 15),
118+
("Scaffold.*", 1, 16),
119+
("scaffold_.*", 3, 14),
120+
(r"^\d+$", 4, 13),
121+
("chr.*", 4, 13),
108122
]
109123

110124
tmpfa = NamedTemporaryFile(suffix=".fa").name
111125
for regex, match, no_match in regexps:
112-
fa = genomepy.utils.filter_fasta(
113-
fname, tmpfa, regex=regex, v=False, force=True)
126+
fa = genomepy.utils.filter_fasta(fname, tmpfa, regex=regex, v=False, force=True)
114127
assert len(fa.keys()) == match
115-
fa = genomepy.utils.filter_fasta(
116-
fname, tmpfa, regex=regex, v=True, force=True)
128+
fa = genomepy.utils.filter_fasta(fname, tmpfa, regex=regex, v=True, force=True)
117129
assert len(fa.keys()) == no_match

0 commit comments

Comments
 (0)