[med-svn] [Git][med-team/q2-diversity-lib][upstream] New upstream version 2022.2.1

Andreas Tille (@tille) gitlab at salsa.debian.org
Tue Jul 19 16:42:57 BST 2022



Andreas Tille pushed to branch upstream at Debian Med / q2-diversity-lib


Commits:
47fa3781 by Andreas Tille at 2022-07-19T17:36:43+02:00
New upstream version 2022.2.1
- - - - -


15 changed files:

- .github/workflows/ci.yml
- LICENSE
- Makefile
- ci/recipe/meta.yaml
- q2_diversity_lib/__init__.py
- q2_diversity_lib/_util.py
- q2_diversity_lib/_version.py
- q2_diversity_lib/alpha.py
- q2_diversity_lib/beta.py
- q2_diversity_lib/plugin_setup.py
- q2_diversity_lib/tests/__init__.py
- q2_diversity_lib/tests/test_alpha.py
- q2_diversity_lib/tests/test_beta.py
- q2_diversity_lib/tests/test_util.py
- setup.py


Changes:

=====================================
.github/workflows/ci.yml
=====================================
@@ -1,14 +1,10 @@
-# This file is automatically generated by busywork.qiime2.org and
-# template-repos - any manual edits made to this file will be erased when
-# busywork performs maintenance updates.
-
 name: ci
 
 on:
   pull_request:
   push:
     branches:
-      - master
+      - 2022.2-patches
 
 jobs:
   lint:
@@ -50,6 +46,6 @@ jobs:
     - uses: qiime2/action-library-packaging at alpha1
       with:
         package-name: q2-diversity-lib
-        build-target: dev
+        build-target: release
         additional-tests: py.test --pyargs q2_diversity_lib
         library-token: ${{ secrets.LIBRARY_TOKEN }}


=====================================
LICENSE
=====================================
@@ -1,6 +1,6 @@
 BSD 3-Clause License
 
-Copyright (c) 2018-2021, QIIME 2 development team.
+Copyright (c) 2018-2022, QIIME 2 development team.
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without


=====================================
Makefile
=====================================
@@ -5,6 +5,7 @@ PYTHON ?= python
 all: ;
 
 lint:
+	q2lint
 	flake8
 
 test: all


=====================================
ci/recipe/meta.yaml
=====================================
@@ -18,18 +18,16 @@ requirements:
 
   run:
     - python {{ python }}
-    - biom-format >=2.1.5,<2.2.0
+    - biom-format {{ biom_format }}
     - decorator
-    # Inherit global hard pin
-    - hdf5 {{ hdf5 }}
     - numpy
-    - pandas
+    - pandas {{ pandas }}
     - psutil
     - qiime2 {{ qiime2_epoch }}.*
     - q2-types {{ qiime2_epoch }}.*
-    - scikit-bio
+    - scikit-bio {{ scikit_bio }}
     - scipy
-    - unifrac >=0.20.0
+    - unifrac {{ unifrac }}
 
 test:
   requires:


=====================================
q2_diversity_lib/__init__.py
=====================================
@@ -1,5 +1,5 @@
 # ----------------------------------------------------------------------------
-# Copyright (c) 2018-2021, QIIME 2 development team.
+# Copyright (c) 2018-2022, QIIME 2 development team.
 #
 # Distributed under the terms of the Modified BSD License.
 #


=====================================
q2_diversity_lib/_util.py
=====================================
@@ -1,5 +1,5 @@
 # ----------------------------------------------------------------------------
-# Copyright (c) 2018-2021, QIIME 2 development team.
+# Copyright (c) 2018-2022, QIIME 2 development team.
 #
 # Distributed under the terms of the Modified BSD License.
 #
@@ -7,6 +7,8 @@
 # ----------------------------------------------------------------------------
 
 from inspect import signature
+from os import environ
+import subprocess
 
 import numpy as np
 from decorator import decorator
@@ -98,3 +100,19 @@ def _validate_requested_cpus(wrapped_function, *args, **kwargs):
                          "available to the system.")
 
     return wrapped_function(*bound_arguments.args, **bound_arguments.kwargs)
+
+
+def _run_external_cmd(cmd, verbose=True, env=None):
+    if verbose:
+        print("Running external command line application. This may print"
+              " messages to stdout and/or stderr.\nThe command being run is"
+              " below. This command cannot be manually re-run as it will"
+              " depend on temporary files that no longer exist.\n\nCommand:\n")
+        print(" ".join(cmd), end='\n\n')
+    return subprocess.run(cmd, check=True, env=env)
+
+
+def _omp_cmd_wrapper(threads, cmd, verbose=True):
+    env = environ.copy()
+    env.update({'OMP_NUM_THREADS': str(threads)})
+    return _run_external_cmd(cmd, verbose=verbose, env=env)


=====================================
q2_diversity_lib/_version.py
=====================================
@@ -23,9 +23,9 @@ def get_keywords():
     # setup.py/versioneer.py will grep for the variable names, so they must
     # each be defined on a line of their own. _version.py will just call
     # get_keywords().
-    git_refnames = " (tag: 2021.8.0)"
-    git_full = "9c30351a4ce12d4eccb94158cd808faced68fe0d"
-    git_date = "2021-09-09 18:35:28 +0000"
+    git_refnames = " (tag: 2022.2.1, 2022.2-patches)"
+    git_full = "50ba304057b7d4821ed47d88417ac0f20f34c7f4"
+    git_date = "2022-05-30 21:32:17 -0700"
     keywords = {"refnames": git_refnames, "full": git_full, "date": git_date}
     return keywords
 


