Skip to content

Support opposite direction vectors in align_vectors - #1033

Open
davrens101 wants to merge 2 commits into
biotite-dev:mainfrom
davrens101:fix-align-opposite-vectors
Open

davrens101 wants to merge 2 commits into
biotite-dev:mainfrom
davrens101:fix-align-opposite-vectors

Conversation

@davrens101

Copy link
Copy Markdown

Description

Currently, biotite.structure.align_vectors() raises a ValueError when origin_direction and target_direction point in opposite directions:

ValueError: Direction vectors are point into opposite directions, cannot calculate rotation matrix

This limitation occurs because the standard rotation formula uses $(v \times w) / (1 + \cos\alpha)$, where $1 + \cos\alpha = 0$ when $\cos\alpha = -1$. Furthermore, in single-precision floating point arithmetic, directions that are nearly opposite can also evaluate to cos_a == -1.0 due to precision limits.

Mathematically, aligning two anti-parallel vectors in 3D corresponds to a 180° rotation around any axis perpendicular to the vectors. This PR resolves the singularity by choosing an orthogonal axis and constructing the corresponding 180° reflection-rotation ($R = 2 u u^T - I \in \mathrm{SO}(3)$).

Changes

  • In align_vectors(), when $\cos\alpha \le -1 + 10^{-6}$, find an orthogonal unit vector $u \perp v$ and construct the 180° rotation matrix $R = 2 u u^T - I$.
  • Added unit test test_align_vectors_opposite() verifying that anti-parallel vectors in arbitrary directions align to the target vector with determinant 1 and orthogonality preserved.

AI assistance disclosure: Co-authored with AI coding assistant.

Signed-off-by: Davis Rens <166565828+davrens101@users.noreply.github.com>
@codspeed

codspeed Bot commented Nov 11, 2026

Copy link
Copy Markdown

Merging this PR will degrade performance by 43.55%

❌ 16 regressed benchmarks
✅ 95 untouched benchmarks
⏩ 14 skipped benchmarks1

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Benchmark BASE HEAD Efficiency
❌ benchmark_find_rotatable_bonds 26.7 ms 177.2 ms -84.92%
❌ benchmark_hbond 10.1 ms 29.6 ms -65.77%
❌ benchmark_superimpose[superimpose] 643.7 µs 1,727 µs -62.73%
❌ benchmark_similar_kmers 197.3 µs 481.8 µs -59.04%
❌ benchmark_get_assembly 835.9 ms 1,595.1 ms -47.59%
❌ benchmark_score_threshold_rule[11*11*1*1***111] 2 s 3.5 s -43.26%
❌ benchmark_score_threshold_rule[None] 2 s 3.5 s -43.18%
❌ benchmark_superimpose[superimpose_homologs] 33.6 ms 56.5 ms -40.6%
❌ benchmark_superimpose_multi_model[superimpose_homologs] 44.8 ms 67.4 ms -33.47%
❌ benchmark_structural_alphabet_methods[to_3di] 14.1 ms 21.2 ms -33.44%
❌ benchmark_superimpose[superimpose_structural_homologs] 35.8 ms 51.9 ms -31.08%
❌ benchmark_match_kmer_selection[KmerTable-None] 526.4 µs 641.9 µs -18%
❌ benchmark_set_structure[bcif-True] 32.8 ms 39.1 ms -16.05%
❌ benchmark_match_kmer_selection[BucketKmerTable(10000)-11*11*1*1***111] 652.7 µs 766.4 µs -14.85%
❌ benchmark_set_structure[bcif-False] 15.1 ms 17.7 ms -14.51%
❌ benchmark_match[BucketKmerTable(10000)-11*11*1*1***111] 838.9 µs 954.3 µs -12.09%

Tip

Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.


Comparing davrens101:fix-align-opposite-vectors (9690ca5) with main (2effe8f)2

Open in CodSpeed

Footnotes

  1. 14 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports. ↩

  2. No successful run was found on main (f7eb9c6) during the generation of this report, so 2effe8f was used instead as the comparison base. There might be some changes unrelated to this pull request in this report. ↩

This branch has not been deployed

No deployments
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.

1 participant