From 4ba78c198557593ec967fc071192fb1b8d619a5f Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Thu, 3 Oct 2024 10:55:01 +0100 Subject: [PATCH 01/32] gh-280: add `mypy` pre-commit hook --- .pre-commit-config.yaml | 6 ++++++ pyproject.toml | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2536cd2a..851f3b6f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -61,3 +61,9 @@ repos: rev: v1.5.5 hooks: - id: forbid-tabs + - repo: https://github.com/pre-commit/mirrors-mypy + rev: v1.11.2 + hooks: + - id: mypy + additional_dependencies: + - numpy diff --git a/pyproject.toml b/pyproject.toml index 32e1eb26..f0def65c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -80,6 +80,11 @@ report = {exclude_also = [ build.hooks.vcs.version-file = "glass/_version.py" version.source = "vcs" +[tool.mypy] +plugins = [ + "numpy.typing.mypy_plugin", +] + [tool.pytest.ini_options] addopts = [ "--strict-config", From b23ded020f39f31e190c750c8a8386b410fb26c0 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Thu, 3 Oct 2024 10:58:04 +0100 Subject: [PATCH 02/32] Add scientific Python recommended config --- pyproject.toml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index f0def65c..369cd1d7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -81,9 +81,16 @@ build.hooks.vcs.version-file = "glass/_version.py" version.source = "vcs" [tool.mypy] +enable_error_code = [ + "ignore-without-code", + "redundant-expr", + "truthy-bool", +] plugins = [ "numpy.typing.mypy_plugin", ] +strict = true +warn_unreachable = true [tool.pytest.ini_options] addopts = [ From b9ee0eb1feabb51bc1e6233e048d0b6834346411 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Thu, 3 Oct 2024 11:07:24 +0100 Subject: [PATCH 03/32] Ignore `npt.NDArray` without specified type --- glass/galaxies.py | 12 ++++++------ glass/lensing.py | 4 ++-- glass/observations.py | 12 ++++++------ 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/glass/galaxies.py b/glass/galaxies.py index 865c06e9..71bcd02b 100644 --- a/glass/galaxies.py +++ b/glass/galaxies.py @@ -132,12 +132,12 @@ def redshifts_from_nz( def galaxy_shear( # noqa: PLR0913 - lon: npt.NDArray, - lat: npt.NDArray, - eps: npt.NDArray, - kappa: npt.NDArray, - gamma1: npt.NDArray, - gamma2: npt.NDArray, + lon: npt.NDArray, # type: ignore[type-arg] + lat: npt.NDArray, # type: ignore[type-arg] + eps: npt.NDArray, # type: ignore[type-arg] + kappa: npt.NDArray, # type: ignore[type-arg] + gamma1: npt.NDArray, # type: ignore[type-arg] + gamma2: npt.NDArray, # type: ignore[type-arg] *, reduced_shear: bool = True, ) -> npt.NDArray: diff --git a/glass/lensing.py b/glass/lensing.py index 957605c9..45df36a7 100644 --- a/glass/lensing.py +++ b/glass/lensing.py @@ -47,7 +47,7 @@ def from_convergence( # noqa: PLR0913 - kappa: npt.NDArray, + kappa: npt.NDArray, # type: ignore[type-arg] lmax: int | None = None, *, potential: bool = False, @@ -226,7 +226,7 @@ def from_convergence( # noqa: PLR0913 def shear_from_convergence( - kappa: npt.NDArray, + kappa: npt.NDArray, # type: ignore[type-arg] lmax: int | None = None, *, discretized: bool = True, diff --git a/glass/observations.py b/glass/observations.py index ab712285..8d8b41bb 100644 --- a/glass/observations.py +++ b/glass/observations.py @@ -86,7 +86,7 @@ def vmap_galactic_ecliptic( def gaussian_nz( - z: npt.NDArray, + z: npt.NDArray, # type: ignore[type-arg] mean: npt.ArrayLike, sigma: npt.ArrayLike, *, @@ -131,7 +131,7 @@ def gaussian_nz( def smail_nz( - z: npt.NDArray, + z: npt.NDArray, # type: ignore[type-arg] z_mode: npt.ArrayLike, alpha: npt.ArrayLike, beta: npt.ArrayLike, @@ -232,8 +232,8 @@ def fixed_zbins( def equal_dens_zbins( - z: npt.NDArray, - nz: npt.NDArray, + z: npt.NDArray, # type: ignore[type-arg] + nz: npt.NDArray, # type: ignore[type-arg] nbins: int, ) -> list[tuple[float, float]]: """ @@ -267,8 +267,8 @@ def equal_dens_zbins( def tomo_nz_gausserr( - z: npt.NDArray, - nz: npt.NDArray, + z: npt.NDArray, # type: ignore[type-arg] + nz: npt.NDArray, # type: ignore[type-arg] sigma_0: float, zbins: list[tuple[float, float]], ) -> npt.NDArray: From 3856aa97ad4a4b3c8f1743da363072b49ef5e71b Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Fri, 4 Oct 2024 15:45:03 +0100 Subject: [PATCH 04/32] Add more `ignore[type-arg]` --- glass/fields.py | 10 +++++----- glass/galaxies.py | 8 ++++---- glass/lensing.py | 4 ++-- glass/observations.py | 8 ++++---- glass/shapes.py | 4 ++-- glass/shells.py | 12 ++++++------ 6 files changed, 23 insertions(+), 23 deletions(-) diff --git a/glass/fields.py b/glass/fields.py index 38258c65..fe6d634a 100644 --- a/glass/fields.py +++ b/glass/fields.py @@ -37,15 +37,15 @@ # types Size = Optional[Union[int, tuple[int, ...]]] -Iternorm = tuple[Optional[int], npt.NDArray, npt.NDArray] -ClTransform = Union[str, Callable[[npt.NDArray], npt.NDArray]] -Cls = Sequence[Union[npt.NDArray, Sequence[float]]] -Alms = npt.NDArray +Iternorm = tuple[Optional[int], npt.NDArray, npt.NDArray] # type: ignore[type-arg] +ClTransform = Union[str, Callable[[npt.NDArray], npt.NDArray]] # type: ignore[type-arg] +Cls = Sequence[Union[npt.NDArray, Sequence[float]]] # type: ignore[type-arg] +Alms = npt.NDArray # type: ignore[type-arg] def iternorm( k: int, - cov: Iterable[npt.NDArray], + cov: Iterable[npt.NDArray], # type: ignore[type-arg] size: Size = None, ) -> Generator[Iternorm, None, None]: """Return the vector a and variance sigma^2 for iterative normal sampling.""" diff --git a/glass/galaxies.py b/glass/galaxies.py index 71bcd02b..8b2da78c 100644 --- a/glass/galaxies.py +++ b/glass/galaxies.py @@ -37,7 +37,7 @@ def redshifts( w: RadialWindow, *, rng: np.random.Generator | None = None, -) -> npt.NDArray: +) -> npt.NDArray: # type: ignore[type-arg] """ Sample redshifts from a radial window function. @@ -69,7 +69,7 @@ def redshifts_from_nz( nz: npt.ArrayLike, *, rng: np.random.Generator | None = None, -) -> npt.NDArray: +) -> npt.NDArray: # type: ignore[type-arg] """ Generate galaxy redshifts from a source distribution. @@ -140,7 +140,7 @@ def galaxy_shear( # noqa: PLR0913 gamma2: npt.NDArray, # type: ignore[type-arg] *, reduced_shear: bool = True, -) -> npt.NDArray: +) -> npt.NDArray: # type: ignore[type-arg] """ Observed galaxy shears from weak lensing. @@ -201,7 +201,7 @@ def gaussian_phz( lower: npt.ArrayLike | None = None, upper: npt.ArrayLike | None = None, rng: np.random.Generator | None = None, -) -> npt.NDArray: +) -> npt.NDArray: # type: ignore[type-arg] r""" Photometric redshifts assuming a Gaussian error. diff --git a/glass/lensing.py b/glass/lensing.py index 29505698..55f25fca 100644 --- a/glass/lensing.py +++ b/glass/lensing.py @@ -230,7 +230,7 @@ def shear_from_convergence( lmax: int | None = None, *, discretized: bool = True, -) -> npt.NDArray: +) -> npt.NDArray: # type: ignore[type-arg] r""" Weak lensing shear from convergence. @@ -353,7 +353,7 @@ def kappa(self) -> npt.NDArray | None: return self.kappa3 @property - def delta(self) -> npt.NDArray: + def delta(self) -> npt.NDArray: # type: ignore[type-arg] """The current matter plane.""" return self.delta3 diff --git a/glass/observations.py b/glass/observations.py index 8d8b41bb..ccb2108c 100644 --- a/glass/observations.py +++ b/glass/observations.py @@ -44,7 +44,7 @@ def vmap_galactic_ecliptic( nside: int, galactic: tuple[float, float] = (30, 90), ecliptic: tuple[float, float] = (20, 80), -) -> npt.NDArray: +) -> npt.NDArray: # type: ignore[type-arg] """ Visibility map masking galactic and ecliptic plane. @@ -91,7 +91,7 @@ def gaussian_nz( sigma: npt.ArrayLike, *, norm: npt.ArrayLike | None = None, -) -> npt.NDArray: +) -> npt.NDArray: # type: ignore[type-arg] r""" Gaussian redshift distribution. @@ -137,7 +137,7 @@ def smail_nz( beta: npt.ArrayLike, *, norm: npt.ArrayLike | None = None, -) -> npt.NDArray: +) -> npt.NDArray: # type: ignore[type-arg] r""" Redshift distribution following Smail et al. (1994). @@ -271,7 +271,7 @@ def tomo_nz_gausserr( nz: npt.NDArray, # type: ignore[type-arg] sigma_0: float, zbins: list[tuple[float, float]], -) -> npt.NDArray: +) -> npt.NDArray: # type: ignore[type-arg] """ Tomographic redshift bins with a Gaussian redshift error. diff --git a/glass/shapes.py b/glass/shapes.py index a883fe91..10533525 100644 --- a/glass/shapes.py +++ b/glass/shapes.py @@ -171,7 +171,7 @@ def ellipticity_gaussian( sigma: npt.ArrayLike, *, rng: np.random.Generator | None = None, -) -> npt.NDArray: +) -> npt.NDArray: # type: ignore[type-arg] r""" Sample Gaussian galaxy ellipticities. @@ -228,7 +228,7 @@ def ellipticity_intnorm( sigma: npt.ArrayLike, *, rng: np.random.Generator | None = None, -) -> npt.NDArray: +) -> npt.NDArray: # type: ignore[type-arg] r""" Sample galaxy ellipticities with intrinsic normal distribution. diff --git a/glass/shells.py b/glass/shells.py index d1054af4..613e282a 100644 --- a/glass/shells.py +++ b/glass/shells.py @@ -57,21 +57,21 @@ from cosmology import Cosmology # types -ArrayLike1D = Union[Sequence[float], npt.NDArray] -WeightFunc = Callable[[ArrayLike1D], npt.NDArray] +ArrayLike1D = Union[Sequence[float], npt.NDArray] # type: ignore[type-arg] +WeightFunc = Callable[[ArrayLike1D], npt.NDArray] # type: ignore[type-arg] -def distance_weight(z: npt.ArrayLike, cosmo: Cosmology) -> npt.NDArray: +def distance_weight(z: npt.ArrayLike, cosmo: Cosmology) -> npt.NDArray: # type: ignore[type-arg] """Uniform weight in comoving distance.""" return 1 / cosmo.ef(z) -def volume_weight(z: npt.ArrayLike, cosmo: Cosmology) -> npt.NDArray: +def volume_weight(z: npt.ArrayLike, cosmo: Cosmology) -> npt.NDArray: # type: ignore[type-arg] """Uniform weight in comoving volume.""" return cosmo.xm(z) ** 2 / cosmo.ef(z) -def density_weight(z: npt.ArrayLike, cosmo: Cosmology) -> npt.NDArray: +def density_weight(z: npt.ArrayLike, cosmo: Cosmology) -> npt.NDArray: # type: ignore[type-arg] """Uniform weight in matter density.""" return cosmo.rho_m_z(z) * cosmo.xm(z) ** 2 / cosmo.ef(z) @@ -311,7 +311,7 @@ def restrict( z: ArrayLike1D, f: ArrayLike1D, w: RadialWindow, -) -> tuple[npt.NDArray, npt.NDArray]: +) -> tuple[npt.NDArray, npt.NDArray]: # type: ignore[type-arg] """ Restrict a function to a redshift window. From 58696dc45d8934bae202bdec64b2466e098fe303 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Fri, 4 Oct 2024 16:50:31 +0100 Subject: [PATCH 05/32] Add `None` return type for tests --- tests/core/test_algorithm.py | 2 +- tests/core/test_array.py | 10 +++++----- tests/test_fields.py | 2 +- tests/test_fits.py | 6 +++--- tests/test_galaxies.py | 6 +++--- tests/test_lensing.py | 8 ++++---- tests/test_points.py | 6 +++--- tests/test_shapes.py | 8 ++++---- tests/test_shells.py | 6 +++--- 9 files changed, 27 insertions(+), 27 deletions(-) diff --git a/tests/core/test_algorithm.py b/tests/core/test_algorithm.py index 470ab6ea..7049c584 100644 --- a/tests/core/test_algorithm.py +++ b/tests/core/test_algorithm.py @@ -10,7 +10,7 @@ @pytest.mark.skipif(not HAVE_SCIPY, reason="test requires SciPy") -def test_nnls(rng): +def test_nnls(rng) -> None: from scipy.optimize import nnls as nnls_scipy # cross-check output with scipy's nnls diff --git a/tests/core/test_array.py b/tests/core/test_array.py index aec1bc29..461ac0c6 100644 --- a/tests/core/test_array.py +++ b/tests/core/test_array.py @@ -15,7 +15,7 @@ HAVE_SCIPY = importlib.util.find_spec("scipy") is not None -def test_broadcast_first(): +def test_broadcast_first() -> None: a = np.ones((2, 3, 4)) b = np.ones((2, 1)) @@ -44,7 +44,7 @@ def test_broadcast_first(): assert b_a.shape == (4, 5, 6) -def test_broadcast_leading_axes(): +def test_broadcast_leading_axes() -> None: a = 0 b = np.zeros((4, 10)) c = np.zeros((3, 1, 5, 6)) @@ -57,7 +57,7 @@ def test_broadcast_leading_axes(): assert c.shape == (3, 4, 5, 6) -def test_ndinterp(): +def test_ndinterp() -> None: # test 1d interpolation xp = [0, 1, 2, 3, 4] @@ -140,7 +140,7 @@ def test_ndinterp(): ) -def test_trapz_product(): +def test_trapz_product() -> None: x1 = np.linspace(0, 2, 100) f1 = np.full_like(x1, 2.0) @@ -153,7 +153,7 @@ def test_trapz_product(): @pytest.mark.skipif(not HAVE_SCIPY, reason="test requires SciPy") -def test_cumtrapz(): +def test_cumtrapz() -> None: from scipy.integrate import cumulative_trapezoid # 1D f and x diff --git a/tests/test_fields.py b/tests/test_fields.py index e65a0f94..14009a04 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -1,7 +1,7 @@ from glass.fields import getcl -def test_getcl(): +def test_getcl() -> None: # make a mock Cls array with the index pairs as entries cls = [{i, j} for i in range(10) for j in range(i, -1, -1)] # make sure indices are retrieved correctly diff --git a/tests/test_fits.py b/tests/test_fits.py index f036b4cd..97d85fe8 100644 --- a/tests/test_fits.py +++ b/tests/test_fits.py @@ -9,7 +9,7 @@ HAVE_FITSIO = importlib.util.find_spec("fitsio") is not None -def _test_append(fits, data, names): +def _test_append(fits, data, names) -> None: """Write routine for FITS test cases.""" cat_name = "CATALOG" if cat_name not in fits: @@ -26,7 +26,7 @@ def _test_append(fits, data, names): @pytest.mark.skipif(not HAVE_FITSIO, reason="test requires fitsio") -def test_basic_write(tmp_path): +def test_basic_write(tmp_path) -> None: import fitsio filename_gfits = "gfits.fits" # what GLASS creates @@ -55,7 +55,7 @@ def test_basic_write(tmp_path): @pytest.mark.skipif(not HAVE_FITSIO, reason="test requires fitsio") -def test_write_exception(tmp_path): +def test_write_exception(tmp_path) -> None: try: with user.write_catalog(tmp_path / filename, ext="CATALOG") as out: for i in range(my_max): diff --git a/tests/test_galaxies.py b/tests/test_galaxies.py index f897bfe0..9508ed3f 100644 --- a/tests/test_galaxies.py +++ b/tests/test_galaxies.py @@ -4,7 +4,7 @@ from glass.galaxies import gaussian_phz, redshifts, redshifts_from_nz -def test_redshifts(mocker): +def test_redshifts(mocker) -> None: # create a mock radial window function w = mocker.Mock() w.za = np.linspace(0.0, 1.0, 20) @@ -21,7 +21,7 @@ def test_redshifts(mocker): assert z.shape == (10,) -def test_redshifts_from_nz(): +def test_redshifts_from_nz() -> None: # test sampling redshifts = redshifts_from_nz(10, [0, 1, 2, 3, 4], [1, 0, 0, 0, 0]) @@ -89,7 +89,7 @@ def test_redshifts_from_nz(): redshifts_from_nz(count, z, nz) -def test_gaussian_phz(): +def test_gaussian_phz() -> None: # test sampling # case: zero variance diff --git a/tests/test_lensing.py b/tests/test_lensing.py index af9ee858..22218038 100644 --- a/tests/test_lensing.py +++ b/tests/test_lensing.py @@ -41,7 +41,7 @@ def xm(self, z, z2=None): @pytest.mark.parametrize("usecomplex", [True, False]) -def test_deflect_nsew(usecomplex): +def test_deflect_nsew(usecomplex) -> None: d = 5.0 r = np.radians(d) @@ -71,7 +71,7 @@ def alpha(re, im): assert np.allclose([lon, lat], [d, 0.0]) -def test_deflect_many(rng): +def test_deflect_many(rng) -> None: n = 1000 abs_alpha = rng.uniform(0, 2 * np.pi, size=n) arg_alpha = rng.uniform(-np.pi, np.pi, size=n) @@ -89,7 +89,7 @@ def test_deflect_many(rng): np.testing.assert_allclose(dotp, np.cos(abs_alpha)) -def test_multi_plane_matrix(shells, cosmo, rng): +def test_multi_plane_matrix(shells, cosmo, rng) -> None: mat = multi_plane_matrix(shells, cosmo) np.testing.assert_array_equal(mat, np.tril(mat)) @@ -106,7 +106,7 @@ def test_multi_plane_matrix(shells, cosmo, rng): np.testing.assert_allclose(mat @ deltas, kappas) -def test_multi_plane_weights(shells, cosmo, rng): +def test_multi_plane_weights(shells, cosmo, rng) -> None: w_in = np.eye(len(shells)) w_out = multi_plane_weights(w_in, shells, cosmo) diff --git a/tests/test_points.py b/tests/test_points.py index 7d8283db..754b94b1 100644 --- a/tests/test_points.py +++ b/tests/test_points.py @@ -12,7 +12,7 @@ def catpos(pos): return lon, lat, cnt -def test_positions_from_delta(): +def test_positions_from_delta() -> None: # case: single-dimensional input ngal = 1e-3 @@ -65,7 +65,7 @@ def test_positions_from_delta(): assert lat.shape == (cnt.sum(),) -def test_uniform_positions(): +def test_uniform_positions() -> None: # case: scalar input ngal = 1e-3 @@ -94,7 +94,7 @@ def test_uniform_positions(): assert lon.shape == lat.shape == (cnt.sum(),) -def test_position_weights(rng): +def test_position_weights(rng) -> None: for bshape in None, (), (100,), (100, 1): for cshape in (100,), (100, 50), (100, 3, 2): counts = rng.random(cshape) diff --git a/tests/test_shapes.py b/tests/test_shapes.py index c814db4d..bcaf15ba 100644 --- a/tests/test_shapes.py +++ b/tests/test_shapes.py @@ -9,7 +9,7 @@ ) -def test_triaxial_axis_ratio(): +def test_triaxial_axis_ratio() -> None: # single axis ratio q = triaxial_axis_ratio(0.8, 0.4) @@ -46,7 +46,7 @@ def test_triaxial_axis_ratio(): assert np.all((qmax >= q) & (q >= qmin)) -def test_ellipticity_ryden04(): +def test_ellipticity_ryden04() -> None: # single ellipticity e = ellipticity_ryden04(-1.85, 0.89, 0.222, 0.056) @@ -78,7 +78,7 @@ def test_ellipticity_ryden04(): assert np.all((e.real >= -1.0) & (e.real <= 1.0)) -def test_ellipticity_gaussian(): +def test_ellipticity_gaussian() -> None: n = 1_000_000 eps = ellipticity_gaussian(n, 0.256) @@ -102,7 +102,7 @@ def test_ellipticity_gaussian(): assert np.isclose(np.std(eps.imag[n:]), 0.256, atol=1e-3, rtol=0) -def test_ellipticity_intnorm(): +def test_ellipticity_intnorm() -> None: n = 1_000_000 eps = ellipticity_intnorm(n, 0.256) diff --git a/tests/test_shells.py b/tests/test_shells.py index c524e806..d865ed85 100644 --- a/tests/test_shells.py +++ b/tests/test_shells.py @@ -4,7 +4,7 @@ from glass.shells import RadialWindow, partition, restrict, tophat_windows -def test_tophat_windows(): +def test_tophat_windows() -> None: zb = [0.0, 0.1, 0.2, 0.5, 1.0, 2.0] dz = 0.005 @@ -21,7 +21,7 @@ def test_tophat_windows(): assert all(np.all(w.wa == 1) for w in ws) -def test_restrict(): +def test_restrict() -> None: # Gaussian test function z = np.linspace(0.0, 5.0, 1000) f = np.exp(-(((z - 2.0) / 0.5) ** 2) / 2) @@ -49,7 +49,7 @@ def test_restrict(): @pytest.mark.parametrize("method", ["lstsq", "nnls", "restrict"]) -def test_partition(method): +def test_partition(method) -> None: shells = [ RadialWindow(np.array([0.0, 1.0]), np.array([1.0, 0.0]), 0.0), RadialWindow(np.array([0.0, 1.0, 2.0]), np.array([0.0, 1.0, 0.0]), 0.5), From d22891e222f8b7da602f01833fd4022a5fb861ac Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Fri, 4 Oct 2024 17:05:56 +0100 Subject: [PATCH 06/32] Add types from docstrings --- glass/fields.py | 10 ++++++++-- glass/observations.py | 2 +- glass/points.py | 19 +++++++++++-------- glass/shapes.py | 14 ++++++++++++-- tests/test_fields.py | 2 +- tests/test_points.py | 2 +- 6 files changed, 34 insertions(+), 15 deletions(-) diff --git a/glass/fields.py b/glass/fields.py index fe6d634a..1969ec8d 100644 --- a/glass/fields.py +++ b/glass/fields.py @@ -320,7 +320,9 @@ def generate_lognormal( yield m -def getcl(cls, i, j, lmax=None): +def getcl( + cls: list[npt.ArrayLike], i: int, j: int, lmax: int | None = None +) -> npt.ArrayLike: """ Return a specific angular power spectrum from an array. @@ -354,7 +356,11 @@ def getcl(cls, i, j, lmax=None): def effective_cls( - cls, weights1, weights2=None, *, lmax=None + cls: list[npt.ArrayLike], + weights1: npt.ArrayLike, + weights2: npt.ArrayLike | None = None, + *, + lmax: int | None = None, ) -> npt.NDArray[np.float64]: r""" Compute effective angular power spectra from weights. diff --git a/glass/observations.py b/glass/observations.py index ccb2108c..f7f7a0bc 100644 --- a/glass/observations.py +++ b/glass/observations.py @@ -136,7 +136,7 @@ def smail_nz( alpha: npt.ArrayLike, beta: npt.ArrayLike, *, - norm: npt.ArrayLike | None = None, + norm: float | npt.ArrayLike | None = None, ) -> npt.NDArray: # type: ignore[type-arg] r""" Redshift distribution following Smail et al. (1994). diff --git a/glass/points.py b/glass/points.py index 3b8dcf10..ecf5c341 100644 --- a/glass/points.py +++ b/glass/points.py @@ -29,8 +29,11 @@ """ # noqa: D205, D400, D415 +from __future__ import annotations + import healpix import numpy as np +import numpy.typing as npt from glass.core.array import broadcast_first, broadcast_leading_axes, trapz_product @@ -86,14 +89,14 @@ def loglinear_bias(delta, b): def positions_from_delta( # noqa: PLR0912, PLR0913, PLR0915 - ngal, - delta, - bias=None, - vis=None, + ngal: float | npt.ArrayLike, + delta: npt.ArrayLike, + bias: float | npt.ArrayLike | None = None, + vis: npt.ArrayLike | None = None, *, bias_model="linear", - remove_monopole=False, - batch=1_000_000, + remove_monopole: bool = False, + batch: int | None = 1_000_000, rng=None, ): """ @@ -247,7 +250,7 @@ def positions_from_delta( # noqa: PLR0912, PLR0913, PLR0915 assert np.sum(n[stop:]) == 0 # noqa: S101 -def uniform_positions(ngal, *, rng=None): +def uniform_positions(ngal: float | npt.ArrayLike, *, rng=None): """ Generate positions uniformly over the sphere. @@ -298,7 +301,7 @@ def uniform_positions(ngal, *, rng=None): yield lon, lat, count -def position_weights(densities, bias=None): +def position_weights(densities: npt.ArrayLike, bias: npt.ArrayLike | None = None): r""" Compute relative weights for angular clustering. diff --git a/glass/shapes.py b/glass/shapes.py index 10533525..6d53350e 100644 --- a/glass/shapes.py +++ b/glass/shapes.py @@ -32,7 +32,9 @@ import numpy.typing as npt -def triaxial_axis_ratio(zeta, xi, size=None, *, rng=None): +def triaxial_axis_ratio( + zeta: npt.ArrayLike, xi: npt.ArrayLike, size: tuple[int] | None = None, *, rng=None +): r""" Axis ratio of a randomly projected triaxial ellipsoid. @@ -97,7 +99,15 @@ def triaxial_axis_ratio(zeta, xi, size=None, *, rng=None): ) -def ellipticity_ryden04(mu, sigma, gamma, sigma_gamma, size=None, *, rng=None): # noqa: PLR0913 +def ellipticity_ryden04( # noqa: PLR0913 + mu: npt.ArrayLike, + sigma: npt.ArrayLike, + gamma: npt.ArrayLike, + sigma_gamma: npt.ArrayLike, + size: int | tuple[int] | None = None, + *, + rng=None, +): r""" Ellipticity distribution following Ryden (2004). diff --git a/tests/test_fields.py b/tests/test_fields.py index 14009a04..05a73d11 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -1,7 +1,7 @@ from glass.fields import getcl -def test_getcl() -> None: +def test_getcl() -> None: # make a mock Cls array with the index pairs as entries cls = [{i, j} for i in range(10) for j in range(i, -1, -1)] # make sure indices are retrieved correctly diff --git a/tests/test_points.py b/tests/test_points.py index 754b94b1..1c846599 100644 --- a/tests/test_points.py +++ b/tests/test_points.py @@ -94,7 +94,7 @@ def test_uniform_positions() -> None: assert lon.shape == lat.shape == (cnt.sum(),) -def test_position_weights(rng) -> None: +def test_position_weights(rng) -> None: for bshape in None, (), (100,), (100, 1): for cshape in (100,), (100, 50), (100, 3, 2): counts = rng.random(cshape) From e6c8f77e318424577517436a5b3fcd5c36a8ec65 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Fri, 4 Oct 2024 17:11:00 +0100 Subject: [PATCH 07/32] Add `rng` type --- glass/points.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glass/points.py b/glass/points.py index ecf5c341..0562110b 100644 --- a/glass/points.py +++ b/glass/points.py @@ -97,7 +97,7 @@ def positions_from_delta( # noqa: PLR0912, PLR0913, PLR0915 bias_model="linear", remove_monopole: bool = False, batch: int | None = 1_000_000, - rng=None, + rng: np.random.Generator | None = None, ): """ Generate positions tracing a density contrast. From f53ffc527715a49073f5554971c0f5a3759f43a5 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Fri, 4 Oct 2024 17:14:20 +0100 Subject: [PATCH 08/32] Add other `rng` --- glass/points.py | 4 +++- glass/shapes.py | 8 ++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/glass/points.py b/glass/points.py index 0562110b..ee596ea7 100644 --- a/glass/points.py +++ b/glass/points.py @@ -250,7 +250,9 @@ def positions_from_delta( # noqa: PLR0912, PLR0913, PLR0915 assert np.sum(n[stop:]) == 0 # noqa: S101 -def uniform_positions(ngal: float | npt.ArrayLike, *, rng=None): +def uniform_positions( + ngal: float | npt.ArrayLike, *, rng: np.random.Generator | None = None +): """ Generate positions uniformly over the sphere. diff --git a/glass/shapes.py b/glass/shapes.py index c23ffa6e..50a12d18 100644 --- a/glass/shapes.py +++ b/glass/shapes.py @@ -33,7 +33,11 @@ def triaxial_axis_ratio( - zeta: npt.ArrayLike, xi: npt.ArrayLike, size: tuple[int] | None = None, *, rng=None + zeta: npt.ArrayLike, + xi: npt.ArrayLike, + size: tuple[int] | None = None, + *, + rng: np.random.Generator | None = None, ): r""" Axis ratio of a randomly projected triaxial ellipsoid. @@ -106,7 +110,7 @@ def ellipticity_ryden04( # noqa: PLR0913 sigma_gamma: npt.ArrayLike, size: int | tuple[int] | None = None, *, - rng=None, + rng: np.random.Generator | None = None, ): r""" Ellipticity distribution following Ryden (2004). From 46c75e9d5903730e962ff49d101f249843a2ba80 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Mon, 7 Oct 2024 12:19:30 +0100 Subject: [PATCH 09/32] Switch from `NDArray` to `ArrayLke` --- glass/fields.py | 20 +++++++++++--------- glass/galaxies.py | 20 ++++++++++---------- glass/lensing.py | 24 ++++++++++++------------ glass/observations.py | 20 ++++++++++---------- glass/shapes.py | 4 ++-- glass/shells.py | 12 ++++++------ 6 files changed, 51 insertions(+), 49 deletions(-) diff --git a/glass/fields.py b/glass/fields.py index 1969ec8d..83a789cc 100644 --- a/glass/fields.py +++ b/glass/fields.py @@ -37,15 +37,15 @@ # types Size = Optional[Union[int, tuple[int, ...]]] -Iternorm = tuple[Optional[int], npt.NDArray, npt.NDArray] # type: ignore[type-arg] -ClTransform = Union[str, Callable[[npt.NDArray], npt.NDArray]] # type: ignore[type-arg] -Cls = Sequence[Union[npt.NDArray, Sequence[float]]] # type: ignore[type-arg] -Alms = npt.NDArray # type: ignore[type-arg] +Iternorm = tuple[Optional[int], npt.ArrayLike, npt.ArrayLike] +ClTransform = Union[str, Callable[[npt.ArrayLike], npt.ArrayLike]] +Cls = Sequence[Union[npt.ArrayLike, Sequence[float]]] +Alms = npt.ArrayLike def iternorm( k: int, - cov: Iterable[npt.NDArray], # type: ignore[type-arg] + cov: Iterable[npt.ArrayLike], size: Size = None, ) -> Generator[Iternorm, None, None]: """Return the vector a and variance sigma^2 for iterative normal sampling.""" @@ -105,7 +105,9 @@ def iternorm( yield j, a, s -def cls2cov(cls: Cls, nl: int, nf: int, nc: int) -> Generator[npt.NDArray, None, None]: +def cls2cov( + cls: Cls, nl: int, nf: int, nc: int +) -> Generator[npt.ArrayLike, None, None]: """Return array of cls as a covariance matrix for iterative sampling.""" cov = np.zeros((nl, nc + 1)) end = 0 @@ -125,7 +127,7 @@ def cls2cov(cls: Cls, nl: int, nf: int, nc: int) -> Generator[npt.NDArray, None, yield cov -def multalm(alm: Alms, bl: npt.NDArray, *, inplace: bool = False) -> Alms: +def multalm(alm: Alms, bl: npt.ArrayLike, *, inplace: bool = False) -> Alms: """Multiply alm by bl.""" n = len(bl) out = np.asanyarray(alm) if inplace else np.copy(alm) @@ -212,7 +214,7 @@ def generate_gaussian( *, ncorr: int | None = None, rng: np.random.Generator | None = None, -) -> Generator[npt.NDArray, None, None]: +) -> Generator[npt.ArrayLike, None, None]: """ Sample Gaussian random fields from Cls iteratively. @@ -298,7 +300,7 @@ def generate_lognormal( *, ncorr: int | None = None, rng: np.random.Generator | None = None, -) -> Generator[npt.NDArray, None, None]: +) -> Generator[npt.ArrayLike, None, None]: """Sample lognormal random fields from Gaussian Cls iteratively.""" for i, m in enumerate(generate_gaussian(gls, nside, ncorr=ncorr, rng=rng)): # compute the variance of the auto-correlation diff --git a/glass/galaxies.py b/glass/galaxies.py index 8b2da78c..63678e30 100644 --- a/glass/galaxies.py +++ b/glass/galaxies.py @@ -37,7 +37,7 @@ def redshifts( w: RadialWindow, *, rng: np.random.Generator | None = None, -) -> npt.NDArray: # type: ignore[type-arg] +) -> npt.ArrayLike: """ Sample redshifts from a radial window function. @@ -69,7 +69,7 @@ def redshifts_from_nz( nz: npt.ArrayLike, *, rng: np.random.Generator | None = None, -) -> npt.NDArray: # type: ignore[type-arg] +) -> npt.ArrayLike: """ Generate galaxy redshifts from a source distribution. @@ -132,15 +132,15 @@ def redshifts_from_nz( def galaxy_shear( # noqa: PLR0913 - lon: npt.NDArray, # type: ignore[type-arg] - lat: npt.NDArray, # type: ignore[type-arg] - eps: npt.NDArray, # type: ignore[type-arg] - kappa: npt.NDArray, # type: ignore[type-arg] - gamma1: npt.NDArray, # type: ignore[type-arg] - gamma2: npt.NDArray, # type: ignore[type-arg] + lon: npt.ArrayLike, + lat: npt.ArrayLike, + eps: npt.ArrayLike, + kappa: npt.ArrayLike, + gamma1: npt.ArrayLike, + gamma2: npt.ArrayLike, *, reduced_shear: bool = True, -) -> npt.NDArray: # type: ignore[type-arg] +) -> npt.ArrayLike: """ Observed galaxy shears from weak lensing. @@ -201,7 +201,7 @@ def gaussian_phz( lower: npt.ArrayLike | None = None, upper: npt.ArrayLike | None = None, rng: np.random.Generator | None = None, -) -> npt.NDArray: # type: ignore[type-arg] +) -> npt.ArrayLike: r""" Photometric redshifts assuming a Gaussian error. diff --git a/glass/lensing.py b/glass/lensing.py index 55f25fca..886dc7d1 100644 --- a/glass/lensing.py +++ b/glass/lensing.py @@ -47,14 +47,14 @@ def from_convergence( # noqa: PLR0913 - kappa: npt.NDArray, # type: ignore[type-arg] + kappa: npt.ArrayLike, lmax: int | None = None, *, potential: bool = False, deflection: bool = False, shear: bool = False, discretized: bool = True, -) -> tuple[npt.NDArray, ...]: +) -> tuple[npt.ArrayLike, ...]: r""" Compute other weak lensing maps from the convergence. @@ -226,11 +226,11 @@ def from_convergence( # noqa: PLR0913 def shear_from_convergence( - kappa: npt.NDArray, # type: ignore[type-arg] + kappa: npt.ArrayLike, lmax: int | None = None, *, discretized: bool = True, -) -> npt.NDArray: # type: ignore[type-arg] +) -> npt.ArrayLike: r""" Weak lensing shear from convergence. @@ -282,11 +282,11 @@ def __init__(self, cosmo: Cosmology) -> None: self.x3: float = 0.0 self.w3: float = 0.0 self.r23: float = 1.0 - self.delta3: npt.NDArray = np.array(0.0) - self.kappa2: npt.NDArray | None = None - self.kappa3: npt.NDArray | None = None + self.delta3: npt.ArrayLike = np.array(0.0) + self.kappa2: npt.ArrayLike | None = None + self.kappa3: npt.ArrayLike | None = None - def add_window(self, delta: npt.NDArray, w: RadialWindow) -> None: + def add_window(self, delta: npt.ArrayLike, w: RadialWindow) -> None: """ Add a mass plane from a window function to the convergence. @@ -299,7 +299,7 @@ def add_window(self, delta: npt.NDArray, w: RadialWindow) -> None: self.add_plane(delta, zsrc, lens_weight) - def add_plane(self, delta: npt.NDArray, zsrc: float, wlens: float = 1.0) -> None: + def add_plane(self, delta: npt.ArrayLike, zsrc: float, wlens: float = 1.0) -> None: """Add a mass plane at redshift ``zsrc`` to the convergence.""" if zsrc <= self.z3: msg = "source redshift must be increasing" @@ -348,12 +348,12 @@ def zsrc(self) -> float: return self.z3 @property - def kappa(self) -> npt.NDArray | None: + def kappa(self) -> npt.ArrayLike | None: """The current convergence plane.""" return self.kappa3 @property - def delta(self) -> npt.NDArray: # type: ignore[type-arg] + def delta(self) -> npt.ArrayLike: """The current matter plane.""" return self.delta3 @@ -421,7 +421,7 @@ def multi_plane_weights( def deflect( lon: npt.ArrayLike, lat: npt.ArrayLike, alpha: npt.ArrayLike -) -> npt.NDArray: +) -> npt.ArrayLike: r""" Apply deflections to positions. diff --git a/glass/observations.py b/glass/observations.py index f7f7a0bc..f66fd9cf 100644 --- a/glass/observations.py +++ b/glass/observations.py @@ -44,7 +44,7 @@ def vmap_galactic_ecliptic( nside: int, galactic: tuple[float, float] = (30, 90), ecliptic: tuple[float, float] = (20, 80), -) -> npt.NDArray: # type: ignore[type-arg] +) -> npt.ArrayLike: """ Visibility map masking galactic and ecliptic plane. @@ -86,12 +86,12 @@ def vmap_galactic_ecliptic( def gaussian_nz( - z: npt.NDArray, # type: ignore[type-arg] + z: npt.ArrayLike, mean: npt.ArrayLike, sigma: npt.ArrayLike, *, norm: npt.ArrayLike | None = None, -) -> npt.NDArray: # type: ignore[type-arg] +) -> npt.ArrayLike: r""" Gaussian redshift distribution. @@ -131,13 +131,13 @@ def gaussian_nz( def smail_nz( - z: npt.NDArray, # type: ignore[type-arg] + z: npt.ArrayLike, z_mode: npt.ArrayLike, alpha: npt.ArrayLike, beta: npt.ArrayLike, *, norm: float | npt.ArrayLike | None = None, -) -> npt.NDArray: # type: ignore[type-arg] +) -> npt.ArrayLike: r""" Redshift distribution following Smail et al. (1994). @@ -232,8 +232,8 @@ def fixed_zbins( def equal_dens_zbins( - z: npt.NDArray, # type: ignore[type-arg] - nz: npt.NDArray, # type: ignore[type-arg] + z: npt.ArrayLike, + nz: npt.ArrayLike, nbins: int, ) -> list[tuple[float, float]]: """ @@ -267,11 +267,11 @@ def equal_dens_zbins( def tomo_nz_gausserr( - z: npt.NDArray, # type: ignore[type-arg] - nz: npt.NDArray, # type: ignore[type-arg] + z: npt.ArrayLike, + nz: npt.ArrayLike, sigma_0: float, zbins: list[tuple[float, float]], -) -> npt.NDArray: # type: ignore[type-arg] +) -> npt.ArrayLike: """ Tomographic redshift bins with a Gaussian redshift error. diff --git a/glass/shapes.py b/glass/shapes.py index 50a12d18..cd16cf9a 100644 --- a/glass/shapes.py +++ b/glass/shapes.py @@ -189,7 +189,7 @@ def ellipticity_gaussian( sigma: npt.ArrayLike, *, rng: np.random.Generator | None = None, -) -> npt.NDArray: # type: ignore[type-arg] +) -> npt.ArrayLike: r""" Sample Gaussian galaxy ellipticities. @@ -246,7 +246,7 @@ def ellipticity_intnorm( sigma: npt.ArrayLike, *, rng: np.random.Generator | None = None, -) -> npt.NDArray: # type: ignore[type-arg] +) -> npt.ArrayLike: r""" Sample galaxy ellipticities with intrinsic normal distribution. diff --git a/glass/shells.py b/glass/shells.py index 613e282a..bc01b532 100644 --- a/glass/shells.py +++ b/glass/shells.py @@ -57,21 +57,21 @@ from cosmology import Cosmology # types -ArrayLike1D = Union[Sequence[float], npt.NDArray] # type: ignore[type-arg] -WeightFunc = Callable[[ArrayLike1D], npt.NDArray] # type: ignore[type-arg] +ArrayLike1D = Union[Sequence[float], npt.ArrayLike] +WeightFunc = Callable[[ArrayLike1D], npt.ArrayLike] -def distance_weight(z: npt.ArrayLike, cosmo: Cosmology) -> npt.NDArray: # type: ignore[type-arg] +def distance_weight(z: npt.ArrayLike, cosmo: Cosmology) -> npt.ArrayLike: """Uniform weight in comoving distance.""" return 1 / cosmo.ef(z) -def volume_weight(z: npt.ArrayLike, cosmo: Cosmology) -> npt.NDArray: # type: ignore[type-arg] +def volume_weight(z: npt.ArrayLike, cosmo: Cosmology) -> npt.ArrayLike: """Uniform weight in comoving volume.""" return cosmo.xm(z) ** 2 / cosmo.ef(z) -def density_weight(z: npt.ArrayLike, cosmo: Cosmology) -> npt.NDArray: # type: ignore[type-arg] +def density_weight(z: npt.ArrayLike, cosmo: Cosmology) -> npt.ArrayLike: """Uniform weight in matter density.""" return cosmo.rho_m_z(z) * cosmo.xm(z) ** 2 / cosmo.ef(z) @@ -311,7 +311,7 @@ def restrict( z: ArrayLike1D, f: ArrayLike1D, w: RadialWindow, -) -> tuple[npt.NDArray, npt.NDArray]: # type: ignore[type-arg] +) -> tuple[npt.ArrayLike, npt.ArrayLike]: """ Restrict a function to a redshift window. From cdc4312311c6de78455efcc08a6c7cffdd0e9aae Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Mon, 7 Oct 2024 12:39:16 +0100 Subject: [PATCH 10/32] Add typing to `array` --- glass/core/array.py | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/glass/core/array.py b/glass/core/array.py index ff19ba2e..b713870c 100644 --- a/glass/core/array.py +++ b/glass/core/array.py @@ -1,18 +1,23 @@ """Module for array utilities.""" +from __future__ import annotations + from functools import partial import numpy as np +import numpy.typing as npt -def broadcast_first(*arrays): +def broadcast_first(*arrays: npt.ArrayLike) -> tuple[npt.ArrayLike, ...]: """Broadcast arrays, treating the first axis as common.""" arrays = tuple(np.moveaxis(a, 0, -1) if np.ndim(a) else a for a in arrays) arrays = np.broadcast_arrays(*arrays) return tuple(np.moveaxis(a, -1, 0) if np.ndim(a) else a for a in arrays) -def broadcast_leading_axes(*args): +def broadcast_leading_axes( + *args: tuple[npt.ArrayLike, int], +) -> tuple[tuple[int, ...], ...]: """ Broadcast all but the last N axes. @@ -49,7 +54,15 @@ def broadcast_leading_axes(*args): return (dims, *arrs) -def ndinterp(x, xp, fp, axis=-1, left=None, right=None, period=None): # noqa: PLR0913 +def ndinterp( # noqa: PLR0913 + x: npt.ArrayLike, + xp: npt.ArrayLike, + fp: npt.ArrayLike, + axis: int = -1, + left: float | None = None, + right: float | None = None, + period: float | None = None, +) -> npt.ArrayLike: """Interpolate multi-dimensional array over axis.""" return np.apply_along_axis( partial(np.interp, x, xp), @@ -61,7 +74,11 @@ def ndinterp(x, xp, fp, axis=-1, left=None, right=None, period=None): # noqa: P ) -def trapz_product(f, *ff, axis=-1): +def trapz_product( + f: tuple[npt.ArrayLike, npt.ArrayLike], + *ff: tuple[npt.ArrayLike, npt.ArrayLike], + axis: int = -1, +) -> npt.ArrayLike: """Trapezoidal rule for a product of functions.""" x, _ = f for x_, _ in ff: @@ -75,7 +92,12 @@ def trapz_product(f, *ff, axis=-1): return np.trapz(y, x, axis=axis) -def cumtrapz(f, x, dtype=None, out=None): +def cumtrapz( + f: npt.ArrayLike, + x: npt.ArrayLike, + dtype: np.dtype | None = None, + out: npt.ArrayLike | None = None, +) -> npt.NDArray: """Cumulative trapezoidal rule along last axis.""" if out is None: out = np.empty_like(f, dtype=dtype) From 6e456e863b891124be05b649c5275a44faa992fe Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Mon, 7 Oct 2024 12:47:04 +0100 Subject: [PATCH 11/32] Add types to `user` --- glass/core/array.py | 2 +- glass/user.py | 20 ++++++++++++++------ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/glass/core/array.py b/glass/core/array.py index b713870c..42362879 100644 --- a/glass/core/array.py +++ b/glass/core/array.py @@ -54,7 +54,7 @@ def broadcast_leading_axes( return (dims, *arrs) -def ndinterp( # noqa: PLR0913 +def ndinterp( # noqa: PLR0913 x: npt.ArrayLike, xp: npt.ArrayLike, fp: npt.ArrayLike, diff --git a/glass/user.py b/glass/user.py index 7996e784..d4fe463d 100644 --- a/glass/user.py +++ b/glass/user.py @@ -17,12 +17,16 @@ """ # noqa: D205, D400, D415 +from __future__ import annotations + +import typing from contextlib import contextmanager import numpy as np +import numpy.typing as npt -def save_cls(filename, cls) -> None: +def save_cls(filename: str, cls: list[npt.ArrayLike | None]) -> None: """ Save a list of Cls to file. @@ -35,7 +39,7 @@ def save_cls(filename, cls) -> None: np.savez(filename, values=values, split=split) -def load_cls(filename): +def load_cls(filename: str) -> list[npt.ArrayLike]: """ Load a list of Cls from file. @@ -55,12 +59,12 @@ class _FitsWriter: Initialised with the fits object and extension name. """ - def __init__(self, fits, ext=None) -> None: + def __init__(self, fits, ext: str | None = None) -> None: """Create a new, uninitialised writer.""" self.fits = fits self.ext = ext - def _append(self, data, names=None) -> None: + def _append(self, data: npt.ArrayLike, names: list[str] | None = None) -> None: """Write the FITS file.""" if self.ext is None or self.ext not in self.fits: self.fits.write_table(data, names=names, extname=self.ext) @@ -71,7 +75,9 @@ def _append(self, data, names=None) -> None: # not using hdu.append here because of incompatibilities hdu.write(data, names=names, firstrow=hdu.get_nrows()) - def write(self, data=None, /, **columns) -> None: + def write( + self, data: npt.ArrayLike | None = None, /, **columns: npt.ArrayLike + ) -> None: """ Write to FITS by calling the internal _append method. @@ -89,7 +95,9 @@ def write(self, data=None, /, **columns) -> None: @contextmanager -def write_catalog(filename, *, ext=None): +def write_catalog( + filename: str, *, ext: str | None = None +) -> typing.Iterator[_FitsWriter]: """ Write a catalogue into a FITS file. From 5b3a94cdd097621d5f76fa238783a99de065e90a Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Mon, 7 Oct 2024 12:55:23 +0100 Subject: [PATCH 12/32] Add `points` typing --- glass/points.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/glass/points.py b/glass/points.py index ee596ea7..d5368b64 100644 --- a/glass/points.py +++ b/glass/points.py @@ -31,16 +31,23 @@ from __future__ import annotations +import typing + import healpix import numpy as np import numpy.typing as npt from glass.core.array import broadcast_first, broadcast_leading_axes, trapz_product +if typing.TYPE_CHECKING: + from glass.shells import RadialWindow + ARCMIN2_SPHERE = 60**6 // 100 / np.pi -def effective_bias(z, bz, w): +def effective_bias( + z: npt.ArrayLike, bz: npt.ArrayLike, w: RadialWindow +) -> npt.ArrayLike: r""" Effective bias parameter from a redshift-dependent bias function. From ec53ba5fa4ad4ea439b9c3caf70e86fe00f19e20 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Mon, 7 Oct 2024 15:22:15 +0100 Subject: [PATCH 13/32] Typing for `shells` --- glass/shells.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/glass/shells.py b/glass/shells.py index bc01b532..40d6f355 100644 --- a/glass/shells.py +++ b/glass/shells.py @@ -578,7 +578,9 @@ def partition_restrict( return part -def redshift_grid(zmin, zmax, *, dz=None, num=None): +def redshift_grid( + zmin: float, zmax: float, *, dz: float | None = None, num: int | None = None +) -> npt.NDArray[float]: """Redshift grid with uniform spacing in redshift.""" if dz is not None and num is None: z = np.arange(zmin, np.nextafter(zmax + dz, zmax), dz) @@ -590,7 +592,9 @@ def redshift_grid(zmin, zmax, *, dz=None, num=None): return z -def distance_grid(cosmo, zmin, zmax, *, dx=None, num=None): +def distance_grid( + cosmo, zmin: float, zmax: float, *, dx: float | None = None, num: int | None = None +) -> npt.NDArray[float]: """Redshift grid with uniform spacing in comoving distance.""" xmin, xmax = cosmo.dc(zmin), cosmo.dc(zmax) if dx is not None and num is None: From e59a5fa55c24a259bedde1092dfa02b7a672faba Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Mon, 7 Oct 2024 16:02:15 +0100 Subject: [PATCH 14/32] Add more typing --- glass/points.py | 6 ++++-- glass/shells.py | 7 ++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/glass/points.py b/glass/points.py index d5368b64..055fbe2e 100644 --- a/glass/points.py +++ b/glass/points.py @@ -82,12 +82,14 @@ def effective_bias( return trapz_product((z, bz), (w.za, w.wa)) / norm -def linear_bias(delta, b): +def linear_bias(delta: npt.ArrayLike, b: float | npt.ArrayLike) -> npt.NDArray[float]: r"""Linear bias model :math:`\\delta_g = b \\, \\delta`.""" return b * delta -def loglinear_bias(delta, b): +def loglinear_bias( + delta: npt.ArrayLike, b: float | npt.ArrayLike +) -> npt.NDArray[float]: r"""log-linear bias model :math:`\\ln(1 + \\delta_g) = b \\ln(1 + \\delta)`.""" delta_g = np.log1p(delta) delta_g *= b diff --git a/glass/shells.py b/glass/shells.py index 40d6f355..52a624b7 100644 --- a/glass/shells.py +++ b/glass/shells.py @@ -593,7 +593,12 @@ def redshift_grid( def distance_grid( - cosmo, zmin: float, zmax: float, *, dx: float | None = None, num: int | None = None + cosmo: Cosmology, + zmin: float, + zmax: float, + *, + dx: float | None = None, + num: int | None = None, ) -> npt.NDArray[float]: """Redshift grid with uniform spacing in comoving distance.""" xmin, xmax = cosmo.dc(zmin), cosmo.dc(zmax) From d4e5396f772e7977df05f0a84b3263a2dbe2219e Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Mon, 7 Oct 2024 16:29:32 +0100 Subject: [PATCH 15/32] Turn off decorator warnings --- glass/shells.py | 2 +- pyproject.toml | 1 + tests/test_lensing.py | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/glass/shells.py b/glass/shells.py index 52a624b7..a10c1ba4 100644 --- a/glass/shells.py +++ b/glass/shells.py @@ -122,7 +122,7 @@ class RadialWindow(NamedTuple): za: Sequence[float] wa: Sequence[float] - zeff: float + zeff: float | None def tophat_windows( diff --git a/pyproject.toml b/pyproject.toml index 96a07871..fa39ffe1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -94,6 +94,7 @@ build.targets.sdist.exclude = [ version.source = "vcs" [tool.mypy] +disallow_untyped_decorators = false enable_error_code = [ "ignore-without-code", "redundant-expr", diff --git a/tests/test_lensing.py b/tests/test_lensing.py index 22218038..5ba75ae1 100644 --- a/tests/test_lensing.py +++ b/tests/test_lensing.py @@ -12,7 +12,7 @@ @pytest.fixture -def shells(): +def shells() -> list[RadialWindow]: return [ RadialWindow([0.0, 1.0, 2.0], [0.0, 1.0, 0.0], 1.0), RadialWindow([1.0, 2.0, 3.0], [0.0, 1.0, 0.0], 2.0), From a2a1a5f03626ebc4daef9a82975e95dac56c1bd7 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Mon, 7 Oct 2024 17:32:05 +0100 Subject: [PATCH 16/32] Add return types --- glass/shapes.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/glass/shapes.py b/glass/shapes.py index cd16cf9a..e9fbe0c0 100644 --- a/glass/shapes.py +++ b/glass/shapes.py @@ -38,7 +38,7 @@ def triaxial_axis_ratio( size: tuple[int] | None = None, *, rng: np.random.Generator | None = None, -): +) -> npt.ArrayLike: r""" Axis ratio of a randomly projected triaxial ellipsoid. @@ -111,7 +111,7 @@ def ellipticity_ryden04( # noqa: PLR0913 size: int | tuple[int] | None = None, *, rng: np.random.Generator | None = None, -): +) -> npt.ArrayLike: r""" Ellipticity distribution following Ryden (2004). From c2c145be509a81b4c56011564eb880f30aa888d8 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Mon, 7 Oct 2024 22:39:05 +0100 Subject: [PATCH 17/32] More typing --- glass/core/array.py | 2 +- glass/lensing.py | 2 +- glass/observations.py | 4 ++-- glass/points.py | 2 +- glass/shapes.py | 2 +- glass/shells.py | 10 +++++----- tests/conftest.py | 3 ++- tests/test_lensing.py | 2 +- tests/test_points.py | 2 +- tests/test_shells.py | 2 +- 10 files changed, 16 insertions(+), 15 deletions(-) diff --git a/glass/core/array.py b/glass/core/array.py index 42362879..bcd3ca55 100644 --- a/glass/core/array.py +++ b/glass/core/array.py @@ -89,7 +89,7 @@ def trapz_product( y = np.interp(x, *f) for f_ in ff: y *= np.interp(x, *f_) - return np.trapz(y, x, axis=axis) + return np.trapz(y, x, axis=axis) # type: ignore[attr-defined] def cumtrapz( diff --git a/glass/lensing.py b/glass/lensing.py index 886dc7d1..6f8f3295 100644 --- a/glass/lensing.py +++ b/glass/lensing.py @@ -295,7 +295,7 @@ def add_window(self, delta: npt.ArrayLike, w: RadialWindow) -> None: """ zsrc = w.zeff - lens_weight = np.trapz(w.wa, w.za) / np.interp(zsrc, w.za, w.wa) + lens_weight = np.trapz(w.wa, w.za) / np.interp(zsrc, w.za, w.wa) # type: ignore[attr-defined] self.add_plane(delta, zsrc, lens_weight) diff --git a/glass/observations.py b/glass/observations.py index f66fd9cf..7a8b14bc 100644 --- a/glass/observations.py +++ b/glass/observations.py @@ -122,7 +122,7 @@ def gaussian_nz( sigma = np.reshape(sigma, np.shape(sigma) + (1,) * np.ndim(z)) nz = np.exp(-(((z - mean) / sigma) ** 2) / 2) - nz /= np.trapz(nz, z, axis=-1)[..., np.newaxis] + nz /= np.trapz(nz, z, axis=-1)[..., np.newaxis] # type: ignore[attr-defined] if norm is not None: nz *= norm @@ -184,7 +184,7 @@ def smail_nz( beta = np.asanyarray(beta)[..., np.newaxis] pz = z**alpha * np.exp(-alpha / beta * (z / z_mode) ** beta) - pz /= np.trapz(pz, z, axis=-1)[..., np.newaxis] + pz /= np.trapz(pz, z, axis=-1)[..., np.newaxis] # type: ignore[attr-defined] if norm is not None: pz *= norm diff --git a/glass/points.py b/glass/points.py index 055fbe2e..26ac31b5 100644 --- a/glass/points.py +++ b/glass/points.py @@ -78,7 +78,7 @@ def effective_bias( \\;. """ - norm = np.trapz(w.wa, w.za) + norm = np.trapz(w.wa, w.za) # type: ignore[attr-defined] return trapz_product((z, bz), (w.za, w.wa)) / norm diff --git a/glass/shapes.py b/glass/shapes.py index e9fbe0c0..32664933 100644 --- a/glass/shapes.py +++ b/glass/shapes.py @@ -108,7 +108,7 @@ def ellipticity_ryden04( # noqa: PLR0913 sigma: npt.ArrayLike, gamma: npt.ArrayLike, sigma_gamma: npt.ArrayLike, - size: int | tuple[int] | None = None, + size: int | tuple[int, ...] | None = None, *, rng: np.random.Generator | None = None, ) -> npt.ArrayLike: diff --git a/glass/shells.py b/glass/shells.py index a10c1ba4..e0627076 100644 --- a/glass/shells.py +++ b/glass/shells.py @@ -179,7 +179,7 @@ def tophat_windows( n = max(round((zmax - zmin) / dz), 2) z = np.linspace(zmin, zmax, n) w = wht(z) - zeff = np.trapz(w * z, z) / np.trapz(w, z) + zeff = np.trapz(w * z, z) / np.trapz(w, z) # type: ignore[attr-defined] ws.append(RadialWindow(z, w, zeff)) return ws @@ -482,7 +482,7 @@ def partition_lstsq( # create the window function matrix a = [np.interp(zp, za, wa, left=0.0, right=0.0) for za, wa, _ in shells] - a /= np.trapz(a, zp, axis=-1)[..., None] + a /= np.trapz(a, zp, axis=-1)[..., None] # type: ignore[attr-defined] a = a * dz # create the target vector of distribution values @@ -536,7 +536,7 @@ def partition_nnls( # create the window function matrix a = [np.interp(zp, za, wa, left=0.0, right=0.0) for za, wa, _ in shells] - a /= np.trapz(a, zp, axis=-1)[..., None] + a /= np.trapz(a, zp, axis=-1)[..., None] # type: ignore[attr-defined] a = a * dz # create the target vector of distribution values @@ -574,7 +574,7 @@ def partition_restrict( part = np.empty((len(shells),) + np.shape(fz)[:-1]) for i, w in enumerate(shells): zr, fr = restrict(z, fz, w) - part[i] = np.trapz(fr, zr, axis=-1) + part[i] = np.trapz(fr, zr, axis=-1) # type: ignore[attr-defined] return part @@ -653,7 +653,7 @@ def combine( * np.interp( z, shell.za, - shell.wa / np.trapz(shell.wa, shell.za), + shell.wa / np.trapz(shell.wa, shell.za), # type: ignore[attr-defined] left=0.0, right=0.0, ) diff --git a/tests/conftest.py b/tests/conftest.py index c9b96801..b2b6a9fd 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,8 +1,9 @@ +import numpy as np import pytest @pytest.fixture(scope="session") -def rng(): +def rng() -> np.random.Generator: import numpy as np return np.random.default_rng(seed=42) diff --git a/tests/test_lensing.py b/tests/test_lensing.py index 5ba75ae1..2c089535 100644 --- a/tests/test_lensing.py +++ b/tests/test_lensing.py @@ -41,7 +41,7 @@ def xm(self, z, z2=None): @pytest.mark.parametrize("usecomplex", [True, False]) -def test_deflect_nsew(usecomplex) -> None: +def test_deflect_nsew(usecomplex: bool) -> None: d = 5.0 r = np.radians(d) diff --git a/tests/test_points.py b/tests/test_points.py index 1c846599..ca9524b2 100644 --- a/tests/test_points.py +++ b/tests/test_points.py @@ -94,7 +94,7 @@ def test_uniform_positions() -> None: assert lon.shape == lat.shape == (cnt.sum(),) -def test_position_weights(rng) -> None: +def test_position_weights(rng: np.random.Generator) -> None: for bshape in None, (), (100,), (100, 1): for cshape in (100,), (100, 50), (100, 3, 2): counts = rng.random(cshape) diff --git a/tests/test_shells.py b/tests/test_shells.py index d865ed85..fcfc3ab0 100644 --- a/tests/test_shells.py +++ b/tests/test_shells.py @@ -69,4 +69,4 @@ def test_partition(method) -> None: assert part.shape == (len(shells), 3, 2) - assert np.allclose(part.sum(axis=0), np.trapz(fz, z)) + assert np.allclose(part.sum(axis=0), np.trapz(fz, z)) # type: ignore[attr-defined] From b28be77475d1976d1321cd359096b7e71208ef3c Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Tue, 8 Oct 2024 17:08:21 +0100 Subject: [PATCH 18/32] Run `mypy_clean_slate` --- docs/conf.py | 2 +- glass/core/array.py | 22 +++++------ glass/ext/__init__.py | 2 +- glass/fields.py | 50 ++++++++++++------------- glass/galaxies.py | 44 +++++++++++----------- glass/lensing.py | 18 ++++----- glass/observations.py | 18 ++++----- glass/points.py | 32 +++++++++------- glass/shapes.py | 16 ++++---- glass/shells.py | 72 ++++++++++++++++++------------------ glass/user.py | 10 ++--- noxfile.py | 16 ++++---- tests/conftest.py | 4 +- tests/core/test_algorithm.py | 10 ++--- tests/core/test_array.py | 68 +++++++++++++++++----------------- tests/test_fields.py | 2 +- tests/test_fits.py | 26 +++++++------ tests/test_galaxies.py | 72 ++++++++++++++++++------------------ tests/test_lensing.py | 48 ++++++++++++------------ tests/test_points.py | 30 +++++++-------- tests/test_shapes.py | 42 ++++++++++----------- tests/test_shells.py | 38 +++++++++---------- 22 files changed, 324 insertions(+), 318 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 4392b0b6..89382b50 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -54,7 +54,7 @@ html_logo = "_static/logo.png" html_favicon = "_static/favicon.ico" -html_css_files = [] +html_css_files = [] # type: ignore[var-annotated] # -- Intersphinx ------------------------------------------------------------- diff --git a/glass/core/array.py b/glass/core/array.py index bcd3ca55..1dea9593 100644 --- a/glass/core/array.py +++ b/glass/core/array.py @@ -10,7 +10,7 @@ def broadcast_first(*arrays: npt.ArrayLike) -> tuple[npt.ArrayLike, ...]: """Broadcast arrays, treating the first axis as common.""" - arrays = tuple(np.moveaxis(a, 0, -1) if np.ndim(a) else a for a in arrays) + arrays = tuple(np.moveaxis(a, 0, -1) if np.ndim(a) else a for a in arrays) # type: ignore[arg-type] arrays = np.broadcast_arrays(*arrays) return tuple(np.moveaxis(a, -1, 0) if np.ndim(a) else a for a in arrays) @@ -51,7 +51,7 @@ def broadcast_leading_axes( trails.append(s[i:]) dims = np.broadcast_shapes(*shapes) arrs = (np.broadcast_to(a, dims + t) for (a, _), t in zip(args, trails)) - return (dims, *arrs) + return (dims, *arrs) # type: ignore[arg-type] def ndinterp( # noqa: PLR0913 @@ -83,25 +83,25 @@ def trapz_product( x, _ = f for x_, _ in ff: x = np.union1d( - x[(x >= x_[0]) & (x <= x_[-1])], - x_[(x_ >= x[0]) & (x_ <= x[-1])], + x[(x >= x_[0]) & (x <= x_[-1])], # type: ignore[index, operator] + x_[(x_ >= x[0]) & (x_ <= x[-1])], # type: ignore[index, operator] ) - y = np.interp(x, *f) + y = np.interp(x, *f) # type: ignore[arg-type] for f_ in ff: - y *= np.interp(x, *f_) - return np.trapz(y, x, axis=axis) # type: ignore[attr-defined] + y *= np.interp(x, *f_) # type: ignore[arg-type] + return np.trapz(y, x, axis=axis) # type: ignore[no-any-return] # type: ignore[attr-defined] def cumtrapz( f: npt.ArrayLike, x: npt.ArrayLike, - dtype: np.dtype | None = None, + dtype: np.dtype | None = None, # type: ignore[type-arg] out: npt.ArrayLike | None = None, -) -> npt.NDArray: +) -> npt.ArrayLike: """Cumulative trapezoidal rule along last axis.""" if out is None: out = np.empty_like(f, dtype=dtype) - np.cumsum((f[..., 1:] + f[..., :-1]) / 2 * np.diff(x), axis=-1, out=out[..., 1:]) - out[..., 0] = 0 + np.cumsum((f[..., 1:] + f[..., :-1]) / 2 * np.diff(x), axis=-1, out=out[..., 1:]) # type: ignore[arg-type, call-overload, index, operator] + out[..., 0] = 0 # type: ignore[index] return out diff --git a/glass/ext/__init__.py b/glass/ext/__init__.py index df401e13..ad17a437 100644 --- a/glass/ext/__init__.py +++ b/glass/ext/__init__.py @@ -7,7 +7,7 @@ """ -def _extend_path(path, name) -> list: +def _extend_path(path, name) -> list: # type: ignore[no-untyped-def, type-arg] import os.path from pkgutil import extend_path diff --git a/glass/fields.py b/glass/fields.py index 83a789cc..4780c003 100644 --- a/glass/fields.py +++ b/glass/fields.py @@ -30,10 +30,10 @@ from collections.abc import Generator, Iterable, Sequence from typing import Any, Callable, Optional, Union -import healpy as hp +import healpy as hp # type: ignore[import-untyped] import numpy as np import numpy.typing as npt -from gaussiancl import gaussiancl +from gaussiancl import gaussiancl # type: ignore[import-untyped] # types Size = Optional[Union[int, tuple[int, ...]]] @@ -115,12 +115,12 @@ def cls2cov( begin, end = end, end + j + 1 for i, cl in enumerate(cls[begin:end][: nc + 1]): if cl is None: - cov[:, i] = 0 + cov[:, i] = 0 # type: ignore[unreachable] else: if i == 0 and np.any(np.less(cl, 0)): msg = "negative values in cl" raise ValueError(msg) - n = len(cl) + n = len(cl) # type: ignore[arg-type] cov[:n, i] = cl cov[n:, i] = 0 cov /= 2 @@ -129,10 +129,10 @@ def cls2cov( def multalm(alm: Alms, bl: npt.ArrayLike, *, inplace: bool = False) -> Alms: """Multiply alm by bl.""" - n = len(bl) + n = len(bl) # type: ignore[arg-type] out = np.asanyarray(alm) if inplace else np.copy(alm) for m in range(n): - out[m * n - m * (m - 1) // 2 : (m + 1) * n - m * (m + 1) // 2] *= bl[m:] + out[m * n - m * (m - 1) // 2 : (m + 1) * n - m * (m + 1) // 2] *= bl[m:] # type: ignore[index] return out @@ -140,8 +140,8 @@ def transform_cls(cls: Cls, tfm: ClTransform, pars: tuple[Any, ...] = ()) -> Cls """Transform Cls to Gaussian Cls.""" gls = [] for cl in cls: - if cl is not None and len(cl) > 0: - monopole = 0.0 if cl[0] == 0 else None + if cl is not None and len(cl) > 0: # type: ignore[arg-type, redundant-expr] + monopole = 0.0 if cl[0] == 0 else None # type: ignore[index] gl, info, _, _ = gaussiancl(cl, tfm, pars, monopole=monopole) if info == 0: warnings.warn( @@ -185,12 +185,12 @@ def gaussian_gls( gls = [] for cl in cls: - if cl is not None and len(cl) > 0: + if cl is not None and len(cl) > 0: # type: ignore[arg-type, redundant-expr] if lmax is not None: - cl = cl[: lmax + 1] # noqa: PLW2901 + cl = cl[: lmax + 1] # type: ignore[index] # noqa: PLW2901 if nside is not None: - n = min(len(cl), len(pw)) - cl = cl[:n] * pw[:n] ** 2 # noqa: PLW2901 + n = min(len(cl), len(pw)) # type: ignore[arg-type] + cl = cl[:n] * pw[:n] ** 2 # type: ignore[index] # noqa: PLW2901 gls.append(cl) return gls @@ -251,7 +251,7 @@ def generate_gaussian( ncorr = ngrf - 1 # number of modes - n = max((len(gl) for gl in gls if gl is not None), default=0) + n = max((len(gl) for gl in gls if gl is not None), default=0) # type: ignore[arg-type, redundant-expr] if n == 0: msg = "all gls are empty" raise ValueError(msg) @@ -278,15 +278,15 @@ def generate_gaussian( # add the mean of the conditional distribution for i in range(ncorr): - alm += multalm(y[:, i], a[:, i]) + alm += multalm(y[:, i], a[:, i]) # type: ignore[call-overload, index, operator] # store the standard normal in y array at the indicated index if j is not None: y[:, j] = z # modes with m = 0 are real-valued and come first in array - alm[:n].real += alm[:n].imag - alm[:n].imag[:] = 0 + alm[:n].real += alm[:n].imag # type: ignore[index, misc, union-attr] + alm[:n].imag[:] = 0 # type: ignore[index, union-attr] # transform alm to maps # can be performed in place on the temporary alm array @@ -305,18 +305,18 @@ def generate_lognormal( for i, m in enumerate(generate_gaussian(gls, nside, ncorr=ncorr, rng=rng)): # compute the variance of the auto-correlation gl = gls[i * (i + 1) // 2] - ell = np.arange(len(gl)) - var = np.sum((2 * ell + 1) * gl) / (4 * np.pi) + ell = np.arange(len(gl)) # type: ignore[arg-type] + var = np.sum((2 * ell + 1) * gl) / (4 * np.pi) # type: ignore[operator] # fix mean of the Gaussian random field for lognormal transformation m -= var / 2 # noqa: PLW2901 # exponentiate values in place and subtract 1 in one operation - np.expm1(m, out=m) + np.expm1(m, out=m) # type: ignore[call-overload] # lognormal shift, unless unity if shift != 1: - m *= shift # noqa: PLW2901 + m *= shift # type: ignore[operator] # noqa: PLW2901 # yield the lognormal map yield m @@ -350,10 +350,10 @@ def getcl( i, j = j, i cl = cls[i * (i + 1) // 2 + i - j] if lmax is not None: - if len(cl) > lmax + 1: - cl = cl[: lmax + 1] + if len(cl) > lmax + 1: # type: ignore[arg-type] + cl = cl[: lmax + 1] # type: ignore[index] else: - cl = np.pad(cl, (0, lmax + 1 - len(cl))) + cl = np.pad(cl, (0, lmax + 1 - len(cl))) # type: ignore[arg-type] return cl @@ -401,7 +401,7 @@ def effective_cls( # find lmax if not given if lmax is None: - lmax = max(map(len, cls), default=0) - 1 + lmax = max(map(len, cls), default=0) - 1 # type: ignore[arg-type] # broadcast weights1 such that its shape ends in n weights1 = np.asanyarray(weights1) @@ -418,7 +418,7 @@ def effective_cls( if weights2 is weights1: pairs = combinations_with_replacement(np.ndindex(shape1[1:]), 2) else: - pairs = product(np.ndindex(shape1[1:]), np.ndindex(shape2[1:])) + pairs = product(np.ndindex(shape1[1:]), np.ndindex(shape2[1:])) # type: ignore[assignment] # create the output array: axes for all input axes plus lmax+1 out = np.empty(shape1[1:] + shape2[1:] + (lmax + 1,)) diff --git a/glass/galaxies.py b/glass/galaxies.py index 63678e30..f11f0ada 100644 --- a/glass/galaxies.py +++ b/glass/galaxies.py @@ -26,7 +26,7 @@ from glass.shells import RadialWindow -import healpix +import healpix # type: ignore[import-untyped] import numpy as np from glass.core.array import broadcast_leading_axes, cumtrapz @@ -107,7 +107,7 @@ def redshifts_from_nz( dims, count, z, nz = broadcast_leading_axes((count, 0), (z, 1), (nz, 1)) # list of results for all dimensions - redshifts = np.empty(count.sum()) + redshifts = np.empty(count.sum()) # type: ignore[attr-defined] # keep track of the number of sampled redshifts total = 0 @@ -115,16 +115,16 @@ def redshifts_from_nz( # go through extra dimensions; also works if dims is empty for k in np.ndindex(dims): # compute the CDF of each galaxy population - cdf = cumtrapz(nz[k], z[k], dtype=float) - cdf /= cdf[-1] + cdf = cumtrapz(nz[k], z[k], dtype=float) # type: ignore[arg-type, call-overload] + cdf /= cdf[-1] # type: ignore[index, operator] # sample redshifts and store result - redshifts[total : total + count[k]] = np.interp( - rng.uniform(0, 1, size=count[k]), - cdf, - z[k], + redshifts[total : total + count[k]] = np.interp( # type: ignore[call-overload] + rng.uniform(0, 1, size=count[k]), # type: ignore[call-overload] + cdf, # type: ignore[arg-type] + z[k], # type: ignore[call-overload] ) - total += count[k] + total += count[k] # type: ignore[call-overload] assert total == redshifts.size # noqa: S101 @@ -176,17 +176,17 @@ def galaxy_shear( # noqa: PLR0913 # get the lensing maps at galaxy position for i in range(0, size, 10000): s = slice(i, i + 10000) - ipix = healpix.ang2pix(nside, lon[s], lat[s], lonlat=True) - k[s] = kappa[ipix] - g.real[s] = gamma1[ipix] - g.imag[s] = gamma2[ipix] + ipix = healpix.ang2pix(nside, lon[s], lat[s], lonlat=True) # type: ignore[index] + k[s] = kappa[ipix] # type: ignore[index] + g.real[s] = gamma1[ipix] # type: ignore[index] + g.imag[s] = gamma2[ipix] # type: ignore[index] if reduced_shear: # compute reduced shear in place g /= 1 - k # compute lensed ellipticities - g = (eps + g) / (1 + g.conj() * eps) + g = (eps + g) / (1 + g.conj() * eps) # type: ignore[operator] else: # simple sum of shears g += eps @@ -255,26 +255,26 @@ def gaussian_phz( sigma = np.add(1, z) * sigma_0 dims = np.shape(sigma) - zphot = rng.normal(z, sigma) + zphot = rng.normal(z, sigma) # type: ignore[arg-type] if lower is None: lower = 0.0 if upper is None: upper = np.inf - if not np.all(lower < upper): + if not np.all(lower < upper): # type: ignore[operator] msg = "requires lower < upper" raise ValueError(msg) if not dims: - while zphot < lower or zphot > upper: - zphot = rng.normal(z, sigma) + while zphot < lower or zphot > upper: # type: ignore[operator] + zphot = rng.normal(z, sigma) # type: ignore[arg-type] else: z = np.broadcast_to(z, dims) - trunc = np.where((zphot < lower) | (zphot > upper))[0] + trunc = np.where((zphot < lower) | (zphot > upper))[0] # type: ignore[operator] while trunc.size: - znew = rng.normal(z[trunc], sigma[trunc]) - zphot[trunc] = znew - trunc = trunc[(znew < lower) | (znew > upper)] + znew = rng.normal(z[trunc], sigma[trunc]) # type: ignore[arg-type] + zphot[trunc] = znew # type: ignore[index] + trunc = trunc[(znew < lower) | (znew > upper)] # type: ignore[operator] return zphot diff --git a/glass/lensing.py b/glass/lensing.py index 6f8f3295..8a60907c 100644 --- a/glass/lensing.py +++ b/glass/lensing.py @@ -33,7 +33,7 @@ from typing import TYPE_CHECKING -import healpy as hp +import healpy as hp # type: ignore[import-untyped] import numpy as np if TYPE_CHECKING: @@ -41,7 +41,7 @@ import numpy.typing as npt - from cosmology import Cosmology + from cosmology import Cosmology # type: ignore[import-untyped] from glass.shells import RadialWindow @@ -182,7 +182,7 @@ def from_convergence( # noqa: PLR0913 # if potential is requested, compute map and add to output if potential: psi = hp.alm2map(alm, nside, lmax=lmax) - results += (psi,) + results += (psi,) # type: ignore[assignment] # if no spin-weighted maps are requested, stop here if not (deflection or shear): @@ -201,7 +201,7 @@ def from_convergence( # noqa: PLR0913 if deflection: alpha = hp.alm2map_spin([alm, blm], nside, 1, lmax) alpha = alpha[0] + 1j * alpha[1] - results += (alpha,) + results += (alpha,) # type: ignore[assignment] # if no shear is requested, stop here if not shear: @@ -219,7 +219,7 @@ def from_convergence( # noqa: PLR0913 # transform to shear maps gamma = hp.alm2map_spin([alm, blm], nside, 2, lmax) gamma = gamma[0] + 1j * gamma[1] - results += (gamma,) + results += (gamma,) # type: ignore[assignment] # all done return results @@ -266,7 +266,7 @@ def shear_from_convergence( hp.almxfl(alm, fl, inplace=True) # transform to shear maps - return hp.alm2map_spin([alm, blm], nside, 2, lmax) + return hp.alm2map_spin([alm, blm], nside, 2, lmax) # type: ignore[no-any-return] class MultiPlaneConvergence: @@ -295,9 +295,9 @@ def add_window(self, delta: npt.ArrayLike, w: RadialWindow) -> None: """ zsrc = w.zeff - lens_weight = np.trapz(w.wa, w.za) / np.interp(zsrc, w.za, w.wa) # type: ignore[attr-defined] + lens_weight = np.trapz(w.wa, w.za) / np.interp(zsrc, w.za, w.wa) # type: ignore[arg-type] # type: ignore[attr-defined] - self.add_plane(delta, zsrc, lens_weight) + self.add_plane(delta, zsrc, lens_weight) # type: ignore[arg-type] def add_plane(self, delta: npt.ArrayLike, zsrc: float, wlens: float = 1.0) -> None: """Add a mass plane at redshift ``zsrc`` to the convergence.""" @@ -416,7 +416,7 @@ def multi_plane_weights( weights = weights / np.sum(weights, axis=0) # combine weights and the matrix of lensing contributions mat = multi_plane_matrix(shells, cosmo) - return np.matmul(mat.T, weights) + return np.matmul(mat.T, weights) # type: ignore[no-any-return, union-attr] def deflect( diff --git a/glass/observations.py b/glass/observations.py index 7a8b14bc..9615b296 100644 --- a/glass/observations.py +++ b/glass/observations.py @@ -31,7 +31,7 @@ import math from typing import TYPE_CHECKING -import healpy as hp +import healpy as hp # type: ignore[import-untyped] import numpy as np from glass.core.array import cumtrapz @@ -82,7 +82,7 @@ def vmap_galactic_ecliptic( m[hp.query_strip(nside, *galactic)] = 0 m = hp.Rotator(coord="GC").rotate_map_pixel(m) m[hp.query_strip(nside, *ecliptic)] = 0 - return hp.Rotator(coord="CE").rotate_map_pixel(m) + return hp.Rotator(coord="CE").rotate_map_pixel(m) # type: ignore[no-any-return] def gaussian_nz( @@ -127,7 +127,7 @@ def gaussian_nz( if norm is not None: nz *= norm - return nz + return nz # type: ignore[no-any-return] def smail_nz( @@ -189,7 +189,7 @@ def smail_nz( if norm is not None: pz *= norm - return pz + return pz # type: ignore[no-any-return] def fixed_zbins( @@ -260,8 +260,8 @@ def equal_dens_zbins( # then normalise: the first z is at CDF = 0, the last z at CDF = 1 # interpolate to find the z values at CDF = i/nbins for i = 0, ..., nbins cuml_nz = cumtrapz(nz, z) - cuml_nz /= cuml_nz[[-1]] - zbinedges = np.interp(np.linspace(0, 1, nbins + 1), cuml_nz, z) + cuml_nz /= cuml_nz[[-1]] # type: ignore[index, operator] + zbinedges = np.interp(np.linspace(0, 1, nbins + 1), cuml_nz, z) # type: ignore[arg-type] return list(zip(zbinedges, zbinedges[1:])) @@ -323,10 +323,10 @@ def tomo_nz_gausserr( # compute the probabilities that redshifts z end up in each bin # then apply probability as weights to given nz # leading axis corresponds to the different bins - sz = 2**0.5 * sigma_0 * (1 + z) + sz = 2**0.5 * sigma_0 * (1 + z) # type: ignore[operator] binned_nz = erf((z - z_lower) / sz) binned_nz -= erf((z - z_upper) / sz) - binned_nz /= 1 + erf(z / sz) + binned_nz /= 1 + erf(z / sz) # type: ignore[operator] binned_nz *= nz - return binned_nz + return binned_nz # type: ignore[no-any-return] diff --git a/glass/points.py b/glass/points.py index 26ac31b5..e4acd925 100644 --- a/glass/points.py +++ b/glass/points.py @@ -33,7 +33,7 @@ import typing -import healpix +import healpix # type: ignore[import-untyped] import numpy as np import numpy.typing as npt @@ -79,12 +79,12 @@ def effective_bias( """ norm = np.trapz(w.wa, w.za) # type: ignore[attr-defined] - return trapz_product((z, bz), (w.za, w.wa)) / norm + return trapz_product((z, bz), (w.za, w.wa)) / norm # type: ignore[no-any-return] -def linear_bias(delta: npt.ArrayLike, b: float | npt.ArrayLike) -> npt.NDArray[float]: +def linear_bias(delta: npt.ArrayLike, b: float | npt.ArrayLike) -> npt.NDArray[float]: # type: ignore[type-var] r"""Linear bias model :math:`\\delta_g = b \\, \\delta`.""" - return b * delta + return b * delta # type: ignore[operator, return-value] def loglinear_bias( @@ -97,7 +97,7 @@ def loglinear_bias( return delta_g -def positions_from_delta( # noqa: PLR0912, PLR0913, PLR0915 +def positions_from_delta( # noqa: PLR0912, PLR0913, PLR0915 # type: ignore[no-untyped-def] ngal: float | npt.ArrayLike, delta: npt.ArrayLike, bias: float | npt.ArrayLike | None = None, @@ -191,7 +191,7 @@ def positions_from_delta( # noqa: PLR0912, PLR0913, PLR0915 # iterate the leading dimensions for k in np.ndindex(dims): # compute density contrast from bias model, or copy - n = np.copy(delta[k]) if bias is None else bias_model(delta[k], bias[k]) + n = np.copy(delta[k]) if bias is None else bias_model(delta[k], bias[k]) # type: ignore[call-overload] # remove monopole if asked to if remove_monopole: @@ -199,11 +199,11 @@ def positions_from_delta( # noqa: PLR0912, PLR0913, PLR0915 # turn into number count, modifying the array in place n += 1 - n *= ARCMIN2_SPHERE / n.size * ngal[k] + n *= ARCMIN2_SPHERE / n.size * ngal[k] # type: ignore[call-overload] # apply visibility if given if vis is not None: - n *= vis[k] + n *= vis[k] # type: ignore[call-overload] # clip number density at zero np.clip(n, 0, None, out=n) @@ -226,7 +226,7 @@ def positions_from_delta( # noqa: PLR0912, PLR0913, PLR0915 cmask = np.zeros(dims, dtype=int) cmask[k] = 1 else: - cmask = 1 + cmask = 1 # type: ignore[assignment] # sample the map in batches step = 1000 @@ -241,7 +241,7 @@ def positions_from_delta( # noqa: PLR0912, PLR0913, PLR0915 size += q[-1] else: # how many pixels from this group do we need? - stop += np.searchsorted(q, batch - size, side="right") + stop += np.searchsorted(q, batch - size, side="right") # type: ignore[call-overload, operator] # if the first pixel alone is too much, use it anyway if stop == start: stop += 1 @@ -261,7 +261,11 @@ def positions_from_delta( # noqa: PLR0912, PLR0913, PLR0915 def uniform_positions( ngal: float | npt.ArrayLike, *, rng: np.random.Generator | None = None -): +) -> typing.Iterator[ # type: ignore[type-arg] + npt.ArrayLike | list[npt.ArrayLike], + npt.ArrayLike | list[npt.ArrayLike], + int | list[int], +]: """ Generate positions uniformly over the sphere. @@ -307,12 +311,12 @@ def uniform_positions( count = np.zeros(dims, dtype=int) count[k] = ngal[k] else: - count = int(ngal[k]) + count = int(ngal[k]) # type: ignore[assignment] yield lon, lat, count -def position_weights(densities: npt.ArrayLike, bias: npt.ArrayLike | None = None): +def position_weights(densities: npt.ArrayLike, bias: npt.ArrayLike | None = None): # type: ignore[no-untyped-def] r""" Compute relative weights for angular clustering. @@ -345,6 +349,6 @@ def position_weights(densities: npt.ArrayLike, bias: npt.ArrayLike | None = None densities = densities / np.sum(densities, axis=0) # apply bias after normalisation if bias is not None: - densities = densities * bias + densities = densities * bias # type: ignore[operator] # densities now contains the relative contribution with bias applied return densities diff --git a/glass/shapes.py b/glass/shapes.py index 32664933..03490f2a 100644 --- a/glass/shapes.py +++ b/glass/shapes.py @@ -77,7 +77,7 @@ def triaxial_axis_ratio( # get size from inputs if not explicitly provided if size is None: - size = np.broadcast(zeta, xi).shape + size = np.broadcast(zeta, xi).shape # type: ignore[assignment] # draw random viewing angle (theta, phi) cos2_theta = rng.uniform(low=-1.0, high=1.0, size=size) @@ -98,7 +98,7 @@ def triaxial_axis_ratio( C = 1 + z2m1 * cos2_phi # noqa: N806 # eq. (12) - return np.sqrt( + return np.sqrt( # type: ignore[no-any-return] (A + C - np.sqrt((A - C) ** 2 + B2)) / (A + C + np.sqrt((A - C) ** 2 + B2)), ) @@ -158,15 +158,15 @@ def ellipticity_ryden04( # noqa: PLR0913 # draw gamma and epsilon from truncated normal -- eq.s (10)-(11) # first sample unbounded normal, then rejection sample truncation - eps = rng.normal(mu, sigma, size=size) + eps = rng.normal(mu, sigma, size=size) # type: ignore[arg-type] bad = eps > 0 while np.any(bad): - eps[bad] = rng.normal(mu, sigma, size=eps[bad].shape) + eps[bad] = rng.normal(mu, sigma, size=eps[bad].shape) # type: ignore[arg-type] bad = eps > 0 - gam = rng.normal(gamma, sigma_gamma, size=size) + gam = rng.normal(gamma, sigma_gamma, size=size) # type: ignore[arg-type] bad = (gam < 0) | (gam > 1) while np.any(bad): - gam[bad] = rng.normal(gamma, sigma_gamma, size=gam[bad].shape) + gam[bad] = rng.normal(gamma, sigma_gamma, size=gam[bad].shape) # type: ignore[arg-type] bad = (gam < 0) | (gam > 1) # compute triaxial axis ratios zeta = B/A, xi = C/A @@ -178,10 +178,10 @@ def ellipticity_ryden04( # noqa: PLR0913 # assemble ellipticity with random complex phase e = np.exp(1j * rng.uniform(0, 2 * np.pi, size=np.shape(q))) - e *= (1 - q) / (1 + q) + e *= (1 - q) / (1 + q) # type: ignore[operator] # return the ellipticity - return e + return e # type: ignore[no-any-return] def ellipticity_gaussian( diff --git a/glass/shells.py b/glass/shells.py index e0627076..2b3a1e41 100644 --- a/glass/shells.py +++ b/glass/shells.py @@ -54,7 +54,7 @@ from glass.core.array import ndinterp if TYPE_CHECKING: - from cosmology import Cosmology + from cosmology import Cosmology # type: ignore[import-untyped] # types ArrayLike1D = Union[Sequence[float], npt.ArrayLike] @@ -63,17 +63,17 @@ def distance_weight(z: npt.ArrayLike, cosmo: Cosmology) -> npt.ArrayLike: """Uniform weight in comoving distance.""" - return 1 / cosmo.ef(z) + return 1 / cosmo.ef(z) # type: ignore[no-any-return] def volume_weight(z: npt.ArrayLike, cosmo: Cosmology) -> npt.ArrayLike: """Uniform weight in comoving volume.""" - return cosmo.xm(z) ** 2 / cosmo.ef(z) + return cosmo.xm(z) ** 2 / cosmo.ef(z) # type: ignore[no-any-return] def density_weight(z: npt.ArrayLike, cosmo: Cosmology) -> npt.ArrayLike: """Uniform weight in matter density.""" - return cosmo.rho_m_z(z) * cosmo.xm(z) ** 2 / cosmo.ef(z) + return cosmo.rho_m_z(z) * cosmo.xm(z) ** 2 / cosmo.ef(z) # type: ignore[no-any-return] class RadialWindow(NamedTuple): @@ -164,23 +164,23 @@ def tophat_windows( :ref:`user-window-functions` """ - if len(zbins) < 2: + if len(zbins) < 2: # type: ignore[arg-type] msg = "zbins must have at least two entries" raise ValueError(msg) - if zbins[0] != 0: + if zbins[0] != 0: # type: ignore[index] warnings.warn( "first tophat window does not start at redshift zero", stacklevel=2 ) wht: WeightFunc - wht = weight if weight is not None else np.ones_like + wht = weight if weight is not None else np.ones_like # type: ignore[assignment] ws = [] - for zmin, zmax in zip(zbins, zbins[1:]): + for zmin, zmax in zip(zbins, zbins[1:]): # type: ignore[arg-type, index] n = max(round((zmax - zmin) / dz), 2) - z = np.linspace(zmin, zmax, n) + z = np.linspace(zmin, zmax, n) # type: ignore[arg-type] w = wht(z) - zeff = np.trapz(w * z, z) / np.trapz(w, z) # type: ignore[attr-defined] - ws.append(RadialWindow(z, w, zeff)) + zeff = np.trapz(w * z, z) / np.trapz(w, z) # type: ignore[operator] # type: ignore[attr-defined] + ws.append(RadialWindow(z, w, zeff)) # type: ignore[arg-type] return ws @@ -223,25 +223,25 @@ def linear_windows( :ref:`user-window-functions` """ - if len(zgrid) < 3: + if len(zgrid) < 3: # type: ignore[arg-type] msg = "nodes must have at least 3 entries" raise ValueError(msg) - if zgrid[0] != 0: + if zgrid[0] != 0: # type: ignore[index] warnings.warn("first triangular window does not start at z=0", stacklevel=2) ws = [] - for zmin, zmid, zmax in zip(zgrid, zgrid[1:], zgrid[2:]): + for zmin, zmid, zmax in zip(zgrid, zgrid[1:], zgrid[2:]): # type: ignore[arg-type, index] n = max(round((zmid - zmin) / dz), 2) - 1 m = max(round((zmax - zmid) / dz), 2) z = np.concatenate( - [np.linspace(zmin, zmid, n, endpoint=False), np.linspace(zmid, zmax, m)], + [np.linspace(zmin, zmid, n, endpoint=False), np.linspace(zmid, zmax, m)], # type: ignore[arg-type] ) w = np.concatenate( [np.linspace(0.0, 1.0, n, endpoint=False), np.linspace(1.0, 0.0, m)], ) if weight is not None: w *= weight(z) - ws.append(RadialWindow(z, w, zmid)) + ws.append(RadialWindow(z, w, zmid)) # type: ignore[arg-type] return ws @@ -285,25 +285,25 @@ def cubic_windows( :ref:`user-window-functions` """ - if len(zgrid) < 3: + if len(zgrid) < 3: # type: ignore[arg-type] msg = "nodes must have at least 3 entries" raise ValueError(msg) - if zgrid[0] != 0: + if zgrid[0] != 0: # type: ignore[index] warnings.warn("first cubic spline window does not start at z=0", stacklevel=2) ws = [] - for zmin, zmid, zmax in zip(zgrid, zgrid[1:], zgrid[2:]): + for zmin, zmid, zmax in zip(zgrid, zgrid[1:], zgrid[2:]): # type: ignore[arg-type, index] n = max(round((zmid - zmin) / dz), 2) - 1 m = max(round((zmax - zmid) / dz), 2) z = np.concatenate( - [np.linspace(zmin, zmid, n, endpoint=False), np.linspace(zmid, zmax, m)], + [np.linspace(zmin, zmid, n, endpoint=False), np.linspace(zmid, zmax, m)], # type: ignore[arg-type] ) u = np.linspace(0.0, 1.0, n, endpoint=False) v = np.linspace(1.0, 0.0, m) w = np.concatenate([u**2 * (3 - 2 * u), v**2 * (3 - 2 * v)]) if weight is not None: w *= weight(z) - ws.append(RadialWindow(z, w, zmid)) + ws.append(RadialWindow(z, w, zmid)) # type: ignore[arg-type] return ws @@ -344,7 +344,7 @@ def restrict( """ z_ = np.compress(np.greater(z, w.za[0]) & np.less(z, w.za[-1]), z) zr = np.union1d(w.za, z_) - fr = ndinterp(zr, z, f, left=0.0, right=0.0) * ndinterp(zr, w.za, w.wa) + fr = ndinterp(zr, z, f, left=0.0, right=0.0) * ndinterp(zr, w.za, w.wa) # type: ignore[operator] return zr, fr @@ -455,7 +455,7 @@ def partition( except KeyError: msg = f"invalid method: {method}" raise ValueError(msg) from None - return partition_method(z, fz, shells) + return partition_method(z, fz, shells) # type: ignore[no-any-return] def partition_lstsq( @@ -481,7 +481,7 @@ def partition_lstsq( dz = np.gradient(zp) # create the window function matrix - a = [np.interp(zp, za, wa, left=0.0, right=0.0) for za, wa, _ in shells] + a = [np.interp(zp, za, wa, left=0.0, right=0.0) for za, wa, _ in shells] # type: ignore[arg-type] a /= np.trapz(a, zp, axis=-1)[..., None] # type: ignore[attr-defined] a = a * dz @@ -491,14 +491,14 @@ def partition_lstsq( # append a constraint for the integral mult = 1 / sumtol - a = np.concatenate([a, mult * np.ones((len(shells), 1))], axis=-1) - b = np.concatenate([b, mult * np.reshape(np.trapz(fz, z), (*dims, 1))], axis=-1) + a = np.concatenate([a, mult * np.ones((len(shells), 1))], axis=-1) # type: ignore[assignment] + b = np.concatenate([b, mult * np.reshape(np.trapz(fz, z), (*dims, 1))], axis=-1) # type: ignore[attr-defined] # now a is a matrix of shape (len(shells), len(zp) + 1) # and b is a matrix of shape (*dims, len(zp) + 1) # need to find weights x such that b == x @ a over all axes of b # do the least-squares fit over partially flattened b, then reshape - x = np.linalg.lstsq(a.T, b.reshape(-1, zp.size + 1).T, rcond=None)[0] + x = np.linalg.lstsq(a.T, b.reshape(-1, zp.size + 1).T, rcond=None)[0] # type: ignore[attr-defined, union-attr] x = x.T.reshape(*dims, len(shells)) # roll the last axis of size len(shells) to the front return np.moveaxis(x, -1, 0) @@ -535,7 +535,7 @@ def partition_nnls( dz = np.gradient(zp) # create the window function matrix - a = [np.interp(zp, za, wa, left=0.0, right=0.0) for za, wa, _ in shells] + a = [np.interp(zp, za, wa, left=0.0, right=0.0) for za, wa, _ in shells] # type: ignore[arg-type] a /= np.trapz(a, zp, axis=-1)[..., None] # type: ignore[attr-defined] a = a * dz @@ -545,15 +545,15 @@ def partition_nnls( # append a constraint for the integral mult = 1 / sumtol - a = np.concatenate([a, mult * np.ones((len(shells), 1))], axis=-1) - b = np.concatenate([b, mult * np.reshape(np.trapz(fz, z), (*dims, 1))], axis=-1) + a = np.concatenate([a, mult * np.ones((len(shells), 1))], axis=-1) # type: ignore[assignment] + b = np.concatenate([b, mult * np.reshape(np.trapz(fz, z), (*dims, 1))], axis=-1) # type: ignore[attr-defined] # now a is a matrix of shape (len(shells), len(zp) + 1) # and b is a matrix of shape (*dims, len(zp) + 1) # for each dim, find non-negative weights x such that b == a.T @ x # reduce the dimensionality of the problem using a thin QR decomposition - q, r = np.linalg.qr(a.T) + q, r = np.linalg.qr(a.T) # type: ignore[attr-defined] y = np.einsum("ji,...j", q, b) # for each dim, find non-negative weights x such that y == r @ x @@ -580,7 +580,7 @@ def partition_restrict( def redshift_grid( zmin: float, zmax: float, *, dz: float | None = None, num: int | None = None -) -> npt.NDArray[float]: +) -> npt.NDArray[np.float64]: """Redshift grid with uniform spacing in redshift.""" if dz is not None and num is None: z = np.arange(zmin, np.nextafter(zmax + dz, zmax), dz) @@ -599,7 +599,7 @@ def distance_grid( *, dx: float | None = None, num: int | None = None, -) -> npt.NDArray[float]: +) -> npt.NDArray[np.float64]: """Redshift grid with uniform spacing in comoving distance.""" xmin, xmax = cosmo.dc(zmin), cosmo.dc(zmax) if dx is not None and num is None: @@ -609,7 +609,7 @@ def distance_grid( else: msg = 'exactly one of "dx" or "num" must be given' raise ValueError(msg) - return cosmo.dc_inv(x) + return cosmo.dc_inv(x) # type: ignore[no-any-return] def combine( @@ -651,11 +651,11 @@ def combine( return sum( np.expand_dims(weight, -1) * np.interp( - z, + z, # type: ignore[arg-type] shell.za, shell.wa / np.trapz(shell.wa, shell.za), # type: ignore[attr-defined] left=0.0, right=0.0, ) - for shell, weight in zip(shells, weights) + for shell, weight in zip(shells, weights) # type: ignore[arg-type] ) diff --git a/glass/user.py b/glass/user.py index d4fe463d..beabdab5 100644 --- a/glass/user.py +++ b/glass/user.py @@ -34,7 +34,7 @@ def save_cls(filename: str, cls: list[npt.ArrayLike | None]) -> None: ``.npz`` suffix, or it will be given one. """ - split = np.cumsum([len(cl) if cl is not None else 0 for cl in cls[:-1]]) + split = np.cumsum([len(cl) if cl is not None else 0 for cl in cls[:-1]]) # type: ignore[arg-type] values = np.concatenate([cl for cl in cls if cl is not None]) np.savez(filename, values=values, split=split) @@ -49,7 +49,7 @@ def load_cls(filename: str) -> list[npt.ArrayLike]: with np.load(filename) as npz: values = npz["values"] split = npz["split"] - return np.split(values, split) + return np.split(values, split) # type: ignore[return-value] class _FitsWriter: @@ -59,7 +59,7 @@ class _FitsWriter: Initialised with the fits object and extension name. """ - def __init__(self, fits, ext: str | None = None) -> None: + def __init__(self, fits, ext: str | None = None) -> None: # type: ignore[no-untyped-def] """Create a new, uninitialised writer.""" self.fits = fits self.ext = ext @@ -91,7 +91,7 @@ def write( # if keyword arguments are given, treat them as names and columns if columns: names, values = list(columns.keys()), list(columns.values()) - self._append(values, names) + self._append(values, names) # type: ignore[arg-type] @contextmanager @@ -114,7 +114,7 @@ def write_catalog( Requires the ``fitsio`` package. """ - import fitsio + import fitsio # type: ignore[import-not-found] with fitsio.FITS(filename, "rw", clobber=True) as fits: fits.write(None) diff --git a/noxfile.py b/noxfile.py index 26aeb950..99db21e0 100644 --- a/noxfile.py +++ b/noxfile.py @@ -4,7 +4,7 @@ from pathlib import Path -import nox +import nox # type: ignore[import-not-found] # Options to modify nox behaviour nox.options.reuse_existing_virtualenvs = True @@ -13,14 +13,14 @@ ALL_PYTHON = ["3.9", "3.10", "3.11", "3.12"] -@nox.session +@nox.session # type: ignore[misc] def lint(session: nox.Session) -> None: """Run the linter.""" session.install("pre-commit") session.run("pre-commit", "run", "--all-files", *session.posargs) -@nox.session(python=ALL_PYTHON) +@nox.session(python=ALL_PYTHON) # type: ignore[misc] def tests(session: nox.Session) -> None: """Run the unit tests.""" session.install("-c", ".github/test-constraints.txt", "-e", ".[test]") @@ -30,14 +30,14 @@ def tests(session: nox.Session) -> None: ) -@nox.session(python=ALL_PYTHON) +@nox.session(python=ALL_PYTHON) # type: ignore[misc] def coverage(session: nox.Session) -> None: """Run tests and compute coverage.""" session.posargs.append("--cov") tests(session) -@nox.session(python=ALL_PYTHON) +@nox.session(python=ALL_PYTHON) # type: ignore[misc] def doctests(session: nox.Session) -> None: """Run the doctests.""" session.posargs.append("--doctest-plus") @@ -45,7 +45,7 @@ def doctests(session: nox.Session) -> None: tests(session) -@nox.session +@nox.session # type: ignore[misc] def examples(session: nox.Session) -> None: """Run the example notebooks.""" session.install("-e", ".[examples]") @@ -54,7 +54,7 @@ def examples(session: nox.Session) -> None: ) -@nox.session +@nox.session # type: ignore[misc] def docs(session: nox.Session) -> None: """Build the docs. Pass "serve" to serve.""" session.install("-e", ".[docs]") @@ -71,7 +71,7 @@ def docs(session: nox.Session) -> None: print("Unsupported argument to docs") -@nox.session +@nox.session # type: ignore[misc] def build(session: nox.Session) -> None: """Build an SDist and wheel.""" session.install("build") diff --git a/tests/conftest.py b/tests/conftest.py index b2b6a9fd..df5ee22a 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,8 +1,8 @@ import numpy as np -import pytest +import pytest # type: ignore[import-not-found] -@pytest.fixture(scope="session") +@pytest.fixture(scope="session") # type: ignore[misc] def rng() -> np.random.Generator: import numpy as np diff --git a/tests/core/test_algorithm.py b/tests/core/test_algorithm.py index 7049c584..95b977bd 100644 --- a/tests/core/test_algorithm.py +++ b/tests/core/test_algorithm.py @@ -1,7 +1,7 @@ import importlib.util import numpy as np -import pytest +import pytest # type: ignore[import-not-found] from glass.core.algorithm import nnls as nnls_glass @@ -9,9 +9,9 @@ HAVE_SCIPY = importlib.util.find_spec("scipy") is not None -@pytest.mark.skipif(not HAVE_SCIPY, reason="test requires SciPy") -def test_nnls(rng) -> None: - from scipy.optimize import nnls as nnls_scipy +@pytest.mark.skipif(not HAVE_SCIPY, reason="test requires SciPy") # type: ignore[misc] +def test_nnls(rng) -> None: # type: ignore[no-untyped-def] + from scipy.optimize import nnls as nnls_scipy # type: ignore[import-untyped] # cross-check output with scipy's nnls @@ -21,7 +21,7 @@ def test_nnls(rng) -> None: x_glass = nnls_glass(a, b) x_scipy, _ = nnls_scipy(a, b) - np.testing.assert_allclose(x_glass, x_scipy) + np.testing.assert_allclose(x_glass, x_scipy) # type: ignore[arg-type] # check matrix and vector's shape diff --git a/tests/core/test_array.py b/tests/core/test_array.py index 461ac0c6..dc8a92dd 100644 --- a/tests/core/test_array.py +++ b/tests/core/test_array.py @@ -1,7 +1,7 @@ import importlib.util import numpy as np -import pytest +import pytest # type: ignore[import-not-found] from glass.core.array import ( broadcast_first, @@ -22,8 +22,8 @@ def test_broadcast_first() -> None: # arrays with shape ((3, 4, 2)) and ((1, 2)) are passed # to np.broadcast_arrays; hence it works a_a, b_a = broadcast_first(a, b) - assert a_a.shape == (2, 3, 4) - assert b_a.shape == (2, 3, 4) + assert a_a.shape == (2, 3, 4) # type: ignore[union-attr] + assert b_a.shape == (2, 3, 4) # type: ignore[union-attr] # plain np.broadcast_arrays will not work with pytest.raises(ValueError, match="shape mismatch"): @@ -49,10 +49,10 @@ def test_broadcast_leading_axes() -> None: b = np.zeros((4, 10)) c = np.zeros((3, 1, 5, 6)) - dims, a, b, c = broadcast_leading_axes((a, 0), (b, 1), (c, 2)) + dims, a, b, c = broadcast_leading_axes((a, 0), (b, 1), (c, 2)) # type: ignore[assignment] assert dims == (3, 4) - assert a.shape == (3, 4) + assert a.shape == (3, 4) # type: ignore[attr-defined] assert b.shape == (3, 4, 10) assert c.shape == (3, 4, 5, 6) @@ -66,64 +66,64 @@ def test_ndinterp() -> None: x = 0.5 y = ndinterp(x, xp, yp) assert np.shape(y) == () - np.testing.assert_allclose(y, 1.15, atol=1e-15) + np.testing.assert_allclose(y, 1.15, atol=1e-15) # type: ignore[arg-type] - x = [0.5, 1.5, 2.5] + x = [0.5, 1.5, 2.5] # type: ignore[assignment] y = ndinterp(x, xp, yp) assert np.shape(y) == (3,) - np.testing.assert_allclose(y, [1.15, 1.25, 1.35], atol=1e-15) + np.testing.assert_allclose(y, [1.15, 1.25, 1.35], atol=1e-15) # type: ignore[arg-type] - x = [[0.5, 1.5], [2.5, 3.5]] + x = [[0.5, 1.5], [2.5, 3.5]] # type: ignore[assignment] y = ndinterp(x, xp, yp) assert np.shape(y) == (2, 2) - np.testing.assert_allclose(y, [[1.15, 1.25], [1.35, 1.45]], atol=1e-15) + np.testing.assert_allclose(y, [[1.15, 1.25], [1.35, 1.45]], atol=1e-15) # type: ignore[arg-type] # test nd interpolation in final axis - yp = [[1.1, 1.2, 1.3, 1.4, 1.5], [2.1, 2.2, 2.3, 2.4, 2.5]] + yp = [[1.1, 1.2, 1.3, 1.4, 1.5], [2.1, 2.2, 2.3, 2.4, 2.5]] # type: ignore[list-item] x = 0.5 y = ndinterp(x, xp, yp) assert np.shape(y) == (2,) - np.testing.assert_allclose(y, [1.15, 2.15], atol=1e-15) + np.testing.assert_allclose(y, [1.15, 2.15], atol=1e-15) # type: ignore[arg-type] - x = [0.5, 1.5, 2.5] + x = [0.5, 1.5, 2.5] # type: ignore[assignment] y = ndinterp(x, xp, yp) assert np.shape(y) == (2, 3) - np.testing.assert_allclose(y, [[1.15, 1.25, 1.35], [2.15, 2.25, 2.35]], atol=1e-15) + np.testing.assert_allclose(y, [[1.15, 1.25, 1.35], [2.15, 2.25, 2.35]], atol=1e-15) # type: ignore[arg-type] - x = [[0.5, 1.5], [2.5, 3.5]] + x = [[0.5, 1.5], [2.5, 3.5]] # type: ignore[assignment] y = ndinterp(x, xp, yp) assert np.shape(y) == (2, 2, 2) np.testing.assert_allclose( - y, + y, # type: ignore[arg-type] [[[1.15, 1.25], [1.35, 1.45]], [[2.15, 2.25], [2.35, 2.45]]], atol=1e-15, ) # test nd interpolation in middle axis - yp = [[[1.1], [1.2], [1.3], [1.4], [1.5]], [[2.1], [2.2], [2.3], [2.4], [2.5]]] + yp = [[[1.1], [1.2], [1.3], [1.4], [1.5]], [[2.1], [2.2], [2.3], [2.4], [2.5]]] # type: ignore[list-item] x = 0.5 y = ndinterp(x, xp, yp, axis=1) assert np.shape(y) == (2, 1) - np.testing.assert_allclose(y, [[1.15], [2.15]], atol=1e-15) + np.testing.assert_allclose(y, [[1.15], [2.15]], atol=1e-15) # type: ignore[arg-type] - x = [0.5, 1.5, 2.5] + x = [0.5, 1.5, 2.5] # type: ignore[assignment] y = ndinterp(x, xp, yp, axis=1) assert np.shape(y) == (2, 3, 1) np.testing.assert_allclose( - y, + y, # type: ignore[arg-type] [[[1.15], [1.25], [1.35]], [[2.15], [2.25], [2.35]]], atol=1e-15, ) - x = [[0.5, 1.5, 2.5, 3.5], [3.5, 2.5, 1.5, 0.5], [0.5, 3.5, 1.5, 2.5]] + x = [[0.5, 1.5, 2.5, 3.5], [3.5, 2.5, 1.5, 0.5], [0.5, 3.5, 1.5, 2.5]] # type: ignore[assignment] y = ndinterp(x, xp, yp, axis=1) assert np.shape(y) == (2, 3, 4, 1) np.testing.assert_allclose( - y, + y, # type: ignore[arg-type] [ [ [[1.15], [1.25], [1.35], [1.45]], @@ -152,9 +152,9 @@ def test_trapz_product() -> None: assert np.allclose(s, 1.0) -@pytest.mark.skipif(not HAVE_SCIPY, reason="test requires SciPy") +@pytest.mark.skipif(not HAVE_SCIPY, reason="test requires SciPy") # type: ignore[misc] def test_cumtrapz() -> None: - from scipy.integrate import cumulative_trapezoid + from scipy.integrate import cumulative_trapezoid # type: ignore[import-untyped] # 1D f and x @@ -164,19 +164,19 @@ def test_cumtrapz() -> None: # default dtype (int - not supported by scipy) glass_ct = cumtrapz(f, x) - np.testing.assert_allclose(glass_ct, np.array([0, 1, 4, 7])) + np.testing.assert_allclose(glass_ct, np.array([0, 1, 4, 7])) # type: ignore[arg-type] # explicit dtype (float) - glass_ct = cumtrapz(f, x, dtype=float) + glass_ct = cumtrapz(f, x, dtype=float) # type: ignore[arg-type] scipy_ct = cumulative_trapezoid(f, x, initial=0) - np.testing.assert_allclose(glass_ct, scipy_ct) + np.testing.assert_allclose(glass_ct, scipy_ct) # type: ignore[arg-type] # explicit return array - result = cumtrapz(f, x, dtype=float, out=np.zeros((4,))) + result = cumtrapz(f, x, dtype=float, out=np.zeros((4,))) # type: ignore[arg-type] scipy_ct = cumulative_trapezoid(f, x, initial=0) - np.testing.assert_allclose(result, scipy_ct) + np.testing.assert_allclose(result, scipy_ct) # type: ignore[arg-type] # 2D f and 1D x @@ -186,16 +186,16 @@ def test_cumtrapz() -> None: # default dtype (int - not supported by scipy) glass_ct = cumtrapz(f, x) - np.testing.assert_allclose(glass_ct, np.array([[0, 2, 12, 31], [0, 2, 8, 17]])) + np.testing.assert_allclose(glass_ct, np.array([[0, 2, 12, 31], [0, 2, 8, 17]])) # type: ignore[arg-type] # explicit dtype (float) - glass_ct = cumtrapz(f, x, dtype=float) + glass_ct = cumtrapz(f, x, dtype=float) # type: ignore[arg-type] scipy_ct = cumulative_trapezoid(f, x, initial=0) - np.testing.assert_allclose(glass_ct, scipy_ct) + np.testing.assert_allclose(glass_ct, scipy_ct) # type: ignore[arg-type] # explicit return array - glass_ct = cumtrapz(f, x, dtype=float, out=np.zeros((2, 4))) + glass_ct = cumtrapz(f, x, dtype=float, out=np.zeros((2, 4))) # type: ignore[arg-type] scipy_ct = cumulative_trapezoid(f, x, initial=0) - np.testing.assert_allclose(glass_ct, scipy_ct) + np.testing.assert_allclose(glass_ct, scipy_ct) # type: ignore[arg-type] diff --git a/tests/test_fields.py b/tests/test_fields.py index 05a73d11..c246a99d 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -7,4 +7,4 @@ def test_getcl() -> None: # make sure indices are retrieved correctly for i in range(10): for j in range(10): - assert getcl(cls, i, j) == {i, j} + assert getcl(cls, i, j) == {i, j} # type: ignore[arg-type, comparison-overlap] diff --git a/tests/test_fits.py b/tests/test_fits.py index 97d85fe8..0ce729c2 100644 --- a/tests/test_fits.py +++ b/tests/test_fits.py @@ -1,7 +1,9 @@ import importlib.util +import os +import pathlib import numpy as np -import pytest +import pytest # type: ignore[import-not-found] from glass import user @@ -9,7 +11,7 @@ HAVE_FITSIO = importlib.util.find_spec("fitsio") is not None -def _test_append(fits, data, names) -> None: +def _test_append(fits, data, names) -> None: # type: ignore[no-untyped-def] """Write routine for FITS test cases.""" cat_name = "CATALOG" if cat_name not in fits: @@ -25,16 +27,16 @@ def _test_append(fits, data, names) -> None: filename = "MyFile.Fits" -@pytest.mark.skipif(not HAVE_FITSIO, reason="test requires fitsio") -def test_basic_write(tmp_path) -> None: - import fitsio +@pytest.mark.skipif(not HAVE_FITSIO, reason="test requires fitsio") # type: ignore[misc] +def test_basic_write(tmp_path: os.PathLike) -> None: # type: ignore[type-arg] + import fitsio # type: ignore[import-not-found] filename_gfits = "gfits.fits" # what GLASS creates filename_tfits = "tfits.fits" # file created on the fly to test against with ( - user.write_catalog(tmp_path / filename_gfits, ext="CATALOG") as out, - fitsio.FITS(tmp_path / filename_tfits, "rw", clobber=True) as my_fits, + user.write_catalog(tmp_path / filename_gfits, ext="CATALOG") as out, # type: ignore[operator] + fitsio.FITS(tmp_path / filename_tfits, "rw", clobber=True) as my_fits, # type: ignore[operator] ): for i in range(my_max): array = np.arange(i, i + 1, delta) # array of size 1/delta @@ -45,8 +47,8 @@ def test_basic_write(tmp_path) -> None: _test_append(my_fits, arrays, names) with ( - fitsio.FITS(tmp_path / filename_gfits) as g_fits, - fitsio.FITS(tmp_path / filename_tfits) as t_fits, + fitsio.FITS(tmp_path / filename_gfits) as g_fits, # type: ignore[operator] + fitsio.FITS(tmp_path / filename_tfits) as t_fits, # type: ignore[operator] ): glass_data = g_fits[1].read() test_data = t_fits[1].read() @@ -54,10 +56,10 @@ def test_basic_write(tmp_path) -> None: assert glass_data["RB"].size == test_data["RA"].size -@pytest.mark.skipif(not HAVE_FITSIO, reason="test requires fitsio") -def test_write_exception(tmp_path) -> None: +@pytest.mark.skipif(not HAVE_FITSIO, reason="test requires fitsio") # type: ignore[misc] +def test_write_exception(tmp_path: pathlib.Path) -> None: try: - with user.write_catalog(tmp_path / filename, ext="CATALOG") as out: + with user.write_catalog(tmp_path / filename, ext="CATALOG") as out: # type: ignore[arg-type] for i in range(my_max): if i == except_int: msg = "Unhandled exception" diff --git a/tests/test_galaxies.py b/tests/test_galaxies.py index 9508ed3f..a492df46 100644 --- a/tests/test_galaxies.py +++ b/tests/test_galaxies.py @@ -1,10 +1,10 @@ import numpy as np -import pytest +import pytest # type: ignore[import-not-found] from glass.galaxies import gaussian_phz, redshifts, redshifts_from_nz -def test_redshifts(mocker) -> None: +def test_redshifts(mocker) -> None: # type: ignore[no-untyped-def] # create a mock radial window function w = mocker.Mock() w.za = np.linspace(0.0, 1.0, 20) @@ -12,29 +12,29 @@ def test_redshifts(mocker) -> None: # sample redshifts (scalar) z = redshifts(13, w) - assert z.shape == (13,) - assert z.min() >= 0.0 - assert z.max() <= 1.0 + assert z.shape == (13,) # type: ignore[union-attr] + assert z.min() >= 0.0 # type: ignore[union-attr] + assert z.max() <= 1.0 # type: ignore[union-attr] # sample redshifts (array) z = redshifts([[1, 2], [3, 4]], w) - assert z.shape == (10,) + assert z.shape == (10,) # type: ignore[union-attr] def test_redshifts_from_nz() -> None: # test sampling redshifts = redshifts_from_nz(10, [0, 1, 2, 3, 4], [1, 0, 0, 0, 0]) - assert np.all((0 <= redshifts) & (redshifts <= 1)) # noqa: SIM300 + assert np.all((0 <= redshifts) & (redshifts <= 1)) # type: ignore[operator] # noqa: SIM300 redshifts = redshifts_from_nz(10, [0, 1, 2, 3, 4], [0, 0, 1, 0, 0]) - assert np.all((1 <= redshifts) & (redshifts <= 3)) # noqa: SIM300 + assert np.all((1 <= redshifts) & (redshifts <= 3)) # type: ignore[operator] # noqa: SIM300 redshifts = redshifts_from_nz(10, [0, 1, 2, 3, 4], [0, 0, 0, 0, 1]) - assert np.all((3 <= redshifts) & (redshifts <= 4)) # noqa: SIM300 + assert np.all((3 <= redshifts) & (redshifts <= 4)) # type: ignore[operator] # noqa: SIM300 redshifts = redshifts_from_nz(10, [0, 1, 2, 3, 4], [0, 0, 1, 1, 1]) - assert not np.any(redshifts <= 1) + assert not np.any(redshifts <= 1) # type: ignore[operator] # test interface @@ -46,12 +46,12 @@ def test_redshifts_from_nz() -> None: redshifts = redshifts_from_nz(count, z, nz) - assert redshifts.shape == (count,) - assert np.all((0 <= redshifts) & (redshifts <= 1)) # noqa: SIM300 + assert redshifts.shape == (count,) # type: ignore[union-attr] + assert np.all((0 <= redshifts) & (redshifts <= 1)) # type: ignore[operator] # noqa: SIM300 # case: extra dimensions from count - count = [10, 20, 30] + count = [10, 20, 30] # type: ignore[assignment] z = np.linspace(0, 1, 100) nz = z * (1 - z) @@ -63,27 +63,27 @@ def test_redshifts_from_nz() -> None: count = 10 z = np.linspace(0, 1, 100) - nz = [z * (1 - z), (z - 0.5) ** 2] + nz = [z * (1 - z), (z - 0.5) ** 2] # type: ignore[assignment] redshifts = redshifts_from_nz(count, z, nz) - assert redshifts.shape == (20,) + assert redshifts.shape == (20,) # type: ignore[union-attr] # case: extra dimensions from count and nz - count = [[10], [20], [30]] + count = [[10], [20], [30]] # type: ignore[assignment] z = np.linspace(0, 1, 100) - nz = [z * (1 - z), (z - 0.5) ** 2] + nz = [z * (1 - z), (z - 0.5) ** 2] # type: ignore[assignment] redshifts = redshifts_from_nz(count, z, nz) - assert redshifts.shape == (120,) + assert redshifts.shape == (120,) # type: ignore[union-attr] # case: incompatible input shapes - count = [10, 20, 30] + count = [10, 20, 30] # type: ignore[assignment] z = np.linspace(0, 1, 100) - nz = [z * (1 - z), (z - 0.5) ** 2] + nz = [z * (1 - z), (z - 0.5) ** 2] # type: ignore[assignment] with pytest.raises(ValueError): redshifts_from_nz(count, z, nz) @@ -103,30 +103,30 @@ def test_gaussian_phz() -> None: # case: truncated normal - z = 0.0 - sigma_0 = np.ones(100) + z = 0.0 # type: ignore[assignment] + sigma_0 = np.ones(100) # type: ignore[assignment] phz = gaussian_phz(z, sigma_0) - assert phz.shape == (100,) - assert np.all(phz >= 0) + assert phz.shape == (100,) # type: ignore[union-attr] + assert np.all(phz >= 0) # type: ignore[operator] # case: upper and lower bound - z = 1.0 - sigma_0 = np.ones(100) + z = 1.0 # type: ignore[assignment] + sigma_0 = np.ones(100) # type: ignore[assignment] phz = gaussian_phz(z, sigma_0, lower=0.5, upper=1.5) - assert phz.shape == (100,) - assert np.all(phz >= 0.5) - assert np.all(phz <= 1.5) + assert phz.shape == (100,) # type: ignore[union-attr] + assert np.all(phz >= 0.5) # type: ignore[operator] + assert np.all(phz <= 1.5) # type: ignore[operator] # test interface # case: scalar redshift, scalar sigma_0 - z = 1.0 + z = 1.0 # type: ignore[assignment] sigma_0 = 0.0 phz = gaussian_phz(z, sigma_0) @@ -141,25 +141,25 @@ def test_gaussian_phz() -> None: phz = gaussian_phz(z, sigma_0) - assert phz.shape == (10,) + assert phz.shape == (10,) # type: ignore[union-attr] np.testing.assert_array_equal(z, phz) # case: scalar redshift, array sigma_0 - z = 1.0 - sigma_0 = np.zeros(10) + z = 1.0 # type: ignore[assignment] + sigma_0 = np.zeros(10) # type: ignore[assignment] phz = gaussian_phz(z, sigma_0) - assert phz.shape == (10,) + assert phz.shape == (10,) # type: ignore[union-attr] np.testing.assert_array_equal(z, phz) # case: array redshift, array sigma_0 z = np.linspace(0, 1, 10) - sigma_0 = np.zeros((11, 1)) + sigma_0 = np.zeros((11, 1)) # type: ignore[assignment] phz = gaussian_phz(z, sigma_0) - assert phz.shape == (11, 10) + assert phz.shape == (11, 10) # type: ignore[union-attr] np.testing.assert_array_equal(np.broadcast_to(z, (11, 10)), phz) diff --git a/tests/test_lensing.py b/tests/test_lensing.py index 2c089535..e196bb2e 100644 --- a/tests/test_lensing.py +++ b/tests/test_lensing.py @@ -1,6 +1,6 @@ -import healpix +import healpix # type: ignore[import-untyped] import numpy as np -import pytest +import pytest # type: ignore[import-not-found] from glass.lensing import ( MultiPlaneConvergence, @@ -11,7 +11,7 @@ from glass.shells import RadialWindow -@pytest.fixture +@pytest.fixture # type: ignore[misc] def shells() -> list[RadialWindow]: return [ RadialWindow([0.0, 1.0, 2.0], [0.0, 1.0, 0.0], 1.0), @@ -23,16 +23,16 @@ def shells() -> list[RadialWindow]: @pytest.fixture -def cosmo(): +def cosmo(): # type: ignore[no-untyped-def] class MockCosmology: @property - def omega_m(self): + def omega_m(self): # type: ignore[no-untyped-def] return 0.3 - def ef(self, z): + def ef(self, z): # type: ignore[no-untyped-def] return (self.omega_m * (1 + z) ** 3 + 1 - self.omega_m) ** 0.5 - def xm(self, z, z2=None): + def xm(self, z, z2=None): # type: ignore[no-untyped-def] if z2 is None: return np.array(z) * 1000 return (np.array(z2) - np.array(z)) * 1000 @@ -40,38 +40,38 @@ def xm(self, z, z2=None): return MockCosmology() -@pytest.mark.parametrize("usecomplex", [True, False]) +@pytest.mark.parametrize("usecomplex", [True, False]) # type: ignore[misc] def test_deflect_nsew(usecomplex: bool) -> None: d = 5.0 r = np.radians(d) if usecomplex: - def alpha(re, im): + def alpha(re, im): # type: ignore[no-untyped-def] return re + 1j * im else: - def alpha(re, im): + def alpha(re, im): # type: ignore[no-untyped-def] return [re, im] # north - lon, lat = deflect(0.0, 0.0, alpha(r, 0)) - assert np.allclose([lon, lat], [0.0, d]) + lon, lat = deflect(0.0, 0.0, alpha(r, 0)) # type: ignore[misc, no-untyped-call] + assert np.allclose([lon, lat], [0.0, d]) # type: ignore[arg-type] # south - lon, lat = deflect(0.0, 0.0, alpha(-r, 0)) - assert np.allclose([lon, lat], [0.0, -d]) + lon, lat = deflect(0.0, 0.0, alpha(-r, 0)) # type: ignore[misc, no-untyped-call] + assert np.allclose([lon, lat], [0.0, -d]) # type: ignore[arg-type] # east - lon, lat = deflect(0.0, 0.0, alpha(0, r)) - assert np.allclose([lon, lat], [-d, 0.0]) + lon, lat = deflect(0.0, 0.0, alpha(0, r)) # type: ignore[misc, no-untyped-call] + assert np.allclose([lon, lat], [-d, 0.0]) # type: ignore[arg-type] # west - lon, lat = deflect(0.0, 0.0, alpha(0, -r)) - assert np.allclose([lon, lat], [d, 0.0]) + lon, lat = deflect(0.0, 0.0, alpha(0, -r)) # type: ignore[misc, no-untyped-call] + assert np.allclose([lon, lat], [d, 0.0]) # type: ignore[arg-type] -def test_deflect_many(rng) -> None: +def test_deflect_many(rng: np.random.Generator) -> None: n = 1000 abs_alpha = rng.uniform(0, 2 * np.pi, size=n) arg_alpha = rng.uniform(-np.pi, np.pi, size=n) @@ -79,7 +79,7 @@ def test_deflect_many(rng) -> None: lon_ = np.degrees(rng.uniform(-np.pi, np.pi, size=n)) lat_ = np.degrees(np.arcsin(rng.uniform(-1, 1, size=n))) - lon, lat = deflect(lon_, lat_, abs_alpha * np.exp(1j * arg_alpha)) + lon, lat = deflect(lon_, lat_, abs_alpha * np.exp(1j * arg_alpha)) # type: ignore[misc] x_, y_, z_ = healpix.ang2vec(lon_, lat_, lonlat=True) x, y, z = healpix.ang2vec(lon, lat, lonlat=True) @@ -89,7 +89,7 @@ def test_deflect_many(rng) -> None: np.testing.assert_allclose(dotp, np.cos(abs_alpha)) -def test_multi_plane_matrix(shells, cosmo, rng) -> None: +def test_multi_plane_matrix(shells, cosmo, rng) -> None: # type: ignore[no-untyped-def] mat = multi_plane_matrix(shells, cosmo) np.testing.assert_array_equal(mat, np.tril(mat)) @@ -101,12 +101,12 @@ def test_multi_plane_matrix(shells, cosmo, rng) -> None: kappas = [] for shell, delta in zip(shells, deltas): convergence.add_window(delta, shell) - kappas.append(convergence.kappa.copy()) + kappas.append(convergence.kappa.copy()) # type: ignore[union-attr] np.testing.assert_allclose(mat @ deltas, kappas) -def test_multi_plane_weights(shells, cosmo, rng) -> None: +def test_multi_plane_weights(shells, cosmo, rng) -> None: # type: ignore[no-untyped-def] w_in = np.eye(len(shells)) w_out = multi_plane_weights(w_in, shells, cosmo) @@ -125,4 +125,4 @@ def test_multi_plane_weights(shells, cosmo, rng) -> None: wmat = multi_plane_weights(weights, shells, cosmo) - np.testing.assert_allclose(np.einsum("ij,ik", wmat, deltas), kappa) + np.testing.assert_allclose(np.einsum("ij,ik", wmat, deltas), kappa) # type: ignore[arg-type] diff --git a/tests/test_points.py b/tests/test_points.py index ca9524b2..ceb20401 100644 --- a/tests/test_points.py +++ b/tests/test_points.py @@ -3,11 +3,11 @@ from glass.points import position_weights, positions_from_delta, uniform_positions -def catpos(pos): - lon, lat, cnt = [], [], 0 +def catpos(pos): # type: ignore[no-untyped-def] + lon, lat, cnt = [], [], 0 # type: ignore[var-annotated] for lo, la, co in pos: - lon = np.concatenate([lon, lo]) - lat = np.concatenate([lat, la]) + lon = np.concatenate([lon, lo]) # type: ignore[assignment] + lat = np.concatenate([lat, la]) # type: ignore[assignment] cnt = cnt + co return lon, lat, cnt @@ -20,19 +20,19 @@ def test_positions_from_delta() -> None: bias = 0.8 vis = np.ones(12) - lon, lat, cnt = catpos(positions_from_delta(ngal, delta, bias, vis)) + lon, lat, cnt = catpos(positions_from_delta(ngal, delta, bias, vis)) # type: ignore[no-untyped-call] assert isinstance(cnt, int) assert lon.shape == lat.shape == (cnt,) # case: multi-dimensional ngal - ngal = [1e-3, 2e-3] + ngal = [1e-3, 2e-3] # type: ignore[assignment] delta = np.zeros(12) bias = 0.8 vis = np.ones(12) - lon, lat, cnt = catpos(positions_from_delta(ngal, delta, bias, vis)) + lon, lat, cnt = catpos(positions_from_delta(ngal, delta, bias, vis)) # type: ignore[no-untyped-call] assert cnt.shape == (2,) assert lon.shape == (cnt.sum(),) @@ -45,7 +45,7 @@ def test_positions_from_delta() -> None: bias = 0.8 vis = np.ones(12) - lon, lat, cnt = catpos(positions_from_delta(ngal, delta, bias, vis)) + lon, lat, cnt = catpos(positions_from_delta(ngal, delta, bias, vis)) # type: ignore[no-untyped-call] assert cnt.shape == (3, 2) assert lon.shape == (cnt.sum(),) @@ -53,12 +53,12 @@ def test_positions_from_delta() -> None: # case: multi-dimensional broadcasting - ngal = [1e-3, 2e-3] + ngal = [1e-3, 2e-3] # type: ignore[assignment] delta = np.zeros((3, 1, 12)) bias = 0.8 vis = np.ones(12) - lon, lat, cnt = catpos(positions_from_delta(ngal, delta, bias, vis)) + lon, lat, cnt = catpos(positions_from_delta(ngal, delta, bias, vis)) # type: ignore[no-untyped-call] assert cnt.shape == (3, 2) assert lon.shape == (cnt.sum(),) @@ -70,25 +70,25 @@ def test_uniform_positions() -> None: ngal = 1e-3 - lon, lat, cnt = catpos(uniform_positions(ngal)) + lon, lat, cnt = catpos(uniform_positions(ngal)) # type: ignore[no-untyped-call] assert isinstance(cnt, int) assert lon.shape == lat.shape == (cnt,) # case: 1-D array input - ngal = [1e-3, 2e-3, 3e-3] + ngal = [1e-3, 2e-3, 3e-3] # type: ignore[assignment] - lon, lat, cnt = catpos(uniform_positions(ngal)) + lon, lat, cnt = catpos(uniform_positions(ngal)) # type: ignore[no-untyped-call] assert cnt.shape == (3,) assert lon.shape == lat.shape == (cnt.sum(),) # case: 2-D array input - ngal = [[1e-3, 2e-3], [3e-3, 4e-3], [5e-3, 6e-3]] + ngal = [[1e-3, 2e-3], [3e-3, 4e-3], [5e-3, 6e-3]] # type: ignore[assignment] - lon, lat, cnt = catpos(uniform_positions(ngal)) + lon, lat, cnt = catpos(uniform_positions(ngal)) # type: ignore[no-untyped-call] assert cnt.shape == (3, 2) assert lon.shape == lat.shape == (cnt.sum(),) diff --git a/tests/test_shapes.py b/tests/test_shapes.py index 578545c6..dd2fe917 100644 --- a/tests/test_shapes.py +++ b/tests/test_shapes.py @@ -1,5 +1,5 @@ import numpy as np -import pytest +import pytest # type: ignore[import-not-found] from glass.shapes import ( ellipticity_gaussian, @@ -17,12 +17,12 @@ def test_triaxial_axis_ratio() -> None: # many axis ratios - q = triaxial_axis_ratio(0.8, 0.4, size=1000) + q = triaxial_axis_ratio(0.8, 0.4, size=1000) # type: ignore[arg-type] assert np.shape(q) == (1000,) # explicit shape - q = triaxial_axis_ratio(0.8, 0.4, size=(10, 10)) + q = triaxial_axis_ratio(0.8, 0.4, size=(10, 10)) # type: ignore[arg-type] assert np.shape(q) == (10, 10) # implicit size @@ -78,10 +78,10 @@ def test_ellipticity_ryden04() -> None: # check that result is in the specified range e = ellipticity_ryden04(0.0, 1.0, 0.222, 0.056, size=10) - assert np.all((e.real >= -1.0) & (e.real <= 1.0)) + assert np.all((e.real >= -1.0) & (e.real <= 1.0)) # type: ignore[union-attr] e = ellipticity_ryden04(0.0, 1.0, 0.0, 1.0, size=10) - assert np.all((e.real >= -1.0) & (e.real <= 1.0)) + assert np.all((e.real >= -1.0) & (e.real <= 1.0)) # type: ignore[union-attr] def test_ellipticity_gaussian() -> None: @@ -89,23 +89,23 @@ def test_ellipticity_gaussian() -> None: eps = ellipticity_gaussian(n, 0.256) - assert eps.shape == (n,) + assert eps.shape == (n,) # type: ignore[union-attr] assert np.all(np.abs(eps) < 1) - assert np.isclose(np.std(eps.real), 0.256, atol=1e-3, rtol=0) - assert np.isclose(np.std(eps.imag), 0.256, atol=1e-3, rtol=0) + assert np.isclose(np.std(eps.real), 0.256, atol=1e-3, rtol=0) # type: ignore[union-attr] + assert np.isclose(np.std(eps.imag), 0.256, atol=1e-3, rtol=0) # type: ignore[union-attr] eps = ellipticity_gaussian([n, n], [0.128, 0.256]) - assert eps.shape == (2 * n,) + assert eps.shape == (2 * n,) # type: ignore[union-attr] assert np.all(np.abs(eps) < 1) - assert np.isclose(np.std(eps.real[:n]), 0.128, atol=1e-3, rtol=0) - assert np.isclose(np.std(eps.imag[:n]), 0.128, atol=1e-3, rtol=0) - assert np.isclose(np.std(eps.real[n:]), 0.256, atol=1e-3, rtol=0) - assert np.isclose(np.std(eps.imag[n:]), 0.256, atol=1e-3, rtol=0) + assert np.isclose(np.std(eps.real[:n]), 0.128, atol=1e-3, rtol=0) # type: ignore[index, union-attr] + assert np.isclose(np.std(eps.imag[:n]), 0.128, atol=1e-3, rtol=0) # type: ignore[index, union-attr] + assert np.isclose(np.std(eps.real[n:]), 0.256, atol=1e-3, rtol=0) # type: ignore[index, union-attr] + assert np.isclose(np.std(eps.imag[n:]), 0.256, atol=1e-3, rtol=0) # type: ignore[index, union-attr] def test_ellipticity_intnorm() -> None: @@ -113,23 +113,23 @@ def test_ellipticity_intnorm() -> None: eps = ellipticity_intnorm(n, 0.256) - assert eps.shape == (n,) + assert eps.shape == (n,) # type: ignore[union-attr] assert np.all(np.abs(eps) < 1) - assert np.isclose(np.std(eps.real), 0.256, atol=1e-3, rtol=0) - assert np.isclose(np.std(eps.imag), 0.256, atol=1e-3, rtol=0) + assert np.isclose(np.std(eps.real), 0.256, atol=1e-3, rtol=0) # type: ignore[union-attr] + assert np.isclose(np.std(eps.imag), 0.256, atol=1e-3, rtol=0) # type: ignore[union-attr] eps = ellipticity_intnorm([n, n], [0.128, 0.256]) - assert eps.shape == (2 * n,) + assert eps.shape == (2 * n,) # type: ignore[union-attr] assert np.all(np.abs(eps) < 1) - assert np.isclose(np.std(eps.real[:n]), 0.128, atol=1e-3, rtol=0) - assert np.isclose(np.std(eps.imag[:n]), 0.128, atol=1e-3, rtol=0) - assert np.isclose(np.std(eps.real[n:]), 0.256, atol=1e-3, rtol=0) - assert np.isclose(np.std(eps.imag[n:]), 0.256, atol=1e-3, rtol=0) + assert np.isclose(np.std(eps.real[:n]), 0.128, atol=1e-3, rtol=0) # type: ignore[index, union-attr] + assert np.isclose(np.std(eps.imag[:n]), 0.128, atol=1e-3, rtol=0) # type: ignore[index, union-attr] + assert np.isclose(np.std(eps.real[n:]), 0.256, atol=1e-3, rtol=0) # type: ignore[index, union-attr] + assert np.isclose(np.std(eps.imag[n:]), 0.256, atol=1e-3, rtol=0) # type: ignore[index, union-attr] with pytest.raises(ValueError): ellipticity_intnorm(1, 0.71) diff --git a/tests/test_shells.py b/tests/test_shells.py index fcfc3ab0..dbf206b1 100644 --- a/tests/test_shells.py +++ b/tests/test_shells.py @@ -1,5 +1,5 @@ import numpy as np -import pytest +import pytest # type: ignore[import-not-found] from glass.shells import RadialWindow, partition, restrict, tophat_windows @@ -18,7 +18,7 @@ def test_tophat_windows() -> None: zn <= z0 + len(w.za) * dz <= zn + dz for w, z0, zn in zip(ws, zb, zb[1:]) ) - assert all(np.all(w.wa == 1) for w in ws) + assert all(np.all(w.wa == 1) for w in ws) # type: ignore[comparison-overlap] def test_restrict() -> None: @@ -31,32 +31,32 @@ def test_restrict() -> None: zr, fr = restrict(z, f, w) - assert zr[0] == w.za[0] - assert zr[-1] == w.za[-1] + assert zr[0] == w.za[0] # type: ignore[index] + assert zr[-1] == w.za[-1] # type: ignore[index] - assert fr[0] == fr[-1] == 0.0 + assert fr[0] == fr[-1] == 0.0 # type: ignore[index] for zi, wi in zip(w.za, w.wa): i = np.searchsorted(zr, zi) - assert zr[i] == zi - assert fr[i] == wi * np.interp(zi, z, f) + assert zr[i] == zi # type: ignore[index] + assert fr[i] == wi * np.interp(zi, z, f) # type: ignore[index] for zi, fi in zip(z, f): if w.za[0] <= zi <= w.za[-1]: i = np.searchsorted(zr, zi) - assert zr[i] == zi - assert fr[i] == fi * np.interp(zi, w.za, w.wa) + assert zr[i] == zi # type: ignore[index] + assert fr[i] == fi * np.interp(zi, w.za, w.wa) # type: ignore[index] -@pytest.mark.parametrize("method", ["lstsq", "nnls", "restrict"]) -def test_partition(method) -> None: +@pytest.mark.parametrize("method", ["lstsq", "nnls", "restrict"]) # type: ignore[misc] +def test_partition(method) -> None: # type: ignore[no-untyped-def] shells = [ - RadialWindow(np.array([0.0, 1.0]), np.array([1.0, 0.0]), 0.0), - RadialWindow(np.array([0.0, 1.0, 2.0]), np.array([0.0, 1.0, 0.0]), 0.5), - RadialWindow(np.array([1.0, 2.0, 3.0]), np.array([0.0, 1.0, 0.0]), 1.5), - RadialWindow(np.array([2.0, 3.0, 4.0]), np.array([0.0, 1.0, 0.0]), 2.5), - RadialWindow(np.array([3.0, 4.0, 5.0]), np.array([0.0, 1.0, 0.0]), 3.5), - RadialWindow(np.array([4.0, 5.0]), np.array([0.0, 1.0]), 5.0), + RadialWindow(np.array([0.0, 1.0]), np.array([1.0, 0.0]), 0.0), # type: ignore[arg-type] + RadialWindow(np.array([0.0, 1.0, 2.0]), np.array([0.0, 1.0, 0.0]), 0.5), # type: ignore[arg-type] + RadialWindow(np.array([1.0, 2.0, 3.0]), np.array([0.0, 1.0, 0.0]), 1.5), # type: ignore[arg-type] + RadialWindow(np.array([2.0, 3.0, 4.0]), np.array([0.0, 1.0, 0.0]), 2.5), # type: ignore[arg-type] + RadialWindow(np.array([3.0, 4.0, 5.0]), np.array([0.0, 1.0, 0.0]), 3.5), # type: ignore[arg-type] + RadialWindow(np.array([4.0, 5.0]), np.array([0.0, 1.0]), 5.0), # type: ignore[arg-type] ] z = np.linspace(0.0, 5.0, 1000) @@ -67,6 +67,6 @@ def test_partition(method) -> None: part = partition(z, fz, shells, method=method) - assert part.shape == (len(shells), 3, 2) + assert part.shape == (len(shells), 3, 2) # type: ignore[union-attr] - assert np.allclose(part.sum(axis=0), np.trapz(fz, z)) # type: ignore[attr-defined] + assert np.allclose(part.sum(axis=0), np.trapz(fz, z)) # type: ignore[union-attr] # type: ignore[attr-defined] From 9151d81d004100f030d8ea077663706d94ec0396 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Tue, 8 Oct 2024 17:17:21 +0100 Subject: [PATCH 19/32] More fixing --- glass/fields.py | 4 ++-- glass/galaxies.py | 2 +- glass/lensing.py | 4 ++-- glass/observations.py | 2 +- glass/points.py | 2 +- glass/shells.py | 2 +- glass/user.py | 2 +- noxfile.py | 16 ++++++++-------- tests/conftest.py | 4 ++-- tests/core/test_algorithm.py | 4 ++-- tests/core/test_array.py | 4 ++-- tests/test_fits.py | 6 +++--- tests/test_galaxies.py | 2 +- tests/test_lensing.py | 6 +++--- tests/test_shapes.py | 2 +- tests/test_shells.py | 2 +- 16 files changed, 32 insertions(+), 32 deletions(-) diff --git a/glass/fields.py b/glass/fields.py index 4780c003..3daa18d8 100644 --- a/glass/fields.py +++ b/glass/fields.py @@ -30,10 +30,10 @@ from collections.abc import Generator, Iterable, Sequence from typing import Any, Callable, Optional, Union -import healpy as hp # type: ignore[import-untyped] +import healpy as hp import numpy as np import numpy.typing as npt -from gaussiancl import gaussiancl # type: ignore[import-untyped] +from gaussiancl import gaussiancl # types Size = Optional[Union[int, tuple[int, ...]]] diff --git a/glass/galaxies.py b/glass/galaxies.py index f11f0ada..4cf10886 100644 --- a/glass/galaxies.py +++ b/glass/galaxies.py @@ -26,7 +26,7 @@ from glass.shells import RadialWindow -import healpix # type: ignore[import-untyped] +import healpix import numpy as np from glass.core.array import broadcast_leading_axes, cumtrapz diff --git a/glass/lensing.py b/glass/lensing.py index 8a60907c..5a3e887f 100644 --- a/glass/lensing.py +++ b/glass/lensing.py @@ -33,7 +33,7 @@ from typing import TYPE_CHECKING -import healpy as hp # type: ignore[import-untyped] +import healpy as hp import numpy as np if TYPE_CHECKING: @@ -41,7 +41,7 @@ import numpy.typing as npt - from cosmology import Cosmology # type: ignore[import-untyped] + from cosmology import Cosmology from glass.shells import RadialWindow diff --git a/glass/observations.py b/glass/observations.py index 9615b296..5637e993 100644 --- a/glass/observations.py +++ b/glass/observations.py @@ -31,7 +31,7 @@ import math from typing import TYPE_CHECKING -import healpy as hp # type: ignore[import-untyped] +import healpy as hp import numpy as np from glass.core.array import cumtrapz diff --git a/glass/points.py b/glass/points.py index e4acd925..ec7a8c49 100644 --- a/glass/points.py +++ b/glass/points.py @@ -33,7 +33,7 @@ import typing -import healpix # type: ignore[import-untyped] +import healpix import numpy as np import numpy.typing as npt diff --git a/glass/shells.py b/glass/shells.py index 2b3a1e41..64052eb9 100644 --- a/glass/shells.py +++ b/glass/shells.py @@ -54,7 +54,7 @@ from glass.core.array import ndinterp if TYPE_CHECKING: - from cosmology import Cosmology # type: ignore[import-untyped] + from cosmology import Cosmology # types ArrayLike1D = Union[Sequence[float], npt.ArrayLike] diff --git a/glass/user.py b/glass/user.py index beabdab5..0366d374 100644 --- a/glass/user.py +++ b/glass/user.py @@ -114,7 +114,7 @@ def write_catalog( Requires the ``fitsio`` package. """ - import fitsio # type: ignore[import-not-found] + import fitsio with fitsio.FITS(filename, "rw", clobber=True) as fits: fits.write(None) diff --git a/noxfile.py b/noxfile.py index 99db21e0..26aeb950 100644 --- a/noxfile.py +++ b/noxfile.py @@ -4,7 +4,7 @@ from pathlib import Path -import nox # type: ignore[import-not-found] +import nox # Options to modify nox behaviour nox.options.reuse_existing_virtualenvs = True @@ -13,14 +13,14 @@ ALL_PYTHON = ["3.9", "3.10", "3.11", "3.12"] -@nox.session # type: ignore[misc] +@nox.session def lint(session: nox.Session) -> None: """Run the linter.""" session.install("pre-commit") session.run("pre-commit", "run", "--all-files", *session.posargs) -@nox.session(python=ALL_PYTHON) # type: ignore[misc] +@nox.session(python=ALL_PYTHON) def tests(session: nox.Session) -> None: """Run the unit tests.""" session.install("-c", ".github/test-constraints.txt", "-e", ".[test]") @@ -30,14 +30,14 @@ def tests(session: nox.Session) -> None: ) -@nox.session(python=ALL_PYTHON) # type: ignore[misc] +@nox.session(python=ALL_PYTHON) def coverage(session: nox.Session) -> None: """Run tests and compute coverage.""" session.posargs.append("--cov") tests(session) -@nox.session(python=ALL_PYTHON) # type: ignore[misc] +@nox.session(python=ALL_PYTHON) def doctests(session: nox.Session) -> None: """Run the doctests.""" session.posargs.append("--doctest-plus") @@ -45,7 +45,7 @@ def doctests(session: nox.Session) -> None: tests(session) -@nox.session # type: ignore[misc] +@nox.session def examples(session: nox.Session) -> None: """Run the example notebooks.""" session.install("-e", ".[examples]") @@ -54,7 +54,7 @@ def examples(session: nox.Session) -> None: ) -@nox.session # type: ignore[misc] +@nox.session def docs(session: nox.Session) -> None: """Build the docs. Pass "serve" to serve.""" session.install("-e", ".[docs]") @@ -71,7 +71,7 @@ def docs(session: nox.Session) -> None: print("Unsupported argument to docs") -@nox.session # type: ignore[misc] +@nox.session def build(session: nox.Session) -> None: """Build an SDist and wheel.""" session.install("build") diff --git a/tests/conftest.py b/tests/conftest.py index df5ee22a..b2b6a9fd 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,8 +1,8 @@ import numpy as np -import pytest # type: ignore[import-not-found] +import pytest -@pytest.fixture(scope="session") # type: ignore[misc] +@pytest.fixture(scope="session") def rng() -> np.random.Generator: import numpy as np diff --git a/tests/core/test_algorithm.py b/tests/core/test_algorithm.py index 95b977bd..efd0ec5c 100644 --- a/tests/core/test_algorithm.py +++ b/tests/core/test_algorithm.py @@ -1,7 +1,7 @@ import importlib.util import numpy as np -import pytest # type: ignore[import-not-found] +import pytest from glass.core.algorithm import nnls as nnls_glass @@ -11,7 +11,7 @@ @pytest.mark.skipif(not HAVE_SCIPY, reason="test requires SciPy") # type: ignore[misc] def test_nnls(rng) -> None: # type: ignore[no-untyped-def] - from scipy.optimize import nnls as nnls_scipy # type: ignore[import-untyped] + from scipy.optimize import nnls as nnls_scipy # cross-check output with scipy's nnls diff --git a/tests/core/test_array.py b/tests/core/test_array.py index dc8a92dd..4a5ab275 100644 --- a/tests/core/test_array.py +++ b/tests/core/test_array.py @@ -1,7 +1,7 @@ import importlib.util import numpy as np -import pytest # type: ignore[import-not-found] +import pytest from glass.core.array import ( broadcast_first, @@ -154,7 +154,7 @@ def test_trapz_product() -> None: @pytest.mark.skipif(not HAVE_SCIPY, reason="test requires SciPy") # type: ignore[misc] def test_cumtrapz() -> None: - from scipy.integrate import cumulative_trapezoid # type: ignore[import-untyped] + from scipy.integrate import cumulative_trapezoid # 1D f and x diff --git a/tests/test_fits.py b/tests/test_fits.py index 0ce729c2..1438a24d 100644 --- a/tests/test_fits.py +++ b/tests/test_fits.py @@ -3,7 +3,7 @@ import pathlib import numpy as np -import pytest # type: ignore[import-not-found] +import pytest from glass import user @@ -27,9 +27,9 @@ def _test_append(fits, data, names) -> None: # type: ignore[no-untyped-def] filename = "MyFile.Fits" -@pytest.mark.skipif(not HAVE_FITSIO, reason="test requires fitsio") # type: ignore[misc] +@pytest.mark.skipif(not HAVE_FITSIO, reason="test requires fitsio") def test_basic_write(tmp_path: os.PathLike) -> None: # type: ignore[type-arg] - import fitsio # type: ignore[import-not-found] + import fitsio filename_gfits = "gfits.fits" # what GLASS creates filename_tfits = "tfits.fits" # file created on the fly to test against diff --git a/tests/test_galaxies.py b/tests/test_galaxies.py index a492df46..cb2c43a9 100644 --- a/tests/test_galaxies.py +++ b/tests/test_galaxies.py @@ -1,5 +1,5 @@ import numpy as np -import pytest # type: ignore[import-not-found] +import pytest from glass.galaxies import gaussian_phz, redshifts, redshifts_from_nz diff --git a/tests/test_lensing.py b/tests/test_lensing.py index e196bb2e..b6877d92 100644 --- a/tests/test_lensing.py +++ b/tests/test_lensing.py @@ -1,6 +1,6 @@ -import healpix # type: ignore[import-untyped] +import healpix import numpy as np -import pytest # type: ignore[import-not-found] +import pytest from glass.lensing import ( MultiPlaneConvergence, @@ -41,7 +41,7 @@ def xm(self, z, z2=None): # type: ignore[no-untyped-def] @pytest.mark.parametrize("usecomplex", [True, False]) # type: ignore[misc] -def test_deflect_nsew(usecomplex: bool) -> None: +def test_deflect_nsew(*, usecomplex: bool) -> None: d = 5.0 r = np.radians(d) diff --git a/tests/test_shapes.py b/tests/test_shapes.py index dd2fe917..2f658c28 100644 --- a/tests/test_shapes.py +++ b/tests/test_shapes.py @@ -1,5 +1,5 @@ import numpy as np -import pytest # type: ignore[import-not-found] +import pytest from glass.shapes import ( ellipticity_gaussian, diff --git a/tests/test_shells.py b/tests/test_shells.py index dbf206b1..823f0ef4 100644 --- a/tests/test_shells.py +++ b/tests/test_shells.py @@ -1,5 +1,5 @@ import numpy as np -import pytest # type: ignore[import-not-found] +import pytest from glass.shells import RadialWindow, partition, restrict, tophat_windows From cc07ade2fab4019bc0ce65f8810d74f700f8a4ed Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Tue, 8 Oct 2024 20:59:55 +0100 Subject: [PATCH 20/32] `mypy` passes --- glass/core/array.py | 2 +- glass/lensing.py | 2 +- glass/observations.py | 2 +- glass/points.py | 11 +++++------ glass/shells.py | 2 +- tests/core/test_algorithm.py | 2 +- tests/core/test_array.py | 2 +- tests/test_fits.py | 2 +- tests/test_lensing.py | 4 ++-- tests/test_shells.py | 4 ++-- 10 files changed, 16 insertions(+), 17 deletions(-) diff --git a/glass/core/array.py b/glass/core/array.py index 1dea9593..cdfe4bfa 100644 --- a/glass/core/array.py +++ b/glass/core/array.py @@ -89,7 +89,7 @@ def trapz_product( y = np.interp(x, *f) # type: ignore[arg-type] for f_ in ff: y *= np.interp(x, *f_) # type: ignore[arg-type] - return np.trapz(y, x, axis=axis) # type: ignore[no-any-return] # type: ignore[attr-defined] + return np.trapz(y, x, axis=axis) # type: ignore[attr-defined,no-any-return] def cumtrapz( diff --git a/glass/lensing.py b/glass/lensing.py index 5a3e887f..36fc3ffd 100644 --- a/glass/lensing.py +++ b/glass/lensing.py @@ -295,7 +295,7 @@ def add_window(self, delta: npt.ArrayLike, w: RadialWindow) -> None: """ zsrc = w.zeff - lens_weight = np.trapz(w.wa, w.za) / np.interp(zsrc, w.za, w.wa) # type: ignore[arg-type] # type: ignore[attr-defined] + lens_weight = np.trapz(w.wa, w.za) / np.interp(zsrc, w.za, w.wa) # type: ignore[arg-type,attr-defined] self.add_plane(delta, zsrc, lens_weight) # type: ignore[arg-type] diff --git a/glass/observations.py b/glass/observations.py index 5637e993..b0ce4f23 100644 --- a/glass/observations.py +++ b/glass/observations.py @@ -311,7 +311,7 @@ def tomo_nz_gausserr( """ # converting zbins into an array: - zbins_arr = np.asanyarray(zbins) # type: ignore[no-redef] + zbins_arr = np.asanyarray(zbins) # bin edges and adds a new axis z_lower = zbins_arr[:, 0, np.newaxis] diff --git a/glass/points.py b/glass/points.py index ec7a8c49..fdd16405 100644 --- a/glass/points.py +++ b/glass/points.py @@ -97,17 +97,17 @@ def loglinear_bias( return delta_g -def positions_from_delta( # noqa: PLR0912, PLR0913, PLR0915 # type: ignore[no-untyped-def] +def positions_from_delta( # noqa: PLR0912, PLR0913, PLR0915 ngal: float | npt.ArrayLike, delta: npt.ArrayLike, bias: float | npt.ArrayLike | None = None, vis: npt.ArrayLike | None = None, *, - bias_model="linear", + bias_model: str | typing.Callable[..., typing.Any] = "linear", remove_monopole: bool = False, batch: int | None = 1_000_000, rng: np.random.Generator | None = None, -): +) -> typing.Iterator[tuple[npt.ArrayLike, npt.ArrayLike, npt.ArrayLike]]: """ Generate positions tracing a density contrast. @@ -173,8 +173,7 @@ def positions_from_delta( # noqa: PLR0912, PLR0913, PLR0915 # type: ignore[no- if isinstance(bias_model, str): bias_model = globals()[f"{bias_model}_bias"] elif not callable(bias_model): - msg = "bias_model must be string or callable" - raise TypeError(msg) + raise TypeError("bias_model must be string or callable") # noqa: EM101,TRY003 # broadcast inputs to common shape of extra dimensions inputs = [(ngal, 0), (delta, 1)] @@ -191,7 +190,7 @@ def positions_from_delta( # noqa: PLR0912, PLR0913, PLR0915 # type: ignore[no- # iterate the leading dimensions for k in np.ndindex(dims): # compute density contrast from bias model, or copy - n = np.copy(delta[k]) if bias is None else bias_model(delta[k], bias[k]) # type: ignore[call-overload] + n = np.copy(delta[k]) if bias is None else bias_model(delta[k], bias[k]) # type: ignore[call-overload,operator] # remove monopole if asked to if remove_monopole: diff --git a/glass/shells.py b/glass/shells.py index 64052eb9..c5f7c1f3 100644 --- a/glass/shells.py +++ b/glass/shells.py @@ -179,7 +179,7 @@ def tophat_windows( n = max(round((zmax - zmin) / dz), 2) z = np.linspace(zmin, zmax, n) # type: ignore[arg-type] w = wht(z) - zeff = np.trapz(w * z, z) / np.trapz(w, z) # type: ignore[operator] # type: ignore[attr-defined] + zeff = np.trapz(w * z, z) / np.trapz(w, z) # type: ignore[attr-defined,operator] ws.append(RadialWindow(z, w, zeff)) # type: ignore[arg-type] return ws diff --git a/tests/core/test_algorithm.py b/tests/core/test_algorithm.py index efd0ec5c..450eaa85 100644 --- a/tests/core/test_algorithm.py +++ b/tests/core/test_algorithm.py @@ -9,7 +9,7 @@ HAVE_SCIPY = importlib.util.find_spec("scipy") is not None -@pytest.mark.skipif(not HAVE_SCIPY, reason="test requires SciPy") # type: ignore[misc] +@pytest.mark.skipif(not HAVE_SCIPY, reason="test requires SciPy") def test_nnls(rng) -> None: # type: ignore[no-untyped-def] from scipy.optimize import nnls as nnls_scipy diff --git a/tests/core/test_array.py b/tests/core/test_array.py index 4a5ab275..ac568dda 100644 --- a/tests/core/test_array.py +++ b/tests/core/test_array.py @@ -152,7 +152,7 @@ def test_trapz_product() -> None: assert np.allclose(s, 1.0) -@pytest.mark.skipif(not HAVE_SCIPY, reason="test requires SciPy") # type: ignore[misc] +@pytest.mark.skipif(not HAVE_SCIPY, reason="test requires SciPy") def test_cumtrapz() -> None: from scipy.integrate import cumulative_trapezoid diff --git a/tests/test_fits.py b/tests/test_fits.py index 1438a24d..906b18e7 100644 --- a/tests/test_fits.py +++ b/tests/test_fits.py @@ -56,7 +56,7 @@ def test_basic_write(tmp_path: os.PathLike) -> None: # type: ignore[type-arg] assert glass_data["RB"].size == test_data["RA"].size -@pytest.mark.skipif(not HAVE_FITSIO, reason="test requires fitsio") # type: ignore[misc] +@pytest.mark.skipif(not HAVE_FITSIO, reason="test requires fitsio") def test_write_exception(tmp_path: pathlib.Path) -> None: try: with user.write_catalog(tmp_path / filename, ext="CATALOG") as out: # type: ignore[arg-type] diff --git a/tests/test_lensing.py b/tests/test_lensing.py index b6877d92..fc276636 100644 --- a/tests/test_lensing.py +++ b/tests/test_lensing.py @@ -11,7 +11,7 @@ from glass.shells import RadialWindow -@pytest.fixture # type: ignore[misc] +@pytest.fixture def shells() -> list[RadialWindow]: return [ RadialWindow([0.0, 1.0, 2.0], [0.0, 1.0, 0.0], 1.0), @@ -40,7 +40,7 @@ def xm(self, z, z2=None): # type: ignore[no-untyped-def] return MockCosmology() -@pytest.mark.parametrize("usecomplex", [True, False]) # type: ignore[misc] +@pytest.mark.parametrize("usecomplex", [True, False]) def test_deflect_nsew(*, usecomplex: bool) -> None: d = 5.0 r = np.radians(d) diff --git a/tests/test_shells.py b/tests/test_shells.py index 823f0ef4..1d3e2fd9 100644 --- a/tests/test_shells.py +++ b/tests/test_shells.py @@ -48,7 +48,7 @@ def test_restrict() -> None: assert fr[i] == fi * np.interp(zi, w.za, w.wa) # type: ignore[index] -@pytest.mark.parametrize("method", ["lstsq", "nnls", "restrict"]) # type: ignore[misc] +@pytest.mark.parametrize("method", ["lstsq", "nnls", "restrict"]) def test_partition(method) -> None: # type: ignore[no-untyped-def] shells = [ RadialWindow(np.array([0.0, 1.0]), np.array([1.0, 0.0]), 0.0), # type: ignore[arg-type] @@ -69,4 +69,4 @@ def test_partition(method) -> None: # type: ignore[no-untyped-def] assert part.shape == (len(shells), 3, 2) # type: ignore[union-attr] - assert np.allclose(part.sum(axis=0), np.trapz(fz, z)) # type: ignore[union-attr] # type: ignore[attr-defined] + assert np.allclose(part.sum(axis=0), np.trapz(fz, z)) # type: ignore[attr-defined,union-attr] From 6883e1ca0a1070cfac5c2cb60d6e9c72b0223564 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Tue, 8 Oct 2024 21:06:07 +0100 Subject: [PATCH 21/32] Add space --- glass/core/array.py | 2 +- glass/lensing.py | 2 +- glass/points.py | 2 +- glass/shells.py | 2 +- tests/test_shells.py | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/glass/core/array.py b/glass/core/array.py index cdfe4bfa..940171a7 100644 --- a/glass/core/array.py +++ b/glass/core/array.py @@ -89,7 +89,7 @@ def trapz_product( y = np.interp(x, *f) # type: ignore[arg-type] for f_ in ff: y *= np.interp(x, *f_) # type: ignore[arg-type] - return np.trapz(y, x, axis=axis) # type: ignore[attr-defined,no-any-return] + return np.trapz(y, x, axis=axis) # type: ignore[attr-defined, no-any-return] def cumtrapz( diff --git a/glass/lensing.py b/glass/lensing.py index 36fc3ffd..4ec0373d 100644 --- a/glass/lensing.py +++ b/glass/lensing.py @@ -295,7 +295,7 @@ def add_window(self, delta: npt.ArrayLike, w: RadialWindow) -> None: """ zsrc = w.zeff - lens_weight = np.trapz(w.wa, w.za) / np.interp(zsrc, w.za, w.wa) # type: ignore[arg-type,attr-defined] + lens_weight = np.trapz(w.wa, w.za) / np.interp(zsrc, w.za, w.wa) # type: ignore[arg-type, attr-defined] self.add_plane(delta, zsrc, lens_weight) # type: ignore[arg-type] diff --git a/glass/points.py b/glass/points.py index fdd16405..1f5e66d0 100644 --- a/glass/points.py +++ b/glass/points.py @@ -190,7 +190,7 @@ def positions_from_delta( # noqa: PLR0912, PLR0913, PLR0915 # iterate the leading dimensions for k in np.ndindex(dims): # compute density contrast from bias model, or copy - n = np.copy(delta[k]) if bias is None else bias_model(delta[k], bias[k]) # type: ignore[call-overload,operator] + n = np.copy(delta[k]) if bias is None else bias_model(delta[k], bias[k]) # type: ignore[call-overload, operator] # remove monopole if asked to if remove_monopole: diff --git a/glass/shells.py b/glass/shells.py index c5f7c1f3..85a7e29b 100644 --- a/glass/shells.py +++ b/glass/shells.py @@ -179,7 +179,7 @@ def tophat_windows( n = max(round((zmax - zmin) / dz), 2) z = np.linspace(zmin, zmax, n) # type: ignore[arg-type] w = wht(z) - zeff = np.trapz(w * z, z) / np.trapz(w, z) # type: ignore[attr-defined,operator] + zeff = np.trapz(w * z, z) / np.trapz(w, z) # type: ignore[attr-defined, operator] ws.append(RadialWindow(z, w, zeff)) # type: ignore[arg-type] return ws diff --git a/tests/test_shells.py b/tests/test_shells.py index 1d3e2fd9..ef4c597c 100644 --- a/tests/test_shells.py +++ b/tests/test_shells.py @@ -69,4 +69,4 @@ def test_partition(method) -> None: # type: ignore[no-untyped-def] assert part.shape == (len(shells), 3, 2) # type: ignore[union-attr] - assert np.allclose(part.sum(axis=0), np.trapz(fz, z)) # type: ignore[attr-defined,union-attr] + assert np.allclose(part.sum(axis=0), np.trapz(fz, z)) # type: ignore[attr-defined, union-attr] From 3d894b4fdd3296b5dc7f8e34a95a0301103e889a Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Wed, 9 Oct 2024 11:30:54 +0100 Subject: [PATCH 22/32] Fix `mypy` --- .gitignore | 1 + glass/shapes.py | 2 +- glass/shells.py | 46 ++++++++++++++++++++++---------------------- glass/user.py | 14 ++++++-------- tests/test_shapes.py | 16 +++++++-------- tests/test_shells.py | 14 +++++++------- 6 files changed, 46 insertions(+), 47 deletions(-) diff --git a/.gitignore b/.gitignore index 93b4e32e..485375d0 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ dist .env .coverage* coverage* +mypy_error_report.txt diff --git a/glass/shapes.py b/glass/shapes.py index 37aec2a6..5f17665b 100644 --- a/glass/shapes.py +++ b/glass/shapes.py @@ -246,7 +246,7 @@ def ellipticity_intnorm( sigma: npt.ArrayLike, *, rng: np.random.Generator | None = None, -) -> npt.ArrayLike: +) -> npt.NDArray: # type: ignore[type-arg] r""" Sample galaxy ellipticities with intrinsic normal distribution. diff --git a/glass/shells.py b/glass/shells.py index 85a7e29b..b6d2e70d 100644 --- a/glass/shells.py +++ b/glass/shells.py @@ -57,21 +57,21 @@ from cosmology import Cosmology # types -ArrayLike1D = Union[Sequence[float], npt.ArrayLike] -WeightFunc = Callable[[ArrayLike1D], npt.ArrayLike] +ArrayLike1D = Union[Sequence[float], npt.NDArray] # type: ignore[type-arg] +WeightFunc = Callable[[ArrayLike1D], npt.NDArray] # type: ignore[type-arg] -def distance_weight(z: npt.ArrayLike, cosmo: Cosmology) -> npt.ArrayLike: +def distance_weight(z: npt.ArrayLike, cosmo: Cosmology) -> npt.NDArray: # type: ignore[type-arg] """Uniform weight in comoving distance.""" return 1 / cosmo.ef(z) # type: ignore[no-any-return] -def volume_weight(z: npt.ArrayLike, cosmo: Cosmology) -> npt.ArrayLike: +def volume_weight(z: npt.ArrayLike, cosmo: Cosmology) -> npt.NDArray: # type: ignore[type-arg] """Uniform weight in comoving volume.""" return cosmo.xm(z) ** 2 / cosmo.ef(z) # type: ignore[no-any-return] -def density_weight(z: npt.ArrayLike, cosmo: Cosmology) -> npt.ArrayLike: +def density_weight(z: npt.ArrayLike, cosmo: Cosmology) -> npt.NDArray: # type: ignore[type-arg] """Uniform weight in matter density.""" return cosmo.rho_m_z(z) * cosmo.xm(z) ** 2 / cosmo.ef(z) # type: ignore[no-any-return] @@ -164,10 +164,10 @@ def tophat_windows( :ref:`user-window-functions` """ - if len(zbins) < 2: # type: ignore[arg-type] + if len(zbins) < 2: msg = "zbins must have at least two entries" raise ValueError(msg) - if zbins[0] != 0: # type: ignore[index] + if zbins[0] != 0: warnings.warn( "first tophat window does not start at redshift zero", stacklevel=2 ) @@ -175,11 +175,11 @@ def tophat_windows( wht: WeightFunc wht = weight if weight is not None else np.ones_like # type: ignore[assignment] ws = [] - for zmin, zmax in zip(zbins, zbins[1:]): # type: ignore[arg-type, index] + for zmin, zmax in zip(zbins, zbins[1:]): n = max(round((zmax - zmin) / dz), 2) - z = np.linspace(zmin, zmax, n) # type: ignore[arg-type] + z = np.linspace(zmin, zmax, n) w = wht(z) - zeff = np.trapz(w * z, z) / np.trapz(w, z) # type: ignore[attr-defined, operator] + zeff = np.trapz(w * z, z) / np.trapz(w, z) ws.append(RadialWindow(z, w, zeff)) # type: ignore[arg-type] return ws @@ -223,25 +223,25 @@ def linear_windows( :ref:`user-window-functions` """ - if len(zgrid) < 3: # type: ignore[arg-type] + if len(zgrid) < 3: msg = "nodes must have at least 3 entries" raise ValueError(msg) - if zgrid[0] != 0: # type: ignore[index] + if zgrid[0] != 0: warnings.warn("first triangular window does not start at z=0", stacklevel=2) ws = [] - for zmin, zmid, zmax in zip(zgrid, zgrid[1:], zgrid[2:]): # type: ignore[arg-type, index] + for zmin, zmid, zmax in zip(zgrid, zgrid[1:], zgrid[2:]): n = max(round((zmid - zmin) / dz), 2) - 1 m = max(round((zmax - zmid) / dz), 2) z = np.concatenate( - [np.linspace(zmin, zmid, n, endpoint=False), np.linspace(zmid, zmax, m)], # type: ignore[arg-type] + [np.linspace(zmin, zmid, n, endpoint=False), np.linspace(zmid, zmax, m)], ) w = np.concatenate( [np.linspace(0.0, 1.0, n, endpoint=False), np.linspace(1.0, 0.0, m)], ) if weight is not None: w *= weight(z) - ws.append(RadialWindow(z, w, zmid)) # type: ignore[arg-type] + ws.append(RadialWindow(z, w, zmid)) return ws @@ -285,25 +285,25 @@ def cubic_windows( :ref:`user-window-functions` """ - if len(zgrid) < 3: # type: ignore[arg-type] + if len(zgrid) < 3: msg = "nodes must have at least 3 entries" raise ValueError(msg) - if zgrid[0] != 0: # type: ignore[index] + if zgrid[0] != 0: warnings.warn("first cubic spline window does not start at z=0", stacklevel=2) ws = [] - for zmin, zmid, zmax in zip(zgrid, zgrid[1:], zgrid[2:]): # type: ignore[arg-type, index] + for zmin, zmid, zmax in zip(zgrid, zgrid[1:], zgrid[2:]): n = max(round((zmid - zmin) / dz), 2) - 1 m = max(round((zmax - zmid) / dz), 2) z = np.concatenate( - [np.linspace(zmin, zmid, n, endpoint=False), np.linspace(zmid, zmax, m)], # type: ignore[arg-type] + [np.linspace(zmin, zmid, n, endpoint=False), np.linspace(zmid, zmax, m)], ) u = np.linspace(0.0, 1.0, n, endpoint=False) v = np.linspace(1.0, 0.0, m) w = np.concatenate([u**2 * (3 - 2 * u), v**2 * (3 - 2 * v)]) if weight is not None: w *= weight(z) - ws.append(RadialWindow(z, w, zmid)) # type: ignore[arg-type] + ws.append(RadialWindow(z, w, zmid)) return ws @@ -311,7 +311,7 @@ def restrict( z: ArrayLike1D, f: ArrayLike1D, w: RadialWindow, -) -> tuple[npt.ArrayLike, npt.ArrayLike]: +) -> tuple[npt.NDArray, npt.NDArray]: # type: ignore[type-arg] """ Restrict a function to a redshift window. @@ -345,7 +345,7 @@ def restrict( z_ = np.compress(np.greater(z, w.za[0]) & np.less(z, w.za[-1]), z) zr = np.union1d(w.za, z_) fr = ndinterp(zr, z, f, left=0.0, right=0.0) * ndinterp(zr, w.za, w.wa) # type: ignore[operator] - return zr, fr + return zr, fr # type: ignore[return-value] def partition( @@ -573,7 +573,7 @@ def partition_restrict( """Partition by restriction and integration.""" part = np.empty((len(shells),) + np.shape(fz)[:-1]) for i, w in enumerate(shells): - zr, fr = restrict(z, fz, w) + zr, fr = restrict(z, fz, w) # type: ignore[arg-type] part[i] = np.trapz(fr, zr, axis=-1) # type: ignore[attr-defined] return part diff --git a/glass/user.py b/glass/user.py index 0366d374..8e8da00a 100644 --- a/glass/user.py +++ b/glass/user.py @@ -26,7 +26,7 @@ import numpy.typing as npt -def save_cls(filename: str, cls: list[npt.ArrayLike | None]) -> None: +def save_cls(filename: str, cls: list[npt.NDArray | None]) -> None: # type: ignore[type-arg] """ Save a list of Cls to file. @@ -34,12 +34,12 @@ def save_cls(filename: str, cls: list[npt.ArrayLike | None]) -> None: ``.npz`` suffix, or it will be given one. """ - split = np.cumsum([len(cl) if cl is not None else 0 for cl in cls[:-1]]) # type: ignore[arg-type] + split = np.cumsum([len(cl) if cl is not None else 0 for cl in cls[:-1]]) values = np.concatenate([cl for cl in cls if cl is not None]) np.savez(filename, values=values, split=split) -def load_cls(filename: str) -> list[npt.ArrayLike]: +def load_cls(filename: str) -> list[npt.NDArray]: # type: ignore[type-arg] """ Load a list of Cls from file. @@ -49,7 +49,7 @@ def load_cls(filename: str) -> list[npt.ArrayLike]: with np.load(filename) as npz: values = npz["values"] split = npz["split"] - return np.split(values, split) # type: ignore[return-value] + return np.split(values, split) class _FitsWriter: @@ -64,7 +64,7 @@ def __init__(self, fits, ext: str | None = None) -> None: # type: ignore[no-unt self.fits = fits self.ext = ext - def _append(self, data: npt.ArrayLike, names: list[str] | None = None) -> None: + def _append(self, data: npt.NDArray, names: list[str] | None = None) -> None: # type: ignore[type-arg] """Write the FITS file.""" if self.ext is None or self.ext not in self.fits: self.fits.write_table(data, names=names, extname=self.ext) @@ -75,9 +75,7 @@ def _append(self, data: npt.ArrayLike, names: list[str] | None = None) -> None: # not using hdu.append here because of incompatibilities hdu.write(data, names=names, firstrow=hdu.get_nrows()) - def write( - self, data: npt.ArrayLike | None = None, /, **columns: npt.ArrayLike - ) -> None: + def write(self, data: npt.NDArray | None = None, /, **columns: npt.NDArray) -> None: # type: ignore[type-arg] """ Write to FITS by calling the internal _append method. diff --git a/tests/test_shapes.py b/tests/test_shapes.py index 74742443..6edc40b5 100644 --- a/tests/test_shapes.py +++ b/tests/test_shapes.py @@ -113,23 +113,23 @@ def test_ellipticity_intnorm() -> None: eps = ellipticity_intnorm(n, 0.256) - assert eps.shape == (n,) # type: ignore[union-attr] + assert eps.shape == (n,) np.testing.assert_array_less(np.abs(eps), 1) - np.testing.assert_allclose(np.std(eps.real), 0.256, atol=1e-3, rtol=0) # type: ignore[union-attr] - np.testing.assert_allclose(np.std(eps.imag), 0.256, atol=1e-3, rtol=0) # type: ignore[union-attr] + np.testing.assert_allclose(np.std(eps.real), 0.256, atol=1e-3, rtol=0) + np.testing.assert_allclose(np.std(eps.imag), 0.256, atol=1e-3, rtol=0) eps = ellipticity_intnorm([n, n], [0.128, 0.256]) - assert eps.shape == (2 * n,) # type: ignore[union-attr] + assert eps.shape == (2 * n,) np.testing.assert_array_less(np.abs(eps), 1) - np.testing.assert_allclose(np.std(eps.real[:n]), 0.128, atol=1e-3, rtol=0) # type: ignore[index, union-attr] - np.testing.assert_allclose(np.std(eps.imag[:n]), 0.128, atol=1e-3, rtol=0) # type: ignore[index, union-attr] - np.testing.assert_allclose(np.std(eps.real[n:]), 0.256, atol=1e-3, rtol=0) # type: ignore[index, union-attr] - np.testing.assert_allclose(np.std(eps.imag[n:]), 0.256, atol=1e-3, rtol=0) # type: ignore[index, union-attr] + np.testing.assert_allclose(np.std(eps.real[:n]), 0.128, atol=1e-3, rtol=0) + np.testing.assert_allclose(np.std(eps.imag[:n]), 0.128, atol=1e-3, rtol=0) + np.testing.assert_allclose(np.std(eps.real[n:]), 0.256, atol=1e-3, rtol=0) + np.testing.assert_allclose(np.std(eps.imag[n:]), 0.256, atol=1e-3, rtol=0) with pytest.raises(ValueError): ellipticity_intnorm(1, 0.71) diff --git a/tests/test_shells.py b/tests/test_shells.py index 34caa55b..5cba9cdb 100644 --- a/tests/test_shells.py +++ b/tests/test_shells.py @@ -31,21 +31,21 @@ def test_restrict() -> None: zr, fr = restrict(z, f, w) - assert zr[0] == w.za[0] # type: ignore[index] - assert zr[-1] == w.za[-1] # type: ignore[index] + assert zr[0] == w.za[0] + assert zr[-1] == w.za[-1] - assert fr[0] == fr[-1] == 0.0 # type: ignore[index] + assert fr[0] == fr[-1] == 0.0 for zi, wi in zip(w.za, w.wa): i = np.searchsorted(zr, zi) - assert zr[i] == zi # type: ignore[index] - assert fr[i] == wi * np.interp(zi, z, f) # type: ignore[index] + assert zr[i] == zi + assert fr[i] == wi * np.interp(zi, z, f) for zi, fi in zip(z, f): if w.za[0] <= zi <= w.za[-1]: i = np.searchsorted(zr, zi) - assert zr[i] == zi # type: ignore[index] - assert fr[i] == fi * np.interp(zi, w.za, w.wa) # type: ignore[index] + assert zr[i] == zi + assert fr[i] == fi * np.interp(zi, w.za, w.wa) @pytest.mark.parametrize("method", ["lstsq", "nnls", "restrict"]) From 12ad51ad3da6aa6499f1a6c8ed20c29b9a612e50 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Wed, 9 Oct 2024 12:31:01 +0100 Subject: [PATCH 23/32] Fix mypy --- glass/core/algorithm.py | 6 +-- glass/core/array.py | 40 +++++++++---------- glass/fields.py | 75 +++++++++++++++++------------------ glass/galaxies.py | 76 ++++++++++++++++++------------------ glass/lensing.py | 38 +++++++++--------- glass/observations.py | 42 ++++++++++---------- glass/points.py | 51 +++++++++++++----------- glass/shapes.py | 36 ++++++++--------- glass/shells.py | 56 +++++++++++++------------- tests/core/test_algorithm.py | 2 +- tests/core/test_array.py | 56 +++++++++++++------------- tests/test_fields.py | 2 +- tests/test_galaxies.py | 38 +++++++++--------- tests/test_lensing.py | 20 +++++----- tests/test_shapes.py | 58 +++++++++++++-------------- tests/test_shells.py | 4 +- 16 files changed, 304 insertions(+), 296 deletions(-) diff --git a/glass/core/algorithm.py b/glass/core/algorithm.py index 437ce63a..9e83db27 100644 --- a/glass/core/algorithm.py +++ b/glass/core/algorithm.py @@ -11,12 +11,12 @@ def nnls( - a: npt.ArrayLike, - b: npt.ArrayLike, + a: npt.NDArray, # type: ignore[type-arg] + b: npt.NDArray, # type: ignore[type-arg] *, tol: float = 0.0, maxiter: int | None = None, -) -> npt.ArrayLike: +) -> npt.NDArray: # type: ignore[type-arg] """ Compute a non-negative least squares solution. diff --git a/glass/core/array.py b/glass/core/array.py index 940171a7..86ee5fec 100644 --- a/glass/core/array.py +++ b/glass/core/array.py @@ -8,15 +8,15 @@ import numpy.typing as npt -def broadcast_first(*arrays: npt.ArrayLike) -> tuple[npt.ArrayLike, ...]: +def broadcast_first(*arrays: npt.NDArray) -> tuple[npt.NDArray, ...]: # type: ignore[type-arg] """Broadcast arrays, treating the first axis as common.""" - arrays = tuple(np.moveaxis(a, 0, -1) if np.ndim(a) else a for a in arrays) # type: ignore[arg-type] + arrays = tuple(np.moveaxis(a, 0, -1) if np.ndim(a) else a for a in arrays) arrays = np.broadcast_arrays(*arrays) return tuple(np.moveaxis(a, -1, 0) if np.ndim(a) else a for a in arrays) def broadcast_leading_axes( - *args: tuple[npt.ArrayLike, int], + *args: tuple[npt.NDArray, int], # type: ignore[type-arg] ) -> tuple[tuple[int, ...], ...]: """ Broadcast all but the last N axes. @@ -55,14 +55,14 @@ def broadcast_leading_axes( def ndinterp( # noqa: PLR0913 - x: npt.ArrayLike, - xp: npt.ArrayLike, - fp: npt.ArrayLike, + x: npt.NDArray, # type: ignore[type-arg] + xp: npt.NDArray, # type: ignore[type-arg] + fp: npt.NDArray, # type: ignore[type-arg] axis: int = -1, left: float | None = None, right: float | None = None, period: float | None = None, -) -> npt.ArrayLike: +) -> npt.NDArray: # type: ignore[type-arg] """Interpolate multi-dimensional array over axis.""" return np.apply_along_axis( partial(np.interp, x, xp), @@ -75,33 +75,33 @@ def ndinterp( # noqa: PLR0913 def trapz_product( - f: tuple[npt.ArrayLike, npt.ArrayLike], - *ff: tuple[npt.ArrayLike, npt.ArrayLike], + f: tuple[npt.NDArray, npt.NDArray], # type: ignore[type-arg] + *ff: tuple[npt.NDArray, npt.NDArray], # type: ignore[type-arg] axis: int = -1, -) -> npt.ArrayLike: +) -> npt.NDArray: # type: ignore[type-arg] """Trapezoidal rule for a product of functions.""" x, _ = f for x_, _ in ff: x = np.union1d( - x[(x >= x_[0]) & (x <= x_[-1])], # type: ignore[index, operator] - x_[(x_ >= x[0]) & (x_ <= x[-1])], # type: ignore[index, operator] + x[(x >= x_[0]) & (x <= x_[-1])], + x_[(x_ >= x[0]) & (x_ <= x[-1])], ) - y = np.interp(x, *f) # type: ignore[arg-type] + y = np.interp(x, *f) for f_ in ff: - y *= np.interp(x, *f_) # type: ignore[arg-type] + y *= np.interp(x, *f_) return np.trapz(y, x, axis=axis) # type: ignore[attr-defined, no-any-return] def cumtrapz( - f: npt.ArrayLike, - x: npt.ArrayLike, + f: npt.NDArray, # type: ignore[type-arg] + x: npt.NDArray, # type: ignore[type-arg] dtype: np.dtype | None = None, # type: ignore[type-arg] - out: npt.ArrayLike | None = None, -) -> npt.ArrayLike: + out: npt.NDArray | None = None, # type: ignore[type-arg] +) -> npt.NDArray: # type: ignore[type-arg] """Cumulative trapezoidal rule along last axis.""" if out is None: out = np.empty_like(f, dtype=dtype) - np.cumsum((f[..., 1:] + f[..., :-1]) / 2 * np.diff(x), axis=-1, out=out[..., 1:]) # type: ignore[arg-type, call-overload, index, operator] - out[..., 0] = 0 # type: ignore[index] + np.cumsum((f[..., 1:] + f[..., :-1]) / 2 * np.diff(x), axis=-1, out=out[..., 1:]) + out[..., 0] = 0 return out diff --git a/glass/fields.py b/glass/fields.py index 3daa18d8..fccfe74e 100644 --- a/glass/fields.py +++ b/glass/fields.py @@ -37,15 +37,15 @@ # types Size = Optional[Union[int, tuple[int, ...]]] -Iternorm = tuple[Optional[int], npt.ArrayLike, npt.ArrayLike] -ClTransform = Union[str, Callable[[npt.ArrayLike], npt.ArrayLike]] -Cls = Sequence[Union[npt.ArrayLike, Sequence[float]]] -Alms = npt.ArrayLike +Iternorm = tuple[Optional[int], npt.NDArray, npt.NDArray] # type: ignore[type-arg] +ClTransform = Union[str, Callable[[npt.NDArray], npt.NDArray]] # type: ignore[type-arg] +Cls = Sequence[Union[npt.NDArray, Sequence[float]]] # type: ignore[type-arg] +Alms = npt.NDArray # type: ignore[type-arg] def iternorm( k: int, - cov: Iterable[npt.ArrayLike], + cov: Iterable[npt.NDArray], # type: ignore[type-arg] size: Size = None, ) -> Generator[Iternorm, None, None]: """Return the vector a and variance sigma^2 for iterative normal sampling.""" @@ -105,9 +105,7 @@ def iternorm( yield j, a, s -def cls2cov( - cls: Cls, nl: int, nf: int, nc: int -) -> Generator[npt.ArrayLike, None, None]: +def cls2cov(cls: Cls, nl: int, nf: int, nc: int) -> Generator[npt.NDArray, None, None]: # type: ignore[type-arg] """Return array of cls as a covariance matrix for iterative sampling.""" cov = np.zeros((nl, nc + 1)) end = 0 @@ -120,19 +118,19 @@ def cls2cov( if i == 0 and np.any(np.less(cl, 0)): msg = "negative values in cl" raise ValueError(msg) - n = len(cl) # type: ignore[arg-type] + n = len(cl) cov[:n, i] = cl cov[n:, i] = 0 cov /= 2 yield cov -def multalm(alm: Alms, bl: npt.ArrayLike, *, inplace: bool = False) -> Alms: +def multalm(alm: Alms, bl: npt.NDArray, *, inplace: bool = False) -> Alms: # type: ignore[type-arg] """Multiply alm by bl.""" - n = len(bl) # type: ignore[arg-type] + n = len(bl) out = np.asanyarray(alm) if inplace else np.copy(alm) for m in range(n): - out[m * n - m * (m - 1) // 2 : (m + 1) * n - m * (m + 1) // 2] *= bl[m:] # type: ignore[index] + out[m * n - m * (m - 1) // 2 : (m + 1) * n - m * (m + 1) // 2] *= bl[m:] return out @@ -140,8 +138,8 @@ def transform_cls(cls: Cls, tfm: ClTransform, pars: tuple[Any, ...] = ()) -> Cls """Transform Cls to Gaussian Cls.""" gls = [] for cl in cls: - if cl is not None and len(cl) > 0: # type: ignore[arg-type, redundant-expr] - monopole = 0.0 if cl[0] == 0 else None # type: ignore[index] + if cl is not None and len(cl) > 0: # type: ignore[redundant-expr] + monopole = 0.0 if cl[0] == 0 else None gl, info, _, _ = gaussiancl(cl, tfm, pars, monopole=monopole) if info == 0: warnings.warn( @@ -185,12 +183,12 @@ def gaussian_gls( gls = [] for cl in cls: - if cl is not None and len(cl) > 0: # type: ignore[arg-type, redundant-expr] + if cl is not None and len(cl) > 0: # type: ignore[redundant-expr] if lmax is not None: - cl = cl[: lmax + 1] # type: ignore[index] # noqa: PLW2901 + cl = cl[: lmax + 1] # noqa: PLW2901 if nside is not None: - n = min(len(cl), len(pw)) # type: ignore[arg-type] - cl = cl[:n] * pw[:n] ** 2 # type: ignore[index] # noqa: PLW2901 + n = min(len(cl), len(pw)) + cl = cl[:n] * pw[:n] ** 2 # noqa: PLW2901 gls.append(cl) return gls @@ -214,7 +212,7 @@ def generate_gaussian( *, ncorr: int | None = None, rng: np.random.Generator | None = None, -) -> Generator[npt.ArrayLike, None, None]: +) -> Generator[npt.NDArray, None, None]: # type: ignore[type-arg] """ Sample Gaussian random fields from Cls iteratively. @@ -251,7 +249,7 @@ def generate_gaussian( ncorr = ngrf - 1 # number of modes - n = max((len(gl) for gl in gls if gl is not None), default=0) # type: ignore[arg-type, redundant-expr] + n = max((len(gl) for gl in gls if gl is not None), default=0) # type: ignore[redundant-expr] if n == 0: msg = "all gls are empty" raise ValueError(msg) @@ -278,15 +276,15 @@ def generate_gaussian( # add the mean of the conditional distribution for i in range(ncorr): - alm += multalm(y[:, i], a[:, i]) # type: ignore[call-overload, index, operator] + alm += multalm(y[:, i], a[:, i]) # store the standard normal in y array at the indicated index if j is not None: y[:, j] = z # modes with m = 0 are real-valued and come first in array - alm[:n].real += alm[:n].imag # type: ignore[index, misc, union-attr] - alm[:n].imag[:] = 0 # type: ignore[index, union-attr] + alm[:n].real += alm[:n].imag + alm[:n].imag[:] = 0 # transform alm to maps # can be performed in place on the temporary alm array @@ -300,31 +298,34 @@ def generate_lognormal( *, ncorr: int | None = None, rng: np.random.Generator | None = None, -) -> Generator[npt.ArrayLike, None, None]: +) -> Generator[npt.NDArray, None, None]: # type: ignore[type-arg] """Sample lognormal random fields from Gaussian Cls iteratively.""" for i, m in enumerate(generate_gaussian(gls, nside, ncorr=ncorr, rng=rng)): # compute the variance of the auto-correlation gl = gls[i * (i + 1) // 2] - ell = np.arange(len(gl)) # type: ignore[arg-type] - var = np.sum((2 * ell + 1) * gl) / (4 * np.pi) # type: ignore[operator] + ell = np.arange(len(gl)) + var = np.sum((2 * ell + 1) * gl) / (4 * np.pi) # fix mean of the Gaussian random field for lognormal transformation m -= var / 2 # noqa: PLW2901 # exponentiate values in place and subtract 1 in one operation - np.expm1(m, out=m) # type: ignore[call-overload] + np.expm1(m, out=m) # lognormal shift, unless unity if shift != 1: - m *= shift # type: ignore[operator] # noqa: PLW2901 + m *= shift # noqa: PLW2901 # yield the lognormal map yield m def getcl( - cls: list[npt.ArrayLike], i: int, j: int, lmax: int | None = None -) -> npt.ArrayLike: + cls: list[npt.NDArray], # type: ignore[type-arg] + i: int, + j: int, + lmax: int | None = None, +) -> npt.NDArray: # type: ignore[type-arg] """ Return a specific angular power spectrum from an array. @@ -350,17 +351,17 @@ def getcl( i, j = j, i cl = cls[i * (i + 1) // 2 + i - j] if lmax is not None: - if len(cl) > lmax + 1: # type: ignore[arg-type] - cl = cl[: lmax + 1] # type: ignore[index] + if len(cl) > lmax + 1: + cl = cl[: lmax + 1] else: - cl = np.pad(cl, (0, lmax + 1 - len(cl))) # type: ignore[arg-type] + cl = np.pad(cl, (0, lmax + 1 - len(cl))) return cl def effective_cls( - cls: list[npt.ArrayLike], - weights1: npt.ArrayLike, - weights2: npt.ArrayLike | None = None, + cls: list[npt.NDArray], # type: ignore[type-arg] + weights1: npt.NDArray, # type: ignore[type-arg] + weights2: npt.NDArray | None = None, # type: ignore[type-arg] *, lmax: int | None = None, ) -> npt.NDArray[np.float64]: @@ -401,7 +402,7 @@ def effective_cls( # find lmax if not given if lmax is None: - lmax = max(map(len, cls), default=0) - 1 # type: ignore[arg-type] + lmax = max(map(len, cls), default=0) - 1 # broadcast weights1 such that its shape ends in n weights1 = np.asanyarray(weights1) diff --git a/glass/galaxies.py b/glass/galaxies.py index 6f45eded..3668e89e 100644 --- a/glass/galaxies.py +++ b/glass/galaxies.py @@ -34,11 +34,11 @@ def redshifts( - n: int | npt.ArrayLike, + n: int | npt.NDArray, # type: ignore[type-arg] w: RadialWindow, *, rng: np.random.Generator | None = None, -) -> npt.ArrayLike: +) -> npt.NDArray: # type: ignore[type-arg] """ Sample redshifts from a radial window function. @@ -61,13 +61,13 @@ def redshifts( Random redshifts following the radial window function. """ - return redshifts_from_nz(n, w.za, w.wa, rng=rng, warn=False) + return redshifts_from_nz(n, w.za, w.wa, rng=rng, warn=False) # type: ignore[arg-type] def redshifts_from_nz( - count: int | npt.ArrayLike, - z: npt.ArrayLike, - nz: npt.ArrayLike, + count: int | npt.NDArray, # type: ignore[type-arg] + z: npt.NDArray, # type: ignore[type-arg] + nz: npt.NDArray, # type: ignore[type-arg] *, rng: np.random.Generator | None = None, warn: bool = True, @@ -115,10 +115,10 @@ def redshifts_from_nz( rng = np.random.default_rng() # bring inputs' leading axes into common shape - dims, count, z, nz = broadcast_leading_axes((count, 0), (z, 1), (nz, 1)) + dims, count, z, nz = broadcast_leading_axes((count, 0), (z, 1), (nz, 1)) # type: ignore[arg-type, assignment] # list of results for all dimensions - redshifts = np.empty(count.sum()) # type: ignore[attr-defined] + redshifts = np.empty(count.sum()) # type: ignore[union-attr] # keep track of the number of sampled redshifts total = 0 @@ -126,16 +126,16 @@ def redshifts_from_nz( # go through extra dimensions; also works if dims is empty for k in np.ndindex(dims): # compute the CDF of each galaxy population - cdf = cumtrapz(nz[k], z[k], dtype=float) # type: ignore[arg-type, call-overload] - cdf /= cdf[-1] # type: ignore[index, operator] + cdf = cumtrapz(nz[k], z[k], dtype=float) # type: ignore[arg-type] + cdf /= cdf[-1] # sample redshifts and store result - redshifts[total : total + count[k]] = np.interp( # type: ignore[call-overload] - rng.uniform(0, 1, size=count[k]), # type: ignore[call-overload] - cdf, # type: ignore[arg-type] - z[k], # type: ignore[call-overload] + redshifts[total : total + count[k]] = np.interp( # type: ignore[index] + rng.uniform(0, 1, size=count[k]), # type: ignore[index] + cdf, + z[k], ) - total += count[k] # type: ignore[call-overload] + total += count[k] # type: ignore[index] assert total == redshifts.size # noqa: S101 @@ -143,15 +143,15 @@ def redshifts_from_nz( def galaxy_shear( # noqa: PLR0913 - lon: npt.ArrayLike, - lat: npt.ArrayLike, - eps: npt.ArrayLike, - kappa: npt.ArrayLike, - gamma1: npt.ArrayLike, - gamma2: npt.ArrayLike, + lon: npt.NDArray, # type: ignore[type-arg] + lat: npt.NDArray, # type: ignore[type-arg] + eps: npt.NDArray, # type: ignore[type-arg] + kappa: npt.NDArray, # type: ignore[type-arg] + gamma1: npt.NDArray, # type: ignore[type-arg] + gamma2: npt.NDArray, # type: ignore[type-arg] *, reduced_shear: bool = True, -) -> npt.ArrayLike: +) -> npt.NDArray: # type: ignore[type-arg] """ Observed galaxy shears from weak lensing. @@ -187,17 +187,17 @@ def galaxy_shear( # noqa: PLR0913 # get the lensing maps at galaxy position for i in range(0, size, 10000): s = slice(i, i + 10000) - ipix = healpix.ang2pix(nside, lon[s], lat[s], lonlat=True) # type: ignore[index] - k[s] = kappa[ipix] # type: ignore[index] - g.real[s] = gamma1[ipix] # type: ignore[index] - g.imag[s] = gamma2[ipix] # type: ignore[index] + ipix = healpix.ang2pix(nside, lon[s], lat[s], lonlat=True) + k[s] = kappa[ipix] + g.real[s] = gamma1[ipix] + g.imag[s] = gamma2[ipix] if reduced_shear: # compute reduced shear in place g /= 1 - k # compute lensed ellipticities - g = (eps + g) / (1 + g.conj() * eps) # type: ignore[operator] + g = (eps + g) / (1 + g.conj() * eps) else: # simple sum of shears g += eps @@ -206,13 +206,13 @@ def galaxy_shear( # noqa: PLR0913 def gaussian_phz( - z: npt.ArrayLike, - sigma_0: float | npt.ArrayLike, + z: npt.NDArray, # type: ignore[type-arg] + sigma_0: float | npt.NDArray, # type: ignore[type-arg] *, - lower: npt.ArrayLike | None = None, - upper: npt.ArrayLike | None = None, + lower: npt.NDArray | None = None, # type: ignore[type-arg] + upper: npt.NDArray | None = None, # type: ignore[type-arg] rng: np.random.Generator | None = None, -) -> npt.ArrayLike: +) -> npt.NDArray: # type: ignore[type-arg] r""" Photometric redshifts assuming a Gaussian error. @@ -266,12 +266,12 @@ def gaussian_phz( sigma = np.add(1, z) * sigma_0 dims = np.shape(sigma) - zphot = rng.normal(z, sigma) # type: ignore[arg-type] + zphot = rng.normal(z, sigma) if lower is None: - lower = 0.0 + lower = 0.0 # type: ignore[assignment] if upper is None: - upper = np.inf + upper = np.inf # type: ignore[assignment] if not np.all(lower < upper): # type: ignore[operator] msg = "requires lower < upper" @@ -279,13 +279,13 @@ def gaussian_phz( if not dims: while zphot < lower or zphot > upper: # type: ignore[operator] - zphot = rng.normal(z, sigma) # type: ignore[arg-type] + zphot = rng.normal(z, sigma) else: z = np.broadcast_to(z, dims) trunc = np.where((zphot < lower) | (zphot > upper))[0] # type: ignore[operator] while trunc.size: - znew = rng.normal(z[trunc], sigma[trunc]) # type: ignore[arg-type] - zphot[trunc] = znew # type: ignore[index] + znew = rng.normal(z[trunc], sigma[trunc]) + zphot[trunc] = znew trunc = trunc[(znew < lower) | (znew > upper)] # type: ignore[operator] return zphot diff --git a/glass/lensing.py b/glass/lensing.py index 4ec0373d..d1c76be6 100644 --- a/glass/lensing.py +++ b/glass/lensing.py @@ -47,14 +47,14 @@ def from_convergence( # noqa: PLR0913 - kappa: npt.ArrayLike, + kappa: npt.NDArray, # type: ignore[type-arg] lmax: int | None = None, *, potential: bool = False, deflection: bool = False, shear: bool = False, discretized: bool = True, -) -> tuple[npt.ArrayLike, ...]: +) -> tuple[npt.NDArray, ...]: # type: ignore[type-arg] r""" Compute other weak lensing maps from the convergence. @@ -226,11 +226,11 @@ def from_convergence( # noqa: PLR0913 def shear_from_convergence( - kappa: npt.ArrayLike, + kappa: npt.NDArray, # type: ignore[type-arg] lmax: int | None = None, *, discretized: bool = True, -) -> npt.ArrayLike: +) -> npt.NDArray: # type: ignore[type-arg] r""" Weak lensing shear from convergence. @@ -282,11 +282,11 @@ def __init__(self, cosmo: Cosmology) -> None: self.x3: float = 0.0 self.w3: float = 0.0 self.r23: float = 1.0 - self.delta3: npt.ArrayLike = np.array(0.0) - self.kappa2: npt.ArrayLike | None = None - self.kappa3: npt.ArrayLike | None = None + self.delta3: npt.NDArray = np.array(0.0) # type: ignore[type-arg] + self.kappa2: npt.NDArray | None = None # type: ignore[type-arg] + self.kappa3: npt.NDArray | None = None # type: ignore[type-arg] - def add_window(self, delta: npt.ArrayLike, w: RadialWindow) -> None: + def add_window(self, delta: npt.NDArray, w: RadialWindow) -> None: # type: ignore[type-arg] """ Add a mass plane from a window function to the convergence. @@ -299,7 +299,7 @@ def add_window(self, delta: npt.ArrayLike, w: RadialWindow) -> None: self.add_plane(delta, zsrc, lens_weight) # type: ignore[arg-type] - def add_plane(self, delta: npt.ArrayLike, zsrc: float, wlens: float = 1.0) -> None: + def add_plane(self, delta: npt.NDArray, zsrc: float, wlens: float = 1.0) -> None: # type: ignore[type-arg] """Add a mass plane at redshift ``zsrc`` to the convergence.""" if zsrc <= self.z3: msg = "source redshift must be increasing" @@ -348,12 +348,12 @@ def zsrc(self) -> float: return self.z3 @property - def kappa(self) -> npt.ArrayLike | None: + def kappa(self) -> npt.NDArray | None: # type: ignore[type-arg] """The current convergence plane.""" return self.kappa3 @property - def delta(self) -> npt.ArrayLike: + def delta(self) -> npt.NDArray: # type: ignore[type-arg] """The current matter plane.""" return self.delta3 @@ -366,7 +366,7 @@ def wlens(self) -> float: def multi_plane_matrix( shells: Sequence[RadialWindow], cosmo: Cosmology, -) -> npt.ArrayLike: +) -> npt.NDArray: # type: ignore[type-arg] """Compute the matrix of lensing contributions from each shell.""" mpc = MultiPlaneConvergence(cosmo) wmat = np.eye(len(shells)) @@ -377,10 +377,10 @@ def multi_plane_matrix( def multi_plane_weights( - weights: npt.ArrayLike, + weights: npt.NDArray, # type: ignore[type-arg] shells: Sequence[RadialWindow], cosmo: Cosmology, -) -> npt.ArrayLike: +) -> npt.NDArray: # type: ignore[type-arg] """ Compute effective weights for multi-plane convergence. @@ -416,12 +416,14 @@ def multi_plane_weights( weights = weights / np.sum(weights, axis=0) # combine weights and the matrix of lensing contributions mat = multi_plane_matrix(shells, cosmo) - return np.matmul(mat.T, weights) # type: ignore[no-any-return, union-attr] + return np.matmul(mat.T, weights) # type: ignore[no-any-return] def deflect( - lon: npt.ArrayLike, lat: npt.ArrayLike, alpha: npt.ArrayLike -) -> npt.ArrayLike: + lon: npt.NDArray, # type: ignore[type-arg] + lat: npt.NDArray, # type: ignore[type-arg] + alpha: npt.NDArray, # type: ignore[type-arg] +) -> npt.NDArray: # type: ignore[type-arg] r""" Apply deflections to positions. @@ -476,4 +478,4 @@ def deflect( d = np.arctan2(sa * sg, st * ca - ct * sa * cg) - return lon - np.degrees(d), np.degrees(tp) + return lon - np.degrees(d), np.degrees(tp) # type: ignore[return-value] diff --git a/glass/observations.py b/glass/observations.py index b0ce4f23..7e14ec33 100644 --- a/glass/observations.py +++ b/glass/observations.py @@ -44,7 +44,7 @@ def vmap_galactic_ecliptic( nside: int, galactic: tuple[float, float] = (30, 90), ecliptic: tuple[float, float] = (20, 80), -) -> npt.ArrayLike: +) -> npt.NDArray: # type: ignore[type-arg] """ Visibility map masking galactic and ecliptic plane. @@ -86,12 +86,12 @@ def vmap_galactic_ecliptic( def gaussian_nz( - z: npt.ArrayLike, - mean: npt.ArrayLike, - sigma: npt.ArrayLike, + z: npt.NDArray, # type: ignore[type-arg] + mean: npt.NDArray, # type: ignore[type-arg] + sigma: npt.NDArray, # type: ignore[type-arg] *, - norm: npt.ArrayLike | None = None, -) -> npt.ArrayLike: + norm: npt.NDArray | None = None, # type: ignore[type-arg] +) -> npt.NDArray: # type: ignore[type-arg] r""" Gaussian redshift distribution. @@ -131,13 +131,13 @@ def gaussian_nz( def smail_nz( - z: npt.ArrayLike, - z_mode: npt.ArrayLike, - alpha: npt.ArrayLike, - beta: npt.ArrayLike, + z: npt.NDArray, # type: ignore[type-arg] + z_mode: npt.NDArray, # type: ignore[type-arg] + alpha: npt.NDArray, # type: ignore[type-arg] + beta: npt.NDArray, # type: ignore[type-arg] *, - norm: float | npt.ArrayLike | None = None, -) -> npt.ArrayLike: + norm: float | npt.NDArray | None = None, # type: ignore[type-arg] +) -> npt.NDArray: # type: ignore[type-arg] r""" Redshift distribution following Smail et al. (1994). @@ -232,8 +232,8 @@ def fixed_zbins( def equal_dens_zbins( - z: npt.ArrayLike, - nz: npt.ArrayLike, + z: npt.NDArray, # type: ignore[type-arg] + nz: npt.NDArray, # type: ignore[type-arg] nbins: int, ) -> list[tuple[float, float]]: """ @@ -260,18 +260,18 @@ def equal_dens_zbins( # then normalise: the first z is at CDF = 0, the last z at CDF = 1 # interpolate to find the z values at CDF = i/nbins for i = 0, ..., nbins cuml_nz = cumtrapz(nz, z) - cuml_nz /= cuml_nz[[-1]] # type: ignore[index, operator] - zbinedges = np.interp(np.linspace(0, 1, nbins + 1), cuml_nz, z) # type: ignore[arg-type] + cuml_nz /= cuml_nz[[-1]] + zbinedges = np.interp(np.linspace(0, 1, nbins + 1), cuml_nz, z) return list(zip(zbinedges, zbinedges[1:])) def tomo_nz_gausserr( - z: npt.ArrayLike, - nz: npt.ArrayLike, + z: npt.NDArray, # type: ignore[type-arg] + nz: npt.NDArray, # type: ignore[type-arg] sigma_0: float, zbins: list[tuple[float, float]], -) -> npt.ArrayLike: +) -> npt.NDArray: # type: ignore[type-arg] """ Tomographic redshift bins with a Gaussian redshift error. @@ -323,10 +323,10 @@ def tomo_nz_gausserr( # compute the probabilities that redshifts z end up in each bin # then apply probability as weights to given nz # leading axis corresponds to the different bins - sz = 2**0.5 * sigma_0 * (1 + z) # type: ignore[operator] + sz = 2**0.5 * sigma_0 * (1 + z) binned_nz = erf((z - z_lower) / sz) binned_nz -= erf((z - z_upper) / sz) - binned_nz /= 1 + erf(z / sz) # type: ignore[operator] + binned_nz /= 1 + erf(z / sz) binned_nz *= nz return binned_nz # type: ignore[no-any-return] diff --git a/glass/points.py b/glass/points.py index 1f5e66d0..fcb97318 100644 --- a/glass/points.py +++ b/glass/points.py @@ -46,8 +46,10 @@ def effective_bias( - z: npt.ArrayLike, bz: npt.ArrayLike, w: RadialWindow -) -> npt.ArrayLike: + z: npt.NDArray, # type: ignore[type-arg] + bz: npt.NDArray, # type: ignore[type-arg] + w: RadialWindow, +) -> npt.NDArray: # type: ignore[type-arg] r""" Effective bias parameter from a redshift-dependent bias function. @@ -79,35 +81,36 @@ def effective_bias( """ norm = np.trapz(w.wa, w.za) # type: ignore[attr-defined] - return trapz_product((z, bz), (w.za, w.wa)) / norm # type: ignore[no-any-return] + return trapz_product((z, bz), (w.za, w.wa)) / norm # type: ignore[arg-type, no-any-return] -def linear_bias(delta: npt.ArrayLike, b: float | npt.ArrayLike) -> npt.NDArray[float]: # type: ignore[type-var] +def linear_bias(delta: npt.NDArray, b: float | npt.NDArray) -> npt.NDArray[float]: # type: ignore[type-arg, type-var] r"""Linear bias model :math:`\\delta_g = b \\, \\delta`.""" - return b * delta # type: ignore[operator, return-value] + return b * delta # type: ignore[return-value] def loglinear_bias( - delta: npt.ArrayLike, b: float | npt.ArrayLike + delta: npt.NDArray, # type: ignore[type-arg] + b: float | npt.NDArray, # type: ignore[type-arg] ) -> npt.NDArray[float]: r"""log-linear bias model :math:`\\ln(1 + \\delta_g) = b \\ln(1 + \\delta)`.""" delta_g = np.log1p(delta) delta_g *= b np.expm1(delta_g, out=delta_g) - return delta_g + return delta_g # type: ignore[no-any-return] def positions_from_delta( # noqa: PLR0912, PLR0913, PLR0915 - ngal: float | npt.ArrayLike, - delta: npt.ArrayLike, - bias: float | npt.ArrayLike | None = None, - vis: npt.ArrayLike | None = None, + ngal: float | npt.NDArray, # type: ignore[type-arg] + delta: npt.NDArray, # type: ignore[type-arg] + bias: float | npt.NDArray | None = None, # type: ignore[type-arg] + vis: npt.NDArray | None = None, # type: ignore[type-arg] *, bias_model: str | typing.Callable[..., typing.Any] = "linear", remove_monopole: bool = False, batch: int | None = 1_000_000, rng: np.random.Generator | None = None, -) -> typing.Iterator[tuple[npt.ArrayLike, npt.ArrayLike, npt.ArrayLike]]: +) -> typing.Iterator[tuple[npt.NDArray, npt.NDArray, npt.NDArray]]: # type: ignore[type-arg] """ Generate positions tracing a density contrast. @@ -181,16 +184,16 @@ def positions_from_delta( # noqa: PLR0912, PLR0913, PLR0915 inputs += [(bias, 0)] if vis is not None: inputs += [(vis, 1)] - dims, ngal, delta, *rest = broadcast_leading_axes(*inputs) + dims, ngal, delta, *rest = broadcast_leading_axes(*inputs) # type: ignore[arg-type, assignment] if bias is not None: - bias, *rest = rest + bias, *rest = rest # type: ignore[assignment] if vis is not None: - vis, *rest = rest + vis, *rest = rest # type: ignore[assignment] # iterate the leading dimensions for k in np.ndindex(dims): # compute density contrast from bias model, or copy - n = np.copy(delta[k]) if bias is None else bias_model(delta[k], bias[k]) # type: ignore[call-overload, operator] + n = np.copy(delta[k]) if bias is None else bias_model(delta[k], bias[k]) # type: ignore[index, operator] # remove monopole if asked to if remove_monopole: @@ -198,11 +201,11 @@ def positions_from_delta( # noqa: PLR0912, PLR0913, PLR0915 # turn into number count, modifying the array in place n += 1 - n *= ARCMIN2_SPHERE / n.size * ngal[k] # type: ignore[call-overload] + n *= ARCMIN2_SPHERE / n.size * ngal[k] # type: ignore[index] # apply visibility if given if vis is not None: - n *= vis[k] # type: ignore[call-overload] + n *= vis[k] # clip number density at zero np.clip(n, 0, None, out=n) @@ -259,10 +262,12 @@ def positions_from_delta( # noqa: PLR0912, PLR0913, PLR0915 def uniform_positions( - ngal: float | npt.ArrayLike, *, rng: np.random.Generator | None = None + ngal: float | npt.NDArray, # type: ignore[type-arg] + *, + rng: np.random.Generator | None = None, ) -> typing.Iterator[ # type: ignore[type-arg] - npt.ArrayLike | list[npt.ArrayLike], - npt.ArrayLike | list[npt.ArrayLike], + npt.NDArray | list[npt.NDArray], + npt.NDArray | list[npt.NDArray], int | list[int], ]: """ @@ -315,7 +320,7 @@ def uniform_positions( yield lon, lat, count -def position_weights(densities: npt.ArrayLike, bias: npt.ArrayLike | None = None): # type: ignore[no-untyped-def] +def position_weights(densities: npt.NDArray, bias: npt.NDArray | None = None): # type: ignore[no-untyped-def, type-arg] r""" Compute relative weights for angular clustering. @@ -348,6 +353,6 @@ def position_weights(densities: npt.ArrayLike, bias: npt.ArrayLike | None = None densities = densities / np.sum(densities, axis=0) # apply bias after normalisation if bias is not None: - densities = densities * bias # type: ignore[operator] + densities = densities * bias # densities now contains the relative contribution with bias applied return densities diff --git a/glass/shapes.py b/glass/shapes.py index 5f17665b..4072acdc 100644 --- a/glass/shapes.py +++ b/glass/shapes.py @@ -33,12 +33,12 @@ def triaxial_axis_ratio( - zeta: npt.ArrayLike, - xi: npt.ArrayLike, + zeta: npt.NDArray, # type: ignore[type-arg] + xi: npt.NDArray, # type: ignore[type-arg] size: tuple[int] | None = None, *, rng: np.random.Generator | None = None, -) -> npt.ArrayLike: +) -> npt.NDArray: # type: ignore[type-arg] r""" Axis ratio of a randomly projected triaxial ellipsoid. @@ -104,14 +104,14 @@ def triaxial_axis_ratio( def ellipticity_ryden04( # noqa: PLR0913 - mu: npt.ArrayLike, - sigma: npt.ArrayLike, - gamma: npt.ArrayLike, - sigma_gamma: npt.ArrayLike, + mu: npt.NDArray, # type: ignore[type-arg] + sigma: npt.NDArray, # type: ignore[type-arg] + gamma: npt.NDArray, # type: ignore[type-arg] + sigma_gamma: npt.NDArray, # type: ignore[type-arg] size: int | tuple[int, ...] | None = None, *, rng: np.random.Generator | None = None, -) -> npt.ArrayLike: +) -> npt.NDArray: # type: ignore[type-arg] r""" Ellipticity distribution following Ryden (2004). @@ -158,15 +158,15 @@ def ellipticity_ryden04( # noqa: PLR0913 # draw gamma and epsilon from truncated normal -- eq.s (10)-(11) # first sample unbounded normal, then rejection sample truncation - eps = rng.normal(mu, sigma, size=size) # type: ignore[arg-type] + eps = rng.normal(mu, sigma, size=size) bad = eps > 0 while np.any(bad): - eps[bad] = rng.normal(mu, sigma, size=size)[bad] # type: ignore[arg-type] + eps[bad] = rng.normal(mu, sigma, size=size)[bad] bad = eps > 0 - gam = rng.normal(gamma, sigma_gamma, size=size) # type: ignore[arg-type] + gam = rng.normal(gamma, sigma_gamma, size=size) bad = (gam < 0) | (gam > 1) while np.any(bad): - gam[bad] = rng.normal(gamma, sigma_gamma, size=size)[bad] # type: ignore[arg-type] + gam[bad] = rng.normal(gamma, sigma_gamma, size=size)[bad] bad = (gam < 0) | (gam > 1) # compute triaxial axis ratios zeta = B/A, xi = C/A @@ -178,18 +178,18 @@ def ellipticity_ryden04( # noqa: PLR0913 # assemble ellipticity with random complex phase e = np.exp(1j * rng.uniform(0, 2 * np.pi, size=np.shape(q))) - e *= (1 - q) / (1 + q) # type: ignore[operator] + e *= (1 - q) / (1 + q) # return the ellipticity return e # type: ignore[no-any-return] def ellipticity_gaussian( - count: int | npt.ArrayLike, - sigma: npt.ArrayLike, + count: int | npt.NDArray, # type: ignore[type-arg] + sigma: npt.NDArray, # type: ignore[type-arg] *, rng: np.random.Generator | None = None, -) -> npt.ArrayLike: +) -> npt.NDArray: # type: ignore[type-arg] r""" Sample Gaussian galaxy ellipticities. @@ -242,8 +242,8 @@ def ellipticity_gaussian( def ellipticity_intnorm( - count: int | npt.ArrayLike, - sigma: npt.ArrayLike, + count: int | npt.NDArray, # type: ignore[type-arg] + sigma: npt.NDArray, # type: ignore[type-arg] *, rng: np.random.Generator | None = None, ) -> npt.NDArray: # type: ignore[type-arg] diff --git a/glass/shells.py b/glass/shells.py index b6d2e70d..a8277d70 100644 --- a/glass/shells.py +++ b/glass/shells.py @@ -61,17 +61,17 @@ WeightFunc = Callable[[ArrayLike1D], npt.NDArray] # type: ignore[type-arg] -def distance_weight(z: npt.ArrayLike, cosmo: Cosmology) -> npt.NDArray: # type: ignore[type-arg] +def distance_weight(z: npt.NDArray, cosmo: Cosmology) -> npt.NDArray: # type: ignore[type-arg] """Uniform weight in comoving distance.""" return 1 / cosmo.ef(z) # type: ignore[no-any-return] -def volume_weight(z: npt.ArrayLike, cosmo: Cosmology) -> npt.NDArray: # type: ignore[type-arg] +def volume_weight(z: npt.NDArray, cosmo: Cosmology) -> npt.NDArray: # type: ignore[type-arg] """Uniform weight in comoving volume.""" return cosmo.xm(z) ** 2 / cosmo.ef(z) # type: ignore[no-any-return] -def density_weight(z: npt.ArrayLike, cosmo: Cosmology) -> npt.NDArray: # type: ignore[type-arg] +def density_weight(z: npt.NDArray, cosmo: Cosmology) -> npt.NDArray: # type: ignore[type-arg] """Uniform weight in matter density.""" return cosmo.rho_m_z(z) * cosmo.xm(z) ** 2 / cosmo.ef(z) # type: ignore[no-any-return] @@ -179,7 +179,7 @@ def tophat_windows( n = max(round((zmax - zmin) / dz), 2) z = np.linspace(zmin, zmax, n) w = wht(z) - zeff = np.trapz(w * z, z) / np.trapz(w, z) + zeff = np.trapz(w * z, z) / np.trapz(w, z) # type: ignore[attr-defined] ws.append(RadialWindow(z, w, zeff)) # type: ignore[arg-type] return ws @@ -344,17 +344,17 @@ def restrict( """ z_ = np.compress(np.greater(z, w.za[0]) & np.less(z, w.za[-1]), z) zr = np.union1d(w.za, z_) - fr = ndinterp(zr, z, f, left=0.0, right=0.0) * ndinterp(zr, w.za, w.wa) # type: ignore[operator] - return zr, fr # type: ignore[return-value] + fr = ndinterp(zr, z, f, left=0.0, right=0.0) * ndinterp(zr, w.za, w.wa) # type: ignore[arg-type] + return zr, fr def partition( - z: npt.ArrayLike, - fz: npt.ArrayLike, + z: npt.NDArray, # type: ignore[type-arg] + fz: npt.NDArray, # type: ignore[type-arg] shells: Sequence[RadialWindow], *, method: str = "nnls", -) -> npt.ArrayLike: +) -> npt.NDArray: # type: ignore[type-arg] r""" Partition a function by a sequence of windows. @@ -459,12 +459,12 @@ def partition( def partition_lstsq( - z: npt.ArrayLike, - fz: npt.ArrayLike, + z: npt.NDArray, # type: ignore[type-arg] + fz: npt.NDArray, # type: ignore[type-arg] shells: Sequence[RadialWindow], *, sumtol: float = 0.01, -) -> npt.ArrayLike: +) -> npt.NDArray: # type: ignore[type-arg] """Least-squares partition.""" # make sure nothing breaks sumtol = max(sumtol, 1e-4) @@ -481,7 +481,7 @@ def partition_lstsq( dz = np.gradient(zp) # create the window function matrix - a = [np.interp(zp, za, wa, left=0.0, right=0.0) for za, wa, _ in shells] # type: ignore[arg-type] + a = [np.interp(zp, za, wa, left=0.0, right=0.0) for za, wa, _ in shells] a /= np.trapz(a, zp, axis=-1)[..., None] # type: ignore[attr-defined] a = a * dz @@ -498,19 +498,19 @@ def partition_lstsq( # and b is a matrix of shape (*dims, len(zp) + 1) # need to find weights x such that b == x @ a over all axes of b # do the least-squares fit over partially flattened b, then reshape - x = np.linalg.lstsq(a.T, b.reshape(-1, zp.size + 1).T, rcond=None)[0] # type: ignore[attr-defined, union-attr] + x = np.linalg.lstsq(a.T, b.reshape(-1, zp.size + 1).T, rcond=None)[0] # type: ignore[attr-defined] x = x.T.reshape(*dims, len(shells)) # roll the last axis of size len(shells) to the front return np.moveaxis(x, -1, 0) def partition_nnls( - z: npt.ArrayLike, - fz: npt.ArrayLike, + z: npt.NDArray, # type: ignore[type-arg] + fz: npt.NDArray, # type: ignore[type-arg] shells: Sequence[RadialWindow], *, sumtol: float = 0.01, -) -> npt.ArrayLike: +) -> npt.NDArray: # type: ignore[type-arg] """ Non-negative least-squares partition. @@ -535,7 +535,7 @@ def partition_nnls( dz = np.gradient(zp) # create the window function matrix - a = [np.interp(zp, za, wa, left=0.0, right=0.0) for za, wa, _ in shells] # type: ignore[arg-type] + a = [np.interp(zp, za, wa, left=0.0, right=0.0) for za, wa, _ in shells] a /= np.trapz(a, zp, axis=-1)[..., None] # type: ignore[attr-defined] a = a * dz @@ -566,14 +566,14 @@ def partition_nnls( def partition_restrict( - z: npt.ArrayLike, - fz: npt.ArrayLike, + z: npt.NDArray, # type: ignore[type-arg] + fz: npt.NDArray, # type: ignore[type-arg] shells: Sequence[RadialWindow], -) -> npt.ArrayLike: +) -> npt.NDArray: # type: ignore[type-arg] """Partition by restriction and integration.""" part = np.empty((len(shells),) + np.shape(fz)[:-1]) for i, w in enumerate(shells): - zr, fr = restrict(z, fz, w) # type: ignore[arg-type] + zr, fr = restrict(z, fz, w) part[i] = np.trapz(fr, zr, axis=-1) # type: ignore[attr-defined] return part @@ -613,10 +613,10 @@ def distance_grid( def combine( - z: npt.ArrayLike, - weights: npt.ArrayLike, + z: npt.NDArray, # type: ignore[type-arg] + weights: npt.NDArray, # type: ignore[type-arg] shells: Sequence[RadialWindow], -) -> npt.ArrayLike: +) -> npt.NDArray: # type: ignore[type-arg] r""" Evaluate a linear combination of window functions. @@ -648,14 +648,14 @@ def combine( partition : Find weights for a given function. """ - return sum( + return sum( # type: ignore[return-value] np.expand_dims(weight, -1) * np.interp( - z, # type: ignore[arg-type] + z, shell.za, shell.wa / np.trapz(shell.wa, shell.za), # type: ignore[attr-defined] left=0.0, right=0.0, ) - for shell, weight in zip(shells, weights) # type: ignore[arg-type] + for shell, weight in zip(shells, weights) ) diff --git a/tests/core/test_algorithm.py b/tests/core/test_algorithm.py index 450eaa85..11179edf 100644 --- a/tests/core/test_algorithm.py +++ b/tests/core/test_algorithm.py @@ -21,7 +21,7 @@ def test_nnls(rng) -> None: # type: ignore[no-untyped-def] x_glass = nnls_glass(a, b) x_scipy, _ = nnls_scipy(a, b) - np.testing.assert_allclose(x_glass, x_scipy) # type: ignore[arg-type] + np.testing.assert_allclose(x_glass, x_scipy) # check matrix and vector's shape diff --git a/tests/core/test_array.py b/tests/core/test_array.py index 98e74505..f023a3f5 100644 --- a/tests/core/test_array.py +++ b/tests/core/test_array.py @@ -22,8 +22,8 @@ def test_broadcast_first() -> None: # arrays with shape ((3, 4, 2)) and ((1, 2)) are passed # to np.broadcast_arrays; hence it works a_a, b_a = broadcast_first(a, b) - assert a_a.shape == (2, 3, 4) # type: ignore[union-attr] - assert b_a.shape == (2, 3, 4) # type: ignore[union-attr] + assert a_a.shape == (2, 3, 4) + assert b_a.shape == (2, 3, 4) # plain np.broadcast_arrays will not work with pytest.raises(ValueError, match="shape mismatch"): @@ -49,7 +49,7 @@ def test_broadcast_leading_axes() -> None: b = np.zeros((4, 10)) c = np.zeros((3, 1, 5, 6)) - dims, a, b, c = broadcast_leading_axes((a, 0), (b, 1), (c, 2)) # type: ignore[assignment] + dims, a, b, c = broadcast_leading_axes((a, 0), (b, 1), (c, 2)) # type: ignore[arg-type, assignment] assert dims == (3, 4) assert a.shape == (3, 4) # type: ignore[attr-defined] @@ -64,39 +64,39 @@ def test_ndinterp() -> None: yp = [1.1, 1.2, 1.3, 1.4, 1.5] x = 0.5 - y = ndinterp(x, xp, yp) + y = ndinterp(x, xp, yp) # type: ignore[arg-type] assert np.shape(y) == () - np.testing.assert_allclose(y, 1.15, atol=1e-15) # type: ignore[arg-type] + np.testing.assert_allclose(y, 1.15, atol=1e-15) x = [0.5, 1.5, 2.5] # type: ignore[assignment] - y = ndinterp(x, xp, yp) + y = ndinterp(x, xp, yp) # type: ignore[arg-type] assert np.shape(y) == (3,) - np.testing.assert_allclose(y, [1.15, 1.25, 1.35], atol=1e-15) # type: ignore[arg-type] + np.testing.assert_allclose(y, [1.15, 1.25, 1.35], atol=1e-15) x = [[0.5, 1.5], [2.5, 3.5]] # type: ignore[assignment] - y = ndinterp(x, xp, yp) + y = ndinterp(x, xp, yp) # type: ignore[arg-type] assert np.shape(y) == (2, 2) - np.testing.assert_allclose(y, [[1.15, 1.25], [1.35, 1.45]], atol=1e-15) # type: ignore[arg-type] + np.testing.assert_allclose(y, [[1.15, 1.25], [1.35, 1.45]], atol=1e-15) # test nd interpolation in final axis yp = [[1.1, 1.2, 1.3, 1.4, 1.5], [2.1, 2.2, 2.3, 2.4, 2.5]] # type: ignore[list-item] x = 0.5 - y = ndinterp(x, xp, yp) + y = ndinterp(x, xp, yp) # type: ignore[arg-type] assert np.shape(y) == (2,) - np.testing.assert_allclose(y, [1.15, 2.15], atol=1e-15) # type: ignore[arg-type] + np.testing.assert_allclose(y, [1.15, 2.15], atol=1e-15) x = [0.5, 1.5, 2.5] # type: ignore[assignment] - y = ndinterp(x, xp, yp) + y = ndinterp(x, xp, yp) # type: ignore[arg-type] assert np.shape(y) == (2, 3) - np.testing.assert_allclose(y, [[1.15, 1.25, 1.35], [2.15, 2.25, 2.35]], atol=1e-15) # type: ignore[arg-type] + np.testing.assert_allclose(y, [[1.15, 1.25, 1.35], [2.15, 2.25, 2.35]], atol=1e-15) x = [[0.5, 1.5], [2.5, 3.5]] # type: ignore[assignment] - y = ndinterp(x, xp, yp) + y = ndinterp(x, xp, yp) # type: ignore[arg-type] assert np.shape(y) == (2, 2, 2) np.testing.assert_allclose( - y, # type: ignore[arg-type] + y, [[[1.15, 1.25], [1.35, 1.45]], [[2.15, 2.25], [2.35, 2.45]]], atol=1e-15, ) @@ -106,24 +106,24 @@ def test_ndinterp() -> None: yp = [[[1.1], [1.2], [1.3], [1.4], [1.5]], [[2.1], [2.2], [2.3], [2.4], [2.5]]] # type: ignore[list-item] x = 0.5 - y = ndinterp(x, xp, yp, axis=1) + y = ndinterp(x, xp, yp, axis=1) # type: ignore[arg-type] assert np.shape(y) == (2, 1) - np.testing.assert_allclose(y, [[1.15], [2.15]], atol=1e-15) # type: ignore[arg-type] + np.testing.assert_allclose(y, [[1.15], [2.15]], atol=1e-15) x = [0.5, 1.5, 2.5] # type: ignore[assignment] - y = ndinterp(x, xp, yp, axis=1) + y = ndinterp(x, xp, yp, axis=1) # type: ignore[arg-type] assert np.shape(y) == (2, 3, 1) np.testing.assert_allclose( - y, # type: ignore[arg-type] + y, [[[1.15], [1.25], [1.35]], [[2.15], [2.25], [2.35]]], atol=1e-15, ) x = [[0.5, 1.5, 2.5, 3.5], [3.5, 2.5, 1.5, 0.5], [0.5, 3.5, 1.5, 2.5]] # type: ignore[assignment] - y = ndinterp(x, xp, yp, axis=1) + y = ndinterp(x, xp, yp, axis=1) # type: ignore[arg-type] assert np.shape(y) == (2, 3, 4, 1) np.testing.assert_allclose( - y, # type: ignore[arg-type] + y, [ [ [[1.15], [1.25], [1.35], [1.45]], @@ -149,7 +149,7 @@ def test_trapz_product() -> None: s = trapz_product((x1, f1), (x2, f2)) - np.testing.assert_allclose(s, 1.0) # type: ignore[arg-type] + np.testing.assert_allclose(s, 1.0) @pytest.mark.skipif(not HAVE_SCIPY, reason="test requires SciPy") @@ -164,19 +164,19 @@ def test_cumtrapz() -> None: # default dtype (int - not supported by scipy) glass_ct = cumtrapz(f, x) - np.testing.assert_allclose(glass_ct, np.array([0, 1, 4, 7])) # type: ignore[arg-type] + np.testing.assert_allclose(glass_ct, np.array([0, 1, 4, 7])) # explicit dtype (float) glass_ct = cumtrapz(f, x, dtype=float) # type: ignore[arg-type] scipy_ct = cumulative_trapezoid(f, x, initial=0) - np.testing.assert_allclose(glass_ct, scipy_ct) # type: ignore[arg-type] + np.testing.assert_allclose(glass_ct, scipy_ct) # explicit return array result = cumtrapz(f, x, dtype=float, out=np.zeros((4,))) # type: ignore[arg-type] scipy_ct = cumulative_trapezoid(f, x, initial=0) - np.testing.assert_allclose(result, scipy_ct) # type: ignore[arg-type] + np.testing.assert_allclose(result, scipy_ct) # 2D f and 1D x @@ -186,16 +186,16 @@ def test_cumtrapz() -> None: # default dtype (int - not supported by scipy) glass_ct = cumtrapz(f, x) - np.testing.assert_allclose(glass_ct, np.array([[0, 2, 12, 31], [0, 2, 8, 17]])) # type: ignore[arg-type] + np.testing.assert_allclose(glass_ct, np.array([[0, 2, 12, 31], [0, 2, 8, 17]])) # explicit dtype (float) glass_ct = cumtrapz(f, x, dtype=float) # type: ignore[arg-type] scipy_ct = cumulative_trapezoid(f, x, initial=0) - np.testing.assert_allclose(glass_ct, scipy_ct) # type: ignore[arg-type] + np.testing.assert_allclose(glass_ct, scipy_ct) # explicit return array glass_ct = cumtrapz(f, x, dtype=float, out=np.zeros((2, 4))) # type: ignore[arg-type] scipy_ct = cumulative_trapezoid(f, x, initial=0) - np.testing.assert_allclose(glass_ct, scipy_ct) # type: ignore[arg-type] + np.testing.assert_allclose(glass_ct, scipy_ct) diff --git a/tests/test_fields.py b/tests/test_fields.py index c246a99d..c332a639 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -7,4 +7,4 @@ def test_getcl() -> None: # make sure indices are retrieved correctly for i in range(10): for j in range(10): - assert getcl(cls, i, j) == {i, j} # type: ignore[arg-type, comparison-overlap] + assert getcl(cls, i, j) == {i, j} # type: ignore[arg-type] diff --git a/tests/test_galaxies.py b/tests/test_galaxies.py index 0dffa3d8..0bfe2499 100644 --- a/tests/test_galaxies.py +++ b/tests/test_galaxies.py @@ -12,28 +12,28 @@ def test_redshifts(mocker) -> None: # type: ignore[no-untyped-def] # sample redshifts (scalar) z = redshifts(13, w) - assert z.shape == (13,) # type: ignore[union-attr] - assert z.min() >= 0.0 # type: ignore[union-attr] - assert z.max() <= 1.0 # type: ignore[union-attr] + assert z.shape == (13,) + assert z.min() >= 0.0 + assert z.max() <= 1.0 # sample redshifts (array) - z = redshifts([[1, 2], [3, 4]], w) - assert z.shape == (10,) # type: ignore[union-attr] + z = redshifts([[1, 2], [3, 4]], w) # type: ignore[arg-type] + assert z.shape == (10,) def test_redshifts_from_nz() -> None: # test sampling - redshifts = redshifts_from_nz(10, [0, 1, 2, 3, 4], [1, 0, 0, 0, 0], warn=False) + redshifts = redshifts_from_nz(10, [0, 1, 2, 3, 4], [1, 0, 0, 0, 0], warn=False) # type: ignore[arg-type] assert np.all((0 <= redshifts) & (redshifts <= 1)) # noqa: SIM300 - redshifts = redshifts_from_nz(10, [0, 1, 2, 3, 4], [0, 0, 1, 0, 0], warn=False) + redshifts = redshifts_from_nz(10, [0, 1, 2, 3, 4], [0, 0, 1, 0, 0], warn=False) # type: ignore[arg-type] assert np.all((1 <= redshifts) & (redshifts <= 3)) # noqa: SIM300 - redshifts = redshifts_from_nz(10, [0, 1, 2, 3, 4], [0, 0, 0, 0, 1], warn=False) + redshifts = redshifts_from_nz(10, [0, 1, 2, 3, 4], [0, 0, 0, 0, 1], warn=False) # type: ignore[arg-type] assert np.all((3 <= redshifts) & (redshifts <= 4)) # noqa: SIM300 - redshifts = redshifts_from_nz(10, [0, 1, 2, 3, 4], [0, 0, 1, 1, 1], warn=False) + redshifts = redshifts_from_nz(10, [0, 1, 2, 3, 4], [0, 0, 1, 1, 1], warn=False) # type: ignore[arg-type] assert not np.any(redshifts <= 1) # test interface @@ -89,7 +89,7 @@ def test_redshifts_from_nz() -> None: redshifts_from_nz(count, z, nz, warn=False) with pytest.warns(UserWarning, match="when sampling galaxies"): - redshifts = redshifts_from_nz(10, [0, 1, 2, 3, 4], [1, 0, 0, 0, 0]) + redshifts = redshifts_from_nz(10, [0, 1, 2, 3, 4], [1, 0, 0, 0, 0]) # type: ignore[arg-type] def test_gaussian_phz() -> None: @@ -111,19 +111,19 @@ def test_gaussian_phz() -> None: phz = gaussian_phz(z, sigma_0) - assert phz.shape == (100,) # type: ignore[union-attr] - assert np.all(phz >= 0) # type: ignore[operator] + assert phz.shape == (100,) + assert np.all(phz >= 0) # case: upper and lower bound z = 1.0 # type: ignore[assignment] sigma_0 = np.ones(100) # type: ignore[assignment] - phz = gaussian_phz(z, sigma_0, lower=0.5, upper=1.5) + phz = gaussian_phz(z, sigma_0, lower=0.5, upper=1.5) # type: ignore[arg-type] - assert phz.shape == (100,) # type: ignore[union-attr] - assert np.all(phz >= 0.5) # type: ignore[operator] - assert np.all(phz <= 1.5) # type: ignore[operator] + assert phz.shape == (100,) + assert np.all(phz >= 0.5) + assert np.all(phz <= 1.5) # test interface @@ -144,7 +144,7 @@ def test_gaussian_phz() -> None: phz = gaussian_phz(z, sigma_0) - assert phz.shape == (10,) # type: ignore[union-attr] + assert phz.shape == (10,) np.testing.assert_array_equal(z, phz) # case: scalar redshift, array sigma_0 @@ -154,7 +154,7 @@ def test_gaussian_phz() -> None: phz = gaussian_phz(z, sigma_0) - assert phz.shape == (10,) # type: ignore[union-attr] + assert phz.shape == (10,) np.testing.assert_array_equal(z, phz) # case: array redshift, array sigma_0 @@ -164,5 +164,5 @@ def test_gaussian_phz() -> None: phz = gaussian_phz(z, sigma_0) - assert phz.shape == (11, 10) # type: ignore[union-attr] + assert phz.shape == (11, 10) np.testing.assert_array_equal(np.broadcast_to(z, (11, 10)), phz) diff --git a/tests/test_lensing.py b/tests/test_lensing.py index 89cfc4b5..1694496f 100644 --- a/tests/test_lensing.py +++ b/tests/test_lensing.py @@ -55,20 +55,20 @@ def alpha(re, im): # type: ignore[no-untyped-def] return [re, im] # north - lon, lat = deflect(0.0, 0.0, alpha(r, 0)) # type: ignore[misc, no-untyped-call] - np.testing.assert_allclose([lon, lat], [0.0, d], atol=1e-15) # type: ignore[arg-type] + lon, lat = deflect(0.0, 0.0, alpha(r, 0)) # type: ignore[arg-type, no-untyped-call] + np.testing.assert_allclose([lon, lat], [0.0, d], atol=1e-15) # south - lon, lat = deflect(0.0, 0.0, alpha(-r, 0)) # type: ignore[misc, no-untyped-call] - np.testing.assert_allclose([lon, lat], [0.0, -d], atol=1e-15) # type: ignore[arg-type] + lon, lat = deflect(0.0, 0.0, alpha(-r, 0)) # type: ignore[arg-type, no-untyped-call] + np.testing.assert_allclose([lon, lat], [0.0, -d], atol=1e-15) # east - lon, lat = deflect(0.0, 0.0, alpha(0, r)) # type: ignore[misc, no-untyped-call] - np.testing.assert_allclose([lon, lat], [-d, 0.0], atol=1e-15) # type: ignore[arg-type] + lon, lat = deflect(0.0, 0.0, alpha(0, r)) # type: ignore[arg-type, no-untyped-call] + np.testing.assert_allclose([lon, lat], [-d, 0.0], atol=1e-15) # west - lon, lat = deflect(0.0, 0.0, alpha(0, -r)) # type: ignore[misc, no-untyped-call] - np.testing.assert_allclose([lon, lat], [d, 0.0], atol=1e-15) # type: ignore[arg-type] + lon, lat = deflect(0.0, 0.0, alpha(0, -r)) # type: ignore[arg-type, no-untyped-call] + np.testing.assert_allclose([lon, lat], [d, 0.0], atol=1e-15) def test_deflect_many(rng: np.random.Generator) -> None: @@ -79,7 +79,7 @@ def test_deflect_many(rng: np.random.Generator) -> None: lon_ = np.degrees(rng.uniform(-np.pi, np.pi, size=n)) lat_ = np.degrees(np.arcsin(rng.uniform(-1, 1, size=n))) - lon, lat = deflect(lon_, lat_, abs_alpha * np.exp(1j * arg_alpha)) # type: ignore[misc] + lon, lat = deflect(lon_, lat_, abs_alpha * np.exp(1j * arg_alpha)) x_, y_, z_ = healpix.ang2vec(lon_, lat_, lonlat=True) x, y, z = healpix.ang2vec(lon, lat, lonlat=True) @@ -125,4 +125,4 @@ def test_multi_plane_weights(shells, cosmo, rng) -> None: # type: ignore[no-unt wmat = multi_plane_weights(weights, shells, cosmo) - np.testing.assert_allclose(np.einsum("ij,ik", wmat, deltas), kappa) # type: ignore[arg-type] + np.testing.assert_allclose(np.einsum("ij,ik", wmat, deltas), kappa) diff --git a/tests/test_shapes.py b/tests/test_shapes.py index 6edc40b5..b234ed2b 100644 --- a/tests/test_shapes.py +++ b/tests/test_shapes.py @@ -12,7 +12,7 @@ def test_triaxial_axis_ratio() -> None: # single axis ratio - q = triaxial_axis_ratio(0.8, 0.4) + q = triaxial_axis_ratio(0.8, 0.4) # type: ignore[arg-type] assert np.isscalar(q) # many axis ratios @@ -27,13 +27,13 @@ def test_triaxial_axis_ratio() -> None: # implicit size - q1 = triaxial_axis_ratio([0.8, 0.9], 0.4) - q2 = triaxial_axis_ratio(0.8, [0.4, 0.5]) + q1 = triaxial_axis_ratio([0.8, 0.9], 0.4) # type: ignore[arg-type] + q2 = triaxial_axis_ratio(0.8, [0.4, 0.5]) # type: ignore[arg-type] assert np.shape(q1) == np.shape(q2) == (2,) # broadcasting rule - q = triaxial_axis_ratio([[0.6, 0.7], [0.8, 0.9]], [0.4, 0.5]) + q = triaxial_axis_ratio([[0.6, 0.7], [0.8, 0.9]], [0.4, 0.5]) # type: ignore[arg-type] assert np.shape(q) == (2, 2) # random parameters and check that projection is @@ -49,69 +49,69 @@ def test_triaxial_axis_ratio() -> None: def test_ellipticity_ryden04() -> None: # single ellipticity - e = ellipticity_ryden04(-1.85, 0.89, 0.222, 0.056) + e = ellipticity_ryden04(-1.85, 0.89, 0.222, 0.056) # type: ignore[arg-type] assert np.isscalar(e) # many ellipticities - e = ellipticity_ryden04(-1.85, 0.89, 0.222, 0.056, size=1000) + e = ellipticity_ryden04(-1.85, 0.89, 0.222, 0.056, size=1000) # type: ignore[arg-type] assert np.shape(e) == (1000,) # explicit shape - e = ellipticity_ryden04(-1.85, 0.89, 0.222, 0.056, size=(10, 10)) + e = ellipticity_ryden04(-1.85, 0.89, 0.222, 0.056, size=(10, 10)) # type: ignore[arg-type] assert np.shape(e) == (10, 10) # implicit size - e1 = ellipticity_ryden04(-1.85, 0.89, [0.222, 0.333], 0.056) - e2 = ellipticity_ryden04(-1.85, 0.89, 0.222, [0.056, 0.067]) - e3 = ellipticity_ryden04([-1.85, -2.85], 0.89, 0.222, 0.056) - e4 = ellipticity_ryden04(-1.85, [0.89, 1.001], 0.222, 0.056) + e1 = ellipticity_ryden04(-1.85, 0.89, [0.222, 0.333], 0.056) # type: ignore[arg-type] + e2 = ellipticity_ryden04(-1.85, 0.89, 0.222, [0.056, 0.067]) # type: ignore[arg-type] + e3 = ellipticity_ryden04([-1.85, -2.85], 0.89, 0.222, 0.056) # type: ignore[arg-type] + e4 = ellipticity_ryden04(-1.85, [0.89, 1.001], 0.222, 0.056) # type: ignore[arg-type] assert np.shape(e1) == np.shape(e2) == np.shape(e3) == np.shape(e4) == (2,) # broadcasting rule - e = ellipticity_ryden04([-1.9, -2.9], 0.9, [[0.2, 0.3], [0.4, 0.5]], 0.1) + e = ellipticity_ryden04([-1.9, -2.9], 0.9, [[0.2, 0.3], [0.4, 0.5]], 0.1) # type: ignore[arg-type] assert np.shape(e) == (2, 2) # check that result is in the specified range - e = ellipticity_ryden04(0.0, 1.0, 0.222, 0.056, size=10) - assert np.all((e.real >= -1.0) & (e.real <= 1.0)) # type: ignore[union-attr] + e = ellipticity_ryden04(0.0, 1.0, 0.222, 0.056, size=10) # type: ignore[arg-type] + assert np.all((e.real >= -1.0) & (e.real <= 1.0)) - e = ellipticity_ryden04(0.0, 1.0, 0.0, 1.0, size=10) - assert np.all((e.real >= -1.0) & (e.real <= 1.0)) # type: ignore[union-attr] + e = ellipticity_ryden04(0.0, 1.0, 0.0, 1.0, size=10) # type: ignore[arg-type] + assert np.all((e.real >= -1.0) & (e.real <= 1.0)) def test_ellipticity_gaussian() -> None: n = 1_000_000 - eps = ellipticity_gaussian(n, 0.256) + eps = ellipticity_gaussian(n, 0.256) # type: ignore[arg-type] - assert eps.shape == (n,) # type: ignore[union-attr] + assert eps.shape == (n,) np.testing.assert_array_less(np.abs(eps), 1) - np.testing.assert_allclose(np.std(eps.real), 0.256, atol=1e-3, rtol=0) # type: ignore[union-attr] - np.testing.assert_allclose(np.std(eps.imag), 0.256, atol=1e-3, rtol=0) # type: ignore[union-attr] + np.testing.assert_allclose(np.std(eps.real), 0.256, atol=1e-3, rtol=0) + np.testing.assert_allclose(np.std(eps.imag), 0.256, atol=1e-3, rtol=0) - eps = ellipticity_gaussian([n, n], [0.128, 0.256]) + eps = ellipticity_gaussian([n, n], [0.128, 0.256]) # type: ignore[arg-type] - assert eps.shape == (2 * n,) # type: ignore[union-attr] + assert eps.shape == (2 * n,) np.testing.assert_array_less(np.abs(eps), 1) - np.testing.assert_allclose(np.std(eps.real[:n]), 0.128, atol=1e-3, rtol=0) # type: ignore[index, union-attr] - np.testing.assert_allclose(np.std(eps.imag[:n]), 0.128, atol=1e-3, rtol=0) # type: ignore[index, union-attr] - np.testing.assert_allclose(np.std(eps.real[n:]), 0.256, atol=1e-3, rtol=0) # type: ignore[index, union-attr] - np.testing.assert_allclose(np.std(eps.imag[n:]), 0.256, atol=1e-3, rtol=0) # type: ignore[index, union-attr] + np.testing.assert_allclose(np.std(eps.real[:n]), 0.128, atol=1e-3, rtol=0) + np.testing.assert_allclose(np.std(eps.imag[:n]), 0.128, atol=1e-3, rtol=0) + np.testing.assert_allclose(np.std(eps.real[n:]), 0.256, atol=1e-3, rtol=0) + np.testing.assert_allclose(np.std(eps.imag[n:]), 0.256, atol=1e-3, rtol=0) def test_ellipticity_intnorm() -> None: n = 1_000_000 - eps = ellipticity_intnorm(n, 0.256) + eps = ellipticity_intnorm(n, 0.256) # type: ignore[arg-type] assert eps.shape == (n,) @@ -120,7 +120,7 @@ def test_ellipticity_intnorm() -> None: np.testing.assert_allclose(np.std(eps.real), 0.256, atol=1e-3, rtol=0) np.testing.assert_allclose(np.std(eps.imag), 0.256, atol=1e-3, rtol=0) - eps = ellipticity_intnorm([n, n], [0.128, 0.256]) + eps = ellipticity_intnorm([n, n], [0.128, 0.256]) # type: ignore[arg-type] assert eps.shape == (2 * n,) @@ -132,4 +132,4 @@ def test_ellipticity_intnorm() -> None: np.testing.assert_allclose(np.std(eps.imag[n:]), 0.256, atol=1e-3, rtol=0) with pytest.raises(ValueError): - ellipticity_intnorm(1, 0.71) + ellipticity_intnorm(1, 0.71) # type: ignore[arg-type] diff --git a/tests/test_shells.py b/tests/test_shells.py index 5cba9cdb..8a49f46e 100644 --- a/tests/test_shells.py +++ b/tests/test_shells.py @@ -67,6 +67,6 @@ def test_partition(method) -> None: # type: ignore[no-untyped-def] part = partition(z, fz, shells, method=method) - assert part.shape == (len(shells), 3, 2) # type: ignore[union-attr] + assert part.shape == (len(shells), 3, 2) - np.testing.assert_allclose(part.sum(axis=0), np.trapz(fz, z)) # type: ignore[attr-defined, union-attr] + np.testing.assert_allclose(part.sum(axis=0), np.trapz(fz, z)) # type: ignore[attr-defined] From 5bf6a27c28c742c5080d461f98b3bd669009d23b Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Wed, 9 Oct 2024 12:39:11 +0100 Subject: [PATCH 24/32] Fix linting --- tests/test_lensing.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_lensing.py b/tests/test_lensing.py index 1694496f..ba3689be 100644 --- a/tests/test_lensing.py +++ b/tests/test_lensing.py @@ -41,7 +41,7 @@ def xm(self, z, z2=None): # type: ignore[no-untyped-def] @pytest.mark.parametrize("usecomplex", [True, False]) -def test_deflect_nsew(*, usecomplex: bool) -> None: +def test_deflect_nsew(usecomplex: bool) -> None: # noqa: FBT001 d = 5.0 r = np.radians(d) From aab5b92f51ab780c0b92c35e09c797e0a863fe3d Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Wed, 9 Oct 2024 16:34:49 +0100 Subject: [PATCH 25/32] Separate out all `typing` imports --- glass/core/algorithm.py | 4 ++-- glass/fields.py | 28 ++++++++++++++++------------ glass/galaxies.py | 4 ++-- glass/lensing.py | 10 ++++------ glass/observations.py | 4 ++-- glass/shapes.py | 4 ++-- glass/shells.py | 29 ++++++++++++++--------------- pyproject.toml | 2 +- 8 files changed, 43 insertions(+), 42 deletions(-) diff --git a/glass/core/algorithm.py b/glass/core/algorithm.py index 9e83db27..f180ee7f 100644 --- a/glass/core/algorithm.py +++ b/glass/core/algorithm.py @@ -2,11 +2,11 @@ from __future__ import annotations -from typing import TYPE_CHECKING +import typing import numpy as np -if TYPE_CHECKING: +if typing.TYPE_CHECKING: import numpy.typing as npt diff --git a/glass/fields.py b/glass/fields.py index fccfe74e..bbf1feb7 100644 --- a/glass/fields.py +++ b/glass/fields.py @@ -26,28 +26,30 @@ from __future__ import annotations +import typing import warnings -from collections.abc import Generator, Iterable, Sequence -from typing import Any, Callable, Optional, Union import healpy as hp import numpy as np import numpy.typing as npt from gaussiancl import gaussiancl +if typing.TYPE_CHECKING: + import collections.abc + # types -Size = Optional[Union[int, tuple[int, ...]]] -Iternorm = tuple[Optional[int], npt.NDArray, npt.NDArray] # type: ignore[type-arg] -ClTransform = Union[str, Callable[[npt.NDArray], npt.NDArray]] # type: ignore[type-arg] -Cls = Sequence[Union[npt.NDArray, Sequence[float]]] # type: ignore[type-arg] +Size = typing.Optional[typing.Union[int, tuple[int, ...]]] +Iternorm = tuple[typing.Optional[int], npt.NDArray, npt.NDArray] # type: ignore[type-arg] +ClTransform = typing.Union[str, typing.Callable[[npt.NDArray], npt.NDArray]] # type: ignore[type-arg] +Cls = typing.Sequence[typing.Union[npt.NDArray, typing.Sequence[float]]] # type: ignore[type-arg] Alms = npt.NDArray # type: ignore[type-arg] def iternorm( k: int, - cov: Iterable[npt.NDArray], # type: ignore[type-arg] + cov: collections.abc.Iterable[npt.NDArray], # type: ignore[type-arg] size: Size = None, -) -> Generator[Iternorm, None, None]: +) -> collections.abc.Generator[Iternorm, None, None]: """Return the vector a and variance sigma^2 for iterative normal sampling.""" n: tuple[int, ...] if size is None: @@ -105,7 +107,9 @@ def iternorm( yield j, a, s -def cls2cov(cls: Cls, nl: int, nf: int, nc: int) -> Generator[npt.NDArray, None, None]: # type: ignore[type-arg] +def cls2cov( + cls: Cls, nl: int, nf: int, nc: int +) -> collections.abc.Generator[npt.NDArray, None, None]: # type: ignore[type-arg] """Return array of cls as a covariance matrix for iterative sampling.""" cov = np.zeros((nl, nc + 1)) end = 0 @@ -134,7 +138,7 @@ def multalm(alm: Alms, bl: npt.NDArray, *, inplace: bool = False) -> Alms: # ty return out -def transform_cls(cls: Cls, tfm: ClTransform, pars: tuple[Any, ...] = ()) -> Cls: +def transform_cls(cls: Cls, tfm: ClTransform, pars: tuple[typing.Any, ...] = ()) -> Cls: """Transform Cls to Gaussian Cls.""" gls = [] for cl in cls: @@ -212,7 +216,7 @@ def generate_gaussian( *, ncorr: int | None = None, rng: np.random.Generator | None = None, -) -> Generator[npt.NDArray, None, None]: # type: ignore[type-arg] +) -> collections.abc.Generator[npt.NDArray, None, None]: # type: ignore[type-arg] """ Sample Gaussian random fields from Cls iteratively. @@ -298,7 +302,7 @@ def generate_lognormal( *, ncorr: int | None = None, rng: np.random.Generator | None = None, -) -> Generator[npt.NDArray, None, None]: # type: ignore[type-arg] +) -> collections.abc.Generator[npt.NDArray, None, None]: # type: ignore[type-arg] """Sample lognormal random fields from Gaussian Cls iteratively.""" for i, m in enumerate(generate_gaussian(gls, nside, ncorr=ncorr, rng=rng)): # compute the variance of the auto-correlation diff --git a/glass/galaxies.py b/glass/galaxies.py index 3668e89e..fe6e7c0a 100644 --- a/glass/galaxies.py +++ b/glass/galaxies.py @@ -19,10 +19,10 @@ from __future__ import annotations +import typing import warnings -from typing import TYPE_CHECKING -if TYPE_CHECKING: +if typing.TYPE_CHECKING: import numpy.typing as npt from glass.shells import RadialWindow diff --git a/glass/lensing.py b/glass/lensing.py index d1c76be6..fd95efc7 100644 --- a/glass/lensing.py +++ b/glass/lensing.py @@ -31,14 +31,12 @@ from __future__ import annotations -from typing import TYPE_CHECKING +import typing import healpy as hp import numpy as np -if TYPE_CHECKING: - from collections.abc import Sequence - +if typing.TYPE_CHECKING: import numpy.typing as npt from cosmology import Cosmology @@ -364,7 +362,7 @@ def wlens(self) -> float: def multi_plane_matrix( - shells: Sequence[RadialWindow], + shells: typing.Sequence[RadialWindow], cosmo: Cosmology, ) -> npt.NDArray: # type: ignore[type-arg] """Compute the matrix of lensing contributions from each shell.""" @@ -378,7 +376,7 @@ def multi_plane_matrix( def multi_plane_weights( weights: npt.NDArray, # type: ignore[type-arg] - shells: Sequence[RadialWindow], + shells: typing.Sequence[RadialWindow], cosmo: Cosmology, ) -> npt.NDArray: # type: ignore[type-arg] """ diff --git a/glass/observations.py b/glass/observations.py index 7e14ec33..d9050fb8 100644 --- a/glass/observations.py +++ b/glass/observations.py @@ -29,14 +29,14 @@ from __future__ import annotations import math -from typing import TYPE_CHECKING +import typing import healpy as hp import numpy as np from glass.core.array import cumtrapz -if TYPE_CHECKING: +if typing.TYPE_CHECKING: import numpy.typing as npt diff --git a/glass/shapes.py b/glass/shapes.py index 4072acdc..4ac08364 100644 --- a/glass/shapes.py +++ b/glass/shapes.py @@ -24,11 +24,11 @@ from __future__ import annotations -from typing import TYPE_CHECKING +import typing import numpy as np -if TYPE_CHECKING: +if typing.TYPE_CHECKING: import numpy.typing as npt diff --git a/glass/shells.py b/glass/shells.py index a8277d70..7230e2b4 100644 --- a/glass/shells.py +++ b/glass/shells.py @@ -44,21 +44,20 @@ from __future__ import annotations +import typing import warnings -from collections.abc import Sequence -from typing import TYPE_CHECKING, Callable, NamedTuple, Union import numpy as np import numpy.typing as npt from glass.core.array import ndinterp -if TYPE_CHECKING: +if typing.TYPE_CHECKING: from cosmology import Cosmology # types -ArrayLike1D = Union[Sequence[float], npt.NDArray] # type: ignore[type-arg] -WeightFunc = Callable[[ArrayLike1D], npt.NDArray] # type: ignore[type-arg] +ArrayLike1D = typing.Union[typing.Sequence[float], npt.NDArray] # type: ignore[type-arg] +WeightFunc = typing.Callable[[ArrayLike1D], npt.NDArray] # type: ignore[type-arg] def distance_weight(z: npt.NDArray, cosmo: Cosmology) -> npt.NDArray: # type: ignore[type-arg] @@ -76,7 +75,7 @@ def density_weight(z: npt.NDArray, cosmo: Cosmology) -> npt.NDArray: # type: ig return cosmo.rho_m_z(z) * cosmo.xm(z) ** 2 / cosmo.ef(z) # type: ignore[no-any-return] -class RadialWindow(NamedTuple): +class RadialWindow(typing.NamedTuple): """ A radial window, defined by a window function. @@ -107,9 +106,9 @@ class RadialWindow(NamedTuple): Attributes ---------- - za : Sequence[float] + za : typing.Sequence[float] Redshift array; the abscissae of the window function. - wa : Sequence[float] + wa : typing.Sequence[float] Weight array; the values (ordinates) of the window function. zeff : float Effective redshift of the window. @@ -120,8 +119,8 @@ class RadialWindow(NamedTuple): """ - za: Sequence[float] - wa: Sequence[float] + za: typing.Sequence[float] + wa: typing.Sequence[float] zeff: float | None @@ -351,7 +350,7 @@ def restrict( def partition( z: npt.NDArray, # type: ignore[type-arg] fz: npt.NDArray, # type: ignore[type-arg] - shells: Sequence[RadialWindow], + shells: typing.Sequence[RadialWindow], *, method: str = "nnls", ) -> npt.NDArray: # type: ignore[type-arg] @@ -461,7 +460,7 @@ def partition( def partition_lstsq( z: npt.NDArray, # type: ignore[type-arg] fz: npt.NDArray, # type: ignore[type-arg] - shells: Sequence[RadialWindow], + shells: typing.Sequence[RadialWindow], *, sumtol: float = 0.01, ) -> npt.NDArray: # type: ignore[type-arg] @@ -507,7 +506,7 @@ def partition_lstsq( def partition_nnls( z: npt.NDArray, # type: ignore[type-arg] fz: npt.NDArray, # type: ignore[type-arg] - shells: Sequence[RadialWindow], + shells: typing.Sequence[RadialWindow], *, sumtol: float = 0.01, ) -> npt.NDArray: # type: ignore[type-arg] @@ -568,7 +567,7 @@ def partition_nnls( def partition_restrict( z: npt.NDArray, # type: ignore[type-arg] fz: npt.NDArray, # type: ignore[type-arg] - shells: Sequence[RadialWindow], + shells: typing.Sequence[RadialWindow], ) -> npt.NDArray: # type: ignore[type-arg] """Partition by restriction and integration.""" part = np.empty((len(shells),) + np.shape(fz)[:-1]) @@ -615,7 +614,7 @@ def distance_grid( def combine( z: npt.NDArray, # type: ignore[type-arg] weights: npt.NDArray, # type: ignore[type-arg] - shells: Sequence[RadialWindow], + shells: typing.Sequence[RadialWindow], ) -> npt.NDArray: # type: ignore[type-arg] r""" Evaluate a linear combination of window functions. diff --git a/pyproject.toml b/pyproject.toml index fa39ffe1..a6108814 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -70,7 +70,7 @@ Issues = "https://github.com/glass-dev/glass/issues" [tool.coverage] report = {exclude_also = [ - "if TYPE_CHECKING:", + "if typing.TYPE_CHECKING:", ], omit = [ "glass/_version.py", ], skip_covered = true, sort = "cover"} From 0ff8b08db3b7f53fa96fe65d400c9ba102d8e153 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Wed, 9 Oct 2024 16:49:58 +0100 Subject: [PATCH 26/32] Using `typing.Any` throughout --- glass/core/algorithm.py | 6 +++--- glass/core/array.py | 29 ++++++++++++++----------- glass/fields.py | 30 ++++++++++++++------------ glass/galaxies.py | 36 +++++++++++++++---------------- glass/lensing.py | 38 ++++++++++++++++---------------- glass/observations.py | 34 ++++++++++++++--------------- glass/points.py | 36 ++++++++++++++++++------------- glass/shapes.py | 28 ++++++++++++------------ glass/shells.py | 48 +++++++++++++++++++++++------------------ glass/user.py | 15 +++++++++---- 10 files changed, 163 insertions(+), 137 deletions(-) diff --git a/glass/core/algorithm.py b/glass/core/algorithm.py index f180ee7f..7582967b 100644 --- a/glass/core/algorithm.py +++ b/glass/core/algorithm.py @@ -11,12 +11,12 @@ def nnls( - a: npt.NDArray, # type: ignore[type-arg] - b: npt.NDArray, # type: ignore[type-arg] + a: npt.NDArray[typing.Any], + b: npt.NDArray[typing.Any], *, tol: float = 0.0, maxiter: int | None = None, -) -> npt.NDArray: # type: ignore[type-arg] +) -> npt.NDArray[typing.Any]: """ Compute a non-negative least squares solution. diff --git a/glass/core/array.py b/glass/core/array.py index 86ee5fec..c8305039 100644 --- a/glass/core/array.py +++ b/glass/core/array.py @@ -2,13 +2,16 @@ from __future__ import annotations +import typing from functools import partial import numpy as np import numpy.typing as npt -def broadcast_first(*arrays: npt.NDArray) -> tuple[npt.NDArray, ...]: # type: ignore[type-arg] +def broadcast_first( + *arrays: npt.NDArray[typing.Any], +) -> tuple[npt.NDArray[typing.Any], ...]: """Broadcast arrays, treating the first axis as common.""" arrays = tuple(np.moveaxis(a, 0, -1) if np.ndim(a) else a for a in arrays) arrays = np.broadcast_arrays(*arrays) @@ -16,7 +19,7 @@ def broadcast_first(*arrays: npt.NDArray) -> tuple[npt.NDArray, ...]: # type: i def broadcast_leading_axes( - *args: tuple[npt.NDArray, int], # type: ignore[type-arg] + *args: tuple[npt.NDArray[typing.Any], int], ) -> tuple[tuple[int, ...], ...]: """ Broadcast all but the last N axes. @@ -55,14 +58,14 @@ def broadcast_leading_axes( def ndinterp( # noqa: PLR0913 - x: npt.NDArray, # type: ignore[type-arg] - xp: npt.NDArray, # type: ignore[type-arg] - fp: npt.NDArray, # type: ignore[type-arg] + x: npt.NDArray[typing.Any], + xp: npt.NDArray[typing.Any], + fp: npt.NDArray[typing.Any], axis: int = -1, left: float | None = None, right: float | None = None, period: float | None = None, -) -> npt.NDArray: # type: ignore[type-arg] +) -> npt.NDArray[typing.Any]: """Interpolate multi-dimensional array over axis.""" return np.apply_along_axis( partial(np.interp, x, xp), @@ -75,10 +78,10 @@ def ndinterp( # noqa: PLR0913 def trapz_product( - f: tuple[npt.NDArray, npt.NDArray], # type: ignore[type-arg] - *ff: tuple[npt.NDArray, npt.NDArray], # type: ignore[type-arg] + f: tuple[npt.NDArray[typing.Any], npt.NDArray[typing.Any]], + *ff: tuple[npt.NDArray[typing.Any], npt.NDArray[typing.Any]], axis: int = -1, -) -> npt.NDArray: # type: ignore[type-arg] +) -> npt.NDArray[typing.Any]: """Trapezoidal rule for a product of functions.""" x, _ = f for x_, _ in ff: @@ -93,11 +96,11 @@ def trapz_product( def cumtrapz( - f: npt.NDArray, # type: ignore[type-arg] - x: npt.NDArray, # type: ignore[type-arg] + f: npt.NDArray[typing.Any], + x: npt.NDArray[typing.Any], dtype: np.dtype | None = None, # type: ignore[type-arg] - out: npt.NDArray | None = None, # type: ignore[type-arg] -) -> npt.NDArray: # type: ignore[type-arg] + out: npt.NDArray[typing.Any] | None = None, +) -> npt.NDArray[typing.Any]: """Cumulative trapezoidal rule along last axis.""" if out is None: out = np.empty_like(f, dtype=dtype) diff --git a/glass/fields.py b/glass/fields.py index bbf1feb7..c5644880 100644 --- a/glass/fields.py +++ b/glass/fields.py @@ -39,15 +39,17 @@ # types Size = typing.Optional[typing.Union[int, tuple[int, ...]]] -Iternorm = tuple[typing.Optional[int], npt.NDArray, npt.NDArray] # type: ignore[type-arg] -ClTransform = typing.Union[str, typing.Callable[[npt.NDArray], npt.NDArray]] # type: ignore[type-arg] -Cls = typing.Sequence[typing.Union[npt.NDArray, typing.Sequence[float]]] # type: ignore[type-arg] -Alms = npt.NDArray # type: ignore[type-arg] +Iternorm = tuple[typing.Optional[int], npt.NDArray[typing.Any], npt.NDArray[typing.Any]] +ClTransform = typing.Union[ + str, typing.Callable[[npt.NDArray[typing.Any]], npt.NDArray[typing.Any]] +] +Cls = typing.Sequence[typing.Union[npt.NDArray[typing.Any], typing.Sequence[float]]] +Alms = npt.NDArray[typing.Any] def iternorm( k: int, - cov: collections.abc.Iterable[npt.NDArray], # type: ignore[type-arg] + cov: collections.abc.Iterable[npt.NDArray[typing.Any]], size: Size = None, ) -> collections.abc.Generator[Iternorm, None, None]: """Return the vector a and variance sigma^2 for iterative normal sampling.""" @@ -109,7 +111,7 @@ def iternorm( def cls2cov( cls: Cls, nl: int, nf: int, nc: int -) -> collections.abc.Generator[npt.NDArray, None, None]: # type: ignore[type-arg] +) -> collections.abc.Generator[npt.NDArray[typing.Any], None, None]: """Return array of cls as a covariance matrix for iterative sampling.""" cov = np.zeros((nl, nc + 1)) end = 0 @@ -129,7 +131,7 @@ def cls2cov( yield cov -def multalm(alm: Alms, bl: npt.NDArray, *, inplace: bool = False) -> Alms: # type: ignore[type-arg] +def multalm(alm: Alms, bl: npt.NDArray[typing.Any], *, inplace: bool = False) -> Alms: """Multiply alm by bl.""" n = len(bl) out = np.asanyarray(alm) if inplace else np.copy(alm) @@ -216,7 +218,7 @@ def generate_gaussian( *, ncorr: int | None = None, rng: np.random.Generator | None = None, -) -> collections.abc.Generator[npt.NDArray, None, None]: # type: ignore[type-arg] +) -> collections.abc.Generator[npt.NDArray[typing.Any], None, None]: """ Sample Gaussian random fields from Cls iteratively. @@ -302,7 +304,7 @@ def generate_lognormal( *, ncorr: int | None = None, rng: np.random.Generator | None = None, -) -> collections.abc.Generator[npt.NDArray, None, None]: # type: ignore[type-arg] +) -> collections.abc.Generator[npt.NDArray[typing.Any], None, None]: """Sample lognormal random fields from Gaussian Cls iteratively.""" for i, m in enumerate(generate_gaussian(gls, nside, ncorr=ncorr, rng=rng)): # compute the variance of the auto-correlation @@ -325,11 +327,11 @@ def generate_lognormal( def getcl( - cls: list[npt.NDArray], # type: ignore[type-arg] + cls: list[npt.NDArray[typing.Any]], i: int, j: int, lmax: int | None = None, -) -> npt.NDArray: # type: ignore[type-arg] +) -> npt.NDArray[typing.Any]: """ Return a specific angular power spectrum from an array. @@ -363,9 +365,9 @@ def getcl( def effective_cls( - cls: list[npt.NDArray], # type: ignore[type-arg] - weights1: npt.NDArray, # type: ignore[type-arg] - weights2: npt.NDArray | None = None, # type: ignore[type-arg] + cls: list[npt.NDArray[typing.Any]], + weights1: npt.NDArray[typing.Any], + weights2: npt.NDArray[typing.Any] | None = None, *, lmax: int | None = None, ) -> npt.NDArray[np.float64]: diff --git a/glass/galaxies.py b/glass/galaxies.py index fe6e7c0a..ee4c5419 100644 --- a/glass/galaxies.py +++ b/glass/galaxies.py @@ -34,11 +34,11 @@ def redshifts( - n: int | npt.NDArray, # type: ignore[type-arg] + n: int | npt.NDArray[typing.Any], w: RadialWindow, *, rng: np.random.Generator | None = None, -) -> npt.NDArray: # type: ignore[type-arg] +) -> npt.NDArray[typing.Any]: """ Sample redshifts from a radial window function. @@ -65,13 +65,13 @@ def redshifts( def redshifts_from_nz( - count: int | npt.NDArray, # type: ignore[type-arg] - z: npt.NDArray, # type: ignore[type-arg] - nz: npt.NDArray, # type: ignore[type-arg] + count: int | npt.NDArray[typing.Any], + z: npt.NDArray[typing.Any], + nz: npt.NDArray[typing.Any], *, rng: np.random.Generator | None = None, warn: bool = True, -) -> npt.NDArray: # type: ignore[type-arg] +) -> npt.NDArray[typing.Any]: """ Generate galaxy redshifts from a source distribution. @@ -143,15 +143,15 @@ def redshifts_from_nz( def galaxy_shear( # noqa: PLR0913 - lon: npt.NDArray, # type: ignore[type-arg] - lat: npt.NDArray, # type: ignore[type-arg] - eps: npt.NDArray, # type: ignore[type-arg] - kappa: npt.NDArray, # type: ignore[type-arg] - gamma1: npt.NDArray, # type: ignore[type-arg] - gamma2: npt.NDArray, # type: ignore[type-arg] + lon: npt.NDArray[typing.Any], + lat: npt.NDArray[typing.Any], + eps: npt.NDArray[typing.Any], + kappa: npt.NDArray[typing.Any], + gamma1: npt.NDArray[typing.Any], + gamma2: npt.NDArray[typing.Any], *, reduced_shear: bool = True, -) -> npt.NDArray: # type: ignore[type-arg] +) -> npt.NDArray[typing.Any]: """ Observed galaxy shears from weak lensing. @@ -206,13 +206,13 @@ def galaxy_shear( # noqa: PLR0913 def gaussian_phz( - z: npt.NDArray, # type: ignore[type-arg] - sigma_0: float | npt.NDArray, # type: ignore[type-arg] + z: npt.NDArray[typing.Any], + sigma_0: float | npt.NDArray[typing.Any], *, - lower: npt.NDArray | None = None, # type: ignore[type-arg] - upper: npt.NDArray | None = None, # type: ignore[type-arg] + lower: npt.NDArray[typing.Any] | None = None, + upper: npt.NDArray[typing.Any] | None = None, rng: np.random.Generator | None = None, -) -> npt.NDArray: # type: ignore[type-arg] +) -> npt.NDArray[typing.Any]: r""" Photometric redshifts assuming a Gaussian error. diff --git a/glass/lensing.py b/glass/lensing.py index fd95efc7..0b6e13f7 100644 --- a/glass/lensing.py +++ b/glass/lensing.py @@ -45,14 +45,14 @@ def from_convergence( # noqa: PLR0913 - kappa: npt.NDArray, # type: ignore[type-arg] + kappa: npt.NDArray[typing.Any], lmax: int | None = None, *, potential: bool = False, deflection: bool = False, shear: bool = False, discretized: bool = True, -) -> tuple[npt.NDArray, ...]: # type: ignore[type-arg] +) -> tuple[npt.NDArray[typing.Any], ...]: r""" Compute other weak lensing maps from the convergence. @@ -224,11 +224,11 @@ def from_convergence( # noqa: PLR0913 def shear_from_convergence( - kappa: npt.NDArray, # type: ignore[type-arg] + kappa: npt.NDArray[typing.Any], lmax: int | None = None, *, discretized: bool = True, -) -> npt.NDArray: # type: ignore[type-arg] +) -> npt.NDArray[typing.Any]: r""" Weak lensing shear from convergence. @@ -280,11 +280,11 @@ def __init__(self, cosmo: Cosmology) -> None: self.x3: float = 0.0 self.w3: float = 0.0 self.r23: float = 1.0 - self.delta3: npt.NDArray = np.array(0.0) # type: ignore[type-arg] - self.kappa2: npt.NDArray | None = None # type: ignore[type-arg] - self.kappa3: npt.NDArray | None = None # type: ignore[type-arg] + self.delta3: npt.NDArray[typing.Any] = np.array(0.0) + self.kappa2: npt.NDArray[typing.Any] | None = None + self.kappa3: npt.NDArray[typing.Any] | None = None - def add_window(self, delta: npt.NDArray, w: RadialWindow) -> None: # type: ignore[type-arg] + def add_window(self, delta: npt.NDArray[typing.Any], w: RadialWindow) -> None: """ Add a mass plane from a window function to the convergence. @@ -297,7 +297,9 @@ def add_window(self, delta: npt.NDArray, w: RadialWindow) -> None: # type: igno self.add_plane(delta, zsrc, lens_weight) # type: ignore[arg-type] - def add_plane(self, delta: npt.NDArray, zsrc: float, wlens: float = 1.0) -> None: # type: ignore[type-arg] + def add_plane( + self, delta: npt.NDArray[typing.Any], zsrc: float, wlens: float = 1.0 + ) -> None: """Add a mass plane at redshift ``zsrc`` to the convergence.""" if zsrc <= self.z3: msg = "source redshift must be increasing" @@ -346,12 +348,12 @@ def zsrc(self) -> float: return self.z3 @property - def kappa(self) -> npt.NDArray | None: # type: ignore[type-arg] + def kappa(self) -> npt.NDArray[typing.Any] | None: """The current convergence plane.""" return self.kappa3 @property - def delta(self) -> npt.NDArray: # type: ignore[type-arg] + def delta(self) -> npt.NDArray[typing.Any]: """The current matter plane.""" return self.delta3 @@ -364,7 +366,7 @@ def wlens(self) -> float: def multi_plane_matrix( shells: typing.Sequence[RadialWindow], cosmo: Cosmology, -) -> npt.NDArray: # type: ignore[type-arg] +) -> npt.NDArray[typing.Any]: """Compute the matrix of lensing contributions from each shell.""" mpc = MultiPlaneConvergence(cosmo) wmat = np.eye(len(shells)) @@ -375,10 +377,10 @@ def multi_plane_matrix( def multi_plane_weights( - weights: npt.NDArray, # type: ignore[type-arg] + weights: npt.NDArray[typing.Any], shells: typing.Sequence[RadialWindow], cosmo: Cosmology, -) -> npt.NDArray: # type: ignore[type-arg] +) -> npt.NDArray[typing.Any]: """ Compute effective weights for multi-plane convergence. @@ -418,10 +420,10 @@ def multi_plane_weights( def deflect( - lon: npt.NDArray, # type: ignore[type-arg] - lat: npt.NDArray, # type: ignore[type-arg] - alpha: npt.NDArray, # type: ignore[type-arg] -) -> npt.NDArray: # type: ignore[type-arg] + lon: npt.NDArray[typing.Any], + lat: npt.NDArray[typing.Any], + alpha: npt.NDArray[typing.Any], +) -> npt.NDArray[typing.Any]: r""" Apply deflections to positions. diff --git a/glass/observations.py b/glass/observations.py index d9050fb8..663d967e 100644 --- a/glass/observations.py +++ b/glass/observations.py @@ -44,7 +44,7 @@ def vmap_galactic_ecliptic( nside: int, galactic: tuple[float, float] = (30, 90), ecliptic: tuple[float, float] = (20, 80), -) -> npt.NDArray: # type: ignore[type-arg] +) -> npt.NDArray[typing.Any]: """ Visibility map masking galactic and ecliptic plane. @@ -86,12 +86,12 @@ def vmap_galactic_ecliptic( def gaussian_nz( - z: npt.NDArray, # type: ignore[type-arg] - mean: npt.NDArray, # type: ignore[type-arg] - sigma: npt.NDArray, # type: ignore[type-arg] + z: npt.NDArray[typing.Any], + mean: npt.NDArray[typing.Any], + sigma: npt.NDArray[typing.Any], *, - norm: npt.NDArray | None = None, # type: ignore[type-arg] -) -> npt.NDArray: # type: ignore[type-arg] + norm: npt.NDArray[typing.Any] | None = None, +) -> npt.NDArray[typing.Any]: r""" Gaussian redshift distribution. @@ -131,13 +131,13 @@ def gaussian_nz( def smail_nz( - z: npt.NDArray, # type: ignore[type-arg] - z_mode: npt.NDArray, # type: ignore[type-arg] - alpha: npt.NDArray, # type: ignore[type-arg] - beta: npt.NDArray, # type: ignore[type-arg] + z: npt.NDArray[typing.Any], + z_mode: npt.NDArray[typing.Any], + alpha: npt.NDArray[typing.Any], + beta: npt.NDArray[typing.Any], *, - norm: float | npt.NDArray | None = None, # type: ignore[type-arg] -) -> npt.NDArray: # type: ignore[type-arg] + norm: float | npt.NDArray[typing.Any] | None = None, +) -> npt.NDArray[typing.Any]: r""" Redshift distribution following Smail et al. (1994). @@ -232,8 +232,8 @@ def fixed_zbins( def equal_dens_zbins( - z: npt.NDArray, # type: ignore[type-arg] - nz: npt.NDArray, # type: ignore[type-arg] + z: npt.NDArray[typing.Any], + nz: npt.NDArray[typing.Any], nbins: int, ) -> list[tuple[float, float]]: """ @@ -267,11 +267,11 @@ def equal_dens_zbins( def tomo_nz_gausserr( - z: npt.NDArray, # type: ignore[type-arg] - nz: npt.NDArray, # type: ignore[type-arg] + z: npt.NDArray[typing.Any], + nz: npt.NDArray[typing.Any], sigma_0: float, zbins: list[tuple[float, float]], -) -> npt.NDArray: # type: ignore[type-arg] +) -> npt.NDArray[typing.Any]: """ Tomographic redshift bins with a Gaussian redshift error. diff --git a/glass/points.py b/glass/points.py index fcb97318..031425d4 100644 --- a/glass/points.py +++ b/glass/points.py @@ -46,10 +46,10 @@ def effective_bias( - z: npt.NDArray, # type: ignore[type-arg] - bz: npt.NDArray, # type: ignore[type-arg] + z: npt.NDArray[typing.Any], + bz: npt.NDArray[typing.Any], w: RadialWindow, -) -> npt.NDArray: # type: ignore[type-arg] +) -> npt.NDArray[typing.Any]: r""" Effective bias parameter from a redshift-dependent bias function. @@ -84,14 +84,16 @@ def effective_bias( return trapz_product((z, bz), (w.za, w.wa)) / norm # type: ignore[arg-type, no-any-return] -def linear_bias(delta: npt.NDArray, b: float | npt.NDArray) -> npt.NDArray[float]: # type: ignore[type-arg, type-var] +def linear_bias( + delta: npt.NDArray[typing.Any], b: float | npt.NDArray[typing.Any] +) -> npt.NDArray[float]: # type: ignore[type-var] r"""Linear bias model :math:`\\delta_g = b \\, \\delta`.""" return b * delta # type: ignore[return-value] def loglinear_bias( - delta: npt.NDArray, # type: ignore[type-arg] - b: float | npt.NDArray, # type: ignore[type-arg] + delta: npt.NDArray[typing.Any], + b: float | npt.NDArray[typing.Any], ) -> npt.NDArray[float]: r"""log-linear bias model :math:`\\ln(1 + \\delta_g) = b \\ln(1 + \\delta)`.""" delta_g = np.log1p(delta) @@ -101,16 +103,18 @@ def loglinear_bias( def positions_from_delta( # noqa: PLR0912, PLR0913, PLR0915 - ngal: float | npt.NDArray, # type: ignore[type-arg] - delta: npt.NDArray, # type: ignore[type-arg] - bias: float | npt.NDArray | None = None, # type: ignore[type-arg] - vis: npt.NDArray | None = None, # type: ignore[type-arg] + ngal: float | npt.NDArray[typing.Any], + delta: npt.NDArray[typing.Any], + bias: float | npt.NDArray[typing.Any] | None = None, + vis: npt.NDArray[typing.Any] | None = None, *, bias_model: str | typing.Callable[..., typing.Any] = "linear", remove_monopole: bool = False, batch: int | None = 1_000_000, rng: np.random.Generator | None = None, -) -> typing.Iterator[tuple[npt.NDArray, npt.NDArray, npt.NDArray]]: # type: ignore[type-arg] +) -> typing.Iterator[ + tuple[npt.NDArray[typing.Any], npt.NDArray[typing.Any], npt.NDArray[typing.Any]] +]: """ Generate positions tracing a density contrast. @@ -262,12 +266,12 @@ def positions_from_delta( # noqa: PLR0912, PLR0913, PLR0915 def uniform_positions( - ngal: float | npt.NDArray, # type: ignore[type-arg] + ngal: float | npt.NDArray[typing.Any], *, rng: np.random.Generator | None = None, ) -> typing.Iterator[ # type: ignore[type-arg] - npt.NDArray | list[npt.NDArray], - npt.NDArray | list[npt.NDArray], + npt.NDArray[typing.Any] | list[npt.NDArray[typing.Any]], + npt.NDArray[typing.Any] | list[npt.NDArray[typing.Any]], int | list[int], ]: """ @@ -320,7 +324,9 @@ def uniform_positions( yield lon, lat, count -def position_weights(densities: npt.NDArray, bias: npt.NDArray | None = None): # type: ignore[no-untyped-def, type-arg] +def position_weights( + densities: npt.NDArray[typing.Any], bias: npt.NDArray[typing.Any] | None = None +) -> npt.NDArray[typing.Any]: r""" Compute relative weights for angular clustering. diff --git a/glass/shapes.py b/glass/shapes.py index 4ac08364..2e1cdb22 100644 --- a/glass/shapes.py +++ b/glass/shapes.py @@ -33,12 +33,12 @@ def triaxial_axis_ratio( - zeta: npt.NDArray, # type: ignore[type-arg] - xi: npt.NDArray, # type: ignore[type-arg] + zeta: npt.NDArray[typing.Any], + xi: npt.NDArray[typing.Any], size: tuple[int] | None = None, *, rng: np.random.Generator | None = None, -) -> npt.NDArray: # type: ignore[type-arg] +) -> npt.NDArray[typing.Any]: r""" Axis ratio of a randomly projected triaxial ellipsoid. @@ -104,14 +104,14 @@ def triaxial_axis_ratio( def ellipticity_ryden04( # noqa: PLR0913 - mu: npt.NDArray, # type: ignore[type-arg] - sigma: npt.NDArray, # type: ignore[type-arg] - gamma: npt.NDArray, # type: ignore[type-arg] - sigma_gamma: npt.NDArray, # type: ignore[type-arg] + mu: npt.NDArray[typing.Any], + sigma: npt.NDArray[typing.Any], + gamma: npt.NDArray[typing.Any], + sigma_gamma: npt.NDArray[typing.Any], size: int | tuple[int, ...] | None = None, *, rng: np.random.Generator | None = None, -) -> npt.NDArray: # type: ignore[type-arg] +) -> npt.NDArray[typing.Any]: r""" Ellipticity distribution following Ryden (2004). @@ -185,11 +185,11 @@ def ellipticity_ryden04( # noqa: PLR0913 def ellipticity_gaussian( - count: int | npt.NDArray, # type: ignore[type-arg] - sigma: npt.NDArray, # type: ignore[type-arg] + count: int | npt.NDArray[typing.Any], + sigma: npt.NDArray[typing.Any], *, rng: np.random.Generator | None = None, -) -> npt.NDArray: # type: ignore[type-arg] +) -> npt.NDArray[typing.Any]: r""" Sample Gaussian galaxy ellipticities. @@ -242,11 +242,11 @@ def ellipticity_gaussian( def ellipticity_intnorm( - count: int | npt.NDArray, # type: ignore[type-arg] - sigma: npt.NDArray, # type: ignore[type-arg] + count: int | npt.NDArray[typing.Any], + sigma: npt.NDArray[typing.Any], *, rng: np.random.Generator | None = None, -) -> npt.NDArray: # type: ignore[type-arg] +) -> npt.NDArray[typing.Any]: r""" Sample galaxy ellipticities with intrinsic normal distribution. diff --git a/glass/shells.py b/glass/shells.py index 7230e2b4..2ccecf0c 100644 --- a/glass/shells.py +++ b/glass/shells.py @@ -56,21 +56,27 @@ from cosmology import Cosmology # types -ArrayLike1D = typing.Union[typing.Sequence[float], npt.NDArray] # type: ignore[type-arg] -WeightFunc = typing.Callable[[ArrayLike1D], npt.NDArray] # type: ignore[type-arg] +ArrayLike1D = typing.Union[typing.Sequence[float], npt.NDArray[typing.Any]] +WeightFunc = typing.Callable[[ArrayLike1D], npt.NDArray[typing.Any]] -def distance_weight(z: npt.NDArray, cosmo: Cosmology) -> npt.NDArray: # type: ignore[type-arg] +def distance_weight( + z: npt.NDArray[typing.Any], cosmo: Cosmology +) -> npt.NDArray[typing.Any]: """Uniform weight in comoving distance.""" return 1 / cosmo.ef(z) # type: ignore[no-any-return] -def volume_weight(z: npt.NDArray, cosmo: Cosmology) -> npt.NDArray: # type: ignore[type-arg] +def volume_weight( + z: npt.NDArray[typing.Any], cosmo: Cosmology +) -> npt.NDArray[typing.Any]: """Uniform weight in comoving volume.""" return cosmo.xm(z) ** 2 / cosmo.ef(z) # type: ignore[no-any-return] -def density_weight(z: npt.NDArray, cosmo: Cosmology) -> npt.NDArray: # type: ignore[type-arg] +def density_weight( + z: npt.NDArray[typing.Any], cosmo: Cosmology +) -> npt.NDArray[typing.Any]: """Uniform weight in matter density.""" return cosmo.rho_m_z(z) * cosmo.xm(z) ** 2 / cosmo.ef(z) # type: ignore[no-any-return] @@ -310,7 +316,7 @@ def restrict( z: ArrayLike1D, f: ArrayLike1D, w: RadialWindow, -) -> tuple[npt.NDArray, npt.NDArray]: # type: ignore[type-arg] +) -> tuple[npt.NDArray[typing.Any], npt.NDArray[typing.Any]]: """ Restrict a function to a redshift window. @@ -348,12 +354,12 @@ def restrict( def partition( - z: npt.NDArray, # type: ignore[type-arg] - fz: npt.NDArray, # type: ignore[type-arg] + z: npt.NDArray[typing.Any], + fz: npt.NDArray[typing.Any], shells: typing.Sequence[RadialWindow], *, method: str = "nnls", -) -> npt.NDArray: # type: ignore[type-arg] +) -> npt.NDArray[typing.Any]: r""" Partition a function by a sequence of windows. @@ -458,12 +464,12 @@ def partition( def partition_lstsq( - z: npt.NDArray, # type: ignore[type-arg] - fz: npt.NDArray, # type: ignore[type-arg] + z: npt.NDArray[typing.Any], + fz: npt.NDArray[typing.Any], shells: typing.Sequence[RadialWindow], *, sumtol: float = 0.01, -) -> npt.NDArray: # type: ignore[type-arg] +) -> npt.NDArray[typing.Any]: """Least-squares partition.""" # make sure nothing breaks sumtol = max(sumtol, 1e-4) @@ -504,12 +510,12 @@ def partition_lstsq( def partition_nnls( - z: npt.NDArray, # type: ignore[type-arg] - fz: npt.NDArray, # type: ignore[type-arg] + z: npt.NDArray[typing.Any], + fz: npt.NDArray[typing.Any], shells: typing.Sequence[RadialWindow], *, sumtol: float = 0.01, -) -> npt.NDArray: # type: ignore[type-arg] +) -> npt.NDArray[typing.Any]: """ Non-negative least-squares partition. @@ -565,10 +571,10 @@ def partition_nnls( def partition_restrict( - z: npt.NDArray, # type: ignore[type-arg] - fz: npt.NDArray, # type: ignore[type-arg] + z: npt.NDArray[typing.Any], + fz: npt.NDArray[typing.Any], shells: typing.Sequence[RadialWindow], -) -> npt.NDArray: # type: ignore[type-arg] +) -> npt.NDArray[typing.Any]: """Partition by restriction and integration.""" part = np.empty((len(shells),) + np.shape(fz)[:-1]) for i, w in enumerate(shells): @@ -612,10 +618,10 @@ def distance_grid( def combine( - z: npt.NDArray, # type: ignore[type-arg] - weights: npt.NDArray, # type: ignore[type-arg] + z: npt.NDArray[typing.Any], + weights: npt.NDArray[typing.Any], shells: typing.Sequence[RadialWindow], -) -> npt.NDArray: # type: ignore[type-arg] +) -> npt.NDArray[typing.Any]: r""" Evaluate a linear combination of window functions. diff --git a/glass/user.py b/glass/user.py index 8e8da00a..b3e23fe7 100644 --- a/glass/user.py +++ b/glass/user.py @@ -26,7 +26,7 @@ import numpy.typing as npt -def save_cls(filename: str, cls: list[npt.NDArray | None]) -> None: # type: ignore[type-arg] +def save_cls(filename: str, cls: list[npt.NDArray[typing.Any] | None]) -> None: """ Save a list of Cls to file. @@ -39,7 +39,7 @@ def save_cls(filename: str, cls: list[npt.NDArray | None]) -> None: # type: ign np.savez(filename, values=values, split=split) -def load_cls(filename: str) -> list[npt.NDArray]: # type: ignore[type-arg] +def load_cls(filename: str) -> list[npt.NDArray[typing.Any]]: """ Load a list of Cls from file. @@ -64,7 +64,9 @@ def __init__(self, fits, ext: str | None = None) -> None: # type: ignore[no-unt self.fits = fits self.ext = ext - def _append(self, data: npt.NDArray, names: list[str] | None = None) -> None: # type: ignore[type-arg] + def _append( + self, data: npt.NDArray[typing.Any], names: list[str] | None = None + ) -> None: """Write the FITS file.""" if self.ext is None or self.ext not in self.fits: self.fits.write_table(data, names=names, extname=self.ext) @@ -75,7 +77,12 @@ def _append(self, data: npt.NDArray, names: list[str] | None = None) -> None: # # not using hdu.append here because of incompatibilities hdu.write(data, names=names, firstrow=hdu.get_nrows()) - def write(self, data: npt.NDArray | None = None, /, **columns: npt.NDArray) -> None: # type: ignore[type-arg] + def write( + self, + data: npt.NDArray[typing.Any] | None = None, + /, + **columns: npt.NDArray[typing.Any], + ) -> None: """ Write to FITS by calling the internal _append method. From cc231ed1a8fe5a7163bda40dfeaf8bad7da47f1c Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Mon, 14 Oct 2024 13:47:54 +0100 Subject: [PATCH 27/32] Fix `mypy` --- tests/test_galaxies.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_galaxies.py b/tests/test_galaxies.py index 54ba4f58..02e82fac 100644 --- a/tests/test_galaxies.py +++ b/tests/test_galaxies.py @@ -92,7 +92,7 @@ def test_redshifts_from_nz() -> None: redshifts = redshifts_from_nz(10, [0, 1, 2, 3, 4], [1, 0, 0, 0, 0]) # type: ignore[arg-type] -def test_galaxy_shear(rng): +def test_galaxy_shear(rng) -> None: # type: ignore[no-untyped-def] # check shape of the output kappa, gamma1, gamma2 = ( @@ -101,7 +101,7 @@ def test_galaxy_shear(rng): rng.normal(size=(12,)), ) - shear = galaxy_shear([], [], [], kappa, gamma1, gamma2) + shear = galaxy_shear([], [], [], kappa, gamma1, gamma2) # type: ignore[arg-type] np.testing.assert_equal(shear, []) gal_lon, gal_lat, gal_eps = ( @@ -114,7 +114,7 @@ def test_galaxy_shear(rng): # shape with no reduced shear - shear = galaxy_shear([], [], [], kappa, gamma1, gamma2, reduced_shear=False) + shear = galaxy_shear([], [], [], kappa, gamma1, gamma2, reduced_shear=False) # type: ignore[arg-type] np.testing.assert_equal(shear, []) gal_lon, gal_lat, gal_eps = ( From 12723f8d7471efafbf5ddc4c831f1b597c69d77b Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Tue, 15 Oct 2024 12:26:40 +0100 Subject: [PATCH 28/32] Fix linting --- glass/core/algorithm.py | 2 ++ glass/fields.py | 7 +++---- glass/observations.py | 1 + glass/shapes.py | 4 +++- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/glass/core/algorithm.py b/glass/core/algorithm.py index 71cc4a2e..94257fad 100644 --- a/glass/core/algorithm.py +++ b/glass/core/algorithm.py @@ -1,7 +1,9 @@ """Core module for algorithms.""" from __future__ import annotations + import typing + import numpy as np import numpy.typing as npt diff --git a/glass/fields.py b/glass/fields.py index 4b6965fb..f504ce93 100644 --- a/glass/fields.py +++ b/glass/fields.py @@ -35,16 +35,15 @@ import numpy.typing as npt from gaussiancl import gaussiancl -if typing.TYPE_CHECKING: - import collections.abc - # types Size = typing.Optional[typing.Union[int, tuple[int, ...]]] Iternorm = tuple[typing.Optional[int], npt.NDArray[typing.Any], npt.NDArray[typing.Any]] ClTransform = typing.Union[ str, typing.Callable[[npt.NDArray[typing.Any]], npt.NDArray[typing.Any]] ] -Cls = collections.abc.Sequence[typing.Union[npt.NDArray[typing.Any], collections.abc.Sequence[float]]] +Cls = collections.abc.Sequence[ + typing.Union[npt.NDArray[typing.Any], collections.abc.Sequence[float]] +] Alms = npt.NDArray[typing.Any] diff --git a/glass/observations.py b/glass/observations.py index 5d225a3f..47c60678 100644 --- a/glass/observations.py +++ b/glass/observations.py @@ -29,6 +29,7 @@ from __future__ import annotations import math +import typing import healpy as hp import numpy as np diff --git a/glass/shapes.py b/glass/shapes.py index 0781aa04..80e942a8 100644 --- a/glass/shapes.py +++ b/glass/shapes.py @@ -24,9 +24,11 @@ from __future__ import annotations +import typing + import numpy as np import numpy.typing as npt -import typing + def triaxial_axis_ratio( zeta: npt.NDArray[typing.Any], From 52b2fc8e4e26176fc8ed6a08edae58039ba8d2a4 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Tue, 15 Oct 2024 12:27:15 +0100 Subject: [PATCH 29/32] Undo `.gitignore` --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index 485375d0..93b4e32e 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,3 @@ dist .env .coverage* coverage* -mypy_error_report.txt From 74a94deca2ebcb479fd67084ad17fa1ee3c42d8c Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Tue, 15 Oct 2024 12:45:14 +0100 Subject: [PATCH 30/32] Fix `mypy` --- glass/fields.py | 2 +- glass/galaxies.py | 6 +++--- glass/lensing.py | 2 +- glass/observations.py | 2 +- glass/points.py | 2 +- glass/shapes.py | 2 +- glass/shells.py | 8 ++++---- tests/core/test_algorithm.py | 2 +- tests/core/test_array.py | 10 +++++----- tests/test_fits.py | 2 +- tests/test_lensing.py | 2 +- tests/test_points.py | 2 +- tests/test_shapes.py | 2 +- tests/test_shells.py | 4 ++-- 14 files changed, 24 insertions(+), 24 deletions(-) diff --git a/glass/fields.py b/glass/fields.py index dafd1f6d..f504ce93 100644 --- a/glass/fields.py +++ b/glass/fields.py @@ -432,7 +432,7 @@ def effective_cls( for j1, j2 in pairs: w1, w2 = weights1[c + j1], weights2[c + j2] cl = sum( - w1[i1] * w2[i2] * getcl(cls, i1, i2, lmax=lmax) # type: ignore[no-untyped-call] + w1[i1] * w2[i2] * getcl(cls, i1, i2, lmax=lmax) for i1, i2 in np.ndindex(n, n) ) out[j1 + j2] = cl diff --git a/glass/galaxies.py b/glass/galaxies.py index 2ab974f8..018255ba 100644 --- a/glass/galaxies.py +++ b/glass/galaxies.py @@ -129,7 +129,7 @@ def redshifts_from_nz( redshifts[total : total + count[k]] = np.interp( # type: ignore[index] rng.uniform(0, 1, size=count[k]), # type: ignore[index] cdf, - z[k], # type: ignore[arg-type, call-overload, index] + z[k], ) total += count[k] # type: ignore[index] @@ -264,7 +264,7 @@ def gaussian_phz( sigma = np.add(1, z) * sigma_0 dims = np.shape(sigma) - zphot = rng.normal(z, sigma) # type: ignore[arg-type] + zphot = rng.normal(z, sigma) if lower is None: lower = 0.0 # type: ignore[assignment] @@ -286,4 +286,4 @@ def gaussian_phz( zphot[trunc] = znew trunc = trunc[(znew < lower) | (znew > upper)] # type: ignore[operator] - return zphot # type: ignore[return-value] + return zphot diff --git a/glass/lensing.py b/glass/lensing.py index b2238b0c..0f6ad97b 100644 --- a/glass/lensing.py +++ b/glass/lensing.py @@ -293,7 +293,7 @@ def add_window(self, delta: npt.NDArray[typing.Any], w: RadialWindow) -> None: """ zsrc = w.zeff - lens_weight = np.trapz(w.wa, w.za) / np.interp(zsrc, w.za, w.wa) # type: ignore[attr-defined] + lens_weight = np.trapz(w.wa, w.za) / np.interp(zsrc, w.za, w.wa) # type: ignore[arg-type, attr-defined] self.add_plane(delta, zsrc, lens_weight) # type: ignore[arg-type] diff --git a/glass/observations.py b/glass/observations.py index 869273d9..47c60678 100644 --- a/glass/observations.py +++ b/glass/observations.py @@ -262,7 +262,7 @@ def equal_dens_zbins( # first compute the cumulative integral (by trapezoidal rule) # then normalise: the first z is at CDF = 0, the last z at CDF = 1 # interpolate to find the z values at CDF = i/nbins for i = 0, ..., nbins - cuml_nz = cumtrapz(nz, z) # type: ignore[no-untyped-call] + cuml_nz = cumtrapz(nz, z) cuml_nz /= cuml_nz[[-1]] zbinedges = np.interp(np.linspace(0, 1, nbins + 1), cuml_nz, z) diff --git a/glass/points.py b/glass/points.py index 34efc9e8..9314393a 100644 --- a/glass/points.py +++ b/glass/points.py @@ -357,7 +357,7 @@ def position_weights( """ # bring densities and bias into the same shape if bias is not None: - densities, bias = broadcast_first(densities, bias) # type: ignore[no-untyped-call] + densities, bias = broadcast_first(densities, bias) # normalise densities after shape has been fixed densities = densities / np.sum(densities, axis=0) # apply bias after normalisation diff --git a/glass/shapes.py b/glass/shapes.py index 8a450361..80e942a8 100644 --- a/glass/shapes.py +++ b/glass/shapes.py @@ -175,7 +175,7 @@ def ellipticity_ryden04( # noqa: PLR0913 xi = (1 - gam) * zeta # random projection of random triaxial ellipsoid - q = triaxial_axis_ratio(zeta, xi, rng=rng) # type: ignore[no-untyped-call] + q = triaxial_axis_ratio(zeta, xi, rng=rng) # assemble ellipticity with random complex phase e = np.exp(1j * rng.uniform(0, 2 * np.pi, size=np.shape(q))) diff --git a/glass/shells.py b/glass/shells.py index e9d07a55..37e3e30f 100644 --- a/glass/shells.py +++ b/glass/shells.py @@ -480,7 +480,7 @@ def partition_lstsq( a = a * dz # create the target vector of distribution values - b = ndinterp(zp, z, fz, left=0.0, right=0.0) # type: ignore[no-untyped-call] + b = ndinterp(zp, z, fz, left=0.0, right=0.0) b = b * dz # append a constraint for the integral @@ -534,7 +534,7 @@ def partition_nnls( a = a * dz # create the target vector of distribution values - b = ndinterp(zp, z, fz, left=0.0, right=0.0) # type: ignore[no-untyped-call] + b = ndinterp(zp, z, fz, left=0.0, right=0.0) b = b * dz # append a constraint for the integral @@ -643,11 +643,11 @@ def combine( return sum( # type: ignore[return-value] np.expand_dims(weight, -1) * np.interp( - z, # type: ignore[arg-type] + z, shell.za, shell.wa / np.trapz(shell.wa, shell.za), # type: ignore[attr-defined] left=0.0, right=0.0, ) - for shell, weight in zip(shells, weights) # type: ignore[arg-type] + for shell, weight in zip(shells, weights) ) diff --git a/tests/core/test_algorithm.py b/tests/core/test_algorithm.py index 450eaa85..11179edf 100644 --- a/tests/core/test_algorithm.py +++ b/tests/core/test_algorithm.py @@ -21,7 +21,7 @@ def test_nnls(rng) -> None: # type: ignore[no-untyped-def] x_glass = nnls_glass(a, b) x_scipy, _ = nnls_scipy(a, b) - np.testing.assert_allclose(x_glass, x_scipy) # type: ignore[arg-type] + np.testing.assert_allclose(x_glass, x_scipy) # check matrix and vector's shape diff --git a/tests/core/test_array.py b/tests/core/test_array.py index e7266ba5..f023a3f5 100644 --- a/tests/core/test_array.py +++ b/tests/core/test_array.py @@ -21,7 +21,7 @@ def test_broadcast_first() -> None: # arrays with shape ((3, 4, 2)) and ((1, 2)) are passed # to np.broadcast_arrays; hence it works - a_a, b_a = broadcast_first(a, b) # type: ignore[no-untyped-call] + a_a, b_a = broadcast_first(a, b) assert a_a.shape == (2, 3, 4) assert b_a.shape == (2, 3, 4) @@ -35,7 +35,7 @@ def test_broadcast_first() -> None: b = np.ones((5, 6)) with pytest.raises(ValueError, match="shape mismatch"): - broadcast_first(a, b) # type: ignore[no-untyped-call] + broadcast_first(a, b) # plain np.broadcast_arrays will work a_a, b_a = np.broadcast_arrays(a, b) @@ -147,7 +147,7 @@ def test_trapz_product() -> None: x2 = np.linspace(1, 2, 10) f2 = np.full_like(x2, 0.5) - s = trapz_product((x1, f1), (x2, f2)) # type: ignore[no-untyped-call] + s = trapz_product((x1, f1), (x2, f2)) np.testing.assert_allclose(s, 1.0) @@ -163,7 +163,7 @@ def test_cumtrapz() -> None: # default dtype (int - not supported by scipy) - glass_ct = cumtrapz(f, x) # type: ignore[no-untyped-call] + glass_ct = cumtrapz(f, x) np.testing.assert_allclose(glass_ct, np.array([0, 1, 4, 7])) # explicit dtype (float) @@ -185,7 +185,7 @@ def test_cumtrapz() -> None: # default dtype (int - not supported by scipy) - glass_ct = cumtrapz(f, x) # type: ignore[no-untyped-call] + glass_ct = cumtrapz(f, x) np.testing.assert_allclose(glass_ct, np.array([[0, 2, 12, 31], [0, 2, 8, 17]])) # explicit dtype (float) diff --git a/tests/test_fits.py b/tests/test_fits.py index 41a5ee7c..906b18e7 100644 --- a/tests/test_fits.py +++ b/tests/test_fits.py @@ -44,7 +44,7 @@ def test_basic_write(tmp_path: os.PathLike) -> None: # type: ignore[type-arg] out.write(RA=array, RB=array2) arrays = [array, array2] names = ["RA", "RB"] - _test_append(my_fits, arrays, names) # type: ignore[no-untyped-call] + _test_append(my_fits, arrays, names) with ( fitsio.FITS(tmp_path / filename_gfits) as g_fits, # type: ignore[operator] diff --git a/tests/test_lensing.py b/tests/test_lensing.py index 8396d512..ba3689be 100644 --- a/tests/test_lensing.py +++ b/tests/test_lensing.py @@ -125,4 +125,4 @@ def test_multi_plane_weights(shells, cosmo, rng) -> None: # type: ignore[no-unt wmat = multi_plane_weights(weights, shells, cosmo) - np.testing.assert_allclose(np.einsum("ij,ik", wmat, deltas), kappa) # type: ignore[arg-type] + np.testing.assert_allclose(np.einsum("ij,ik", wmat, deltas), kappa) diff --git a/tests/test_points.py b/tests/test_points.py index a42d9be5..ceb20401 100644 --- a/tests/test_points.py +++ b/tests/test_points.py @@ -100,7 +100,7 @@ def test_position_weights(rng: np.random.Generator) -> None: counts = rng.random(cshape) bias = None if bshape is None else rng.random(bshape) - weights = position_weights(counts, bias) # type: ignore[no-untyped-call] + weights = position_weights(counts, bias) expected = counts / counts.sum(axis=0, keepdims=True) if bias is not None: diff --git a/tests/test_shapes.py b/tests/test_shapes.py index af071974..b234ed2b 100644 --- a/tests/test_shapes.py +++ b/tests/test_shapes.py @@ -42,7 +42,7 @@ def test_triaxial_axis_ratio() -> None: zeta, xi = np.sort(np.random.uniform(0, 1, size=(2, 1000)), axis=0) qmin = np.min([zeta, xi, xi / zeta], axis=0) qmax = np.max([zeta, xi, xi / zeta], axis=0) - q = triaxial_axis_ratio(zeta, xi) # type: ignore[no-untyped-call] + q = triaxial_axis_ratio(zeta, xi) assert np.all((qmax >= q) & (q >= qmin)) diff --git a/tests/test_shells.py b/tests/test_shells.py index a6ea5509..8a49f46e 100644 --- a/tests/test_shells.py +++ b/tests/test_shells.py @@ -27,7 +27,7 @@ def test_restrict() -> None: f = np.exp(-(((z - 2.0) / 0.5) ** 2) / 2) # window for restriction - w = RadialWindow(za=[1.0, 2.0, 3.0, 4.0], wa=[0.0, 0.5, 0.5, 0.0], zeff=None) # type: ignore[arg-type] + w = RadialWindow(za=[1.0, 2.0, 3.0, 4.0], wa=[0.0, 0.5, 0.5, 0.0], zeff=None) zr, fr = restrict(z, f, w) @@ -67,6 +67,6 @@ def test_partition(method) -> None: # type: ignore[no-untyped-def] part = partition(z, fz, shells, method=method) - assert part.shape == (len(shells), 3, 2) # type: ignore[union-attr] + assert part.shape == (len(shells), 3, 2) np.testing.assert_allclose(part.sum(axis=0), np.trapz(fz, z)) # type: ignore[attr-defined] From 2e2020f0ff06375388818ce01a6b0fa9bddb83de Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Tue, 15 Oct 2024 12:48:17 +0100 Subject: [PATCH 31/32] Fix merge --- tests/test_shapes.py | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/tests/test_shapes.py b/tests/test_shapes.py index 68a37ad8..6b65f75d 100644 --- a/tests/test_shapes.py +++ b/tests/test_shapes.py @@ -9,7 +9,7 @@ ) -def test_triaxial_axis_ratio(rng) -> None: +def test_triaxial_axis_ratio(rng: np.random.Generator) -> None: # single axis ratio q = triaxial_axis_ratio(0.8, 0.4) # type: ignore[arg-type] @@ -131,10 +131,5 @@ def test_ellipticity_intnorm() -> None: np.testing.assert_allclose(np.std(eps.real[n:]), 0.256, atol=1e-3, rtol=0) np.testing.assert_allclose(np.std(eps.imag[n:]), 0.256, atol=1e-3, rtol=0) -<<<<<<< HEAD - with pytest.raises(ValueError): - ellipticity_intnorm(1, 0.71) # type: ignore[arg-type] -======= with pytest.raises(ValueError, match="sigma must be between"): - ellipticity_intnorm(1, 0.71) ->>>>>>> main + ellipticity_intnorm(1, 0.71) # type: ignore[arg-type] From bc62666bb2f951c83094d2d66df737c36144bdc0 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Tue, 15 Oct 2024 12:55:14 +0100 Subject: [PATCH 32/32] New line --- tests/test_lensing.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_lensing.py b/tests/test_lensing.py index ba3689be..4decb819 100644 --- a/tests/test_lensing.py +++ b/tests/test_lensing.py @@ -49,6 +49,7 @@ def test_deflect_nsew(usecomplex: bool) -> None: # noqa: FBT001 def alpha(re, im): # type: ignore[no-untyped-def] return re + 1j * im + else: def alpha(re, im): # type: ignore[no-untyped-def]