Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prevent the single-node tree check from yielding "false positives" on linear trees; also fix the build #48

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 0 additions & 22 deletions .travis.yml

This file was deleted.

4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
libbitarr.a:
cd BitArray && $(MAKE)
make -C BitArray -f Makefile
cd bp/BitArray && $(MAKE)
make -C bp/BitArray -f Makefile
ElDeveloper marked this conversation as resolved.
Show resolved Hide resolved

build: libbitarr.a
python setup.py build_ext --inplace
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
Improved Octo Waddle
--------------------

[![Improved Octo Waddle CI](https://github.com/biocore/improved-octo-waddle/actions/workflows/python-package-conda.yml/badge.svg)](https://github.com/biocore/improved-octo-waddle/actions/workflows/python-package-conda.yml)

An implementation of the balanced parentheses tree structure as described by
[Cordova and Navarro](http://www.dcc.uchile.cl/~gnavarro/ps/tcs16.2.pdf).

Expand Down
1 change: 0 additions & 1 deletion bp/GPL/tests/test_insert.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,3 @@ def test_insert_multifurcating(self):

if __name__ == '__main__':
unittest.main()

6 changes: 3 additions & 3 deletions bp/_io.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -148,16 +148,16 @@ cpdef parse_newick(unicode data):
np.ndarray[np.double_t, ndim=1] lengths
np.ndarray[np.int32_t, ndim=1] edges

if data.count(',') == 0:
raise ValueError("Only trees with more than 1 node supported")

data = data.strip()
if not data.endswith(';'):
raise ValueError("Newick does not appear terminated with a semicolon")

datalen = len(data)
topology = _newick_to_bp(data)

if len(topology.B) <= 1:
raise ValueError("Only trees with more than 1 node supported")

names = np.full(len(topology.B), None, dtype=object)
lengths = np.zeros(len(topology.B), dtype=np.double)
edges = np.full(len(topology.B), 0, dtype=np.int32)
Expand Down
13 changes: 9 additions & 4 deletions bp/_version.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

# This file helps to compute a version number in source trees obtained from
# git-archive tarball (such as those provided by githubs download-from-tag
# feature). Distribution tarballs (built by setup.py sdist) and build
Expand Down Expand Up @@ -339,7 +338,9 @@ def git_pieces_from_vcs(tag_prefix, root, verbose, runner=run_command):
pieces["distance"] = int(count_out) # total number of commits

# commit date: see ISO-8601 comment in git_versions_from_keywords()
date = runner(GITS, ["show", "-s", "--format=%ci", "HEAD"], cwd=root)[0].strip()
date = runner(
GITS, ["show", "-s", "--format=%ci", "HEAD"], cwd=root
)[0].strip()
# Use only the last line. Previous lines may contain GPG signature
# information.
date = date.splitlines()[-1]
Expand Down Expand Up @@ -429,10 +430,14 @@ def render_pep440_pre(pieces):
if pieces["closest-tag"]:
if pieces["distance"]:
# update the post release segment
tag_version, post_version = pep440_split_post(pieces["closest-tag"])
tag_version, post_version = pep440_split_post(
pieces["closest-tag"]
)
rendered = tag_version
if post_version is not None:
rendered += ".post%d.dev%d" % (post_version+1, pieces["distance"])
rendered += ".post%d.dev%d" % (
post_version+1, pieces["distance"]
)
else:
rendered += ".post0.dev%d" % (pieces["distance"])
else:
Expand Down
2 changes: 1 addition & 1 deletion bp/tests/test_conv.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def setUp(self):
self.sktn = skbio.TreeNode.read(StringIO(self.tstr))

def test_to_skbio_treenode_with_edge_numbers(self):
# from https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0031009
# from https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0031009 # noqa
# but without edge labels
# 0 1 2 3 4 5 6 7 8 9
# 1 1 1 0 1 0 0 1 0 0
Expand Down
6 changes: 5 additions & 1 deletion bp/tests/test_insert.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@

class InsertTests(unittest.TestCase):
package = 'bp.tests'

def setUp(self):
self.jplacedata_multiple = \
open(self.get_data_path('300/placement_mul.jplace')).read()
self.final_multiple_fully_resolved = \
skbio.TreeNode.read(self.get_data_path('300/placement.full_resolve.newick'))
skbio.TreeNode.read(
self.get_data_path('300/placement.full_resolve.newick')
)

def get_data_path(self, filename):
# adapted from qiime2.plugin.testing.TestPluginBase
Expand Down Expand Up @@ -51,5 +54,6 @@ def test_insert_fully_resolved_multiple_placements(self):
self.assertEqual(obs.compare_rfd(exp), 0)
self.assertAlmostEqual(obs.compare_tip_distances(exp), 0)


if __name__ == '__main__':
unittest.main()
22 changes: 19 additions & 3 deletions bp/tests/test_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,13 @@

class NewickTests(TestCase):
def test_parse_newick_simple_edge_numbers(self):
# from https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0031009
# from https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0031009 # noqa
# but without edge labels
# 0 1 2 3 4 5 6 7 8 9
# 1 1 1 0 1 0 0 1 0 0
in_ = '((A:.01{0}, B:.01{1})D:.01{3}, C:.01{4}) {5};'
exp_sk = '((A:.01, B:.01)D:.01, C:.01);' # skbio doesn't know about edge numbers
# skbio doesn't know about edge numbers
exp_sk = '((A:.01, B:.01)D:.01, C:.01);'
obs = parse_newick(in_)
obs_sk = to_skbio_treenode(obs)
exp_sk = skbio.TreeNode.read([exp_sk])
Expand Down Expand Up @@ -82,6 +83,21 @@ def test_parse_newick_singlenode_bug(self):
with self.assertRaises(ValueError):
parse_newick(test)

def test_parse_newick_linear_tree(self):
# https://github.com/biocore/improved-octo-waddle/pull/48
test = '((b:3)a:2)root:1;'

# Test that we can parse these edge cases successfully, without
# mistaking them for single-node trees
topology = parse_newick(test)

# Convert the tree to a skbio TreeNode to make checking easier
skbio_tree = to_skbio_treenode(topology)
self.assertEqual(skbio_tree.name, "root")
self.assertEqual([n.name for n in skbio_tree.children], ["a"])
self.assertEqual([n.name for n in skbio_tree.non_tips()], ["a"])
self.assertEqual([n.name for n in skbio_tree.tips()], ["b"])

def test_parse_newick_no_semicolon_bug(self):
# https://github.com/wasade/improved-octo-waddle/issues/26
test = "((h:1, i:1, j:1, k:1, l: 1),(e:1,f:1),(n:1,o:1,p:1))a:1"
Expand All @@ -96,7 +112,7 @@ def test_parse_newick_no_semicolon_bug(self):
def test_write_newick_underscore_bug(self):
test = "(((a)b)'c_foo',((d)e)f)r;"
buf = io.StringIO()
obs = write_newick(parse_newick(test), buf, False)
write_newick(parse_newick(test), buf, False)
buf.seek(0)
self.assertIn("'c_foo'", test)

Expand Down