From bbec76c7e5b9118755b0ed1741a46bd563cf38ac Mon Sep 17 00:00:00 2001 From: John Huddleston Date: Tue, 23 Jul 2024 14:52:43 -0700 Subject: [PATCH 1/3] Fix titer substitution model tree annotations Fixes a bug in the `augur titers sub` tree annotations in the JSON output where antigenic weights were assigned per branch for the opposite substitution values than expected. Specifically, the bug caused each branch to get the antigenic weight associated with substitutions in the form of "" instead of "". For example, when the substitution model found antigenic weights for HA1 substitutions N193S and S193N, the tree annotations would have assigned the N193S weight to branches with the S193N substitution. This commit expands an existing functional test to check for a data-specific antigenic weight. After confirming this test failed, I fixed the bug and confirmed that the test passed. Note that this bug dates back to December 2018 when I first added the code to annotate the tree with the substitution model weights [1]. This bug had no impact on the accuracy of the underlying model itself, so we would never have noticed it without manually comparing the titer drops in the tree to the "substitution" array in the JSON output. [1] https://github.com/nextstrain/augur/commit/6721b7d67193361b9b41906e7cbc1d0346289350#diff-96cfc90794aa092cbb7b8577ca92d5757a777325d78078da3761ea26ee4c5956R67 --- augur/titer_model.py | 2 +- tests/functional/titers/cram/titers-sub-with-tree.t | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/augur/titer_model.py b/augur/titer_model.py index 0ff2b9167..92b213be0 100644 --- a/augur/titer_model.py +++ b/augur/titer_model.py @@ -1142,7 +1142,7 @@ def annotate_tree(self, tree): for node in tree.find_clades(): for child in node.clades: # Get mutations between the current node and its parent. - mutations = self.get_mutations(child.name, node.name) + mutations = self.get_mutations(node.name, child.name) # Calculate titer drop on the branch to the current node. child.dTiterSub = 0 diff --git a/tests/functional/titers/cram/titers-sub-with-tree.t b/tests/functional/titers/cram/titers-sub-with-tree.t index a8804e441..5e97cae8a 100644 --- a/tests/functional/titers/cram/titers-sub-with-tree.t +++ b/tests/functional/titers/cram/titers-sub-with-tree.t @@ -17,3 +17,11 @@ Test titer substitution model with alignment and tree inputs. --- 272 total measurements $ grep cTiterSub $TMP/titers-sub.json | wc -l \s*120 (re) + +Verify that the titer drops assigned per branch correspond to the expected values for this dataset. +In this example, we know that the HA1 amino acid sequence for A/Fujian/445/2003 carries a S193N substitution and that the titer model assigns a weight of 0.6 to that substitution. +The titer model assigns a higher weight of 1.22 to the opposite substitution N193S. +When we search for that sequence's per-branch titer drop, we should get the smaller value below. + + $ grep -A 3 '"A/Fujian/445/2003": {' $TMP/titers-sub.json | grep dTiterSub + \s*"dTiterSub": 0.60.* (re) From dea89c5dee74bca49eba07b0743440ee3ce14a27 Mon Sep 17 00:00:00 2001 From: John Huddleston Date: Tue, 23 Jul 2024 15:06:11 -0700 Subject: [PATCH 2/3] Note bug fix in change log --- CHANGES.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 89ea757d2..75e9de3c0 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -8,8 +8,13 @@ * traits, export v2: `augur traits` now reports all confidence values above 0.1% rather than limiting them to the top 4 results. There is no change in the eventual Auspice dataset as `augur export v2` will still only consider the top 4. [#1512][] (@jameshadfield) * curate: Excel (`.xlsx` and `.xls`) and OpenOffice (`.ods`) spreadsheet files are now also supported as metadata inputs (`--metadata`). The first sheet in the workbook is read as tabular data. [#1550][] (@tsibley) +### Bug Fixes + +* titers sub: Fixes a bug where antigenic weights were assigned to branches for substitutions in the incorrect order of `` instead of ``. [#1555][] (@huddlej) + [#1512]: https://github.com/nextstrain/augur/pull/1512 [#1550]: https://github.com/nextstrain/augur/pull/1550 +[#1555]: https://github.com/nextstrain/augur/pull/1555 ## 25.1.1 (15 July 2024) From 4846fbb0b405e833c7f4773ad1a3f210d794fe58 Mon Sep 17 00:00:00 2001 From: John Huddleston Date: Tue, 23 Jul 2024 16:13:13 -0700 Subject: [PATCH 3/3] Update tests/functional/titers/cram/titers-sub-with-tree.t Co-authored-by: Thomas Sibley --- tests/functional/titers/cram/titers-sub-with-tree.t | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/functional/titers/cram/titers-sub-with-tree.t b/tests/functional/titers/cram/titers-sub-with-tree.t index 5e97cae8a..ea8a2e176 100644 --- a/tests/functional/titers/cram/titers-sub-with-tree.t +++ b/tests/functional/titers/cram/titers-sub-with-tree.t @@ -23,5 +23,5 @@ In this example, we know that the HA1 amino acid sequence for A/Fujian/445/2003 The titer model assigns a higher weight of 1.22 to the opposite substitution N193S. When we search for that sequence's per-branch titer drop, we should get the smaller value below. - $ grep -A 3 '"A/Fujian/445/2003": {' $TMP/titers-sub.json | grep dTiterSub - \s*"dTiterSub": 0.60.* (re) + $ python3 -c 'import json, sys; print(json.load(sys.stdin)["nodes"]["A/Fujian/445/2003"]["dTiterSub"])' < $TMP/titers-sub.json + 0.60* (glob)