=====================================
q2_diversity_lib/alpha.py
=====================================
@@ -1,5 +1,5 @@
 # ----------------------------------------------------------------------------
-# Copyright (c) 2018-2021, QIIME 2 development team.
+# Copyright (c) 2018-2022, QIIME 2 development team.
 #
 # Distributed under the terms of the Modified BSD License.
 #
@@ -9,12 +9,14 @@
 import pandas as pd
 import skbio.diversity
 import biom
-import unifrac
 
 from q2_types.feature_table import BIOMV210Format
+from q2_types.sample_data import AlphaDiversityFormat
 from q2_types.tree import NewickFormat
 from ._util import (_drop_undefined_samples,
-                    _disallow_empty_tables)
+                    _disallow_empty_tables,
+                    _validate_requested_cpus,
+                    _omp_cmd_wrapper)
 
 
 METRICS = {
@@ -43,12 +45,13 @@ METRICS = {
 
 # --------------------- Phylogenetic -----------------------------------------
 @_disallow_empty_tables
-def faith_pd(table: BIOMV210Format, phylogeny: NewickFormat) -> pd.Series:
-    table_str = str(table)
-    tree_str = str(phylogeny)
-    result = unifrac.faith_pd(table_str, tree_str)
-    result.name = 'faith_pd'
-    return result
+ at _validate_requested_cpus
+def faith_pd(table: BIOMV210Format, phylogeny: NewickFormat,
+             threads: int = 1) -> AlphaDiversityFormat:
+    vec = AlphaDiversityFormat()
+    cmd = ['faithpd', '-i', str(table), '-t', str(phylogeny), '-o', str(vec)]
+    _omp_cmd_wrapper(threads, cmd)
+    return vec
 
 
 # --------------------- Non-Phylogenetic -------------------------------------


=====================================
q2_diversity_lib/beta.py
=====================================
@@ -1,13 +1,11 @@
 # ----------------------------------------------------------------------------
-# Copyright (c) 2018-2021, QIIME 2 development team.
+# Copyright (c) 2018-2022, QIIME 2 development team.
 #
 # Distributed under the terms of the Modified BSD License.
 #
 # The full license is in the file LICENSE, distributed with this software.
 # ----------------------------------------------------------------------------
 
-from functools import partial
-
 import biom
 import skbio.diversity
 import sklearn.metrics
@@ -17,10 +15,12 @@ from scipy.spatial.distance import euclidean
 from scipy.spatial.distance import jensenshannon
 import numpy as np
 
+from q2_types.distance_matrix import LSMatFormat
 from q2_types.feature_table import BIOMV210Format
 from q2_types.tree import NewickFormat
 from ._util import (_disallow_empty_tables,
-                    _validate_requested_cpus)
+                    _validate_requested_cpus,
+                    _omp_cmd_wrapper)
 
 
 # NOTE: some phylo metrics are currently in both implemented and unimplemented
@@ -95,28 +95,47 @@ def beta_phylogenetic_passthrough(table: BIOMV210Format,
                                   variance_adjusted: bool = False,
                                   alpha: float = None,
                                   bypass_tips: bool = False
-                                  ) -> skbio.DistanceMatrix:
-    unifrac_functions = {
-            'unweighted_unifrac': unifrac.unweighted,
-            'weighted_unifrac': unifrac.weighted_unnormalized,
-            'weighted_normalized_unifrac': unifrac.weighted_normalized,
-            'generalized_unifrac': unifrac.generalized}
-    func = unifrac_functions[metric]
-
+                                  ) -> LSMatFormat:
     # Ideally we remove this when we can support optional type-mapped params.
     if alpha is not None and metric != 'generalized_unifrac':
         raise ValueError("The alpha parameter is only allowed when the "
                          "selected metric is 'generalized_unifrac'")
 
+    method = {
+        'unweighted_unifrac': 'unweighted',
+        'weighted_unifrac': 'weighted_unnormalized',
+        'weighted_normalized_unifrac': 'weighted_normalized',
+        'generalized_unifrac': 'generalized',
+    }[metric]
+
+    result = LSMatFormat()
+
+    cmd = [
+        'ssu',
+        '-i', str(table),
+        '-t', str(phylogeny),
+        '-m', method,
+        '-o', str(result),
+    ]
+
     # handle unimplemented unifracs
     if metric == 'generalized_unifrac':
         alpha = 1.0 if alpha is None else alpha
-        func = partial(func, alpha=alpha)
+        cmd += ['-a', str(alpha)]
+
+    if variance_adjusted:
+        cmd += ['--vaw']
+
+    if bypass_tips:
+        cmd += ['-f']
+
+    _omp_cmd_wrapper(threads, cmd)
 
