From 4ba78c198557593ec967fc071192fb1b8d619a5f Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Thu, 3 Oct 2024 10:55:01 +0100 Subject: [PATCH 001/143] 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 002/143] 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 003/143] 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 004/143] 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 005/143] 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 006/143] 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 007/143] 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 008/143] 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 009/143] 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 010/143] 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 011/143] 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 012/143] 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 013/143] 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 014/143] 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 015/143] 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 016/143] 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 017/143] 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 018/143] 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 019/143] 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 020/143] `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 021/143] 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 022/143] 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 023/143] 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 024/143] 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 025/143] 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 026/143] 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 027/143] 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 028/143] 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 029/143] 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 030/143] 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 031/143] 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 032/143] 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] From c1fdd6d680db476dffa902019ea9617d2b79a0f1 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Tue, 15 Oct 2024 15:03:11 +0100 Subject: [PATCH 033/143] Fix formatting --- examples/2-advanced/cosmic_shear.ipynb | 7 ++++++- examples/2-advanced/stage_4_galaxies.ipynb | 12 ++++++++++-- glass/ext/__init__.py | 2 +- glass/fields.py | 11 ++++++++--- glass/lensing.py | 5 ++++- glass/points.py | 6 ++++-- glass/shells.py | 18 +++++++++++++----- glass/user.py | 8 ++++++-- noxfile.py | 5 ++++- tests/test_galaxies.py | 8 +++++++- 10 files changed, 63 insertions(+), 19 deletions(-) diff --git a/examples/2-advanced/cosmic_shear.ipynb b/examples/2-advanced/cosmic_shear.ipynb index 76a36934..2309a397 100644 --- a/examples/2-advanced/cosmic_shear.ipynb +++ b/examples/2-advanced/cosmic_shear.ipynb @@ -219,7 +219,12 @@ "\n", " # apply the shear fields to the ellipticities\n", " gal_she = glass.galaxy_shear(\n", - " gal_lon, gal_lat, gal_eps, kappa_i, gamm1_i, gamm2_i\n", + " gal_lon,\n", + " gal_lat,\n", + " gal_eps,\n", + " kappa_i,\n", + " gamm1_i,\n", + " gamm2_i,\n", " )\n", "\n", " # map the galaxy shears to a HEALPix map; this is opaque but works\n", diff --git a/examples/2-advanced/stage_4_galaxies.ipynb b/examples/2-advanced/stage_4_galaxies.ipynb index 1db2ccea..538f29e6 100644 --- a/examples/2-advanced/stage_4_galaxies.ipynb +++ b/examples/2-advanced/stage_4_galaxies.ipynb @@ -276,7 +276,10 @@ "\n", " # generate galaxy positions from the matter density contrast\n", " for gal_lon, gal_lat, gal_count in glass.positions_from_delta(\n", - " ngal[i], delta_i, bias, vis\n", + " ngal[i],\n", + " delta_i,\n", + " bias,\n", + " vis,\n", " ):\n", " # generate random redshifts over the given shell\n", " gal_z = glass.redshifts(gal_count, ws[i])\n", @@ -292,7 +295,12 @@ "\n", " # apply the shear fields to the ellipticities\n", " gal_she = glass.galaxy_shear(\n", - " gal_lon, gal_lat, gal_eps, kappa_i, gamm1_i, gamm2_i\n", + " gal_lon,\n", + " gal_lat,\n", + " gal_eps,\n", + " kappa_i,\n", + " gamm1_i,\n", + " gamm2_i,\n", " )\n", "\n", " # make a mini-catalogue for the new rows\n", diff --git a/glass/ext/__init__.py b/glass/ext/__init__.py index ad17a437..eba224bb 100644 --- a/glass/ext/__init__.py +++ b/glass/ext/__init__.py @@ -17,7 +17,7 @@ def _extend_path(path, name) -> list: # type: ignore[no-untyped-def, type-arg] filter( os.path.isdir, (os.path.join(p, _mod) for p in extend_path(path, _pkg)), # noqa: PTH118 - ) + ), ) diff --git a/glass/fields.py b/glass/fields.py index f504ce93..a83352c7 100644 --- a/glass/fields.py +++ b/glass/fields.py @@ -39,7 +39,8 @@ 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]] + 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]] @@ -110,7 +111,10 @@ def iternorm( def cls2cov( - cls: Cls, nl: int, nf: int, nc: int + cls: Cls, + nl: int, + nf: int, + nc: int, ) -> 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)) @@ -149,7 +153,8 @@ def transform_cls(cls: Cls, tfm: ClTransform, pars: tuple[typing.Any, ...] = ()) gl, info, _, _ = gaussiancl(cl, tfm, pars, monopole=monopole) if info == 0: warnings.warn( - "Gaussian cl did not converge, inexact transform", stacklevel=2 + "Gaussian cl did not converge, inexact transform", + stacklevel=2, ) else: gl = [] diff --git a/glass/lensing.py b/glass/lensing.py index 0f6ad97b..86a0a719 100644 --- a/glass/lensing.py +++ b/glass/lensing.py @@ -298,7 +298,10 @@ def add_window(self, delta: npt.NDArray[typing.Any], w: RadialWindow) -> None: self.add_plane(delta, zsrc, lens_weight) # type: ignore[arg-type] def add_plane( - self, delta: npt.NDArray[typing.Any], zsrc: float, wlens: float = 1.0 + 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: diff --git a/glass/points.py b/glass/points.py index 9314393a..d4eefba4 100644 --- a/glass/points.py +++ b/glass/points.py @@ -87,7 +87,8 @@ def effective_bias( def linear_bias( - delta: npt.NDArray[typing.Any], b: float | npt.NDArray[typing.Any] + 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] @@ -328,7 +329,8 @@ def uniform_positions( def position_weights( - densities: npt.NDArray[typing.Any], bias: npt.NDArray[typing.Any] | None = None + 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/shells.py b/glass/shells.py index 37e3e30f..63daf9d2 100644 --- a/glass/shells.py +++ b/glass/shells.py @@ -62,21 +62,24 @@ def distance_weight( - z: npt.NDArray[typing.Any], cosmo: Cosmology + 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[typing.Any], cosmo: Cosmology + 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[typing.Any], cosmo: Cosmology + 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] @@ -171,7 +174,8 @@ def tophat_windows( raise ValueError(msg) if zbins[0] != 0: warnings.warn( - "first tophat window does not start at redshift zero", stacklevel=2 + "first tophat window does not start at redshift zero", + stacklevel=2, ) wht: WeightFunc @@ -573,7 +577,11 @@ def partition_restrict( def redshift_grid( - zmin: float, zmax: float, *, dz: float | None = None, num: int | None = None + zmin: float, + zmax: float, + *, + dz: float | None = None, + num: int | None = None, ) -> npt.NDArray[np.float64]: """Redshift grid with uniform spacing in redshift.""" if dz is not None and num is None: diff --git a/glass/user.py b/glass/user.py index f5ef0563..7fb4d308 100644 --- a/glass/user.py +++ b/glass/user.py @@ -65,7 +65,9 @@ def __init__(self, fits, ext: str | None = None) -> None: # type: ignore[no-unt self.ext = ext def _append( - self, data: npt.NDArray[typing.Any], names: list[str] | None = None + 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: @@ -101,7 +103,9 @@ def write( @contextmanager def write_catalog( - filename: str, *, ext: str | None = None + filename: str, + *, + ext: str | None = None, ) -> typing.Iterator[_FitsWriter]: """ Write a catalogue into a FITS file. diff --git a/noxfile.py b/noxfile.py index 26aeb950..269a58fe 100644 --- a/noxfile.py +++ b/noxfile.py @@ -50,7 +50,10 @@ def examples(session: nox.Session) -> None: """Run the example notebooks.""" session.install("-e", ".[examples]") session.run( - "jupyter", "execute", *Path().glob("examples/**/*.ipynb"), *session.posargs + "jupyter", + "execute", + *Path().glob("examples/**/*.ipynb"), + *session.posargs, ) diff --git a/tests/test_galaxies.py b/tests/test_galaxies.py index 7ef17e38..4f31cd5d 100644 --- a/tests/test_galaxies.py +++ b/tests/test_galaxies.py @@ -123,7 +123,13 @@ def test_galaxy_shear(rng) -> None: # type: ignore[no-untyped-def] rng.normal(size=(512,)), ) shear = galaxy_shear( - gal_lon, gal_lat, gal_eps, kappa, gamma1, gamma2, reduced_shear=False + gal_lon, + gal_lat, + gal_eps, + kappa, + gamma1, + gamma2, + reduced_shear=False, ) assert np.shape(shear) == (512,) From 6d6d4476ae83a38e3b34d9cb29db187d20b2f449 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Tue, 15 Oct 2024 15:40:22 +0100 Subject: [PATCH 034/143] Fix `Returns` in docstrings (I think entered in #357) --- glass/observations.py | 44 +++++++++++++------------------------------ glass/points.py | 14 ++++---------- glass/shapes.py | 28 ++++++++------------------- 3 files changed, 25 insertions(+), 61 deletions(-) diff --git a/glass/observations.py b/glass/observations.py index 47c60678..81150183 100644 --- a/glass/observations.py +++ b/glass/observations.py @@ -50,6 +50,8 @@ def vmap_galactic_ecliptic( the galactic and ecliptic planes. The location of the stripes is set with optional parameters. + Returns a HEALPix :term:`visibility map`. + Parameters ---------- nside: @@ -59,11 +61,6 @@ def vmap_galactic_ecliptic( ecliptic: The location of the ecliptic plane in the respective coordinate system. - Returns - ------- - vis: - A HEALPix :term:`visibility map`. - Raises ------ TypeError @@ -100,6 +97,8 @@ def gaussian_nz( If ``mean`` or ``sigma`` are array_like, their axes will be the leading axes of the redshift distribution. + Returns the redshift distribution at the given ``z`` values. + Parameters ---------- z: @@ -111,11 +110,6 @@ def gaussian_nz( norm: If given, the normalisation of the distribution. - Returns - ------- - nz: - Redshift distribution at the given ``z`` values. - """ mean = np.reshape(mean, np.shape(mean) + (1,) * np.ndim(z)) sigma = np.reshape(sigma, np.shape(sigma) + (1,) * np.ndim(z)) @@ -142,6 +136,8 @@ def smail_nz( The redshift follows the Smail et al. [1] redshift distribution. + Returns the redshift distribution at the given ``z`` values. + Parameters ---------- z: @@ -155,11 +151,6 @@ def smail_nz( norm: If given, the normalisation of the distribution. - Returns - ------- - pz: - Redshift distribution at the given ``z`` values. - Notes ----- The probability distribution function :math:`p(z)` for redshift :math:`z` @@ -204,6 +195,8 @@ def fixed_zbins( This function creates contiguous tomographic redshift bins of fixed size. It takes either the number or size of the bins. + Returns a list of redshift bin edges. + Parameters ---------- zmin: @@ -215,11 +208,6 @@ def fixed_zbins( dz: Size of redshift bin. Only one of ``nbins`` and ``dz`` can be given. - Returns - ------- - zbins: - List of redshift bin edges. - """ if nbins is not None and dz is None: zbinedges = np.linspace(zmin, zmax, nbins + 1) @@ -243,6 +231,8 @@ def equal_dens_zbins( This function subdivides a source redshift distribution into ``nbins`` tomographic redshift bins with equal density. + Returns a list of redshift bin edges. + Parameters ---------- z: @@ -252,11 +242,6 @@ def equal_dens_zbins( nbins: Number of redshift bins. - Returns - ------- - zbins: - List of redshift bin edges. - """ # compute the normalised cumulative distribution function # first compute the cumulative integral (by trapezoidal rule) @@ -285,6 +270,9 @@ def tomo_nz_gausserr( standard deviation of the Gaussian depends on redshift and is given by ``sigma(z) = sigma_0*(1 + z)``. + Returns the tomographic redshift bins convolved with a gaussian error. + Array has a shape (nbins, len(z)) + Parameters ---------- z: @@ -296,12 +284,6 @@ def tomo_nz_gausserr( zbins: List of redshift bin edges. - Returns - ------- - binned_nz: - Tomographic redshift bins convolved with a gaussian error. - Array has a shape (nbins, len(z)) - See Also -------- equal_dens_zbins: diff --git a/glass/points.py b/glass/points.py index d4eefba4..003dd4e1 100644 --- a/glass/points.py +++ b/glass/points.py @@ -57,6 +57,8 @@ def effective_bias( and computes an effective bias parameter :math:`\bar{b}` for a given window function :math:`w(z)`. + Returns the effective bias parameter for the window. + Parameters ---------- z: @@ -66,11 +68,6 @@ def effective_bias( w: The radial window function :math:`w(z)`. - Returns - ------- - beff: - Effective bias parameter for the window. - Notes ----- The effective bias parameter :math:`\bar{b}` is computed using the @@ -343,6 +340,8 @@ def position_weights( redshift distribution and bias factor :math:`n(z) \, b(z)` for the discretised shells. + Returns the relative weight of each shell for angular clustering. + Parameters ---------- densities: @@ -351,11 +350,6 @@ def position_weights( bias: Value or values of the linear bias parameter for each shell. - Returns - ------- - weights: - Relative weight of each shell for angular clustering. - """ # bring densities and bias into the same shape if bias is not None: diff --git a/glass/shapes.py b/glass/shapes.py index 80e942a8..7989e364 100644 --- a/glass/shapes.py +++ b/glass/shapes.py @@ -43,6 +43,8 @@ def triaxial_axis_ratio( Given the two axis ratios `1 >= zeta >= xi` of a randomly oriented triaxial ellipsoid, computes the axis ratio `q` of the projection. + Returns the axis ratio of the randomly projected ellipsoid. + Parameters ---------- zeta: @@ -55,11 +57,6 @@ def triaxial_axis_ratio( rng: Random number generator. If not given, a default RNG will be used. - Returns - ------- - q: - Axis ratio of the randomly projected ellipsoid. - Notes ----- See equations (11) and (12) in [1] for details. @@ -120,6 +117,8 @@ def ellipticity_ryden04( # noqa: PLR0913 standard deviation :math:`\sigma_\gamma` [2]. Both distributions are truncated to produce ratios in the range 0 to 1 using rejection sampling. + Returns an array of :term:`ellipticity` from projected axis ratios. + Parameters ---------- mu: @@ -135,11 +134,6 @@ def ellipticity_ryden04( # noqa: PLR0913 rng: Random number generator. If not given, a default RNG will be used. - Returns - ------- - eps: - Array of :term:`ellipticity` from projected axis ratios. - References ---------- * [1] Ryden B. S., 2004, ApJ, 601, 214. @@ -200,6 +194,8 @@ def ellipticity_gaussian( this function with too large values of ``sigma``, or the sampling will become inefficient. + Returns an array of galaxy :term:`ellipticity`. + Parameters ---------- count: @@ -209,11 +205,6 @@ def ellipticity_gaussian( rng: Random number generator. If not given, a default RNG is used. - Returns - ------- - eps: - Array of galaxy :term:`ellipticity`. - """ # default RNG if not provided if rng is None: @@ -254,6 +245,8 @@ def ellipticity_intnorm( The ellipticities are sampled from an intrinsic normal distribution with standard deviation ``sigma`` for each component. + Returns an array of galaxy :term:`ellipticity`. + Parameters ---------- count: @@ -263,11 +256,6 @@ def ellipticity_intnorm( rng: Random number generator. If not given, a default RNG is used. - Returns - ------- - eps: - Array of galaxy :term:`ellipticity`. - """ # default RNG if not provided if rng is None: From 484c7bd77f20f4784fe7cf16183edf348d4d034c Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Tue, 15 Oct 2024 16:42:18 +0100 Subject: [PATCH 035/143] Switch numpy arrays to float/complex --- glass/core/algorithm.py | 8 +++--- glass/core/array.py | 29 ++++++++++----------- glass/fields.py | 34 ++++++++++++------------ glass/galaxies.py | 36 +++++++++++++------------- glass/lensing.py | 36 +++++++++++++------------- glass/observations.py | 35 ++++++++++++------------- glass/points.py | 57 ++++++++++++++++++++++------------------- glass/shapes.py | 30 ++++++++++------------ glass/shells.py | 50 ++++++++++++++++++------------------ glass/user.py | 15 ++++++----- 10 files changed, 166 insertions(+), 164 deletions(-) diff --git a/glass/core/algorithm.py b/glass/core/algorithm.py index 94257fad..4cd6b953 100644 --- a/glass/core/algorithm.py +++ b/glass/core/algorithm.py @@ -2,19 +2,17 @@ from __future__ import annotations -import typing - import numpy as np import numpy.typing as npt def nnls( - a: npt.NDArray[typing.Any], - b: npt.NDArray[typing.Any], + a: npt.NDArray[np.float64], + b: npt.NDArray[np.float64], *, tol: float = 0.0, maxiter: int | None = None, -) -> npt.NDArray[typing.Any]: +) -> npt.NDArray[np.float64]: """ Compute a non-negative least squares solution. diff --git a/glass/core/array.py b/glass/core/array.py index c8305039..f92b63f8 100644 --- a/glass/core/array.py +++ b/glass/core/array.py @@ -2,7 +2,6 @@ from __future__ import annotations -import typing from functools import partial import numpy as np @@ -10,8 +9,8 @@ def broadcast_first( - *arrays: npt.NDArray[typing.Any], -) -> tuple[npt.NDArray[typing.Any], ...]: + *arrays: npt.NDArray[np.float64], +) -> tuple[npt.NDArray[np.float64], ...]: """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) @@ -19,7 +18,7 @@ def broadcast_first( def broadcast_leading_axes( - *args: tuple[npt.NDArray[typing.Any], int], + *args: tuple[npt.NDArray[np.float64], int], ) -> tuple[tuple[int, ...], ...]: """ Broadcast all but the last N axes. @@ -58,14 +57,14 @@ def broadcast_leading_axes( def ndinterp( # noqa: PLR0913 - x: npt.NDArray[typing.Any], - xp: npt.NDArray[typing.Any], - fp: npt.NDArray[typing.Any], + x: npt.NDArray[np.float64], + xp: npt.NDArray[np.float64], + fp: npt.NDArray[np.float64], axis: int = -1, left: float | None = None, right: float | None = None, period: float | None = None, -) -> npt.NDArray[typing.Any]: +) -> npt.NDArray[np.float64]: """Interpolate multi-dimensional array over axis.""" return np.apply_along_axis( partial(np.interp, x, xp), @@ -78,10 +77,10 @@ def ndinterp( # noqa: PLR0913 def trapz_product( - f: tuple[npt.NDArray[typing.Any], npt.NDArray[typing.Any]], - *ff: tuple[npt.NDArray[typing.Any], npt.NDArray[typing.Any]], + f: tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]], + *ff: tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]], axis: int = -1, -) -> npt.NDArray[typing.Any]: +) -> npt.NDArray[np.float64]: """Trapezoidal rule for a product of functions.""" x, _ = f for x_, _ in ff: @@ -96,11 +95,11 @@ def trapz_product( def cumtrapz( - f: npt.NDArray[typing.Any], - x: npt.NDArray[typing.Any], + f: npt.NDArray[np.float64], + x: npt.NDArray[np.float64], dtype: np.dtype | None = None, # type: ignore[type-arg] - out: npt.NDArray[typing.Any] | None = None, -) -> npt.NDArray[typing.Any]: + out: npt.NDArray[np.float64] | None = None, +) -> npt.NDArray[np.float64]: """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 a83352c7..57425ab8 100644 --- a/glass/fields.py +++ b/glass/fields.py @@ -36,23 +36,23 @@ from gaussiancl import gaussiancl # types -Size = typing.Optional[typing.Union[int, tuple[int, ...]]] -Iternorm = tuple[typing.Optional[int], npt.NDArray[typing.Any], npt.NDArray[typing.Any]] +Size = typing.Union[int, tuple[int, ...]] +Iternorm = tuple[typing.Optional[int], npt.NDArray[np.float64], npt.NDArray[np.float64]] ClTransform = typing.Union[ str, - typing.Callable[[npt.NDArray[typing.Any]], npt.NDArray[typing.Any]], + typing.Callable[[npt.NDArray[np.float64]], npt.NDArray[np.float64]], ] Cls = collections.abc.Sequence[ - typing.Union[npt.NDArray[typing.Any], collections.abc.Sequence[float]] + typing.Union[npt.NDArray[np.float64], collections.abc.Sequence[float]] ] -Alms = npt.NDArray[typing.Any] +Alms = npt.NDArray[np.complex128] def iternorm( k: int, - cov: collections.abc.Iterable[npt.NDArray[typing.Any]], - size: Size = None, -) -> collections.abc.Generator[Iternorm, None, None]: + cov: collections.abc.Iterable[npt.NDArray[np.float64]], + size: Size | None = None, +) -> collections.abc.Generator[Iternorm]: """Return the vector a and variance sigma^2 for iterative normal sampling.""" n: tuple[int, ...] if size is None: @@ -115,7 +115,7 @@ def cls2cov( nl: int, nf: int, nc: int, -) -> collections.abc.Generator[npt.NDArray[typing.Any], None, None]: +) -> collections.abc.Generator[npt.NDArray[np.float64]]: """Return array of cls as a covariance matrix for iterative sampling.""" cov = np.zeros((nl, nc + 1)) end = 0 @@ -135,7 +135,7 @@ def cls2cov( yield cov -def multalm(alm: Alms, bl: npt.NDArray[typing.Any], *, inplace: bool = False) -> Alms: +def multalm(alm: Alms, bl: npt.NDArray[np.float64], *, inplace: bool = False) -> Alms: """Multiply alm by bl.""" n = len(bl) out = np.asanyarray(alm) if inplace else np.copy(alm) @@ -223,7 +223,7 @@ def generate_gaussian( *, ncorr: int | None = None, rng: np.random.Generator | None = None, -) -> collections.abc.Generator[npt.NDArray[typing.Any], None, None]: +) -> collections.abc.Generator[npt.NDArray[np.complex128]]: """ Sample Gaussian random fields from Cls iteratively. @@ -309,7 +309,7 @@ def generate_lognormal( *, ncorr: int | None = None, rng: np.random.Generator | None = None, -) -> collections.abc.Generator[npt.NDArray[typing.Any], None, None]: +) -> collections.abc.Generator[npt.NDArray[np.complex128]]: """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 @@ -332,11 +332,11 @@ def generate_lognormal( def getcl( - cls: list[npt.NDArray[typing.Any]], + cls: list[npt.NDArray[np.float64]], i: int, j: int, lmax: int | None = None, -) -> npt.NDArray[typing.Any]: +) -> npt.NDArray[np.float64]: """ Return a specific angular power spectrum from an array. @@ -367,9 +367,9 @@ def getcl( def effective_cls( - cls: list[npt.NDArray[typing.Any]], - weights1: npt.NDArray[typing.Any], - weights2: npt.NDArray[typing.Any] | None = None, + cls: list[npt.NDArray[np.float64]], + weights1: npt.NDArray[np.float64], + weights2: npt.NDArray[np.float64] | None = None, *, lmax: int | None = None, ) -> npt.NDArray[np.float64]: diff --git a/glass/galaxies.py b/glass/galaxies.py index 018255ba..b6db2282 100644 --- a/glass/galaxies.py +++ b/glass/galaxies.py @@ -33,11 +33,11 @@ def redshifts( - n: int | npt.NDArray[typing.Any], + n: int | npt.NDArray[np.float64], w: RadialWindow, *, rng: np.random.Generator | None = None, -) -> npt.NDArray[typing.Any]: +) -> npt.NDArray[np.float64]: """ Sample redshifts from a radial window function. @@ -61,13 +61,13 @@ def redshifts( def redshifts_from_nz( - count: int | npt.NDArray[typing.Any], - z: npt.NDArray[typing.Any], - nz: npt.NDArray[typing.Any], + count: int | npt.NDArray[np.float64], + z: npt.NDArray[np.float64], + nz: npt.NDArray[np.float64], *, rng: np.random.Generator | None = None, warn: bool = True, -) -> npt.NDArray[typing.Any]: +) -> npt.NDArray[np.float64]: """ Generate galaxy redshifts from a source distribution. @@ -139,15 +139,15 @@ def redshifts_from_nz( def galaxy_shear( # noqa: PLR0913 - 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], + lon: npt.NDArray[np.float64], + lat: npt.NDArray[np.float64], + eps: npt.NDArray[np.float64], + kappa: npt.NDArray[np.float64], + gamma1: npt.NDArray[np.float64], + gamma2: npt.NDArray[np.float64], *, reduced_shear: bool = True, -) -> npt.NDArray[typing.Any]: +) -> npt.NDArray[np.float64]: """ Observed galaxy shears from weak lensing. @@ -206,13 +206,13 @@ def galaxy_shear( # noqa: PLR0913 def gaussian_phz( - z: npt.NDArray[typing.Any], - sigma_0: float | npt.NDArray[typing.Any], + z: npt.NDArray[np.float64], + sigma_0: float | npt.NDArray[np.float64], *, - lower: npt.NDArray[typing.Any] | None = None, - upper: npt.NDArray[typing.Any] | None = None, + lower: npt.NDArray[np.float64] | None = None, + upper: npt.NDArray[np.float64] | None = None, rng: np.random.Generator | None = None, -) -> npt.NDArray[typing.Any]: +) -> npt.NDArray[np.float64]: r""" Photometric redshifts assuming a Gaussian error. diff --git a/glass/lensing.py b/glass/lensing.py index 86a0a719..9582cc58 100644 --- a/glass/lensing.py +++ b/glass/lensing.py @@ -46,14 +46,14 @@ def from_convergence( # noqa: PLR0913 - kappa: npt.NDArray[typing.Any], + kappa: npt.NDArray[np.float64], lmax: int | None = None, *, potential: bool = False, deflection: bool = False, shear: bool = False, discretized: bool = True, -) -> tuple[npt.NDArray[typing.Any], ...]: +) -> tuple[npt.NDArray[np.float64], ...]: 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[typing.Any], + kappa: npt.NDArray[np.float64], lmax: int | None = None, *, discretized: bool = True, -) -> npt.NDArray[typing.Any]: +) -> npt.NDArray[np.float64]: 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[typing.Any] = np.array(0.0) - self.kappa2: npt.NDArray[typing.Any] | None = None - self.kappa3: npt.NDArray[typing.Any] | None = None + self.delta3: npt.NDArray[np.float64] = np.array(0.0) + self.kappa2: npt.NDArray[np.float64] | None = None + self.kappa3: npt.NDArray[np.float64] | None = None - def add_window(self, delta: npt.NDArray[typing.Any], w: RadialWindow) -> None: + def add_window(self, delta: npt.NDArray[np.float64], 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[typing.Any], w: RadialWindow) -> None: def add_plane( self, - delta: npt.NDArray[typing.Any], + delta: npt.NDArray[np.float64], zsrc: float, wlens: float = 1.0, ) -> None: @@ -351,12 +351,12 @@ def zsrc(self) -> float: return self.z3 @property - def kappa(self) -> npt.NDArray[typing.Any] | None: + def kappa(self) -> npt.NDArray[np.float64] | None: """The current convergence plane.""" return self.kappa3 @property - def delta(self) -> npt.NDArray[typing.Any]: + def delta(self) -> npt.NDArray[np.float64]: """The current matter plane.""" return self.delta3 @@ -369,7 +369,7 @@ def wlens(self) -> float: def multi_plane_matrix( shells: collections.abc.Sequence[RadialWindow], cosmo: Cosmology, -) -> npt.NDArray[typing.Any]: +) -> npt.NDArray[np.float64]: """Compute the matrix of lensing contributions from each shell.""" mpc = MultiPlaneConvergence(cosmo) wmat = np.eye(len(shells)) @@ -380,10 +380,10 @@ def multi_plane_matrix( def multi_plane_weights( - weights: npt.NDArray[typing.Any], + weights: npt.NDArray[np.float64], shells: collections.abc.Sequence[RadialWindow], cosmo: Cosmology, -) -> npt.NDArray[typing.Any]: +) -> npt.NDArray[np.float64]: """ Compute effective weights for multi-plane convergence. @@ -420,10 +420,10 @@ def multi_plane_weights( def deflect( - lon: npt.NDArray[typing.Any], - lat: npt.NDArray[typing.Any], - alpha: npt.NDArray[typing.Any], -) -> npt.NDArray[typing.Any]: + lon: npt.NDArray[np.float64], + lat: npt.NDArray[np.float64], + alpha: npt.NDArray[np.float64], +) -> npt.NDArray[np.float64]: r""" Apply deflections to positions. diff --git a/glass/observations.py b/glass/observations.py index 81150183..090efa43 100644 --- a/glass/observations.py +++ b/glass/observations.py @@ -29,7 +29,6 @@ from __future__ import annotations import math -import typing import healpy as hp import numpy as np @@ -42,7 +41,7 @@ def vmap_galactic_ecliptic( nside: int, galactic: tuple[float, float] = (30, 90), ecliptic: tuple[float, float] = (20, 80), -) -> npt.NDArray[typing.Any]: +) -> npt.NDArray[np.float64]: """ Visibility map masking galactic and ecliptic plane. @@ -82,12 +81,12 @@ def vmap_galactic_ecliptic( def gaussian_nz( - z: npt.NDArray[typing.Any], - mean: npt.NDArray[typing.Any], - sigma: npt.NDArray[typing.Any], + z: npt.NDArray[np.float64], + mean: npt.NDArray[np.float64], + sigma: npt.NDArray[np.float64], *, - norm: npt.NDArray[typing.Any] | None = None, -) -> npt.NDArray[typing.Any]: + norm: npt.NDArray[np.float64] | None = None, +) -> npt.NDArray[np.float64]: r""" Gaussian redshift distribution. @@ -124,13 +123,13 @@ def gaussian_nz( def smail_nz( - z: npt.NDArray[typing.Any], - z_mode: npt.NDArray[typing.Any], - alpha: npt.NDArray[typing.Any], - beta: npt.NDArray[typing.Any], + z: npt.NDArray[np.float64], + z_mode: npt.NDArray[np.float64], + alpha: npt.NDArray[np.float64], + beta: npt.NDArray[np.float64], *, - norm: float | npt.NDArray[typing.Any] | None = None, -) -> npt.NDArray[typing.Any]: + norm: float | npt.NDArray[np.float64] | None = None, +) -> npt.NDArray[np.float64]: r""" Redshift distribution following Smail et al. (1994). @@ -221,8 +220,8 @@ def fixed_zbins( def equal_dens_zbins( - z: npt.NDArray[typing.Any], - nz: npt.NDArray[typing.Any], + z: npt.NDArray[np.float64], + nz: npt.NDArray[np.float64], nbins: int, ) -> list[tuple[float, float]]: """ @@ -255,11 +254,11 @@ def equal_dens_zbins( def tomo_nz_gausserr( - z: npt.NDArray[typing.Any], - nz: npt.NDArray[typing.Any], + z: npt.NDArray[np.float64], + nz: npt.NDArray[np.float64], sigma_0: float, zbins: list[tuple[float, float]], -) -> npt.NDArray[typing.Any]: +) -> npt.NDArray[np.float64]: """ Tomographic redshift bins with a Gaussian redshift error. diff --git a/glass/points.py b/glass/points.py index 003dd4e1..e7cde83b 100644 --- a/glass/points.py +++ b/glass/points.py @@ -40,16 +40,19 @@ from glass.core.array import broadcast_first, broadcast_leading_axes, trapz_product if typing.TYPE_CHECKING: + import collections.abc + from glass.shells import RadialWindow + ARCMIN2_SPHERE = 60**6 // 100 / np.pi def effective_bias( - z: npt.NDArray[typing.Any], - bz: npt.NDArray[typing.Any], + z: npt.NDArray[np.float64], + bz: npt.NDArray[np.float64], w: RadialWindow, -) -> npt.NDArray[typing.Any]: +) -> npt.NDArray[np.float64]: r""" Effective bias parameter from a redshift-dependent bias function. @@ -84,36 +87,36 @@ def effective_bias( def linear_bias( - delta: npt.NDArray[typing.Any], - b: float | npt.NDArray[typing.Any], -) -> npt.NDArray[float]: # type: ignore[type-var] + delta: npt.NDArray[np.float64], + b: float | npt.NDArray[np.float64], +) -> npt.NDArray[np.float64]: r"""Linear bias model :math:`\delta_g = b \, \delta`.""" - return b * delta # type: ignore[return-value] + return b * delta def loglinear_bias( - delta: npt.NDArray[typing.Any], - b: float | npt.NDArray[typing.Any], -) -> npt.NDArray[float]: + delta: npt.NDArray[np.float64], + b: float | npt.NDArray[np.float64], +) -> npt.NDArray[np.float64]: 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 # type: ignore[no-any-return] + return delta_g def positions_from_delta( # noqa: PLR0912, PLR0913, PLR0915 - 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, + ngal: float | npt.NDArray[np.float64], + delta: npt.NDArray[np.float64], + bias: float | npt.NDArray[np.float64] | None = None, + vis: npt.NDArray[np.float64] | 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[typing.Any], npt.NDArray[typing.Any], npt.NDArray[typing.Any]] +) -> collections.abc.Generator[ + tuple[npt.NDArray[np.float64], npt.NDArray[np.float64], npt.NDArray[np.int_]] ]: """ Generate positions tracing a density contrast. @@ -265,13 +268,15 @@ def positions_from_delta( # noqa: PLR0912, PLR0913, PLR0915 def uniform_positions( - ngal: float | npt.NDArray[typing.Any], + ngal: float | npt.NDArray[np.float64], *, rng: np.random.Generator | None = None, -) -> typing.Iterator[ # type: ignore[type-arg] - npt.NDArray[typing.Any] | list[npt.NDArray[typing.Any]], - npt.NDArray[typing.Any] | list[npt.NDArray[typing.Any]], - int | list[int], +) -> collections.abc.Generator[ + tuple[ + npt.NDArray[np.float64], + npt.NDArray[np.float64], + int | npt.NDArray[np.int_], + ] ]: """ Generate positions uniformly over the sphere. @@ -301,7 +306,7 @@ def uniform_positions( rng = np.random.default_rng() # sample number of galaxies - ngal = rng.poisson(np.multiply(ARCMIN2_SPHERE, ngal)) + ngal = rng.poisson(np.multiply(ARCMIN2_SPHERE, ngal)) # type: ignore[assignment] # extra dimensions of the output dims = np.shape(ngal) @@ -326,9 +331,9 @@ def uniform_positions( def position_weights( - densities: npt.NDArray[typing.Any], - bias: npt.NDArray[typing.Any] | None = None, -) -> npt.NDArray[typing.Any]: + densities: npt.NDArray[np.float64], + bias: npt.NDArray[np.float64] | None = None, +) -> npt.NDArray[np.float64]: r""" Compute relative weights for angular clustering. diff --git a/glass/shapes.py b/glass/shapes.py index 7989e364..a9c4fdc6 100644 --- a/glass/shapes.py +++ b/glass/shapes.py @@ -24,19 +24,17 @@ from __future__ import annotations -import typing - import numpy as np import numpy.typing as npt def triaxial_axis_ratio( - zeta: npt.NDArray[typing.Any], - xi: npt.NDArray[typing.Any], + zeta: npt.NDArray[np.float64], + xi: npt.NDArray[np.float64], size: tuple[int] | None = None, *, rng: np.random.Generator | None = None, -) -> npt.NDArray[typing.Any]: +) -> npt.NDArray[np.float64]: r""" Axis ratio of a randomly projected triaxial ellipsoid. @@ -99,14 +97,14 @@ def triaxial_axis_ratio( def ellipticity_ryden04( # noqa: PLR0913 - mu: npt.NDArray[typing.Any], - sigma: npt.NDArray[typing.Any], - gamma: npt.NDArray[typing.Any], - sigma_gamma: npt.NDArray[typing.Any], + mu: npt.NDArray[np.float64], + sigma: npt.NDArray[np.float64], + gamma: npt.NDArray[np.float64], + sigma_gamma: npt.NDArray[np.float64], size: int | tuple[int, ...] | None = None, *, rng: np.random.Generator | None = None, -) -> npt.NDArray[typing.Any]: +) -> npt.NDArray[np.float64]: r""" Ellipticity distribution following Ryden (2004). @@ -180,11 +178,11 @@ def ellipticity_ryden04( # noqa: PLR0913 def ellipticity_gaussian( - count: int | npt.NDArray[typing.Any], - sigma: npt.NDArray[typing.Any], + count: int | npt.NDArray[np.float64], + sigma: npt.NDArray[np.float64], *, rng: np.random.Generator | None = None, -) -> npt.NDArray[typing.Any]: +) -> npt.NDArray[np.complex128]: r""" Sample Gaussian galaxy ellipticities. @@ -234,11 +232,11 @@ def ellipticity_gaussian( def ellipticity_intnorm( - count: int | npt.NDArray[typing.Any], - sigma: npt.NDArray[typing.Any], + count: int | npt.NDArray[np.float64], + sigma: npt.NDArray[np.float64], *, rng: np.random.Generator | None = None, -) -> npt.NDArray[typing.Any]: +) -> npt.NDArray[np.complex128]: r""" Sample galaxy ellipticities with intrinsic normal distribution. diff --git a/glass/shells.py b/glass/shells.py index 63daf9d2..5659f461 100644 --- a/glass/shells.py +++ b/glass/shells.py @@ -57,30 +57,30 @@ from cosmology import Cosmology # types -ArrayLike1D = typing.Union[collections.abc.Sequence[float], npt.NDArray[typing.Any]] -WeightFunc = typing.Callable[[ArrayLike1D], npt.NDArray[typing.Any]] +ArrayLike1D = typing.Union[collections.abc.Sequence[float], npt.NDArray[np.float64]] +WeightFunc = typing.Callable[[ArrayLike1D], npt.NDArray[np.float64]] def distance_weight( - z: npt.NDArray[typing.Any], + z: npt.NDArray[np.float64], cosmo: Cosmology, -) -> npt.NDArray[typing.Any]: +) -> npt.NDArray[np.float64]: """Uniform weight in comoving distance.""" return 1 / cosmo.ef(z) # type: ignore[no-any-return] def volume_weight( - z: npt.NDArray[typing.Any], + z: npt.NDArray[np.float64], cosmo: Cosmology, -) -> npt.NDArray[typing.Any]: +) -> npt.NDArray[np.float64]: """Uniform weight in comoving volume.""" return cosmo.xm(z) ** 2 / cosmo.ef(z) # type: ignore[no-any-return] def density_weight( - z: npt.NDArray[typing.Any], + z: npt.NDArray[np.float64], cosmo: Cosmology, -) -> npt.NDArray[typing.Any]: +) -> npt.NDArray[np.float64]: """Uniform weight in matter density.""" return cosmo.rho_m_z(z) * cosmo.xm(z) ** 2 / cosmo.ef(z) # type: ignore[no-any-return] @@ -309,7 +309,7 @@ def restrict( z: ArrayLike1D, f: ArrayLike1D, w: RadialWindow, -) -> tuple[npt.NDArray[typing.Any], npt.NDArray[typing.Any]]: +) -> tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]]: """ Restrict a function to a redshift window. @@ -346,12 +346,12 @@ def restrict( def partition( - z: npt.NDArray[typing.Any], - fz: npt.NDArray[typing.Any], + z: npt.NDArray[np.float64], + fz: npt.NDArray[np.float64], shells: collections.abc.Sequence[RadialWindow], *, method: str = "nnls", -) -> npt.NDArray[typing.Any]: +) -> npt.NDArray[np.float64]: r""" Partition a function by a sequence of windows. @@ -457,12 +457,12 @@ def partition( def partition_lstsq( - z: npt.NDArray[typing.Any], - fz: npt.NDArray[typing.Any], + z: npt.NDArray[np.float64], + fz: npt.NDArray[np.float64], shells: collections.abc.Sequence[RadialWindow], *, sumtol: float = 0.01, -) -> npt.NDArray[typing.Any]: +) -> npt.NDArray[np.float64]: """Least-squares partition.""" # make sure nothing breaks sumtol = max(sumtol, 1e-4) @@ -496,19 +496,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] + x = np.linalg.lstsq(a.T, b.reshape(-1, zp.size + 1).T, rcond=None)[0] # type: ignore[arg-type, 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.NDArray[typing.Any], - fz: npt.NDArray[typing.Any], + z: npt.NDArray[np.float64], + fz: npt.NDArray[np.float64], shells: collections.abc.Sequence[RadialWindow], *, sumtol: float = 0.01, -) -> npt.NDArray[typing.Any]: +) -> npt.NDArray[np.float64]: """ Non-negative least-squares partition. @@ -564,10 +564,10 @@ def partition_nnls( def partition_restrict( - z: npt.NDArray[typing.Any], - fz: npt.NDArray[typing.Any], + z: npt.NDArray[np.float64], + fz: npt.NDArray[np.float64], shells: collections.abc.Sequence[RadialWindow], -) -> npt.NDArray[typing.Any]: +) -> npt.NDArray[np.float64]: """Partition by restriction and integration.""" part = np.empty((len(shells),) + np.shape(fz)[:-1]) for i, w in enumerate(shells): @@ -615,10 +615,10 @@ def distance_grid( def combine( - z: npt.NDArray[typing.Any], - weights: npt.NDArray[typing.Any], + z: npt.NDArray[np.float64], + weights: npt.NDArray[np.float64], shells: collections.abc.Sequence[RadialWindow], -) -> npt.NDArray[typing.Any]: +) -> npt.NDArray[np.float64]: r""" Evaluate a linear combination of window functions. diff --git a/glass/user.py b/glass/user.py index 7fb4d308..00ce8c60 100644 --- a/glass/user.py +++ b/glass/user.py @@ -25,8 +25,11 @@ import numpy as np import numpy.typing as npt +if typing.TYPE_CHECKING: + import collections.abc -def save_cls(filename: str, cls: list[npt.NDArray[typing.Any] | None]) -> None: + +def save_cls(filename: str, cls: list[npt.NDArray[np.float64] | None]) -> None: """ Save a list of Cls to file. @@ -39,7 +42,7 @@ def save_cls(filename: str, cls: list[npt.NDArray[typing.Any] | None]) -> None: np.savez(filename, values=values, split=split) -def load_cls(filename: str) -> list[npt.NDArray[typing.Any]]: +def load_cls(filename: str) -> list[npt.NDArray[np.float64]]: """ Load a list of Cls from file. @@ -66,7 +69,7 @@ def __init__(self, fits, ext: str | None = None) -> None: # type: ignore[no-unt def _append( self, - data: npt.NDArray[typing.Any], + data: npt.NDArray[np.float64], names: list[str] | None = None, ) -> None: """Write the FITS file.""" @@ -81,9 +84,9 @@ def _append( def write( self, - data: npt.NDArray[typing.Any] | None = None, + data: npt.NDArray[np.float64] | None = None, /, - **columns: npt.NDArray[typing.Any], + **columns: npt.NDArray[np.float64], ) -> None: """ Write to FITS by calling the internal _append method. @@ -106,7 +109,7 @@ def write_catalog( filename: str, *, ext: str | None = None, -) -> typing.Iterator[_FitsWriter]: +) -> collections.abc.Generator[_FitsWriter]: """ Write a catalogue into a FITS file. From 7ddf501735267117dae3ca9e0341d1d57b19c669 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Tue, 15 Oct 2024 17:14:11 +0100 Subject: [PATCH 036/143] Fix some more typing --- docs/conf.py | 2 +- glass/core/array.py | 2 +- tests/core/test_algorithm.py | 2 +- tests/test_fits.py | 2 +- tests/test_galaxies.py | 2 +- tests/test_lensing.py | 16 +++++++++++++--- tests/test_shells.py | 2 +- 7 files changed, 19 insertions(+), 9 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 05b15944..874ec590 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 = [] # type: ignore[var-annotated] +html_css_files: list[str] = [] # -- Intersphinx ------------------------------------------------------------- diff --git a/glass/core/array.py b/glass/core/array.py index f92b63f8..f8673f99 100644 --- a/glass/core/array.py +++ b/glass/core/array.py @@ -97,7 +97,7 @@ def trapz_product( def cumtrapz( f: npt.NDArray[np.float64], x: npt.NDArray[np.float64], - dtype: np.dtype | None = None, # type: ignore[type-arg] + dtype: np.dtype[np.float64] | None = None, out: npt.NDArray[np.float64] | None = None, ) -> npt.NDArray[np.float64]: """Cumulative trapezoidal rule along last axis.""" diff --git a/tests/core/test_algorithm.py b/tests/core/test_algorithm.py index 11179edf..fa1badf9 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) -> None: # type: ignore[no-untyped-def] +def test_nnls(rng: np.random.Generator) -> None: from scipy.optimize import nnls as nnls_scipy # cross-check output with scipy's nnls diff --git a/tests/test_fits.py b/tests/test_fits.py index 906b18e7..f9349001 100644 --- a/tests/test_fits.py +++ b/tests/test_fits.py @@ -28,7 +28,7 @@ def _test_append(fits, data, names) -> None: # type: ignore[no-untyped-def] @pytest.mark.skipif(not HAVE_FITSIO, reason="test requires fitsio") -def test_basic_write(tmp_path: os.PathLike) -> None: # type: ignore[type-arg] +def test_basic_write(tmp_path: os.PathLike[str]) -> None: import fitsio filename_gfits = "gfits.fits" # what GLASS creates diff --git a/tests/test_galaxies.py b/tests/test_galaxies.py index 4f31cd5d..cc93700e 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) -> None: # type: ignore[no-untyped-def] +def test_galaxy_shear(rng: np.random.Generator) -> None: # check shape of the output kappa, gamma1, gamma2 = ( diff --git a/tests/test_lensing.py b/tests/test_lensing.py index 4decb819..defbaa2d 100644 --- a/tests/test_lensing.py +++ b/tests/test_lensing.py @@ -2,6 +2,8 @@ import numpy as np import pytest +from cosmology import Cosmology + from glass.lensing import ( MultiPlaneConvergence, deflect, @@ -23,7 +25,7 @@ def shells() -> list[RadialWindow]: @pytest.fixture -def cosmo(): # type: ignore[no-untyped-def] +def cosmo() -> Cosmology: class MockCosmology: @property def omega_m(self): # type: ignore[no-untyped-def] @@ -90,7 +92,11 @@ def test_deflect_many(rng: np.random.Generator) -> None: np.testing.assert_allclose(dotp, np.cos(abs_alpha)) -def test_multi_plane_matrix(shells, cosmo, rng) -> None: # type: ignore[no-untyped-def] +def test_multi_plane_matrix( + shells: list[RadialWindow], + cosmo: Cosmology, + rng: np.random.Generator, +) -> None: mat = multi_plane_matrix(shells, cosmo) np.testing.assert_array_equal(mat, np.tril(mat)) @@ -107,7 +113,11 @@ def test_multi_plane_matrix(shells, cosmo, rng) -> None: # type: ignore[no-unty np.testing.assert_allclose(mat @ deltas, kappas) -def test_multi_plane_weights(shells, cosmo, rng) -> None: # type: ignore[no-untyped-def] +def test_multi_plane_weights( + shells: list[RadialWindow], + cosmo: Cosmology, + rng: np.random.Generator, +) -> None: w_in = np.eye(len(shells)) w_out = multi_plane_weights(w_in, shells, cosmo) diff --git a/tests/test_shells.py b/tests/test_shells.py index 8a49f46e..6723af41 100644 --- a/tests/test_shells.py +++ b/tests/test_shells.py @@ -49,7 +49,7 @@ def test_restrict() -> None: @pytest.mark.parametrize("method", ["lstsq", "nnls", "restrict"]) -def test_partition(method) -> None: # type: ignore[no-untyped-def] +def test_partition(method: str) -> None: shells = [ 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] From 008e9a56a9dadffc505d94a6c50cc045a543f698 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Wed, 16 Oct 2024 11:29:22 +0100 Subject: [PATCH 037/143] Remove some `untyped-def` --- tests/test_lensing.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_lensing.py b/tests/test_lensing.py index defbaa2d..541a5cbb 100644 --- a/tests/test_lensing.py +++ b/tests/test_lensing.py @@ -28,7 +28,7 @@ def shells() -> list[RadialWindow]: def cosmo() -> Cosmology: class MockCosmology: @property - def omega_m(self): # type: ignore[no-untyped-def] + def omega_m(self) -> float: return 0.3 def ef(self, z): # type: ignore[no-untyped-def] @@ -49,12 +49,12 @@ def test_deflect_nsew(usecomplex: bool) -> None: # noqa: FBT001 if usecomplex: - def alpha(re, im): # type: ignore[no-untyped-def] + def alpha(re: float, im: float) -> complex: return re + 1j * im else: - def alpha(re, im): # type: ignore[no-untyped-def] + def alpha(re: float, im: float) -> list[float]: # type: ignore[misc] return [re, im] # north From 112c36c1001608e8ababfa9450422c6090f42d52 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Wed, 16 Oct 2024 15:41:41 +0100 Subject: [PATCH 038/143] Add typing for `redshifts_for_nz` --- glass/galaxies.py | 10 +++++----- glass/shells.py | 6 +++--- tests/test_galaxies.py | 14 +++++++------- tests/test_lensing.py | 8 ++++---- tests/test_shells.py | 14 +++++++------- 5 files changed, 26 insertions(+), 26 deletions(-) diff --git a/glass/galaxies.py b/glass/galaxies.py index 0f684dc2..5cf0dda7 100644 --- a/glass/galaxies.py +++ b/glass/galaxies.py @@ -63,13 +63,13 @@ def redshifts( Random number generator. If not given, a default RNG is used. """ - return redshifts_from_nz(n, w.za, w.wa, rng=rng, warn=False) # type: ignore[arg-type] + return redshifts_from_nz(n, w.za, w.wa, rng=rng, warn=False) def redshifts_from_nz( count: int | npt.NDArray[np.float64], - z: npt.NDArray[np.float64], - nz: npt.NDArray[np.float64], + z: list[float] | npt.NDArray[np.float64], + nz: list[float] | npt.NDArray[np.float64], *, rng: np.random.Generator | None = None, warn: bool = True, @@ -128,14 +128,14 @@ 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] + cdf = cumtrapz(nz[k], z[k], dtype=float) # type: ignore[arg-type, call-overload] cdf /= cdf[-1] # sample redshifts and store result redshifts[total : total + count[k]] = np.interp( # type: ignore[index] rng.uniform(0, 1, size=count[k]), # type: ignore[index] cdf, - z[k], + z[k], # type: ignore[call-overload] ) total += count[k] # type: ignore[index] diff --git a/glass/shells.py b/glass/shells.py index 5659f461..8d87040a 100644 --- a/glass/shells.py +++ b/glass/shells.py @@ -129,8 +129,8 @@ class RadialWindow(typing.NamedTuple): """ - za: collections.abc.Sequence[float] - wa: collections.abc.Sequence[float] + za: list[float] | npt.NDArray[np.float64] + wa: list[float] | npt.NDArray[np.float64] zeff: float | None @@ -186,7 +186,7 @@ def tophat_windows( z = np.linspace(zmin, zmax, n) w = wht(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] + ws.append(RadialWindow(z, w, zeff)) return ws diff --git a/tests/test_galaxies.py b/tests/test_galaxies.py index e73cad3d..5b5b4f89 100644 --- a/tests/test_galaxies.py +++ b/tests/test_galaxies.py @@ -24,24 +24,24 @@ def test_redshifts(mocker) -> None: # type: ignore[no-untyped-def] def test_redshifts_from_nz(rng: np.random.Generator) -> None: # test sampling - redshifts = redshifts_from_nz(10, [0, 1, 2, 3, 4], [1, 0, 0, 0, 0], warn=False) # type: ignore[arg-type] + redshifts = redshifts_from_nz(10, [0, 1, 2, 3, 4], [1, 0, 0, 0, 0], warn=False) 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) # type: ignore[arg-type] + redshifts = redshifts_from_nz(10, [0, 1, 2, 3, 4], [0, 0, 1, 0, 0], warn=False) 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) # type: ignore[arg-type] + redshifts = redshifts_from_nz(10, [0, 1, 2, 3, 4], [0, 0, 0, 0, 1], warn=False) 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) # type: ignore[arg-type] + redshifts = redshifts_from_nz(10, [0, 1, 2, 3, 4], [0, 0, 1, 1, 1], warn=False) assert not np.any(redshifts <= 1) # test with rng redshifts = redshifts_from_nz( 10, - [0, 1, 2, 3, 4], # type: ignore[arg-type] - [0, 0, 1, 1, 1], # type: ignore[arg-type] + [0, 1, 2, 3, 4], + [0, 0, 1, 1, 1], warn=False, rng=rng, ) @@ -100,7 +100,7 @@ def test_redshifts_from_nz(rng: np.random.Generator) -> 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]) # type: ignore[arg-type] + redshifts = redshifts_from_nz(10, [0, 1, 2, 3, 4], [1, 0, 0, 0, 0]) def test_galaxy_shear(rng: np.random.Generator) -> None: diff --git a/tests/test_lensing.py b/tests/test_lensing.py index 541a5cbb..dcfd7dfc 100644 --- a/tests/test_lensing.py +++ b/tests/test_lensing.py @@ -58,19 +58,19 @@ def alpha(re: float, im: float) -> list[float]: # type: ignore[misc] return [re, im] # north - lon, lat = deflect(0.0, 0.0, alpha(r, 0)) # type: ignore[arg-type, no-untyped-call] + lon, lat = deflect(0.0, 0.0, alpha(r, 0)) # type: ignore[arg-type] 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[arg-type, no-untyped-call] + lon, lat = deflect(0.0, 0.0, alpha(-r, 0)) # type: ignore[arg-type] 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[arg-type, no-untyped-call] + lon, lat = deflect(0.0, 0.0, alpha(0, r)) # type: ignore[arg-type] 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[arg-type, no-untyped-call] + lon, lat = deflect(0.0, 0.0, alpha(0, -r)) # type: ignore[arg-type] np.testing.assert_allclose([lon, lat], [d, 0.0], atol=1e-15) diff --git a/tests/test_shells.py b/tests/test_shells.py index 6723af41..cc0ec4b3 100644 --- a/tests/test_shells.py +++ b/tests/test_shells.py @@ -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) # type: ignore[comparison-overlap] + assert all(np.all(w.wa == 1) for w in ws) def test_restrict() -> None: @@ -51,12 +51,12 @@ def test_restrict() -> None: @pytest.mark.parametrize("method", ["lstsq", "nnls", "restrict"]) def test_partition(method: str) -> None: shells = [ - 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] + 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), ] z = np.linspace(0.0, 5.0, 1000) From 394f4583ce671172b597e015b027771c81c8acda Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Wed, 16 Oct 2024 15:47:42 +0100 Subject: [PATCH 039/143] `positions_from_delta` --- glass/points.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/glass/points.py b/glass/points.py index e7cde83b..3ab4c52c 100644 --- a/glass/points.py +++ b/glass/points.py @@ -106,9 +106,9 @@ def loglinear_bias( def positions_from_delta( # noqa: PLR0912, PLR0913, PLR0915 - ngal: float | npt.NDArray[np.float64], + ngal: float | list[float], delta: npt.NDArray[np.float64], - bias: float | npt.NDArray[np.float64] | None = None, + bias: float | None = None, vis: npt.NDArray[np.float64] | None = None, *, bias_model: str | typing.Callable[..., typing.Any] = "linear", @@ -207,7 +207,7 @@ 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[index] + n *= ARCMIN2_SPHERE / n.size * ngal[k] # type: ignore[call-overload, index] # apply visibility if given if vis is not None: From c9b4b63058017c51770c9f58fa58e4a9716f272e Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Wed, 16 Oct 2024 15:55:46 +0100 Subject: [PATCH 040/143] `uniform_positions` --- glass/points.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/glass/points.py b/glass/points.py index 3ab4c52c..a1561e3e 100644 --- a/glass/points.py +++ b/glass/points.py @@ -268,7 +268,7 @@ def positions_from_delta( # noqa: PLR0912, PLR0913, PLR0915 def uniform_positions( - ngal: float | npt.NDArray[np.float64], + ngal: float | list[float], *, rng: np.random.Generator | None = None, ) -> collections.abc.Generator[ @@ -312,22 +312,22 @@ def uniform_positions( dims = np.shape(ngal) # make sure ntot is an array even if scalar - ngal = np.broadcast_to(ngal, dims) + ngal = np.broadcast_to(ngal, dims) # type: ignore[assignment] # sample each set of points for k in np.ndindex(dims): # sample uniformly over the sphere - lon = rng.uniform(-180, 180, size=ngal[k]) - lat = np.rad2deg(np.arcsin(rng.uniform(-1, 1, size=ngal[k]))) + lon = rng.uniform(-180, 180, size=ngal[k]) # type: ignore[call-overload, index] + lat = np.rad2deg(np.arcsin(rng.uniform(-1, 1, size=ngal[k]))) # type: ignore[call-overload, index] # report count if dims: count = np.zeros(dims, dtype=int) - count[k] = ngal[k] + count[k] = ngal[k] # type: ignore[call-overload, index] else: - count = int(ngal[k]) # type: ignore[assignment] + count = int(ngal[k]) # type: ignore[assignment, call-overload, index] - yield lon, lat, count + yield lon, lat, count # type: ignore[misc] def position_weights( From 57f28202266df5a5df66fc004edc86687623e207 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Wed, 16 Oct 2024 16:03:56 +0100 Subject: [PATCH 041/143] `catpos` --- glass/points.py | 6 +++++- tests/test_points.py | 34 +++++++++++++++++++++++++--------- 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/glass/points.py b/glass/points.py index a1561e3e..29d64f1c 100644 --- a/glass/points.py +++ b/glass/points.py @@ -116,7 +116,11 @@ def positions_from_delta( # noqa: PLR0912, PLR0913, PLR0915 batch: int | None = 1_000_000, rng: np.random.Generator | None = None, ) -> collections.abc.Generator[ - tuple[npt.NDArray[np.float64], npt.NDArray[np.float64], npt.NDArray[np.int_]] + tuple[ + npt.NDArray[np.float64], + npt.NDArray[np.float64], + int | npt.NDArray[np.int_], + ] ]: """ Generate positions tracing a density contrast. diff --git a/tests/test_points.py b/tests/test_points.py index ceb20401..a78bea09 100644 --- a/tests/test_points.py +++ b/tests/test_points.py @@ -1,14 +1,30 @@ +from __future__ import annotations + +import typing + import numpy as np +import numpy.typing as npt from glass.points import position_weights, positions_from_delta, uniform_positions +if typing.TYPE_CHECKING: + import collections.abc + -def catpos(pos): # type: ignore[no-untyped-def] +def catpos( # type: ignore[no-untyped-def] + pos: collections.abc.Generator[ + tuple[ + npt.NDArray[np.float64], + npt.NDArray[np.float64], + int | npt.NDArray[np.int_], + ] + ], +): lon, lat, cnt = [], [], 0 # type: ignore[var-annotated] for lo, la, co in pos: lon = np.concatenate([lon, lo]) # type: ignore[assignment] lat = np.concatenate([lat, la]) # type: ignore[assignment] - cnt = cnt + co + cnt = cnt + co # type: ignore[assignment] return lon, lat, cnt @@ -20,7 +36,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)) # type: ignore[no-untyped-call] + lon, lat, cnt = catpos(positions_from_delta(ngal, delta, bias, vis)) assert isinstance(cnt, int) assert lon.shape == lat.shape == (cnt,) @@ -32,7 +48,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)) # type: ignore[no-untyped-call] + lon, lat, cnt = catpos(positions_from_delta(ngal, delta, bias, vis)) assert cnt.shape == (2,) assert lon.shape == (cnt.sum(),) @@ -45,7 +61,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)) # type: ignore[no-untyped-call] + lon, lat, cnt = catpos(positions_from_delta(ngal, delta, bias, vis)) assert cnt.shape == (3, 2) assert lon.shape == (cnt.sum(),) @@ -58,7 +74,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)) # type: ignore[no-untyped-call] + lon, lat, cnt = catpos(positions_from_delta(ngal, delta, bias, vis)) assert cnt.shape == (3, 2) assert lon.shape == (cnt.sum(),) @@ -70,7 +86,7 @@ def test_uniform_positions() -> None: ngal = 1e-3 - lon, lat, cnt = catpos(uniform_positions(ngal)) # type: ignore[no-untyped-call] + lon, lat, cnt = catpos(uniform_positions(ngal)) assert isinstance(cnt, int) assert lon.shape == lat.shape == (cnt,) @@ -79,7 +95,7 @@ def test_uniform_positions() -> None: ngal = [1e-3, 2e-3, 3e-3] # type: ignore[assignment] - lon, lat, cnt = catpos(uniform_positions(ngal)) # type: ignore[no-untyped-call] + lon, lat, cnt = catpos(uniform_positions(ngal)) assert cnt.shape == (3,) assert lon.shape == lat.shape == (cnt.sum(),) @@ -88,7 +104,7 @@ def test_uniform_positions() -> None: ngal = [[1e-3, 2e-3], [3e-3, 4e-3], [5e-3, 6e-3]] # type: ignore[assignment] - lon, lat, cnt = catpos(uniform_positions(ngal)) # type: ignore[no-untyped-call] + lon, lat, cnt = catpos(uniform_positions(ngal)) assert cnt.shape == (3, 2) assert lon.shape == lat.shape == (cnt.sum(),) From 205ae4c9238bb2743b89b792e2488d058cd81870 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Wed, 16 Oct 2024 16:25:55 +0100 Subject: [PATCH 042/143] Fix `return-value` --- glass/lensing.py | 7 +++++-- glass/shells.py | 4 ++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/glass/lensing.py b/glass/lensing.py index 9582cc58..f8441f36 100644 --- a/glass/lensing.py +++ b/glass/lensing.py @@ -423,7 +423,10 @@ def deflect( lon: npt.NDArray[np.float64], lat: npt.NDArray[np.float64], alpha: npt.NDArray[np.float64], -) -> npt.NDArray[np.float64]: +) -> tuple[ + npt.NDArray[np.float64], + npt.NDArray[np.float64], +]: r""" Apply deflections to positions. @@ -477,4 +480,4 @@ def deflect( d = np.arctan2(sa * sg, st * ca - ct * sa * cg) - return lon - np.degrees(d), np.degrees(tp) # type: ignore[return-value] + return lon - np.degrees(d), np.degrees(tp) diff --git a/glass/shells.py b/glass/shells.py index 8d87040a..805a183f 100644 --- a/glass/shells.py +++ b/glass/shells.py @@ -618,7 +618,7 @@ def combine( z: npt.NDArray[np.float64], weights: npt.NDArray[np.float64], shells: collections.abc.Sequence[RadialWindow], -) -> npt.NDArray[np.float64]: +) -> int: r""" Evaluate a linear combination of window functions. @@ -648,7 +648,7 @@ def combine( Find weights for a given function. """ - return sum( # type: ignore[return-value] + return sum( np.expand_dims(weight, -1) * np.interp( z, From 42cb3b863d89f764a8e71d8d7bf48b15ce3f770e Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Wed, 16 Oct 2024 16:29:26 +0100 Subject: [PATCH 043/143] `redundant-expr` --- glass/fields.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/glass/fields.py b/glass/fields.py index 9189e266..58303391 100644 --- a/glass/fields.py +++ b/glass/fields.py @@ -148,7 +148,7 @@ def transform_cls(cls: Cls, tfm: ClTransform, pars: tuple[typing.Any, ...] = ()) """Transform Cls to Gaussian Cls.""" gls = [] for cl in cls: - if cl is not None and len(cl) > 0: # type: ignore[redundant-expr] + if len(cl) > 0: monopole = 0.0 if cl[0] == 0 else None gl, info, _, _ = gaussiancl(cl, tfm, pars, monopole=monopole) if info == 0: @@ -194,7 +194,7 @@ def discretized_cls( gls = [] for cl in cls: - if cl is not None and len(cl) > 0: # type: ignore[redundant-expr] + if cl and len(cl) > 0: if lmax is not None: cl = cl[: lmax + 1] # noqa: PLW2901 if nside is not None: @@ -255,7 +255,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[redundant-expr] + n = max((len(gl) for gl in gls), default=0) if n == 0: msg = "all gls are empty" raise ValueError(msg) From 8f4f79f0fb2bd63b639c453207cbe1b68b6f15d1 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Thu, 17 Oct 2024 10:42:20 +0100 Subject: [PATCH 044/143] Fix more typing --- glass/galaxies.py | 4 ++-- glass/user.py | 3 ++- tests/test_fits.py | 13 ++++++------- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/glass/galaxies.py b/glass/galaxies.py index 5cf0dda7..96891010 100644 --- a/glass/galaxies.py +++ b/glass/galaxies.py @@ -296,7 +296,7 @@ def gaussian_phz( def kappa_ia_nla( # noqa: PLR0913 - delta: npt.NDArray[typing.Any], + delta: npt.NDArray[np.float64], zeff: float, a_ia: float, cosmo: Cosmology, @@ -306,7 +306,7 @@ def kappa_ia_nla( # noqa: PLR0913 lbar: float = 0.0, l0: float = 1e-9, beta: float = 0.0, -) -> npt.NDArray[typing.Any]: +) -> npt.NDArray[np.float64]: r""" Effective convergence from intrinsic alignments using the NLA model. diff --git a/glass/user.py b/glass/user.py index 00ce8c60..606a3b44 100644 --- a/glass/user.py +++ b/glass/user.py @@ -27,6 +27,7 @@ if typing.TYPE_CHECKING: import collections.abc + import pathlib def save_cls(filename: str, cls: list[npt.NDArray[np.float64] | None]) -> None: @@ -106,7 +107,7 @@ def write( @contextmanager def write_catalog( - filename: str, + filename: pathlib.Path, *, ext: str | None = None, ) -> collections.abc.Generator[_FitsWriter]: diff --git a/tests/test_fits.py b/tests/test_fits.py index f9349001..09dbab22 100644 --- a/tests/test_fits.py +++ b/tests/test_fits.py @@ -1,5 +1,4 @@ import importlib.util -import os import pathlib import numpy as np @@ -28,15 +27,15 @@ def _test_append(fits, data, names) -> None: # type: ignore[no-untyped-def] @pytest.mark.skipif(not HAVE_FITSIO, reason="test requires fitsio") -def test_basic_write(tmp_path: os.PathLike[str]) -> None: +def test_basic_write(tmp_path: pathlib.Path) -> None: import fitsio 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, # type: ignore[operator] - fitsio.FITS(tmp_path / filename_tfits, "rw", clobber=True) as my_fits, # type: ignore[operator] + user.write_catalog(tmp_path / filename_gfits, ext="CATALOG") as out, + fitsio.FITS(tmp_path / filename_tfits, "rw", clobber=True) as my_fits, ): for i in range(my_max): array = np.arange(i, i + 1, delta) # array of size 1/delta @@ -47,8 +46,8 @@ def test_basic_write(tmp_path: os.PathLike[str]) -> None: _test_append(my_fits, arrays, names) with ( - fitsio.FITS(tmp_path / filename_gfits) as g_fits, # type: ignore[operator] - fitsio.FITS(tmp_path / filename_tfits) as t_fits, # type: ignore[operator] + fitsio.FITS(tmp_path / filename_gfits) as g_fits, + fitsio.FITS(tmp_path / filename_tfits) as t_fits, ): glass_data = g_fits[1].read() test_data = t_fits[1].read() @@ -59,7 +58,7 @@ def test_basic_write(tmp_path: os.PathLike[str]) -> None: @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] + with user.write_catalog(tmp_path / filename, ext="CATALOG") as out: for i in range(my_max): if i == except_int: msg = "Unhandled exception" From f165dcbd7d3bcbd489e821873174cb3149814123 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Thu, 17 Oct 2024 11:37:15 +0100 Subject: [PATCH 045/143] Add types to lists --- tests/core/test_array.py | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/tests/core/test_array.py b/tests/core/test_array.py index f023a3f5..a3f936f4 100644 --- a/tests/core/test_array.py +++ b/tests/core/test_array.py @@ -61,38 +61,44 @@ def test_ndinterp() -> None: # test 1d interpolation xp = [0, 1, 2, 3, 4] - yp = [1.1, 1.2, 1.3, 1.4, 1.5] - - x = 0.5 + yp: list[float] | list[list[float]] | list[list[list[float]]] = [ + 1.1, + 1.2, + 1.3, + 1.4, + 1.5, + ] + + x: float | list[float] | list[list[float]] = 0.5 y = ndinterp(x, xp, yp) # type: ignore[arg-type] assert np.shape(y) == () np.testing.assert_allclose(y, 1.15, atol=1e-15) - x = [0.5, 1.5, 2.5] # type: ignore[assignment] + x = [0.5, 1.5, 2.5] 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) - x = [[0.5, 1.5], [2.5, 3.5]] # type: ignore[assignment] + x = [[0.5, 1.5], [2.5, 3.5]] 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) # 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] + yp = [[1.1, 1.2, 1.3, 1.4, 1.5], [2.1, 2.2, 2.3, 2.4, 2.5]] x = 0.5 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) - x = [0.5, 1.5, 2.5] # type: ignore[assignment] + x = [0.5, 1.5, 2.5] 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) - x = [[0.5, 1.5], [2.5, 3.5]] # type: ignore[assignment] + x = [[0.5, 1.5], [2.5, 3.5]] y = ndinterp(x, xp, yp) # type: ignore[arg-type] assert np.shape(y) == (2, 2, 2) np.testing.assert_allclose( @@ -103,14 +109,14 @@ def test_ndinterp() -> None: # 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]]] # type: ignore[list-item] + yp = [[[1.1], [1.2], [1.3], [1.4], [1.5]], [[2.1], [2.2], [2.3], [2.4], [2.5]]] x = 0.5 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) - x = [0.5, 1.5, 2.5] # type: ignore[assignment] + x = [0.5, 1.5, 2.5] y = ndinterp(x, xp, yp, axis=1) # type: ignore[arg-type] assert np.shape(y) == (2, 3, 1) np.testing.assert_allclose( @@ -119,7 +125,7 @@ def test_ndinterp() -> None: 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] + 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]] y = ndinterp(x, xp, yp, axis=1) # type: ignore[arg-type] assert np.shape(y) == (2, 3, 4, 1) np.testing.assert_allclose( From 3d86e1945d00fd0711ea243a2497551f39fa1858 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Thu, 17 Oct 2024 11:46:25 +0100 Subject: [PATCH 046/143] Type count --- glass/galaxies.py | 10 +++++----- tests/test_galaxies.py | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/glass/galaxies.py b/glass/galaxies.py index 96891010..ad8c35c4 100644 --- a/glass/galaxies.py +++ b/glass/galaxies.py @@ -39,7 +39,7 @@ def redshifts( - n: int | npt.NDArray[np.float64], + n: int | list[int] | list[list[int]], w: RadialWindow, *, rng: np.random.Generator | None = None, @@ -67,7 +67,7 @@ def redshifts( def redshifts_from_nz( - count: int | npt.NDArray[np.float64], + count: int | list[int] | list[list[int]], z: list[float] | npt.NDArray[np.float64], nz: list[float] | npt.NDArray[np.float64], *, @@ -132,12 +132,12 @@ def redshifts_from_nz( cdf /= cdf[-1] # sample redshifts and store result - redshifts[total : total + count[k]] = np.interp( # type: ignore[index] - rng.uniform(0, 1, size=count[k]), # type: ignore[index] + redshifts[total : total + count[k]] = np.interp( # type: ignore[call-overload, index] + rng.uniform(0, 1, size=count[k]), # type: ignore[call-overload, index] cdf, z[k], # type: ignore[call-overload] ) - total += count[k] # type: ignore[index] + total += count[k] # type: ignore[call-overload, index] assert total == redshifts.size # noqa: S101 diff --git a/tests/test_galaxies.py b/tests/test_galaxies.py index 5b5b4f89..13968e17 100644 --- a/tests/test_galaxies.py +++ b/tests/test_galaxies.py @@ -17,7 +17,7 @@ def test_redshifts(mocker) -> None: # type: ignore[no-untyped-def] assert z.max() <= 1.0 # sample redshifts (array) - z = redshifts([[1, 2], [3, 4]], w) # type: ignore[arg-type] + z = redshifts([[1, 2], [3, 4]], w) assert z.shape == (10,) @@ -51,7 +51,7 @@ def test_redshifts_from_nz(rng: np.random.Generator) -> None: # case: no extra dimensions - count = 10 + count: int | list[int] | list[list[int]] = 10 z = np.linspace(0, 1, 100) nz = z * (1 - z) @@ -62,7 +62,7 @@ def test_redshifts_from_nz(rng: np.random.Generator) -> None: # case: extra dimensions from count - count = [10, 20, 30] # type: ignore[assignment] + count = [10, 20, 30] z = np.linspace(0, 1, 100) nz = z * (1 - z) @@ -82,7 +82,7 @@ def test_redshifts_from_nz(rng: np.random.Generator) -> None: # case: extra dimensions from count and nz - count = [[10], [20], [30]] # type: ignore[assignment] + count = [[10], [20], [30]] z = np.linspace(0, 1, 100) nz = [z * (1 - z), (z - 0.5) ** 2] # type: ignore[assignment] @@ -92,7 +92,7 @@ def test_redshifts_from_nz(rng: np.random.Generator) -> None: # case: incompatible input shapes - count = [10, 20, 30] # type: ignore[assignment] + count = [10, 20, 30] z = np.linspace(0, 1, 100) nz = [z * (1 - z), (z - 0.5) ** 2] # type: ignore[assignment] From e809b1c0a70d1aa8d51fe5853b9d014b5009d01c Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Thu, 17 Oct 2024 11:59:30 +0100 Subject: [PATCH 047/143] `ndinterp` --- glass/core/array.py | 9 ++++++--- tests/core/test_array.py | 18 +++++++++--------- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/glass/core/array.py b/glass/core/array.py index f8673f99..aa0eb7b8 100644 --- a/glass/core/array.py +++ b/glass/core/array.py @@ -57,9 +57,12 @@ def broadcast_leading_axes( def ndinterp( # noqa: PLR0913 - x: npt.NDArray[np.float64], - xp: npt.NDArray[np.float64], - fp: npt.NDArray[np.float64], + x: float | list[float] | list[list[float]] | npt.NDArray[np.float64], + xp: list[int] | npt.NDArray[np.float64], + fp: list[float] + | list[list[float]] + | list[list[list[float]]] + | npt.NDArray[np.float64], axis: int = -1, left: float | None = None, right: float | None = None, diff --git a/tests/core/test_array.py b/tests/core/test_array.py index a3f936f4..a80fc883 100644 --- a/tests/core/test_array.py +++ b/tests/core/test_array.py @@ -70,17 +70,17 @@ def test_ndinterp() -> None: ] x: float | list[float] | list[list[float]] = 0.5 - y = ndinterp(x, xp, yp) # type: ignore[arg-type] + y = ndinterp(x, xp, yp) assert np.shape(y) == () np.testing.assert_allclose(y, 1.15, atol=1e-15) x = [0.5, 1.5, 2.5] - y = ndinterp(x, xp, yp) # type: ignore[arg-type] + y = ndinterp(x, xp, yp) assert np.shape(y) == (3,) np.testing.assert_allclose(y, [1.15, 1.25, 1.35], atol=1e-15) x = [[0.5, 1.5], [2.5, 3.5]] - y = ndinterp(x, xp, yp) # type: ignore[arg-type] + 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) @@ -89,17 +89,17 @@ 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]] x = 0.5 - y = ndinterp(x, xp, yp) # type: ignore[arg-type] + y = ndinterp(x, xp, yp) assert np.shape(y) == (2,) np.testing.assert_allclose(y, [1.15, 2.15], atol=1e-15) x = [0.5, 1.5, 2.5] - y = ndinterp(x, xp, yp) # type: ignore[arg-type] + 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) x = [[0.5, 1.5], [2.5, 3.5]] - y = ndinterp(x, xp, yp) # type: ignore[arg-type] + y = ndinterp(x, xp, yp) assert np.shape(y) == (2, 2, 2) np.testing.assert_allclose( y, @@ -112,12 +112,12 @@ 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]]] x = 0.5 - y = ndinterp(x, xp, yp, axis=1) # type: ignore[arg-type] + 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) x = [0.5, 1.5, 2.5] - y = ndinterp(x, xp, yp, axis=1) # type: ignore[arg-type] + y = ndinterp(x, xp, yp, axis=1) assert np.shape(y) == (2, 3, 1) np.testing.assert_allclose( y, @@ -126,7 +126,7 @@ def test_ndinterp() -> None: ) 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]] - y = ndinterp(x, xp, yp, axis=1) # type: ignore[arg-type] + y = ndinterp(x, xp, yp, axis=1) assert np.shape(y) == (2, 3, 4, 1) np.testing.assert_allclose( y, From cb2b05ce06a9cd013b5f984f54000f7d69361cd4 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Thu, 17 Oct 2024 12:17:27 +0100 Subject: [PATCH 048/143] Type `z` --- glass/galaxies.py | 2 +- tests/test_galaxies.py | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/glass/galaxies.py b/glass/galaxies.py index ad8c35c4..00b75277 100644 --- a/glass/galaxies.py +++ b/glass/galaxies.py @@ -212,7 +212,7 @@ def galaxy_shear( # noqa: PLR0913 def gaussian_phz( - z: npt.NDArray[np.float64], + z: float | npt.NDArray[np.float64], sigma_0: float | npt.NDArray[np.float64], *, lower: npt.NDArray[np.float64] | None = None, diff --git a/tests/test_galaxies.py b/tests/test_galaxies.py index 13968e17..df6198b9 100644 --- a/tests/test_galaxies.py +++ b/tests/test_galaxies.py @@ -1,4 +1,5 @@ import numpy as np +import numpy.typing as npt import pytest from glass.galaxies import galaxy_shear, gaussian_phz, redshifts, redshifts_from_nz @@ -150,7 +151,7 @@ def test_gaussian_phz(rng: np.random.Generator) -> None: # case: zero variance - z = np.linspace(0, 1, 100) + z: float | npt.NDArray[np.float64] = np.linspace(0, 1, 100) sigma_0 = 0.0 phz = gaussian_phz(z, sigma_0) @@ -165,7 +166,7 @@ def test_gaussian_phz(rng: np.random.Generator) -> None: # case: truncated normal - z = 0.0 # type: ignore[assignment] + z = 0.0 sigma_0 = np.ones(100) # type: ignore[assignment] phz = gaussian_phz(z, sigma_0) @@ -175,7 +176,7 @@ def test_gaussian_phz(rng: np.random.Generator) -> None: # case: upper and lower bound - z = 1.0 # type: ignore[assignment] + z = 1.0 sigma_0 = np.ones(100) # type: ignore[assignment] phz = gaussian_phz(z, sigma_0, lower=0.5, upper=1.5) # type: ignore[arg-type] @@ -188,7 +189,7 @@ def test_gaussian_phz(rng: np.random.Generator) -> None: # case: scalar redshift, scalar sigma_0 - z = 1.0 # type: ignore[assignment] + z = 1.0 sigma_0 = 0.0 phz = gaussian_phz(z, sigma_0) @@ -208,7 +209,7 @@ def test_gaussian_phz(rng: np.random.Generator) -> None: # case: scalar redshift, array sigma_0 - z = 1.0 # type: ignore[assignment] + z = 1.0 sigma_0 = np.zeros(10) # type: ignore[assignment] phz = gaussian_phz(z, sigma_0) From b9ddf834d4cb1ffae5a429952ac482c7bf15ea8e Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Thu, 17 Oct 2024 12:27:11 +0100 Subject: [PATCH 049/143] Type `triaxial_axis_ratio` --- glass/shapes.py | 6 +++--- tests/test_shapes.py | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/glass/shapes.py b/glass/shapes.py index a9c4fdc6..6cf04537 100644 --- a/glass/shapes.py +++ b/glass/shapes.py @@ -29,9 +29,9 @@ def triaxial_axis_ratio( - zeta: npt.NDArray[np.float64], - xi: npt.NDArray[np.float64], - size: tuple[int] | None = None, + zeta: float | list[float] | list[list[float]] | npt.NDArray[np.float64], + xi: float | list[float], + size: int | tuple[int, int] | None = None, *, rng: np.random.Generator | None = None, ) -> npt.NDArray[np.float64]: diff --git a/tests/test_shapes.py b/tests/test_shapes.py index e73061a9..fe20e28d 100644 --- a/tests/test_shapes.py +++ b/tests/test_shapes.py @@ -12,28 +12,28 @@ 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] + q = triaxial_axis_ratio(0.8, 0.4) assert np.isscalar(q) # many axis ratios - q = triaxial_axis_ratio(0.8, 0.4, size=1000) # type: ignore[arg-type] + q = triaxial_axis_ratio(0.8, 0.4, size=1000) assert np.shape(q) == (1000,) # explicit shape - q = triaxial_axis_ratio(0.8, 0.4, size=(10, 10)) # type: ignore[arg-type] + q = triaxial_axis_ratio(0.8, 0.4, size=(10, 10)) assert np.shape(q) == (10, 10) # implicit size - 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] + q1 = triaxial_axis_ratio([0.8, 0.9], 0.4) + q2 = triaxial_axis_ratio(0.8, [0.4, 0.5]) 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]) # type: ignore[arg-type] + q = triaxial_axis_ratio([[0.6, 0.7], [0.8, 0.9]], [0.4, 0.5]) assert np.shape(q) == (2, 2) # random parameters and check that projection is From 9ebfa62c20d960a7a9e60945eaa5b6a987f12e58 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Thu, 17 Oct 2024 12:31:02 +0100 Subject: [PATCH 050/143] Add more typing --- tests/test_galaxies.py | 10 +++++----- tests/test_points.py | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/test_galaxies.py b/tests/test_galaxies.py index df6198b9..02e6cd53 100644 --- a/tests/test_galaxies.py +++ b/tests/test_galaxies.py @@ -152,7 +152,7 @@ def test_gaussian_phz(rng: np.random.Generator) -> None: # case: zero variance z: float | npt.NDArray[np.float64] = np.linspace(0, 1, 100) - sigma_0 = 0.0 + sigma_0 : float | npt.NDArray[np.float64] = 0.0 phz = gaussian_phz(z, sigma_0) @@ -167,7 +167,7 @@ def test_gaussian_phz(rng: np.random.Generator) -> None: # case: truncated normal z = 0.0 - sigma_0 = np.ones(100) # type: ignore[assignment] + sigma_0 = np.ones(100) phz = gaussian_phz(z, sigma_0) @@ -177,7 +177,7 @@ def test_gaussian_phz(rng: np.random.Generator) -> None: # case: upper and lower bound z = 1.0 - sigma_0 = np.ones(100) # type: ignore[assignment] + sigma_0 = np.ones(100) phz = gaussian_phz(z, sigma_0, lower=0.5, upper=1.5) # type: ignore[arg-type] @@ -210,7 +210,7 @@ def test_gaussian_phz(rng: np.random.Generator) -> None: # case: scalar redshift, array sigma_0 z = 1.0 - sigma_0 = np.zeros(10) # type: ignore[assignment] + sigma_0 = np.zeros(10) phz = gaussian_phz(z, sigma_0) @@ -220,7 +220,7 @@ def test_gaussian_phz(rng: np.random.Generator) -> None: # case: array redshift, array sigma_0 z = np.linspace(0, 1, 10) - sigma_0 = np.zeros((11, 1)) # type: ignore[assignment] + sigma_0 = np.zeros((11, 1)) phz = gaussian_phz(z, sigma_0) diff --git a/tests/test_points.py b/tests/test_points.py index a78bea09..0942a75e 100644 --- a/tests/test_points.py +++ b/tests/test_points.py @@ -31,7 +31,7 @@ def catpos( # type: ignore[no-untyped-def] def test_positions_from_delta() -> None: # case: single-dimensional input - ngal = 1e-3 + ngal: float | list[float] = 1e-3 delta = np.zeros(12) bias = 0.8 vis = np.ones(12) @@ -43,7 +43,7 @@ def test_positions_from_delta() -> None: # case: multi-dimensional ngal - ngal = [1e-3, 2e-3] # type: ignore[assignment] + ngal = [1e-3, 2e-3] delta = np.zeros(12) bias = 0.8 vis = np.ones(12) @@ -69,7 +69,7 @@ def test_positions_from_delta() -> None: # case: multi-dimensional broadcasting - ngal = [1e-3, 2e-3] # type: ignore[assignment] + ngal = [1e-3, 2e-3] delta = np.zeros((3, 1, 12)) bias = 0.8 vis = np.ones(12) From a5b0f7bf121ba138c84a5d0465bbcd053a3dea93 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Thu, 17 Oct 2024 12:52:55 +0100 Subject: [PATCH 051/143] Type `ngal` --- tests/test_points.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_points.py b/tests/test_points.py index 0942a75e..57b810f9 100644 --- a/tests/test_points.py +++ b/tests/test_points.py @@ -84,7 +84,7 @@ def test_positions_from_delta() -> None: def test_uniform_positions() -> None: # case: scalar input - ngal = 1e-3 + ngal: float | list[float] | list[list[float]] = 1e-3 lon, lat, cnt = catpos(uniform_positions(ngal)) @@ -93,7 +93,7 @@ def test_uniform_positions() -> None: # case: 1-D array input - ngal = [1e-3, 2e-3, 3e-3] # type: ignore[assignment] + ngal = [1e-3, 2e-3, 3e-3] lon, lat, cnt = catpos(uniform_positions(ngal)) @@ -102,7 +102,7 @@ def test_uniform_positions() -> None: # case: 2-D array input - ngal = [[1e-3, 2e-3], [3e-3, 4e-3], [5e-3, 6e-3]] # type: ignore[assignment] + ngal = [[1e-3, 2e-3], [3e-3, 4e-3], [5e-3, 6e-3]] lon, lat, cnt = catpos(uniform_positions(ngal)) From 7fe9725c07b98a3c6242e54f6bcd8e19170fab6d Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Thu, 17 Oct 2024 13:11:01 +0100 Subject: [PATCH 052/143] Fix `uniform_positions` --- glass/points.py | 2 +- tests/test_galaxies.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/glass/points.py b/glass/points.py index 29d64f1c..3876f3a4 100644 --- a/glass/points.py +++ b/glass/points.py @@ -272,7 +272,7 @@ def positions_from_delta( # noqa: PLR0912, PLR0913, PLR0915 def uniform_positions( - ngal: float | list[float], + ngal: float | list[float] | list[list[float]], *, rng: np.random.Generator | None = None, ) -> collections.abc.Generator[ diff --git a/tests/test_galaxies.py b/tests/test_galaxies.py index 02e6cd53..721c306e 100644 --- a/tests/test_galaxies.py +++ b/tests/test_galaxies.py @@ -152,7 +152,7 @@ def test_gaussian_phz(rng: np.random.Generator) -> None: # case: zero variance z: float | npt.NDArray[np.float64] = np.linspace(0, 1, 100) - sigma_0 : float | npt.NDArray[np.float64] = 0.0 + sigma_0: float | npt.NDArray[np.float64] = 0.0 phz = gaussian_phz(z, sigma_0) From eaa525cda9dce76762144d7612b4dc3eb552484a Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Thu, 17 Oct 2024 13:13:21 +0100 Subject: [PATCH 053/143] `var-annotated` --- tests/test_points.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/test_points.py b/tests/test_points.py index 57b810f9..2bafae0e 100644 --- a/tests/test_points.py +++ b/tests/test_points.py @@ -20,7 +20,9 @@ def catpos( # type: ignore[no-untyped-def] ] ], ): - lon, lat, cnt = [], [], 0 # type: ignore[var-annotated] + lon: list[float] = [] + lat: list[float] = [] + cnt: int = 0 for lo, la, co in pos: lon = np.concatenate([lon, lo]) # type: ignore[assignment] lat = np.concatenate([lat, la]) # type: ignore[assignment] From a8753f31c7b1c1be28fe6b433f045183cb34c036 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Thu, 17 Oct 2024 14:11:07 +0100 Subject: [PATCH 054/143] Tidy `catpos` --- tests/test_points.py | 50 ++++++++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/tests/test_points.py b/tests/test_points.py index 2bafae0e..e08a4f17 100644 --- a/tests/test_points.py +++ b/tests/test_points.py @@ -11,7 +11,7 @@ import collections.abc -def catpos( # type: ignore[no-untyped-def] +def catpos( pos: collections.abc.Generator[ tuple[ npt.NDArray[np.float64], @@ -19,14 +19,18 @@ def catpos( # type: ignore[no-untyped-def] int | npt.NDArray[np.int_], ] ], -): - lon: list[float] = [] - lat: list[float] = [] - cnt: int = 0 +) -> tuple[ + list[float] | npt.NDArray[np.float64], + list[float] | npt.NDArray[np.float64], + int | npt.NDArray[np.int_], +]: + lon: list[float] | npt.NDArray[np.float64] = [] + lat: list[float] | npt.NDArray[np.float64] = [] + cnt: int | npt.NDArray[np.int_] = 0 for lo, la, co in pos: - lon = np.concatenate([lon, lo]) # type: ignore[assignment] - lat = np.concatenate([lat, la]) # type: ignore[assignment] - cnt = cnt + co # type: ignore[assignment] + lon = np.concatenate([lon, lo]) + lat = np.concatenate([lat, la]) + cnt = cnt + co return lon, lat, cnt @@ -41,7 +45,7 @@ def test_positions_from_delta() -> None: lon, lat, cnt = catpos(positions_from_delta(ngal, delta, bias, vis)) assert isinstance(cnt, int) - assert lon.shape == lat.shape == (cnt,) + assert lon.shape == lat.shape == (cnt,) # type: ignore[union-attr] # case: multi-dimensional ngal @@ -52,9 +56,9 @@ def test_positions_from_delta() -> None: lon, lat, cnt = catpos(positions_from_delta(ngal, delta, bias, vis)) - assert cnt.shape == (2,) - assert lon.shape == (cnt.sum(),) - assert lat.shape == (cnt.sum(),) + assert cnt.shape == (2,) # type: ignore[union-attr] + assert lon.shape == (cnt.sum(),) # type: ignore[union-attr] + assert lat.shape == (cnt.sum(),) # type: ignore[union-attr] # case: multi-dimensional delta @@ -65,9 +69,9 @@ def test_positions_from_delta() -> None: lon, lat, cnt = catpos(positions_from_delta(ngal, delta, bias, vis)) - assert cnt.shape == (3, 2) - assert lon.shape == (cnt.sum(),) - assert lat.shape == (cnt.sum(),) + assert cnt.shape == (3, 2) # type: ignore[union-attr] + assert lon.shape == (cnt.sum(),) # type: ignore[union-attr] + assert lat.shape == (cnt.sum(),) # type: ignore[union-attr] # case: multi-dimensional broadcasting @@ -78,9 +82,9 @@ def test_positions_from_delta() -> None: lon, lat, cnt = catpos(positions_from_delta(ngal, delta, bias, vis)) - assert cnt.shape == (3, 2) - assert lon.shape == (cnt.sum(),) - assert lat.shape == (cnt.sum(),) + assert cnt.shape == (3, 2) # type: ignore[union-attr] + assert lon.shape == (cnt.sum(),) # type: ignore[union-attr] + assert lat.shape == (cnt.sum(),) # type: ignore[union-attr] def test_uniform_positions() -> None: @@ -91,7 +95,7 @@ def test_uniform_positions() -> None: lon, lat, cnt = catpos(uniform_positions(ngal)) assert isinstance(cnt, int) - assert lon.shape == lat.shape == (cnt,) + assert lon.shape == lat.shape == (cnt,) # type: ignore[union-attr] # case: 1-D array input @@ -99,8 +103,8 @@ def test_uniform_positions() -> None: lon, lat, cnt = catpos(uniform_positions(ngal)) - assert cnt.shape == (3,) - assert lon.shape == lat.shape == (cnt.sum(),) + assert cnt.shape == (3,) # type: ignore[union-attr] + assert lon.shape == lat.shape == (cnt.sum(),) # type: ignore[union-attr] # case: 2-D array input @@ -108,8 +112,8 @@ def test_uniform_positions() -> None: lon, lat, cnt = catpos(uniform_positions(ngal)) - assert cnt.shape == (3, 2) - assert lon.shape == lat.shape == (cnt.sum(),) + assert cnt.shape == (3, 2) # type: ignore[union-attr] + assert lon.shape == lat.shape == (cnt.sum(),) # type: ignore[union-attr] def test_position_weights(rng: np.random.Generator) -> None: From 4ed953bfca1979520e88e86800f059d35b496b3d Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Thu, 17 Oct 2024 14:31:31 +0100 Subject: [PATCH 055/143] Fix `nz` typing --- glass/galaxies.py | 5 ++++- glass/shells.py | 7 ++++++- tests/test_galaxies.py | 8 ++++---- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/glass/galaxies.py b/glass/galaxies.py index 00b75277..88f0023f 100644 --- a/glass/galaxies.py +++ b/glass/galaxies.py @@ -69,7 +69,10 @@ def redshifts( def redshifts_from_nz( count: int | list[int] | list[list[int]], z: list[float] | npt.NDArray[np.float64], - nz: list[float] | npt.NDArray[np.float64], + nz: list[int] + | list[float] + | npt.NDArray[np.float64] + | list[npt.NDArray[np.float64]], *, rng: np.random.Generator | None = None, warn: bool = True, diff --git a/glass/shells.py b/glass/shells.py index 805a183f..5fced9a5 100644 --- a/glass/shells.py +++ b/glass/shells.py @@ -130,7 +130,12 @@ class RadialWindow(typing.NamedTuple): """ za: list[float] | npt.NDArray[np.float64] - wa: list[float] | npt.NDArray[np.float64] + wa: ( + list[int] + | list[float] + | npt.NDArray[np.float64] + | list[npt.NDArray[np.float64]] + ) zeff: float | None diff --git a/tests/test_galaxies.py b/tests/test_galaxies.py index 721c306e..ac74e94d 100644 --- a/tests/test_galaxies.py +++ b/tests/test_galaxies.py @@ -54,7 +54,7 @@ def test_redshifts_from_nz(rng: np.random.Generator) -> None: count: int | list[int] | list[list[int]] = 10 z = np.linspace(0, 1, 100) - nz = z * (1 - z) + nz: npt.NDArray[np.float64] | list[npt.NDArray[np.float64]] = z * (1 - z) redshifts = redshifts_from_nz(count, z, nz, warn=False) @@ -75,7 +75,7 @@ def test_redshifts_from_nz(rng: np.random.Generator) -> None: count = 10 z = np.linspace(0, 1, 100) - nz = [z * (1 - z), (z - 0.5) ** 2] # type: ignore[assignment] + nz = [z * (1 - z), (z - 0.5) ** 2] redshifts = redshifts_from_nz(count, z, nz, warn=False) @@ -85,7 +85,7 @@ def test_redshifts_from_nz(rng: np.random.Generator) -> None: count = [[10], [20], [30]] z = np.linspace(0, 1, 100) - nz = [z * (1 - z), (z - 0.5) ** 2] # type: ignore[assignment] + nz = [z * (1 - z), (z - 0.5) ** 2] redshifts = redshifts_from_nz(count, z, nz, warn=False) @@ -95,7 +95,7 @@ def test_redshifts_from_nz(rng: np.random.Generator) -> None: count = [10, 20, 30] z = np.linspace(0, 1, 100) - nz = [z * (1 - z), (z - 0.5) ** 2] # type: ignore[assignment] + nz = [z * (1 - z), (z - 0.5) ** 2] with pytest.raises(ValueError, match="shape mismatch"): redshifts_from_nz(count, z, nz, warn=False) From 5d4b6327bf3f74beb597975809aa628d20fc3ebb Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Thu, 17 Oct 2024 14:38:37 +0100 Subject: [PATCH 056/143] Fix lower/upper --- glass/galaxies.py | 16 ++++++++-------- tests/test_galaxies.py | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/glass/galaxies.py b/glass/galaxies.py index 88f0023f..7810011f 100644 --- a/glass/galaxies.py +++ b/glass/galaxies.py @@ -218,8 +218,8 @@ def gaussian_phz( z: float | npt.NDArray[np.float64], sigma_0: float | npt.NDArray[np.float64], *, - lower: npt.NDArray[np.float64] | None = None, - upper: npt.NDArray[np.float64] | None = None, + lower: float | npt.NDArray[np.float64] | None = None, + upper: float | npt.NDArray[np.float64] | None = None, rng: np.random.Generator | None = None, ) -> npt.NDArray[np.float64]: r""" @@ -276,24 +276,24 @@ def gaussian_phz( zphot = rng.normal(z, sigma) if lower is None: - lower = 0.0 # type: ignore[assignment] + lower = 0.0 if upper is None: - upper = np.inf # type: ignore[assignment] + upper = np.inf - if not np.all(lower < upper): # type: ignore[operator] + if not np.all(lower < upper): msg = "requires lower < upper" raise ValueError(msg) if not dims: - while zphot < lower or zphot > upper: # type: ignore[operator] + while zphot < lower or zphot > upper: zphot = rng.normal(z, sigma) else: z = np.broadcast_to(z, dims) - trunc = np.where((zphot < lower) | (zphot > upper))[0] # type: ignore[operator] + trunc = np.where((zphot < lower) | (zphot > upper))[0] while trunc.size: znew = rng.normal(z[trunc], sigma[trunc]) zphot[trunc] = znew - trunc = trunc[(znew < lower) | (znew > upper)] # type: ignore[operator] + trunc = trunc[(znew < lower) | (znew > upper)] return zphot diff --git a/tests/test_galaxies.py b/tests/test_galaxies.py index ac74e94d..4305edc4 100644 --- a/tests/test_galaxies.py +++ b/tests/test_galaxies.py @@ -179,7 +179,7 @@ def test_gaussian_phz(rng: np.random.Generator) -> None: z = 1.0 sigma_0 = np.ones(100) - phz = gaussian_phz(z, sigma_0, lower=0.5, upper=1.5) # type: ignore[arg-type] + phz = gaussian_phz(z, sigma_0, lower=0.5, upper=1.5) assert phz.shape == (100,) assert np.all(phz >= 0.5) From ce10ed0b4b62044e1f18c9c9d1f4fa126dced62e Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Thu, 17 Oct 2024 14:39:52 +0100 Subject: [PATCH 057/143] Fix `wht` --- glass/shells.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/glass/shells.py b/glass/shells.py index 5fced9a5..5621620f 100644 --- a/glass/shells.py +++ b/glass/shells.py @@ -183,8 +183,8 @@ def tophat_windows( stacklevel=2, ) - wht: WeightFunc - wht = weight if weight is not None else np.ones_like # type: ignore[assignment] + wht: WeightFunc | npt.NDArray[np.float64] + wht = weight if weight is not None else np.ones_like ws = [] for zmin, zmax in zip(zbins, zbins[1:]): n = max(round((zmax - zmin) / dz), 2) From d6c1cfbdf9cbc219a75c14350dcd086699dc18fb Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Thu, 17 Oct 2024 14:43:00 +0100 Subject: [PATCH 058/143] `cmask` and `count` --- glass/points.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/glass/points.py b/glass/points.py index 3876f3a4..28398420 100644 --- a/glass/points.py +++ b/glass/points.py @@ -234,11 +234,12 @@ def positions_from_delta( # noqa: PLR0912, PLR0913, PLR0915 nside = healpix.npix2nside(npix) # create a mask to report the count in the right axis + cmask: int | npt.NDArray[np.int_] if dims: cmask = np.zeros(dims, dtype=int) cmask[k] = 1 else: - cmask = 1 # type: ignore[assignment] + cmask = 1 # sample the map in batches step = 1000 @@ -325,11 +326,12 @@ def uniform_positions( lat = np.rad2deg(np.arcsin(rng.uniform(-1, 1, size=ngal[k]))) # type: ignore[call-overload, index] # report count + count: int | npt.NDArray[np.int_] if dims: count = np.zeros(dims, dtype=int) count[k] = ngal[k] # type: ignore[call-overload, index] else: - count = int(ngal[k]) # type: ignore[assignment, call-overload, index] + count = int(ngal[k]) # type: ignore[call-overload, index] yield lon, lat, count # type: ignore[misc] From b1d0131cae89f083815f503ab41bd12784e31990 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Thu, 17 Oct 2024 14:58:51 +0100 Subject: [PATCH 059/143] Type `a` --- glass/shells.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/glass/shells.py b/glass/shells.py index 5621620f..2fc2b89e 100644 --- a/glass/shells.py +++ b/glass/shells.py @@ -484,7 +484,9 @@ 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: list[npt.NDArray[np.float64]] | npt.NDArray[np.float64] = [ + 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 @@ -494,14 +496,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) # type: ignore[assignment] + 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) # 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] # type: ignore[arg-type, attr-defined] + x = np.linalg.lstsq(a.T, b.reshape(-1, zp.size + 1).T, rcond=None)[0] # type: ignore[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) From fca667e8ecde9940e361974ead02b0024adc8277 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Thu, 17 Oct 2024 15:16:50 +0100 Subject: [PATCH 060/143] Type `ellipticity_ryden04` --- glass/shapes.py | 8 ++++---- tests/test_shapes.py | 22 +++++++++++----------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/glass/shapes.py b/glass/shapes.py index 6cf04537..86e6fe5e 100644 --- a/glass/shapes.py +++ b/glass/shapes.py @@ -97,10 +97,10 @@ def triaxial_axis_ratio( def ellipticity_ryden04( # noqa: PLR0913 - mu: npt.NDArray[np.float64], - sigma: npt.NDArray[np.float64], - gamma: npt.NDArray[np.float64], - sigma_gamma: npt.NDArray[np.float64], + mu: float | list[float] | npt.NDArray[np.float64], + sigma: float | list[float] | npt.NDArray[np.float64], + gamma: float | list[float] | list[list[float]] | npt.NDArray[np.float64], + sigma_gamma: float | list[float] | npt.NDArray[np.float64], size: int | tuple[int, ...] | None = None, *, rng: np.random.Generator | None = None, diff --git a/tests/test_shapes.py b/tests/test_shapes.py index fe20e28d..3aaaf8d6 100644 --- a/tests/test_shapes.py +++ b/tests/test_shapes.py @@ -49,43 +49,43 @@ def test_triaxial_axis_ratio(rng: np.random.Generator) -> None: def test_ellipticity_ryden04(rng: np.random.Generator) -> None: # single ellipticity - e = ellipticity_ryden04(-1.85, 0.89, 0.222, 0.056) # type: ignore[arg-type] + e = ellipticity_ryden04(-1.85, 0.89, 0.222, 0.056) assert np.isscalar(e) # test with rng - e = ellipticity_ryden04(-1.85, 0.89, 0.222, 0.056, rng=rng) # type: ignore[arg-type] + e = ellipticity_ryden04(-1.85, 0.89, 0.222, 0.056, rng=rng) assert np.isscalar(e) # many ellipticities - e = ellipticity_ryden04(-1.85, 0.89, 0.222, 0.056, size=1000) # type: ignore[arg-type] + e = ellipticity_ryden04(-1.85, 0.89, 0.222, 0.056, size=1000) assert np.shape(e) == (1000,) # explicit shape - e = ellipticity_ryden04(-1.85, 0.89, 0.222, 0.056, size=(10, 10)) # type: ignore[arg-type] + e = ellipticity_ryden04(-1.85, 0.89, 0.222, 0.056, size=(10, 10)) assert np.shape(e) == (10, 10) # implicit size - 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] + 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) 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) # type: ignore[arg-type] + e = ellipticity_ryden04([-1.9, -2.9], 0.9, [[0.2, 0.3], [0.4, 0.5]], 0.1) 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) # type: ignore[arg-type] + e = ellipticity_ryden04(0.0, 1.0, 0.222, 0.056, size=10) assert np.all((e.real >= -1.0) & (e.real <= 1.0)) - e = ellipticity_ryden04(0.0, 1.0, 0.0, 1.0, size=10) # type: ignore[arg-type] + e = ellipticity_ryden04(0.0, 1.0, 0.0, 1.0, size=10) assert np.all((e.real >= -1.0) & (e.real <= 1.0)) From c58fc87fb7e6a8a7927efa01b08fa5a325ab11c0 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Thu, 17 Oct 2024 15:24:11 +0100 Subject: [PATCH 061/143] Fix `ellipticity_gaussian` --- glass/shapes.py | 4 ++-- tests/test_shapes.py | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/glass/shapes.py b/glass/shapes.py index 86e6fe5e..0c6f0a47 100644 --- a/glass/shapes.py +++ b/glass/shapes.py @@ -178,8 +178,8 @@ def ellipticity_ryden04( # noqa: PLR0913 def ellipticity_gaussian( - count: int | npt.NDArray[np.float64], - sigma: npt.NDArray[np.float64], + count: int | list[int] | npt.NDArray[np.int_], + sigma: float | list[float] | npt.NDArray[np.float64], *, rng: np.random.Generator | None = None, ) -> npt.NDArray[np.complex128]: diff --git a/tests/test_shapes.py b/tests/test_shapes.py index 3aaaf8d6..822a8d0e 100644 --- a/tests/test_shapes.py +++ b/tests/test_shapes.py @@ -92,13 +92,13 @@ def test_ellipticity_ryden04(rng: np.random.Generator) -> None: def test_ellipticity_gaussian(rng: np.random.Generator) -> None: n = 1_000_000 - eps = ellipticity_gaussian(n, 0.256) # type: ignore[arg-type] + eps = ellipticity_gaussian(n, 0.256) assert eps.shape == (n,) # test with rng - eps = ellipticity_gaussian(n, 0.256, rng=rng) # type: ignore[arg-type] + eps = ellipticity_gaussian(n, 0.256, rng=rng) assert eps.shape == (n,) @@ -107,7 +107,7 @@ def test_ellipticity_gaussian(rng: np.random.Generator) -> 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-2, rtol=0) - eps = ellipticity_gaussian([n, n], [0.128, 0.256]) # type: ignore[arg-type] + eps = ellipticity_gaussian([n, n], [0.128, 0.256]) assert eps.shape == (2 * n,) From 16e7b15f3c81892eb7af8065e97dd59377398142 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Thu, 17 Oct 2024 15:27:50 +0100 Subject: [PATCH 062/143] `ellipticity_intnorm` --- glass/shapes.py | 4 ++-- tests/test_shapes.py | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/glass/shapes.py b/glass/shapes.py index 0c6f0a47..b377ab91 100644 --- a/glass/shapes.py +++ b/glass/shapes.py @@ -232,8 +232,8 @@ def ellipticity_gaussian( def ellipticity_intnorm( - count: int | npt.NDArray[np.float64], - sigma: npt.NDArray[np.float64], + count: int | list[int] | npt.NDArray[np.int_], + sigma: float | list[float] | npt.NDArray[np.float64], *, rng: np.random.Generator | None = None, ) -> npt.NDArray[np.complex128]: diff --git a/tests/test_shapes.py b/tests/test_shapes.py index 822a8d0e..f39e5587 100644 --- a/tests/test_shapes.py +++ b/tests/test_shapes.py @@ -122,13 +122,13 @@ def test_ellipticity_gaussian(rng: np.random.Generator) -> None: def test_ellipticity_intnorm(rng: np.random.Generator) -> None: n = 1_000_000 - eps = ellipticity_intnorm(n, 0.256) # type: ignore[arg-type] + eps = ellipticity_intnorm(n, 0.256) assert eps.shape == (n,) # test with rng - eps = ellipticity_intnorm(n, 0.256, rng=rng) # type: ignore[arg-type] + eps = ellipticity_intnorm(n, 0.256, rng=rng) assert eps.shape == (n,) @@ -137,7 +137,7 @@ def test_ellipticity_intnorm(rng: np.random.Generator) -> 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]) # type: ignore[arg-type] + eps = ellipticity_intnorm([n, n], [0.128, 0.256]) assert eps.shape == (2 * n,) @@ -149,4 +149,4 @@ def test_ellipticity_intnorm(rng: np.random.Generator) -> None: np.testing.assert_allclose(np.std(eps.imag[n:]), 0.256, atol=1e-3, rtol=0) with pytest.raises(ValueError, match="sigma must be between"): - ellipticity_intnorm(1, 0.71) # type: ignore[arg-type] + ellipticity_intnorm(1, 0.71) From 7c9341b0207cbe5046e6d7bb03f51eb762017ad6 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Thu, 17 Oct 2024 15:38:53 +0100 Subject: [PATCH 063/143] Sort `deflect` typing --- glass/lensing.py | 6 +++--- tests/test_lensing.py | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/glass/lensing.py b/glass/lensing.py index f8441f36..5c611f41 100644 --- a/glass/lensing.py +++ b/glass/lensing.py @@ -420,9 +420,9 @@ def multi_plane_weights( def deflect( - lon: npt.NDArray[np.float64], - lat: npt.NDArray[np.float64], - alpha: npt.NDArray[np.float64], + lon: float | npt.NDArray[np.float64], + lat: float | npt.NDArray[np.float64], + alpha: complex | list[float] | npt.NDArray[np.complex128] | npt.NDArray[np.float64], ) -> tuple[ npt.NDArray[np.float64], npt.NDArray[np.float64], diff --git a/tests/test_lensing.py b/tests/test_lensing.py index dcfd7dfc..17573cc9 100644 --- a/tests/test_lensing.py +++ b/tests/test_lensing.py @@ -58,19 +58,19 @@ def alpha(re: float, im: float) -> list[float]: # type: ignore[misc] return [re, im] # north - lon, lat = deflect(0.0, 0.0, alpha(r, 0)) # type: ignore[arg-type] + lon, lat = deflect(0.0, 0.0, alpha(r, 0)) 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[arg-type] + lon, lat = deflect(0.0, 0.0, alpha(-r, 0)) 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[arg-type] + lon, lat = deflect(0.0, 0.0, alpha(0, r)) 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[arg-type] + lon, lat = deflect(0.0, 0.0, alpha(0, -r)) np.testing.assert_allclose([lon, lat], [d, 0.0], atol=1e-15) From 7b6d294b55ef36a732ccbede3cc7f5e902e4c24c Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Thu, 17 Oct 2024 15:42:41 +0100 Subject: [PATCH 064/143] Fix typing --- glass/core/array.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/glass/core/array.py b/glass/core/array.py index aa0eb7b8..227c93fd 100644 --- a/glass/core/array.py +++ b/glass/core/array.py @@ -98,8 +98,8 @@ def trapz_product( def cumtrapz( - f: npt.NDArray[np.float64], - x: npt.NDArray[np.float64], + f: npt.NDArray[np.int_] | npt.NDArray[np.float64], + x: npt.NDArray[np.int_] | npt.NDArray[np.float64], dtype: np.dtype[np.float64] | None = None, out: npt.NDArray[np.float64] | None = None, ) -> npt.NDArray[np.float64]: From 0b8d071381cb304dac67d195409ae10a5a3c555e Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Fri, 18 Oct 2024 09:57:41 +0100 Subject: [PATCH 065/143] Fix `arg-type` --- glass/core/array.py | 11 ++++++++++- glass/galaxies.py | 2 +- glass/points.py | 2 +- tests/core/test_array.py | 2 +- 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/glass/core/array.py b/glass/core/array.py index 227c93fd..1f7a903e 100644 --- a/glass/core/array.py +++ b/glass/core/array.py @@ -18,7 +18,16 @@ def broadcast_first( def broadcast_leading_axes( - *args: tuple[npt.NDArray[np.float64], int], + *args: tuple[ + int + | float + | npt.NDArray[np.float64] + | list[int] + | list[float] + | list[npt.NDArray[np.float64]] + | list[list[int]], + int, + ], ) -> tuple[tuple[int, ...], ...]: """ Broadcast all but the last N axes. diff --git a/glass/galaxies.py b/glass/galaxies.py index 7810011f..6ddc39e6 100644 --- a/glass/galaxies.py +++ b/glass/galaxies.py @@ -120,7 +120,7 @@ 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)) # type: ignore[arg-type, assignment] + dims, count, z, nz = broadcast_leading_axes((count, 0), (z, 1), (nz, 1)) # type: ignore[assignment] # list of results for all dimensions redshifts = np.empty(count.sum()) # type: ignore[union-attr] diff --git a/glass/points.py b/glass/points.py index 28398420..7975339b 100644 --- a/glass/points.py +++ b/glass/points.py @@ -194,7 +194,7 @@ 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) # type: ignore[arg-type, assignment] + dims, ngal, delta, *rest = broadcast_leading_axes(*inputs) # type: ignore[assignment] if bias is not None: bias, *rest = rest # type: ignore[assignment] if vis is not None: diff --git a/tests/core/test_array.py b/tests/core/test_array.py index a80fc883..5bb0e415 100644 --- a/tests/core/test_array.py +++ b/tests/core/test_array.py @@ -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[arg-type, assignment] + 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) # type: ignore[attr-defined] From 6c8f9247a788b3e2c2e921e24382b7f8c28914d5 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Fri, 18 Oct 2024 10:39:53 +0100 Subject: [PATCH 066/143] `dtype` --- glass/core/array.py | 2 +- glass/galaxies.py | 2 +- tests/core/test_array.py | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/glass/core/array.py b/glass/core/array.py index 1f7a903e..586fb45c 100644 --- a/glass/core/array.py +++ b/glass/core/array.py @@ -109,7 +109,7 @@ def trapz_product( def cumtrapz( f: npt.NDArray[np.int_] | npt.NDArray[np.float64], x: npt.NDArray[np.int_] | npt.NDArray[np.float64], - dtype: np.dtype[np.float64] | None = None, + dtype: type | None = None, out: npt.NDArray[np.float64] | None = None, ) -> npt.NDArray[np.float64]: """Cumulative trapezoidal rule along last axis.""" diff --git a/glass/galaxies.py b/glass/galaxies.py index 6ddc39e6..adcf6449 100644 --- a/glass/galaxies.py +++ b/glass/galaxies.py @@ -131,7 +131,7 @@ 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 = cumtrapz(nz[k], z[k], dtype=float) # type: ignore[call-overload] cdf /= cdf[-1] # sample redshifts and store result diff --git a/tests/core/test_array.py b/tests/core/test_array.py index 5bb0e415..b2acdba6 100644 --- a/tests/core/test_array.py +++ b/tests/core/test_array.py @@ -174,13 +174,13 @@ def test_cumtrapz() -> None: # explicit dtype (float) - glass_ct = cumtrapz(f, x, dtype=float) # type: ignore[arg-type] + glass_ct = cumtrapz(f, x, dtype=float) scipy_ct = cumulative_trapezoid(f, x, initial=0) 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] + result = cumtrapz(f, x, dtype=float, out=np.zeros((4,))) scipy_ct = cumulative_trapezoid(f, x, initial=0) np.testing.assert_allclose(result, scipy_ct) @@ -196,12 +196,12 @@ def test_cumtrapz() -> None: # explicit dtype (float) - glass_ct = cumtrapz(f, x, dtype=float) # type: ignore[arg-type] + glass_ct = cumtrapz(f, x, dtype=float) scipy_ct = cumulative_trapezoid(f, x, initial=0) 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] + glass_ct = cumtrapz(f, x, dtype=float, out=np.zeros((2, 4))) scipy_ct = cumulative_trapezoid(f, x, initial=0) np.testing.assert_allclose(glass_ct, scipy_ct) From 7b2703f20789893b567491e56c7c37e7d889654a Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Fri, 18 Oct 2024 10:44:48 +0100 Subject: [PATCH 067/143] `zsrc` --- glass/lensing.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/glass/lensing.py b/glass/lensing.py index 5c611f41..a1b22ed2 100644 --- a/glass/lensing.py +++ b/glass/lensing.py @@ -275,8 +275,8 @@ def __init__(self, cosmo: Cosmology) -> None: self.cosmo = cosmo # set up initial values of variables - self.z2: float = 0.0 - self.z3: float = 0.0 + self.z2: float | None = 0.0 + self.z3: float | None = 0.0 self.x3: float = 0.0 self.w3: float = 0.0 self.r23: float = 1.0 @@ -295,16 +295,16 @@ def add_window(self, delta: npt.NDArray[np.float64], 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] - self.add_plane(delta, zsrc, lens_weight) # type: ignore[arg-type] + self.add_plane(delta, zsrc, lens_weight) def add_plane( self, delta: npt.NDArray[np.float64], - zsrc: float, + zsrc: float | None, wlens: float = 1.0, ) -> None: """Add a mass plane at redshift ``zsrc`` to the convergence.""" - if zsrc <= self.z3: + if zsrc <= self.z3: # type: ignore[operator] msg = "source redshift must be increasing" raise ValueError(msg) @@ -326,7 +326,7 @@ def add_plane( # lensing weight of mass plane to be added f = 3 * self.cosmo.omega_m / 2 f *= x2 * self.r23 - f *= (1 + self.z2) / self.cosmo.ef(self.z2) + f *= (1 + self.z2) / self.cosmo.ef(self.z2) # type: ignore[operator] f *= w2 # create kappa planes on first iteration @@ -346,7 +346,7 @@ def add_plane( self.kappa3 += f * delta2 @property - def zsrc(self) -> float: + def zsrc(self) -> float | None: """The redshift of the current convergence plane.""" return self.z3 From a6af6eafc3ec13df57c97e2c809fab1e23d49d41 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Fri, 18 Oct 2024 11:07:40 +0100 Subject: [PATCH 068/143] Remove custom types --- glass/fields.py | 65 ++++++++++++++++++++++++++++++++----------------- glass/shells.py | 43 +++++++++++++++++++++----------- 2 files changed, 71 insertions(+), 37 deletions(-) diff --git a/glass/fields.py b/glass/fields.py index 58303391..46cd943c 100644 --- a/glass/fields.py +++ b/glass/fields.py @@ -26,7 +26,6 @@ from __future__ import annotations -import collections.abc import typing import warnings @@ -35,24 +34,17 @@ import numpy.typing as npt from gaussiancl import gaussiancl -# types -Size = typing.Union[int, tuple[int, ...]] -Iternorm = tuple[typing.Optional[int], npt.NDArray[np.float64], npt.NDArray[np.float64]] -ClTransform = typing.Union[ - str, - typing.Callable[[npt.NDArray[np.float64]], npt.NDArray[np.float64]], -] -Cls = collections.abc.Sequence[ - typing.Union[npt.NDArray[np.float64], collections.abc.Sequence[float]] -] -Alms = npt.NDArray[np.complex128] +if typing.TYPE_CHECKING: + import collections.abc def iternorm( k: int, cov: collections.abc.Iterable[npt.NDArray[np.float64]], - size: Size | None = None, -) -> collections.abc.Generator[Iternorm]: + size: int | tuple[int, ...] | None = None, +) -> collections.abc.Generator[ + tuple[int | None, npt.NDArray[np.float64], npt.NDArray[np.float64]] +]: """Return the vector a and variance sigma^2 for iterative normal sampling.""" n: tuple[int, ...] if size is None: @@ -111,7 +103,9 @@ def iternorm( def cls2cov( - cls: Cls, + cls: collections.abc.Sequence[ + npt.NDArray[np.float64] | collections.abc.Sequence[float] + ], nl: int, nf: int, nc: int, @@ -135,7 +129,12 @@ def cls2cov( yield cov -def multalm(alm: Alms, bl: npt.NDArray[np.float64], *, inplace: bool = False) -> Alms: +def multalm( + alm: npt.NDArray[np.complex128], + bl: npt.NDArray[np.float64], + *, + inplace: bool = False, +) -> npt.NDArray[np.complex128]: """Multiply alm by bl.""" n = len(bl) out = np.asanyarray(alm) if inplace else np.copy(alm) @@ -144,7 +143,15 @@ def multalm(alm: Alms, bl: npt.NDArray[np.float64], *, inplace: bool = False) -> return out -def transform_cls(cls: Cls, tfm: ClTransform, pars: tuple[typing.Any, ...] = ()) -> Cls: +def transform_cls( + cls: collections.abc.Sequence[ + npt.NDArray[np.float64] | collections.abc.Sequence[float] + ], + tfm: str | typing.Callable[[npt.NDArray[np.float64]], npt.NDArray[np.float64]], + pars: tuple[typing.Any, ...] = (), +) -> collections.abc.Sequence[ + npt.NDArray[np.float64] | collections.abc.Sequence[float] +]: """Transform Cls to Gaussian Cls.""" gls = [] for cl in cls: @@ -163,12 +170,16 @@ def transform_cls(cls: Cls, tfm: ClTransform, pars: tuple[typing.Any, ...] = ()) def discretized_cls( - cls: Cls, + cls: collections.abc.Sequence[ + npt.NDArray[np.float64] | collections.abc.Sequence[float] + ], *, lmax: int | None = None, ncorr: int | None = None, nside: int | None = None, -) -> Cls: +) -> collections.abc.Sequence[ + npt.NDArray[np.float64] | collections.abc.Sequence[float] +]: """ Apply discretisation effects to angular power spectra. @@ -205,15 +216,21 @@ def discretized_cls( def lognormal_gls( - cls: Cls, + cls: collections.abc.Sequence[ + npt.NDArray[np.float64] | collections.abc.Sequence[float] + ], shift: float = 1.0, -) -> Cls: +) -> collections.abc.Sequence[ + npt.NDArray[np.float64] | collections.abc.Sequence[float] +]: """Compute Gaussian Cls for a lognormal random field.""" return transform_cls(cls, "lognormal", (shift,)) def generate_gaussian( - gls: Cls, + gls: collections.abc.Sequence[ + npt.NDArray[np.float64] | collections.abc.Sequence[float] + ], nside: int, *, ncorr: int | None = None, @@ -298,7 +315,9 @@ def generate_gaussian( def generate_lognormal( - gls: Cls, + gls: collections.abc.Sequence[ + npt.NDArray[np.float64] | collections.abc.Sequence[float] + ], nside: int, shift: float = 1.0, *, diff --git a/glass/shells.py b/glass/shells.py index 2fc2b89e..6edfb1a6 100644 --- a/glass/shells.py +++ b/glass/shells.py @@ -44,7 +44,6 @@ from __future__ import annotations -import collections.abc import typing import warnings @@ -54,11 +53,9 @@ from glass.core.array import ndinterp if typing.TYPE_CHECKING: - from cosmology import Cosmology + import collections.abc -# types -ArrayLike1D = typing.Union[collections.abc.Sequence[float], npt.NDArray[np.float64]] -WeightFunc = typing.Callable[[ArrayLike1D], npt.NDArray[np.float64]] + from cosmology import Cosmology def distance_weight( @@ -140,9 +137,13 @@ class RadialWindow(typing.NamedTuple): def tophat_windows( - zbins: ArrayLike1D, + zbins: collections.abc.Sequence[float] | npt.NDArray[np.float64], dz: float = 1e-3, - weight: WeightFunc | None = None, + weight: typing.Callable[ + [collections.abc.Sequence[float] | npt.NDArray[np.float64]], + npt.NDArray[np.float64], + ] + | None = None, ) -> list[RadialWindow]: """ Tophat window functions from the given redshift bin edges. @@ -183,7 +184,13 @@ def tophat_windows( stacklevel=2, ) - wht: WeightFunc | npt.NDArray[np.float64] + wht: ( + typing.Callable[ + [collections.abc.Sequence[float] | npt.NDArray[np.float64]], + npt.NDArray[np.float64], + ] + | npt.NDArray[np.float64] + ) wht = weight if weight is not None else np.ones_like ws = [] for zmin, zmax in zip(zbins, zbins[1:]): @@ -196,9 +203,13 @@ def tophat_windows( def linear_windows( - zgrid: ArrayLike1D, + zgrid: collections.abc.Sequence[float] | npt.NDArray[np.float64], dz: float = 1e-3, - weight: WeightFunc | None = None, + weight: typing.Callable[ + [collections.abc.Sequence[float] | npt.NDArray[np.float64]], + npt.NDArray[np.float64], + ] + | None = None, ) -> list[RadialWindow]: """ Linear interpolation window functions. @@ -253,9 +264,13 @@ def linear_windows( def cubic_windows( - zgrid: ArrayLike1D, + zgrid: collections.abc.Sequence[float] | npt.NDArray[np.float64], dz: float = 1e-3, - weight: WeightFunc | None = None, + weight: typing.Callable[ + [collections.abc.Sequence[float] | npt.NDArray[np.float64]], + npt.NDArray[np.float64], + ] + | None = None, ) -> list[RadialWindow]: """ Cubic interpolation window functions. @@ -311,8 +326,8 @@ def cubic_windows( def restrict( - z: ArrayLike1D, - f: ArrayLike1D, + z: collections.abc.Sequence[float] | npt.NDArray[np.float64], + f: collections.abc.Sequence[float] | npt.NDArray[np.float64], w: RadialWindow, ) -> tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]]: """ From aff15811cfd0427c733fa07935a77729bbc7a2dd Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Fri, 18 Oct 2024 11:32:57 +0100 Subject: [PATCH 069/143] Remove `collections.abc.Sequence` --- glass/fields.py | 36 +++++++++--------------------------- glass/lensing.py | 6 ++---- glass/shells.py | 30 ++++++++++++++---------------- 3 files changed, 25 insertions(+), 47 deletions(-) diff --git a/glass/fields.py b/glass/fields.py index 46cd943c..5345d018 100644 --- a/glass/fields.py +++ b/glass/fields.py @@ -103,9 +103,7 @@ def iternorm( def cls2cov( - cls: collections.abc.Sequence[ - npt.NDArray[np.float64] | collections.abc.Sequence[float] - ], + cls: list[list[float] | npt.NDArray[np.float64]], nl: int, nf: int, nc: int, @@ -144,14 +142,10 @@ def multalm( def transform_cls( - cls: collections.abc.Sequence[ - npt.NDArray[np.float64] | collections.abc.Sequence[float] - ], + cls: list[list[float] | npt.NDArray[np.float64]], tfm: str | typing.Callable[[npt.NDArray[np.float64]], npt.NDArray[np.float64]], pars: tuple[typing.Any, ...] = (), -) -> collections.abc.Sequence[ - npt.NDArray[np.float64] | collections.abc.Sequence[float] -]: +) -> list[list[float] | npt.NDArray[np.float64]]: """Transform Cls to Gaussian Cls.""" gls = [] for cl in cls: @@ -170,16 +164,12 @@ def transform_cls( def discretized_cls( - cls: collections.abc.Sequence[ - npt.NDArray[np.float64] | collections.abc.Sequence[float] - ], + cls: list[list[float] | npt.NDArray[np.float64]], *, lmax: int | None = None, ncorr: int | None = None, nside: int | None = None, -) -> collections.abc.Sequence[ - npt.NDArray[np.float64] | collections.abc.Sequence[float] -]: +) -> list[list[float] | npt.NDArray[np.float64]]: """ Apply discretisation effects to angular power spectra. @@ -216,21 +206,15 @@ def discretized_cls( def lognormal_gls( - cls: collections.abc.Sequence[ - npt.NDArray[np.float64] | collections.abc.Sequence[float] - ], + cls: list[list[float] | npt.NDArray[np.float64]], shift: float = 1.0, -) -> collections.abc.Sequence[ - npt.NDArray[np.float64] | collections.abc.Sequence[float] -]: +) -> list[list[float] | npt.NDArray[np.float64]]: """Compute Gaussian Cls for a lognormal random field.""" return transform_cls(cls, "lognormal", (shift,)) def generate_gaussian( - gls: collections.abc.Sequence[ - npt.NDArray[np.float64] | collections.abc.Sequence[float] - ], + gls: list[list[float] | npt.NDArray[np.float64]], nside: int, *, ncorr: int | None = None, @@ -315,9 +299,7 @@ def generate_gaussian( def generate_lognormal( - gls: collections.abc.Sequence[ - npt.NDArray[np.float64] | collections.abc.Sequence[float] - ], + gls: list[list[float] | npt.NDArray[np.float64]], nside: int, shift: float = 1.0, *, diff --git a/glass/lensing.py b/glass/lensing.py index a1b22ed2..7781bff5 100644 --- a/glass/lensing.py +++ b/glass/lensing.py @@ -38,8 +38,6 @@ import numpy.typing as npt if typing.TYPE_CHECKING: - import collections.abc - from cosmology import Cosmology from glass.shells import RadialWindow @@ -367,7 +365,7 @@ def wlens(self) -> float: def multi_plane_matrix( - shells: collections.abc.Sequence[RadialWindow], + shells: list[RadialWindow], cosmo: Cosmology, ) -> npt.NDArray[np.float64]: """Compute the matrix of lensing contributions from each shell.""" @@ -381,7 +379,7 @@ def multi_plane_matrix( def multi_plane_weights( weights: npt.NDArray[np.float64], - shells: collections.abc.Sequence[RadialWindow], + shells: list[RadialWindow], cosmo: Cosmology, ) -> npt.NDArray[np.float64]: """ diff --git a/glass/shells.py b/glass/shells.py index 6edfb1a6..29320f8f 100644 --- a/glass/shells.py +++ b/glass/shells.py @@ -53,8 +53,6 @@ from glass.core.array import ndinterp if typing.TYPE_CHECKING: - import collections.abc - from cosmology import Cosmology @@ -137,10 +135,10 @@ class RadialWindow(typing.NamedTuple): def tophat_windows( - zbins: collections.abc.Sequence[float] | npt.NDArray[np.float64], + zbins: list[float] | npt.NDArray[np.float64], dz: float = 1e-3, weight: typing.Callable[ - [collections.abc.Sequence[float] | npt.NDArray[np.float64]], + [list[float] | npt.NDArray[np.float64]], npt.NDArray[np.float64], ] | None = None, @@ -186,7 +184,7 @@ def tophat_windows( wht: ( typing.Callable[ - [collections.abc.Sequence[float] | npt.NDArray[np.float64]], + [list[float] | npt.NDArray[np.float64]], npt.NDArray[np.float64], ] | npt.NDArray[np.float64] @@ -203,10 +201,10 @@ def tophat_windows( def linear_windows( - zgrid: collections.abc.Sequence[float] | npt.NDArray[np.float64], + zgrid: list[float] | npt.NDArray[np.float64], dz: float = 1e-3, weight: typing.Callable[ - [collections.abc.Sequence[float] | npt.NDArray[np.float64]], + [list[float] | npt.NDArray[np.float64]], npt.NDArray[np.float64], ] | None = None, @@ -264,10 +262,10 @@ def linear_windows( def cubic_windows( - zgrid: collections.abc.Sequence[float] | npt.NDArray[np.float64], + zgrid: list[float] | npt.NDArray[np.float64], dz: float = 1e-3, weight: typing.Callable[ - [collections.abc.Sequence[float] | npt.NDArray[np.float64]], + [list[float] | npt.NDArray[np.float64]], npt.NDArray[np.float64], ] | None = None, @@ -326,8 +324,8 @@ def cubic_windows( def restrict( - z: collections.abc.Sequence[float] | npt.NDArray[np.float64], - f: collections.abc.Sequence[float] | npt.NDArray[np.float64], + z: list[float] | npt.NDArray[np.float64], + f: list[float] | npt.NDArray[np.float64], w: RadialWindow, ) -> tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]]: """ @@ -368,7 +366,7 @@ def restrict( def partition( z: npt.NDArray[np.float64], fz: npt.NDArray[np.float64], - shells: collections.abc.Sequence[RadialWindow], + shells: list[RadialWindow], *, method: str = "nnls", ) -> npt.NDArray[np.float64]: @@ -479,7 +477,7 @@ def partition( def partition_lstsq( z: npt.NDArray[np.float64], fz: npt.NDArray[np.float64], - shells: collections.abc.Sequence[RadialWindow], + shells: list[RadialWindow], *, sumtol: float = 0.01, ) -> npt.NDArray[np.float64]: @@ -527,7 +525,7 @@ def partition_lstsq( def partition_nnls( z: npt.NDArray[np.float64], fz: npt.NDArray[np.float64], - shells: collections.abc.Sequence[RadialWindow], + shells: list[RadialWindow], *, sumtol: float = 0.01, ) -> npt.NDArray[np.float64]: @@ -588,7 +586,7 @@ def partition_nnls( def partition_restrict( z: npt.NDArray[np.float64], fz: npt.NDArray[np.float64], - shells: collections.abc.Sequence[RadialWindow], + shells: list[RadialWindow], ) -> npt.NDArray[np.float64]: """Partition by restriction and integration.""" part = np.empty((len(shells),) + np.shape(fz)[:-1]) @@ -639,7 +637,7 @@ def distance_grid( def combine( z: npt.NDArray[np.float64], weights: npt.NDArray[np.float64], - shells: collections.abc.Sequence[RadialWindow], + shells: list[RadialWindow], ) -> int: r""" Evaluate a linear combination of window functions. From e3722a72a5639357a8937d7f35e0fb081d134ff5 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Fri, 18 Oct 2024 11:34:41 +0100 Subject: [PATCH 070/143] `galaxy_shear` --- glass/galaxies.py | 6 +++--- tests/test_galaxies.py | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/glass/galaxies.py b/glass/galaxies.py index adcf6449..409eaa05 100644 --- a/glass/galaxies.py +++ b/glass/galaxies.py @@ -148,9 +148,9 @@ def redshifts_from_nz( def galaxy_shear( # noqa: PLR0913 - lon: npt.NDArray[np.float64], - lat: npt.NDArray[np.float64], - eps: npt.NDArray[np.float64], + lon: list[float] | npt.NDArray[np.float64], + lat: list[float] | npt.NDArray[np.float64], + eps: list[float] | npt.NDArray[np.float64], kappa: npt.NDArray[np.float64], gamma1: npt.NDArray[np.float64], gamma2: npt.NDArray[np.float64], diff --git a/tests/test_galaxies.py b/tests/test_galaxies.py index 4305edc4..40aa8a78 100644 --- a/tests/test_galaxies.py +++ b/tests/test_galaxies.py @@ -113,7 +113,7 @@ def test_galaxy_shear(rng: np.random.Generator) -> None: rng.normal(size=(12,)), ) - shear = galaxy_shear([], [], [], kappa, gamma1, gamma2) # type: ignore[arg-type] + shear = galaxy_shear([], [], [], kappa, gamma1, gamma2) np.testing.assert_equal(shear, []) gal_lon, gal_lat, gal_eps = ( @@ -126,7 +126,7 @@ def test_galaxy_shear(rng: np.random.Generator) -> None: # shape with no reduced shear - shear = galaxy_shear([], [], [], kappa, gamma1, gamma2, reduced_shear=False) # type: ignore[arg-type] + shear = galaxy_shear([], [], [], kappa, gamma1, gamma2, reduced_shear=False) np.testing.assert_equal(shear, []) gal_lon, gal_lat, gal_eps = ( From b70ad8a6c5551b95f05c5f482c17cbbce3e9d0d8 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Fri, 18 Oct 2024 11:37:49 +0100 Subject: [PATCH 071/143] `trapz_product` --- glass/core/array.py | 8 +++++++- glass/points.py | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/glass/core/array.py b/glass/core/array.py index 586fb45c..989e4a66 100644 --- a/glass/core/array.py +++ b/glass/core/array.py @@ -90,7 +90,13 @@ def ndinterp( # noqa: PLR0913 def trapz_product( f: tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]], - *ff: tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]], + *ff: tuple[ + list[float] | npt.NDArray[np.float64], + list[int] + | list[float] + | npt.NDArray[np.float64] + | list[npt.NDArray[np.float64]], + ], axis: int = -1, ) -> npt.NDArray[np.float64]: """Trapezoidal rule for a product of functions.""" diff --git a/glass/points.py b/glass/points.py index 7975339b..a9c89ea3 100644 --- a/glass/points.py +++ b/glass/points.py @@ -83,7 +83,7 @@ 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[arg-type, no-any-return] + return trapz_product((z, bz), (w.za, w.wa)) / norm # type: ignore[no-any-return] def linear_bias( From f9814cee275e6e2a8bc94cd3fb3ef464b617166b Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Fri, 18 Oct 2024 11:48:53 +0100 Subject: [PATCH 072/143] Switch to numpy empty --- tests/test_points.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/test_points.py b/tests/test_points.py index e08a4f17..fdb162b2 100644 --- a/tests/test_points.py +++ b/tests/test_points.py @@ -20,12 +20,12 @@ def catpos( ] ], ) -> tuple[ - list[float] | npt.NDArray[np.float64], - list[float] | npt.NDArray[np.float64], + npt.NDArray[np.float64], + npt.NDArray[np.float64], int | npt.NDArray[np.int_], ]: - lon: list[float] | npt.NDArray[np.float64] = [] - lat: list[float] | npt.NDArray[np.float64] = [] + lon = np.empty(0) + lat = np.empty(0) cnt: int | npt.NDArray[np.int_] = 0 for lo, la, co in pos: lon = np.concatenate([lon, lo]) @@ -45,7 +45,7 @@ def test_positions_from_delta() -> None: lon, lat, cnt = catpos(positions_from_delta(ngal, delta, bias, vis)) assert isinstance(cnt, int) - assert lon.shape == lat.shape == (cnt,) # type: ignore[union-attr] + assert lon.shape == lat.shape == (cnt,) # case: multi-dimensional ngal @@ -95,7 +95,7 @@ def test_uniform_positions() -> None: lon, lat, cnt = catpos(uniform_positions(ngal)) assert isinstance(cnt, int) - assert lon.shape == lat.shape == (cnt,) # type: ignore[union-attr] + assert lon.shape == lat.shape == (cnt,) # case: 1-D array input From 487810b0c65a698fadc92704d3d71fc085d99ccf Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Fri, 18 Oct 2024 12:02:24 +0100 Subject: [PATCH 073/143] Add `pytest_mock` --- tests/test_galaxies.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/test_galaxies.py b/tests/test_galaxies.py index 40aa8a78..68c1d0ed 100644 --- a/tests/test_galaxies.py +++ b/tests/test_galaxies.py @@ -1,11 +1,12 @@ import numpy as np import numpy.typing as npt import pytest +import pytest_mock from glass.galaxies import galaxy_shear, gaussian_phz, redshifts, redshifts_from_nz -def test_redshifts(mocker) -> None: # type: ignore[no-untyped-def] +def test_redshifts(mocker: pytest_mock.MockerFixture) -> None: # create a mock radial window function w = mocker.Mock() w.za = np.linspace(0.0, 1.0, 20) From 1c2296a8802bf214a74cd5ee23c057162b0e2b26 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Fri, 18 Oct 2024 12:05:06 +0100 Subject: [PATCH 074/143] Fix ext path --- glass/ext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glass/ext/__init__.py b/glass/ext/__init__.py index eba224bb..2b55ab0f 100644 --- a/glass/ext/__init__.py +++ b/glass/ext/__init__.py @@ -7,7 +7,7 @@ """ -def _extend_path(path, name) -> list: # type: ignore[no-untyped-def, type-arg] +def _extend_path(path: list[str], name: str) -> list[str]: import os.path from pkgutil import extend_path From 43ad02ce56d2178a8ac57e865ff4c40d816a136a Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Fri, 18 Oct 2024 12:18:57 +0100 Subject: [PATCH 075/143] `assert isinstance` --- tests/test_points.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/test_points.py b/tests/test_points.py index fdb162b2..6e4abaca 100644 --- a/tests/test_points.py +++ b/tests/test_points.py @@ -56,9 +56,10 @@ def test_positions_from_delta() -> None: lon, lat, cnt = catpos(positions_from_delta(ngal, delta, bias, vis)) - assert cnt.shape == (2,) # type: ignore[union-attr] - assert lon.shape == (cnt.sum(),) # type: ignore[union-attr] - assert lat.shape == (cnt.sum(),) # type: ignore[union-attr] + assert isinstance(cnt, np.ndarray) + assert cnt.shape == (2,) + assert lon.shape == (cnt.sum(),) + assert lat.shape == (cnt.sum(),) # case: multi-dimensional delta From 2e73bce6b070a72d24172e7d508bae9555a6eb32 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Fri, 18 Oct 2024 12:20:44 +0100 Subject: [PATCH 076/143] More `assert isinstance` --- tests/test_points.py | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/tests/test_points.py b/tests/test_points.py index 6e4abaca..4c1b5a77 100644 --- a/tests/test_points.py +++ b/tests/test_points.py @@ -70,9 +70,10 @@ def test_positions_from_delta() -> None: lon, lat, cnt = catpos(positions_from_delta(ngal, delta, bias, vis)) - assert cnt.shape == (3, 2) # type: ignore[union-attr] - assert lon.shape == (cnt.sum(),) # type: ignore[union-attr] - assert lat.shape == (cnt.sum(),) # type: ignore[union-attr] + assert isinstance(cnt, np.ndarray) + assert cnt.shape == (3, 2) + assert lon.shape == (cnt.sum(),) + assert lat.shape == (cnt.sum(),) # case: multi-dimensional broadcasting @@ -83,9 +84,10 @@ def test_positions_from_delta() -> None: lon, lat, cnt = catpos(positions_from_delta(ngal, delta, bias, vis)) - assert cnt.shape == (3, 2) # type: ignore[union-attr] - assert lon.shape == (cnt.sum(),) # type: ignore[union-attr] - assert lat.shape == (cnt.sum(),) # type: ignore[union-attr] + assert isinstance(cnt, np.ndarray) + assert cnt.shape == (3, 2) + assert lon.shape == (cnt.sum(),) + assert lat.shape == (cnt.sum(),) def test_uniform_positions() -> None: @@ -104,8 +106,9 @@ def test_uniform_positions() -> None: lon, lat, cnt = catpos(uniform_positions(ngal)) - assert cnt.shape == (3,) # type: ignore[union-attr] - assert lon.shape == lat.shape == (cnt.sum(),) # type: ignore[union-attr] + assert isinstance(cnt, np.ndarray) + assert cnt.shape == (3,) + assert lon.shape == lat.shape == (cnt.sum(),) # case: 2-D array input @@ -113,8 +116,9 @@ def test_uniform_positions() -> None: lon, lat, cnt = catpos(uniform_positions(ngal)) - assert cnt.shape == (3, 2) # type: ignore[union-attr] - assert lon.shape == lat.shape == (cnt.sum(),) # type: ignore[union-attr] + assert isinstance(cnt, np.ndarray) + assert cnt.shape == (3, 2) + assert lon.shape == lat.shape == (cnt.sum(),) def test_position_weights(rng: np.random.Generator) -> None: From f08ab67e96f4b338bebf670d031b23ac5367ef97 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Fri, 18 Oct 2024 14:11:24 +0100 Subject: [PATCH 077/143] `ef` --- tests/test_lensing.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/test_lensing.py b/tests/test_lensing.py index 17573cc9..79922403 100644 --- a/tests/test_lensing.py +++ b/tests/test_lensing.py @@ -1,5 +1,6 @@ import healpix import numpy as np +import numpy.typing as npt import pytest from cosmology import Cosmology @@ -31,7 +32,7 @@ class MockCosmology: def omega_m(self) -> float: return 0.3 - def ef(self, z): # type: ignore[no-untyped-def] + def ef(self, z: npt.NDArray[np.float64]) -> npt.NDArray[np.float64]: return (self.omega_m * (1 + z) ** 3 + 1 - self.omega_m) ** 0.5 def xm(self, z, z2=None): # type: ignore[no-untyped-def] From 41c129b0a27c7759646c61930ebf098700e5ee8c Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Fri, 18 Oct 2024 14:14:26 +0100 Subject: [PATCH 078/143] `xm` --- tests/test_lensing.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/test_lensing.py b/tests/test_lensing.py index 79922403..517c38d9 100644 --- a/tests/test_lensing.py +++ b/tests/test_lensing.py @@ -1,3 +1,7 @@ +from __future__ import annotations + +import typing + import healpix import numpy as np import numpy.typing as npt @@ -13,6 +17,9 @@ ) from glass.shells import RadialWindow +if typing.TYPE_CHECKING: + from cosmology import Cosmology + @pytest.fixture def shells() -> list[RadialWindow]: @@ -35,7 +42,9 @@ def omega_m(self) -> float: def ef(self, z: npt.NDArray[np.float64]) -> npt.NDArray[np.float64]: return (self.omega_m * (1 + z) ** 3 + 1 - self.omega_m) ** 0.5 - def xm(self, z, z2=None): # type: ignore[no-untyped-def] + def xm( + self, z: npt.NDArray[np.float64], z2: npt.NDArray[np.float64] | None = None + ) -> npt.NDArray[np.float64]: if z2 is None: return np.array(z) * 1000 return (np.array(z2) - np.array(z)) * 1000 From 015496ca1cdbfbd03f885a81319a61d27c5e2022 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Fri, 18 Oct 2024 14:20:40 +0100 Subject: [PATCH 079/143] Move `_test_append` into function --- tests/test_fits.py | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/tests/test_fits.py b/tests/test_fits.py index 09dbab22..48fdad87 100644 --- a/tests/test_fits.py +++ b/tests/test_fits.py @@ -9,17 +9,6 @@ # check if fitsio is available for testing HAVE_FITSIO = importlib.util.find_spec("fitsio") is not 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: - fits.write_table(data, names=names, extname=cat_name) - else: - hdu = fits[cat_name] - hdu.write(data, names=names, firstrow=hdu.get_nrows()) - - delta = 0.001 # Number of points in arrays my_max = 1000 # Typically number of galaxies in loop except_int = 750 # Where test exception occurs in loop @@ -33,6 +22,15 @@ def test_basic_write(tmp_path: pathlib.Path) -> None: filename_gfits = "gfits.fits" # what GLASS creates filename_tfits = "tfits.fits" # file created on the fly to test against + def _test_append(fits: fitsio.FITS, data, names) -> None: # type: ignore[no-untyped-def] + """Write routine for FITS test cases.""" + cat_name = "CATALOG" + if cat_name not in fits: + fits.write_table(data, names=names, extname=cat_name) + else: + hdu = fits[cat_name] + hdu.write(data, names=names, firstrow=hdu.get_nrows()) + with ( user.write_catalog(tmp_path / filename_gfits, ext="CATALOG") as out, fitsio.FITS(tmp_path / filename_tfits, "rw", clobber=True) as my_fits, From 1e154e1bdcf87ef2e7206aed687a38d59d4b1e5f Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Fri, 18 Oct 2024 14:24:30 +0100 Subject: [PATCH 080/143] Fix typing of basic write --- tests/test_fits.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/test_fits.py b/tests/test_fits.py index 48fdad87..037e1aa8 100644 --- a/tests/test_fits.py +++ b/tests/test_fits.py @@ -2,6 +2,7 @@ import pathlib import numpy as np +import numpy.typing as npt import pytest from glass import user @@ -22,7 +23,9 @@ def test_basic_write(tmp_path: pathlib.Path) -> None: filename_gfits = "gfits.fits" # what GLASS creates filename_tfits = "tfits.fits" # file created on the fly to test against - def _test_append(fits: fitsio.FITS, data, names) -> None: # type: ignore[no-untyped-def] + def _test_append( + fits: fitsio.FITS, data: list[npt.NDArray[np.float64]], names: list[str] + ) -> None: """Write routine for FITS test cases.""" cat_name = "CATALOG" if cat_name not in fits: From a10fab9d188f133b602f77ffbac91cc13f6494bf Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Fri, 18 Oct 2024 14:37:55 +0100 Subject: [PATCH 081/143] Fix results tuple --- glass/lensing.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/glass/lensing.py b/glass/lensing.py index 7781bff5..6cfcd8e8 100644 --- a/glass/lensing.py +++ b/glass/lensing.py @@ -169,7 +169,7 @@ def from_convergence( # noqa: PLR0913 l = np.arange(lmax + 1) # noqa: E741 # this tuple will be returned - results = () + results: tuple[npt.NDArray[np.float64], ...] = () # convert convergence to potential fl = np.divide(-2, l * (l + 1), where=(l > 0), out=np.zeros(lmax + 1)) @@ -178,7 +178,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,) # type: ignore[assignment] + results += (psi,) # if no spin-weighted maps are requested, stop here if not (deflection or shear): @@ -197,7 +197,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,) # type: ignore[assignment] + results += (alpha,) # if no shear is requested, stop here if not shear: @@ -215,7 +215,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,) # type: ignore[assignment] + results += (gamma,) # all done return results From 994fdf337f6a3fcea3642f5f84de7c5c8af1b542 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Mon, 21 Oct 2024 12:41:18 +0100 Subject: [PATCH 082/143] `uniform_positions` --- glass/points.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/glass/points.py b/glass/points.py index a9c89ea3..28e2d1da 100644 --- a/glass/points.py +++ b/glass/points.py @@ -273,7 +273,7 @@ def positions_from_delta( # noqa: PLR0912, PLR0913, PLR0915 def uniform_positions( - ngal: float | list[float] | list[list[float]], + ngal: float | npt.NDArray[np.int_] | list[float] | list[list[float]], *, rng: np.random.Generator | None = None, ) -> collections.abc.Generator[ @@ -311,29 +311,29 @@ def uniform_positions( rng = np.random.default_rng() # sample number of galaxies - ngal = rng.poisson(np.multiply(ARCMIN2_SPHERE, ngal)) # type: ignore[assignment] + ngal = rng.poisson(np.multiply(ARCMIN2_SPHERE, ngal)) # extra dimensions of the output dims = np.shape(ngal) # make sure ntot is an array even if scalar - ngal = np.broadcast_to(ngal, dims) # type: ignore[assignment] + ngal = np.broadcast_to(ngal, dims) # sample each set of points for k in np.ndindex(dims): # sample uniformly over the sphere - lon = rng.uniform(-180, 180, size=ngal[k]) # type: ignore[call-overload, index] - lat = np.rad2deg(np.arcsin(rng.uniform(-1, 1, size=ngal[k]))) # type: ignore[call-overload, index] + lon = rng.uniform(-180, 180, size=ngal[k]) + lat = np.rad2deg(np.arcsin(rng.uniform(-1, 1, size=ngal[k]))) # report count count: int | npt.NDArray[np.int_] if dims: count = np.zeros(dims, dtype=int) - count[k] = ngal[k] # type: ignore[call-overload, index] + count[k] = ngal[k] else: - count = int(ngal[k]) # type: ignore[call-overload, index] + count = int(ngal[k]) - yield lon, lat, count # type: ignore[misc] + yield lon, lat, count def position_weights( From 85961b8463b0f77def2d4dbddb335724711ae190 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Mon, 21 Oct 2024 12:50:23 +0100 Subject: [PATCH 083/143] Fix `phz` typing --- glass/galaxies.py | 2 +- tests/test_galaxies.py | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/glass/galaxies.py b/glass/galaxies.py index 409eaa05..815978cf 100644 --- a/glass/galaxies.py +++ b/glass/galaxies.py @@ -221,7 +221,7 @@ def gaussian_phz( lower: float | npt.NDArray[np.float64] | None = None, upper: float | npt.NDArray[np.float64] | None = None, rng: np.random.Generator | None = None, -) -> npt.NDArray[np.float64]: +) -> float | npt.NDArray[np.float64]: r""" Photometric redshifts assuming a Gaussian error. diff --git a/tests/test_galaxies.py b/tests/test_galaxies.py index 68c1d0ed..0ae76ad4 100644 --- a/tests/test_galaxies.py +++ b/tests/test_galaxies.py @@ -172,6 +172,7 @@ def test_gaussian_phz(rng: np.random.Generator) -> None: phz = gaussian_phz(z, sigma_0) + assert isinstance(phz, np.ndarray) assert phz.shape == (100,) assert np.all(phz >= 0) @@ -182,6 +183,7 @@ def test_gaussian_phz(rng: np.random.Generator) -> None: phz = gaussian_phz(z, sigma_0, lower=0.5, upper=1.5) + assert isinstance(phz, np.ndarray) assert phz.shape == (100,) assert np.all(phz >= 0.5) assert np.all(phz <= 1.5) @@ -205,6 +207,7 @@ def test_gaussian_phz(rng: np.random.Generator) -> None: phz = gaussian_phz(z, sigma_0) + assert isinstance(phz, np.ndarray) assert phz.shape == (10,) np.testing.assert_array_equal(z, phz) @@ -215,6 +218,7 @@ def test_gaussian_phz(rng: np.random.Generator) -> None: phz = gaussian_phz(z, sigma_0) + assert isinstance(phz, np.ndarray) assert phz.shape == (10,) np.testing.assert_array_equal(z, phz) @@ -225,15 +229,16 @@ def test_gaussian_phz(rng: np.random.Generator) -> None: phz = gaussian_phz(z, sigma_0) + assert isinstance(phz, np.ndarray) assert phz.shape == (11, 10) np.testing.assert_array_equal(np.broadcast_to(z, (11, 10)), phz) # test resampling phz = gaussian_phz(np.array(0.0), np.array(1.0), lower=np.array([0])) - assert isinstance(phz, float) # type: ignore[unreachable] + assert isinstance(phz, float) - phz = gaussian_phz(np.array(0.0), np.array(1.0), upper=np.array([1])) # type: ignore[unreachable] + phz = gaussian_phz(np.array(0.0), np.array(1.0), upper=np.array([1])) assert isinstance(phz, float) # test error From 6e7efbe506687b664d401d630e5431ba9408d713 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Mon, 21 Oct 2024 12:59:31 +0100 Subject: [PATCH 084/143] Create conditional `alpha` function --- tests/test_lensing.py | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/tests/test_lensing.py b/tests/test_lensing.py index 517c38d9..fcf0b482 100644 --- a/tests/test_lensing.py +++ b/tests/test_lensing.py @@ -57,30 +57,23 @@ def test_deflect_nsew(usecomplex: bool) -> None: # noqa: FBT001 d = 5.0 r = np.radians(d) - if usecomplex: - - def alpha(re: float, im: float) -> complex: - return re + 1j * im - - else: - - def alpha(re: float, im: float) -> list[float]: # type: ignore[misc] - return [re, im] + def alpha(re: float, im: float, *, usecomplex: bool) -> complex | list[float]: + return re + 1j * im if usecomplex else [re, im] # north - lon, lat = deflect(0.0, 0.0, alpha(r, 0)) + lon, lat = deflect(0.0, 0.0, alpha(r, 0, usecomplex=usecomplex)) np.testing.assert_allclose([lon, lat], [0.0, d], atol=1e-15) # south - lon, lat = deflect(0.0, 0.0, alpha(-r, 0)) + lon, lat = deflect(0.0, 0.0, alpha(-r, 0, usecomplex=usecomplex)) np.testing.assert_allclose([lon, lat], [0.0, -d], atol=1e-15) # east - lon, lat = deflect(0.0, 0.0, alpha(0, r)) + lon, lat = deflect(0.0, 0.0, alpha(0, r, usecomplex=usecomplex)) np.testing.assert_allclose([lon, lat], [-d, 0.0], atol=1e-15) # west - lon, lat = deflect(0.0, 0.0, alpha(0, -r)) + lon, lat = deflect(0.0, 0.0, alpha(0, -r, usecomplex=usecomplex)) np.testing.assert_allclose([lon, lat], [d, 0.0], atol=1e-15) From 48cdb5396a2f41b0050a86ebbb5277bdf03140ca Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Mon, 21 Oct 2024 16:11:04 +0100 Subject: [PATCH 085/143] Move `attr-defined` ignore nearer definition --- glass/core/array.py | 6 +++- glass/lensing.py | 9 +++++- glass/observations.py | 12 ++++++-- glass/points.py | 5 +++- glass/shells.py | 64 +++++++++++++++++++++++++++++++++++----- tests/core/test_array.py | 2 +- tests/test_shells.py | 8 ++++- 7 files changed, 91 insertions(+), 15 deletions(-) diff --git a/glass/core/array.py b/glass/core/array.py index 989e4a66..dcf6e259 100644 --- a/glass/core/array.py +++ b/glass/core/array.py @@ -109,7 +109,11 @@ def trapz_product( y = np.interp(x, *f) for f_ in ff: y *= np.interp(x, *f_) - return np.trapz(y, x, axis=axis) # type: ignore[attr-defined, no-any-return] + return np.trapz( # type: ignore[attr-defined, no-any-return] + y, + x, + axis=axis, + ) def cumtrapz( diff --git a/glass/lensing.py b/glass/lensing.py index 6cfcd8e8..cbc4e8bb 100644 --- a/glass/lensing.py +++ b/glass/lensing.py @@ -291,7 +291,14 @@ def add_window(self, delta: npt.NDArray[np.float64], 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( # type: ignore[attr-defined] + w.wa, + w.za, + ) / np.interp( + zsrc, # type: ignore[arg-type] + w.za, + w.wa, + ) self.add_plane(delta, zsrc, lens_weight) diff --git a/glass/observations.py b/glass/observations.py index 090efa43..3d4823b5 100644 --- a/glass/observations.py +++ b/glass/observations.py @@ -114,7 +114,11 @@ 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] # type: ignore[attr-defined] + nz /= np.trapz( # type: ignore[attr-defined] + nz, + z, + axis=-1, + )[..., np.newaxis] if norm is not None: nz *= norm @@ -173,7 +177,11 @@ 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] # type: ignore[attr-defined] + pz /= np.trapz( # type: ignore[attr-defined] + pz, + z, + axis=-1, + )[..., np.newaxis] if norm is not None: pz *= norm diff --git a/glass/points.py b/glass/points.py index 28e2d1da..51f4dba9 100644 --- a/glass/points.py +++ b/glass/points.py @@ -82,7 +82,10 @@ def effective_bias( \;. """ - norm = np.trapz(w.wa, w.za) # type: ignore[attr-defined] + norm = np.trapz( # type: ignore[attr-defined] + w.wa, + w.za, + ) return trapz_product((z, bz), (w.za, w.wa)) / norm # type: ignore[no-any-return] diff --git a/glass/shells.py b/glass/shells.py index 29320f8f..0530ad99 100644 --- a/glass/shells.py +++ b/glass/shells.py @@ -195,7 +195,13 @@ 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) # type: ignore[attr-defined] + zeff = np.trapz( # type: ignore[attr-defined] + w * z, + z, + ) / np.trapz( # type: ignore[attr-defined] + w, + z, + ) ws.append(RadialWindow(z, w, zeff)) return ws @@ -500,7 +506,11 @@ def partition_lstsq( a: list[npt.NDArray[np.float64]] | npt.NDArray[np.float64] = [ 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 /= np.trapz( # type: ignore[attr-defined] + a, + zp, + axis=-1, + )[..., None] a = a * dz # create the target vector of distribution values @@ -510,7 +520,20 @@ 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) # type: ignore[attr-defined] + b = np.concatenate( + [ + b, + mult + * np.reshape( + np.trapz( # type: ignore[attr-defined] + fz, + z, + ), + (*dims, 1), + ), + ], + axis=-1, + ) # now a is a matrix of shape (len(shells), len(zp) + 1) # and b is a matrix of shape (*dims, len(zp) + 1) @@ -554,7 +577,11 @@ 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] # type: ignore[attr-defined] + a /= np.trapz( # type: ignore[attr-defined] + a, + zp, + axis=-1, + )[..., None] a = a * dz # create the target vector of distribution values @@ -564,14 +591,27 @@ def partition_nnls( # append a constraint for the integral mult = 1 / sumtol 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] + b = np.concatenate( + [ + b, + mult + * np.reshape( + np.trapz( # type: ignore[attr-defined] + fz, + z, + ), + (*dims, 1), + ), + ], + axis=-1, + ) # 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) # type: ignore[attr-defined] + q, r = np.linalg.qr(a.T) y = np.einsum("ji,...j", q, b) # for each dim, find non-negative weights x such that y == r @ x @@ -592,7 +632,11 @@ 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) # type: ignore[attr-defined] + part[i] = np.trapz( # type: ignore[attr-defined] + fr, + zr, + axis=-1, + ) return part @@ -673,7 +717,11 @@ def combine( * np.interp( z, shell.za, - shell.wa / np.trapz(shell.wa, shell.za), # type: ignore[attr-defined] + shell.wa + / np.trapz( # type: ignore[attr-defined] + shell.wa, + shell.za, + ), left=0.0, right=0.0, ) diff --git a/tests/core/test_array.py b/tests/core/test_array.py index b2acdba6..764bd9e7 100644 --- a/tests/core/test_array.py +++ b/tests/core/test_array.py @@ -52,7 +52,7 @@ def test_broadcast_leading_axes() -> None: 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) # type: ignore[attr-defined] + assert a.shape == (3, 4) assert b.shape == (3, 4, 10) assert c.shape == (3, 4, 5, 6) diff --git a/tests/test_shells.py b/tests/test_shells.py index cc0ec4b3..5f7381f5 100644 --- a/tests/test_shells.py +++ b/tests/test_shells.py @@ -69,4 +69,10 @@ def test_partition(method: str) -> None: assert part.shape == (len(shells), 3, 2) - np.testing.assert_allclose(part.sum(axis=0), np.trapz(fz, z)) # type: ignore[attr-defined] + np.testing.assert_allclose( + part.sum(axis=0), + np.trapz( # type: ignore[attr-defined] + fz, + z, + ), + ) From b730b322178dccfc49da6bd3be4b9ba91a663718 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Mon, 21 Oct 2024 16:24:51 +0100 Subject: [PATCH 086/143] Sort `attr-defined` --- glass/core/array.py | 18 +++++++++--------- glass/shells.py | 25 ++++++++++++++++++------- tests/core/test_array.py | 12 +++++++++++- 3 files changed, 38 insertions(+), 17 deletions(-) diff --git a/glass/core/array.py b/glass/core/array.py index dcf6e259..335c6811 100644 --- a/glass/core/array.py +++ b/glass/core/array.py @@ -19,13 +19,13 @@ def broadcast_first( def broadcast_leading_axes( *args: tuple[ - int - | float - | npt.NDArray[np.float64] - | list[int] + float + | int | list[float] + | list[int] + | list[list[int]] | list[npt.NDArray[np.float64]] - | list[list[int]], + | npt.NDArray[np.float64], int, ], ) -> tuple[tuple[int, ...], ...]: @@ -92,10 +92,10 @@ def trapz_product( f: tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]], *ff: tuple[ list[float] | npt.NDArray[np.float64], - list[int] - | list[float] - | npt.NDArray[np.float64] - | list[npt.NDArray[np.float64]], + list[float] + | list[int] + | list[npt.NDArray[np.float64]] + | npt.NDArray[np.float64], ], axis: int = -1, ) -> npt.NDArray[np.float64]: diff --git a/glass/shells.py b/glass/shells.py index 0530ad99..75ab9987 100644 --- a/glass/shells.py +++ b/glass/shells.py @@ -126,10 +126,10 @@ class RadialWindow(typing.NamedTuple): za: list[float] | npt.NDArray[np.float64] wa: ( - list[int] - | list[float] - | npt.NDArray[np.float64] + list[float] + | list[int] | list[npt.NDArray[np.float64]] + | npt.NDArray[np.float64] ) zeff: float | None @@ -183,11 +183,11 @@ def tophat_windows( ) wht: ( - typing.Callable[ + npt.NDArray[np.float64] + | typing.Callable[ [list[float] | npt.NDArray[np.float64]], npt.NDArray[np.float64], ] - | npt.NDArray[np.float64] ) wht = weight if weight is not None else np.ones_like ws = [] @@ -576,7 +576,18 @@ 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.array( + [ + np.interp( + zp, + za, + wa, + left=0.0, + right=0.0, + ) + for za, wa, _ in shells + ] + ) a /= np.trapz( # type: ignore[attr-defined] a, zp, @@ -590,7 +601,7 @@ def partition_nnls( # append a constraint for the integral mult = 1 / sumtol - a = np.concatenate([a, mult * np.ones((len(shells), 1))], axis=-1) # type: ignore[assignment] + a = np.concatenate([a, mult * np.ones((len(shells), 1))], axis=-1) b = np.concatenate( [ b, diff --git a/tests/core/test_array.py b/tests/core/test_array.py index 764bd9e7..110f72ec 100644 --- a/tests/core/test_array.py +++ b/tests/core/test_array.py @@ -1,6 +1,7 @@ import importlib.util import numpy as np +import numpy.typing as npt import pytest from glass.core.array import ( @@ -45,13 +46,22 @@ def test_broadcast_first() -> None: def test_broadcast_leading_axes() -> None: - a = 0 + a: ( + float + | int + | list[float] + | list[int] + | list[list[int]] + | list[npt.NDArray[np.float64]] + | npt.NDArray[np.float64] + ) = 0 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] assert dims == (3, 4) + assert isinstance(a, np.ndarray) assert a.shape == (3, 4) assert b.shape == (3, 4, 10) assert c.shape == (3, 4, 5, 6) From 3c097ca4133e3c38ede9fe7f2a546f2d1f6aa604 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Mon, 21 Oct 2024 17:27:48 +0100 Subject: [PATCH 087/143] Disable `warn_return_any` --- glass/core/array.py | 2 +- glass/galaxies.py | 2 +- glass/lensing.py | 4 ++-- glass/observations.py | 8 ++++---- glass/points.py | 2 +- glass/shapes.py | 4 ++-- glass/shells.py | 10 +++++----- pyproject.toml | 1 + 8 files changed, 17 insertions(+), 16 deletions(-) diff --git a/glass/core/array.py b/glass/core/array.py index 335c6811..835192dd 100644 --- a/glass/core/array.py +++ b/glass/core/array.py @@ -109,7 +109,7 @@ def trapz_product( y = np.interp(x, *f) for f_ in ff: y *= np.interp(x, *f_) - return np.trapz( # type: ignore[attr-defined, no-any-return] + return np.trapz( # type: ignore[attr-defined] y, x, axis=axis, diff --git a/glass/galaxies.py b/glass/galaxies.py index 815978cf..fff0969b 100644 --- a/glass/galaxies.py +++ b/glass/galaxies.py @@ -395,4 +395,4 @@ def kappa_ia_nla( # noqa: PLR0913 prefactor * inverse_linear_growth * redshift_dependence * luminosity_dependence ) - return delta * f_nla # type: ignore[no-any-return] + return delta * f_nla diff --git a/glass/lensing.py b/glass/lensing.py index cbc4e8bb..025bff13 100644 --- a/glass/lensing.py +++ b/glass/lensing.py @@ -262,7 +262,7 @@ def shear_from_convergence( hp.almxfl(alm, fl, inplace=True) # transform to shear maps - return hp.alm2map_spin([alm, blm], nside, 2, lmax) # type: ignore[no-any-return] + return hp.alm2map_spin([alm, blm], nside, 2, lmax) class MultiPlaneConvergence: @@ -421,7 +421,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) # type: ignore[no-any-return] + return np.matmul(mat.T, weights) def deflect( diff --git a/glass/observations.py b/glass/observations.py index 3d4823b5..77a489c1 100644 --- a/glass/observations.py +++ b/glass/observations.py @@ -77,7 +77,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) # type: ignore[no-any-return] + return hp.Rotator(coord="CE").rotate_map_pixel(m) def gaussian_nz( @@ -123,7 +123,7 @@ def gaussian_nz( if norm is not None: nz *= norm - return nz # type: ignore[no-any-return] + return nz def smail_nz( @@ -186,7 +186,7 @@ def smail_nz( if norm is not None: pz *= norm - return pz # type: ignore[no-any-return] + return pz def fixed_zbins( @@ -323,4 +323,4 @@ def tomo_nz_gausserr( binned_nz /= 1 + erf(z / sz) binned_nz *= nz - return binned_nz # type: ignore[no-any-return] + return binned_nz diff --git a/glass/points.py b/glass/points.py index 51f4dba9..567530c3 100644 --- a/glass/points.py +++ b/glass/points.py @@ -86,7 +86,7 @@ def effective_bias( w.wa, w.za, ) - 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 def linear_bias( diff --git a/glass/shapes.py b/glass/shapes.py index b377ab91..b5da39c5 100644 --- a/glass/shapes.py +++ b/glass/shapes.py @@ -91,7 +91,7 @@ def triaxial_axis_ratio( C = 1 + z2m1 * cos2_phi # noqa: N806 # eq. (12) - return np.sqrt( # type: ignore[no-any-return] + return np.sqrt( (A + C - np.sqrt((A - C) ** 2 + B2)) / (A + C + np.sqrt((A - C) ** 2 + B2)), ) @@ -174,7 +174,7 @@ def ellipticity_ryden04( # noqa: PLR0913 e *= (1 - q) / (1 + q) # return the ellipticity - return e # type: ignore[no-any-return] + return e def ellipticity_gaussian( diff --git a/glass/shells.py b/glass/shells.py index 75ab9987..fb42ab70 100644 --- a/glass/shells.py +++ b/glass/shells.py @@ -61,7 +61,7 @@ def distance_weight( cosmo: Cosmology, ) -> npt.NDArray[np.float64]: """Uniform weight in comoving distance.""" - return 1 / cosmo.ef(z) # type: ignore[no-any-return] + return 1 / cosmo.ef(z) def volume_weight( @@ -69,7 +69,7 @@ def volume_weight( cosmo: Cosmology, ) -> npt.NDArray[np.float64]: """Uniform weight in comoving volume.""" - return cosmo.xm(z) ** 2 / cosmo.ef(z) # type: ignore[no-any-return] + return cosmo.xm(z) ** 2 / cosmo.ef(z) def density_weight( @@ -77,7 +77,7 @@ def density_weight( cosmo: Cosmology, ) -> npt.NDArray[np.float64]: """Uniform weight in matter density.""" - return cosmo.rho_m_z(z) * cosmo.xm(z) ** 2 / cosmo.ef(z) # type: ignore[no-any-return] + return cosmo.rho_m_z(z) * cosmo.xm(z) ** 2 / cosmo.ef(z) class RadialWindow(typing.NamedTuple): @@ -477,7 +477,7 @@ def partition( except KeyError: msg = f"invalid method: {method}" raise ValueError(msg) from None - return partition_method(z, fz, shells) # type: ignore[no-any-return] + return partition_method(z, fz, shells) def partition_lstsq( @@ -686,7 +686,7 @@ def distance_grid( else: msg = 'exactly one of "dx" or "num" must be given' raise ValueError(msg) - return cosmo.dc_inv(x) # type: ignore[no-any-return] + return cosmo.dc_inv(x) def combine( diff --git a/pyproject.toml b/pyproject.toml index 08b2f0d2..ad2c4451 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -104,6 +104,7 @@ plugins = [ "numpy.typing.mypy_plugin", ] strict = true +warn_return_any = false warn_unreachable = true [tool.pytest.ini_options] From aa92c4d5e9060c24b59eea7b31fd066612e85386 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Tue, 22 Oct 2024 16:25:28 +0100 Subject: [PATCH 088/143] Fix `unreachable` code --- glass/fields.py | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/glass/fields.py b/glass/fields.py index 5345d018..e56fbfba 100644 --- a/glass/fields.py +++ b/glass/fields.py @@ -114,15 +114,12 @@ def cls2cov( for j in range(nf): begin, end = end, end + j + 1 for i, cl in enumerate(cls[begin:end][: nc + 1]): - if cl is None: - 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) - cov[:n, i] = cl - cov[n:, i] = 0 + if i == 0 and np.any(np.less(cl, 0)): + msg = "negative values in cl" + raise ValueError(msg) + n = len(cl) + cov[:n, i] = cl + cov[n:, i] = 0 cov /= 2 yield cov From 1c77c15b84b2eb060c707b89343c4e0c6d0f2f94 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Tue, 22 Oct 2024 16:53:38 +0100 Subject: [PATCH 089/143] List comprehension fixes assignment mypy --- .gitignore | 1 + glass/fields.py | 9 +++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 93b4e32e..856bbb0e 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ dist .env .coverage* coverage* +.ipynb_checkpoints diff --git a/glass/fields.py b/glass/fields.py index e56fbfba..7e1789db 100644 --- a/glass/fields.py +++ b/glass/fields.py @@ -414,10 +414,11 @@ def effective_cls( # get the iterator over leading weight axes # auto-spectra do not repeat identical computations - if weights2 is weights1: - pairs = combinations_with_replacement(np.ndindex(shape1[1:]), 2) - else: - pairs = product(np.ndindex(shape1[1:]), np.ndindex(shape2[1:])) # type: ignore[assignment] + pairs = ( + combinations_with_replacement(np.ndindex(shape1[1:]), 2) + if weights2 is weights1 + else product(np.ndindex(shape1[1:]), np.ndindex(shape2[1:])) + ) # create the output array: axes for all input axes plus lmax+1 out = np.empty(shape1[1:] + shape2[1:] + (lmax + 1,)) From 426db7b299a3229881c5c020873f1e4b1afaa4d4 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Tue, 22 Oct 2024 16:55:54 +0100 Subject: [PATCH 090/143] Fix notebook --- glass/fields.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glass/fields.py b/glass/fields.py index 7e1789db..c6692707 100644 --- a/glass/fields.py +++ b/glass/fields.py @@ -192,7 +192,7 @@ def discretized_cls( gls = [] for cl in cls: - if cl and len(cl) > 0: + if cl is not None and len(cl) > 0: # type: ignore[redundant-expr] if lmax is not None: cl = cl[: lmax + 1] # noqa: PLW2901 if nside is not None: From 8971dadc2ba821f1a50e78c9beef31f6380b9f07 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Tue, 22 Oct 2024 17:56:53 +0100 Subject: [PATCH 091/143] Look at `broadcast_leading_axes` --- glass/core/array.py | 12 +++--------- glass/galaxies.py | 15 +++++++++++---- glass/points.py | 6 +++--- tests/core/test_array.py | 28 +++++++++++----------------- 4 files changed, 28 insertions(+), 33 deletions(-) diff --git a/glass/core/array.py b/glass/core/array.py index 835192dd..21649566 100644 --- a/glass/core/array.py +++ b/glass/core/array.py @@ -19,16 +19,10 @@ def broadcast_first( def broadcast_leading_axes( *args: tuple[ - float - | int - | list[float] - | list[int] - | list[list[int]] - | list[npt.NDArray[np.float64]] - | npt.NDArray[np.float64], + int | npt.NDArray[np.int_] | npt.NDArray[np.float64], int, ], -) -> tuple[tuple[int, ...], ...]: +) -> tuple[tuple[int, int], tuple[npt.NDArray[np.int_], ...]]: """ Broadcast all but the last N axes. @@ -62,7 +56,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) # type: ignore[arg-type] + return (dims, *arrs) # type: ignore[return-value] def ndinterp( # noqa: PLR0913 diff --git a/glass/galaxies.py b/glass/galaxies.py index fff0969b..7b29a358 100644 --- a/glass/galaxies.py +++ b/glass/galaxies.py @@ -67,12 +67,19 @@ def redshifts( def redshifts_from_nz( - count: int | list[int] | list[list[int]], - z: list[float] | npt.NDArray[np.float64], + count: float + | list[float] + | list[int] + | list[list[int]] + | list[npt.NDArray[np.float64]] + | npt.NDArray[np.float64] + | npt.NDArray[np.int_], + z: list[float] | npt.NDArray[np.float64] | npt.NDArray[np.int_], nz: list[int] | list[float] | npt.NDArray[np.float64] - | list[npt.NDArray[np.float64]], + | list[npt.NDArray[np.float64]] + | npt.NDArray[np.int_], *, rng: np.random.Generator | None = None, warn: bool = True, @@ -120,7 +127,7 @@ 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)) # type: ignore[assignment] + dims, count, z, nz = broadcast_leading_axes((count, 0), (z, 1), (nz, 1)) # type: ignore[arg-type, misc] # list of results for all dimensions redshifts = np.empty(count.sum()) # type: ignore[union-attr] diff --git a/glass/points.py b/glass/points.py index 567530c3..3c25a2e3 100644 --- a/glass/points.py +++ b/glass/points.py @@ -197,11 +197,11 @@ 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) # type: ignore[assignment] + dims, ngal, delta, *rest = broadcast_leading_axes(*inputs) # type: ignore[arg-type, misc] if bias is not None: - bias, *rest = rest # type: ignore[assignment] + bias, *rest = rest if vis is not None: - vis, *rest = rest # type: ignore[assignment] + vis, *rest = rest # iterate the leading dimensions for k in np.ndindex(dims): diff --git a/tests/core/test_array.py b/tests/core/test_array.py index 110f72ec..fcaad6ab 100644 --- a/tests/core/test_array.py +++ b/tests/core/test_array.py @@ -46,25 +46,19 @@ def test_broadcast_first() -> None: def test_broadcast_leading_axes() -> None: - a: ( - float - | int - | list[float] - | list[int] - | list[list[int]] - | list[npt.NDArray[np.float64]] - | npt.NDArray[np.float64] - ) = 0 - 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] + a_in = 0 + b_in = np.zeros((4, 10)) + c_in = np.zeros((3, 1, 5, 6)) + + a_out: npt.NDArray[np.int_] + b_out: npt.NDArray[np.int_] + c_out: npt.NDArray[np.int_] + dims, a_out, b_out, c_out = broadcast_leading_axes((a_in, 0), (b_in, 1), (c_in, 2)) # type: ignore[misc] assert dims == (3, 4) - assert isinstance(a, np.ndarray) - assert a.shape == (3, 4) - assert b.shape == (3, 4, 10) - assert c.shape == (3, 4, 5, 6) + assert a_out.shape == (3, 4) + assert b_out.shape == (3, 4, 10) + assert c_out.shape == (3, 4, 5, 6) def test_ndinterp() -> None: From ddfe641dbc1f06fb30a18c64c0579363495767a0 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Wed, 23 Oct 2024 09:07:24 +0100 Subject: [PATCH 092/143] Simplify `redshifts_from_nz` --- glass/core/array.py | 2 +- glass/galaxies.py | 28 +++++++++------------------ glass/shells.py | 9 ++------- tests/core/test_array.py | 2 +- tests/test_galaxies.py | 42 +++++++++++++++++++++++++--------------- tests/test_lensing.py | 10 +++++----- tests/test_shells.py | 4 +++- 7 files changed, 47 insertions(+), 50 deletions(-) diff --git a/glass/core/array.py b/glass/core/array.py index 21649566..3039e1c3 100644 --- a/glass/core/array.py +++ b/glass/core/array.py @@ -19,7 +19,7 @@ def broadcast_first( def broadcast_leading_axes( *args: tuple[ - int | npt.NDArray[np.int_] | npt.NDArray[np.float64], + int | npt.NDArray[np.int_], int, ], ) -> tuple[tuple[int, int], tuple[npt.NDArray[np.int_], ...]]: diff --git a/glass/galaxies.py b/glass/galaxies.py index 7b29a358..757cfb04 100644 --- a/glass/galaxies.py +++ b/glass/galaxies.py @@ -39,7 +39,7 @@ def redshifts( - n: int | list[int] | list[list[int]], + n: int | npt.NDArray[np.int_], w: RadialWindow, *, rng: np.random.Generator | None = None, @@ -67,19 +67,9 @@ def redshifts( def redshifts_from_nz( - count: float - | list[float] - | list[int] - | list[list[int]] - | list[npt.NDArray[np.float64]] - | npt.NDArray[np.float64] - | npt.NDArray[np.int_], - z: list[float] | npt.NDArray[np.float64] | npt.NDArray[np.int_], - nz: list[int] - | list[float] - | npt.NDArray[np.float64] - | list[npt.NDArray[np.float64]] - | npt.NDArray[np.int_], + count: int | npt.NDArray[np.int_], + z: npt.NDArray[np.float64], + nz: npt.NDArray[np.float64], *, rng: np.random.Generator | None = None, warn: bool = True, @@ -138,16 +128,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[call-overload] + cdf = cumtrapz(nz[k], z[k], dtype=float) cdf /= cdf[-1] # sample redshifts and store result - redshifts[total : total + count[k]] = np.interp( # type: ignore[call-overload, index] - rng.uniform(0, 1, size=count[k]), # type: ignore[call-overload, index] + 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[call-overload] + z[k], ) - total += count[k] # type: ignore[call-overload, index] + total += count[k] # type: ignore[index] assert total == redshifts.size # noqa: S101 diff --git a/glass/shells.py b/glass/shells.py index fb42ab70..f8a2f7cf 100644 --- a/glass/shells.py +++ b/glass/shells.py @@ -124,13 +124,8 @@ class RadialWindow(typing.NamedTuple): """ - za: list[float] | npt.NDArray[np.float64] - wa: ( - list[float] - | list[int] - | list[npt.NDArray[np.float64]] - | npt.NDArray[np.float64] - ) + za: npt.NDArray[np.float64] + wa: npt.NDArray[np.float64] zeff: float | None diff --git a/tests/core/test_array.py b/tests/core/test_array.py index fcaad6ab..b5ce2325 100644 --- a/tests/core/test_array.py +++ b/tests/core/test_array.py @@ -53,7 +53,7 @@ def test_broadcast_leading_axes() -> None: a_out: npt.NDArray[np.int_] b_out: npt.NDArray[np.int_] c_out: npt.NDArray[np.int_] - dims, a_out, b_out, c_out = broadcast_leading_axes((a_in, 0), (b_in, 1), (c_in, 2)) # type: ignore[misc] + dims, a_out, b_out, c_out = broadcast_leading_axes((a_in, 0), (b_in, 1), (c_in, 2)) # type: ignore[arg-type, misc] assert dims == (3, 4) assert a_out.shape == (3, 4) diff --git a/tests/test_galaxies.py b/tests/test_galaxies.py index 0ae76ad4..4935698d 100644 --- a/tests/test_galaxies.py +++ b/tests/test_galaxies.py @@ -19,31 +19,39 @@ def test_redshifts(mocker: pytest_mock.MockerFixture) -> None: assert z.max() <= 1.0 # sample redshifts (array) - z = redshifts([[1, 2], [3, 4]], w) + z = redshifts(np.array([[1, 2], [3, 4]]), w) assert z.shape == (10,) def test_redshifts_from_nz(rng: np.random.Generator) -> 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, np.array([0, 1, 2, 3, 4]), np.array([1, 0, 0, 0, 0]), warn=False + ) 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, np.array([0, 1, 2, 3, 4]), np.array([0, 0, 1, 0, 0]), warn=False + ) 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, np.array([0, 1, 2, 3, 4]), np.array([0, 0, 0, 0, 1]), warn=False + ) 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, np.array([0, 1, 2, 3, 4]), np.array([0, 0, 1, 1, 1]), warn=False + ) assert not np.any(redshifts <= 1) # test with rng redshifts = redshifts_from_nz( 10, - [0, 1, 2, 3, 4], - [0, 0, 1, 1, 1], + np.array([0, 1, 2, 3, 4]), + np.array([0, 0, 1, 1, 1]), warn=False, rng=rng, ) @@ -53,9 +61,9 @@ def test_redshifts_from_nz(rng: np.random.Generator) -> None: # case: no extra dimensions - count: int | list[int] | list[list[int]] = 10 + count: int | npt.NDArray[np.int_] = 10 z = np.linspace(0, 1, 100) - nz: npt.NDArray[np.float64] | list[npt.NDArray[np.float64]] = z * (1 - z) + nz = z * (1 - z) redshifts = redshifts_from_nz(count, z, nz, warn=False) @@ -64,7 +72,7 @@ def test_redshifts_from_nz(rng: np.random.Generator) -> None: # case: extra dimensions from count - count = [10, 20, 30] + count = np.array([10, 20, 30]) z = np.linspace(0, 1, 100) nz = z * (1 - z) @@ -76,7 +84,7 @@ def test_redshifts_from_nz(rng: np.random.Generator) -> None: count = 10 z = np.linspace(0, 1, 100) - nz = [z * (1 - z), (z - 0.5) ** 2] + nz = np.array([z * (1 - z), (z - 0.5) ** 2]) redshifts = redshifts_from_nz(count, z, nz, warn=False) @@ -84,9 +92,9 @@ def test_redshifts_from_nz(rng: np.random.Generator) -> None: # case: extra dimensions from count and nz - count = [[10], [20], [30]] + count = np.array([[10], [20], [30]]) z = np.linspace(0, 1, 100) - nz = [z * (1 - z), (z - 0.5) ** 2] + nz = np.array([z * (1 - z), (z - 0.5) ** 2]) redshifts = redshifts_from_nz(count, z, nz, warn=False) @@ -94,15 +102,17 @@ def test_redshifts_from_nz(rng: np.random.Generator) -> None: # case: incompatible input shapes - count = [10, 20, 30] + count = np.array([10, 20, 30]) z = np.linspace(0, 1, 100) - nz = [z * (1 - z), (z - 0.5) ** 2] + nz = np.array([z * (1 - z), (z - 0.5) ** 2]) with pytest.raises(ValueError, match="shape mismatch"): 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, np.array([0, 1, 2, 3, 4]), np.array([1, 0, 0, 0, 0]) + ) def test_galaxy_shear(rng: np.random.Generator) -> None: diff --git a/tests/test_lensing.py b/tests/test_lensing.py index fcf0b482..63a42be4 100644 --- a/tests/test_lensing.py +++ b/tests/test_lensing.py @@ -24,11 +24,11 @@ @pytest.fixture 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), - RadialWindow([2.0, 3.0, 4.0], [0.0, 1.0, 0.0], 3.0), - RadialWindow([3.0, 4.0, 5.0], [0.0, 1.0, 0.0], 4.0), - RadialWindow([4.0, 5.0, 6.0], [0.0, 1.0, 0.0], 5.0), + RadialWindow(np.array([0.0, 1.0, 2.0]), np.array([0.0, 1.0, 0.0]), 1.0), + RadialWindow(np.array([1.0, 2.0, 3.0]), np.array([0.0, 1.0, 0.0]), 2.0), + RadialWindow(np.array([2.0, 3.0, 4.0]), np.array([0.0, 1.0, 0.0]), 3.0), + RadialWindow(np.array([3.0, 4.0, 5.0]), np.array([0.0, 1.0, 0.0]), 4.0), + RadialWindow(np.array([4.0, 5.0, 6.0]), np.array([0.0, 1.0, 0.0]), 5.0), ] diff --git a/tests/test_shells.py b/tests/test_shells.py index 5f7381f5..4e4e498a 100644 --- a/tests/test_shells.py +++ b/tests/test_shells.py @@ -27,7 +27,9 @@ 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) + w = RadialWindow( + za=np.array([1.0, 2.0, 3.0, 4.0]), wa=np.array([0.0, 0.5, 0.5, 0.0]), zeff=None + ) zr, fr = restrict(z, f, w) From 3f9c158a04c737139bd61977d6b8826834f352d0 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Wed, 23 Oct 2024 09:15:41 +0100 Subject: [PATCH 093/143] Switch to arrays --- glass/shapes.py | 4 ++-- tests/test_shapes.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/glass/shapes.py b/glass/shapes.py index b5da39c5..40fba2ad 100644 --- a/glass/shapes.py +++ b/glass/shapes.py @@ -232,8 +232,8 @@ def ellipticity_gaussian( def ellipticity_intnorm( - count: int | list[int] | npt.NDArray[np.int_], - sigma: float | list[float] | npt.NDArray[np.float64], + count: int | npt.NDArray[np.int_], + sigma: float | npt.NDArray[np.float64], *, rng: np.random.Generator | None = None, ) -> npt.NDArray[np.complex128]: diff --git a/tests/test_shapes.py b/tests/test_shapes.py index 270987f5..fed15bc1 100644 --- a/tests/test_shapes.py +++ b/tests/test_shapes.py @@ -138,7 +138,7 @@ def test_ellipticity_intnorm(rng: np.random.Generator) -> 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(np.array([n, n]), np.array([0.128, 0.256])) assert eps.shape == (2 * n,) From 3f63c2ec18ccec3928fb172f39f3690f93543408 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Wed, 23 Oct 2024 09:39:27 +0100 Subject: [PATCH 094/143] Simplify more types --- glass/core/array.py | 16 +++++----------- glass/fields.py | 30 ++++++++++++++++-------------- glass/galaxies.py | 6 +++--- glass/points.py | 6 +++--- glass/shapes.py | 16 ++++++++-------- glass/shells.py | 18 ++++++++---------- tests/core/test_array.py | 32 ++++++++++++++------------------ tests/test_galaxies.py | 14 ++++++++++++-- tests/test_points.py | 12 ++++++------ tests/test_shapes.py | 20 +++++++++++--------- tests/test_shells.py | 2 +- 11 files changed, 87 insertions(+), 85 deletions(-) diff --git a/glass/core/array.py b/glass/core/array.py index 3039e1c3..056c1779 100644 --- a/glass/core/array.py +++ b/glass/core/array.py @@ -60,12 +60,9 @@ def broadcast_leading_axes( def ndinterp( # noqa: PLR0913 - x: float | list[float] | list[list[float]] | npt.NDArray[np.float64], - xp: list[int] | npt.NDArray[np.float64], - fp: list[float] - | list[list[float]] - | list[list[list[float]]] - | npt.NDArray[np.float64], + x: float | npt.NDArray[np.float64], + xp: npt.NDArray[np.float64], + fp: npt.NDArray[np.float64], axis: int = -1, left: float | None = None, right: float | None = None, @@ -85,11 +82,8 @@ def ndinterp( # noqa: PLR0913 def trapz_product( f: tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]], *ff: tuple[ - list[float] | npt.NDArray[np.float64], - list[float] - | list[int] - | list[npt.NDArray[np.float64]] - | npt.NDArray[np.float64], + npt.NDArray[np.float64], + npt.NDArray[np.float64], ], axis: int = -1, ) -> npt.NDArray[np.float64]: diff --git a/glass/fields.py b/glass/fields.py index c6692707..43200b10 100644 --- a/glass/fields.py +++ b/glass/fields.py @@ -103,7 +103,7 @@ def iternorm( def cls2cov( - cls: list[list[float] | npt.NDArray[np.float64]], + cls: npt.NDArray[np.float64], nl: int, nf: int, nc: int, @@ -139,7 +139,7 @@ def multalm( def transform_cls( - cls: list[list[float] | npt.NDArray[np.float64]], + cls: npt.NDArray[np.float64], tfm: str | typing.Callable[[npt.NDArray[np.float64]], npt.NDArray[np.float64]], pars: tuple[typing.Any, ...] = (), ) -> list[list[float] | npt.NDArray[np.float64]]: @@ -161,7 +161,7 @@ def transform_cls( def discretized_cls( - cls: list[list[float] | npt.NDArray[np.float64]], + cls: npt.NDArray[np.float64], *, lmax: int | None = None, ncorr: int | None = None, @@ -181,18 +181,20 @@ def discretized_cls( if n * (n + 1) // 2 != len(cls): msg = "length of cls array is not a triangle number" raise ValueError(msg) - cls = [ - cls[i * (i + 1) // 2 + j] if j <= ncorr else [] - for i in range(n) - for j in range(i + 1) - ] + cls = np.array( + [ + cls[i * (i + 1) // 2 + j] if j <= ncorr else [] + for i in range(n) + for j in range(i + 1) + ] + ) if nside is not None: pw = hp.pixwin(nside, lmax=lmax) gls = [] for cl in cls: - if cl is not None and len(cl) > 0: # type: ignore[redundant-expr] + if cl is not None and len(cl) > 0: if lmax is not None: cl = cl[: lmax + 1] # noqa: PLW2901 if nside is not None: @@ -203,7 +205,7 @@ def discretized_cls( def lognormal_gls( - cls: list[list[float] | npt.NDArray[np.float64]], + cls: npt.NDArray[np.float64], shift: float = 1.0, ) -> list[list[float] | npt.NDArray[np.float64]]: """Compute Gaussian Cls for a lognormal random field.""" @@ -211,7 +213,7 @@ def lognormal_gls( def generate_gaussian( - gls: list[list[float] | npt.NDArray[np.float64]], + gls: npt.NDArray[np.float64], nside: int, *, ncorr: int | None = None, @@ -296,7 +298,7 @@ def generate_gaussian( def generate_lognormal( - gls: list[list[float] | npt.NDArray[np.float64]], + gls: npt.NDArray[np.float64], nside: int, shift: float = 1.0, *, @@ -325,7 +327,7 @@ def generate_lognormal( def getcl( - cls: list[npt.NDArray[np.float64]], + cls: npt.NDArray[np.float64], i: int, j: int, lmax: int | None = None, @@ -360,7 +362,7 @@ def getcl( def effective_cls( - cls: list[npt.NDArray[np.float64]], + cls: npt.NDArray[np.float64], weights1: npt.NDArray[np.float64], weights2: npt.NDArray[np.float64] | None = None, *, diff --git a/glass/galaxies.py b/glass/galaxies.py index 757cfb04..be088f61 100644 --- a/glass/galaxies.py +++ b/glass/galaxies.py @@ -145,9 +145,9 @@ def redshifts_from_nz( def galaxy_shear( # noqa: PLR0913 - lon: list[float] | npt.NDArray[np.float64], - lat: list[float] | npt.NDArray[np.float64], - eps: list[float] | npt.NDArray[np.float64], + lon: npt.NDArray[np.float64], + lat: npt.NDArray[np.float64], + eps: npt.NDArray[np.float64], kappa: npt.NDArray[np.float64], gamma1: npt.NDArray[np.float64], gamma2: npt.NDArray[np.float64], diff --git a/glass/points.py b/glass/points.py index 3c25a2e3..eb26091a 100644 --- a/glass/points.py +++ b/glass/points.py @@ -109,7 +109,7 @@ def loglinear_bias( def positions_from_delta( # noqa: PLR0912, PLR0913, PLR0915 - ngal: float | list[float], + ngal: float | npt.NDArray[np.float64], delta: npt.NDArray[np.float64], bias: float | None = None, vis: npt.NDArray[np.float64] | None = None, @@ -214,7 +214,7 @@ 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, index] + n *= ARCMIN2_SPHERE / n.size * ngal[k] # type: ignore[index] # apply visibility if given if vis is not None: @@ -276,7 +276,7 @@ def positions_from_delta( # noqa: PLR0912, PLR0913, PLR0915 def uniform_positions( - ngal: float | npt.NDArray[np.int_] | list[float] | list[list[float]], + ngal: float | npt.NDArray[np.int_] | npt.NDArray[np.float64], *, rng: np.random.Generator | None = None, ) -> collections.abc.Generator[ diff --git a/glass/shapes.py b/glass/shapes.py index 40fba2ad..88f7101e 100644 --- a/glass/shapes.py +++ b/glass/shapes.py @@ -29,8 +29,8 @@ def triaxial_axis_ratio( - zeta: float | list[float] | list[list[float]] | npt.NDArray[np.float64], - xi: float | list[float], + zeta: float | npt.NDArray[np.float64], + xi: float | npt.NDArray[np.float64], size: int | tuple[int, int] | None = None, *, rng: np.random.Generator | None = None, @@ -97,10 +97,10 @@ def triaxial_axis_ratio( def ellipticity_ryden04( # noqa: PLR0913 - mu: float | list[float] | npt.NDArray[np.float64], - sigma: float | list[float] | npt.NDArray[np.float64], - gamma: float | list[float] | list[list[float]] | npt.NDArray[np.float64], - sigma_gamma: float | list[float] | npt.NDArray[np.float64], + mu: float | npt.NDArray[np.float64], + sigma: float | npt.NDArray[np.float64], + gamma: float | npt.NDArray[np.float64], + sigma_gamma: float | npt.NDArray[np.float64], size: int | tuple[int, ...] | None = None, *, rng: np.random.Generator | None = None, @@ -178,8 +178,8 @@ def ellipticity_ryden04( # noqa: PLR0913 def ellipticity_gaussian( - count: int | list[int] | npt.NDArray[np.int_], - sigma: float | list[float] | npt.NDArray[np.float64], + count: int | npt.NDArray[np.int_], + sigma: float | npt.NDArray[np.float64], *, rng: np.random.Generator | None = None, ) -> npt.NDArray[np.complex128]: diff --git a/glass/shells.py b/glass/shells.py index f8a2f7cf..3c85bf27 100644 --- a/glass/shells.py +++ b/glass/shells.py @@ -130,7 +130,7 @@ class RadialWindow(typing.NamedTuple): def tophat_windows( - zbins: list[float] | npt.NDArray[np.float64], + zbins: npt.NDArray[np.float64], dz: float = 1e-3, weight: typing.Callable[ [list[float] | npt.NDArray[np.float64]], @@ -202,7 +202,7 @@ def tophat_windows( def linear_windows( - zgrid: list[float] | npt.NDArray[np.float64], + zgrid: npt.NDArray[np.float64], dz: float = 1e-3, weight: typing.Callable[ [list[float] | npt.NDArray[np.float64]], @@ -263,7 +263,7 @@ def linear_windows( def cubic_windows( - zgrid: list[float] | npt.NDArray[np.float64], + zgrid: npt.NDArray[np.float64], dz: float = 1e-3, weight: typing.Callable[ [list[float] | npt.NDArray[np.float64]], @@ -325,8 +325,8 @@ def cubic_windows( def restrict( - z: list[float] | npt.NDArray[np.float64], - f: list[float] | npt.NDArray[np.float64], + z: npt.NDArray[np.float64], + f: npt.NDArray[np.float64], w: RadialWindow, ) -> tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]]: """ @@ -360,7 +360,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[arg-type] + fr = ndinterp(zr, z, f, left=0.0, right=0.0) * ndinterp(zr, w.za, w.wa) return zr, fr @@ -498,9 +498,7 @@ def partition_lstsq( dz = np.gradient(zp) # create the window function matrix - a: list[npt.NDArray[np.float64]] | npt.NDArray[np.float64] = [ - np.interp(zp, za, wa, left=0.0, right=0.0) for za, wa, _ in shells - ] + a = np.array([np.interp(zp, za, wa, left=0.0, right=0.0) for za, wa, _ in shells]) a /= np.trapz( # type: ignore[attr-defined] a, zp, @@ -534,7 +532,7 @@ 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[union-attr] + x = np.linalg.lstsq(a.T, b.reshape(-1, zp.size + 1).T, rcond=None)[0] x = x.T.reshape(*dims, len(shells)) # roll the last axis of size len(shells) to the front return np.moveaxis(x, -1, 0) diff --git a/tests/core/test_array.py b/tests/core/test_array.py index b5ce2325..caa8acaa 100644 --- a/tests/core/test_array.py +++ b/tests/core/test_array.py @@ -64,45 +64,39 @@ def test_broadcast_leading_axes() -> None: def test_ndinterp() -> None: # test 1d interpolation - xp = [0, 1, 2, 3, 4] - yp: list[float] | list[list[float]] | list[list[list[float]]] = [ - 1.1, - 1.2, - 1.3, - 1.4, - 1.5, - ] - - x: float | list[float] | list[list[float]] = 0.5 + xp = np.array([0, 1, 2, 3, 4]) + yp = np.array([1.1, 1.2, 1.3, 1.4, 1.5]) + + x: float | npt.NDArray[np.float64] = 0.5 y = ndinterp(x, xp, yp) assert np.shape(y) == () np.testing.assert_allclose(y, 1.15, atol=1e-15) - x = [0.5, 1.5, 2.5] + x = np.array([0.5, 1.5, 2.5]) y = ndinterp(x, xp, yp) assert np.shape(y) == (3,) np.testing.assert_allclose(y, [1.15, 1.25, 1.35], atol=1e-15) - x = [[0.5, 1.5], [2.5, 3.5]] + x = np.array([[0.5, 1.5], [2.5, 3.5]]) 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) # 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 = np.array([[1.1, 1.2, 1.3, 1.4, 1.5], [2.1, 2.2, 2.3, 2.4, 2.5]]) 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) - x = [0.5, 1.5, 2.5] + x = np.array([0.5, 1.5, 2.5]) 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) - x = [[0.5, 1.5], [2.5, 3.5]] + x = np.array([[0.5, 1.5], [2.5, 3.5]]) y = ndinterp(x, xp, yp) assert np.shape(y) == (2, 2, 2) np.testing.assert_allclose( @@ -113,14 +107,16 @@ def test_ndinterp() -> None: # 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 = np.array( + [[[1.1], [1.2], [1.3], [1.4], [1.5]], [[2.1], [2.2], [2.3], [2.4], [2.5]]] + ) 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) - x = [0.5, 1.5, 2.5] + x = np.array([0.5, 1.5, 2.5]) y = ndinterp(x, xp, yp, axis=1) assert np.shape(y) == (2, 3, 1) np.testing.assert_allclose( @@ -129,7 +125,7 @@ def test_ndinterp() -> None: 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 = np.array([[0.5, 1.5, 2.5, 3.5], [3.5, 2.5, 1.5, 0.5], [0.5, 3.5, 1.5, 2.5]]) y = ndinterp(x, xp, yp, axis=1) assert np.shape(y) == (2, 3, 4, 1) np.testing.assert_allclose( diff --git a/tests/test_galaxies.py b/tests/test_galaxies.py index 4935698d..a3a3f49e 100644 --- a/tests/test_galaxies.py +++ b/tests/test_galaxies.py @@ -124,7 +124,9 @@ def test_galaxy_shear(rng: np.random.Generator) -> None: rng.normal(size=(12,)), ) - shear = galaxy_shear([], [], [], kappa, gamma1, gamma2) + shear = galaxy_shear( + np.array([]), np.array([]), np.array([]), kappa, gamma1, gamma2 + ) np.testing.assert_equal(shear, []) gal_lon, gal_lat, gal_eps = ( @@ -137,7 +139,15 @@ def test_galaxy_shear(rng: np.random.Generator) -> None: # shape with no reduced shear - shear = galaxy_shear([], [], [], kappa, gamma1, gamma2, reduced_shear=False) + shear = galaxy_shear( + np.array([]), + np.array([]), + np.array([]), + kappa, + gamma1, + gamma2, + reduced_shear=False, + ) np.testing.assert_equal(shear, []) gal_lon, gal_lat, gal_eps = ( diff --git a/tests/test_points.py b/tests/test_points.py index 4c1b5a77..d76a8204 100644 --- a/tests/test_points.py +++ b/tests/test_points.py @@ -37,7 +37,7 @@ def catpos( def test_positions_from_delta() -> None: # case: single-dimensional input - ngal: float | list[float] = 1e-3 + ngal: float | npt.NDArray[np.float64] = 1e-3 delta = np.zeros(12) bias = 0.8 vis = np.ones(12) @@ -49,7 +49,7 @@ def test_positions_from_delta() -> None: # case: multi-dimensional ngal - ngal = [1e-3, 2e-3] + ngal = np.array([1e-3, 2e-3]) delta = np.zeros(12) bias = 0.8 vis = np.ones(12) @@ -77,7 +77,7 @@ def test_positions_from_delta() -> None: # case: multi-dimensional broadcasting - ngal = [1e-3, 2e-3] + ngal = np.array([1e-3, 2e-3]) delta = np.zeros((3, 1, 12)) bias = 0.8 vis = np.ones(12) @@ -93,7 +93,7 @@ def test_positions_from_delta() -> None: def test_uniform_positions() -> None: # case: scalar input - ngal: float | list[float] | list[list[float]] = 1e-3 + ngal: float | npt.NDArray[np.float64] = 1e-3 lon, lat, cnt = catpos(uniform_positions(ngal)) @@ -102,7 +102,7 @@ def test_uniform_positions() -> None: # case: 1-D array input - ngal = [1e-3, 2e-3, 3e-3] + ngal = np.array([1e-3, 2e-3, 3e-3]) lon, lat, cnt = catpos(uniform_positions(ngal)) @@ -112,7 +112,7 @@ def test_uniform_positions() -> None: # case: 2-D array input - ngal = [[1e-3, 2e-3], [3e-3, 4e-3], [5e-3, 6e-3]] + ngal = np.array([[1e-3, 2e-3], [3e-3, 4e-3], [5e-3, 6e-3]]) lon, lat, cnt = catpos(uniform_positions(ngal)) diff --git a/tests/test_shapes.py b/tests/test_shapes.py index fed15bc1..31ac996f 100644 --- a/tests/test_shapes.py +++ b/tests/test_shapes.py @@ -27,13 +27,13 @@ def test_triaxial_axis_ratio(rng: np.random.Generator) -> 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(np.array([0.8, 0.9]), 0.4) + q2 = triaxial_axis_ratio(0.8, np.array([0.4, 0.5])) 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(np.array([[0.6, 0.7], [0.8, 0.9]]), np.array([0.4, 0.5])) assert np.shape(q) == (2, 2) # random parameters and check that projection is @@ -69,15 +69,17 @@ def test_ellipticity_ryden04(rng: np.random.Generator) -> None: # 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, np.array([0.222, 0.333]), 0.056) + e2 = ellipticity_ryden04(-1.85, 0.89, 0.222, np.array([0.056, 0.067])) + e3 = ellipticity_ryden04(np.array([-1.85, -2.85]), 0.89, 0.222, 0.056) + e4 = ellipticity_ryden04(-1.85, np.array([0.89, 1.001]), 0.222, 0.056) 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( + np.array([-1.9, -2.9]), 0.9, np.array([[0.2, 0.3], [0.4, 0.5]]), 0.1 + ) assert np.shape(e) == (2, 2) # check that result is in the specified range @@ -108,7 +110,7 @@ def test_ellipticity_gaussian(rng: np.random.Generator) -> 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_gaussian([n, n], [0.128, 0.256]) + eps = ellipticity_gaussian(np.array([n, n]), np.array([0.128, 0.256])) assert eps.shape == (2 * n,) diff --git a/tests/test_shells.py b/tests/test_shells.py index 4e4e498a..2865db5a 100644 --- a/tests/test_shells.py +++ b/tests/test_shells.py @@ -5,7 +5,7 @@ def test_tophat_windows() -> None: - zb = [0.0, 0.1, 0.2, 0.5, 1.0, 2.0] + zb = np.array([0.0, 0.1, 0.2, 0.5, 1.0, 2.0]) dz = 0.005 ws = tophat_windows(zb, dz) From 4d78c5e971fd13d2c2b6cb988b25f358b09f9a92 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Wed, 23 Oct 2024 09:46:59 +0100 Subject: [PATCH 095/143] Remove double import --- tests/test_lensing.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/test_lensing.py b/tests/test_lensing.py index 63a42be4..4af33c6c 100644 --- a/tests/test_lensing.py +++ b/tests/test_lensing.py @@ -7,8 +7,6 @@ import numpy.typing as npt import pytest -from cosmology import Cosmology - from glass.lensing import ( MultiPlaneConvergence, deflect, From 2cb042d4eb99f0304088c7ecccdf409ffb0c0138 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Wed, 23 Oct 2024 09:57:28 +0100 Subject: [PATCH 096/143] Fix tests --- glass/fields.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/glass/fields.py b/glass/fields.py index 43200b10..7cd6e9da 100644 --- a/glass/fields.py +++ b/glass/fields.py @@ -161,7 +161,7 @@ def transform_cls( def discretized_cls( - cls: npt.NDArray[np.float64], + cls: list[list[float]] | npt.NDArray[np.float64], *, lmax: int | None = None, ncorr: int | None = None, @@ -181,13 +181,11 @@ def discretized_cls( if n * (n + 1) // 2 != len(cls): msg = "length of cls array is not a triangle number" raise ValueError(msg) - cls = np.array( - [ - cls[i * (i + 1) // 2 + j] if j <= ncorr else [] - for i in range(n) - for j in range(i + 1) - ] - ) + cls = [ + cls[i * (i + 1) // 2 + j] if j <= ncorr else [] + for i in range(n) + for j in range(i + 1) + ] if nside is not None: pw = hp.pixwin(nside, lmax=lmax) From 0a0ed290d5a12b2f876cc3611da6c6e29e10b280 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Wed, 23 Oct 2024 10:01:08 +0100 Subject: [PATCH 097/143] Remove float --- glass/observations.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glass/observations.py b/glass/observations.py index 77a489c1..c878c683 100644 --- a/glass/observations.py +++ b/glass/observations.py @@ -132,7 +132,7 @@ def smail_nz( alpha: npt.NDArray[np.float64], beta: npt.NDArray[np.float64], *, - norm: float | npt.NDArray[np.float64] | None = None, + norm: npt.NDArray[np.float64] | None = None, ) -> npt.NDArray[np.float64]: r""" Redshift distribution following Smail et al. (1994). From 5603418ef3483ce3e9dfc64bb8093ca415601612 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Wed, 23 Oct 2024 10:21:27 +0100 Subject: [PATCH 098/143] Fix return value --- glass/core/array.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/glass/core/array.py b/glass/core/array.py index 056c1779..cf71ead5 100644 --- a/glass/core/array.py +++ b/glass/core/array.py @@ -2,6 +2,7 @@ from __future__ import annotations +import typing from functools import partial import numpy as np @@ -22,7 +23,10 @@ def broadcast_leading_axes( int | npt.NDArray[np.int_], int, ], -) -> tuple[tuple[int, int], tuple[npt.NDArray[np.int_], ...]]: +) -> tuple[ + tuple[int, ...], + typing.Unpack[tuple[npt.NDArray[np.int_], ...]], +]: """ Broadcast all but the last N axes. @@ -56,7 +60,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) # type: ignore[return-value] + return (dims, *arrs) def ndinterp( # noqa: PLR0913 From 5e520ce2f8dde8aa2b6eb85e5e3e8d275b1ad6e1 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Wed, 23 Oct 2024 18:09:53 +0100 Subject: [PATCH 099/143] Undo number --- glass/core/array.py | 2 +- glass/galaxies.py | 2 +- tests/core/test_array.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/glass/core/array.py b/glass/core/array.py index cf71ead5..1c31143e 100644 --- a/glass/core/array.py +++ b/glass/core/array.py @@ -20,7 +20,7 @@ def broadcast_first( def broadcast_leading_axes( *args: tuple[ - int | npt.NDArray[np.int_], + int | npt.NDArray[np.int_] | npt.NDArray[np.float64], int, ], ) -> tuple[ diff --git a/glass/galaxies.py b/glass/galaxies.py index be088f61..c5d10bd6 100644 --- a/glass/galaxies.py +++ b/glass/galaxies.py @@ -117,7 +117,7 @@ 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)) # type: ignore[arg-type, misc] + dims, count, z, nz = broadcast_leading_axes((count, 0), (z, 1), (nz, 1)) # type: ignore[misc] # list of results for all dimensions redshifts = np.empty(count.sum()) # type: ignore[union-attr] diff --git a/tests/core/test_array.py b/tests/core/test_array.py index caa8acaa..3b7289c8 100644 --- a/tests/core/test_array.py +++ b/tests/core/test_array.py @@ -53,7 +53,7 @@ def test_broadcast_leading_axes() -> None: a_out: npt.NDArray[np.int_] b_out: npt.NDArray[np.int_] c_out: npt.NDArray[np.int_] - dims, a_out, b_out, c_out = broadcast_leading_axes((a_in, 0), (b_in, 1), (c_in, 2)) # type: ignore[arg-type, misc] + dims, a_out, b_out, c_out = broadcast_leading_axes((a_in, 0), (b_in, 1), (c_in, 2)) # type: ignore[misc] assert dims == (3, 4) assert a_out.shape == (3, 4) From 9b5a011055813205f3a8420c0cb3a119836e168e Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Wed, 23 Oct 2024 18:31:55 +0100 Subject: [PATCH 100/143] Fix `broadcast_leading_axes` --- glass/core/array.py | 4 ++-- glass/galaxies.py | 19 ++++++++++--------- tests/test_galaxies.py | 2 +- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/glass/core/array.py b/glass/core/array.py index 1c31143e..8100f35e 100644 --- a/glass/core/array.py +++ b/glass/core/array.py @@ -20,12 +20,12 @@ def broadcast_first( def broadcast_leading_axes( *args: tuple[ - int | npt.NDArray[np.int_] | npt.NDArray[np.float64], + int | npt.NDArray[np.float64], int, ], ) -> tuple[ tuple[int, ...], - typing.Unpack[tuple[npt.NDArray[np.int_], ...]], + typing.Unpack[tuple[npt.NDArray[np.float64], ...]], ]: """ Broadcast all but the last N axes. diff --git a/glass/galaxies.py b/glass/galaxies.py index c5d10bd6..15e8b73a 100644 --- a/glass/galaxies.py +++ b/glass/galaxies.py @@ -39,7 +39,7 @@ def redshifts( - n: int | npt.NDArray[np.int_], + n: int | npt.NDArray[np.float64], w: RadialWindow, *, rng: np.random.Generator | None = None, @@ -67,7 +67,7 @@ def redshifts( def redshifts_from_nz( - count: int | npt.NDArray[np.int_], + count: int | npt.NDArray[np.float64], z: npt.NDArray[np.float64], nz: npt.NDArray[np.float64], *, @@ -117,10 +117,11 @@ 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)) # type: ignore[misc] + dims, *rest = broadcast_leading_axes((count, 0), (z, 1), (nz, 1)) + count_out, z_out, nz_out = rest # list of results for all dimensions - redshifts = np.empty(count.sum()) # type: ignore[union-attr] + redshifts = np.empty(count_out.sum()) # keep track of the number of sampled redshifts total = 0 @@ -128,16 +129,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 = cumtrapz(nz_out[k], z_out[k], dtype=float) cdf /= cdf[-1] # sample redshifts and store result - redshifts[total : total + count[k]] = np.interp( # type: ignore[index] - rng.uniform(0, 1, size=count[k]), # type: ignore[index] + redshifts[total : total + count_out[k]] = np.interp( + rng.uniform(0, 1, size=count_out[k]), cdf, - z[k], + z_out[k], ) - total += count[k] # type: ignore[index] + total += count_out[k] assert total == redshifts.size # noqa: S101 diff --git a/tests/test_galaxies.py b/tests/test_galaxies.py index a3a3f49e..2164818b 100644 --- a/tests/test_galaxies.py +++ b/tests/test_galaxies.py @@ -61,7 +61,7 @@ def test_redshifts_from_nz(rng: np.random.Generator) -> None: # case: no extra dimensions - count: int | npt.NDArray[np.int_] = 10 + count: int | npt.NDArray[np.float64] = 10 z = np.linspace(0, 1, 100) nz = z * (1 - z) From f6729860bebc51d477f56d3655bf8244165bb1b9 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Thu, 24 Oct 2024 09:48:58 +0100 Subject: [PATCH 101/143] Fix the `zsrc` errors --- glass/lensing.py | 14 +++++++------- glass/shells.py | 2 +- tests/test_shells.py | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/glass/lensing.py b/glass/lensing.py index 025bff13..b4a6ae3a 100644 --- a/glass/lensing.py +++ b/glass/lensing.py @@ -273,8 +273,8 @@ def __init__(self, cosmo: Cosmology) -> None: self.cosmo = cosmo # set up initial values of variables - self.z2: float | None = 0.0 - self.z3: float | None = 0.0 + self.z2: float = 0.0 + self.z3: float = 0.0 self.x3: float = 0.0 self.w3: float = 0.0 self.r23: float = 1.0 @@ -295,7 +295,7 @@ def add_window(self, delta: npt.NDArray[np.float64], w: RadialWindow) -> None: w.wa, w.za, ) / np.interp( - zsrc, # type: ignore[arg-type] + zsrc, w.za, w.wa, ) @@ -305,11 +305,11 @@ def add_window(self, delta: npt.NDArray[np.float64], w: RadialWindow) -> None: def add_plane( self, delta: npt.NDArray[np.float64], - zsrc: float | None, + zsrc: float, wlens: float = 1.0, ) -> None: """Add a mass plane at redshift ``zsrc`` to the convergence.""" - if zsrc <= self.z3: # type: ignore[operator] + if zsrc <= self.z3: msg = "source redshift must be increasing" raise ValueError(msg) @@ -331,7 +331,7 @@ def add_plane( # lensing weight of mass plane to be added f = 3 * self.cosmo.omega_m / 2 f *= x2 * self.r23 - f *= (1 + self.z2) / self.cosmo.ef(self.z2) # type: ignore[operator] + f *= (1 + self.z2) / self.cosmo.ef(self.z2) f *= w2 # create kappa planes on first iteration @@ -351,7 +351,7 @@ def add_plane( self.kappa3 += f * delta2 @property - def zsrc(self) -> float | None: + def zsrc(self) -> float: """The redshift of the current convergence plane.""" return self.z3 diff --git a/glass/shells.py b/glass/shells.py index 3c85bf27..84a6d93f 100644 --- a/glass/shells.py +++ b/glass/shells.py @@ -126,7 +126,7 @@ class RadialWindow(typing.NamedTuple): za: npt.NDArray[np.float64] wa: npt.NDArray[np.float64] - zeff: float | None + zeff: float = 0 def tophat_windows( diff --git a/tests/test_shells.py b/tests/test_shells.py index 2865db5a..1fbd2157 100644 --- a/tests/test_shells.py +++ b/tests/test_shells.py @@ -28,7 +28,7 @@ def test_restrict() -> None: # window for restriction w = RadialWindow( - za=np.array([1.0, 2.0, 3.0, 4.0]), wa=np.array([0.0, 0.5, 0.5, 0.0]), zeff=None + za=np.array([1.0, 2.0, 3.0, 4.0]), wa=np.array([0.0, 0.5, 0.5, 0.0]) ) zr, fr = restrict(z, f, w) From 64d6991d756cbd5d4913a0ff38ab1cef40bad162 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Thu, 24 Oct 2024 09:58:19 +0100 Subject: [PATCH 102/143] Fix test --- tests/test_fields.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/test_fields.py b/tests/test_fields.py index c332a639..ae58bde0 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -1,10 +1,12 @@ +import numpy as np + from glass.fields import 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)] + cls = np.array([{i, j} for i in range(10) for j in range(i, -1, -1)]) # 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] + assert getcl(cls, i, j) == {i, j} From 29a685e03b9d856de647dc90481c7a455523663c Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Thu, 24 Oct 2024 10:06:02 +0100 Subject: [PATCH 103/143] Fix `fitsio` import --- glass/user.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/glass/user.py b/glass/user.py index 606a3b44..c3740a61 100644 --- a/glass/user.py +++ b/glass/user.py @@ -27,8 +27,12 @@ if typing.TYPE_CHECKING: import collections.abc + import importlib.util import pathlib + if importlib.util.find_spec("fitsio") is not None: + import fitsio + def save_cls(filename: str, cls: list[npt.NDArray[np.float64] | None]) -> None: """ @@ -63,7 +67,7 @@ class _FitsWriter: Initialised with the fits object and extension name. """ - def __init__(self, fits, ext: str | None = None) -> None: # type: ignore[no-untyped-def] + def __init__(self, fits: fitsio.FITS, ext: str | None = None) -> None: """Create a new, uninitialised writer.""" self.fits = fits self.ext = ext From fada69c0981ea833e10b8760d4b04ccf85d62cb1 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Thu, 24 Oct 2024 10:09:50 +0100 Subject: [PATCH 104/143] Fix `union-attr` --- tests/test_lensing.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/test_lensing.py b/tests/test_lensing.py index 4af33c6c..47d1e06d 100644 --- a/tests/test_lensing.py +++ b/tests/test_lensing.py @@ -109,7 +109,8 @@ def test_multi_plane_matrix( kappas = [] for shell, delta in zip(shells, deltas): convergence.add_window(delta, shell) - kappas.append(convergence.kappa.copy()) # type: ignore[union-attr] + if convergence.kappa is not None: + kappas.append(convergence.kappa.copy()) np.testing.assert_allclose(mat @ deltas, kappas) From 22efda8938de3a5ce7ae694cc7c873907f2dd930 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Thu, 24 Oct 2024 10:18:01 +0100 Subject: [PATCH 105/143] Fix `arg-type` --- glass/user.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/glass/user.py b/glass/user.py index c3740a61..add56e84 100644 --- a/glass/user.py +++ b/glass/user.py @@ -74,7 +74,7 @@ def __init__(self, fits: fitsio.FITS, ext: str | None = None) -> None: def _append( self, - data: npt.NDArray[np.float64], + data: npt.NDArray[np.float64] | list[npt.NDArray[np.float64]], names: list[str] | None = None, ) -> None: """Write the FITS file.""" @@ -106,7 +106,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) # type: ignore[arg-type] + self._append(values, names) @contextmanager From 3a7a1d0683f515f5b3d55ace2ee1747938c60788 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Thu, 24 Oct 2024 10:22:28 +0100 Subject: [PATCH 106/143] Fix assignment --- glass/shapes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glass/shapes.py b/glass/shapes.py index 88f7101e..48414748 100644 --- a/glass/shapes.py +++ b/glass/shapes.py @@ -70,7 +70,7 @@ def triaxial_axis_ratio( # get size from inputs if not explicitly provided if size is None: - size = np.broadcast(zeta, xi).shape # type: ignore[assignment] + size = tuple(np.broadcast(zeta, xi).shape) # draw random viewing angle (theta, phi) cos2_theta = rng.uniform(low=-1.0, high=1.0, size=size) From 88f41c6b2d5cf5073c21a62afbea2c9d85aa3755 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Thu, 24 Oct 2024 10:24:29 +0100 Subject: [PATCH 107/143] Fix test broadcast --- tests/core/test_array.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tests/core/test_array.py b/tests/core/test_array.py index 3b7289c8..7ecafffc 100644 --- a/tests/core/test_array.py +++ b/tests/core/test_array.py @@ -50,10 +50,8 @@ def test_broadcast_leading_axes() -> None: b_in = np.zeros((4, 10)) c_in = np.zeros((3, 1, 5, 6)) - a_out: npt.NDArray[np.int_] - b_out: npt.NDArray[np.int_] - c_out: npt.NDArray[np.int_] - dims, a_out, b_out, c_out = broadcast_leading_axes((a_in, 0), (b_in, 1), (c_in, 2)) # type: ignore[misc] + dims, *rest = broadcast_leading_axes((a_in, 0), (b_in, 1), (c_in, 2)) + a_out, b_out, c_out = rest assert dims == (3, 4) assert a_out.shape == (3, 4) From e7cdfd6a87a943ce0d0e44a05c5624fa834e5da9 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Thu, 24 Oct 2024 10:34:18 +0100 Subject: [PATCH 108/143] Fix `*rest` --- glass/points.py | 7 ++++--- glass/shapes.py | 4 ++-- tests/test_shapes.py | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/glass/points.py b/glass/points.py index eb26091a..96263c97 100644 --- a/glass/points.py +++ b/glass/points.py @@ -197,9 +197,10 @@ 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) # type: ignore[arg-type, misc] + dims, *rest = broadcast_leading_axes(*inputs) # type: ignore[arg-type] + ngal, delta, *rest = rest if bias is not None: - bias, *rest = rest + bias, *rest = rest # type: ignore[assignment] if vis is not None: vis, *rest = rest @@ -214,7 +215,7 @@ 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[index] + n *= ARCMIN2_SPHERE / n.size * ngal[k] # apply visibility if given if vis is not None: diff --git a/glass/shapes.py b/glass/shapes.py index 48414748..06319745 100644 --- a/glass/shapes.py +++ b/glass/shapes.py @@ -31,7 +31,7 @@ def triaxial_axis_ratio( zeta: float | npt.NDArray[np.float64], xi: float | npt.NDArray[np.float64], - size: int | tuple[int, int] | None = None, + size: tuple[int, ...] | None = None, *, rng: np.random.Generator | None = None, ) -> npt.NDArray[np.float64]: @@ -70,7 +70,7 @@ def triaxial_axis_ratio( # get size from inputs if not explicitly provided if size is None: - size = tuple(np.broadcast(zeta, xi).shape) + size = np.broadcast(zeta, xi).shape # draw random viewing angle (theta, phi) cos2_theta = rng.uniform(low=-1.0, high=1.0, size=size) diff --git a/tests/test_shapes.py b/tests/test_shapes.py index 31ac996f..d82471e1 100644 --- a/tests/test_shapes.py +++ b/tests/test_shapes.py @@ -17,7 +17,7 @@ def test_triaxial_axis_ratio(rng: np.random.Generator) -> None: # many axis ratios - q = triaxial_axis_ratio(0.8, 0.4, size=1000) + q = triaxial_axis_ratio(0.8, 0.4, size=(1000,)) assert np.shape(q) == (1000,) # explicit shape From 61e273ef0f550c2a97b4cefc13d263c5951a59b4 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Thu, 24 Oct 2024 10:54:56 +0100 Subject: [PATCH 109/143] Fix assignment --- glass/points.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/glass/points.py b/glass/points.py index 96263c97..24562430 100644 --- a/glass/points.py +++ b/glass/points.py @@ -116,7 +116,7 @@ def positions_from_delta( # noqa: PLR0912, PLR0913, PLR0915 *, bias_model: str | typing.Callable[..., typing.Any] = "linear", remove_monopole: bool = False, - batch: int | None = 1_000_000, + batch: int = 1_000_000, rng: np.random.Generator | None = None, ) -> collections.abc.Generator[ tuple[ @@ -258,7 +258,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") # type: ignore[call-overload, operator] + stop += int(np.searchsorted(q, batch - size, side="right")) # if the first pixel alone is too much, use it anyway if stop == start: stop += 1 From a921881cde0001e8b12d446efa0523a19ba174ae Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Thu, 24 Oct 2024 10:55:41 +0100 Subject: [PATCH 110/143] Add typing metadata --- glass/py.typed | 0 pyproject.toml | 1 + 2 files changed, 1 insertion(+) create mode 100644 glass/py.typed diff --git a/glass/py.typed b/glass/py.typed new file mode 100644 index 00000000..e69de29b diff --git a/pyproject.toml b/pyproject.toml index ad2c4451..33968c30 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,6 +17,7 @@ classifiers = [ "Programming Language :: Python :: 3.12", "Topic :: Scientific/Engineering :: Astronomy", "Topic :: Scientific/Engineering :: Physics", + "Typing :: Typed", ] dependencies = [ "cosmology>=2022.10.9", From 1965509b14855d10c994cdcb6a9687a841d2fcd4 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Thu, 24 Oct 2024 11:01:26 +0100 Subject: [PATCH 111/143] `bias` can be array --- glass/points.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/glass/points.py b/glass/points.py index 24562430..0c595410 100644 --- a/glass/points.py +++ b/glass/points.py @@ -111,7 +111,7 @@ def loglinear_bias( def positions_from_delta( # noqa: PLR0912, PLR0913, PLR0915 ngal: float | npt.NDArray[np.float64], delta: npt.NDArray[np.float64], - bias: float | None = None, + bias: float | npt.NDArray[np.float64] | None = None, vis: npt.NDArray[np.float64] | None = None, *, bias_model: str | typing.Callable[..., typing.Any] = "linear", @@ -200,14 +200,14 @@ def positions_from_delta( # noqa: PLR0912, PLR0913, PLR0915 dims, *rest = broadcast_leading_axes(*inputs) # type: ignore[arg-type] ngal, delta, *rest = rest if bias is not None: - bias, *rest = rest # type: ignore[assignment] + bias, *rest = rest if vis is not None: vis, *rest = rest # 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[index, operator] + n = np.copy(delta[k]) if bias is None else bias_model(delta[k], bias[k]) # type: ignore[operator] # remove monopole if asked to if remove_monopole: From 05ad1502145fa5d947fbab52b0b4312656263eba Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Thu, 24 Oct 2024 11:04:11 +0100 Subject: [PATCH 112/143] Create `bias_model_callable` --- glass/points.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/glass/points.py b/glass/points.py index 0c595410..9712f924 100644 --- a/glass/points.py +++ b/glass/points.py @@ -187,9 +187,11 @@ def positions_from_delta( # noqa: PLR0912, PLR0913, PLR0915 # get the bias model if isinstance(bias_model, str): - bias_model = globals()[f"{bias_model}_bias"] + bias_model_callable = globals()[f"{bias_model}_bias"] elif not callable(bias_model): raise TypeError("bias_model must be string or callable") # noqa: EM101,TRY003 + else: + bias_model_callable = bias_model # broadcast inputs to common shape of extra dimensions inputs = [(ngal, 0), (delta, 1)] @@ -207,7 +209,11 @@ 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[operator] + n = ( + np.copy(delta[k]) + if bias is None + else bias_model_callable(delta[k], bias[k]) + ) # remove monopole if asked to if remove_monopole: From 372226bfe7f5fbfd3d8864261c3bd62a03226469 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Thu, 24 Oct 2024 11:14:27 +0100 Subject: [PATCH 113/143] Fix `mypy` --- glass/core/array.py | 2 +- glass/points.py | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/glass/core/array.py b/glass/core/array.py index 8100f35e..036d9740 100644 --- a/glass/core/array.py +++ b/glass/core/array.py @@ -20,7 +20,7 @@ def broadcast_first( def broadcast_leading_axes( *args: tuple[ - int | npt.NDArray[np.float64], + float | npt.NDArray[np.float64], int, ], ) -> tuple[ diff --git a/glass/points.py b/glass/points.py index 9712f924..4c9434a1 100644 --- a/glass/points.py +++ b/glass/points.py @@ -194,12 +194,12 @@ def positions_from_delta( # noqa: PLR0912, PLR0913, PLR0915 bias_model_callable = bias_model # broadcast inputs to common shape of extra dimensions - inputs = [(ngal, 0), (delta, 1)] + inputs: list[tuple[float | npt.NDArray[np.float64], int]] = [(ngal, 0), (delta, 1)] if bias is not None: - inputs += [(bias, 0)] + inputs.append((bias, 0)) if vis is not None: - inputs += [(vis, 1)] - dims, *rest = broadcast_leading_axes(*inputs) # type: ignore[arg-type] + inputs.append((vis, 1)) + dims, *rest = broadcast_leading_axes(*inputs) ngal, delta, *rest = rest if bias is not None: bias, *rest = rest From c200a5da1165b7ab7e2a5f44dd268e634e04a8f3 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Thu, 24 Oct 2024 11:18:54 +0100 Subject: [PATCH 114/143] Add to `git blame` file --- .git-blame-ignore-revs | 1 + 1 file changed, 1 insertion(+) diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index e98ceab3..134713cf 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -4,3 +4,4 @@ b42067f6776dcd763827000d585a88e071b78af3 f9bac62f497a7288aa71fd4dbd948945c37f854e # applied ruff-linting - https://github.com/glass-dev/glass/pull/232 e58d8616c03b8447aba90996905a98b42f18ba0a +# added static typing - https://github.com/glass-dev/glass/pull/368 From 9062f174682faca43ad540d4b6642f4c8be4a606 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Thu, 24 Oct 2024 11:21:36 +0100 Subject: [PATCH 115/143] Ruff formating --- glass/shells.py | 2 +- tests/core/test_array.py | 2 +- tests/test_fits.py | 4 +++- tests/test_galaxies.py | 31 +++++++++++++++++++++++++------ tests/test_lensing.py | 4 +++- tests/test_shapes.py | 5 ++++- tests/test_shells.py | 3 ++- 7 files changed, 39 insertions(+), 12 deletions(-) diff --git a/glass/shells.py b/glass/shells.py index 84a6d93f..33335d71 100644 --- a/glass/shells.py +++ b/glass/shells.py @@ -579,7 +579,7 @@ def partition_nnls( right=0.0, ) for za, wa, _ in shells - ] + ], ) a /= np.trapz( # type: ignore[attr-defined] a, diff --git a/tests/core/test_array.py b/tests/core/test_array.py index 7ecafffc..8258b75e 100644 --- a/tests/core/test_array.py +++ b/tests/core/test_array.py @@ -106,7 +106,7 @@ def test_ndinterp() -> None: # test nd interpolation in middle axis yp = np.array( - [[[1.1], [1.2], [1.3], [1.4], [1.5]], [[2.1], [2.2], [2.3], [2.4], [2.5]]] + [[[1.1], [1.2], [1.3], [1.4], [1.5]], [[2.1], [2.2], [2.3], [2.4], [2.5]]], ) x = 0.5 diff --git a/tests/test_fits.py b/tests/test_fits.py index 037e1aa8..396bcbae 100644 --- a/tests/test_fits.py +++ b/tests/test_fits.py @@ -24,7 +24,9 @@ def test_basic_write(tmp_path: pathlib.Path) -> None: filename_tfits = "tfits.fits" # file created on the fly to test against def _test_append( - fits: fitsio.FITS, data: list[npt.NDArray[np.float64]], names: list[str] + fits: fitsio.FITS, + data: list[npt.NDArray[np.float64]], + names: list[str], ) -> None: """Write routine for FITS test cases.""" cat_name = "CATALOG" diff --git a/tests/test_galaxies.py b/tests/test_galaxies.py index 2164818b..a2a347eb 100644 --- a/tests/test_galaxies.py +++ b/tests/test_galaxies.py @@ -27,22 +27,34 @@ def test_redshifts_from_nz(rng: np.random.Generator) -> None: # test sampling redshifts = redshifts_from_nz( - 10, np.array([0, 1, 2, 3, 4]), np.array([1, 0, 0, 0, 0]), warn=False + 10, + np.array([0, 1, 2, 3, 4]), + np.array([1, 0, 0, 0, 0]), + warn=False, ) assert np.all((0 <= redshifts) & (redshifts <= 1)) # noqa: SIM300 redshifts = redshifts_from_nz( - 10, np.array([0, 1, 2, 3, 4]), np.array([0, 0, 1, 0, 0]), warn=False + 10, + np.array([0, 1, 2, 3, 4]), + np.array([0, 0, 1, 0, 0]), + warn=False, ) assert np.all((1 <= redshifts) & (redshifts <= 3)) # noqa: SIM300 redshifts = redshifts_from_nz( - 10, np.array([0, 1, 2, 3, 4]), np.array([0, 0, 0, 0, 1]), warn=False + 10, + np.array([0, 1, 2, 3, 4]), + np.array([0, 0, 0, 0, 1]), + warn=False, ) assert np.all((3 <= redshifts) & (redshifts <= 4)) # noqa: SIM300 redshifts = redshifts_from_nz( - 10, np.array([0, 1, 2, 3, 4]), np.array([0, 0, 1, 1, 1]), warn=False + 10, + np.array([0, 1, 2, 3, 4]), + np.array([0, 0, 1, 1, 1]), + warn=False, ) assert not np.any(redshifts <= 1) @@ -111,7 +123,9 @@ def test_redshifts_from_nz(rng: np.random.Generator) -> None: with pytest.warns(UserWarning, match="when sampling galaxies"): redshifts = redshifts_from_nz( - 10, np.array([0, 1, 2, 3, 4]), np.array([1, 0, 0, 0, 0]) + 10, + np.array([0, 1, 2, 3, 4]), + np.array([1, 0, 0, 0, 0]), ) @@ -125,7 +139,12 @@ def test_galaxy_shear(rng: np.random.Generator) -> None: ) shear = galaxy_shear( - np.array([]), np.array([]), np.array([]), kappa, gamma1, gamma2 + np.array([]), + np.array([]), + np.array([]), + kappa, + gamma1, + gamma2, ) np.testing.assert_equal(shear, []) diff --git a/tests/test_lensing.py b/tests/test_lensing.py index 47d1e06d..356b2b78 100644 --- a/tests/test_lensing.py +++ b/tests/test_lensing.py @@ -41,7 +41,9 @@ def ef(self, z: npt.NDArray[np.float64]) -> npt.NDArray[np.float64]: return (self.omega_m * (1 + z) ** 3 + 1 - self.omega_m) ** 0.5 def xm( - self, z: npt.NDArray[np.float64], z2: npt.NDArray[np.float64] | None = None + self, + z: npt.NDArray[np.float64], + z2: npt.NDArray[np.float64] | None = None, ) -> npt.NDArray[np.float64]: if z2 is None: return np.array(z) * 1000 diff --git a/tests/test_shapes.py b/tests/test_shapes.py index d82471e1..c3da01e7 100644 --- a/tests/test_shapes.py +++ b/tests/test_shapes.py @@ -78,7 +78,10 @@ def test_ellipticity_ryden04(rng: np.random.Generator) -> None: # broadcasting rule e = ellipticity_ryden04( - np.array([-1.9, -2.9]), 0.9, np.array([[0.2, 0.3], [0.4, 0.5]]), 0.1 + np.array([-1.9, -2.9]), + 0.9, + np.array([[0.2, 0.3], [0.4, 0.5]]), + 0.1, ) assert np.shape(e) == (2, 2) diff --git a/tests/test_shells.py b/tests/test_shells.py index 1fbd2157..5f15f5ed 100644 --- a/tests/test_shells.py +++ b/tests/test_shells.py @@ -28,7 +28,8 @@ def test_restrict() -> None: # window for restriction w = RadialWindow( - za=np.array([1.0, 2.0, 3.0, 4.0]), wa=np.array([0.0, 0.5, 0.5, 0.0]) + za=np.array([1.0, 2.0, 3.0, 4.0]), + wa=np.array([0.0, 0.5, 0.5, 0.0]), ) zr, fr = restrict(z, f, w) From 0b4a446c8cd9fab07e2721798bd40622017ffbed Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Thu, 24 Oct 2024 16:33:53 +0100 Subject: [PATCH 116/143] Make size a tuple --- glass/fields.py | 22 +++++++--------------- glass/shapes.py | 8 ++++---- tests/test_shapes.py | 6 +++--- 3 files changed, 14 insertions(+), 22 deletions(-) diff --git a/glass/fields.py b/glass/fields.py index 7cd6e9da..7bb7ec11 100644 --- a/glass/fields.py +++ b/glass/fields.py @@ -41,23 +41,15 @@ def iternorm( k: int, cov: collections.abc.Iterable[npt.NDArray[np.float64]], - size: int | tuple[int, ...] | None = None, + size: tuple[int, ...] = (), ) -> collections.abc.Generator[ tuple[int | None, npt.NDArray[np.float64], npt.NDArray[np.float64]] ]: """Return the vector a and variance sigma^2 for iterative normal sampling.""" - n: tuple[int, ...] - if size is None: - n = () - elif isinstance(size, int): - n = (size,) - else: - n = size - - m = np.zeros((*n, k, k)) - a = np.zeros((*n, k)) - s = np.zeros((*n,)) - q = (*n, k + 1) + m = np.zeros((*size, k, k)) + a = np.zeros((*size, k)) + s = np.zeros((*size,)) + q = (*size, k + 1) j = 0 if k > 0 else None for i, x in enumerate(cov): @@ -86,7 +78,7 @@ def iternorm( c = x[..., 1:, np.newaxis] a = np.matmul(m[..., :j], c[..., k - j :, :]) a += np.matmul(m[..., j:], c[..., : k - j, :]) - a = a.reshape(*n, k) + a = a.reshape(*size, k) # next rolling index j = (j - 1) % k @@ -266,7 +258,7 @@ def generate_gaussian( y = np.zeros((n * (n + 1) // 2, ncorr), dtype=np.complex128) # generate the conditional normal distribution for iterative sampling - conditional_dist = iternorm(ncorr, cov, size=n) + conditional_dist = iternorm(ncorr, cov, size=(n,)) # sample the fields from the conditional distribution for j, a, s in conditional_dist: diff --git a/glass/shapes.py b/glass/shapes.py index 06319745..2a655c84 100644 --- a/glass/shapes.py +++ b/glass/shapes.py @@ -31,7 +31,7 @@ def triaxial_axis_ratio( zeta: float | npt.NDArray[np.float64], xi: float | npt.NDArray[np.float64], - size: tuple[int, ...] | None = None, + size: tuple[int, ...] = (), *, rng: np.random.Generator | None = None, ) -> npt.NDArray[np.float64]: @@ -69,7 +69,7 @@ def triaxial_axis_ratio( rng = np.random.default_rng() # get size from inputs if not explicitly provided - if size is None: + if not size: size = np.broadcast(zeta, xi).shape # draw random viewing angle (theta, phi) @@ -101,7 +101,7 @@ def ellipticity_ryden04( # noqa: PLR0913 sigma: float | npt.NDArray[np.float64], gamma: float | npt.NDArray[np.float64], sigma_gamma: float | npt.NDArray[np.float64], - size: int | tuple[int, ...] | None = None, + size: tuple[int, ...] = (), *, rng: np.random.Generator | None = None, ) -> npt.NDArray[np.float64]: @@ -143,7 +143,7 @@ def ellipticity_ryden04( # noqa: PLR0913 rng = np.random.default_rng() # default size if not given - if size is None: + if not size: size = np.broadcast(mu, sigma, gamma, sigma_gamma).shape # broadcast all inputs to output shape diff --git a/tests/test_shapes.py b/tests/test_shapes.py index c3da01e7..44d541f3 100644 --- a/tests/test_shapes.py +++ b/tests/test_shapes.py @@ -59,7 +59,7 @@ def test_ellipticity_ryden04(rng: np.random.Generator) -> None: # 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,)) assert np.shape(e) == (1000,) # explicit shape @@ -87,10 +87,10 @@ def test_ellipticity_ryden04(rng: np.random.Generator) -> None: # check that result is in the specified range - e = ellipticity_ryden04(0.0, 1.0, 0.222, 0.056, size=10) + e = ellipticity_ryden04(0.0, 1.0, 0.222, 0.056, size=(10,)) assert np.all((e.real >= -1.0) & (e.real <= 1.0)) - e = ellipticity_ryden04(0.0, 1.0, 0.0, 1.0, size=10) + e = ellipticity_ryden04(0.0, 1.0, 0.0, 1.0, size=(10,)) assert np.all((e.real >= -1.0) & (e.real <= 1.0)) From 6c47fcd23beba0f68e18292afcb628e7ab2d267f Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Thu, 24 Oct 2024 16:44:37 +0100 Subject: [PATCH 117/143] Change `extname` --- glass/user.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/glass/user.py b/glass/user.py index add56e84..9bb5bfd5 100644 --- a/glass/user.py +++ b/glass/user.py @@ -67,7 +67,7 @@ class _FitsWriter: Initialised with the fits object and extension name. """ - def __init__(self, fits: fitsio.FITS, ext: str | None = None) -> None: + def __init__(self, fits: fitsio.FITS, ext: str = "") -> None: """Create a new, uninitialised writer.""" self.fits = fits self.ext = ext @@ -78,9 +78,9 @@ def _append( names: list[str] | None = None, ) -> None: """Write the FITS file.""" - if self.ext is None or self.ext not in self.fits: + if self.ext not in self.fits: self.fits.write_table(data, names=names, extname=self.ext) - if self.ext is None: + if not self.ext: self.ext = self.fits[-1].get_extnum() else: hdu = self.fits[self.ext] From f021549dcc1bd47c2459234d14c970a1a0109f8f Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Thu, 24 Oct 2024 16:58:59 +0100 Subject: [PATCH 118/143] Fix `ext` --- glass/user.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glass/user.py b/glass/user.py index 9bb5bfd5..c8526510 100644 --- a/glass/user.py +++ b/glass/user.py @@ -113,7 +113,7 @@ def write( def write_catalog( filename: pathlib.Path, *, - ext: str | None = None, + ext: str = "", ) -> collections.abc.Generator[_FitsWriter]: """ Write a catalogue into a FITS file. From c0177c54566b1f510dbfd34df379c5898de5f921 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Thu, 24 Oct 2024 17:01:19 +0100 Subject: [PATCH 119/143] Change to `np.sum` --- glass/shells.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/glass/shells.py b/glass/shells.py index 33335d71..6ac04faa 100644 --- a/glass/shells.py +++ b/glass/shells.py @@ -686,7 +686,7 @@ def combine( z: npt.NDArray[np.float64], weights: npt.NDArray[np.float64], shells: list[RadialWindow], -) -> int: +) -> npt.NDArray[np.float64]: r""" Evaluate a linear combination of window functions. @@ -716,7 +716,7 @@ def combine( Find weights for a given function. """ - return sum( + return ( np.expand_dims(weight, -1) * np.interp( z, @@ -730,4 +730,4 @@ def combine( right=0.0, ) for shell, weight in zip(shells, weights) - ) + ).sum(axis=0) From 437bba3d7d81c3e9652108c528440f8c6d6b733f Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Mon, 28 Oct 2024 09:37:24 +0000 Subject: [PATCH 120/143] Change from `dtype` to `DTypeLike` --- glass/core/array.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glass/core/array.py b/glass/core/array.py index 036d9740..646b1896 100644 --- a/glass/core/array.py +++ b/glass/core/array.py @@ -111,7 +111,7 @@ def trapz_product( def cumtrapz( f: npt.NDArray[np.int_] | npt.NDArray[np.float64], x: npt.NDArray[np.int_] | npt.NDArray[np.float64], - dtype: type | None = None, + dtype: npt.DTypeLike | None = None, out: npt.NDArray[np.float64] | None = None, ) -> npt.NDArray[np.float64]: """Cumulative trapezoidal rule along last axis.""" From 6a869b450d04a36c99024abdd3e5fc20f008ae48 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Mon, 28 Oct 2024 09:23:06 +0000 Subject: [PATCH 121/143] Change to `not` --- glass/user.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glass/user.py b/glass/user.py index c8526510..000a1508 100644 --- a/glass/user.py +++ b/glass/user.py @@ -78,7 +78,7 @@ def _append( names: list[str] | None = None, ) -> None: """Write the FITS file.""" - if self.ext not in self.fits: + if not self.ext or self.ext not in self.fits: self.fits.write_table(data, names=names, extname=self.ext) if not self.ext: self.ext = self.fits[-1].get_extnum() From 397efe3709da42e2fb9f86e1678184de6cb8ff96 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Mon, 28 Oct 2024 09:43:02 +0000 Subject: [PATCH 122/143] Change from complex to float --- glass/fields.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/glass/fields.py b/glass/fields.py index 7bb7ec11..eafcc1a9 100644 --- a/glass/fields.py +++ b/glass/fields.py @@ -208,7 +208,7 @@ def generate_gaussian( *, ncorr: int | None = None, rng: np.random.Generator | None = None, -) -> collections.abc.Generator[npt.NDArray[np.complex128]]: +) -> collections.abc.Generator[npt.NDArray[np.float64]]: """ Sample Gaussian random fields from Cls iteratively. @@ -294,7 +294,7 @@ def generate_lognormal( *, ncorr: int | None = None, rng: np.random.Generator | None = None, -) -> collections.abc.Generator[npt.NDArray[np.complex128]]: +) -> collections.abc.Generator[npt.NDArray[np.float64]]: """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 From 5f3d17e52e6a75c8380ceeeeb6459b65a7962d0a Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Mon, 28 Oct 2024 09:56:03 +0000 Subject: [PATCH 123/143] Change `RadialWindow` to a `Sequence` --- glass/lensing.py | 6 ++++-- glass/shells.py | 12 +++++++----- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/glass/lensing.py b/glass/lensing.py index b4a6ae3a..05241377 100644 --- a/glass/lensing.py +++ b/glass/lensing.py @@ -38,6 +38,8 @@ import numpy.typing as npt if typing.TYPE_CHECKING: + import collections.abc + from cosmology import Cosmology from glass.shells import RadialWindow @@ -372,7 +374,7 @@ def wlens(self) -> float: def multi_plane_matrix( - shells: list[RadialWindow], + shells: collections.abc.Sequence[RadialWindow], cosmo: Cosmology, ) -> npt.NDArray[np.float64]: """Compute the matrix of lensing contributions from each shell.""" @@ -386,7 +388,7 @@ def multi_plane_matrix( def multi_plane_weights( weights: npt.NDArray[np.float64], - shells: list[RadialWindow], + shells: collections.abc.Sequence[RadialWindow], cosmo: Cosmology, ) -> npt.NDArray[np.float64]: """ diff --git a/glass/shells.py b/glass/shells.py index 6ac04faa..538148c6 100644 --- a/glass/shells.py +++ b/glass/shells.py @@ -53,6 +53,8 @@ from glass.core.array import ndinterp if typing.TYPE_CHECKING: + import collections.abc + from cosmology import Cosmology @@ -367,7 +369,7 @@ def restrict( def partition( z: npt.NDArray[np.float64], fz: npt.NDArray[np.float64], - shells: list[RadialWindow], + shells: collections.abc.Sequence[RadialWindow], *, method: str = "nnls", ) -> npt.NDArray[np.float64]: @@ -478,7 +480,7 @@ def partition( def partition_lstsq( z: npt.NDArray[np.float64], fz: npt.NDArray[np.float64], - shells: list[RadialWindow], + shells: collections.abc.Sequence[RadialWindow], *, sumtol: float = 0.01, ) -> npt.NDArray[np.float64]: @@ -541,7 +543,7 @@ def partition_lstsq( def partition_nnls( z: npt.NDArray[np.float64], fz: npt.NDArray[np.float64], - shells: list[RadialWindow], + shells: collections.abc.Sequence[RadialWindow], *, sumtol: float = 0.01, ) -> npt.NDArray[np.float64]: @@ -630,7 +632,7 @@ def partition_nnls( def partition_restrict( z: npt.NDArray[np.float64], fz: npt.NDArray[np.float64], - shells: list[RadialWindow], + shells: collections.abc.Sequence[RadialWindow], ) -> npt.NDArray[np.float64]: """Partition by restriction and integration.""" part = np.empty((len(shells),) + np.shape(fz)[:-1]) @@ -685,7 +687,7 @@ def distance_grid( def combine( z: npt.NDArray[np.float64], weights: npt.NDArray[np.float64], - shells: list[RadialWindow], + shells: collections.abc.Sequence[RadialWindow], ) -> npt.NDArray[np.float64]: r""" Evaluate a linear combination of window functions. From 5a16b3681c5fdc16106664609128fe2e3e9e5230 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Mon, 28 Oct 2024 09:57:22 +0000 Subject: [PATCH 124/143] `mu` and `sigma` also floats --- glass/observations.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/glass/observations.py b/glass/observations.py index c878c683..f6af62a7 100644 --- a/glass/observations.py +++ b/glass/observations.py @@ -82,8 +82,8 @@ def vmap_galactic_ecliptic( def gaussian_nz( z: npt.NDArray[np.float64], - mean: npt.NDArray[np.float64], - sigma: npt.NDArray[np.float64], + mean: float | npt.NDArray[np.float64], + sigma: float | npt.NDArray[np.float64], *, norm: npt.NDArray[np.float64] | None = None, ) -> npt.NDArray[np.float64]: From ea4a36b04e55ddbf0260a513305d0623e5c29735 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Mon, 28 Oct 2024 10:41:01 +0000 Subject: [PATCH 125/143] Fix return types --- glass/fields.py | 38 +++++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/glass/fields.py b/glass/fields.py index eafcc1a9..179e2e16 100644 --- a/glass/fields.py +++ b/glass/fields.py @@ -95,7 +95,9 @@ def iternorm( def cls2cov( - cls: npt.NDArray[np.float64], + cls: collections.abc.Sequence[ + npt.NDArray[np.float64] | collections.abc.Sequence[float] + ], nl: int, nf: int, nc: int, @@ -131,7 +133,9 @@ def multalm( def transform_cls( - cls: npt.NDArray[np.float64], + cls: collections.abc.Sequence[ + npt.NDArray[np.float64] | collections.abc.Sequence[float] + ], tfm: str | typing.Callable[[npt.NDArray[np.float64]], npt.NDArray[np.float64]], pars: tuple[typing.Any, ...] = (), ) -> list[list[float] | npt.NDArray[np.float64]]: @@ -153,12 +157,14 @@ def transform_cls( def discretized_cls( - cls: list[list[float]] | npt.NDArray[np.float64], + cls: collections.abc.Sequence[ + npt.NDArray[np.float64] | collections.abc.Sequence[float] + ], *, lmax: int | None = None, ncorr: int | None = None, nside: int | None = None, -) -> list[list[float] | npt.NDArray[np.float64]]: +) -> list[npt.NDArray[np.float64] | collections.abc.Sequence[float]]: """ Apply discretisation effects to angular power spectra. @@ -184,7 +190,7 @@ def discretized_cls( gls = [] for cl in cls: - if cl is not None and len(cl) > 0: + if len(cl) > 0: if lmax is not None: cl = cl[: lmax + 1] # noqa: PLW2901 if nside is not None: @@ -195,7 +201,9 @@ def discretized_cls( def lognormal_gls( - cls: npt.NDArray[np.float64], + cls: collections.abc.Sequence[ + npt.NDArray[np.float64] | collections.abc.Sequence[float] + ], shift: float = 1.0, ) -> list[list[float] | npt.NDArray[np.float64]]: """Compute Gaussian Cls for a lognormal random field.""" @@ -203,7 +211,9 @@ def lognormal_gls( def generate_gaussian( - gls: npt.NDArray[np.float64], + gls: collections.abc.Sequence[ + npt.NDArray[np.float64] | collections.abc.Sequence[float] + ], nside: int, *, ncorr: int | None = None, @@ -288,7 +298,9 @@ def generate_gaussian( def generate_lognormal( - gls: npt.NDArray[np.float64], + gls: collections.abc.Sequence[ + npt.NDArray[np.float64] | collections.abc.Sequence[float] + ], nside: int, shift: float = 1.0, *, @@ -317,11 +329,13 @@ def generate_lognormal( def getcl( - cls: npt.NDArray[np.float64], + cls: collections.abc.Sequence[ + npt.NDArray[np.float64] | collections.abc.Sequence[float] + ], i: int, j: int, lmax: int | None = None, -) -> npt.NDArray[np.float64]: +) -> npt.NDArray[np.float64] | collections.abc.Sequence[float]: """ Return a specific angular power spectrum from an array. @@ -352,7 +366,9 @@ def getcl( def effective_cls( - cls: npt.NDArray[np.float64], + cls: collections.abc.Sequence[ + npt.NDArray[np.float64] | collections.abc.Sequence[float] + ], weights1: npt.NDArray[np.float64], weights2: npt.NDArray[np.float64] | None = None, *, From 43b20d0ee117fea1350811850217d1a9264b224a Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Mon, 28 Oct 2024 10:53:57 +0000 Subject: [PATCH 126/143] Change test to satisfy `mypy` --- tests/test_fields.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/test_fields.py b/tests/test_fields.py index ae58bde0..46b32843 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -5,8 +5,12 @@ def test_getcl() -> None: # make a mock Cls array with the index pairs as entries - cls = np.array([{i, j} for i in range(10) for j in range(i, -1, -1)]) + cls = [ + np.array([i, j], dtype=np.float64) for i in range(10) for j in range(i, -1, -1) + ] # make sure indices are retrieved correctly for i in range(10): for j in range(10): - assert getcl(cls, i, j) == {i, j} + result = getcl(cls, i, j) + expected = np.array([min(i, j), max(i, j)], dtype=np.float64) + np.testing.assert_array_equal(np.sort(result), expected) From 938782c3f010198caefc8a68d4807db4f92d678a Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Mon, 28 Oct 2024 11:01:41 +0000 Subject: [PATCH 127/143] Fix write/load for None type --- glass/user.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/glass/user.py b/glass/user.py index 000a1508..bb9c04ad 100644 --- a/glass/user.py +++ b/glass/user.py @@ -34,7 +34,12 @@ import fitsio -def save_cls(filename: str, cls: list[npt.NDArray[np.float64] | None]) -> None: +def save_cls( + filename: str, + cls: collections.abc.Sequence[ + npt.NDArray[np.float64] | collections.abc.Sequence[float] + ], +) -> None: """ Save a list of Cls to file. @@ -42,12 +47,14 @@ def save_cls(filename: str, cls: list[npt.NDArray[np.float64] | 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]]) - values = np.concatenate([cl for cl in cls if cl is not None]) + split = np.cumsum([len(cl) for cl in cls[:-1]]) + values = np.concatenate(cls) np.savez(filename, values=values, split=split) -def load_cls(filename: str) -> list[npt.NDArray[np.float64]]: +def load_cls( + filename: str, +) -> list[npt.NDArray[np.float64] | collections.abc.Sequence[float]]: """ Load a list of Cls from file. From 152c214525b3c461d122c3f10fbe69fdaac830d6 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Mon, 28 Oct 2024 11:09:04 +0000 Subject: [PATCH 128/143] Restore int --- glass/fields.py | 16 +++++++++------- glass/shapes.py | 4 ++-- tests/test_shapes.py | 8 ++++---- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/glass/fields.py b/glass/fields.py index 179e2e16..ed9da1a3 100644 --- a/glass/fields.py +++ b/glass/fields.py @@ -41,15 +41,17 @@ def iternorm( k: int, cov: collections.abc.Iterable[npt.NDArray[np.float64]], - size: tuple[int, ...] = (), + size: int | tuple[int, ...] = (), ) -> collections.abc.Generator[ tuple[int | None, npt.NDArray[np.float64], npt.NDArray[np.float64]] ]: """Return the vector a and variance sigma^2 for iterative normal sampling.""" - m = np.zeros((*size, k, k)) - a = np.zeros((*size, k)) - s = np.zeros((*size,)) - q = (*size, k + 1) + n = (size,) if isinstance(size, int) else size + + m = np.zeros((*n, k, k)) + a = np.zeros((*n, k)) + s = np.zeros((*n,)) + q = (*n, k + 1) j = 0 if k > 0 else None for i, x in enumerate(cov): @@ -78,7 +80,7 @@ def iternorm( c = x[..., 1:, np.newaxis] a = np.matmul(m[..., :j], c[..., k - j :, :]) a += np.matmul(m[..., j:], c[..., : k - j, :]) - a = a.reshape(*size, k) + a = a.reshape(*n, k) # next rolling index j = (j - 1) % k @@ -268,7 +270,7 @@ def generate_gaussian( y = np.zeros((n * (n + 1) // 2, ncorr), dtype=np.complex128) # generate the conditional normal distribution for iterative sampling - conditional_dist = iternorm(ncorr, cov, size=(n,)) + conditional_dist = iternorm(ncorr, cov, size=n) # sample the fields from the conditional distribution for j, a, s in conditional_dist: diff --git a/glass/shapes.py b/glass/shapes.py index 2a655c84..b2c14f47 100644 --- a/glass/shapes.py +++ b/glass/shapes.py @@ -31,7 +31,7 @@ def triaxial_axis_ratio( zeta: float | npt.NDArray[np.float64], xi: float | npt.NDArray[np.float64], - size: tuple[int, ...] = (), + size: int | tuple[int, ...] = (), *, rng: np.random.Generator | None = None, ) -> npt.NDArray[np.float64]: @@ -101,7 +101,7 @@ def ellipticity_ryden04( # noqa: PLR0913 sigma: float | npt.NDArray[np.float64], gamma: float | npt.NDArray[np.float64], sigma_gamma: float | npt.NDArray[np.float64], - size: tuple[int, ...] = (), + size: int | tuple[int, ...] = (), *, rng: np.random.Generator | None = None, ) -> npt.NDArray[np.float64]: diff --git a/tests/test_shapes.py b/tests/test_shapes.py index 44d541f3..e965fdce 100644 --- a/tests/test_shapes.py +++ b/tests/test_shapes.py @@ -17,7 +17,7 @@ def test_triaxial_axis_ratio(rng: np.random.Generator) -> None: # many axis ratios - q = triaxial_axis_ratio(0.8, 0.4, size=(1000,)) + q = triaxial_axis_ratio(0.8, 0.4, size=1000) assert np.shape(q) == (1000,) # explicit shape @@ -59,7 +59,7 @@ def test_ellipticity_ryden04(rng: np.random.Generator) -> None: # 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) assert np.shape(e) == (1000,) # explicit shape @@ -87,10 +87,10 @@ def test_ellipticity_ryden04(rng: np.random.Generator) -> None: # check that result is in the specified range - e = ellipticity_ryden04(0.0, 1.0, 0.222, 0.056, size=(10,)) + e = ellipticity_ryden04(0.0, 1.0, 0.222, 0.056, size=10) assert np.all((e.real >= -1.0) & (e.real <= 1.0)) - e = ellipticity_ryden04(0.0, 1.0, 0.0, 1.0, size=(10,)) + e = ellipticity_ryden04(0.0, 1.0, 0.0, 1.0, size=10) assert np.all((e.real >= -1.0) & (e.real <= 1.0)) From 0dca63bef44d0f5152ed2d8d6a78280d62232617 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Wed, 30 Oct 2024 14:40:43 +0000 Subject: [PATCH 129/143] Fix types based on NumPy v2 --- glass/core/array.py | 1 + glass/lensing.py | 6 +++--- glass/shells.py | 31 +++++++++++++++++-------------- 3 files changed, 21 insertions(+), 17 deletions(-) diff --git a/glass/core/array.py b/glass/core/array.py index 646b1896..0c6bdd03 100644 --- a/glass/core/array.py +++ b/glass/core/array.py @@ -92,6 +92,7 @@ def trapz_product( axis: int = -1, ) -> npt.NDArray[np.float64]: """Trapezoidal rule for a product of functions.""" + x: npt.NDArray[np.float64] x, _ = f for x_, _ in ff: x = np.union1d( diff --git a/glass/lensing.py b/glass/lensing.py index 05241377..f1d876c1 100644 --- a/glass/lensing.py +++ b/glass/lensing.py @@ -278,7 +278,7 @@ def __init__(self, cosmo: Cosmology) -> None: self.z2: float = 0.0 self.z3: float = 0.0 self.x3: float = 0.0 - self.w3: float = 0.0 + self.w3: npt.NDArray[np.float64] | float = 0.0 self.r23: float = 1.0 self.delta3: npt.NDArray[np.float64] = np.array(0.0) self.kappa2: npt.NDArray[np.float64] | None = None @@ -308,7 +308,7 @@ def add_plane( self, delta: npt.NDArray[np.float64], zsrc: float, - wlens: float = 1.0, + wlens: float | npt.NDArray[np.float64] = 1.0, ) -> None: """Add a mass plane at redshift ``zsrc`` to the convergence.""" if zsrc <= self.z3: @@ -368,7 +368,7 @@ def delta(self) -> npt.NDArray[np.float64]: return self.delta3 @property - def wlens(self) -> float: + def wlens(self) -> float | npt.NDArray[np.float64]: """The weight of the current matter plane.""" return self.w3 diff --git a/glass/shells.py b/glass/shells.py index 538148c6..4d46ce65 100644 --- a/glass/shells.py +++ b/glass/shells.py @@ -718,18 +718,21 @@ def combine( Find weights for a given function. """ - return ( - np.expand_dims(weight, -1) - * np.interp( - z, - shell.za, - shell.wa - / np.trapz( # type: ignore[attr-defined] - shell.wa, + return np.sum( + [ + np.expand_dims(weight, -1) + * np.interp( + z, shell.za, - ), - left=0.0, - right=0.0, - ) - for shell, weight in zip(shells, weights) - ).sum(axis=0) + shell.wa + / np.trapz( # type: ignore[attr-defined] + shell.wa, + shell.za, + ), + left=0.0, + right=0.0, + ) + for shell, weight in zip(shells, weights) + ], + axis=0, + ) From 7c30d017cb4e462ff1646fed17f3269bcc9d7f8e Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Wed, 30 Oct 2024 15:40:40 +0000 Subject: [PATCH 130/143] Disable `ruff` `ANN` rules --- pyproject.toml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 33968c30..ac5656a4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -133,10 +133,6 @@ src = [ "glass", ] lint.ignore = [ - "ANN001", # TODO: missing-type-function-argument - "ANN002", # TODO: missing-type-args - "ANN003", # TODO: missing-type-kwargs - "ANN201", # TODO: missing-return-type-undocumented-public-function "COM812", # missing-trailing-comma (ruff-format recommended) "COM819", # prohibited-trailing-comma (ruff-format recommended) "D203", # one-blank-line-before-class From 4d6bcb4a2c6f78dd6b3c4a26018cdea1d0fb1114 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Wed, 30 Oct 2024 16:31:13 +0000 Subject: [PATCH 131/143] Disable more `ANN` rules in `tests` --- pyproject.toml | 3 --- 1 file changed, 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index ac5656a4..e1830fc0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -178,9 +178,6 @@ lint.per-file-ignores = {"__init__.py" = [ ], "noxfile.py" = [ "T201", # print ], "tests*" = [ - "ANN001", # TODO: missing-type-function-argument - "ANN201", # TODO: issing-return-type-undocumented-public-function - "ANN202", # TODO: missing-return-type-private-function "D100", # undocumented-public-module "D103", # TODO: undocumented-public-function "D104", # undocumented-public-package From 65cf76e9582eb4749f153923b97b680e29933bf6 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Thu, 31 Oct 2024 16:27:30 +0000 Subject: [PATCH 132/143] Add overloading for `from_convergence` --- glass/lensing.py | 115 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 113 insertions(+), 2 deletions(-) diff --git a/glass/lensing.py b/glass/lensing.py index f1d876c1..a59e0cd6 100644 --- a/glass/lensing.py +++ b/glass/lensing.py @@ -45,6 +45,117 @@ from glass.shells import RadialWindow +@typing.overload +def from_convergence( + kappa: npt.NDArray[np.float64], + lmax: int | None = None, + *, + potential: typing.Literal[True] = True, + deflection: typing.Literal[False] = False, + shear: typing.Literal[False] = False, + discretized: bool = True, +) -> tuple[npt.NDArray[np.float64]]: + # returns psi + ... + + +@typing.overload +def from_convergence( + kappa: npt.NDArray[np.float64], + lmax: int | None = None, + *, + potential: typing.Literal[False] = False, + deflection: typing.Literal[True] = True, + shear: typing.Literal[False] = False, + discretized: bool = True, +) -> tuple[npt.NDArray[np.complex128]]: + # returns alpha + ... + + +@typing.overload +def from_convergence( + kappa: npt.NDArray[np.float64], + lmax: int | None = None, + *, + potential: typing.Literal[False] = False, + deflection: typing.Literal[False] = False, + shear: typing.Literal[True] = True, + discretized: bool = True, +) -> tuple[npt.NDArray[np.complex128]]: + # returns gamma + ... + + +@typing.overload +def from_convergence( + kappa: npt.NDArray[np.float64], + lmax: int | None = None, + *, + potential: typing.Literal[True] = True, + deflection: typing.Literal[True] = True, + shear: typing.Literal[False] = False, + discretized: bool = True, +) -> tuple[ + npt.NDArray[np.float64], + npt.NDArray[np.complex128], +]: + # returns psi, alpha + ... + + +@typing.overload +def from_convergence( + kappa: npt.NDArray[np.float64], + lmax: int | None = None, + *, + potential: typing.Literal[True] = True, + deflection: typing.Literal[False] = False, + shear: typing.Literal[True] = True, + discretized: bool = True, +) -> tuple[ + npt.NDArray[np.float64], + npt.NDArray[np.complex128], +]: + # returns psi, gamma + ... + + +@typing.overload +def from_convergence( + kappa: npt.NDArray[np.float64], + lmax: int | None = None, + *, + potential: typing.Literal[False] = False, + deflection: typing.Literal[True] = True, + shear: typing.Literal[True] = True, + discretized: bool = True, +) -> tuple[ + npt.NDArray[np.complex128], + npt.NDArray[np.complex128], +]: + # returns alpha, gamma + ... + + +@typing.overload +def from_convergence( + kappa: npt.NDArray[np.float64], + lmax: int | None = None, + *, + potential: typing.Literal[True] = True, + deflection: typing.Literal[True] = True, + shear: typing.Literal[True] = True, + discretized: bool = True, +) -> tuple[ + npt.NDArray[np.float64], + npt.NDArray[np.complex128], + npt.NDArray[np.complex128], +]: + # returns psi, alpha, gamma + ... + + def from_convergence( # noqa: PLR0913 kappa: npt.NDArray[np.float64], lmax: int | None = None, @@ -53,7 +164,7 @@ def from_convergence( # noqa: PLR0913 deflection: bool = False, shear: bool = False, discretized: bool = True, -) -> tuple[npt.NDArray[np.float64], ...]: +) -> tuple[npt.NDArray[np.float64] | npt.NDArray[np.complex128], ...]: r""" Compute other weak lensing maps from the convergence. @@ -171,7 +282,7 @@ def from_convergence( # noqa: PLR0913 l = np.arange(lmax + 1) # noqa: E741 # this tuple will be returned - results: tuple[npt.NDArray[np.float64], ...] = () + results: tuple[npt.NDArray[np.float64] | npt.NDArray[np.complex128], ...] = () # convert convergence to potential fl = np.divide(-2, l * (l + 1), where=(l > 0), out=np.zeros(lmax + 1)) From 4961d2e999ad8cdb29eb21caebf26fce8cbbd357 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Wed, 6 Nov 2024 11:26:00 +0000 Subject: [PATCH 133/143] Remove blame file --- .git-blame-ignore-revs | 1 - 1 file changed, 1 deletion(-) diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index 134713cf..e98ceab3 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -4,4 +4,3 @@ b42067f6776dcd763827000d585a88e071b78af3 f9bac62f497a7288aa71fd4dbd948945c37f854e # applied ruff-linting - https://github.com/glass-dev/glass/pull/232 e58d8616c03b8447aba90996905a98b42f18ba0a -# added static typing - https://github.com/glass-dev/glass/pull/368 From e96403f9056d71c3b359a5118fe0e6b70f1ba72f Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Wed, 6 Nov 2024 11:33:31 +0000 Subject: [PATCH 134/143] Turn off global `warn_return_any` setting --- glass/core/array.py | 2 +- glass/galaxies.py | 2 +- glass/lensing.py | 4 ++-- glass/observations.py | 8 ++++---- glass/points.py | 2 +- glass/shapes.py | 4 ++-- glass/shells.py | 12 ++++++------ pyproject.toml | 1 - 8 files changed, 17 insertions(+), 18 deletions(-) diff --git a/glass/core/array.py b/glass/core/array.py index 0c6bdd03..2efd32f0 100644 --- a/glass/core/array.py +++ b/glass/core/array.py @@ -102,7 +102,7 @@ def trapz_product( y = np.interp(x, *f) for f_ in ff: y *= np.interp(x, *f_) - return np.trapz( # type: ignore[attr-defined] + return np.trapz( # type: ignore[attr-defined, no-any-return] y, x, axis=axis, diff --git a/glass/galaxies.py b/glass/galaxies.py index 15e8b73a..16c26c9a 100644 --- a/glass/galaxies.py +++ b/glass/galaxies.py @@ -393,4 +393,4 @@ def kappa_ia_nla( # noqa: PLR0913 prefactor * inverse_linear_growth * redshift_dependence * luminosity_dependence ) - return delta * f_nla + return delta * f_nla # type: ignore[no-any-return] diff --git a/glass/lensing.py b/glass/lensing.py index f1d876c1..bb9e8c20 100644 --- a/glass/lensing.py +++ b/glass/lensing.py @@ -264,7 +264,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: @@ -423,7 +423,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] def deflect( diff --git a/glass/observations.py b/glass/observations.py index f6af62a7..bd09a92f 100644 --- a/glass/observations.py +++ b/glass/observations.py @@ -77,7 +77,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( @@ -123,7 +123,7 @@ def gaussian_nz( if norm is not None: nz *= norm - return nz + return nz # type: ignore[no-any-return] def smail_nz( @@ -186,7 +186,7 @@ def smail_nz( if norm is not None: pz *= norm - return pz + return pz # type: ignore[no-any-return] def fixed_zbins( @@ -323,4 +323,4 @@ def tomo_nz_gausserr( binned_nz /= 1 + erf(z / sz) 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 4c9434a1..7c0a5c2b 100644 --- a/glass/points.py +++ b/glass/points.py @@ -86,7 +86,7 @@ def effective_bias( w.wa, w.za, ) - 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( diff --git a/glass/shapes.py b/glass/shapes.py index b2c14f47..2f62f8c6 100644 --- a/glass/shapes.py +++ b/glass/shapes.py @@ -91,7 +91,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)), ) @@ -174,7 +174,7 @@ def ellipticity_ryden04( # noqa: PLR0913 e *= (1 - q) / (1 + q) # 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 4d46ce65..108f58fc 100644 --- a/glass/shells.py +++ b/glass/shells.py @@ -63,7 +63,7 @@ def distance_weight( cosmo: Cosmology, ) -> npt.NDArray[np.float64]: """Uniform weight in comoving distance.""" - return 1 / cosmo.ef(z) + return 1 / cosmo.ef(z) # type: ignore[no-any-return] def volume_weight( @@ -71,7 +71,7 @@ def volume_weight( cosmo: Cosmology, ) -> npt.NDArray[np.float64]: """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( @@ -79,7 +79,7 @@ def density_weight( cosmo: Cosmology, ) -> npt.NDArray[np.float64]: """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(typing.NamedTuple): @@ -474,7 +474,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( @@ -681,7 +681,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( @@ -718,7 +718,7 @@ def combine( Find weights for a given function. """ - return np.sum( + return np.sum( # type: ignore[no-any-return] [ np.expand_dims(weight, -1) * np.interp( diff --git a/pyproject.toml b/pyproject.toml index 6c9b45b3..87788927 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -105,7 +105,6 @@ plugins = [ "numpy.typing.mypy_plugin", ] strict = true -warn_return_any = false warn_unreachable = true [tool.pytest.ini_options] From 515ed8c66afce56e635e617933487e0366012b45 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Wed, 6 Nov 2024 14:34:40 +0000 Subject: [PATCH 135/143] Remove array part of floats --- glass/lensing.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/glass/lensing.py b/glass/lensing.py index bb9e8c20..357e7214 100644 --- a/glass/lensing.py +++ b/glass/lensing.py @@ -278,7 +278,7 @@ def __init__(self, cosmo: Cosmology) -> None: self.z2: float = 0.0 self.z3: float = 0.0 self.x3: float = 0.0 - self.w3: npt.NDArray[np.float64] | float = 0.0 + self.w3: float = 0.0 self.r23: float = 1.0 self.delta3: npt.NDArray[np.float64] = np.array(0.0) self.kappa2: npt.NDArray[np.float64] | None = None @@ -308,7 +308,7 @@ def add_plane( self, delta: npt.NDArray[np.float64], zsrc: float, - wlens: float | npt.NDArray[np.float64] = 1.0, + wlens: float = 1.0, ) -> None: """Add a mass plane at redshift ``zsrc`` to the convergence.""" if zsrc <= self.z3: @@ -368,7 +368,7 @@ def delta(self) -> npt.NDArray[np.float64]: return self.delta3 @property - def wlens(self) -> float | npt.NDArray[np.float64]: + def wlens(self) -> float: """The weight of the current matter plane.""" return self.w3 From 391a27a98a1cac4085b948f202a03742824f0106 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Wed, 6 Nov 2024 14:39:49 +0000 Subject: [PATCH 136/143] Explicitly convert to float --- glass/lensing.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/glass/lensing.py b/glass/lensing.py index 357e7214..4d8b19e6 100644 --- a/glass/lensing.py +++ b/glass/lensing.py @@ -293,13 +293,16 @@ def add_window(self, delta: npt.NDArray[np.float64], w: RadialWindow) -> None: """ zsrc = w.zeff - lens_weight = np.trapz( # type: ignore[attr-defined] - w.wa, - w.za, - ) / np.interp( - zsrc, - w.za, - w.wa, + lens_weight = float( + np.trapz( # type: ignore[attr-defined] + w.wa, + w.za, + ) + / np.interp( + zsrc, + w.za, + w.wa, + ) ) self.add_plane(delta, zsrc, lens_weight) From 7af8b514ae1088eedf9b71a0666ddd9d7068aa75 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Wed, 6 Nov 2024 14:47:04 +0000 Subject: [PATCH 137/143] Restore `ext` is `None` --- glass/user.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/glass/user.py b/glass/user.py index bb9c04ad..11edd66c 100644 --- a/glass/user.py +++ b/glass/user.py @@ -74,7 +74,7 @@ class _FitsWriter: Initialised with the fits object and extension name. """ - def __init__(self, fits: fitsio.FITS, ext: str = "") -> None: + def __init__(self, fits: fitsio.FITS, ext: str | None = None) -> None: """Create a new, uninitialised writer.""" self.fits = fits self.ext = ext @@ -85,9 +85,9 @@ def _append( names: list[str] | None = None, ) -> None: """Write the FITS file.""" - if not self.ext or self.ext not in self.fits: + if self.ext is None or self.ext not in self.fits: self.fits.write_table(data, names=names, extname=self.ext) - if not self.ext: + if self.ext is None: self.ext = self.fits[-1].get_extnum() else: hdu = self.fits[self.ext] @@ -120,7 +120,7 @@ def write( def write_catalog( filename: pathlib.Path, *, - ext: str = "", + ext: str | None = None, ) -> collections.abc.Generator[_FitsWriter]: """ Write a catalogue into a FITS file. From b2df82c76860a817fdf2a63e1190a6cd76d0e274 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Wed, 6 Nov 2024 14:59:15 +0000 Subject: [PATCH 138/143] Return none to triaxial --- glass/shapes.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/glass/shapes.py b/glass/shapes.py index 2f62f8c6..72e26f68 100644 --- a/glass/shapes.py +++ b/glass/shapes.py @@ -31,7 +31,7 @@ def triaxial_axis_ratio( zeta: float | npt.NDArray[np.float64], xi: float | npt.NDArray[np.float64], - size: int | tuple[int, ...] = (), + size: int | tuple[int, ...] | None = None, *, rng: np.random.Generator | None = None, ) -> npt.NDArray[np.float64]: @@ -69,7 +69,7 @@ def triaxial_axis_ratio( rng = np.random.default_rng() # get size from inputs if not explicitly provided - if not size: + if size is None: size = np.broadcast(zeta, xi).shape # draw random viewing angle (theta, phi) From 6ea68e0d62504e3bd9474e4d2dcc1e35aebb25d2 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Wed, 6 Nov 2024 15:01:50 +0000 Subject: [PATCH 139/143] Restore size --- glass/shapes.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/glass/shapes.py b/glass/shapes.py index 72e26f68..25dc6f45 100644 --- a/glass/shapes.py +++ b/glass/shapes.py @@ -101,7 +101,7 @@ def ellipticity_ryden04( # noqa: PLR0913 sigma: float | npt.NDArray[np.float64], gamma: float | npt.NDArray[np.float64], sigma_gamma: float | npt.NDArray[np.float64], - size: int | tuple[int, ...] = (), + size: int | tuple[int, ...] | None = None, *, rng: np.random.Generator | None = None, ) -> npt.NDArray[np.float64]: @@ -143,7 +143,7 @@ def ellipticity_ryden04( # noqa: PLR0913 rng = np.random.default_rng() # default size if not given - if not size: + if size is None: size = np.broadcast(mu, sigma, gamma, sigma_gamma).shape # broadcast all inputs to output shape From dc5bfdfebf5ad8ac68e5e8f92fbbd78def50288d Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Wed, 6 Nov 2024 15:12:42 +0000 Subject: [PATCH 140/143] Restore `WeightFunc` --- glass/shells.py | 30 ++++++++---------------------- 1 file changed, 8 insertions(+), 22 deletions(-) diff --git a/glass/shells.py b/glass/shells.py index 108f58fc..cab305c3 100644 --- a/glass/shells.py +++ b/glass/shells.py @@ -57,6 +57,10 @@ from cosmology import Cosmology +WeightFunc = typing.Callable[ + [list[float] | npt.NDArray[np.float64]], npt.NDArray[np.float64] +] + def distance_weight( z: npt.NDArray[np.float64], @@ -134,11 +138,7 @@ class RadialWindow(typing.NamedTuple): def tophat_windows( zbins: npt.NDArray[np.float64], dz: float = 1e-3, - weight: typing.Callable[ - [list[float] | npt.NDArray[np.float64]], - npt.NDArray[np.float64], - ] - | None = None, + weight: WeightFunc | None = None, ) -> list[RadialWindow]: """ Tophat window functions from the given redshift bin edges. @@ -179,13 +179,7 @@ def tophat_windows( stacklevel=2, ) - wht: ( - npt.NDArray[np.float64] - | typing.Callable[ - [list[float] | npt.NDArray[np.float64]], - npt.NDArray[np.float64], - ] - ) + wht: WeightFunc wht = weight if weight is not None else np.ones_like ws = [] for zmin, zmax in zip(zbins, zbins[1:]): @@ -206,11 +200,7 @@ def tophat_windows( def linear_windows( zgrid: npt.NDArray[np.float64], dz: float = 1e-3, - weight: typing.Callable[ - [list[float] | npt.NDArray[np.float64]], - npt.NDArray[np.float64], - ] - | None = None, + weight: WeightFunc | None = None, ) -> list[RadialWindow]: """ Linear interpolation window functions. @@ -267,11 +257,7 @@ def linear_windows( def cubic_windows( zgrid: npt.NDArray[np.float64], dz: float = 1e-3, - weight: typing.Callable[ - [list[float] | npt.NDArray[np.float64]], - npt.NDArray[np.float64], - ] - | None = None, + weight: WeightFunc | None = None, ) -> list[RadialWindow]: """ Cubic interpolation window functions. From de9cdc98c64b1b210db8c19e2b4bb8e5266dfbec Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Wed, 6 Nov 2024 15:23:22 +0000 Subject: [PATCH 141/143] Restore `ArrayLike1D` --- glass/core/array.py | 7 +++++-- glass/shells.py | 18 ++++++++---------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/glass/core/array.py b/glass/core/array.py index 2efd32f0..c963c35b 100644 --- a/glass/core/array.py +++ b/glass/core/array.py @@ -8,6 +8,9 @@ import numpy as np import numpy.typing as npt +if typing.TYPE_CHECKING: + import collections.abc + def broadcast_first( *arrays: npt.NDArray[np.float64], @@ -65,8 +68,8 @@ def broadcast_leading_axes( def ndinterp( # noqa: PLR0913 x: float | npt.NDArray[np.float64], - xp: npt.NDArray[np.float64], - fp: npt.NDArray[np.float64], + xp: collections.abc.Sequence[float] | npt.NDArray[np.float64], + fp: collections.abc.Sequence[float] | npt.NDArray[np.float64], axis: int = -1, left: float | None = None, right: float | None = None, diff --git a/glass/shells.py b/glass/shells.py index cab305c3..479b589f 100644 --- a/glass/shells.py +++ b/glass/shells.py @@ -44,6 +44,7 @@ from __future__ import annotations +import collections.abc import typing import warnings @@ -53,13 +54,10 @@ from glass.core.array import ndinterp if typing.TYPE_CHECKING: - import collections.abc - from cosmology import Cosmology -WeightFunc = typing.Callable[ - [list[float] | npt.NDArray[np.float64]], npt.NDArray[np.float64] -] +ArrayLike1D = typing.Union[collections.abc.Sequence[float], npt.NDArray[np.float64]] +WeightFunc = typing.Callable[[ArrayLike1D], npt.NDArray[np.float64]] def distance_weight( @@ -136,7 +134,7 @@ class RadialWindow(typing.NamedTuple): def tophat_windows( - zbins: npt.NDArray[np.float64], + zbins: ArrayLike1D, dz: float = 1e-3, weight: WeightFunc | None = None, ) -> list[RadialWindow]: @@ -198,7 +196,7 @@ def tophat_windows( def linear_windows( - zgrid: npt.NDArray[np.float64], + zgrid: ArrayLike1D, dz: float = 1e-3, weight: WeightFunc | None = None, ) -> list[RadialWindow]: @@ -255,7 +253,7 @@ def linear_windows( def cubic_windows( - zgrid: npt.NDArray[np.float64], + zgrid: ArrayLike1D, dz: float = 1e-3, weight: WeightFunc | None = None, ) -> list[RadialWindow]: @@ -313,8 +311,8 @@ def cubic_windows( def restrict( - z: npt.NDArray[np.float64], - f: npt.NDArray[np.float64], + z: ArrayLike1D, + f: ArrayLike1D, w: RadialWindow, ) -> tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]]: """ From 882e7ecd3113105e08ca5f0411432afbaaefbc6a Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Wed, 6 Nov 2024 15:34:36 +0000 Subject: [PATCH 142/143] Restore Cls --- glass/fields.py | 36 +++++++++++++----------------------- 1 file changed, 13 insertions(+), 23 deletions(-) diff --git a/glass/fields.py b/glass/fields.py index ed9da1a3..613a939e 100644 --- a/glass/fields.py +++ b/glass/fields.py @@ -26,6 +26,7 @@ from __future__ import annotations +import collections.abc import typing import warnings @@ -34,8 +35,9 @@ import numpy.typing as npt from gaussiancl import gaussiancl -if typing.TYPE_CHECKING: - import collections.abc +Cls = collections.abc.Sequence[ + typing.Union[npt.NDArray[np.float64], collections.abc.Sequence[float]] +] def iternorm( @@ -97,9 +99,7 @@ def iternorm( def cls2cov( - cls: collections.abc.Sequence[ - npt.NDArray[np.float64] | collections.abc.Sequence[float] - ], + cls: Cls, nl: int, nf: int, nc: int, @@ -135,12 +135,10 @@ def multalm( def transform_cls( - cls: collections.abc.Sequence[ - npt.NDArray[np.float64] | collections.abc.Sequence[float] - ], + cls: Cls, tfm: str | typing.Callable[[npt.NDArray[np.float64]], npt.NDArray[np.float64]], pars: tuple[typing.Any, ...] = (), -) -> list[list[float] | npt.NDArray[np.float64]]: +) -> Cls: """Transform Cls to Gaussian Cls.""" gls = [] for cl in cls: @@ -159,14 +157,12 @@ def transform_cls( def discretized_cls( - cls: collections.abc.Sequence[ - npt.NDArray[np.float64] | collections.abc.Sequence[float] - ], + cls: Cls, *, lmax: int | None = None, ncorr: int | None = None, nside: int | None = None, -) -> list[npt.NDArray[np.float64] | collections.abc.Sequence[float]]: +) -> Cls: """ Apply discretisation effects to angular power spectra. @@ -203,19 +199,15 @@ def discretized_cls( def lognormal_gls( - cls: collections.abc.Sequence[ - npt.NDArray[np.float64] | collections.abc.Sequence[float] - ], + cls: Cls, shift: float = 1.0, -) -> list[list[float] | npt.NDArray[np.float64]]: +) -> Cls: """Compute Gaussian Cls for a lognormal random field.""" return transform_cls(cls, "lognormal", (shift,)) def generate_gaussian( - gls: collections.abc.Sequence[ - npt.NDArray[np.float64] | collections.abc.Sequence[float] - ], + gls: Cls, nside: int, *, ncorr: int | None = None, @@ -300,9 +292,7 @@ def generate_gaussian( def generate_lognormal( - gls: collections.abc.Sequence[ - npt.NDArray[np.float64] | collections.abc.Sequence[float] - ], + gls: Cls, nside: int, shift: float = 1.0, *, From 113d4aa2020fb060cfba8e84e7243c9ff09bd4e4 Mon Sep 17 00:00:00 2001 From: "Patrick J. Roddy" Date: Wed, 6 Nov 2024 17:57:35 +0000 Subject: [PATCH 143/143] Only run on `glass` --- .pre-commit-config.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 85a19922..ae311683 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -69,5 +69,6 @@ repos: rev: v1.13.0 hooks: - id: mypy + files: ^glass/ additional_dependencies: - numpy