diff --git a/package/CHANGELOG b/package/CHANGELOG index be686888025..58511d8d029 100644 --- a/package/CHANGELOG +++ b/package/CHANGELOG @@ -13,7 +13,7 @@ The rules for this file: * release numbers follow "Semantic Versioning" http://semver.org ------------------------------------------------------------------------------ -??/??/?? IAlibay, hmacdope, pillose, jaclark5 +??/??/?? IAlibay, hmacdope, pillose, jaclark5, tylerjereddy * 2.7.0 @@ -23,6 +23,8 @@ Fixes Enhancements Changes + * NumPy `in1d` replaced with `isin` in preparation for NumPy + `2.0` (PR #4255) * Update documentation for SurvivalProbabilty to be more clear (Issue #4247) * Cython DEF statments have been replaced with compile time integer constants diff --git a/package/MDAnalysis/analysis/align.py b/package/MDAnalysis/analysis/align.py index acb3943c576..5b4bb145efc 100644 --- a/package/MDAnalysis/analysis/align.py +++ b/package/MDAnalysis/analysis/align.py @@ -1437,7 +1437,7 @@ def get_atoms_byres(g, match_mask=np.logical_not(mismatch_mask)): good = ag.residues.resids[match_mask] # resid for each residue resids = ag.resids # resid for each atom # boolean array for all matching atoms - ix_good = np.in1d(resids, good) + ix_good = np.isin(resids, good) return ag[ix_good] _ag1 = get_atoms_byres(ag1) diff --git a/package/MDAnalysis/analysis/hydrogenbonds/hbond_analysis.py b/package/MDAnalysis/analysis/hydrogenbonds/hbond_analysis.py index d69040736bb..6202ffdef14 100644 --- a/package/MDAnalysis/analysis/hydrogenbonds/hbond_analysis.py +++ b/package/MDAnalysis/analysis/hydrogenbonds/hbond_analysis.py @@ -680,16 +680,16 @@ def _filter_atoms(self, donors, acceptors): # Find donors in G1 and acceptors in G2 mask[ np.logical_and( - np.in1d(donors.indices, group1.indices), - np.in1d(acceptors.indices, group2.indices) + np.isin(donors.indices, group1.indices), + np.isin(acceptors.indices, group2.indices) ) ] = True # Find acceptors in G1 and donors in G2 mask[ np.logical_and( - np.in1d(acceptors.indices, group1.indices), - np.in1d(donors.indices, group2.indices) + np.isin(acceptors.indices, group1.indices), + np.isin(donors.indices, group2.indices) ) ] = True diff --git a/package/MDAnalysis/core/groups.py b/package/MDAnalysis/core/groups.py index 06156d97c87..a73aef445dd 100644 --- a/package/MDAnalysis/core/groups.py +++ b/package/MDAnalysis/core/groups.py @@ -422,7 +422,7 @@ def get_connections(self, typename, outside=True): indices = self.atoms.ix_array except AttributeError: # if self is an Atom indices = self.ix_array - seen = [np.in1d(col, indices) for col in ugroup._bix.T] + seen = [np.isin(col, indices) for col in ugroup._bix.T] mask = func(seen, axis=0) return ugroup[mask] @@ -2154,7 +2154,7 @@ def subtract(self, other): .. versionadded:: 0.16 """ o_ix = other.ix_array - in_other = np.in1d(self.ix, o_ix) # mask of in self.ix AND other + in_other = np.isin(self.ix, o_ix) # mask of in self.ix AND other return self[~in_other] # ie inverse of previous mask @_only_same_level diff --git a/package/MDAnalysis/core/selection.py b/package/MDAnalysis/core/selection.py index d2c32d80b50..2edbf79e01b 100644 --- a/package/MDAnalysis/core/selection.py +++ b/package/MDAnalysis/core/selection.py @@ -190,7 +190,7 @@ def _apply(self, group): lsel = self.lsel.apply(group) # Mask which lsel indices appear in rsel - mask = np.in1d(rsel.indices, lsel.indices) + mask = np.isin(rsel.indices, lsel.indices) # and mask rsel according to that return rsel[mask] @@ -267,7 +267,7 @@ class NotSelection(UnarySelection): def _apply(self, group): notsel = self.sel.apply(group) - return group[~np.in1d(group.indices, notsel.indices)] + return group[~np.isin(group.indices, notsel.indices)] class GlobalSelection(UnarySelection): @@ -292,7 +292,7 @@ class ByResSelection(UnarySelection): def _apply(self, group): res = self.sel.apply(group) unique_res = unique_int_1d(res.resindices) - mask = np.in1d(group.resindices, unique_res) + mask = np.isin(group.resindices, unique_res) return group[mask] @@ -312,7 +312,7 @@ def _apply(self, group): indices = [] sel = self.sel.apply(group) # All atoms in group that aren't in sel - sys = group[~np.in1d(group.indices, sel.indices)] + sys = group[~np.isin(group.indices, sel.indices)] if not sys or not sel: return sys[[]] @@ -372,7 +372,7 @@ def _apply(self, group): indices = [] sel = self.sel.apply(group) # All atoms in group that aren't in sel - sys = group[~np.in1d(group.indices, sel.indices)] + sys = group[~np.isin(group.indices, sel.indices)] if not sys or not sel: return sys[[]] @@ -389,7 +389,7 @@ def _apply(self, group): sys_ind_outer = np.sort(np.unique(pairs_outer[:,1])) if pairs_inner.size > 0: sys_ind_inner = np.sort(np.unique(pairs_inner[:,1])) - indices = sys_ind_outer[~np.in1d(sys_ind_outer, sys_ind_inner)] + indices = sys_ind_outer[~np.isin(sys_ind_outer, sys_ind_inner)] else: indices = sys_ind_outer @@ -577,9 +577,9 @@ def _apply(self, group): idx = [] # left side - idx.append(bix[:, 0][np.in1d(bix[:, 1], grpidx)]) + idx.append(bix[:, 0][np.isin(bix[:, 1], grpidx)]) # right side - idx.append(bix[:, 1][np.in1d(bix[:, 0], grpidx)]) + idx.append(bix[:, 1][np.isin(bix[:, 0], grpidx)]) idx = np.union1d(*idx) @@ -603,7 +603,7 @@ def __init__(self, parser, tokens): raise ValueError(errmsg) from None def _apply(self, group): - mask = np.in1d(group.indices, self.grp.indices) + mask = np.isin(group.indices, self.grp.indices) return group[mask] @@ -657,7 +657,7 @@ def _apply(self, group): # atomname indices for members of this group nmidx = nmattr.nmidx[getattr(group, self.level)] - return group[np.in1d(nmidx, matches)] + return group[np.isin(nmidx, matches)] class AromaticSelection(Selection): @@ -743,7 +743,7 @@ def _apply(self, group): # flatten all matches and remove duplicated indices indices = np.unique([idx for match in matches for idx in match]) # create boolean mask for atoms based on index - mask = np.in1d(range(group.n_atoms), indices) + mask = np.isin(range(group.n_atoms), indices) return group[mask] @@ -1053,7 +1053,7 @@ def _apply(self, group): # index of each atom's resname nmidx = resname_attr.nmidx[group.resindices] # intersect atom's resname index and matches to prot_res - return group[np.in1d(nmidx, matches)] + return group[np.isin(nmidx, matches)] class NucleicSelection(Selection): @@ -1089,7 +1089,7 @@ def _apply(self, group): matches = [ix for (nm, ix) in resnames.namedict.items() if nm in self.nucl_res] - mask = np.in1d(nmidx, matches) + mask = np.isin(nmidx, matches) return group[mask] @@ -1116,13 +1116,13 @@ def _apply(self, group): name_matches = [ix for (nm, ix) in atomnames.namedict.items() if nm in self.bb_atoms] nmidx = atomnames.nmidx[group.ix] - group = group[np.in1d(nmidx, name_matches)] + group = group[np.isin(nmidx, name_matches)] # filter by resnames resname_matches = [ix for (nm, ix) in resnames.namedict.items() if nm in self.prot_res] nmidx = resnames.nmidx[group.resindices] - group = group[np.in1d(nmidx, resname_matches)] + group = group[np.isin(nmidx, resname_matches)] return group.unique @@ -1149,13 +1149,13 @@ def _apply(self, group): name_matches = [ix for (nm, ix) in atomnames.namedict.items() if nm in self.bb_atoms] nmidx = atomnames.nmidx[group.ix] - group = group[np.in1d(nmidx, name_matches)] + group = group[np.isin(nmidx, name_matches)] # filter by resnames resname_matches = [ix for (nm, ix) in resnames.namedict.items() if nm in self.nucl_res] nmidx = resnames.nmidx[group.resindices] - group = group[np.in1d(nmidx, resname_matches)] + group = group[np.isin(nmidx, resname_matches)] return group.unique @@ -1187,13 +1187,13 @@ def _apply(self, group): name_matches = [ix for (nm, ix) in atomnames.namedict.items() if nm in self.base_atoms] nmidx = atomnames.nmidx[group.ix] - group = group[np.in1d(nmidx, name_matches)] + group = group[np.isin(nmidx, name_matches)] # filter by resnames resname_matches = [ix for (nm, ix) in resnames.namedict.items() if nm in self.nucl_res] nmidx = resnames.nmidx[group.resindices] - group = group[np.in1d(nmidx, resname_matches)] + group = group[np.isin(nmidx, resname_matches)] return group.unique @@ -1217,13 +1217,13 @@ def _apply(self, group): name_matches = [ix for (nm, ix) in atomnames.namedict.items() if nm in self.sug_atoms] nmidx = atomnames.nmidx[group.ix] - group = group[np.in1d(nmidx, name_matches)] + group = group[np.isin(nmidx, name_matches)] # filter by resnames resname_matches = [ix for (nm, ix) in resnames.namedict.items() if nm in self.nucl_res] nmidx = resnames.nmidx[group.resindices] - group = group[np.in1d(nmidx, resname_matches)] + group = group[np.isin(nmidx, resname_matches)] return group.unique @@ -1408,7 +1408,7 @@ def _apply(self, group): # indices are same as fragment(s) indices allfrags = functools.reduce(lambda x, y: x + y, res.fragments) - mask = np.in1d(group.indices, allfrags.indices) + mask = np.isin(group.indices, allfrags.indices) return group[mask] # [xyz] must come before self.prop_trans lookups too! try: @@ -1419,7 +1419,7 @@ def _apply(self, group): # KeyError at this point is impossible! attrname = self.prop_trans[self.prop] vals = getattr(res, attrname) - mask = np.in1d(getattr(group, attrname), vals) + mask = np.isin(getattr(group, attrname), vals) return group[mask] else: diff --git a/package/MDAnalysis/core/topologyattrs.py b/package/MDAnalysis/core/topologyattrs.py index c7685f7c5b6..96e6c1222e1 100644 --- a/package/MDAnalysis/core/topologyattrs.py +++ b/package/MDAnalysis/core/topologyattrs.py @@ -1234,7 +1234,7 @@ def chi1_selection(residue, n_name='N', ca_name='CA', cb_name='CB', """ names = [n_name, ca_name, cb_name, cg_name] atnames = residue.atoms.names - ags = [residue.atoms[np.in1d(atnames, n.split())] for n in names] + ags = [residue.atoms[np.isin(atnames, n.split())] for n in names] if any(len(ag) != 1 for ag in ags): return None return sum(ags) @@ -1267,13 +1267,13 @@ def chi1_selections(residues, n_name='N', ca_name='CA', cb_name='CB', """ results = np.array([None]*len(residues)) names = [n_name, ca_name, cb_name, cg_name] - keep = [all(sum(np.in1d(r.atoms.names, n.split())) == 1 + keep = [all(sum(np.isin(r.atoms.names, n.split())) == 1 for n in names) for r in residues] keepix = np.where(keep)[0] residues = residues[keep] atnames = residues.atoms.names - ags = [residues.atoms[np.in1d(atnames, n.split())] for n in names] + ags = [residues.atoms[np.isin(atnames, n.split())] for n in names] results[keepix] = [sum(atoms) for atoms in zip(*ags)] return list(results) diff --git a/package/MDAnalysis/core/topologyobjects.py b/package/MDAnalysis/core/topologyobjects.py index 40e420f5df8..5d2e37965e4 100644 --- a/package/MDAnalysis/core/topologyobjects.py +++ b/package/MDAnalysis/core/topologyobjects.py @@ -694,7 +694,7 @@ def atomgroup_intersection(self, ag, **kwargs): atom_idx = ag.indices # Create a list of boolean arrays, # each representing a column of bond indices. - seen = [np.in1d(col, atom_idx) for col in self._bix.T] + seen = [np.isin(col, atom_idx) for col in self._bix.T] # Create final boolean mask by summing across rows mask = func(seen, axis=0) diff --git a/testsuite/MDAnalysisTests/core/test_groups.py b/testsuite/MDAnalysisTests/core/test_groups.py index 32390296bef..0e15a1a9e32 100644 --- a/testsuite/MDAnalysisTests/core/test_groups.py +++ b/testsuite/MDAnalysisTests/core/test_groups.py @@ -1646,7 +1646,7 @@ def test_connection_from_atoms_not_outside(self, tpr, typename, cxns = ag.get_connections(typename, outside=False) assert len(cxns) == n_atoms indices = np.ravel(cxns.to_indices()) - assert np.all(np.in1d(indices, ag.indices)) + assert np.all(np.isin(indices, ag.indices)) @pytest.mark.parametrize("typename, n_atoms", [ ("bonds", 13), @@ -1658,7 +1658,7 @@ def test_connection_from_atoms_outside(self, tpr, typename, n_atoms): cxns = ag.get_connections(typename, outside=True) assert len(cxns) == n_atoms indices = np.ravel(cxns.to_indices()) - assert not np.all(np.in1d(indices, ag.indices)) + assert not np.all(np.isin(indices, ag.indices)) def test_invalid_connection_error(self, tpr): with pytest.raises(AttributeError, match="does not contain"): @@ -1708,7 +1708,7 @@ def test_connection_from_residues_not_outside(self, tpr, typename, cxns = ag.get_connections(typename, outside=False) assert len(cxns) == n_atoms indices = np.ravel(cxns.to_indices()) - assert np.all(np.in1d(indices, ag.atoms.indices)) + assert np.all(np.isin(indices, ag.atoms.indices)) @pytest.mark.parametrize("typename, n_atoms", [ ("bonds", 158), @@ -1720,7 +1720,7 @@ def test_connection_from_residues_outside(self, tpr, typename, n_atoms): cxns = ag.get_connections(typename, outside=True) assert len(cxns) == n_atoms indices = np.ravel(cxns.to_indices()) - assert not np.all(np.in1d(indices, ag.atoms.indices)) + assert not np.all(np.isin(indices, ag.atoms.indices)) def test_invalid_connection_error(self, tpr): with pytest.raises(AttributeError, match="does not contain"): @@ -1746,7 +1746,7 @@ def test_topologygroup_gets_connections_inside(tpr, typename, n_inside): cxns = getattr(ag, typename) assert len(cxns) == n_inside indices = np.ravel(cxns.to_indices()) - assert np.all(np.in1d(indices, ag.indices)) + assert np.all(np.isin(indices, ag.indices)) @pytest.mark.parametrize("typename, n_outside", [