-    return func(str(table), str(phylogeny), threads=threads,
-                variance_adjusted=variance_adjusted, bypass_tips=bypass_tips)
+    return result
 
 
+# Note, this method doesn't have a corresponding cli invocation, so we'll
+# just rely on unifrac doing the right thing with `threads` here.
 @_disallow_empty_tables
 @_validate_requested_cpus
 def beta_phylogenetic_meta_passthrough(tables: BIOMV210Format,
@@ -185,17 +204,43 @@ def jaccard(table: biom.Table, n_jobs: int = 1) -> skbio.DistanceMatrix:
 def unweighted_unifrac(table: BIOMV210Format,
                        phylogeny: NewickFormat,
                        threads: int = 1,
-                       bypass_tips: bool = False) -> skbio.DistanceMatrix:
-    return unifrac.unweighted(str(table), str(phylogeny), threads=threads,
-                              variance_adjusted=False, bypass_tips=bypass_tips)
+                       bypass_tips: bool = False) -> LSMatFormat:
+    result = LSMatFormat()
+
+    cmd = [
+        'ssu',
+        '-i', str(table),
+        '-t', str(phylogeny),
+        '-m', 'unweighted',
+        '-o', str(result),
+    ]
+
+    if bypass_tips:
+        cmd += ['-f']
+
+    _omp_cmd_wrapper(threads, cmd)
+
+    return result
 
 
 @_disallow_empty_tables
 @_validate_requested_cpus
 def weighted_unifrac(table: BIOMV210Format, phylogeny: NewickFormat,
                      threads: int = 1, bypass_tips: bool = False
-                     ) -> skbio.DistanceMatrix:
-    return unifrac.weighted_unnormalized(str(table), str(phylogeny),
-                                         threads=threads,
-                                         variance_adjusted=False,
-                                         bypass_tips=bypass_tips)
+                     ) -> LSMatFormat:
+    result = LSMatFormat()
+
+    cmd = [
+        'ssu',
+        '-i', str(table),
+        '-t', str(phylogeny),
+        '-m', 'weighted_unnormalized',
+        '-o', str(result),
+    ]
+
+    if bypass_tips:
+        cmd += ['-f']
+
+    _omp_cmd_wrapper(threads, cmd)
+
+    return result


=====================================
q2_diversity_lib/plugin_setup.py
=====================================
@@ -1,5 +1,5 @@
 # ----------------------------------------------------------------------------
-# Copyright (c) 2018-2021, QIIME 2 development team.
+# Copyright (c) 2018-2022, QIIME 2 development team.
 #
 # Distributed under the terms of the Modified BSD License.
 #
