[med-svn] [Git][med-team/q2-diversity-lib][master] 5 commits: New upstream version 2024.5.0

Michael R. Crusoe (@crusoe) gitlab at salsa.debian.org
Tue Jun 25 02:51:48 BST 2024



Michael R. Crusoe pushed to branch master at Debian Med / q2-diversity-lib


Commits:
953fd6e9 by Michael R. Crusoe at 2024-06-25T03:35:06+02:00
New upstream version 2024.5.0
- - - - -
2c273fda by Michael R. Crusoe at 2024-06-25T03:35:06+02:00
routine-update: New upstream version

- - - - -
4dbc891a by Michael R. Crusoe at 2024-06-25T03:35:07+02:00
Update upstream source from tag 'upstream/2024.5.0'

Update to upstream version '2024.5.0'
with Debian dir 006b04920c26dd54b1518da12cfee5345cc0c271
- - - - -
3fbc167d by Michael R. Crusoe at 2024-06-25T03:35:24+02:00
routine-update: Regenerate debian/control from debian/control.in

- - - - -
168f4089 by Michael R. Crusoe at 2024-06-25T03:39:33+02:00
d/patches/configparser.patch: copy from qiime packaging

- - - - -


13 changed files:

- debian/changelog
- debian/control
- + debian/patches/configparser.patch
- + debian/patches/series
- q2_diversity_lib/_version.py
- q2_diversity_lib/alpha.py
- q2_diversity_lib/beta.py
- q2_diversity_lib/examples.py
- + q2_diversity_lib/skbio/LICENSE
- + q2_diversity_lib/skbio/__init__.py
- + q2_diversity_lib/skbio/_methods.py
- + q2_diversity_lib/skbio/test_methods.py
- q2_diversity_lib/tests/test_alpha.py


Changes:

=====================================
debian/changelog
=====================================
@@ -1,3 +1,12 @@
+q2-diversity-lib (2024.5.0-1) UNRELEASED; urgency=medium
+
+  * Team upload.
+  * New upstream version
+  * Regenerate debian/control from debian/control.in (routine-update)
+  * d/patches/configparser.patch: copy from qiime packaging
+
+ -- Michael R. Crusoe <crusoe at debian.org>  Tue, 25 Jun 2024 03:35:06 +0200
+
 q2-diversity-lib (2024.2.0-1) unstable; urgency=medium
 
   * Team upload.


=====================================
debian/control
=====================================
@@ -11,7 +11,7 @@ Build-Depends: debhelper-compat (= 13),
                python3-pytest <!nocheck>,
                python3-statsmodels <!nocheck>,
                python3-unifrac <!nocheck>,
-               qiime (>= 2024.2) <!nocheck>
+               qiime (>= 2024.5) <!nocheck>
 Standards-Version: 4.6.2
 Vcs-Browser: https://salsa.debian.org/med-team/q2-diversity-lib
 Vcs-Git: https://salsa.debian.org/med-team/q2-diversity-lib.git
@@ -25,9 +25,9 @@ Depends: ${shlibs:Depends},
          ${python3:Depends},
          python3-pandas,
          python3-sklearn,
-         qiime (>= 2024.2),
-         q2-emperor (>= 2024.2),
-         q2-feature-table (>= 2024.2),
+         qiime (>= 2024.5),
+         q2-emperor (>= 2024.5),
+         q2-feature-table (>= 2024.5),
          r-base-core,
          r-cran-vegan,
          python3-statsmodels,


=====================================
debian/patches/configparser.patch
=====================================
@@ -0,0 +1,35 @@
+From: Athos Ribeiro <athos.ribeiro at canonical.com>
+Date: Mon, 3 Jun 2024 11:31:54 -0300
+Subject: [PATCH] Use ConfigParser instead of SafeConfigParser
+
+The configparser's SafeConfigParser has been renamed to ConfigParser in
+Python 3.2 [1]. It was finally removed in Python 3.12 [2].
+
+[1] https://docs.python.org/dev/whatsnew/3.2.html#configparser
+[2] https://docs.python.org/3/whatsnew/3.12.html#configparser
+
+Last-Update: 2024-06-03
+Forwarded: not-needed, see https://github.com/qiime2/q2-sample-classifier/pull/229
+---
+ versioneer.py | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/versioneer.py b/versioneer.py
+index a5e7a20..886455f 100644
+--- a/versioneer.py
++++ b/versioneer.py
+@@ -340,9 +340,9 @@ def get_config_from_root(root):
+     # configparser.NoOptionError (if it lacks "VCS="). See the docstring at
+     # the top of versioneer.py for instructions on writing your setup.cfg .
+     setup_cfg = os.path.join(root, "setup.cfg")
+-    parser = configparser.SafeConfigParser()
++    parser = configparser.ConfigParser()
+     with open(setup_cfg, "r") as f:
+-        parser.readfp(f)
++        parser.read_file(f)
+     VCS = parser.get("versioneer", "VCS")  # mandatory
+ 
+     def get(parser, name):
+-- 
+2.43.0
+


