Skip to content

Commit d6c8cdb

Browse files
gh-163: drop Python 3.9 & NumPy < 2.1.1 support (#391)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent f84a307 commit d6c8cdb

File tree

12 files changed

+47
-116
lines changed

12 files changed

+47
-116
lines changed

.github/workflows/test.yml

+1-2
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ jobs:
2525
strategy:
2626
matrix:
2727
python-version:
28-
- "3.9"
2928
- "3.10"
3029
- "3.11"
3130
- "3.12"
@@ -79,7 +78,7 @@ jobs:
7978
- name: Coveralls finished
8079
uses: coverallsapp/github-action@v2
8180
with:
82-
carryforward: run-3.9,run-3.10,run-3.11,run-3.12,run-3.13
81+
carryforward: run-3.10,run-3.11,run-3.12,run-3.13
8382
parallel-finished: true
8483

8584
build:

examples/1-basic/photoz.ipynb

+1-1
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@
165165
"tomo_nz = glass.tomo_nz_gausserr(z, dndz, phz_sigma_0, zbins)\n",
166166
"tomo_nz *= ARCMIN2_SPHERE * (z[-1] - z[0]) / 40\n",
167167
"\n",
168-
"for (z1, z2), nz in zip(zbins, tomo_nz):\n",
168+
"for (z1, z2), nz in zip(zbins, tomo_nz, strict=False):\n",
169169
" plt.hist(\n",
170170
" ztrue[(z1 <= zphot) & (zphot < z2)],\n",
171171
" bins=40,\n",

glass/core/array.py

+4-6
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,9 @@ def broadcast_leading_axes(
8181
shapes.append(s[:i])
8282
trails.append(s[i:])
8383
dims = np.broadcast_shapes(*shapes)
84-
arrs = (np.broadcast_to(a, dims + t) for (a, _), t in zip(args, trails))
84+
arrs = (
85+
np.broadcast_to(a, dims + t) for (a, _), t in zip(args, trails, strict=False)
86+
)
8587
return (dims, *arrs)
8688

8789

@@ -164,11 +166,7 @@ def trapz_product(
164166
y = np.interp(x, *f)
165167
for f_ in ff:
166168
y *= np.interp(x, *f_)
167-
return np.trapz( # type: ignore[attr-defined, no-any-return]
168-
y,
169-
x,
170-
axis=axis,
171-
)
169+
return np.trapezoid(y, x, axis=axis) # type: ignore[no-any-return]
172170

173171

174172
def cumtrapz(

glass/fields.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
from gaussiancl import gaussiancl
3838

3939
Cls = collections.abc.Sequence[
40-
typing.Union[npt.NDArray[np.float64], collections.abc.Sequence[float]]
40+
npt.NDArray[np.float64] | collections.abc.Sequence[float]
4141
]
4242

4343

glass/lensing.py

+1-11
Original file line numberDiff line numberDiff line change
@@ -324,17 +324,7 @@ def add_window(self, delta: npt.NDArray[np.float64], w: RadialWindow) -> None:
324324
325325
"""
326326
zsrc = w.zeff
327-
lens_weight = float(
328-
np.trapz( # type: ignore[attr-defined]
329-
w.wa,
330-
w.za,
331-
)
332-
/ np.interp(
333-
zsrc,
334-
w.za,
335-
w.wa,
336-
)
337-
)
327+
lens_weight = float(np.trapezoid(w.wa, w.za) / np.interp(zsrc, w.za, w.wa))
338328

339329
self.add_plane(delta, zsrc, lens_weight)
340330

glass/observations.py

+5-12
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
from __future__ import annotations
2929

30+
import itertools
3031
import math
3132

3233
import healpy as hp
@@ -119,11 +120,7 @@ def gaussian_nz(
119120
sigma = np.reshape(sigma, np.shape(sigma) + (1,) * np.ndim(z))
120121

121122
nz = np.exp(-(((z - mean) / sigma) ** 2) / 2)
122-
nz /= np.trapz( # type: ignore[attr-defined]
123-
nz,
124-
z,
125-
axis=-1,
126-
)[..., np.newaxis]
123+
nz /= np.trapezoid(nz, z, axis=-1)[..., np.newaxis]
127124

128125
if norm is not None:
129126
nz *= norm
@@ -184,11 +181,7 @@ def smail_nz(
184181
beta = np.asanyarray(beta)[..., np.newaxis]
185182

186183
pz = z**alpha * np.exp(-alpha / beta * (z / z_mode) ** beta)
187-
pz /= np.trapz( # type: ignore[attr-defined]
188-
pz,
189-
z,
190-
axis=-1,
191-
)[..., np.newaxis]
184+
pz /= np.trapezoid(pz, z, axis=-1)[..., np.newaxis]
192185

193186
if norm is not None:
194187
pz *= norm
@@ -238,7 +231,7 @@ def fixed_zbins(
238231
msg = "exactly one of nbins and dz must be given"
239232
raise ValueError(msg)
240233

241-
return list(zip(zbinedges, zbinedges[1:]))
234+
return list(itertools.pairwise(zbinedges))
242235

243236

244237
def equal_dens_zbins(
@@ -274,7 +267,7 @@ def equal_dens_zbins(
274267
cuml_nz /= cuml_nz[[-1]]
275268
zbinedges = np.interp(np.linspace(0, 1, nbins + 1), cuml_nz, z)
276269

277-
return list(zip(zbinedges, zbinedges[1:]))
270+
return list(itertools.pairwise(zbinedges))
278271

279272

280273
def tomo_nz_gausserr(

glass/points.py

+2-5
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,8 @@ def effective_bias(
8484
\;.
8585
8686
"""
87-
norm = np.trapz( # type: ignore[attr-defined]
88-
w.wa,
89-
w.za,
90-
)
91-
return trapz_product((z, bz), (w.za, w.wa)) / norm # type: ignore[no-any-return]
87+
norm = np.trapezoid(w.wa, w.za)
88+
return trapz_product((z, bz), (w.za, w.wa)) / norm
9289

9390

9491
def linear_bias(

glass/shells.py

+13-60
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
from __future__ import annotations
4747

4848
import collections.abc
49+
import itertools
4950
import typing
5051
import warnings
5152

@@ -58,7 +59,7 @@
5859
if typing.TYPE_CHECKING:
5960
from cosmology import Cosmology
6061

61-
ArrayLike1D = typing.Union[collections.abc.Sequence[float], npt.NDArray[np.float64]]
62+
ArrayLike1D = collections.abc.Sequence[float] | npt.NDArray[np.float64]
6263
WeightFunc = typing.Callable[[ArrayLike1D], npt.NDArray[np.float64]]
6364

6465

@@ -232,17 +233,11 @@ def tophat_windows(
232233
wht: WeightFunc
233234
wht = weight if weight is not None else np.ones_like
234235
ws = []
235-
for zmin, zmax in zip(zbins, zbins[1:]):
236+
for zmin, zmax in itertools.pairwise(zbins):
236237
n = max(round((zmax - zmin) / dz), 2)
237238
z = np.linspace(zmin, zmax, n)
238239
w = wht(z)
239-
zeff = np.trapz( # type: ignore[attr-defined]
240-
w * z,
241-
z,
242-
) / np.trapz( # type: ignore[attr-defined]
243-
w,
244-
z,
245-
)
240+
zeff = np.trapezoid(w * z, z) / np.trapezoid(w, z)
246241
ws.append(RadialWindow(z, w, zeff))
247242
return ws
248243

@@ -296,7 +291,7 @@ def linear_windows(
296291
warnings.warn("first triangular window does not start at z=0", stacklevel=2)
297292

298293
ws = []
299-
for zmin, zmid, zmax in zip(zgrid, zgrid[1:], zgrid[2:]):
294+
for zmin, zmid, zmax in zip(zgrid, zgrid[1:], zgrid[2:], strict=False):
300295
n = max(round((zmid - zmin) / dz), 2) - 1
301296
m = max(round((zmax - zmid) / dz), 2)
302297
z = np.concatenate(
@@ -361,7 +356,7 @@ def cubic_windows(
361356
warnings.warn("first cubic spline window does not start at z=0", stacklevel=2)
362357

363358
ws = []
364-
for zmin, zmid, zmax in zip(zgrid, zgrid[1:], zgrid[2:]):
359+
for zmin, zmid, zmax in zip(zgrid, zgrid[1:], zgrid[2:], strict=False):
365360
n = max(round((zmid - zmin) / dz), 2) - 1
366361
m = max(round((zmax - zmid) / dz), 2)
367362
z = np.concatenate(
@@ -580,11 +575,7 @@ def partition_lstsq(
580575

581576
# create the window function matrix
582577
a = np.array([np.interp(zp, za, wa, left=0.0, right=0.0) for za, wa, _ in shells])
583-
a /= np.trapz( # type: ignore[attr-defined]
584-
a,
585-
zp,
586-
axis=-1,
587-
)[..., None]
578+
a /= np.trapezoid(a, zp, axis=-1)[..., None]
588579
a = a * dz
589580

590581
# create the target vector of distribution values
@@ -594,20 +585,7 @@ def partition_lstsq(
594585
# append a constraint for the integral
595586
mult = 1 / sumtol
596587
a = np.concatenate([a, mult * np.ones((len(shells), 1))], axis=-1)
597-
b = np.concatenate(
598-
[
599-
b,
600-
mult
601-
* np.reshape(
602-
np.trapz( # type: ignore[attr-defined]
603-
fz,
604-
z,
605-
),
606-
(*dims, 1),
607-
),
608-
],
609-
axis=-1,
610-
)
588+
b = np.concatenate([b, mult * np.reshape(np.trapezoid(fz, z), (*dims, 1))], axis=-1)
611589

612590
# now a is a matrix of shape (len(shells), len(zp) + 1)
613591
# and b is a matrix of shape (*dims, len(zp) + 1)
@@ -672,11 +650,7 @@ def partition_nnls(
672650
for za, wa, _ in shells
673651
],
674652
)
675-
a /= np.trapz( # type: ignore[attr-defined]
676-
a,
677-
zp,
678-
axis=-1,
679-
)[..., None]
653+
a /= np.trapezoid(a, zp, axis=-1)[..., None]
680654
a = a * dz
681655

682656
# create the target vector of distribution values
@@ -686,20 +660,7 @@ def partition_nnls(
686660
# append a constraint for the integral
687661
mult = 1 / sumtol
688662
a = np.concatenate([a, mult * np.ones((len(shells), 1))], axis=-1)
689-
b = np.concatenate(
690-
[
691-
b,
692-
mult
693-
* np.reshape(
694-
np.trapz( # type: ignore[attr-defined]
695-
fz,
696-
z,
697-
),
698-
(*dims, 1),
699-
),
700-
],
701-
axis=-1,
702-
)
663+
b = np.concatenate([b, mult * np.reshape(np.trapezoid(fz, z), (*dims, 1))], axis=-1)
703664

704665
# now a is a matrix of shape (len(shells), len(zp) + 1)
705666
# and b is a matrix of shape (*dims, len(zp) + 1)
@@ -743,11 +704,7 @@ def partition_restrict(
743704
part = np.empty((len(shells),) + np.shape(fz)[:-1])
744705
for i, w in enumerate(shells):
745706
zr, fr = restrict(z, fz, w)
746-
part[i] = np.trapz( # type: ignore[attr-defined]
747-
fr,
748-
zr,
749-
axis=-1,
750-
)
707+
part[i] = np.trapezoid(fr, zr, axis=-1)
751708
return part
752709

753710

@@ -879,15 +836,11 @@ def combine(
879836
* np.interp(
880837
z,
881838
shell.za,
882-
shell.wa
883-
/ np.trapz( # type: ignore[attr-defined]
884-
shell.wa,
885-
shell.za,
886-
),
839+
shell.wa / np.trapezoid(shell.wa, shell.za),
887840
left=0.0,
888841
right=0.0,
889842
)
890-
for shell, weight in zip(shells, weights)
843+
for shell, weight in zip(shells, weights, strict=False)
891844
],
892845
axis=0,
893846
)

noxfile.py

+6-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,12 @@
1010
nox.options.reuse_existing_virtualenvs = True
1111
nox.options.sessions = ["lint", "tests"]
1212

13-
ALL_PYTHON = ["3.9", "3.10", "3.11", "3.12", "3.13"]
13+
ALL_PYTHON = [
14+
"3.10",
15+
"3.11",
16+
"3.12",
17+
"3.13",
18+
]
1419

1520

1621
@nox.session

pyproject.toml

+2-4
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ classifiers = [
1111
"Operating System :: OS Independent",
1212
"Programming Language :: Python :: 3",
1313
"Programming Language :: Python :: 3 :: Only",
14-
"Programming Language :: Python :: 3.9",
1514
"Programming Language :: Python :: 3.10",
1615
"Programming Language :: Python :: 3.11",
1716
"Programming Language :: Python :: 3.12",
@@ -25,7 +24,7 @@ dependencies = [
2524
"gaussiancl>=2022.10.21",
2625
"healpix>=2022.11.1",
2726
"healpy>=1.15.0",
28-
"numpy>=1.22.0",
27+
"numpy>=2.1.1",
2928
]
3029
description = "Generator for Large Scale Structure"
3130
dynamic = [
@@ -36,7 +35,7 @@ maintainers = [
3635
]
3736
name = "glass"
3837
readme = "README.md"
39-
requires-python = ">=3.9"
38+
requires-python = ">=3.10"
4039
license.file = "LICENSE"
4140

4241
[project.optional-dependencies]
@@ -142,7 +141,6 @@ lint.ignore = [
142141
"D203", # one-blank-line-before-class
143142
"D212", # blank-line-before-class
144143
"ISC001", # single-line-implicit-string-concatenation (ruff-format recommended)
145-
"NPY201", # TODO: numpy2-deprecation
146144
"RUF003", # ambiguous-unicode-character-comment
147145
]
148146
lint.isort = {known-first-party = [

tests/test_lensing.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ def test_multi_plane_matrix(
109109

110110
deltas = rng.random((len(shells), 10))
111111
kappas = []
112-
for shell, delta in zip(shells, deltas):
112+
for shell, delta in zip(shells, deltas, strict=False):
113113
convergence.add_window(delta, shell)
114114
if convergence.kappa is not None:
115115
kappas.append(convergence.kappa.copy())
@@ -133,7 +133,7 @@ def test_multi_plane_weights(
133133
deltas = rng.random((len(shells), 10))
134134
weights = rng.random((len(shells), 3))
135135
kappa = 0
136-
for shell, delta, weight in zip(shells, deltas, weights):
136+
for shell, delta, weight in zip(shells, deltas, weights, strict=False):
137137
convergence.add_window(delta, shell)
138138
kappa = kappa + weight[..., None] * convergence.kappa
139139
kappa /= weights.sum(axis=0)[..., None]

0 commit comments

Comments
 (0)