@@ -56,7 +56,7 @@ plugin.methods.register_function(
     inputs={'table': FeatureTable[Frequency | RelativeFrequency
             | PresenceAbsence],
             'phylogeny': Phylogeny[Rooted]},
-    parameters=None,
+    parameters={'threads': Int % Range(1, None) | Str % Choices(['auto'])},
     outputs=[('vector', SampleData[AlphaDiversity])],
     input_descriptions={
         'table': "The feature table containing the samples for which Faith's "
@@ -67,7 +67,7 @@ plugin.methods.register_function(
                      "This tree can contain tip ids that are not present in "
                      "the table, but all feature ids in the table must be "
                      "present in this tree."},
-    parameter_descriptions=None,
+    parameter_descriptions={'threads': threads_description},
     output_descriptions={'vector': "Vector containing per-sample values for "
                                    "Faith's Phylogenetic Diversity."},
     name="Faith's Phylogenetic Diversity",


=====================================
q2_diversity_lib/tests/__init__.py
=====================================
@@ -1,5 +1,5 @@
 # ----------------------------------------------------------------------------
-# Copyright (c) 2018-2021, QIIME 2 development team.
+# Copyright (c) 2018-2022, QIIME 2 development team.
 #
 # Distributed under the terms of the Modified BSD License.
 #


=====================================
q2_diversity_lib/tests/test_alpha.py
=====================================
@@ -1,22 +1,22 @@
 # ----------------------------------------------------------------------------
-# Copyright (c) 2018-2021, QIIME 2 development team.
+# Copyright (c) 2018-2022, QIIME 2 development team.
 #
 # Distributed under the terms of the Modified BSD License.
 #
 # The full license is in the file LICENSE, distributed with this software.
 # ----------------------------------------------------------------------------
 
+from subprocess import CalledProcessError
+
 import numpy as np
 import pandas as pd
 import pandas.testing as pdt
 import biom
 
 from qiime2.plugin.testing import TestPluginBase
-from q2_types.feature_table import BIOMV210Format
-from q2_types.tree import NewickFormat
 from qiime2 import Artifact
 
-from ..alpha import (faith_pd, pielou_evenness, observed_features,
+from ..alpha import (pielou_evenness, observed_features,
                      shannon_entropy, METRICS)
 
 
@@ -39,77 +39,53 @@ class SmokeTests(TestPluginBase):
 class FaithPDTests(TestPluginBase):
     package = 'q2_diversity_lib.tests'
 
+    def artifact(self, semantic_type, fp):
+        return Artifact.import_data(semantic_type, self.get_data_path(fp))
+
+    @staticmethod
+    def assert_vec_equal(actual_art, expected):
+        actual = actual_art.view(pd.Series)
+        pdt.assert_series_equal(actual, expected)
+
     def setUp(self):
         super().setUp()
-        empty_table_fp = self.get_data_path('empty_table.biom')
-        self.empty_table_as_BIOMV210Format = \
-            BIOMV210Format(empty_table_fp, mode='r')
-        input_table_fp = self.get_data_path('faith_test_table.biom')
-        self.input_table_as_BIOMV210Format = \
-            BIOMV210Format(input_table_fp, mode='r')
-        rf_table_fp = self.get_data_path('faith_test_table_rf.biom')
-        self.rf_table_as_BIOMV210Format = BIOMV210Format(rf_table_fp, mode='r')
-        pa_table_fp = self.get_data_path('faith_test_table_pa.biom')
-        self.pa_table_as_BIOMV210Format = BIOMV210Format(pa_table_fp, mode='r')
-
-        empty_tree_fp = self.get_data_path('empty.tree')
-        self.empty_tree_as_NewickFormat = NewickFormat(empty_tree_fp, mode='r')
-        input_tree_fp = self.get_data_path('faith_test.tree')
-        self.input_tree_as_NewickFormat = NewickFormat(input_tree_fp, mode='r')
-        root_only_tree_fp = self.get_data_path('root_only.tree')
-        self.root_only_tree_as_NewickFormat = \
-            NewickFormat(root_only_tree_fp, mode='r')
-        missing_tip_tree_fp = self.get_data_path('missing_tip.tree')
-        self.missing_tip_tree_as_NewickFormat = \
-            NewickFormat(missing_tip_tree_fp, mode='r')
-
+        self.fn = self.plugin.actions['faith_pd']
+        self.tbl = self.artifact('FeatureTable[Frequency]',
+                                 'faith_test_table.biom')
+        self.tre = self.artifact('Phylogeny[Rooted]', 'faith_test.tree')
         self.expected = pd.Series({'S1': 0.5, 'S2': 0.7, 'S3': 1.0,
                                    'S4': 100.5, 'S5': 101},
                                   name='faith_pd')
 
     def test_receives_empty_table(self):
-        # empty table generated from self.empty_table with biom v2.1.7
-        empty_table = self.empty_table_as_BIOMV210Format
+        table = self.artifact('FeatureTable[Frequency]', 'empty_table.biom')
         with self.assertRaisesRegex(ValueError, 'empty'):
-            faith_pd(table=empty_table,
-                     phylogeny=self.input_tree_as_NewickFormat)
+            self.fn(table=table, phylogeny=self.tre)
 
     def test_method(self):
-        actual = faith_pd(table=self.input_table_as_BIOMV210Format,
-                          phylogeny=self.input_tree_as_NewickFormat)
-        pdt.assert_series_equal(actual, self.expected)
+        actual_art, = self.fn(table=self.tbl, phylogeny=self.tre)
+        self.assert_vec_equal(actual_art, self.expected)
 
     def test_accepted_types_have_consistent_behavior(self):
-        freq_table = self.input_table_as_BIOMV210Format
-        rel_freq_table = self.rf_table_as_BIOMV210Format
-        p_a_table = self.pa_table_as_BIOMV210Format
-        accepted_tables = [freq_table, rel_freq_table, p_a_table]
-        for table in accepted_tables:
-            actual = faith_pd(table=table,
-                              phylogeny=self.input_tree_as_NewickFormat)
-            pdt.assert_series_equal(actual, self.expected)
+        rf_tbl = self.artifact('FeatureTable[RelativeFrequency]',
+                               'faith_test_table_rf.biom')
+        pa_tbl = self.artifact('FeatureTable[PresenceAbsence]',
+                               'faith_test_table_pa.biom')
+        for table in [self.tbl, rf_tbl, pa_tbl]:
+            actual_art, = self.fn(table=table, phylogeny=self.tre)
+            self.assert_vec_equal(actual_art, self.expected)
 
-    def test_passed_emptytree(self):
-        # NOTE: different regular expressions are used here and in
-        # test_beta.test_phylogenetic_measures_passed_emptytree() because
-        # Unifrac reports different error messages when an empty tree is passed
-        # to faith_pd than when the same is passed to the Unifrac methods.
-        with self.assertRaisesRegex(ValueError,
-                                    'table.*not.*completely represented'):
-            faith_pd(table=self.input_table_as_BIOMV210Format,
-                     phylogeny=self.empty_tree_as_NewickFormat)
+    def test_passed_tree_missing_tip(self):
+        tree = self.artifact('Phylogeny[Rooted]', 'missing_tip.tree')
+        with self.assertRaises(CalledProcessError):
+            obs = self.fn(table=self.tbl, phylogeny=tree)
+            self.assertTrue('not a subset of the tree tips' in obs.stderr)
 
     def test_passed_rootonlytree(self):
-        with self.assertRaisesRegex(ValueError,
-                                    'table.*not.*completely represented'):
-            faith_pd(table=self.input_table_as_BIOMV210Format,
-                     phylogeny=self.root_only_tree_as_NewickFormat)
-
-    def test_passed_tree_missing_tip(self):
-        with self.assertRaisesRegex(ValueError,
-                                    'table.*not.*completely represented'):
-            faith_pd(table=self.input_table_as_BIOMV210Format,
-                     phylogeny=self.missing_tip_tree_as_NewickFormat)
+        tree = self.artifact('Phylogeny[Rooted]', 'root_only.tree')
+        with self.assertRaises(CalledProcessError):
+            obs = self.fn(table=self.tbl, phylogeny=tree)
+            self.assertTrue('not a subset of the tree tips' in obs.stderr)
 
 
 class ObservedFeaturesTests(TestPluginBase):


=====================================
q2_diversity_lib/tests/test_beta.py
=====================================
@@ -1,10 +1,13 @@
 # ----------------------------------------------------------------------------
-# Copyright (c) 2018-2021, QIIME 2 development team.
+# Copyright (c) 2018-2022, QIIME 2 development team.
 #
 # Distributed under the terms of the Modified BSD License.
 #
 # The full license is in the file LICENSE, distributed with this software.
 # ----------------------------------------------------------------------------
+import os
+from subprocess import CalledProcessError
+
 import numpy as np
 import numpy.testing as npt
 import biom
@@ -12,88 +15,9 @@ import skbio
 import pkg_resources
 
 from qiime2.plugin.testing import TestPluginBase
-from q2_types.feature_table import BIOMV210Format
-from q2_types.tree import NewickFormat
 from qiime2 import Artifact
 
-from ..beta import (bray_curtis, jaccard, unweighted_unifrac,
-                    weighted_unifrac, METRICS)
-
-
-nonphylogenetic_measures = [bray_curtis, jaccard]
-phylogenetic_measures = [unweighted_unifrac, weighted_unifrac]
-
-
-class SmokeTests(TestPluginBase):
-    package = 'q2_diversity_lib.tests'
-
-    def setUp(self):
-        super().setUp()
-        valid_table_fp = self.get_data_path('two_feature_table.biom')
-        self.valid_table_as_BIOMV210Format = \
-            BIOMV210Format(valid_table_fp, mode='r')
-        # empty table fp generated from self.empty_table with biom v2.1.7
-        self.empty_table = biom.Table(np.array([]), [], [])
-        empty_table_fp = self.get_data_path('empty_table.biom')
-        self.empty_table_as_BIOMV210Format = \
-            BIOMV210Format(empty_table_fp, mode='r')
-
-        empty_tree_fp = self.get_data_path('empty.tree')
-        self.empty_tree_as_NewickFormat = NewickFormat(empty_tree_fp, mode='r')
-        root_only_tree_fp = self.get_data_path('root_only.tree')
-        self.root_only_tree_as_NewickFormat = NewickFormat(root_only_tree_fp,
-                                                           mode='r')
-        missing_tip_tree_fp = self.get_data_path('missing_tip.tree')
-        self.missing_tip_tree_as_NewickFormat = \
-            NewickFormat(missing_tip_tree_fp, mode='r')
-        two_feature_tree_fp = self.get_data_path('two_feature.tree')
-        self.two_feature_tree_as_NewickFormat = \
-            NewickFormat(two_feature_tree_fp, mode='r')
-        extra_tip_tree_fp = self.get_data_path('extra_tip.tree')
-        self.extra_tip_tree_as_NewickFormat = NewickFormat(extra_tip_tree_fp,
-                                                           mode='r')
-        valid_tree_fp = self.get_data_path('three_feature.tree')
-        self.valid_tree_as_NewickFormat = NewickFormat(valid_tree_fp, mode='r')
-
-    def test_nonphylogenetic_measures_passed_empty_table(self):
-        for measure in nonphylogenetic_measures:
-            with self.assertRaisesRegex(ValueError, "empty"):
-                measure(table=self.empty_table)
-
-    def test_phylogenetic_measures_passed_empty_table(self):
-        for measure in phylogenetic_measures:
-            with self.assertRaisesRegex(ValueError, "empty"):
-                measure(table=self.empty_table_as_BIOMV210Format,
-                        phylogeny=self.valid_tree_as_NewickFormat)
-
-    def test_phylogenetic_measures_passed_empty_tree(self):
-        for measure in phylogenetic_measures:
-            with self.assertRaisesRegex(ValueError, "newick"):
-                measure(table=self.valid_table_as_BIOMV210Format,
-                        phylogeny=self.empty_tree_as_NewickFormat)
-
-    def test_phylogenetic_measures_passed_root_only_tree(self):
-        for measure in phylogenetic_measures:
-            with self.assertRaisesRegex(ValueError,
-                                        "table.*not.*completely represented"):
-                measure(table=self.valid_table_as_BIOMV210Format,
-                        phylogeny=self.root_only_tree_as_NewickFormat)
-
-    def test_phylogenetic_measures_passed_tree_missing_tip(self):
-        for measure in phylogenetic_measures:
-            with self.assertRaisesRegex(ValueError,
-                                        "table.*not.*completely represented"):
-                measure(table=self.valid_table_as_BIOMV210Format,
-                        phylogeny=self.missing_tip_tree_as_NewickFormat)
-
-    def test_phylogenetic_measure_passed_tree_w_extra_tip(self):
-        for measure in phylogenetic_measures:
-            matched_tree_output = measure(
-                self.valid_table_as_BIOMV210Format,
-                self.two_feature_tree_as_NewickFormat)
-            extra_tip_tree_output = measure(self.valid_table_as_BIOMV210Format,
-                                            self.valid_tree_as_NewickFormat)
-            self.assertEqual(matched_tree_output, extra_tip_tree_output)
+from ..beta import bray_curtis, jaccard, METRICS
 
 
 # ----------------------------Non-Phylogenetic---------------------------------
@@ -214,67 +138,85 @@ class JaccardTests(TestPluginBase):
 class UnweightedUnifrac(TestPluginBase):
     package = 'q2_diversity_lib.tests'
 
+    def artifact(self, semantic_type, fp):
+        return Artifact.import_data(semantic_type, self.get_data_path(fp))
+
     def setUp(self):
         super().setUp()
+
+        self.fn = self.plugin.actions['unweighted_unifrac']
+
         # expected computed with skbio.diversity.beta_diversity
         self.expected = skbio.DistanceMatrix([[0.00, 0.25, 0.25],
                                              [0.25, 0.00, 0.00],
                                              [0.25, 0.00, 0.00]],
                                              ids=['S1', 'S2', 'S3'])
 
-        table_fp = self.get_data_path('two_feature_table.biom')
-        self.table_as_BIOMV210Format = BIOMV210Format(table_fp, mode='r')
-        rf_table_fp = self.get_data_path('two_feature_rf_table.biom')
-        self.rf_table_as_BIOMV210Format = BIOMV210Format(rf_table_fp, mode='r')
-        p_a_table_fp = self.get_data_path('two_feature_p_a_table.biom')
-        self.p_a_table_as_BIOMV210Format = BIOMV210Format(p_a_table_fp,
-                                                          mode='r')
-        self.table_as_artifact = Artifact.import_data(
-                    'FeatureTable[Frequency]', self.table_as_BIOMV210Format)
-
-        tree_fp = self.get_data_path('three_feature.tree')
-        self.tree_as_NewickFormat = NewickFormat(tree_fp, mode='r')
-        self.tree_as_artifact = Artifact.import_data(
-                    'Phylogeny[Rooted]', self.tree_as_NewickFormat)
-
-        self.unweighted_unifrac_thru_framework = self.plugin.actions[
-                    'unweighted_unifrac']
+        self.tbl = self.artifact('FeatureTable[Frequency]',
+                                 'two_feature_table.biom')
+        self.tre = self.artifact('Phylogeny[Rooted]', 'three_feature.tree')
 
     def test_method(self):
-        actual = unweighted_unifrac(self.table_as_BIOMV210Format,
-                                    self.tree_as_NewickFormat)
+        actual_art, = self.fn(self.tbl, self.tre)
+        actual = actual_art.view(skbio.DistanceMatrix)
         self.assertEqual(actual.ids, self.expected.ids)
         for id1 in actual.ids:
             for id2 in actual.ids:
                 npt.assert_almost_equal(actual[id1, id2],
                                         self.expected[id1, id2])
 
+    def test_method_bypass_tips(self):
+        actual_art, = self.fn(self.tbl, self.tre, bypass_tips=True)
+        actual = actual_art.view(skbio.DistanceMatrix)
+        self.assertEqual(actual.ids, self.expected.ids)
+
     def test_accepted_types_have_consistent_behavior(self):
-        freq_table = self.table_as_BIOMV210Format
-        rel_freq_table = self.rf_table_as_BIOMV210Format
-        p_a_table = self.p_a_table_as_BIOMV210Format
-        accepted_tables = [freq_table, rel_freq_table, p_a_table]
-        for table in accepted_tables:
-            actual = unweighted_unifrac(table=table,
-                                        phylogeny=self.tree_as_NewickFormat)
+        rf_tbl = self.artifact('FeatureTable[RelativeFrequency]',
+                               'two_feature_rf_table.biom')
+        pa_tbl = self.artifact('FeatureTable[PresenceAbsence]',
+                               'two_feature_p_a_table.biom')
+
+        for table in [self.tbl, rf_tbl, pa_tbl]:
+            actual_art, = self.fn(table=table, phylogeny=self.tre)
+            actual = actual_art.view(skbio.DistanceMatrix)
             self.assertEqual(actual.ids, self.expected.ids)
             for id1 in actual.ids:
                 for id2 in actual.ids:
                     npt.assert_almost_equal(actual[id1, id2],
                                             self.expected[id1, id2])
 
-    def test_does_it_run_through_framework(self):
-        self.unweighted_unifrac_thru_framework(self.table_as_artifact,
-                                               self.tree_as_artifact)
-        # If we get here, then it ran without error
-        self.assertTrue(True)
+    def test_missing_tips_tree(self):
+        tre = self.artifact('Phylogeny[Rooted]', 'root_only.tree')
+        with self.assertRaises(CalledProcessError):
+            obs = self.fn(self.tbl, tre)
+            self.assertTrue('not a subset of the tree tips', obs.stderr)
+
+    def test_extra_tip_tree(self):
+        tbl = self.artifact('FeatureTable[Frequency]',
+                            'two_feature_table.biom')
+
+        tre_2 = self.artifact('Phylogeny[Rooted]', 'two_feature.tree')
+        obs_2_art, = self.fn(tbl, tre_2)
+        obs_2 = obs_2_art.view(skbio.DistanceMatrix)
+
+        tre_3 = self.artifact('Phylogeny[Rooted]', 'three_feature.tree')
+        obs_3_art, = self.fn(tbl, tre_3)
+        obs_3 = obs_3_art.view(skbio.DistanceMatrix)
+
+        self.assertEqual(obs_2, obs_3)
 
 
 class WeightedUnifrac(TestPluginBase):
     package = 'q2_diversity_lib.tests'
 
+    def artifact(self, semantic_type, fp):
+        return Artifact.import_data(semantic_type, self.get_data_path(fp))
+
     def setUp(self):
         super().setUp()
+
+        self.fn = self.plugin.actions['weighted_unifrac']
+
         # expected computed with diversity.beta_phylogenetic (weighted_unifrac)
         self.expected = skbio.DistanceMatrix(
             np.array([0.44656238, 0.23771096, 0.30489123, 0.23446002,
@@ -290,74 +232,99 @@ class WeightedUnifrac(TestPluginBase):
                  '10084.PC.355', '10084.PC.354', '10084.PC.636',
                  '10084.PC.635', '10084.PC.607', '10084.PC.634'))
 
-        table_fp = self.get_data_path('crawford.biom')
-        self.table_as_BIOMV210Format = BIOMV210Format(table_fp, mode='r')
-        rel_freq_table_fp = self.get_data_path('crawford_rf.biom')
-        self.rf_table_as_BIOMV210Format = BIOMV210Format(rel_freq_table_fp,
-                                                         mode='r')
-
-        tree_fp = self.get_data_path('crawford.nwk')
-        self.tree_as_NewickFormat = NewickFormat(tree_fp, mode='r')
+        self.tbl = self.artifact('FeatureTable[Frequency]', 'crawford.biom')
+        self.tre = self.artifact('Phylogeny[Rooted]', 'crawford.nwk')
 
     def test_method(self):
-        actual = weighted_unifrac(
-            self.table_as_BIOMV210Format, self.tree_as_NewickFormat)
+        actual_art, = self.fn(self.tbl, self.tre)
+        actual = actual_art.view(skbio.DistanceMatrix)
         self.assertEqual(actual.ids, self.expected.ids)
         for id1 in actual.ids:
             for id2 in actual.ids:
                 npt.assert_almost_equal(actual[id1, id2],
                                         self.expected[id1, id2])
 
+    def test_method_bypass_tips(self):
+        actual_art, = self.fn(self.tbl, self.tre, bypass_tips=True)
+        actual = actual_art.view(skbio.DistanceMatrix)
+        self.assertEqual(actual.ids, self.expected.ids)
+
     def test_accepted_types_have_consistent_behavior(self):
-        freq_table = self.table_as_BIOMV210Format
-        rel_freq_table = self.rf_table_as_BIOMV210Format
-        accepted_tables = [freq_table, rel_freq_table]
-        for table in accepted_tables:
-            actual = weighted_unifrac(
-                table=table, phylogeny=self.tree_as_NewickFormat)
+        tbl_rf = self.artifact('FeatureTable[RelativeFrequency]',
+                               'crawford_rf.biom')
+
+        for table in [self.tbl, tbl_rf]:
+            actual_art, = self.fn(table=table, phylogeny=self.tre)
+            actual = actual_art.view(skbio.DistanceMatrix)
             self.assertEqual(actual.ids, self.expected.ids)
             for id1 in actual.ids:
                 for id2 in actual.ids:
                     npt.assert_almost_equal(actual[id1, id2],
                                             self.expected[id1, id2])
 
+    def test_missing_tips_tree(self):
+        tre = self.artifact('Phylogeny[Rooted]', 'root_only.tree')
+        with self.assertRaises(CalledProcessError):
+            obs = self.fn(self.tbl, tre)
+            self.assertTrue('not a subset of the tree tips', obs.stderr)
+
+    def test_extra_tip_tree(self):
+        tbl = self.artifact('FeatureTable[Frequency]',
+                            'two_feature_table.biom')
+
+        tre_2 = self.artifact('Phylogeny[Rooted]', 'two_feature.tree')
+        obs_2_art, = self.fn(tbl, tre_2)
+        obs_2 = obs_2_art.view(skbio.DistanceMatrix)
+
+        tre_3 = self.artifact('Phylogeny[Rooted]', 'three_feature.tree')
+        obs_3_art, = self.fn(tbl, tre_3)
+        obs_3 = obs_3_art.view(skbio.DistanceMatrix)
+
+        self.assertEqual(obs_2, obs_3)
+
 
 class BetaPhylogeneticMetaPassthroughTests(TestPluginBase):
     package = 'q2_diversity_lib.tests'
 
     def setUp(self):
         super().setUp()
-        self.method = self.plugin.actions['beta_phylogenetic_meta_passthrough']
-        empty_table = biom.Table(np.array([]), [], [])
-        self.empty_table = Artifact.import_data('FeatureTable[Frequency]',
-                                                empty_table)
+        self.fn = self.plugin.actions['beta_phylogenetic_meta_passthrough']
+
+        self.empty_tbl = Artifact.import_data(
+            'FeatureTable[Frequency]', biom.Table(np.array([]), [], []))
 
         # checking parity with the unifrac.meta tests
-        table1 = pkg_resources.resource_filename('unifrac.tests',
-                                                 'data/e1.biom')
-        table2 = pkg_resources.resource_filename('unifrac.tests',
-                                                 'data/e2.biom')
-        self.tables = [Artifact.import_data('FeatureTable[Frequency]', table1),
-                       Artifact.import_data('FeatureTable[Frequency]', table2)]
-
-        tree1 = pkg_resources.resource_filename('unifrac.tests',
-                                                'data/t1.newick')
-        tree2 = pkg_resources.resource_filename('unifrac.tests',
-                                                'data/t2.newick')
-        self.trees = [Artifact.import_data('Phylogeny[Rooted]', tree1),
-                      Artifact.import_data('Phylogeny[Rooted]', tree2)]
+        def unifrac_data(fn):
+            path = os.path.join('data', fn)
+            return pkg_resources.resource_filename('unifrac.tests', path)
+
+        self.tables = [
+            Artifact.import_data('FeatureTable[Frequency]',
+                                 unifrac_data('e1.biom')),
+            Artifact.import_data('FeatureTable[Frequency]',
+                                 unifrac_data('e2.biom')),
+        ]
+
+        self.trees = [
+            Artifact.import_data('Phylogeny[Rooted]',
+                                 unifrac_data('t1.newick')),
+            Artifact.import_data('Phylogeny[Rooted]',
+                                 unifrac_data('t2.newick')),
+        ]
 
     def test_method(self):
         for metric in METRICS['PHYLO']['UNIMPL']:
-            self.method(tables=self.tables, phylogenies=self.trees,
-                        metric=metric)
-        self.assertTrue(True)
+            obs_art, = self.fn(tables=self.tables, phylogenies=self.trees,
+                               metric=metric)
+            obs = obs_art.view(skbio.DistanceMatrix)
+            self.assertEqual(('A', 'B', 'C'), obs.ids)
+            self.assertEqual((3, 3), obs.shape)
 
     def test_passed_bad_metric(self):
         with self.assertRaisesRegex(TypeError,
                                     'imaginary_metric.*incompatible'):
-            self.method(tables=self.tables, phylogenies=self.trees,
-                        metric='imaginary_metric')
+            self.fn(tables=self.tables, phylogenies=self.trees,
+                    metric='imaginary_metric')
 
 
 class BetaPassthroughTests(TestPluginBase):
@@ -457,44 +424,56 @@ class BetaPassthroughTests(TestPluginBase):
 class BetaPhylogeneticPassthroughTests(TestPluginBase):
     package = 'q2_diversity_lib.tests'
 
+    def artifact(self, semantic_type, fn):
+        return Artifact.import_data(semantic_type, self.get_data_path(fn))
+
     def setUp(self):
         super().setUp()
-        self.method = self.plugin.actions['beta_phylogenetic_passthrough']
-        empty_table = biom.Table(np.array([]), [], [])
-        self.empty_table = Artifact.import_data('FeatureTable[Frequency]',
-                                                empty_table)
-        crawford_tbl = self.get_data_path('crawford.biom')
-        self.crawford_tbl = Artifact.import_data('FeatureTable[Frequency]',
-                                                 crawford_tbl)
-        crawford_tree = self.get_data_path('crawford.nwk')
-        self.crawford_tree = Artifact.import_data('Phylogeny[Rooted]',
-                                                  crawford_tree)
+
+        self.fn = self.plugin.actions['beta_phylogenetic_passthrough']
+
+        self.tbl = self.artifact('FeatureTable[Frequency]', 'crawford.biom')
+        self.tre = self.artifact('Phylogeny[Rooted]', 'crawford.nwk')
 
     def test_method(self):
         for metric in METRICS['PHYLO']['UNIMPL']:
-            self.method(table=self.crawford_tbl,
-                        phylogeny=self.crawford_tree, metric=metric)
-        # If we get here, then our methods ran without error
-        self.assertTrue(True)
+            obs_art, = self.fn(table=self.tbl, phylogeny=self.tre,
+                               metric=metric)
+            obs = obs_art.view(skbio.DistanceMatrix)
+            self.assertEqual(9, len(obs.ids))
+            self.assertEqual((9, 9), obs.shape)
+
+        # variance adjusted
+        for metric in METRICS['PHYLO']['UNIMPL']:
+            obs_art, = self.fn(table=self.tbl, phylogeny=self.tre,
+                               metric=metric, variance_adjusted=True)
+            obs = obs_art.view(skbio.DistanceMatrix)
+            self.assertEqual(9, len(obs.ids))
+            self.assertEqual((9, 9), obs.shape)
+
+        # bypass tips
+        for metric in METRICS['PHYLO']['UNIMPL']:
+            obs_art, = self.fn(table=self.tbl, phylogeny=self.tre,
+                               metric=metric, bypass_tips=True)
+            obs = obs_art.view(skbio.DistanceMatrix)
+            self.assertEqual(9, len(obs.ids))
+            self.assertEqual((9, 9), obs.shape)
 
     def test_passed_empty_table(self):
+        tbl = Artifact.import_data(
+            'FeatureTable[Frequency]', biom.Table(np.array([]), [], []))
+
         for metric in METRICS['PHYLO']['UNIMPL']:
             with self.assertRaisesRegex(ValueError, 'empty'):
-                self.method(table=self.empty_table,
-                            phylogeny=self.crawford_tree, metric=metric)
+                self.fn(table=tbl, phylogeny=self.tre, metric=metric)
 
     def test_passed_bad_metric(self):
-        with self.assertRaisesRegex(TypeError,
-                                    'imaginary_metric.*incompatible'):
-            self.method(table=self.crawford_tbl,
-                        phylogeny=self.crawford_tree,
-                        metric='imaginary_metric')
+        with self.assertRaisesRegex(TypeError, 'imaginary.*incompatible'):
+            self.fn(table=self.tbl, phylogeny=self.tre, metric='imaginary')
 
     def test_beta_phylogenetic_alpha_on_non_generalized(self):
         with self.assertRaisesRegex(ValueError, 'The alpha parameter is only '
                                     'allowed when the selected metric is '
                                     '\'generalized_unifrac\''):
-            self.method(table=self.crawford_tbl,
-                        phylogeny=self.crawford_tree,
-                        metric='unweighted_unifrac',
-                        alpha=0.11)
+            self.fn(table=self.tbl, phylogeny=self.tre,
+                    metric='unweighted_unifrac', alpha=0.11)


=====================================
q2_diversity_lib/tests/test_util.py
=====================================
@@ -1,5 +1,5 @@
 # ----------------------------------------------------------------------------
-# Copyright (c) 2018-2021, QIIME 2 development team.
+# Copyright (c) 2018-2022, QIIME 2 development team.
 #
 # Distributed under the terms of the Modified BSD License.
 #


=====================================
setup.py
=====================================
@@ -1,5 +1,5 @@
 # ----------------------------------------------------------------------------
-# Copyright (c) 2018-2021, QIIME 2 development team.
+# Copyright (c) 2018-2022, QIIME 2 development team.
 #
 # Distributed under the terms of the Modified BSD License.
 #



View it on GitLab: https://salsa.debian.org/med-team/q2-diversity-lib/-/commit/47fa37814c17d77e0f3a7d9ec4d192d7b2b7031a

-- 
View it on GitLab: https://salsa.debian.org/med-team/q2-diversity-lib/-/commit/47fa37814c17d77e0f3a7d9ec4d192d7b2b7031a
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/debian-med-commit/attachments/20220719/30b5bc61/attachment-0001.htm>


More information about the debian-med-commit mailing list