=====================================
debian/patches/series
=====================================
@@ -0,0 +1 @@
+configparser.patch


=====================================
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: 2024.2.0, Release-2024.2)"
-    git_full = "ed3f3f3d0cd7f0dd93afe37540dd0833db438d53"
-    git_date = "2024-02-16 21:56:40 +0000"
+    git_refnames = " (tag: 2024.5.0, Release-2024.5)"
+    git_full = "061b6e199fd2464750c8e59fca899fe3353ddb4e"
+    git_date = "2024-05-29 04:14:53 +0000"
     keywords = {"refnames": git_refnames, "full": git_full, "date": git_date}
     return keywords
 


=====================================
q2_diversity_lib/alpha.py
=====================================
@@ -7,9 +7,13 @@
 # ----------------------------------------------------------------------------
 
 import pandas as pd
+import numpy as np
+import functools
+
 import skbio.diversity
+import skbio.diversity.alpha
+
 import biom
-import numpy as np
 
 from q2_types.feature_table import BIOMV210Format
 from q2_types.sample_data import AlphaDiversityFormat
@@ -19,6 +23,11 @@ from ._util import (_validate_tables,
                     _validate_requested_cpus,
                     _omp_cmd_wrapper)
 
+from q2_diversity_lib.skbio._methods import (_berger_parker, _brillouin_d,
+                                             _simpsons_dominance, _esty_ci,
+                                             _goods_coverage, _margalef,
+                                             _mcintosh_d, _strong, _shannon,
+                                             _p_evenness)
 
 METRICS = {
     'PHYLO': {
@@ -91,7 +100,10 @@ def pielou_evenness(table: biom.Table,
 
     results = []
     for v in table.iter_data(dense=True):
-        results.append(_skbio_alpha_diversity_from_1d(v, 'pielou_e'))
+        # using in-house metrics temporarily
+        # results.append(_skbio_alpha_diversity_from_1d(v, 'pielou_e'))
+        v = np.reshape(v, (1, len(v)))
+        results.extend([_p_evenness(c)for c in v])
     results = pd.Series(results, index=table.ids(), name='pielou_evenness')
     return results
 
@@ -104,7 +116,10 @@ def shannon_entropy(table: biom.Table,
 
     results = []
     for v in table.iter_data(dense=True):
-        results.append(_skbio_alpha_diversity_from_1d(v, 'shannon'))
+        # using in-house metrics temporarily
+        # results.append(_skbio_alpha_diversity_from_1d(v, 'shannon'))
+        v = np.reshape(v, (1, len(v)))
+        results.extend([_shannon(c)for c in v])
     results = pd.Series(results, index=table.ids(), name='shannon_entropy')
     return results
 
@@ -112,8 +127,23 @@ def shannon_entropy(table: biom.Table,
 @_validate_tables
 def alpha_passthrough(table: biom.Table, metric: str) -> pd.Series:
     results = []
-
-    for v in table.iter_data(dense=True):
-        results.append(_skbio_alpha_diversity_from_1d(v.astype(int), metric))
+    method_map = {"berger_parker_d": _berger_parker,
+                  "brillouin_d": _brillouin_d,
+                  "simpson": _simpsons_dominance,
+                  "esty_ci": _esty_ci,
+                  "goods_coverage": _goods_coverage,
+                  "margalef": _margalef,
+                  "mcintosh_d": _mcintosh_d,
+                  "strong": _strong}
+
+    if metric in method_map:
+        metric = functools.partial(method_map[metric])
+        for v in table.iter_data(dense=True):
+            v = np.reshape(v, (1, len(v)))
+            results.extend([metric(c)for c in v])
+    else:
+        for v in table.iter_data(dense=True):
+            results.append(_skbio_alpha_diversity_from_1d(v.astype(int),
+                                                          metric))
     results = pd.Series(results, index=table.ids(), name=metric)
     return results


=====================================
q2_diversity_lib/beta.py
=====================================
@@ -38,7 +38,7 @@ METRICS = {
         'IMPL': {'braycurtis', 'jaccard'},
         'UNIMPL': {'cityblock', 'euclidean', 'seuclidean', 'sqeuclidean',
                    'cosine', 'correlation', 'hamming', 'chebyshev', 'canberra',
-                   'yule', 'matching', 'dice', 'kulsinski',
+                   'yule', 'matching', 'dice',
                    'rogerstanimoto', 'russellrao', 'sokalmichener',
                    'sokalsneath', 'minkowski', 'aitchison', 'canberra_adkins',
                    'jensenshannon'}


=====================================
q2_diversity_lib/examples.py
=====================================
@@ -322,8 +322,8 @@ def beta_passthrough_n_jobs_example(use):
     result, = use.action(
         use.UsageAction(plugin_id='diversity_lib',
                         action_id='beta_passthrough'),
-        use.UsageInputs(table=ft, metric='kulsinski', n_jobs=1),
-        use.UsageOutputNames(distance_matrix='kulsinski_dm')
+        use.UsageInputs(table=ft, metric='euclidean', n_jobs=1),
+        use.UsageOutputNames(distance_matrix='euclidean_dm')
     )
     result.assert_output_type('DistanceMatrix')
 


=====================================
q2_diversity_lib/skbio/LICENSE
=====================================
@@ -0,0 +1,29 @@
+# sourced from https://github.com/scikit-bio/scikit-bio/blob/main/LICENSE.txt
+
+Copyright (c) 2013--, scikit-bio development team.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+  list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice, this
+  list of conditions and the following disclaimer in the documentation and/or
+  other materials provided with the distribution.
+
+* Neither the names scikit-bio, skbio, or biocore nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


=====================================
q2_diversity_lib/skbio/__init__.py
=====================================
@@ -0,0 +1,7 @@
+# ----------------------------------------------------------------------------
+# Copyright (c) 2013--, scikit-bio development team.
+#
+# Distributed under the terms of the Modified BSD License.
+#
+# The full license is in the file LICENSE, distributed with this software.
+# ----------------------------------------------------------------------------


=====================================
q2_diversity_lib/skbio/_methods.py
=====================================
@@ -0,0 +1,79 @@
+import numpy as np
+
+from skbio.diversity._util import _validate_counts_vector
+import skbio.diversity.alpha
+
+from scipy.special import gammaln
+
+
+# c&p methods from skbio
+def _berger_parker(counts):
+    counts = _validate_counts_vector(counts)
+    return counts.max() / counts.sum()
+
+
+def _brillouin_d(counts):
+    counts = _validate_counts_vector(counts)
+    nz = counts[counts.nonzero()]
+    n = nz.sum()
+    return (gammaln(n + 1) - gammaln(nz + 1).sum()) / n
+
+
+def _simpsons_dominance(counts):
+    counts = _validate_counts_vector(counts)
+    return 1 - skbio.diversity.alpha.dominance(counts)
+
+
+def _esty_ci(counts):
+    counts = _validate_counts_vector(counts)
+
+    f1 = skbio.diversity.alpha.singles(counts)
+    f2 = skbio.diversity.alpha.doubles(counts)
+    n = counts.sum()
+    z = 1.959963985
+    W = (f1 * (n - f1) + 2 * n * f2) / (n ** 3)
+
+    return f1 / n - z * np.sqrt(W), f1 / n + z * np.sqrt(W)
+
+
+def _goods_coverage(counts):
+    counts = _validate_counts_vector(counts)
+    f1 = skbio.diversity.alpha.singles(counts)
+    N = counts.sum()
+    return 1 - (f1 / N)
+
+
+def _margalef(counts):
+    counts = _validate_counts_vector(counts)
+    # replaced observed_otu call to sobs
+    return (skbio.diversity.alpha.sobs(counts) - 1) / np.log(counts.sum())
+
+
+def _mcintosh_d(counts):
+    counts = _validate_counts_vector(counts)
+    u = np.sqrt((counts * counts).sum())
+    n = counts.sum()
+    return (n - u) / (n - np.sqrt(n))
+
+
+def _strong(counts):
+    counts = _validate_counts_vector(counts)
+    n = counts.sum()
+    # replaced observed_otu call to sobs
+    s = skbio.diversity.alpha.sobs(counts)
+    i = np.arange(1, len(counts) + 1)
+    sorted_sum = np.sort(counts)[::-1].cumsum()
+    return (sorted_sum / n - (i / s)).max()
+
+
+def _p_evenness(counts):
+    counts = _validate_counts_vector(counts)
+    return _shannon(counts, base=np.e) / np.log(
+        skbio.diversity.alpha.sobs(counts=counts))
+
+
+def _shannon(counts, base=2):
+    counts = _validate_counts_vector(counts)
+    freqs = counts / counts.sum()
+    nonzero_freqs = freqs[freqs.nonzero()]
+    return -(nonzero_freqs * np.log(nonzero_freqs)).sum() / np.log(base)


=====================================
q2_diversity_lib/skbio/test_methods.py
=====================================
@@ -0,0 +1,76 @@
+import numpy as np
+import numpy.testing as npt
+
+from qiime2.plugin.testing import TestPluginBase
+
+from q2_diversity_lib.skbio._methods import (_berger_parker, _brillouin_d,
+                                             _simpsons_dominance, _esty_ci,
+                                             _goods_coverage, _margalef,
+                                             _mcintosh_d, _strong)
+
+
+class SkbioTests(TestPluginBase):
+    package = 'q2_diversity_lib.skbio'
+
+# tests for passthrough metrics were sourced from skbio
+    def test_berger_parker_d(self):
+        self.assertEqual(_berger_parker(np.array([5, 5])), 0.5)
+        self.assertEqual(_berger_parker(np.array([1, 1, 1, 1, 0])), 0.25)
+
+    def test_brillouin_d(self):
+        self.assertAlmostEqual(_brillouin_d(np.array([1, 2, 0, 0, 3, 1])),
+                               0.86289353018248782)
+
+    def test_esty_ci(self):
+        def _diversity(indices, f):
+            """Calculate diversity index for each window of size 1.
+            indices: vector of indices of taxa
+            f: f(counts) -> diversity measure
+            """
+            result = []
+            max_size = max(indices) + 1
+            freqs = np.zeros(max_size, dtype=int)
+            for i in range(len(indices)):
+                freqs += np.bincount(indices[i:i + 1], minlength=max_size)
+                try:
+                    curr = f(freqs)
+                except (ZeroDivisionError, FloatingPointError):
+                    curr = 0
+                result.append(curr)
+            return np.array(result)
+
+        data = [1, 1, 2, 1, 1, 3, 2, 1, 3, 4]
+
+        observed_lower, observed_upper = zip(*_diversity(data, _esty_ci))
+
+        expected_lower = np.array([1, -1.38590382, -0.73353593, -0.17434465,
+                                   -0.15060902, -0.04386191, -0.33042054,
+                                   -0.29041008, -0.43554755, -0.33385652])
+        expected_upper = np.array([1, 1.38590382, 1.40020259, 0.67434465,
+                                   0.55060902, 0.71052858, 0.61613483,
+                                   0.54041008, 0.43554755, 0.53385652])
+
+        npt.assert_array_almost_equal(observed_lower, expected_lower)
+        npt.assert_array_almost_equal(observed_upper, expected_upper)
+
+    def test_simpson(self):
+        self.assertAlmostEqual(_simpsons_dominance(np.array([1, 0, 2, 5, 2])),
+                               0.66)
+        self.assertAlmostEqual(_simpsons_dominance(np.array([5])), 0)
+
+    def test_goods_coverage(self):
+        counts = [1] * 75 + [2, 2, 2, 2, 2, 2, 3, 4, 4]
+        obs = _goods_coverage(counts)
+        self.assertAlmostEqual(obs, 0.23469387755)
+
+    def test_margalef(self):
+
+        self.assertEqual(_margalef(np.array([0, 1, 1, 4, 2, 5, 2, 4, 1, 2])),
+                         8 / np.log(22))
+
+    def test_mcintosh_d(self):
+        self.assertAlmostEqual(_mcintosh_d(np.array([1, 2, 3])),
+                               0.636061424871458)
+
+    def test_strong(self):
+        self.assertAlmostEqual(_strong(np.array([1, 2, 3, 1])), 0.214285714)


=====================================
q2_diversity_lib/tests/test_alpha.py
=====================================
@@ -9,6 +9,7 @@
 from subprocess import CalledProcessError
 
 import numpy as np
+import numpy.testing as npt
 import pandas as pd
 import pandas.testing as pdt
 import biom
@@ -17,7 +18,12 @@ from qiime2.plugin.testing import TestPluginBase
 from qiime2 import Artifact
 
 from ..alpha import (pielou_evenness, observed_features,
-                     shannon_entropy, METRICS)
+                     shannon_entropy, METRICS,
+                     _berger_parker, _brillouin_d,
+                     _simpsons_dominance, _esty_ci,
+                     _goods_coverage, _margalef,
+                     _mcintosh_d, _strong
+                     )
 
 
 class SmokeTests(TestPluginBase):
@@ -154,7 +160,9 @@ class PielouEvennessTests(TestPluginBase):
                                          [0, 0, 0, 1, 0, 1]]),
                                ['A', 'B', 'C'],
                                ['S1', 'S2', 'S3', 'S4', 'S5', 'S6'])
-        expected = pd.Series({'S5': 1, 'S6': 1}, name='pielou_evenness')
+        # pandas supports floating point correction for float dtype only,
+        # these 1 ints were changed to 1.0 floats to get that support
+        expected = pd.Series({'S5': 1.0, 'S6': 1.0}, name='pielou_evenness')
         actual = pielou_evenness(table=NaN_table, drop_undefined_samples=True)
         pdt.assert_series_equal(actual, expected, check_dtype=False)
 
@@ -250,3 +258,68 @@ class AlphaPassthroughTests(TestPluginBase):
         for metric in METRICS['NONPHYLO']['IMPL']:
             with self.assertRaisesRegex(TypeError, f"{metric}.*incompatible"):
                 self.method(table=self.crawford_tbl, metric=metric)
+
+# tests for passthrough metrics were sourced from skbio
+    def test_berger_parker_d(self):
+        self.assertEqual(_berger_parker(np.array([5, 5])), 0.5)
+        self.assertEqual(_berger_parker(np.array([1, 1, 1, 1, 0])), 0.25)
+
+    def test_brillouin_d(self):
+        self.assertAlmostEqual(_brillouin_d(np.array([1, 2, 0, 0, 3, 1])),
+                               0.86289353018248782)
+
+    def test_esty_ci(self):
+        def _diversity(indices, f):
+            """Calculate diversity index for each window of size 1.
+
+            indices: vector of indices of taxa
+            f: f(counts) -> diversity measure
+
+            """
+            result = []
+            max_size = max(indices) + 1
+            freqs = np.zeros(max_size, dtype=int)
+            for i in range(len(indices)):
+                freqs += np.bincount(indices[i:i + 1], minlength=max_size)
+                try:
+                    curr = f(freqs)
+                except (ZeroDivisionError, FloatingPointError):
+                    curr = 0
+                result.append(curr)
+            return np.array(result)
+
+        data = [1, 1, 2, 1, 1, 3, 2, 1, 3, 4]
+
+        observed_lower, observed_upper = zip(*_diversity(data, _esty_ci))
+
+        expected_lower = np.array([1, -1.38590382, -0.73353593, -0.17434465,
+                                   -0.15060902, -0.04386191, -0.33042054,
+                                   -0.29041008, -0.43554755, -0.33385652])
+        expected_upper = np.array([1, 1.38590382, 1.40020259, 0.67434465,
+                                   0.55060902, 0.71052858, 0.61613483,
+                                   0.54041008, 0.43554755, 0.53385652])
+
+        npt.assert_array_almost_equal(observed_lower, expected_lower)
+        npt.assert_array_almost_equal(observed_upper, expected_upper)
+
+    def test_simpson(self):
+        self.assertAlmostEqual(_simpsons_dominance(np.array([1, 0, 2, 5, 2])),
+                               0.66)
+        self.assertAlmostEqual(_simpsons_dominance(np.array([5])), 0)
+
+    def test_goods_coverage(self):
+        counts = [1] * 75 + [2, 2, 2, 2, 2, 2, 3, 4, 4]
+        obs = _goods_coverage(counts)
+        self.assertAlmostEqual(obs, 0.23469387755)
+
+    def test_margalef(self):
+
+        self.assertEqual(_margalef(np.array([0, 1, 1, 4, 2, 5, 2, 4, 1, 2])),
+                         8 / np.log(22))
+
+    def test_mcintosh_d(self):
+        self.assertAlmostEqual(_mcintosh_d(np.array([1, 2, 3])),
+                               0.636061424871458)
+
+    def test_strong(self):
+        self.assertAlmostEqual(_strong(np.array([1, 2, 3, 1])), 0.214285714)



View it on GitLab: https://salsa.debian.org/med-team/q2-diversity-lib/-/compare/3f1b61bc9258f399556931575b26a204db0628b2...168f4089abeb656040e19e85ab771232f03b076d

-- 
This project does not include diff previews in email notifications.
View it on GitLab: https://salsa.debian.org/med-team/q2-diversity-lib/-/compare/3f1b61bc9258f399556931575b26a204db0628b2...168f4089abeb656040e19e85ab771232f03b076d
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/20240625/7e9cf84f/attachment-0001.htm>


More information about the debian-med-commit mailing list