GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Score all sequence pairs without building alignments (GLOBAL, LOCAL): 27-286x faster getAllPairsScores by mikepapadim · Pull Request #1161 · biojava/biojava

Conversation

@mikepapadim

@mikepapadim mikepapadim commented Oct 28, 2026

Copy link
Copy Markdown

Follow-up to #1158, proposal (1): a CPU-only fast path, no new dependencies.

What

Alignments.getAllPairsScores built a full NeedlemanWunsch/SmithWaterman alignment for every pair, with a traceback matrix of objects per cell, only to read its score. So did the pairwise stage of getMultipleSequenceAlignment. For GLOBAL and LOCAL scoring the score needs only the last row of the dynamic-programming matrix.

The new package-private AllPairsScores scores each pair in linear memory on primitive arrays:

  • It uses the recurrences of AlignerHelper, linear and affine, so the scores are exactly the aligners'.
  • The scorers it returns for the guide tree have the aligners' maximum and minimum scores, hence the same distances and the same MSA.
  • Pairs run on the ConcurrencyTools pool, one task per query sequence, so ConcurrencyTools.setThreadPoolSize still applies.

Other scorer types (*_IDENTITIES, *_SIMILARITIES, KMERS, WU_MANBER), fewer than two sequences, an empty sequence or mixed compound sets take the existing path unchanged. No public API changes.

Speed

getAllPairsScores, BLOSUM62, gaps 10/1, best of 3 after 2 warm-ups. i9-13900K (32 threads), JDK 21, ConcurrencyTools default pool. The machine was also running other jobs, so read the ratios rather than the absolute times. The checksum of all scores is identical on both branches.

Input Pairs master this PR Speed-up
200 random proteins, 100–500 aa, GLOBAL 19,900 13.9 s 0.51 s 27×
same, LOCAL 19,900 13.1 s 0.33 s 40×
Pfam PF00104 (283 sequences), GLOBAL 39,903 552.6 s 1.93 s 286×

On PF00104, master is dominated by allocating and collecting the per-cell traceback objects of long sequences.

Tests

AllPairsScoresTest (8 tests). For every pair it compares score, max, min, distance and similarity against getAllPairsScorers + the aligners. Inputs:

  • random and related (mutated) proteins;
  • rare compounds (X B Z U *);
  • lengths from 1 to 300, including identical sequences;
  • DNA with NUC.4.4;
  • six gap penalties (linear and affine) and three matrices (BLOSUM62, BLOSUM30, PAM250).

It also checks that getMultipleSequenceAlignment gives the same profile as before for GLOBAL and LOCAL.

The whole biojava-alignment suite passes: 135 tests, 0 failures.

A bug this found in the existing path

SmithWaterman with a linear gap penalty throws ArrayIndexOutOfBoundsException for a pair that has no positive substitution score, e.g. W vs MK with BLOSUM62. The exception is in its traceback. getListFromFutures logs and drops the failed future, so runPairwiseScorers returns fewer scores than pairs, and every later score sits at the wrong index. The local score of such a pair is 0. That is what SmithWaterman returns with an affine penalty, and what this PR returns for both. noPositiveLocalCell documents it. I left SmithWaterman itself alone; happy to fix it in a separate PR if you like.

How to run

git fetch https://github.com/mikepapadim/biojava.git perf/all-pairs-scores && git checkout FETCH_HEAD
mvn -pl biojava-alignment -am install -DskipTests
mvn -pl biojava-alignment test -Dtest=AllPairsScoresTest                # parity with the aligners
mvn -pl biojava-alignment test                                          # whole module

To time it yourself, a minimal program (run it against master and this branch):

var seqs = new ArrayList<ProteinSequence>();          // e.g. FastaReaderHelper.readFastaProteinSequence(file).values()
var scores = Alignments.getAllPairsScores(seqs, PairwiseSequenceScorerType.GLOBAL,
        new SimpleGapPenalty(10, 1), SubstitutionMatrixHelper.getBlosum62());
ConcurrencyTools.shutdown();

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@mikepapadim
Score all sequence pairs without building alignments (GLOBAL, LOCAL)
c9a3f6f
Alignments.getAllPairsScores, and the pairwise stage of
getMultipleSequenceAlignment, built a full NeedlemanWunsch or SmithWaterman
alignment for every pair, with a traceback matrix of objects per cell, only
to read its score. For GLOBAL and LOCAL scoring the score needs only the last
row of the dynamic programming matrix.

AllPairsScores scores each pair in linear memory on primitive arrays, with
the recurrences of AlignerHelper (linear and affine gap penalties), so the
scores are exactly the aligners'. The scorers it returns for the guide tree
have the aligners' maximum and minimum scores, hence the same distances and
the same multiple alignment. Pairs run on the ConcurrencyTools pool, one task
per query sequence. Other scorer types, a single sequence, an empty sequence
or mixed compound sets take the existing path.

AllPairsScoresTest checks scores, maximum, minimum, distance and similarity
of every pair against the aligners for random and related proteins, rare
compounds, very different lengths, DNA, six gap penalties and three
matrices, and the multiple alignment for GLOBAL and LOCAL.

SmithWaterman with a linear gap penalty throws for a pair with no positive
substitution score (ArrayIndexOutOfBoundsException in its traceback), and
getListFromFutures drops that pair's score, so runPairwiseScorers returns
fewer scores than pairs. The local score of such a pair is 0, which is what
the new path returns; noPositiveLocalCell documents the case.
This was referenced Oct 28, 2026
GPU offload via TornadoVM: 570× faster all-pairs alignment, 18× faster ASA, identical results #1158
Open
biojava-tornadovm: opt-in GPU paths for ASA and all-pairs alignment scores (TornadoVM 8.0.0) #1162
Open
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

No reviews

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

1 participant

@mikepapadim
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.