Skip to content

Fix Numpy 2.4 compatibility in PDB/vectors.py#5138

Closed
Augustin-Zidek wants to merge 8 commits intobiopython:masterfrom
Augustin-Zidek:patch-2
Closed

Fix Numpy 2.4 compatibility in PDB/vectors.py#5138
Augustin-Zidek wants to merge 8 commits intobiopython:masterfrom
Augustin-Zidek:patch-2

Conversation

@Augustin-Zidek
Copy link
Copy Markdown

  • I hereby agree to dual licence this and any previous contributions under both
    the Biopython License Agreement AND the BSD 3-Clause License.

  • I have read the CONTRIBUTING.rst file, have run pre-commit
    locally, and understand that continuous integration checks will be used to
    confirm the Biopython unit tests and style checks pass with these changes.

  • I have added my name to the alphabetical contributors listings in the files
    NEWS.rst and CONTRIB.rst as part of this pull request, am listed
    already, or do not wish to be listed. (This acknowledgement is optional.)

This addresses the expired deprecation in Numpy 2.4: https://numpy.org/devdocs/release/2.4.0-notes.html#raise-typeerror-on-attempt-to-convert-array-with-ndim-0-to-scalar

Closes #5135

Comment thread CONTRIB.rst
@codecov
Copy link
Copy Markdown

codecov bot commented Jan 12, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 86.41%. Comparing base (54a8eda) to head (f117e91).

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #5138      +/-   ##
==========================================
+ Coverage   85.52%   86.41%   +0.89%     
==========================================
  Files         282      282              
  Lines       59497    59499       +2     
==========================================
+ Hits        50882    51418     +536     
+ Misses       8615     8081     -534     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@peterjc
Copy link
Copy Markdown
Member

peterjc commented Jan 13, 2026

@mdehoon you're probably more familar with NumPy than me, does this look good to merge? Thanks!

Comment thread Bio/PDB/vectors.py Outdated
@peterjc
Copy link
Copy Markdown
Member

peterjc commented Jan 17, 2026

Is this one line change not enough to fix it?

❯ git diff --no-ext-diff
diff --git a/Bio/PDB/vectors.py b/Bio/PDB/vectors.py
index 14a23a821..d4cc56644 100644
--- a/Bio/PDB/vectors.py
+++ b/Bio/PDB/vectors.py
@@ -559,7 +559,7 @@ def coord_space(

     # tx acs[1] to origin
     # tm = homog_trans_mtx(-a1[0][0], -a1[1][0], -a1[2][0])
-    set_homog_trans_mtx(-a1[0], -a1[1], -a1[2], tm)
+    set_homog_trans_mtx(-a1[0, 0], -a1[1, 0], -a1[2, 0], tm)

     # directly translate a2 using a1
     p = a2 - a1

@Augustin-Zidek
Copy link
Copy Markdown
Author

Yeah, that looks reasonable as well and more minimal -- I like it. I will test that on Monday.

@Augustin-Zidek
Copy link
Copy Markdown
Author

I tested this and changing that single line is not enough, all of the changes are needed. However, instead of

set_homog_trans_mtx(a1[0].item(), a1[1].item(), a1[2].item(), tm)

one could do:

set_homog_trans_mtx(a1[0, 0], a1[1, 0], a1[2, 0], tm)

But the changes to set_Z_homog_rot_mtx and set_Y_homog_rot_mtx are still necessary.

@peterjc
Copy link
Copy Markdown
Member

peterjc commented Jan 19, 2026

Can you combine this then please? The .item() bit is ugly, and likely less efficient than the explicit indexing. Thanks!

@Augustin-Zidek
Copy link
Copy Markdown
Author

All done + I also changed it to use math for trigonometric functions instead of Numpy where you suggested. This uncovered a few more issues with passing non-scalar values which I fixed. See the latest commit.

Comment thread Bio/PDB/vectors.py Outdated
sinang = math.sin(angle_rads)

mtx[0][0] = mtx[1][1] = cosang
mtx[0][0] = cosang
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These lines feel odd, like it was written before double indexing was possible. Does mtx[0, 0] et work here?

Comment thread Bio/PDB/vectors.py Outdated
set_Z_homog_rot_mtx(-sc[1], mrz)
# rotate translated a2 -polar_angle about Y
set_Y_homog_rot_mtx(-sc[2], mry)
set_Y_homog_rot_mtx(-sc[2][0], mry)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks link -sc[2, 0] should work here as well or better than -cs[2][0] does.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, the linter is unhappy:


Bio/PDB/vectors.py: note: In function "coord_space":
Bio/PDB/vectors.py:576:26: error: Value of type "float" is not indexable 
[index]
        set_Y_homog_rot_mtx(-sc[2][0], mry)
                             ^~~~~~~~
Bio/PDB/vectors.py:623:25: error: Value of type "float" is not indexable 
[index]
        set_Y_homog_rot_mtx(sc[2][0], mry)
                            ^~~~~~~~
Found 2 errors in 1 file (checked 298 source files)

@JoaoRodrigues
Copy link
Copy Markdown
Member

These changes look good to me, thanks for the updates and thanks Peter for the reviews 🙏

@peterjc
Copy link
Copy Markdown
Member

peterjc commented Feb 19, 2026

This was failing, and I just merged #5165 which caused the conflicts.

@peterjc
Copy link
Copy Markdown
Member

peterjc commented Feb 19, 2026

Linting failure from last month still there:

Bio/PDB/vectors.py: note: In function "coord_space":
Bio/PDB/vectors.py:572:26: error: Value of type "float" is not indexable 
[index]
        set_Y_homog_rot_mtx(-sc[2][0], mry)
                             ^~~~~~~~
Bio/PDB/vectors.py:617:25: error: Value of type "float" is not indexable 
[index]
        set_Y_homog_rot_mtx(sc[2][0], mry)
                            ^~~~~~~~
Found 2 errors in 1 file (checked 298 source files)

@peterjc
Copy link
Copy Markdown
Member

peterjc commented Feb 19, 2026

Huh, a new failure:

======================================================================
ERROR: test_i2a_start_fin (test_PDB_internal_coords.Rebuild)
Test assemble start/fin, default NCaC coordinates, IC_duplicate.
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/circleci/project/biopython-1.87.dev0/Tests/test_PDB_internal_coords.py", line 465, in test_i2a_start_fin
    cpy.internal_to_atom_coordinates(start=31, fin=45)
  File "/home/circleci/.pyenv/versions/3.10.19/lib/python3.10/site-packages/Bio/PDB/Chain.py", line 218, in internal_to_atom_coordinates
    self.internal_coord.internal_to_atom_coordinates(
  File "/home/circleci/.pyenv/versions/3.10.19/lib/python3.10/site-packages/Bio/PDB/internal_coords.py", line 1614, in internal_to_atom_coordinates
    self.assemble_residues_ser(
  File "/home/circleci/.pyenv/versions/3.10.19/lib/python3.10/site-packages/Bio/PDB/internal_coords.py", line 1258, in assemble_residues_ser
    atom_coords = ric.assemble(verbose=verbose)
  File "/home/circleci/.pyenv/versions/3.10.19/lib/python3.10/site-packages/Bio/PDB/internal_coords.py", line 2937, in assemble
    d.cst, d.rcst = coord_space(acs[0], acs[1], acs[2], True)
  File "/home/circleci/.pyenv/versions/3.10.19/lib/python3.10/site-packages/Bio/PDB/vectors.py", line 559, in coord_space
    set_homog_trans_mtx(-a1[0, 0], -a1[1, 0], -a1[2, 0], tm)
IndexError: too many indices for array: array is 1-dimensional, but 2 were indexed

======================================================================
ERROR: test_write_SCAD (test_PDB_internal_coords.Rebuild)
Check SCAD output plus MaxPeptideBond and Gly CB.
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/circleci/.pyenv/versions/3.10.19/lib/python3.10/site-packages/Bio/File.py", line 72, in as_handle
    with open(handleish, mode, **kwargs) as fp:
TypeError: expected str, bytes or os.PathLike object, not StringIO

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/circleci/project/biopython-1.87.dev0/Tests/test_PDB_internal_coords.py", line 363, in test_write_SCAD
    write_SCAD(
  File "/home/circleci/.pyenv/versions/3.10.19/lib/python3.10/site-packages/Bio/PDB/SCADIO.py", line 239, in write_SCAD
    chn.internal_coord._write_SCAD(
  File "/home/circleci/.pyenv/versions/3.10.19/lib/python3.10/site-packages/Bio/PDB/internal_coords.py", line 1823, in _write_SCAD
    ric.assemble(resetLocation=True)
  File "/home/circleci/.pyenv/versions/3.10.19/lib/python3.10/site-packages/Bio/PDB/internal_coords.py", line 2926, in assemble
    d.cst, d.rcst = coord_space(
  File "/home/circleci/.pyenv/versions/3.10.19/lib/python3.10/site-packages/Bio/PDB/vectors.py", line 559, in coord_space
    set_homog_trans_mtx(-a1[0, 0], -a1[1, 0], -a1[2, 0], tm)
IndexError: too many indices for array: array is 1-dimensional, but 2 were indexed

----------------------------------------------------------------------
Ran 501 tests in 725.870 seconds

@Augustin-Zidek I may have broken this with the merge resolution?

--

I am increasingly of the view that it is the data structure in the test is odd, and only worked due to a historical oddity in numpy and need not be supported - i.e. let's just merge #5161 to change the test?

@Augustin-Zidek
Copy link
Copy Markdown
Author

Augustin-Zidek commented Feb 19, 2026

Hey, sorry for the delay. I added one more commit that should fix things.

@Augustin-Zidek
Copy link
Copy Markdown
Author

I believe the change is now smaller (just 3 changed lines) and the tests are green on my side.

Comment thread Bio/PDB/vectors.py
return (0, 0, 0)
azimuth = _get_azimuth(xyz[0], xyz[1])
polar_angle: float = np.arccos(xyz[2] / r)
polar_angle: float = np.arccos(xyz[2] / r).item()
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this could just be math.acos to ensure a float.

Are there any other uses? I didn't notice this when working on #5165.

@peterjc
Copy link
Copy Markdown
Member

peterjc commented Feb 20, 2026

Did you try the full test suite? CI is reporting:

======================================================================
ERROR: test_i2a_start_fin (test_PDB_internal_coords.Rebuild)
Test assemble start/fin, default NCaC coordinates, IC_duplicate.
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/circleci/project/biopython-1.87.dev0/Tests/test_PDB_internal_coords.py", line 465, in test_i2a_start_fin
    cpy.internal_to_atom_coordinates(start=31, fin=45)
  File "/home/circleci/.pyenv/versions/3.10.19/lib/python3.10/site-packages/Bio/PDB/Chain.py", line 218, in internal_to_atom_coordinates
    self.internal_coord.internal_to_atom_coordinates(
  File "/home/circleci/.pyenv/versions/3.10.19/lib/python3.10/site-packages/Bio/PDB/internal_coords.py", line 1614, in internal_to_atom_coordinates
    self.assemble_residues_ser(
  File "/home/circleci/.pyenv/versions/3.10.19/lib/python3.10/site-packages/Bio/PDB/internal_coords.py", line 1258, in assemble_residues_ser
    atom_coords = ric.assemble(verbose=verbose)
  File "/home/circleci/.pyenv/versions/3.10.19/lib/python3.10/site-packages/Bio/PDB/internal_coords.py", line 2937, in assemble
    d.cst, d.rcst = coord_space(acs[0], acs[1], acs[2], True)
  File "/home/circleci/.pyenv/versions/3.10.19/lib/python3.10/site-packages/Bio/PDB/vectors.py", line 559, in coord_space
    set_homog_trans_mtx(-a1[0, 0], -a1[1, 0], -a1[2, 0], tm)
IndexError: too many indices for array: array is 1-dimensional, but 2 were indexed

======================================================================
ERROR: test_write_SCAD (test_PDB_internal_coords.Rebuild)
Check SCAD output plus MaxPeptideBond and Gly CB.
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/circleci/.pyenv/versions/3.10.19/lib/python3.10/site-packages/Bio/File.py", line 72, in as_handle
    with open(handleish, mode, **kwargs) as fp:
TypeError: expected str, bytes or os.PathLike object, not StringIO

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/circleci/project/biopython-1.87.dev0/Tests/test_PDB_internal_coords.py", line 363, in test_write_SCAD
    write_SCAD(
  File "/home/circleci/.pyenv/versions/3.10.19/lib/python3.10/site-packages/Bio/PDB/SCADIO.py", line 239, in write_SCAD
    chn.internal_coord._write_SCAD(
  File "/home/circleci/.pyenv/versions/3.10.19/lib/python3.10/site-packages/Bio/PDB/internal_coords.py", line 1823, in _write_SCAD
    ric.assemble(resetLocation=True)
  File "/home/circleci/.pyenv/versions/3.10.19/lib/python3.10/site-packages/Bio/PDB/internal_coords.py", line 2926, in assemble
    d.cst, d.rcst = coord_space(
  File "/home/circleci/.pyenv/versions/3.10.19/lib/python3.10/site-packages/Bio/PDB/vectors.py", line 559, in coord_space
    set_homog_trans_mtx(-a1[0, 0], -a1[1, 0], -a1[2, 0], tm)
IndexError: too many indices for array: array is 1-dimensional, but 2 were indexed

----------------------------------------------------------------------
Ran 501 tests in 692.367 seconds

This is part of why I think the test is wrong, and that while the old array input used to work it was not deliberate.

@Augustin-Zidek
Copy link
Copy Markdown
Author

This is part of why I think the test is wrong, and that while the old array input used to work it was not deliberate.

Yes, I ran the full test suite, but not at head, but rather at an older commit that we have mirrored. But I also suspect something being wrong with the test setup, as the shape of the xyz array in get_spherical_coordinates is not consistent.

@Augustin-Zidek
Copy link
Copy Markdown
Author

Ah, found the issue in test_PDB_vectors:

sc = get_spherical_coordinates(
    [
        (0.5 if i else -0.5),
        0.5 if j else -0.5,
        (1 if k else -1) * srt22,
    ]
)

This is calling the function with a list instead of a Numpy array. Moreover, it is a mixture of floats and Numpy floats (since srt22 is a Numpy float).

@Augustin-Zidek
Copy link
Copy Markdown
Author

Augustin-Zidek commented Feb 20, 2026

If I change it to:

xyz = np.array(
    [
        [0.5 if i else -0.5],
        [0.5 if j else -0.5],
        [(1 if k else -1) * srt22],
    ]
)
sc = get_spherical_coordinates(xyz)

and change the code in vactors.py to:

polar_angle: float = math.acos(xyz[2, 0] / r)

it works well.

It might be worth running the type checker on the tests as well as the rest of the code (I am not sure whether you do that).

@Augustin-Zidek
Copy link
Copy Markdown
Author

I sent #5166 with a fix to the test.

@peterjc
Copy link
Copy Markdown
Member

peterjc commented Mar 9, 2026

I have closed #5135 with the expedient route of changing the failing test.

There may be a real failure with unusual inputs, so there's a good chance we'll have to reopen that issue once a new use case is reported. i.e. someone finds their existing PDB code broke with NumPy 2.4.

@peterjc peterjc closed this Mar 9, 2026
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.

Incompatible with NumPy 2.4

3 participants