Skip to content

Release 4.0.2: vectorize reciprocal ANI averaging (issue #308) - #309

Merged
MrOlm merged 2 commits into
masterfrom
claude/cloud-persistence-sessions-bybcsb
Sep 30, 2026
Merged

MrOlm merged 2 commits into
masterfrom
claude/cloud-persistence-sessions-bybcsb

Conversation

@MrOlm

@MrOlm MrOlm commented Sep 30, 2026

Copy link
Copy Markdown
Owner

Summary

Speeds up secondary clustering on large primary clusters. This matters most for same-species datasets, where everything falls into one primary cluster (#308). Also bumps the version to 4.0.2.

  • add_avani (drep/d_cluster/external.py) averages the two directions of each ANI comparison before clustering. It used to call iterrows() on every row of Ndb and build a string-keyed dict. For one 28k-genome primary cluster that's ~811M rows: hours of runtime and far too much memory. It now encodes each (reference, querry) pair as an integer and looks up the reverse pairs in bulk.
  • The output is identical. This includes the last-duplicate-wins behavior, NaN propagation, and the KeyError raised when a reverse pair is missing.
  • drep/VERSION goes to 4.0.2, and the changelog gets a dated 4.0.2 entry.

Performance

_cluster_Ndb on synthetic single-cluster edge tables:

genomes before after
1,000 34.1 s 1.1 s
2,000 133.0 s 5.9 s
4,000 — 26.8 s

build_ndb_from_edges is now the bottleneck on this path. It took 43 s and ~7 GB at 4k genomes, and both grow quadratically. Making 28k same-species genomes truly tractable would need secondary clustering to build its distance matrix directly instead of the long-form Ndb. That's out of scope here.

Testing

  • Old vs new add_avani: gave identical av_ani on a 3,630-row table that included duplicate pairs, a NaN, and mixed path/bare genome names.
  • End to end: dRep dereplicate on 400 simulated same-species genomes completes. Re-clustering its Ndb with the original settings reproduces the original clusters and winners exactly.
  • tests/tests/test_cluster.py: passes except test_goANI and test_goANI2, which need nsimscan (not installed in the test environment).
  • Rest of tests/tests: 67 passed, 11 skipped, 2 failed. Neither failure comes from this change:
    • test_dereplicate_3 needs nsimscan.
    • test_drep_scaffold_level fails the same way with the old add_avani, and that script doesn't call it.

🤖 Generated with Claude Code

https://claude.ai/code/session_013UpcPFwkh6QMusnD6ApThL


Generated by Claude Code

add_avani looped over every Ndb row with iterrows() into a string-keyed
dict. On a single large primary cluster (e.g. 28k same-species genomes)
that is ~811M rows, taking hours and far too much memory. Encode each
(reference, querry) pair as an integer and look up reverse pairs in bulk
instead. Output is identical, including duplicate and NaN handling and
the KeyError on a missing reverse pair; clustering a 2,000-genome
primary cluster goes from 133s to 6s.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013UpcPFwkh6QMusnD6ApThL
Bump the version and date the changelog. The fix is the vectorized
reciprocal ANI averaging that makes large single-species primary
clusters cluster ~25-30x faster (issue #308).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013UpcPFwkh6QMusnD6ApThL
@MrOlm
MrOlm merged commit bf1d014 into master Sep 30, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants