-
Notifications
You must be signed in to change notification settings - Fork 830
Adding guards to index assignment in Universe creation #5228
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from 4 commits
2008495
cbaefcb
75c084d
3be73b7
adb8029
9c3df62
0d1ce06
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -745,6 +745,22 @@ def empty( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| UserWarning, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if atom_resindex is not None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| atom_resindex = np.asarray(atom_resindex) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if np.any(atom_resindex >= n_residues) or np.any(atom_resindex < 0): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| raise ValueError( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "atom_resindex contains invalid residue indices. " | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "All values must be between 0 and n_residues-1." | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if residue_segindex is not None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| residue_segindex = np.asarray(residue_segindex) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if np.any(residue_segindex >= n_segments) or np.any(residue_segindex < 0): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| raise ValueError( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "residue_segindex contains invalid segment indices. " | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "All values must be between 0 and n_segments-1." | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if np.any(atom_resindex >= n_residues) or np.any(atom_resindex < 0): | |
| raise ValueError( | |
| "atom_resindex contains invalid residue indices. " | |
| "All values must be between 0 and n_residues-1." | |
| ) | |
| if residue_segindex is not None: | |
| residue_segindex = np.asarray(residue_segindex) | |
| if np.any(residue_segindex >= n_segments) or np.any(residue_segindex < 0): | |
| raise ValueError( | |
| "residue_segindex contains invalid segment indices. " | |
| "All values must be between 0 and n_segments-1." | |
| try: | |
| invalid_atom_resindex = ( | |
| np.any(atom_resindex >= n_residues) | |
| or np.any(atom_resindex < 0) | |
| ) | |
| except (TypeError, ValueError) as err: | |
| raise ValueError( | |
| "atom_resindex must be an array of integers between " | |
| "0 and n_residues-1." | |
| ) from err | |
| else: | |
| if invalid_atom_resindex: | |
| raise ValueError( | |
| "atom_resindex contains invalid residue indices. " | |
| "All values must be between 0 and n_residues-1." | |
| ) | |
| if residue_segindex is not None: | |
| residue_segindex = np.asarray(residue_segindex) | |
| try: | |
| invalid_residue_segindex = ( | |
| np.any(residue_segindex >= n_segments) | |
| or np.any(residue_segindex < 0) | |
| ) | |
| except (TypeError, ValueError) as err: | |
| raise ValueError( | |
| "residue_segindex must be an array of integers between " | |
| "0 and n_segments-1." | |
| ) from err | |
| else: | |
| if invalid_residue_segindex: | |
| raise ValueError( | |
| "residue_segindex contains invalid segment indices. " | |
| "All values must be between 0 and n_segments-1." |
Copilot
AI
Feb 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The bounds check does np.any(atom_resindex >= n_residues) after np.asarray(atom_resindex). If atom_resindex contains non-numeric values (e.g., strings/object dtype), this comparison raises a TypeError, changing the failure mode from the ValueError this guard intends to provide. Consider coercing to an integer array (or catching TypeError/ValueError) and re-raising a ValueError with a clear message.
| atom_resindex = np.asarray(atom_resindex) | |
| if np.any(atom_resindex >= n_residues) or np.any(atom_resindex < 0): | |
| raise ValueError( | |
| "atom_resindex contains invalid residue indices. " | |
| "All values must be between 0 and n_residues-1." | |
| ) | |
| if residue_segindex is not None: | |
| residue_segindex = np.asarray(residue_segindex) | |
| if np.any(residue_segindex >= n_segments) or np.any(residue_segindex < 0): | |
| raise ValueError( | |
| "residue_segindex contains invalid segment indices. " | |
| "All values must be between 0 and n_segments-1." | |
| ) | |
| try: | |
| # Ensure atom_resindex is an integer array so that bounds | |
| # checks do not raise unexpected TypeError for non-numeric input. | |
| atom_resindex = np.asarray(atom_resindex, dtype=int) | |
| except (TypeError, ValueError): | |
| raise ValueError( | |
| "atom_resindex must be an array of integers." | |
| ) from None | |
| if np.any(atom_resindex >= n_residues) or np.any(atom_resindex < 0): | |
| raise ValueError( | |
| "atom_resindex contains invalid residue indices. " | |
| "All values must be between 0 and n_residues-1." | |
| ) | |
| if residue_segindex is not None: | |
| try: | |
| # Ensure residue_segindex is an integer array so that bounds | |
| # checks do not raise unexpected TypeError for non-numeric input. | |
| residue_segindex = np.asarray(residue_segindex, dtype=int) | |
| except (TypeError, ValueError): | |
| raise ValueError( | |
| "residue_segindex must be an array of integers." | |
| ) from None | |
| if np.any(residue_segindex >= n_segments) or np.any(residue_segindex < 0): | |
| raise ValueError( | |
| "residue_segindex contains invalid segment indices. " | |
| "All values must be between 0 and n_segments-1." | |
| ) |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -1867,3 +1867,10 @@ def test_no_affect_custom_attrs(self, good): | |||||||||||||||||
| sorted([each.attrname for each in original_attrs]), | ||||||||||||||||||
| sorted([each.attrname for each in good._topology.attrs]), | ||||||||||||||||||
| ) | ||||||||||||||||||
|
|
||||||||||||||||||
| def test_empty_universe_bounds(self): | ||||||||||||||||||
| with pytest.raises(ValueError, match="atom_resindex contains invalid residue indices."): | ||||||||||||||||||
| mda.Universe.empty(n_atoms=2, n_residues=2, atom_resindex=[0, 2], trajectory=True) | ||||||||||||||||||
|
|
||||||||||||||||||
| with pytest.raises(ValueError, match="residue_segindex contains invalid segment indices."): | ||||||||||||||||||
|
||||||||||||||||||
| with pytest.raises(ValueError, match="atom_resindex contains invalid residue indices."): | |
| mda.Universe.empty(n_atoms=2, n_residues=2, atom_resindex=[0, 2], trajectory=True) | |
| with pytest.raises(ValueError, match="residue_segindex contains invalid segment indices."): | |
| with pytest.raises(ValueError, match="atom_resindex contains invalid residue indices\."): | |
| mda.Universe.empty(n_atoms=2, n_residues=2, atom_resindex=[0, 2], trajectory=True) | |
| with pytest.raises(ValueError, match="residue_segindex contains invalid segment indices\."): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Formatting: the closing parenthesis for the
raise ValueError(...)call is indented inconsistently with other multi-line raises in this file (e.g.,Universe.load_new), and there appears to be trailing whitespace on the blank line following it. Align the closing)with theraiseand remove trailing whitespace to match the file's style.