Repository: astro-informatics/sleplet (language: python)

Issue:
Use `numpy.typing`



Discussion / hints:

Fix patch:
diff --git a/sleplet/data/other/earth/create_earth_flm.py b/sleplet/data/other/earth/create_earth_flm.py
index a9c407053..68c0c573c 100644
--- a/sleplet/data/other/earth/create_earth_flm.py
+++ b/sleplet/data/other/earth/create_earth_flm.py
@@ -2,6 +2,7 @@
 
 import numpy as np
 import pyssht as ssht
+from numpy import typing as npt
 from scipy import io as sio
 
 from sleplet.utils.smoothing import apply_gaussian_smoothing
@@ -10,7 +11,7 @@
 _matfile = _file_location.parent / "EGM2008_Topography_flms_L2190.mat"
 
 
-def create_flm(L: int, *, smoothing: int | None = None) -> np.ndarray:
+def create_flm(L: int, *, smoothing: int | None = None) -> npt.NDArray[np.complex_]:
     """
     creates the flm for the whole Earth
     """
@@ -35,7 +36,7 @@ def create_flm(L: int, *, smoothing: int | None = None) -> np.ndarray:
     return flm
 
 
-def _load_flm() -> np.ndarray:
+def _load_flm() -> npt.NDArray[np.complex_]:
     """
     load coefficients from file
     """
diff --git a/sleplet/data/other/wmap/create_wmap_flm.py b/sleplet/data/other/wmap/create_wmap_flm.py
index 210f74173..d39280401 100644
--- a/sleplet/data/other/wmap/create_wmap_flm.py
+++ b/sleplet/data/other/wmap/create_wmap_flm.py
@@ -2,6 +2,7 @@
 
 import numpy as np
 import pyssht as ssht
+from numpy import typing as npt
 from numpy.random import default_rng
 from scipy import io as sio
 
@@ -10,7 +11,7 @@
 _file_location = Path(__file__).resolve()
 
 
-def create_flm(L: int) -> np.ndarray:
+def create_flm(L: int) -> npt.NDArray[np.complex_]:
     """
     creates the flm for the whole CMB
     """
@@ -38,7 +39,9 @@ def create_flm(L: int) -> np.ndarray:
     return flm
 
 
-def _load_cl(*, file_ending: str = "_lcdm_pl_model_wmap7baoh0") -> np.ndarray:
+def _load_cl(
+    *, file_ending: str = "_lcdm_pl_model_wmap7baoh0"
+) -> npt.NDArray[np.float_]:
     """
     pick coefficients from file options are:
     * _lcdm_pl_model_yr1_v1.mat
diff --git a/sleplet/functions/coefficients.py b/sleplet/functions/coefficients.py
index 3a4395d1f..d76bf2a01 100644
--- a/sleplet/functions/coefficients.py
+++ b/sleplet/functions/coefficients.py
@@ -2,6 +2,7 @@
 from dataclasses import KW_ONLY
 
 import numpy as np
+from numpy import typing as npt
 from pydantic import validator
 from pydantic.dataclasses import dataclass
 
@@ -34,7 +35,7 @@ def __post_init_post_parse__(self) -> None:
 
     def translate(
         self, alpha: float, beta: float, *, shannon: int | None = None
-    ) -> np.ndarray:
+    ) -> npt.NDArray[np.complex_ | np.float_]:
         g_coefficients = self._translation_helper(alpha, beta)
         return (
             g_coefficients
@@ -44,11 +45,11 @@ def translate(
 
     def convolve(
         self,
-        f_coefficient: np.ndarray,
-        g_coefficient: np.ndarray,
+        f_coefficient: npt.NDArray[np.complex_ | np.float_],
+        g_coefficient: npt.NDArray[np.complex_ | np.float_],
         *,
         shannon: int | None = None,
-    ) -> np.ndarray:
+    ) -> npt.NDArray[np.complex_ | np.float_]:
         # translation/convolution are not real for general function
         self.reality = False
         return sifting_convolution(f_coefficient, g_coefficient, shannon=shannon)
@@ -85,28 +86,34 @@ def check_coefficients(cls, v, values):
         return v
 
     @abstractmethod
-    def rotate(self, alpha: float, beta: float, *, gamma: float = 0) -> np.ndarray:
+    def rotate(
+        self, alpha: float, beta: float, *, gamma: float = 0
+    ) -> npt.NDArray[np.complex_]:
         """
         rotates given flm on the sphere by alpha/beta/gamma
         """
         raise NotImplementedError
 
     @abstractmethod
-    def _translation_helper(self, alpha: float, beta: float) -> np.ndarray:
+    def _translation_helper(
+        self, alpha: float, beta: float
+    ) -> npt.NDArray[np.complex_]:
         """
         compute the basis function at omega' for translation
         """
         raise NotImplementedError
 
     @abstractmethod
-    def _add_noise_to_signal(self) -> tuple[np.ndarray | None, float | None]:
+    def _add_noise_to_signal(
+        self,
+    ) -> tuple[npt.NDArray[np.complex_ | np.float_] | None, float | None]:
         """
         adds Gaussian white noise to the signal
         """
         raise NotImplementedError
 
     @abstractmethod
-    def _create_coefficients(self) -> np.ndarray:
+    def _create_coefficients(self) -> npt.NDArray[np.complex_ | np.float_]:
         """
         creates the flm on the north pole
         """
diff --git a/sleplet/functions/f_lm.py b/sleplet/functions/f_lm.py
index aebe4c42f..f8473a923 100644
--- a/sleplet/functions/f_lm.py
+++ b/sleplet/functions/f_lm.py
@@ -2,6 +2,7 @@
 
 import numpy as np
 import pyssht as ssht
+from numpy import typing as npt
 from pydantic.dataclasses import dataclass
 
 from sleplet.functions.coefficients import Coefficients
@@ -14,13 +15,19 @@ class F_LM(Coefficients):
     def __post_init_post_parse__(self) -> None:
         super().__post_init_post_parse__()
 
-    def rotate(self, alpha: float, beta: float, *, gamma: float = 0) -> np.ndarray:
+    def rotate(
+        self, alpha: float, beta: float, *, gamma: float = 0
+    ) -> npt.NDArray[np.complex_]:
         return ssht.rotate_flms(self.coefficients, alpha, beta, gamma, self.L)
 
-    def _translation_helper(self, alpha: float, beta: float) -> np.ndarray:
+    def _translation_helper(
+        self, alpha: float, beta: float
+    ) -> npt.NDArray[np.complex_]:
         return ssht.create_ylm(beta, alpha, self.L).conj().flatten()
 
-    def _add_noise_to_signal(self) -> tuple[np.ndarray | None, float | None]:
+    def _add_noise_to_signal(
+        self,
+    ) -> tuple[npt.NDArray[np.complex_ | np.float_] | None, float | None]:
         """
         adds Gaussian white noise to the signal
         """
@@ -28,12 +35,12 @@ def _add_noise_to_signal(self) -> tuple[np.ndarray | None, float | None]:
             unnoised_coefficients = self.coefficients.copy()
             nlm = create_noise(self.L, self.coefficients, self.noise)
             snr = compute_snr(self.coefficients, nlm, "Harmonic")
-            self.coefficients += nlm
+            self.coefficients = self.coefficients + nlm
             return unnoised_coefficients, snr
         return None, None
 
     @abstractmethod
-    def _create_coefficients(self) -> np.ndarray:
+    def _create_coefficients(self) -> npt.NDArray[np.complex_ | np.float_]:
         raise NotImplementedError
 
     @abstractmethod
diff --git a/sleplet/functions/f_p.py b/sleplet/functions/f_p.py
index 04a70bda6..dc606af7f 100644
--- a/sleplet/functions/f_p.py
+++ b/sleplet/functions/f_p.py
@@ -1,6 +1,7 @@
 from abc import abstractmethod
 
 import numpy as np
+from numpy import typing as npt
 from pydantic.dataclasses import dataclass
 
 from sleplet.functions.coefficients import Coefficients
@@ -23,13 +24,19 @@ def __post_init_post_parse__(self) -> None:
         self.slepian = choose_slepian_method(self.L, self.region)
         super().__post_init_post_parse__()
 
-    def rotate(self, alpha: float, beta: float, *, gamma: float = 0) -> np.ndarray:
+    def rotate(
+        self, alpha: float, beta: float, *, gamma: float = 0
+    ) -> npt.NDArray[np.complex_]:
         raise NotImplementedError("Slepian rotation is not defined")
 
-    def _translation_helper(self, alpha: float, beta: float) -> np.ndarray:
+    def _translation_helper(
+        self, alpha: float, beta: float
+    ) -> npt.NDArray[np.complex_]:
         return compute_s_p_omega_prime(self.L, alpha, beta, self.slepian).conj()
 
-    def _add_noise_to_signal(self) -> tuple[np.ndarray | None, float | None]:
+    def _add_noise_to_signal(
+        self,
+    ) -> tuple[npt.NDArray[np.complex_ | np.float_] | None, float | None]:
         """
         adds Gaussian white noise converted to Slepian space
         """
@@ -39,12 +46,12 @@ def _add_noise_to_signal(self) -> tuple[np.ndarray | None, float | None]:
                 self.L, self.coefficients, self.slepian, self.noise
             )
             snr = compute_snr(self.coefficients, n_p, "Slepian")
-            self.coefficients += n_p
+            self.coefficients = self.coefficients + n_p
             return unnoised_coefficients, snr
         return None, None
 
     @abstractmethod
-    def _create_coefficients(self) -> np.ndarray:
+    def _create_coefficients(self) -> npt.NDArray[np.complex_ | np.float_]:
         raise NotImplementedError
 
     @abstractmethod
diff --git a/sleplet/functions/flm/africa.py b/sleplet/functions/flm/africa.py
index f49117feb..3c1728658 100644
--- a/sleplet/functions/flm/africa.py
+++ b/sleplet/functions/flm/africa.py
@@ -2,6 +2,7 @@
 
 import numpy as np
 import pyssht as ssht
+from numpy import typing as npt
 from pydantic.dataclasses import dataclass
 
 from sleplet.data.other.earth.create_earth_flm import create_flm
@@ -21,7 +22,7 @@ class Africa(F_LM):
     def __post_init_post_parse__(self) -> None:
         super().__post_init_post_parse__()
 
-    def _create_coefficients(self) -> np.ndarray:
+    def _create_coefficients(self) -> npt.NDArray[np.complex_ | np.float_]:
         return ensure_f_bandlimited(self._grid_fun, self.L, self.reality, self.spin)
 
     def _create_name(self) -> str:
@@ -39,7 +40,9 @@ def _setup_args(self) -> None:
                 f"{self.__class__.__name__} does not support extra arguments"
             )
 
-    def _grid_fun(self, theta: np.ndarray, phi: np.ndarray) -> np.ndarray:
+    def _grid_fun(
+        self, theta: npt.NDArray[np.float_], phi: npt.NDArray[np.float_]
+    ) -> npt.NDArray[np.float_]:
         """
         function on the grid
         """
diff --git a/sleplet/functions/flm/axisymmetric_wavelet_coefficients_africa.py b/sleplet/functions/flm/axisymmetric_wavelet_coefficients_africa.py
index b6f25565d..876e1690f 100644
--- a/sleplet/functions/flm/axisymmetric_wavelet_coefficients_africa.py
+++ b/sleplet/functions/flm/axisymmetric_wavelet_coefficients_africa.py
@@ -1,4 +1,5 @@
 import numpy as np
+from numpy import typing as npt
 from pydantic import validator
 from pydantic.dataclasses import dataclass
 from pys2let import pys2let_j_max
@@ -27,7 +28,7 @@ class AxisymmetricWaveletCoefficientsAfrica(F_LM):
     def __post_init_post_parse__(self) -> None:
         super().__post_init_post_parse__()
 
-    def _create_coefficients(self) -> np.ndarray:
+    def _create_coefficients(self) -> npt.NDArray[np.complex_ | np.float_]:
         logger.info("start computing wavelet coefficients")
         self.wavelets, self.wavelet_coefficients = self._create_wavelet_coefficients()
         logger.info("finish computing wavelet coefficients")
@@ -55,7 +56,9 @@ def _setup_args(self) -> None:
                 raise ValueError(f"The number of extra arguments should be {num_args}")
             self.B, self.j_min, self.j = self.extra_args
 
-    def _create_wavelet_coefficients(self) -> tuple[np.ndarray, np.ndarray]:
+    def _create_wavelet_coefficients(
+        self,
+    ) -> tuple[npt.NDArray[np.complex_], npt.NDArray[np.complex_]]:
         """
         computes wavelet coefficients of Africa
         """
diff --git a/sleplet/functions/flm/axisymmetric_wavelet_coefficients_earth.py b/sleplet/functions/flm/axisymmetric_wavelet_coefficients_earth.py
index 2b4d2dfa3..a7ff86b5c 100644
--- a/sleplet/functions/flm/axisymmetric_wavelet_coefficients_earth.py
+++ b/sleplet/functions/flm/axisymmetric_wavelet_coefficients_earth.py
@@ -1,4 +1,5 @@
 import numpy as np
+from numpy import typing as npt
 from pydantic import validator
 from pydantic.dataclasses import dataclass
 from pys2let import pys2let_j_max
@@ -27,7 +28,7 @@ class AxisymmetricWaveletCoefficientsEarth(F_LM):
     def __post_init_post_parse__(self) -> None:
         super().__post_init_post_parse__()
 
-    def _create_coefficients(self) -> np.ndarray:
+    def _create_coefficients(self) -> npt.NDArray[np.complex_ | np.float_]:
         logger.info("start computing wavelet coefficients")
         self.wavelets, self.wavelet_coefficients = self._create_wavelet_coefficients()
         logger.info("finish computing wavelet coefficients")
@@ -55,7 +56,9 @@ def _setup_args(self) -> None:
                 raise ValueError(f"The number of extra arguments should be {num_args}")
             self.B, self.j_min, self.j = self.extra_args
 
-    def _create_wavelet_coefficients(self) -> tuple[np.ndarray, np.ndarray]:
+    def _create_wavelet_coefficients(
+        self,
+    ) -> tuple[npt.NDArray[np.complex_], npt.NDArray[np.complex_]]:
         """
         computes wavelet coefficients of the Earth
         """
diff --git a/sleplet/functions/flm/axisymmetric_wavelet_coefficients_south_america.py b/sleplet/functions/flm/axisymmetric_wavelet_coefficients_south_america.py
index 15a8e454c..638edb8eb 100644
--- a/sleplet/functions/flm/axisymmetric_wavelet_coefficients_south_america.py
+++ b/sleplet/functions/flm/axisymmetric_wavelet_coefficients_south_america.py
@@ -1,4 +1,5 @@
 import numpy as np
+from numpy import typing as npt
 from pydantic import validator
 from pydantic.dataclasses import dataclass
 from pys2let import pys2let_j_max
@@ -27,7 +28,7 @@ class AxisymmetricWaveletCoefficientsSouthAmerica(F_LM):
     def __post_init_post_parse__(self) -> None:
         super().__post_init_post_parse__()
 
-    def _create_coefficients(self) -> np.ndarray:
+    def _create_coefficients(self) -> npt.NDArray[np.complex_ | np.float_]:
         logger.info("start computing wavelet coefficients")
         self.wavelets, self.wavelet_coefficients = self._create_wavelet_coefficients()
         logger.info("finish computing wavelet coefficients")
@@ -55,7 +56,9 @@ def _setup_args(self) -> None:
                 raise ValueError(f"The number of extra arguments should be {num_args}")
             self.B, self.j_min, self.j = self.extra_args
 
-    def _create_wavelet_coefficients(self) -> tuple[np.ndarray, np.ndarray]:
+    def _create_wavelet_coefficients(
+        self,
+    ) -> tuple[npt.NDArray[np.complex_], npt.NDArray[np.complex_]]:
         """
         computes wavelet coefficients of South America
         """
diff --git a/sleplet/functions/flm/axisymmetric_wavelets.py b/sleplet/functions/flm/axisymmetric_wavelets.py
index 4510d29c1..e750dfcc8 100644
--- a/sleplet/functions/flm/axisymmetric_wavelets.py
+++ b/sleplet/functions/flm/axisymmetric_wavelets.py
@@ -1,4 +1,5 @@
 import numpy as np
+from numpy import typing as npt
 from pydantic import validator
 from pydantic.dataclasses import dataclass
 from pys2let import pys2let_j_max
@@ -23,7 +24,7 @@ class AxisymmetricWavelets(F_LM):
     def __post_init_post_parse__(self) -> None:
         super().__post_init_post_parse__()
 
-    def _create_coefficients(self) -> np.ndarray:
+    def _create_coefficients(self) -> npt.NDArray[np.complex_ | np.float_]:
         logger.info("start computing wavelets")
         self.wavelets = self._create_wavelets()
         logger.info("finish computing wavelets")
@@ -51,7 +52,7 @@ def _setup_args(self) -> None:
                 raise ValueError(f"The number of extra arguments should be {num_args}")
             self.B, self.j_min, self.j = self.extra_args
 
-    def _create_wavelets(self) -> np.ndarray:
+    def _create_wavelets(self) -> npt.NDArray[np.complex_]:
         """
         compute all wavelets
         """
diff --git a/sleplet/functions/flm/dirac_delta.py b/sleplet/functions/flm/dirac_delta.py
index 6dc55d490..1d75b96f4 100644
--- a/sleplet/functions/flm/dirac_delta.py
+++ b/sleplet/functions/flm/dirac_delta.py
@@ -1,5 +1,6 @@
 import numpy as np
 import pyssht as ssht
+from numpy import typing as npt
 from pydantic.dataclasses import dataclass
 
 from sleplet.functions.f_lm import F_LM
@@ -12,7 +13,7 @@ class DiracDelta(F_LM):
     def __post_init_post_parse__(self) -> None:
         super().__post_init_post_parse__()
 
-    def _create_coefficients(self) -> np.ndarray:
+    def _create_coefficients(self) -> npt.NDArray[np.complex_ | np.float_]:
         flm = np.zeros(self.L**2, dtype=np.complex_)
         for ell in range(self.L):
             ind = ssht.elm2ind(ell, 0)
diff --git a/sleplet/functions/flm/directional_spin_wavelets.py b/sleplet/functions/flm/directional_spin_wavelets.py
index 99b343b77..53802fced 100644
--- a/sleplet/functions/flm/directional_spin_wavelets.py
+++ b/sleplet/functions/flm/directional_spin_wavelets.py
@@ -1,5 +1,6 @@
 import numpy as np
 import pyssht as ssht
+from numpy import typing as npt
 from pydantic import validator
 from pydantic.dataclasses import dataclass
 from pys2let import pys2let_j_max, wavelet_tiling
@@ -25,7 +26,7 @@ class DirectionalSpinWavelets(F_LM):
     def __post_init_post_parse__(self) -> None:
         super().__post_init_post_parse__()
 
-    def _create_coefficients(self) -> np.ndarray:
+    def _create_coefficients(self) -> npt.NDArray[np.complex_ | np.float_]:
         logger.info("start computing wavelets")
         self.wavelets = self._create_wavelets()
         logger.info("finish computing wavelets")
@@ -55,7 +56,7 @@ def _setup_args(self) -> None:
                 raise ValueError(f"The number of extra arguments should be {num_args}")
             self.B, self.j_min, self.spin, self.N, self.j = self.extra_args
 
-    def _create_wavelets(self) -> np.ndarray:
+    def _create_wavelets(self) -> npt.NDArray[np.complex_]:
         """
         compute all wavelets
         """
diff --git a/sleplet/functions/flm/earth.py b/sleplet/functions/flm/earth.py
index 9d95ee641..7f315a2b2 100644
--- a/sleplet/functions/flm/earth.py
+++ b/sleplet/functions/flm/earth.py
@@ -1,4 +1,5 @@
 import numpy as np
+from numpy import typing as npt
 from pydantic.dataclasses import dataclass
 
 from sleplet.data.other.earth.create_earth_flm import create_flm
@@ -12,7 +13,7 @@ class Earth(F_LM):
     def __post_init_post_parse__(self) -> None:
         super().__post_init_post_parse__()
 
-    def _create_coefficients(self) -> np.ndarray:
+    def _create_coefficients(self) -> npt.NDArray[np.complex_ | np.float_]:
         return create_flm(self.L, smoothing=self.smoothing)
 
     def _create_name(self) -> str:
diff --git a/sleplet/functions/flm/elongated_gaussian.py b/sleplet/functions/flm/elongated_gaussian.py
index 6bdd8e17b..4be396f8e 100644
--- a/sleplet/functions/flm/elongated_gaussian.py
+++ b/sleplet/functions/flm/elongated_gaussian.py
@@ -1,4 +1,5 @@
 import numpy as np
+from numpy import typing as npt
 from pydantic.dataclasses import dataclass
 
 from sleplet.functions.f_lm import F_LM
@@ -16,7 +17,7 @@ class ElongatedGaussian(F_LM):
     def __post_init_post_parse__(self) -> None:
         super().__post_init_post_parse__()
 
-    def _create_coefficients(self) -> np.ndarray:
+    def _create_coefficients(self) -> npt.NDArray[np.complex_ | np.float_]:
         return ensure_f_bandlimited(self._grid_fun, self.L, self.reality, self.spin)
 
     def _create_name(self) -> str:
@@ -41,7 +42,9 @@ def _setup_args(self) -> None:
                 np.float_power(10, x) for x in self.extra_args
             ]
 
-    def _grid_fun(self, theta: np.ndarray, phi: np.ndarray) -> np.ndarray:
+    def _grid_fun(
+        self, theta: npt.NDArray[np.float_], phi: npt.NDArray[np.float_]
+    ) -> npt.NDArray[np.float_]:
         """
         function on the grid
         """
diff --git a/sleplet/functions/flm/gaussian.py b/sleplet/functions/flm/gaussian.py
index 5744dd760..14474d0c9 100644
--- a/sleplet/functions/flm/gaussian.py
+++ b/sleplet/functions/flm/gaussian.py
@@ -1,5 +1,6 @@
 import numpy as np
 import pyssht as ssht
+from numpy import typing as npt
 from pydantic.dataclasses import dataclass
 
 from sleplet.functions.f_lm import F_LM
@@ -14,7 +15,7 @@ class Gaussian(F_LM):
     def __post_init_post_parse__(self) -> None:
         super().__post_init_post_parse__()
 
-    def _create_coefficients(self) -> np.ndarray:
+    def _create_coefficients(self) -> npt.NDArray[np.complex_ | np.float_]:
         flm = np.zeros(self.L**2, dtype=np.complex_)
         for ell in range(self.L):
             ind = ssht.elm2ind(ell, 0)
diff --git a/sleplet/functions/flm/harmonic_gaussian.py b/sleplet/functions/flm/harmonic_gaussian.py
index 6649ddada..1f9999ef4 100644
--- a/sleplet/functions/flm/harmonic_gaussian.py
+++ b/sleplet/functions/flm/harmonic_gaussian.py
@@ -1,5 +1,6 @@
 import numpy as np
 import pyssht as ssht
+from numpy import typing as npt
 from pydantic.dataclasses import dataclass
 
 from sleplet.functions.f_lm import F_LM
@@ -15,7 +16,7 @@ class HarmonicGaussian(F_LM):
     def __post_init_post_parse__(self) -> None:
         super().__post_init_post_parse__()
 
-    def _create_coefficients(self) -> np.ndarray:
+    def _create_coefficients(self) -> npt.NDArray[np.complex_ | np.float_]:
         flm = np.zeros(self.L**2, dtype=np.complex_)
         for ell in range(self.L):
             upsilon_l = np.exp(-((ell / self.l_sigma) ** 2) / 2)
diff --git a/sleplet/functions/flm/identity.py b/sleplet/functions/flm/identity.py
index 100f3c26a..91afa02d5 100644
--- a/sleplet/functions/flm/identity.py
+++ b/sleplet/functions/flm/identity.py
@@ -1,4 +1,5 @@
 import numpy as np
+from numpy import typing as npt
 from pydantic.dataclasses import dataclass
 
 from sleplet.functions.f_lm import F_LM
@@ -11,7 +12,7 @@ class Identity(F_LM):
     def __post_init_post_parse__(self) -> None:
         super().__post_init_post_parse__()
 
-    def _create_coefficients(self) -> np.ndarray:
+    def _create_coefficients(self) -> npt.NDArray[np.complex_ | np.float_]:
         return np.ones(self.L**2, dtype=np.complex_)
 
     def _create_name(self) -> str:
diff --git a/sleplet/functions/flm/noise_earth.py b/sleplet/functions/flm/noise_earth.py
index c6e2aaa01..6d9ce11c8 100644
--- a/sleplet/functions/flm/noise_earth.py
+++ b/sleplet/functions/flm/noise_earth.py
@@ -1,4 +1,5 @@
 import numpy as np
+from numpy import typing as npt
 from pydantic.dataclasses import dataclass
 
 from sleplet.functions.f_lm import F_LM
@@ -15,7 +16,7 @@ class NoiseEarth(F_LM):
     def __post_init_post_parse__(self) -> None:
         super().__post_init_post_parse__()
 
-    def _create_coefficients(self) -> np.ndarray:
+    def _create_coefficients(self) -> npt.NDArray[np.complex_ | np.float_]:
         earth = Earth(self.L, smoothing=self.smoothing)
         noise = create_noise(self.L, earth.coefficients, self.SNR)
         compute_snr(earth.coefficients, noise, "Harmonic")
diff --git a/sleplet/functions/flm/ridgelets.py b/sleplet/functions/flm/ridgelets.py
index b8d4ceaa8..ad6caec43 100644
--- a/sleplet/functions/flm/ridgelets.py
+++ b/sleplet/functions/flm/ridgelets.py
@@ -1,5 +1,6 @@
 import numpy as np
 import pyssht as ssht
+from numpy import typing as npt
 from pydantic import validator
 from pydantic.dataclasses import dataclass
 from pys2let import pys2let_j_max
@@ -26,7 +27,7 @@ class Ridgelets(F_LM):
     def __post_init_post_parse__(self) -> None:
         super().__post_init_post_parse__()
 
-    def _create_coefficients(self) -> np.ndarray:
+    def _create_coefficients(self) -> npt.NDArray[np.complex_ | np.float_]:
         logger.info("start computing wavelets")
         self.wavelets = self._create_wavelets()
         logger.info("finish computing wavelets")
@@ -55,7 +56,7 @@ def _setup_args(self) -> None:
                 raise ValueError(f"The number of extra arguments should be {num_args}")
             self.B, self.j_min, self.spin, self.j = self.extra_args
 
-    def _create_wavelets(self) -> np.ndarray:
+    def _create_wavelets(self) -> npt.NDArray[np.complex_]:
         """
         compute all wavelets
         """
@@ -68,7 +69,7 @@ def _create_wavelets(self) -> np.ndarray:
             wavelets[1:, ind] = kappas[1:, ell] * ring_lm[ind] / np.sqrt(2 * np.pi)
         return wavelets
 
-    def _compute_ring(self) -> np.ndarray:
+    def _compute_ring(self) -> npt.NDArray[np.complex_]:
         """
         compute ring in harmonic space
         """
diff --git a/sleplet/functions/flm/south_america.py b/sleplet/functions/flm/south_america.py
index 6c74e1b46..300ae28cd 100644
--- a/sleplet/functions/flm/south_america.py
+++ b/sleplet/functions/flm/south_america.py
@@ -2,6 +2,7 @@
 
 import numpy as np
 import pyssht as ssht
+from numpy import typing as npt
 from pydantic.dataclasses import dataclass
 
 from sleplet.data.other.earth.create_earth_flm import create_flm
@@ -21,7 +22,7 @@ class SouthAmerica(F_LM):
     def __post_init_post_parse__(self) -> None:
         super().__post_init_post_parse__()
 
-    def _create_coefficients(self) -> np.ndarray:
+    def _create_coefficients(self) -> npt.NDArray[np.complex_ | np.float_]:
         return ensure_f_bandlimited(self._grid_fun, self.L, self.reality, self.spin)
 
     def _create_name(self) -> str:
@@ -39,7 +40,9 @@ def _setup_args(self) -> None:
                 f"{self.__class__.__name__} does not support extra arguments"
             )
 
-    def _grid_fun(self, theta: np.ndarray, phi: np.ndarray) -> np.ndarray:
+    def _grid_fun(
+        self, theta: npt.NDArray[np.float_], phi: npt.NDArray[np.float_]
+    ) -> npt.NDArray[np.float_]:
         """
         function on the grid
         """
diff --git a/sleplet/functions/flm/spherical_harmonic.py b/sleplet/functions/flm/spherical_harmonic.py
index 58cfb02bf..9b7c56e9a 100644
--- a/sleplet/functions/flm/spherical_harmonic.py
+++ b/sleplet/functions/flm/spherical_harmonic.py
@@ -1,5 +1,6 @@
 import numpy as np
 import pyssht as ssht
+from numpy import typing as npt
 from pydantic import validator
 from pydantic.dataclasses import dataclass
 
@@ -14,7 +15,7 @@ class SphericalHarmonic(F_LM):
     ell: int = 0
     m: int = 0
 
-    def _create_coefficients(self) -> np.ndarray:
+    def _create_coefficients(self) -> npt.NDArray[np.complex_ | np.float_]:
         ind = ssht.elm2ind(self.ell, self.m)
         return create_spherical_harmonic(self.L, ind)
 
diff --git a/sleplet/functions/flm/squashed_gaussian.py b/sleplet/functions/flm/squashed_gaussian.py
index 92493afc9..584e481cd 100644
--- a/sleplet/functions/flm/squashed_gaussian.py
+++ b/sleplet/functions/flm/squashed_gaussian.py
@@ -1,4 +1,5 @@
 import numpy as np
+from numpy import typing as npt
 from pydantic.dataclasses import dataclass
 
 from sleplet.functions.f_lm import F_LM
@@ -16,7 +17,7 @@ class SquashedGaussian(F_LM):
     def __post_init_post_parse__(self) -> None:
         super().__post_init_post_parse__()
 
-    def _create_coefficients(self) -> np.ndarray:
+    def _create_coefficients(self) -> npt.NDArray[np.complex_ | np.float_]:
         return ensure_f_bandlimited(self._grid_fun, self.L, self.reality, self.spin)
 
     def _create_name(self) -> str:
@@ -39,7 +40,9 @@ def _setup_args(self) -> None:
                 raise ValueError(f"The number of extra arguments should be {num_args}")
             self.t_sigma, self.freq = [np.float_power(10, x) for x in self.extra_args]
 
-    def _grid_fun(self, theta: np.ndarray, phi: np.ndarray) -> np.ndarray:
+    def _grid_fun(
+        self, theta: npt.NDArray[np.float_], phi: npt.NDArray[np.float_]
+    ) -> npt.NDArray[np.float_]:
         """
         function on the grid
         """
diff --git a/sleplet/functions/flm/wmap.py b/sleplet/functions/flm/wmap.py
index 7c8de2ec0..366464b3f 100644
--- a/sleplet/functions/flm/wmap.py
+++ b/sleplet/functions/flm/wmap.py
@@ -1,4 +1,5 @@
 import numpy as np
+from numpy import typing as npt
 from pydantic.dataclasses import dataclass
 
 from sleplet.data.other.wmap.create_wmap_flm import create_flm
@@ -12,7 +13,7 @@ class Wmap(F_LM):
     def __post_init_post_parse__(self) -> None:
         super().__post_init_post_parse__()
 
-    def _create_coefficients(self) -> np.ndarray:
+    def _create_coefficients(self) -> npt.NDArray[np.complex_ | np.float_]:
         return create_flm(self.L)
 
     def _create_name(self) -> str:
diff --git a/sleplet/functions/fp/slepian.py b/sleplet/functions/fp/slepian.py
index 66fdbf073..c15776c9e 100644
--- a/sleplet/functions/fp/slepian.py
+++ b/sleplet/functions/fp/slepian.py
@@ -1,4 +1,5 @@
 import numpy as np
+from numpy import typing as npt
 from pydantic import validator
 from pydantic.dataclasses import dataclass
 
@@ -31,7 +32,7 @@ def _create_name(self) -> str:
             .replace("+", "")
         )
 
-    def _create_coefficients(self) -> np.ndarray:
+    def _create_coefficients(self) -> npt.NDArray[np.complex_ | np.float_]:
         logger.info(f"Shannon number: {self.slepian.N}")
         logger.info(f"Eigenvalue {self.rank}: {self.slepian.eigenvalues[self.rank]:e}")
         return slepian_forward(
diff --git a/sleplet/functions/fp/slepian_africa.py b/sleplet/functions/fp/slepian_africa.py
index b8561ca18..966c4800f 100644
--- a/sleplet/functions/fp/slepian_africa.py
+++ b/sleplet/functions/fp/slepian_africa.py
@@ -1,4 +1,5 @@
 import numpy as np
+from numpy import typing as npt
 from pydantic.dataclasses import dataclass
 
 from sleplet.functions.f_p import F_P
@@ -16,7 +17,7 @@ def __post_init_post_parse__(self) -> None:
         if isinstance(self.region, Region) and self.region.name_ending != "africa":
             raise RuntimeError("Slepian region selected must be 'africa'")
 
-    def _create_coefficients(self) -> np.ndarray:
+    def _create_coefficients(self) -> npt.NDArray[np.complex_ | np.float_]:
         a = Africa(self.L, smoothing=self.smoothing)
         return slepian_forward(self.L, self.slepian, flm=a.coefficients)
 
diff --git a/sleplet/functions/fp/slepian_dirac_delta.py b/sleplet/functions/fp/slepian_dirac_delta.py
index efd826b38..c41b2b30e 100644
--- a/sleplet/functions/fp/slepian_dirac_delta.py
+++ b/sleplet/functions/fp/slepian_dirac_delta.py
@@ -1,5 +1,6 @@
 import numpy as np
 import pyssht as ssht
+from numpy import typing as npt
 from pydantic.dataclasses import dataclass
 
 from sleplet.functions.f_p import F_P
@@ -15,7 +16,7 @@ class SlepianDiracDelta(F_P):
     def __post_init_post_parse__(self) -> None:
         super().__post_init_post_parse__()
 
-    def _create_coefficients(self) -> np.ndarray:
+    def _create_coefficients(self) -> npt.NDArray[np.complex_ | np.float_]:
         self._compute_angles()
         return compute_s_p_omega_prime(
             self.L, self.alpha, self.beta, self.slepian
diff --git a/sleplet/functions/fp/slepian_identity.py b/sleplet/functions/fp/slepian_identity.py
index 64fd4ae76..9d1283c29 100644
--- a/sleplet/functions/fp/slepian_identity.py
+++ b/sleplet/functions/fp/slepian_identity.py
@@ -1,4 +1,5 @@
 import numpy as np
+from numpy import typing as npt
 from pydantic.dataclasses import dataclass
 
 from sleplet.functions.f_p import F_P
@@ -11,7 +12,7 @@ class SlepianIdentity(F_P):
     def __post_init_post_parse__(self) -> None:
         super().__post_init_post_parse__()
 
-    def _create_coefficients(self) -> np.ndarray:
+    def _create_coefficients(self) -> npt.NDArray[np.complex_ | np.float_]:
         return np.ones(self.L**2, dtype=np.complex_)
 
     def _create_name(self) -> str:
diff --git a/sleplet/functions/fp/slepian_noise_africa.py b/sleplet/functions/fp/slepian_noise_africa.py
index 7789ed752..47cfc76e4 100644
--- a/sleplet/functions/fp/slepian_noise_africa.py
+++ b/sleplet/functions/fp/slepian_noise_africa.py
@@ -1,4 +1,5 @@
 import numpy as np
+from numpy import typing as npt
 from pydantic.dataclasses import dataclass
 
 from sleplet.functions.f_p import F_P
@@ -18,7 +19,7 @@ def __post_init_post_parse__(self) -> None:
         if isinstance(self.region, Region) and self.region.name_ending != "africa":
             raise RuntimeError("Slepian region selected must be 'africa'")
 
-    def _create_coefficients(self) -> np.ndarray:
+    def _create_coefficients(self) -> npt.NDArray[np.complex_ | np.float_]:
         sa = SlepianAfrica(self.L, region=self.region, smoothing=self.smoothing)
         noise = create_slepian_noise(self.L, sa.coefficients, self.slepian, self.SNR)
         compute_snr(sa.coefficients, noise, "Slepian")
diff --git a/sleplet/functions/fp/slepian_noise_south_america.py b/sleplet/functions/fp/slepian_noise_south_america.py
index e7d02e88f..560c4b1e4 100644
--- a/sleplet/functions/fp/slepian_noise_south_america.py
+++ b/sleplet/functions/fp/slepian_noise_south_america.py
@@ -1,4 +1,5 @@
 import numpy as np
+from numpy import typing as npt
 from pydantic.dataclasses import dataclass
 
 from sleplet.functions.f_p import F_P
@@ -21,7 +22,7 @@ def __post_init_post_parse__(self) -> None:
         ):
             raise RuntimeError("Slepian region selected must be 'south_america'")
 
-    def _create_coefficients(self) -> np.ndarray:
+    def _create_coefficients(self) -> npt.NDArray[np.complex_ | np.float_]:
         sa = SlepianSouthAmerica(self.L, region=self.region, smoothing=self.smoothing)
         noise = create_slepian_noise(self.L, sa.coefficients, self.slepian, self.SNR)
         compute_snr(sa.coefficients, noise, "Slepian")
diff --git a/sleplet/functions/fp/slepian_south_america.py b/sleplet/functions/fp/slepian_south_america.py
index 32cfd8b7c..f091aaeed 100644
--- a/sleplet/functions/fp/slepian_south_america.py
+++ b/sleplet/functions/fp/slepian_south_america.py
@@ -1,4 +1,5 @@
 import numpy as np
+from numpy import typing as npt
 from pydantic.dataclasses import dataclass
 
 from sleplet.functions.f_p import F_P
@@ -19,7 +20,7 @@ def __post_init_post_parse__(self) -> None:
         ):
             raise RuntimeError("Slepian region selected must be 'south_america'")
 
-    def _create_coefficients(self) -> np.ndarray:
+    def _create_coefficients(self) -> npt.NDArray[np.complex_ | np.float_]:
         sa = SouthAmerica(self.L, smoothing=self.smoothing)
         return slepian_forward(self.L, self.slepian, flm=sa.coefficients)
 
diff --git a/sleplet/functions/fp/slepian_wavelet_coefficients_africa.py b/sleplet/functions/fp/slepian_wavelet_coefficients_africa.py
index 8b1f7bf6d..94465cbcd 100644
--- a/sleplet/functions/fp/slepian_wavelet_coefficients_africa.py
+++ b/sleplet/functions/fp/slepian_wavelet_coefficients_africa.py
@@ -1,4 +1,5 @@
 import numpy as np
+from numpy import typing as npt
 from pydantic import validator
 from pydantic.dataclasses import dataclass
 from pys2let import pys2let_j_max
@@ -28,7 +29,7 @@ def __post_init_post_parse__(self) -> None:
         if isinstance(self.region, Region) and self.region.name_ending != "africa":
             raise RuntimeError("Slepian region selected must be 'africa'")
 
-    def _create_coefficients(self) -> np.ndarray:
+    def _create_coefficients(self) -> npt.NDArray[np.complex_ | np.float_]:
         logger.info("start computing wavelet coefficients")
         self.wavelets, self.wavelet_coefficients = self._create_wavelet_coefficients()
         logger.info("finish computing wavelet coefficients")
@@ -56,7 +57,9 @@ def _setup_args(self) -> None:
                 raise ValueError(f"The number of extra arguments should be {num_args}")
             self.B, self.j_min, self.j = self.extra_args
 
-    def _create_wavelet_coefficients(self) -> tuple[np.ndarray, np.ndarray]:
+    def _create_wavelet_coefficients(
+        self,
+    ) -> tuple[npt.NDArray[np.float_], npt.NDArray[np.complex_ | np.float_]]:
         """
         computes wavelet coefficients in Slepian space
         """
diff --git a/sleplet/functions/fp/slepian_wavelet_coefficients_south_america.py b/sleplet/functions/fp/slepian_wavelet_coefficients_south_america.py
index 9f90f4423..e0fb1994f 100644
--- a/sleplet/functions/fp/slepian_wavelet_coefficients_south_america.py
+++ b/sleplet/functions/fp/slepian_wavelet_coefficients_south_america.py
@@ -1,4 +1,5 @@
 import numpy as np
+from numpy import typing as npt
 from pydantic import validator
 from pydantic.dataclasses import dataclass
 from pys2let import pys2let_j_max
@@ -31,7 +32,7 @@ def __post_init_post_parse__(self) -> None:
         ):
             raise RuntimeError("Slepian region selected must be 'south_america'")
 
-    def _create_coefficients(self) -> np.ndarray:
+    def _create_coefficients(self) -> npt.NDArray[np.complex_ | np.float_]:
         logger.info("start computing wavelet coefficients")
         self.wavelets, self.wavelet_coefficients = self._create_wavelet_coefficients()
         logger.info("finish computing wavelet coefficients")
@@ -59,7 +60,9 @@ def _setup_args(self) -> None:
                 raise ValueError(f"The number of extra arguments should be {num_args}")
             self.B, self.j_min, self.j = self.extra_args
 
-    def _create_wavelet_coefficients(self) -> tuple[np.ndarray, np.ndarray]:
+    def _create_wavelet_coefficients(
+        self,
+    ) -> tuple[npt.NDArray[np.float_], npt.NDArray[np.complex_ | np.float_]]:
         """
         computes wavelet coefficients in Slepian space
         """
diff --git a/sleplet/functions/fp/slepian_wavelets.py b/sleplet/functions/fp/slepian_wavelets.py
index dee864873..128508fd1 100644
--- a/sleplet/functions/fp/slepian_wavelets.py
+++ b/sleplet/functions/fp/slepian_wavelets.py
@@ -1,4 +1,5 @@
 import numpy as np
+from numpy import typing as npt
 from pydantic import validator
 from pydantic.dataclasses import dataclass
 from pys2let import pys2let_j_max
@@ -23,7 +24,7 @@ class SlepianWavelets(F_P):
     def __post_init_post_parse__(self) -> None:
         super().__post_init_post_parse__()
 
-    def _create_coefficients(self) -> np.ndarray:
+    def _create_coefficients(self) -> npt.NDArray[np.complex_ | np.float_]:
         logger.info("start computing wavelets")
         self.wavelets = self._create_wavelets()
         logger.info("finish computing wavelets")
@@ -52,7 +53,7 @@ def _setup_args(self) -> None:
                 raise ValueError(f"The number of extra arguments should be {num_args}")
             self.B, self.j_min, self.j = self.extra_args
 
-    def _create_wavelets(self) -> np.ndarray:
+    def _create_wavelets(self) -> npt.NDArray[np.float_]:
         """
         computes wavelets in Slepian space
         """
diff --git a/sleplet/meshes/classes/mesh_slepian.py b/sleplet/meshes/classes/mesh_slepian.py
index 010350121..e8e85ec46 100644
--- a/sleplet/meshes/classes/mesh_slepian.py
+++ b/sleplet/meshes/classes/mesh_slepian.py
@@ -3,6 +3,7 @@
 
 import numpy as np
 from numpy import linalg as LA
+from numpy import typing as npt
 from pydantic.dataclasses import dataclass
 
 from sleplet.meshes.classes.mesh import Mesh
@@ -72,7 +73,7 @@ def _compute_slepian_functions(self) -> None:
                 np.save(eval_loc, self.slepian_eigenvalues)
                 np.save(evec_loc, self.slepian_functions[: self.N])
 
-    def _create_D_matrix(self) -> np.ndarray:
+    def _create_D_matrix(self) -> npt.NDArray[np.float_]:
         """
         computes the D matrix for the mesh eigenfunctions
         """
@@ -112,7 +113,7 @@ def func(chunk: list[int]) -> None:
         release_shared_memory(shm_ext)
         return D
 
-    def _fill_D_elements(self, D: np.ndarray, i: int) -> None:
+    def _fill_D_elements(self, D: npt.NDArray[np.float_], i: int) -> None:
         """
         fill in the D matrix elements using symmetries
         """
@@ -135,7 +136,7 @@ def _integral(self, i: int, j: int) -> float:
     @staticmethod
     def _clean_evals_and_evecs(
         eigendecomposition: tuple,
-    ) -> tuple[np.ndarray, np.ndarray]:
+    ) -> tuple[npt.NDArray[np.float_], npt.NDArray[np.float_]]:
         """
         need eigenvalues and eigenvectors to be in a certain format
         """
diff --git a/sleplet/meshes/classes/mesh_slepian_decomposition.py b/sleplet/meshes/classes/mesh_slepian_decomposition.py
index bd81cea9e..04101afd0 100644
--- a/sleplet/meshes/classes/mesh_slepian_decomposition.py
+++ b/sleplet/meshes/classes/mesh_slepian_decomposition.py
@@ -1,6 +1,7 @@
 from dataclasses import KW_ONLY
 
 import numpy as np
+from numpy import typing as npt
 from pydantic.dataclasses import dataclass
 
 from sleplet.meshes.classes.mesh_slepian import MeshSlepian
@@ -18,8 +19,8 @@ class MeshSlepianDecomposition:
     mesh_slepian: MeshSlepian
     _: KW_ONLY
     mask: bool = False
-    u_i: np.ndarray | None = None
-    u: np.ndarray | None = None
+    u_i: npt.NDArray[np.complex_ | np.float_] | None = None
+    u: npt.NDArray[np.complex_ | np.float_] | None = None
 
     def __post_init_post_parse__(self) -> None:
         """ """
@@ -41,7 +42,7 @@ def decompose(self, rank: int) -> float:
             case _:
                 raise ValueError(f"'{self.method}' is not a valid method")
 
-    def decompose_all(self, n_coefficients: int) -> np.ndarray:
+    def decompose_all(self, n_coefficients: int) -> npt.NDArray[np.float_]:
         """
         decompose all ranks of the Slepian coefficients
         """
diff --git a/sleplet/meshes/harmonic_coefficients/mesh_basis_functions.py b/sleplet/meshes/harmonic_coefficients/mesh_basis_functions.py
index ea6cf3fe7..37ed6b8e2 100644
--- a/sleplet/meshes/harmonic_coefficients/mesh_basis_functions.py
+++ b/sleplet/meshes/harmonic_coefficients/mesh_basis_functions.py
@@ -1,4 +1,5 @@
 import numpy as np
+from numpy import typing as npt
 from pydantic import validator
 from pydantic.dataclasses import dataclass
 
@@ -16,7 +17,7 @@ def __post_init_post_parse__(self) -> None:
         self._validate_rank()
         super().__post_init_post_parse__()
 
-    def _create_coefficients(self) -> np.ndarray:
+    def _create_coefficients(self) -> npt.NDArray[np.complex_ | np.float_]:
         """
         compute field on the vertices of the mesh
         """
diff --git a/sleplet/meshes/harmonic_coefficients/mesh_field.py b/sleplet/meshes/harmonic_coefficients/mesh_field.py
index 3cf6e0b6c..52ca59e6c 100644
--- a/sleplet/meshes/harmonic_coefficients/mesh_field.py
+++ b/sleplet/meshes/harmonic_coefficients/mesh_field.py
@@ -1,5 +1,6 @@
 import numpy as np
 from igl import per_vertex_normals
+from numpy import typing as npt
 from pydantic.dataclasses import dataclass
 
 from sleplet.meshes.mesh_harmonic_coefficients import MeshHarmonicCoefficients
@@ -12,7 +13,7 @@ class MeshField(MeshHarmonicCoefficients):
     def __post_init_post_parse__(self) -> None:
         super().__post_init_post_parse__()
 
-    def _create_coefficients(self) -> np.ndarray:
+    def _create_coefficients(self) -> npt.NDArray[np.complex_ | np.float_]:
         """
         compute field on the vertices of the mesh
         """
diff --git a/sleplet/meshes/harmonic_coefficients/mesh_noise_field.py b/sleplet/meshes/harmonic_coefficients/mesh_noise_field.py
index 30ad37bb9..95951cf37 100644
--- a/sleplet/meshes/harmonic_coefficients/mesh_noise_field.py
+++ b/sleplet/meshes/harmonic_coefficients/mesh_noise_field.py
@@ -1,4 +1,5 @@
 import numpy as np
+from numpy import typing as npt
 from pydantic.dataclasses import dataclass
 
 from sleplet.meshes.harmonic_coefficients.mesh_field import MeshField
@@ -15,7 +16,7 @@ class MeshNoiseField(MeshHarmonicCoefficients):
     def __post_init_post_parse__(self) -> None:
         super().__post_init_post_parse__()
 
-    def _create_coefficients(self) -> np.ndarray:
+    def _create_coefficients(self) -> npt.NDArray[np.complex_ | np.float_]:
         mf = MeshField(self.mesh)
         noise = create_mesh_noise(mf.coefficients, self.SNR)
         compute_snr(mf.coefficients, noise, "Harmonic")
diff --git a/sleplet/meshes/mesh_coefficients.py b/sleplet/meshes/mesh_coefficients.py
index 405061500..adaff278d 100644
--- a/sleplet/meshes/mesh_coefficients.py
+++ b/sleplet/meshes/mesh_coefficients.py
@@ -2,6 +2,7 @@
 from dataclasses import KW_ONLY
 
 import numpy as np
+from numpy import typing as npt
 from pydantic import validator
 from pydantic.dataclasses import dataclass
 
@@ -49,14 +50,16 @@ def check_coefficients(cls, v, values):
         return v
 
     @abstractmethod
-    def _add_noise_to_signal(self) -> tuple[np.ndarray | None, float | None]:
+    def _add_noise_to_signal(
+        self,
+    ) -> tuple[npt.NDArray[np.complex_ | np.float_] | None, float | None]:
         """
         adds Gaussian white noise to the signal
         """
         raise NotImplementedError
 
     @abstractmethod
-    def _create_coefficients(self) -> np.ndarray:
+    def _create_coefficients(self) -> npt.NDArray[np.complex_ | np.float_]:
         """
         creates the flm on the north pole
         """
diff --git a/sleplet/meshes/mesh_harmonic_coefficients.py b/sleplet/meshes/mesh_harmonic_coefficients.py
index 1d8b85b7c..bb56889cb 100644
--- a/sleplet/meshes/mesh_harmonic_coefficients.py
+++ b/sleplet/meshes/mesh_harmonic_coefficients.py
@@ -1,6 +1,7 @@
 from abc import abstractmethod
 
 import numpy as np
+from numpy import typing as npt
 from pydantic.dataclasses import dataclass
 
 from sleplet.meshes.mesh_coefficients import MeshCoefficients
@@ -13,7 +14,9 @@ class MeshHarmonicCoefficients(MeshCoefficients):
     def __post_init_post_parse__(self) -> None:
         super().__post_init_post_parse__()
 
-    def _add_noise_to_signal(self) -> tuple[np.ndarray | None, float | None]:
+    def _add_noise_to_signal(
+        self,
+    ) -> tuple[npt.NDArray[np.complex_ | np.float_] | None, float | None]:
         """
         adds Gaussian white noise to the signal
         """
@@ -21,12 +24,12 @@ def _add_noise_to_signal(self) -> tuple[np.ndarray | None, float | None]:
             unnoised_coefficients = self.coefficients.copy()
             nlm = create_mesh_noise(self.coefficients, self.noise)
             snr = compute_snr(self.coefficients, nlm, "Harmonic")
-            self.coefficients += nlm
+            self.coefficients = self.coefficients + nlm
             return unnoised_coefficients, snr
         return None, None
 
     @abstractmethod
-    def _create_coefficients(self) -> np.ndarray:
+    def _create_coefficients(self) -> npt.NDArray[np.complex_ | np.float_]:
         raise NotImplementedError
 
     @abstractmethod
diff --git a/sleplet/meshes/mesh_slepian_coefficients.py b/sleplet/meshes/mesh_slepian_coefficients.py
index 17360ee85..fbcd2a565 100644
--- a/sleplet/meshes/mesh_slepian_coefficients.py
+++ b/sleplet/meshes/mesh_slepian_coefficients.py
@@ -1,6 +1,7 @@
 from abc import abstractmethod
 
 import numpy as np
+from numpy import typing as npt
 from pydantic.dataclasses import dataclass
 
 from sleplet.meshes.classes.mesh_slepian import MeshSlepian
@@ -15,7 +16,9 @@ def __post_init_post_parse__(self) -> None:
         self.mesh_slepian = MeshSlepian(self.mesh)
         super().__post_init_post_parse__()
 
-    def _add_noise_to_signal(self) -> tuple[np.ndarray | None, float | None]:
+    def _add_noise_to_signal(
+        self,
+    ) -> tuple[npt.NDArray[np.complex_ | np.float_] | None, float | None]:
         """
         adds Gaussian white noise converted to Slepian space
         """
@@ -25,12 +28,12 @@ def _add_noise_to_signal(self) -> tuple[np.ndarray | None, float | None]:
                 self.mesh_slepian, self.coefficients, self.noise
             )
             snr = compute_snr(self.coefficients, n_p, "Slepian")
-            self.coefficients += n_p
+            self.coefficients = self.coefficients + n_p
             return unnoised_coefficients, snr
         return None, None
 
     @abstractmethod
-    def _create_coefficients(self) -> np.ndarray:
+    def _create_coefficients(self) -> npt.NDArray[np.complex_ | np.float_]:
         raise NotImplementedError
 
     @abstractmethod
diff --git a/sleplet/meshes/slepian_coefficients/mesh_slepian_field.py b/sleplet/meshes/slepian_coefficients/mesh_slepian_field.py
index a0cabe9ea..6b174525a 100644
--- a/sleplet/meshes/slepian_coefficients/mesh_slepian_field.py
+++ b/sleplet/meshes/slepian_coefficients/mesh_slepian_field.py
@@ -1,4 +1,5 @@
 import numpy as np
+from numpy import typing as npt
 from pydantic.dataclasses import dataclass
 
 from sleplet.meshes.harmonic_coefficients.mesh_field import MeshField
@@ -12,7 +13,7 @@ class MeshSlepianField(MeshSlepianCoefficients):
     def __post_init_post_parse__(self) -> None:
         super().__post_init_post_parse__()
 
-    def _create_coefficients(self) -> np.ndarray:
+    def _create_coefficients(self) -> npt.NDArray[np.complex_ | np.float_]:
         """
         compute field on the vertices of the mesh
         """
diff --git a/sleplet/meshes/slepian_coefficients/mesh_slepian_functions.py b/sleplet/meshes/slepian_coefficients/mesh_slepian_functions.py
index 50e7153b4..5766f3728 100644
--- a/sleplet/meshes/slepian_coefficients/mesh_slepian_functions.py
+++ b/sleplet/meshes/slepian_coefficients/mesh_slepian_functions.py
@@ -1,4 +1,5 @@
 import numpy as np
+from numpy import typing as npt
 from pydantic import validator
 from pydantic.dataclasses import dataclass
 
@@ -15,7 +16,7 @@ class MeshSlepianFunctions(MeshSlepianCoefficients):
     def __post_init_post_parse__(self) -> None:
         super().__post_init_post_parse__()
 
-    def _create_coefficients(self) -> np.ndarray:
+    def _create_coefficients(self) -> npt.NDArray[np.complex_ | np.float_]:
         """
         compute field on the vertices of the mesh
         """
diff --git a/sleplet/meshes/slepian_coefficients/mesh_slepian_noise_field.py b/sleplet/meshes/slepian_coefficients/mesh_slepian_noise_field.py
index beb543f66..fd4339428 100644
--- a/sleplet/meshes/slepian_coefficients/mesh_slepian_noise_field.py
+++ b/sleplet/meshes/slepian_coefficients/mesh_slepian_noise_field.py
@@ -1,4 +1,5 @@
 import numpy as np
+from numpy import typing as npt
 from pydantic.dataclasses import dataclass
 
 from sleplet.meshes.mesh_slepian_coefficients import MeshSlepianCoefficients
@@ -15,7 +16,7 @@ class MeshSlepianNoiseField(MeshSlepianCoefficients):
     def __post_init_post_parse__(self) -> None:
         super().__post_init_post_parse__()
 
-    def _create_coefficients(self) -> np.ndarray:
+    def _create_coefficients(self) -> npt.NDArray[np.complex_ | np.float_]:
         smf = MeshSlepianField(self.mesh, region=True)
         noise = create_slepian_mesh_noise(self.mesh_slepian, smf.coefficients, self.SNR)
         compute_snr(smf.coefficients, noise, "Slepian")
diff --git a/sleplet/meshes/slepian_coefficients/mesh_slepian_wavelet_coefficients.py b/sleplet/meshes/slepian_coefficients/mesh_slepian_wavelet_coefficients.py
index 1c40cc3b7..75926e304 100644
--- a/sleplet/meshes/slepian_coefficients/mesh_slepian_wavelet_coefficients.py
+++ b/sleplet/meshes/slepian_coefficients/mesh_slepian_wavelet_coefficients.py
@@ -1,4 +1,5 @@
 import numpy as np
+from numpy import typing as npt
 from pydantic import validator
 from pydantic.dataclasses import dataclass
 from pys2let import pys2let_j_max
@@ -23,7 +24,7 @@ class MeshSlepianWaveletCoefficients(MeshSlepianCoefficients):
     def __post_init_post_parse__(self) -> None:
         super().__post_init_post_parse__()
 
-    def _create_coefficients(self) -> np.ndarray:
+    def _create_coefficients(self) -> npt.NDArray[np.complex_ | np.float_]:
         logger.info("start computing wavelet coefficients")
         self.wavelet_coefficients = self._create_wavelet_coefficients()
         logger.info("finish computing wavelet coefficients")
@@ -45,7 +46,9 @@ def _setup_args(self) -> None:
                 raise ValueError(f"The number of extra arguments should be {num_args}")
             self.B, self.j_min, self.j = self.extra_args
 
-    def _create_wavelet_coefficients(self) -> tuple[np.ndarray, np.ndarray]:
+    def _create_wavelet_coefficients(
+        self,
+    ) -> tuple[npt.NDArray[np.float_], npt.NDArray[np.complex_ | np.float_]]:
         """
         computes wavelet coefficients in Slepian space
         """
diff --git a/sleplet/meshes/slepian_coefficients/mesh_slepian_wavelets.py b/sleplet/meshes/slepian_coefficients/mesh_slepian_wavelets.py
index c08fed6b2..e25993a3c 100644
--- a/sleplet/meshes/slepian_coefficients/mesh_slepian_wavelets.py
+++ b/sleplet/meshes/slepian_coefficients/mesh_slepian_wavelets.py
@@ -1,4 +1,5 @@
 import numpy as np
+from numpy import typing as npt
 from pydantic import validator
 from pydantic.dataclasses import dataclass
 from pys2let import pys2let_j_max
@@ -19,7 +20,7 @@ class MeshSlepianWavelets(MeshSlepianCoefficients):
     def __post_init_post_parse__(self) -> None:
         super().__post_init_post_parse__()
 
-    def _create_coefficients(self) -> np.ndarray:
+    def _create_coefficients(self) -> npt.NDArray[np.complex_ | np.float_]:
         logger.info("start computing wavelets")
         self.wavelets = self._create_wavelets()
         logger.info("finish computing wavelets")
@@ -41,7 +42,7 @@ def _setup_args(self) -> None:
                 raise ValueError(f"The number of extra arguments should be {num_args}")
             self.B, self.j_min, self.j = self.extra_args
 
-    def _create_wavelets(self) -> np.ndarray:
+    def _create_wavelets(self) -> npt.NDArray[np.float_]:
         """
         creates the Slepian wavelets of the mesh
         """
diff --git a/sleplet/plotting/create_plot_mesh.py b/sleplet/plotting/create_plot_mesh.py
index 639e3df83..8ff7b4a8c 100644
--- a/sleplet/plotting/create_plot_mesh.py
+++ b/sleplet/plotting/create_plot_mesh.py
@@ -5,6 +5,7 @@
 import numpy as np
 import plotly.offline as py
 from matplotlib.colors import LinearSegmentedColormap
+from numpy import typing as npt
 from plotly.graph_objs import Figure, Mesh3d
 from plotly.graph_objs.mesh3d import Lighting
 from pydantic.dataclasses import dataclass
@@ -31,7 +32,7 @@
 class Plot:
     mesh: Mesh
     filename: str
-    f: np.ndarray
+    f: npt.NDArray[np.complex_ | np.float_]
     _: KW_ONLY
     amplitude: float | None = None
     colour: LinearSegmentedColormap = cmocean.cm.ice
@@ -98,7 +99,9 @@ def execute(self) -> None:
                 filename = str(_fig_path / file_type / f"{self.filename}.{file_type}")
                 fig.write_image(filename, engine="kaleido")
 
-    def _prepare_field(self, f: np.ndarray) -> np.ndarray:
+    def _prepare_field(
+        self, f: npt.NDArray[np.complex_ | np.float_]
+    ) -> npt.NDArray[np.float_]:
         """
         scales the field before plotting
         """
@@ -106,7 +109,9 @@ def _prepare_field(self, f: np.ndarray) -> np.ndarray:
             average_functions_on_vertices_to_faces(self.mesh.faces, f), self.normalise
         )
 
-    def _set_outside_region_to_minimum(self, f: np.ndarray) -> np.ndarray:
+    def _set_outside_region_to_minimum(
+        self, f: npt.NDArray[np.float_]
+    ) -> npt.NDArray[np.float_]:
         """
         for the Slepian region set the outisde area to negative infinity
         hence it is clear we are only interested in the coloured region
diff --git a/sleplet/plotting/create_plot_sphere.py b/sleplet/plotting/create_plot_sphere.py
index a945000ab..a3d498804 100644
--- a/sleplet/plotting/create_plot_sphere.py
+++ b/sleplet/plotting/create_plot_sphere.py
@@ -5,6 +5,7 @@
 import numpy as np
 import plotly.offline as py
 import pyssht as ssht
+from numpy import typing as npt
 from plotly.graph_objs import Figure, Surface
 from plotly.graph_objs.surface import Lighting
 from pydantic.dataclasses import dataclass
@@ -37,7 +38,7 @@
 
 @dataclass(config=Validation)
 class Plot:
-    f: np.ndarray
+    f: npt.NDArray[np.complex_ | np.float_]
     L: int
     filename: str
     _: KW_ONLY
@@ -113,14 +114,21 @@ def execute(self) -> None:
 
     @staticmethod
     def _setup_plot(
-        f: np.ndarray,
+        f: npt.NDArray[np.float_],
         resolution: int,
         method: str = "MW",
         close: bool = True,
         parametric: bool = False,
         parametric_scaling: list[float] | None = None,
         color_range: list[float] | None = None,
-    ) -> tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray, float, float]:
+    ) -> tuple[
+        npt.NDArray[np.float_],
+        npt.NDArray[np.float_],
+        npt.NDArray[np.float_],
+        npt.NDArray[np.float_],
+        float,
+        float,
+    ]:
         """
         function which creates the data for the matplotlib/plotly plot
         """
@@ -180,7 +188,9 @@ def _setup_plot(
 
         return x, y, z, f_plot, vmin, vmax
 
-    def _prepare_field(self, f: np.ndarray) -> np.ndarray:
+    def _prepare_field(
+        self, f: npt.NDArray[np.complex_ | np.float_]
+    ) -> npt.NDArray[np.float_]:
         """
         boosts, forces plot type and then scales the field before plotting
         """
diff --git a/sleplet/plotting/misc/wavelet_transform.py b/sleplet/plotting/misc/wavelet_transform.py
index 7805c068c..2107ce76c 100644
--- a/sleplet/plotting/misc/wavelet_transform.py
+++ b/sleplet/plotting/misc/wavelet_transform.py
@@ -3,6 +3,7 @@
 import numpy as np
 import seaborn as sns
 from matplotlib import pyplot as plt
+from numpy import typing as npt
 
 from sleplet.utils.plot_methods import save_plot
 
@@ -29,7 +30,7 @@ def main() -> None:
     save_plot(fig_path, "ricker_wavelets")
 
 
-def _ricker(freq: float) -> np.ndarray:
+def _ricker(freq: float) -> npt.NDArray[np.float_]:
     """
     creates a Ricker wavelet
     """
diff --git a/sleplet/plotting/plotting_utils.py b/sleplet/plotting/plotting_utils.py
index 3572f560e..5fb52eb5b 100644
--- a/sleplet/plotting/plotting_utils.py
+++ b/sleplet/plotting/plotting_utils.py
@@ -1,11 +1,14 @@
 import numpy as np
+from numpy import typing as npt
 
 from sleplet.functions.flm.earth import Earth
 from sleplet.utils.region import Region
 from sleplet.utils.slepian_methods import choose_slepian_method, slepian_forward
 
 
-def earth_region_harmonic_coefficients(L: int, theta_max: int) -> np.ndarray:
+def earth_region_harmonic_coefficients(
+    L: int, theta_max: int
+) -> npt.NDArray[np.float_]:
     """
     harmonic coefficients of the Earth for the polar cap region
     """
@@ -16,7 +19,7 @@ def earth_region_harmonic_coefficients(L: int, theta_max: int) -> np.ndarray:
     return coefficients
 
 
-def earth_region_slepian_coefficients(L: int, theta_max: int) -> np.ndarray:
+def earth_region_slepian_coefficients(L: int, theta_max: int) -> npt.NDArray[np.float_]:
     """
     computes the Slepian coefficients
     """
diff --git a/sleplet/plotting/polar_cap/eigenfunctions.py b/sleplet/plotting/polar_cap/eigenfunctions.py
index 723975544..12892142d 100644
--- a/sleplet/plotting/polar_cap/eigenfunctions.py
+++ b/sleplet/plotting/polar_cap/eigenfunctions.py
@@ -3,6 +3,7 @@
 import numpy as np
 import seaborn as sns
 from matplotlib import pyplot as plt
+from numpy import typing as npt
 
 from sleplet.plotting.inputs import TEXT_BOX, THETA_MAX
 from sleplet.slepian.slepian_region.slepian_polar_cap import SlepianPolarCap
@@ -51,7 +52,7 @@ def main() -> None:
 def _helper(
     ax: plt.Axes,
     slepian: SlepianPolarCap,
-    x: np.ndarray,
+    x: npt.NDArray[np.float_],
     i: int,
     rank: int,
 ) -> None:
diff --git a/sleplet/plotting/polar_cap/simons_5_1_.py b/sleplet/plotting/polar_cap/simons_5_1_.py
index 3fec29523..5f1fe3141 100644
--- a/sleplet/plotting/polar_cap/simons_5_1_.py
+++ b/sleplet/plotting/polar_cap/simons_5_1_.py
@@ -3,6 +3,7 @@
 import numpy as np
 import seaborn as sns
 from matplotlib import pyplot as plt
+from numpy import typing as npt
 
 from sleplet.plotting.inputs import TEXT_BOX, THETA_MAX
 from sleplet.slepian.slepian_region.slepian_polar_cap import SlepianPolarCap
@@ -47,10 +48,10 @@ def main() -> None:
 
 
 def _helper(
-    ax: np.ndarray,
+    ax: npt.NDArray,
     slepian: SlepianPolarCap,
     resolution: int,
-    x: np.ndarray,
+    x: npt.NDArray[np.float_],
     i: int,
     order: int,
     rank: int,
diff --git a/sleplet/plotting/polar_cap/simons_5_3.py b/sleplet/plotting/polar_cap/simons_5_3.py
index dea44f9b6..e1f690bfb 100644
--- a/sleplet/plotting/polar_cap/simons_5_3.py
+++ b/sleplet/plotting/polar_cap/simons_5_3.py
@@ -3,6 +3,7 @@
 import numpy as np
 import seaborn as sns
 from matplotlib import pyplot as plt
+from numpy import typing as npt
 
 from sleplet.plotting.inputs import TEXT_BOX
 from sleplet.slepian.slepian_region.slepian_polar_cap import SlepianPolarCap
@@ -31,7 +32,7 @@ def main() -> None:
     save_plot(fig_path, "simons_5_3")
 
 
-def _create_plot(ax: np.ndarray, position: tuple[int, int], theta_max: int) -> None:
+def _create_plot(ax: npt.NDArray, position: tuple[int, int], theta_max: int) -> None:
     """
     helper method which actually makes the plot
     """
diff --git a/sleplet/plotting/polar_cap/slepian_error.py b/sleplet/plotting/polar_cap/slepian_error.py
index 96c01738f..fe1571176 100644
--- a/sleplet/plotting/polar_cap/slepian_error.py
+++ b/sleplet/plotting/polar_cap/slepian_error.py
@@ -4,6 +4,7 @@
 import pyssht as ssht
 import seaborn as sns
 from matplotlib import pyplot as plt
+from numpy import typing as npt
 
 from sleplet.functions.flm.earth import Earth
 from sleplet.plotting.inputs import THETA_MAX
@@ -48,8 +49,11 @@ def main() -> None:
 
 
 def _helper_sphere(
-    L: int, slepian: SlepianFunctions, f: np.ndarray, flm: np.ndarray
-) -> np.ndarray:
+    L: int,
+    slepian: SlepianFunctions,
+    f: npt.NDArray[np.complex_],
+    flm: npt.NDArray[np.complex_ | np.float_],
+) -> npt.NDArray[np.float_]:
     """
     the difference in Slepian coefficients by integration of whole sphere
     """
@@ -59,8 +63,12 @@ def _helper_sphere(
 
 
 def _helper_region(
-    L: int, slepian: SlepianFunctions, f: np.ndarray, flm: np.ndarray, mask: np.ndarray
-) -> np.ndarray:
+    L: int,
+    slepian: SlepianFunctions,
+    f: npt.NDArray[np.complex_],
+    flm: npt.NDArray[np.complex_ | np.float_],
+    mask: npt.NDArray[np.float_],
+) -> npt.NDArray[np.float_]:
     """
     the difference in Slepian coefficients by integration of region on the sphere
     """
diff --git a/sleplet/scripts/plotting_on_mesh.py b/sleplet/scripts/plotting_on_mesh.py
index f40a5680d..dbb7570c8 100644
--- a/sleplet/scripts/plotting_on_mesh.py
+++ b/sleplet/scripts/plotting_on_mesh.py
@@ -2,6 +2,7 @@
 from argparse import ArgumentParser, Namespace
 
 import numpy as np
+from numpy import typing as npt
 
 from sleplet.meshes.classes.mesh import Mesh
 from sleplet.meshes.mesh_coefficients import MeshCoefficients
@@ -103,7 +104,9 @@ def plot(f: MeshCoefficients, normalise: bool, amplitude: float | None) -> None:
     ).execute()
 
 
-def _coefficients_to_field(f: MeshCoefficients, coefficients: np.ndarray) -> np.ndarray:
+def _coefficients_to_field(
+    f: MeshCoefficients, coefficients: npt.NDArray[np.complex_ | np.float_]
+) -> npt.NDArray[np.complex_ | np.float_]:
     """
     computes the field over the whole mesh from the harmonic/Slepian coefficients
     """
diff --git a/sleplet/scripts/plotting_on_sphere.py b/sleplet/scripts/plotting_on_sphere.py
index a57285141..2b22520e7 100644
--- a/sleplet/scripts/plotting_on_sphere.py
+++ b/sleplet/scripts/plotting_on_sphere.py
@@ -3,6 +3,7 @@
 
 import numpy as np
 import pyssht as ssht
+from numpy import typing as npt
 
 from sleplet.functions.coefficients import Coefficients
 from sleplet.functions.f_p import F_P
@@ -245,7 +246,7 @@ def _rotation_helper(
     alpha_pi_frac: float,
     beta_pi_frac: float,
     gamma_pi_frac: float,
-) -> tuple[np.ndarray, str]:
+) -> tuple[npt.NDArray[np.complex_], str]:
     """
     performs the rotation specific steps
     """
@@ -270,7 +271,7 @@ def _translation_helper(
     alpha_pi_frac: float,
     beta_pi_frac: float,
     shannon: int | None,
-) -> tuple[np.ndarray, str, dict]:
+) -> tuple[npt.NDArray[np.complex_ | np.float_], str, dict]:
     """
     performs the translation specific steps
     """
@@ -296,10 +297,10 @@ def _translation_helper(
 def _convolution_helper(
     f: Coefficients,
     g: Coefficients,
-    coefficients: np.ndarray,
+    coefficients: npt.NDArray[np.complex_ | np.float_],
     shannon: int | None,
     filename: str,
-) -> tuple[np.ndarray, str]:
+) -> tuple[npt.NDArray[np.complex_ | np.float_], str]:
     """
     performs the convolution specific steps
     """
@@ -314,7 +315,9 @@ def _convolution_helper(
     return coefficients, filename
 
 
-def _coefficients_to_field(f: Coefficients, coefficients: np.ndarray) -> np.ndarray:
+def _coefficients_to_field(
+    f: Coefficients, coefficients: npt.NDArray[np.complex_ | np.float_]
+) -> npt.NDArray[np.complex_ | np.float_]:
     """
     computes the field over the samples from the harmonic/Slepian coefficients
     """
diff --git a/sleplet/slepian/slepian_decomposition.py b/sleplet/slepian/slepian_decomposition.py
index 6e95167fa..bc3cabe2e 100644
--- a/sleplet/slepian/slepian_decomposition.py
+++ b/sleplet/slepian/slepian_decomposition.py
@@ -2,6 +2,7 @@
 
 import numpy as np
 import pyssht as ssht
+from numpy import typing as npt
 from pydantic.dataclasses import dataclass
 
 from sleplet.slepian.slepian_functions import SlepianFunctions
@@ -20,9 +21,9 @@ class SlepianDecomposition:
     L: int
     slepian: SlepianFunctions
     _: KW_ONLY
-    f: np.ndarray | None = None
-    flm: np.ndarray | None = None
-    mask: np.ndarray | None = None
+    f: npt.NDArray[np.complex_] | None = None
+    flm: npt.NDArray[np.complex_ | np.float_] | None = None
+    mask: npt.NDArray[np.float_] | None = None
 
     def __post_init_post_parse__(self) -> None:
         self._detect_method()
@@ -43,7 +44,7 @@ def decompose(self, rank: int) -> complex:
             case _:
                 raise ValueError(f"'{self.method}' is not a valid method")
 
-    def decompose_all(self, n_coefficients: int) -> np.ndarray:
+    def decompose_all(self, n_coefficients: int) -> npt.NDArray[np.complex_]:
         """
         decompose all ranks of the Slepian coefficients
         """
diff --git a/sleplet/slepian/slepian_functions.py b/sleplet/slepian/slepian_functions.py
index ce9b7feff..8b96ca59f 100644
--- a/sleplet/slepian/slepian_functions.py
+++ b/sleplet/slepian/slepian_functions.py
@@ -2,6 +2,7 @@
 from pathlib import Path
 
 import numpy as np
+from numpy import typing as npt
 from pydantic.dataclasses import dataclass
 
 from sleplet.utils.logger import logger
@@ -40,7 +41,7 @@ def _create_region(self) -> Region:
         raise NotImplementedError
 
     @abstractmethod
-    def _create_mask(self) -> np.ndarray:
+    def _create_mask(self) -> npt.NDArray[np.float_]:
         """
         creates a mask of the region of interest
         """
@@ -61,7 +62,9 @@ def _create_matrix_location(self) -> Path:
         raise NotImplementedError
 
     @abstractmethod
-    def _solve_eigenproblem(self) -> tuple[np.ndarray, np.ndarray]:
+    def _solve_eigenproblem(
+        self,
+    ) -> tuple[npt.NDArray[np.float_], npt.NDArray[np.complex_]]:
         """
         solves the eigenproblem for the given function
         """
diff --git a/sleplet/slepian/slepian_region/slepian_arbitrary.py b/sleplet/slepian/slepian_region/slepian_arbitrary.py
index 2700b36e8..217c6b98f 100644
--- a/sleplet/slepian/slepian_region/slepian_arbitrary.py
+++ b/sleplet/slepian/slepian_region/slepian_arbitrary.py
@@ -5,6 +5,7 @@
 import numpy as np
 import pyssht as ssht
 from numpy import linalg as LA
+from numpy import typing as npt
 from pydantic import validator
 from pydantic.dataclasses import dataclass
 
@@ -51,7 +52,7 @@ def _create_fn_name(self) -> str:
     def _create_region(self) -> Region:
         return Region(mask_name=self.mask_name)
 
-    def _create_mask(self) -> np.ndarray:
+    def _create_mask(self) -> npt.NDArray[np.float_]:
         return create_mask_region(self.resolution, self.region)
 
     def _calculate_area(self) -> float:
@@ -63,7 +64,9 @@ def _create_matrix_location(self) -> Path:
             _slepian_path / "eigensolutions" / f"D_{self.mask_name}_L{self.L}_N{self.N}"
         )
 
-    def _solve_eigenproblem(self) -> tuple[np.ndarray, np.ndarray]:
+    def _solve_eigenproblem(
+        self,
+    ) -> tuple[npt.NDArray[np.float_], npt.NDArray[np.complex_]]:
         eval_loc = self.matrix_location / "eigenvalues.npy"
         evec_loc = self.matrix_location / "eigenvectors.npy"
         if not eval_loc.exists() or not evec_loc.exists():
@@ -94,12 +97,12 @@ def _solve_D_matrix(self, eval_loc, evec_loc):
             np.save(evec_loc, eigenvectors[: self.N])
         return eigenvalues, eigenvectors
 
-    def _create_D_matrix(self) -> np.ndarray:
+    def _create_D_matrix(self) -> npt.NDArray[np.complex_]:
         """
         computes the D matrix in parallel
         """
         # create dictionary for the integrals
-        self._fields: dict[int, np.ndarray] = {}
+        self._fields: dict[int, npt.NDArray[np.complex_ | np.float_]] = {}
 
         # initialise real and imaginary matrices
         D_r = np.zeros((self.L**2, self.L**2))
@@ -139,7 +142,9 @@ def func(chunk: list[int]) -> None:
         release_shared_memory(shm_r_ext, shm_i_ext)
         return D
 
-    def _matrix_helper(self, D_r: np.ndarray, D_i: np.ndarray, i: int) -> None:
+    def _matrix_helper(
+        self, D_r: npt.NDArray[np.float_], D_i: npt.NDArray[np.float_], i: int
+    ) -> None:
         """
         used in both serial and parallel calculations
 
diff --git a/sleplet/slepian/slepian_region/slepian_limit_lat_lon.py b/sleplet/slepian/slepian_region/slepian_limit_lat_lon.py
index 68cf24ed0..5bfdb4a3d 100644
--- a/sleplet/slepian/slepian_region/slepian_limit_lat_lon.py
+++ b/sleplet/slepian/slepian_region/slepian_limit_lat_lon.py
@@ -4,6 +4,7 @@
 import pyssht as ssht
 from numba import njit, prange
 from numpy import linalg as LA
+from numpy import typing as npt
 from pydantic.dataclasses import dataclass
 
 from sleplet.slepian.slepian_functions import SlepianFunctions
@@ -45,7 +46,7 @@ def _create_region(self) -> Region:
             phi_max=self.phi_max,
         )
 
-    def _create_mask(self) -> np.ndarray:
+    def _create_mask(self) -> npt.NDArray[np.float_]:
         return create_mask_region(self.L, self.region)
 
     def _calculate_area(self) -> float:
@@ -56,7 +57,9 @@ def _calculate_area(self) -> float:
     def _create_matrix_location(self) -> Path:
         return _eigen_path / f"D_{self.region.name_ending}_L{self.L}_N{self.N}"
 
-    def _solve_eigenproblem(self) -> tuple[np.ndarray, np.ndarray]:
+    def _solve_eigenproblem(
+        self,
+    ) -> tuple[npt.NDArray[np.float_], npt.NDArray[np.complex_]]:
         eval_loc = self.matrix_location / "eigenvalues.npy"
         evec_loc = self.matrix_location / "eigenvectors.npy"
         if eval_loc.exists() and evec_loc.exists():
@@ -70,7 +73,7 @@ def _solve_eigenproblem(self) -> tuple[np.ndarray, np.ndarray]:
                 np.save(evec_loc, eigenvectors[: self.N])
             return eigenvalues, eigenvectors
 
-    def _create_K_matrix(self) -> np.ndarray:
+    def _create_K_matrix(self) -> npt.NDArray[np.complex_]:
         """
         computes the K matrix
         """
@@ -84,7 +87,7 @@ def _create_K_matrix(self) -> np.ndarray:
 
         return K
 
-    def _slepian_integral(self) -> np.ndarray:
+    def _slepian_integral(self) -> npt.NDArray[np.complex_]:
         """
         Syntax:
         G = _slepian_integral()
@@ -143,7 +146,9 @@ def helper(row: int, col: int, S: float) -> None:
 
     @staticmethod
     @njit(parallel=True, fastmath=True)
-    def _slepian_matrix(dl: np.ndarray, L: int, N: int, G: np.ndarray) -> np.ndarray:
+    def _slepian_matrix(
+        dl: npt.NDArray[np.float_], L: int, N: int, G: npt.NDArray[np.complex_]
+    ) -> npt.NDArray[np.complex_]:
         """
         Syntax:
         K = _slepian_matrix(dl, L, N, G)
@@ -194,7 +199,7 @@ def _slepian_matrix(dl: np.ndarray, L: int, N: int, G: np.ndarray) -> np.ndarray
     @staticmethod
     def _clean_evals_and_evecs(
         eigendecomposition: tuple,
-    ) -> tuple[np.ndarray, np.ndarray]:
+    ) -> tuple[npt.NDArray[np.float_], npt.NDArray[np.complex_]]:
         """
         need eigenvalues and eigenvectors to be in a certain format
         """
diff --git a/sleplet/slepian/slepian_region/slepian_polar_cap.py b/sleplet/slepian/slepian_region/slepian_polar_cap.py
index 44b21e12a..b4a7b867a 100644
--- a/sleplet/slepian/slepian_region/slepian_polar_cap.py
+++ b/sleplet/slepian/slepian_region/slepian_polar_cap.py
@@ -6,6 +6,7 @@
 import numpy as np
 import pyssht as ssht
 from numpy import linalg as LA
+from numpy import typing as npt
 from pydantic import validator
 from pydantic.dataclasses import dataclass
 
@@ -35,7 +36,7 @@ class SlepianPolarCap(SlepianFunctions):
     theta_max: float
     _: KW_ONLY
     gap: bool = False
-    order: int | np.ndarray | None = None
+    order: int | npt.NDArray[np.int_] | None = None
 
     def __post_init_post_parse__(self) -> None:
         super().__post_init_post_parse__()
@@ -46,7 +47,7 @@ def _create_fn_name(self) -> str:
     def _create_region(self) -> Region:
         return Region(gap=self.gap, theta_max=self.theta_max)
 
-    def _create_mask(self) -> np.ndarray:
+    def _create_mask(self) -> npt.NDArray[np.float_]:
         return create_mask_region(self.L, self.region)
 
     def _calculate_area(self) -> float:
@@ -55,7 +56,9 @@ def _calculate_area(self) -> float:
     def _create_matrix_location(self) -> Path:
         return _eigen_path / f"D_{self.region.name_ending}_L{self.L}_N{self.N}"
 
-    def _solve_eigenproblem(self) -> tuple[np.ndarray, np.ndarray]:
+    def _solve_eigenproblem(
+        self,
+    ) -> tuple[npt.NDArray[np.float_], npt.NDArray[np.complex_]]:
         eval_loc = self.matrix_location / "eigenvalues.npy"
         evec_loc = self.matrix_location / "eigenvectors.npy"
         order_loc = self.matrix_location / "orders.npy"
@@ -67,7 +70,7 @@ def _solve_eigenproblem(self) -> tuple[np.ndarray, np.ndarray]:
 
     def _solve_eigenproblem_from_files(
         self, eval_loc: Path, evec_loc: Path, order_loc: Path
-    ) -> tuple[np.ndarray, np.ndarray]:
+    ) -> tuple[npt.NDArray[np.float_], npt.NDArray[np.complex_]]:
         """
         solves eigenproblem with files already saved
         """
@@ -84,7 +87,7 @@ def _solve_eigenproblem_from_files(
 
     def _solve_eigenproblem_from_scratch(
         self, eval_loc: Path, evec_loc: Path, order_loc: Path
-    ) -> tuple[np.ndarray, np.ndarray]:
+    ) -> tuple[npt.NDArray[np.float_], npt.NDArray[np.complex_]]:
         """
         sovles eigenproblem from scratch and then saves the files
         """
@@ -111,7 +114,9 @@ def _solve_eigenproblem_from_scratch(
             np.save(order_loc, self.order)
         return eigenvalues, eigenvectors
 
-    def _solve_eigenproblem_order(self, m: int) -> tuple[np.ndarray, np.ndarray]:
+    def _solve_eigenproblem_order(
+        self, m: int
+    ) -> tuple[npt.NDArray[np.float_], npt.NDArray[np.complex_]]:
         """
         solves the eigenproblem for a given order 'm;
         """
@@ -122,8 +127,11 @@ def _solve_eigenproblem_order(self, m: int) -> tuple[np.ndarray, np.ndarray]:
         return eigenvalues, eigenvectors
 
     def _sort_all_evals_and_evecs(
-        self, eigenvalues: np.ndarray, eigenvectors: np.ndarray, orders: np.ndarray
-    ) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
+        self,
+        eigenvalues: npt.NDArray[np.float_],
+        eigenvectors: npt.NDArray[np.complex_],
+        orders: npt.NDArray[np.int_],
+    ) -> tuple[npt.NDArray[np.float_], npt.NDArray[np.complex_], npt.NDArray[np.int_]]:
         """
         sorts all eigenvalues and eigenvectors for all orders
         """
@@ -133,7 +141,9 @@ def _sort_all_evals_and_evecs(
         orders = orders[idx]
         return eigenvalues, eigenvectors, orders
 
-    def _create_Dm_matrix(self, m: int, emm: np.ndarray) -> np.ndarray:
+    def _create_Dm_matrix(
+        self, m: int, emm: npt.NDArray[np.float_]
+    ) -> npt.NDArray[np.float_]:
         """
         Syntax:
         Dm = _create_Dm_matrix(m, P)
@@ -187,8 +197,8 @@ def func(chunk: list[int]) -> None:
         return Dm
 
     def _create_legendre_polynomials_table(
-        self, emm: np.ndarray
-    ) -> tuple[np.ndarray, np.ndarray]:
+        self, emm: npt.NDArray[np.float_]
+    ) -> tuple[npt.NDArray[np.float_], npt.NDArray[np.int_]]:
         """
         create Legendre polynomials table for matrix calculation
         """
@@ -200,12 +210,12 @@ def _create_legendre_polynomials_table(
 
     def _dm_matrix_helper(
         self,
-        Dm: np.ndarray,
+        Dm: npt.NDArray[np.float_],
         i: int,
         m: int,
-        lvec: np.ndarray,
-        Pl: np.ndarray,
-        ell: np.ndarray,
+        lvec: npt.NDArray[np.int_],
+        Pl: npt.NDArray[np.float_],
+        ell: npt.NDArray[np.int_],
     ) -> None:
         """
         used in both serial and parallel calculations
@@ -321,14 +331,15 @@ def _polar_gap_modification(self, ell1: int, ell2: int) -> int:
         return 1 + self.gap * (-1) ** (ell1 + ell2)
 
     def _clean_evals_and_evecs(
-        self, eigenvalues: np.ndarray, gl: np.ndarray, emm: np.ndarray, m: int
-    ) -> tuple[np.ndarray, np.ndarray]:
+        self,
+        eigenvalues: npt.NDArray[np.float_],
+        gl: npt.NDArray[np.float_],
+        emm: npt.NDArray[np.float_],
+        m: int,
+    ) -> tuple[npt.NDArray[np.float_], npt.NDArray[np.complex_]]:
         """
         need eigenvalues and eigenvectors to be in a certain format
         """
-        # eigenvalues should be real
-        eigenvalues = eigenvalues.real
-
         # Sort eigenvalues and eigenvectors in descending order of eigenvalues
         idx = eigenvalues.argsort()[::-1]
         eigenvalues = eigenvalues[idx]
diff --git a/sleplet/utils/array_methods.py b/sleplet/utils/array_methods.py
index dc5027bd4..5522b9f22 100644
--- a/sleplet/utils/array_methods.py
+++ b/sleplet/utils/array_methods.py
@@ -1,7 +1,10 @@
+from typing import Any
+
 import numpy as np
+from numpy import typing as npt
 
 
-def fill_upper_triangle_of_hermitian_matrix(matrix: np.ndarray) -> None:
+def fill_upper_triangle_of_hermitian_matrix(matrix: npt.NDArray[Any]) -> None:
     """
     using Hermitian matrix symmetry can avoid repeated calculations
     """
diff --git a/sleplet/utils/convolution_methods.py b/sleplet/utils/convolution_methods.py
index 271a16890..bbdbf1f5e 100644
--- a/sleplet/utils/convolution_methods.py
+++ b/sleplet/utils/convolution_methods.py
@@ -1,12 +1,13 @@
 import numpy as np
+from numpy import typing as npt
 
 
 def sifting_convolution(
-    f_coefficient: np.ndarray,
-    g_coefficient: np.ndarray,
+    f_coefficient: npt.NDArray[np.complex_ | np.float_],
+    g_coefficient: npt.NDArray[np.complex_ | np.float_],
     *,
     shannon: int | None = None,
-) -> np.ndarray:
+) -> npt.NDArray[np.complex_ | np.float_]:
     """
     computes the sifting convolution between two multipoles
     """
diff --git a/sleplet/utils/denoising.py b/sleplet/utils/denoising.py
index 49e8179fe..b1a4aee2a 100644
--- a/sleplet/utils/denoising.py
+++ b/sleplet/utils/denoising.py
@@ -1,5 +1,6 @@
 import numpy as np
 import pyssht as ssht
+from numpy import typing as npt
 
 from sleplet.functions.coefficients import Coefficients
 from sleplet.functions.f_p import F_P
@@ -39,7 +40,7 @@ def denoising_axisym(
     n_sigma: int,
     *,
     rotate_to_south_america: bool = False,
-) -> tuple[np.ndarray, float | None, float]:
+) -> tuple[npt.NDArray[np.complex_], float | None, float]:
     """
     reproduce the denoising demo from s2let paper
     """
@@ -81,7 +82,7 @@ def denoising_slepian_wavelet(
     slepian_wavelets: SlepianWavelets,
     snr_in: float,
     n_sigma: int,
-) -> np.ndarray:
+) -> npt.NDArray[np.complex_]:
     """
     denoising demo using Slepian wavelets
     """
@@ -122,7 +123,7 @@ def denoising_slepian_function(
     noised_signal: F_P,
     snr_in: float,
     n_sigma: int,
-) -> np.ndarray:
+) -> npt.NDArray[np.complex_]:
     """
     denoising demo using Slepian function
     """
@@ -148,7 +149,7 @@ def denoising_mesh_slepian(
     mesh_slepian_wavelets: MeshSlepianWavelets,
     snr_in: float,
     n_sigma: int,
-) -> np.ndarray:
+) -> npt.NDArray[np.complex_ | np.float_]:
     """
     denoising demo using Slepian wavelets
     """
diff --git a/sleplet/utils/harmonic_methods.py b/sleplet/utils/harmonic_methods.py
index 253f3008f..da94d2aa0 100644
--- a/sleplet/utils/harmonic_methods.py
+++ b/sleplet/utils/harmonic_methods.py
@@ -1,7 +1,8 @@
-from collections.abc import Callable
+from typing import Any, Callable
 
 import numpy as np
 import pyssht as ssht
+from numpy import typing as npt
 from numpy.random import Generator
 
 from sleplet.meshes.classes.mesh import Mesh
@@ -9,7 +10,7 @@
 from sleplet.utils.vars import SAMPLING_SCHEME
 
 
-def create_spherical_harmonic(L: int, ind: int) -> np.ndarray:
+def create_spherical_harmonic(L: int, ind: int) -> npt.NDArray[np.complex_]:
     """
     create a spherical harmonic in harmonic space for the given index
     """
@@ -18,7 +19,7 @@ def create_spherical_harmonic(L: int, ind: int) -> np.ndarray:
     return flm
 
 
-def boost_coefficient_resolution(flm: np.ndarray, boost: int) -> np.ndarray:
+def boost_coefficient_resolution(flm: npt.NDArray[Any], boost: int) -> npt.NDArray[Any]:
     """
     calculates a boost in resolution for given flm
     """
@@ -26,8 +27,13 @@ def boost_coefficient_resolution(flm: np.ndarray, boost: int) -> np.ndarray:
 
 
 def invert_flm_boosted(
-    flm: np.ndarray, L: int, resolution: int, *, reality: bool = False, spin: int = 0
-) -> np.ndarray:
+    flm: npt.NDArray[np.complex_],
+    L: int,
+    resolution: int,
+    *,
+    reality: bool = False,
+    spin: int = 0,
+) -> npt.NDArray[np.complex_ | np.float_]:
     """
     performs the inverse harmonic transform
     """
@@ -39,11 +45,13 @@ def invert_flm_boosted(
 
 
 def ensure_f_bandlimited(
-    grid_fun: Callable[[np.ndarray, np.ndarray], np.ndarray],
+    grid_fun: Callable[
+        [npt.NDArray[np.float_], npt.NDArray[np.float_]], npt.NDArray[np.float_]
+    ],
     L: int,
     reality: bool,
     spin: int,
-) -> np.ndarray:
+) -> npt.NDArray[np.complex_]:
     """
     if the function created is created in pixel space rather than harmonic
     space then need to transform it into harmonic space first before using it
@@ -53,7 +61,7 @@ def ensure_f_bandlimited(
     return ssht.forward(f, L, Reality=reality, Spin=spin, Method=SAMPLING_SCHEME)
 
 
-def create_emm_vector(L: int) -> np.ndarray:
+def create_emm_vector(L: int) -> npt.NDArray[np.float_]:
     """
     create vector of m values for a given L
     """
@@ -67,7 +75,9 @@ def create_emm_vector(L: int) -> np.ndarray:
     return emm
 
 
-def compute_random_signal(L: int, rng: Generator, *, var_signal: float) -> np.ndarray:
+def compute_random_signal(
+    L: int, rng: Generator, *, var_signal: float
+) -> npt.NDArray[np.complex_]:
     """
     generates a normally distributed random signal of a
     complex signal with mean 0 and variance 1
@@ -77,7 +87,9 @@ def compute_random_signal(L: int, rng: Generator, *, var_signal: float) -> np.nd
     )
 
 
-def mesh_forward(mesh: Mesh, u: np.ndarray) -> np.ndarray:
+def mesh_forward(
+    mesh: Mesh, u: npt.NDArray[np.complex_ | np.float_]
+) -> npt.NDArray[np.float_]:
     """
     computes the mesh forward transform from real space to harmonic space
     """
@@ -87,7 +99,9 @@ def mesh_forward(mesh: Mesh, u: np.ndarray) -> np.ndarray:
     return u_i
 
 
-def mesh_inverse(mesh: Mesh, u_i: np.ndarray) -> np.ndarray:
+def mesh_inverse(
+    mesh: Mesh, u_i: npt.NDArray[np.complex_ | np.float_]
+) -> npt.NDArray[np.complex_ | np.float_]:
     """
     computes the mesh inverse transform from harmonic space to real space
     """
diff --git a/sleplet/utils/integration_methods.py b/sleplet/utils/integration_methods.py
index 0dd6b897a..92000c0cc 100644
--- a/sleplet/utils/integration_methods.py
+++ b/sleplet/utils/integration_methods.py
@@ -1,12 +1,14 @@
 from functools import reduce
+from typing import Any
 
 import numpy as np
 import pyssht as ssht
+from numpy import typing as npt
 
 from sleplet.utils.vars import SAMPLING_SCHEME
 
 
-def calc_integration_weight(L: int) -> np.ndarray:
+def calc_integration_weight(L: int) -> npt.NDArray[np.float_]:
     """
     computes the spherical Jacobian for the integration
     """
@@ -16,7 +18,9 @@ def calc_integration_weight(L: int) -> np.ndarray:
     return np.sin(thetas) * delta_theta * delta_phi
 
 
-def integrate_whole_sphere(weight: np.ndarray, *functions: np.ndarray) -> complex:
+def integrate_whole_sphere(
+    weight: npt.NDArray[np.float_], *functions: npt.NDArray[np.complex_]
+) -> complex:
     """
     computes the integration for the whole sphere
     """
@@ -25,7 +29,9 @@ def integrate_whole_sphere(weight: np.ndarray, *functions: np.ndarray) -> comple
 
 
 def integrate_region_sphere(
-    mask: np.ndarray, weight: np.ndarray, *functions: np.ndarray
+    mask: npt.NDArray[np.float_],
+    weight: npt.NDArray[np.float_],
+    *functions: npt.NDArray[np.complex_ | np.float_],
 ) -> complex:
     """
     computes the integration for a region of the sphere
@@ -35,7 +41,9 @@ def integrate_region_sphere(
 
 
 def integrate_whole_mesh(
-    vertices: np.ndarray, faces: np.ndarray, *functions: np.ndarray
+    vertices: npt.NDArray[np.float_],
+    faces: npt.NDArray[np.int_],
+    *functions: npt.NDArray[np.complex_ | np.float_],
 ) -> float:
     """
     computes the integral of functions on the vertices
@@ -45,10 +53,10 @@ def integrate_whole_mesh(
 
 
 def integrate_region_mesh(
-    mask: np.ndarray,
-    vertices: np.ndarray,
-    faces: np.ndarray,
-    *functions: np.ndarray,
+    mask: npt.NDArray[np.bool_],
+    vertices: npt.NDArray[np.float_],
+    faces: npt.NDArray[np.int_],
+    *functions: npt.NDArray[np.complex_ | np.float_],
 ) -> float:
     """
     computes the integral of a region of functions on the vertices
@@ -57,7 +65,7 @@ def integrate_region_mesh(
     return (multiplied_inputs * mask).sum()
 
 
-def _multiply_args(*args: np.ndarray) -> np.ndarray:
+def _multiply_args(*args: npt.NDArray[Any]) -> npt.NDArray[Any]:
     """
     method to multiply an unknown number of arguments
     """
diff --git a/sleplet/utils/mask_methods.py b/sleplet/utils/mask_methods.py
index 3378a788e..edd0edf3c 100644
--- a/sleplet/utils/mask_methods.py
+++ b/sleplet/utils/mask_methods.py
@@ -3,6 +3,7 @@
 import numpy as np
 import pyssht as ssht
 from box import Box
+from numpy import typing as npt
 
 from sleplet.meshes.classes.mesh import Mesh
 from sleplet.utils.harmonic_methods import mesh_forward, mesh_inverse
@@ -14,7 +15,7 @@
 _mask_path = _file_location.parents[1] / "data" / "slepian" / "masks"
 
 
-def create_mask_region(L: int, region: Region) -> np.ndarray:
+def create_mask_region(L: int, region: Region) -> npt.NDArray[np.float_]:
     """
     creates a mask of a region of interested, the output will be based
     on the value of the provided L. The mask could be either:
@@ -49,11 +50,11 @@ def create_mask_region(L: int, region: Region) -> np.ndarray:
             mask = thetas <= region.theta_max
             if region.gap:
                 logger.info("creating polar gap mask")
-                mask |= thetas >= np.pi - region.theta_max
+                mask += thetas >= np.pi - region.theta_max
     return mask
 
 
-def _load_mask(mask_name: str) -> np.ndarray:
+def _load_mask(mask_name: str) -> npt.NDArray[np.float_]:
     """
     attempts to read the mask from the config file
     """
@@ -67,8 +68,8 @@ def _load_mask(mask_name: str) -> np.ndarray:
 
 
 def ensure_masked_flm_bandlimited(
-    flm: np.ndarray, L: int, region: Region, reality: bool, spin: int
-) -> np.ndarray:
+    flm: npt.NDArray[np.complex_], L: int, region: Region, reality: bool, spin: int
+) -> npt.NDArray[np.complex_]:
     """
     ensures the coefficients is bandlimited for a given region
     """
@@ -92,7 +93,9 @@ def create_default_region(settings: Box) -> Region:
     )
 
 
-def create_mesh_region(mesh_config: Box, vertices: np.ndarray) -> np.ndarray:
+def create_mesh_region(
+    mesh_config: Box, vertices: npt.NDArray[np.float_]
+) -> npt.NDArray[np.bool_]:
     """
     creates the boolean region for the given mesh
     """
@@ -106,7 +109,9 @@ def create_mesh_region(mesh_config: Box, vertices: np.ndarray) -> np.ndarray:
     )
 
 
-def ensure_masked_bandlimit_mesh_signal(mesh: Mesh, u_i: np.ndarray) -> np.ndarray:
+def ensure_masked_bandlimit_mesh_signal(
+    mesh: Mesh, u_i: npt.NDArray[np.complex_ | np.float_]
+) -> npt.NDArray[np.float_]:
     """
     ensures that signal in pixel space is bandlimited
     """
@@ -115,7 +120,7 @@ def ensure_masked_bandlimit_mesh_signal(mesh: Mesh, u_i: np.ndarray) -> np.ndarr
     return mesh_forward(mesh, masked_field)
 
 
-def convert_region_on_vertices_to_faces(mesh: Mesh) -> np.ndarray:
+def convert_region_on_vertices_to_faces(mesh: Mesh) -> npt.NDArray[np.float_]:
     """
     converts the region on vertices to faces
     """
diff --git a/sleplet/utils/mesh_methods.py b/sleplet/utils/mesh_methods.py
index 4a88d12eb..e73ede2ba 100644
--- a/sleplet/utils/mesh_methods.py
+++ b/sleplet/utils/mesh_methods.py
@@ -3,6 +3,7 @@
 import numpy as np
 from box import Box
 from igl import average_onto_faces, cotmatrix, read_triangle_mesh, upsample
+from numpy import typing as npt
 from scipy.sparse import linalg as LA_sparse
 
 from sleplet.utils.config import settings
@@ -14,9 +15,9 @@
 
 
 def average_functions_on_vertices_to_faces(
-    faces: np.ndarray,
-    functions_on_vertices: np.ndarray,
-) -> np.ndarray:
+    faces: npt.NDArray[np.int_],
+    functions_on_vertices: npt.NDArray[np.complex_ | np.float_],
+) -> npt.NDArray[np.float_]:
     """
     the integrals require all functions to be defined on faces
     this method handles an arbitrary number of functions
@@ -37,7 +38,9 @@ def average_functions_on_vertices_to_faces(
     return functions_on_faces
 
 
-def create_mesh_region(mesh_config: Box, vertices: np.ndarray) -> np.ndarray:
+def create_mesh_region(
+    mesh_config: Box, vertices: npt.NDArray[np.float_]
+) -> npt.NDArray[np.bool_]:
     """
     creates the boolean region for the given mesh
     """
@@ -60,11 +63,11 @@ def extract_mesh_config(mesh_name: str) -> Box:
 
 def mesh_eigendecomposition(
     name: str,
-    vertices: np.ndarray,
-    faces: np.ndarray,
+    vertices: npt.NDArray[np.float_],
+    faces: npt.NDArray[np.int_],
     *,
     number_basis_functions: int | None = None,
-) -> tuple[np.ndarray, np.ndarray, int]:
+) -> tuple[npt.NDArray[np.float_], npt.NDArray[np.float_], int]:
     """
     computes the eigendecomposition of the mesh represented
     as a graph if already computed then it loads the data
@@ -104,7 +107,7 @@ def mesh_eigendecomposition(
     return eigenvalues, eigenvectors, number_basis_functions
 
 
-def read_mesh(mesh_config: Box) -> tuple[np.ndarray, np.ndarray]:
+def read_mesh(mesh_config: Box) -> tuple[npt.NDArray[np.float_], npt.NDArray[np.int_]]:
     """
     reads in the given mesh
     """
@@ -114,7 +117,9 @@ def read_mesh(mesh_config: Box) -> tuple[np.ndarray, np.ndarray]:
     return upsample(vertices, faces, number_of_subdivs=mesh_config.UPSAMPLE)
 
 
-def _mesh_laplacian(vertices: np.ndarray, faces: np.ndarray) -> np.ndarray:
+def _mesh_laplacian(
+    vertices: npt.NDArray[np.float_], faces: npt.NDArray[np.int_]
+) -> npt.NDArray[np.float_]:
     """
     computes the cotagent mesh laplacian
     """
@@ -122,8 +127,10 @@ def _mesh_laplacian(vertices: np.ndarray, faces: np.ndarray) -> np.ndarray:
 
 
 def _orthonormalise_basis_functions(
-    vertices: np.ndarray, faces: np.ndarray, basis_functions: np.ndarray
-) -> np.ndarray:
+    vertices: npt.NDArray[np.float_],
+    faces: npt.NDArray[np.int_],
+    basis_functions: npt.NDArray[np.float_],
+) -> npt.NDArray[np.float_]:
     """
     for computing the Slepian D matrix the basis functions must be orthonormal
     """
diff --git a/sleplet/utils/noise.py b/sleplet/utils/noise.py
index fad6b7d31..9de7ee51f 100644
--- a/sleplet/utils/noise.py
+++ b/sleplet/utils/noise.py
@@ -1,5 +1,6 @@
 import numpy as np
 import pyssht as ssht
+from numpy import typing as npt
 from numpy.random import default_rng
 
 from sleplet.meshes.classes.mesh_slepian import MeshSlepian
@@ -17,14 +18,18 @@
 from sleplet.utils.vars import RANDOM_SEED, SAMPLING_SCHEME
 
 
-def _signal_power(signal: np.ndarray) -> float:
+def _signal_power(signal: npt.NDArray[np.complex_ | np.float_]) -> float:
     """
     computes the power of the signal
     """
     return (np.abs(signal) ** 2).sum()
 
 
-def compute_snr(signal: np.ndarray, noise: np.ndarray, signal_type: str) -> float:
+def compute_snr(
+    signal: npt.NDArray[np.complex_ | np.float_],
+    noise: npt.NDArray[np.complex_ | np.float_],
+    signal_type: str,
+) -> float:
     """
     computes the signal to noise ratio
     """
@@ -34,7 +39,7 @@ def compute_snr(signal: np.ndarray, noise: np.ndarray, signal_type: str) -> floa
 
 
 def compute_sigma_noise(
-    signal: np.ndarray,
+    signal: npt.NDArray[np.complex_ | np.float_],
     snr_in: float,
     *,
     denominator: int | None = None,
@@ -47,7 +52,9 @@ def compute_sigma_noise(
     return np.sqrt(10 ** (-snr_in / 10) * _signal_power(signal) / denominator)
 
 
-def create_noise(L: int, signal: np.ndarray, snr_in: float) -> np.ndarray:
+def create_noise(
+    L: int, signal: npt.NDArray[np.complex_ | np.float_], snr_in: float
+) -> npt.NDArray[np.complex_]:
     """
     computes Gaussian white noise
     """
@@ -77,8 +84,11 @@ def create_noise(L: int, signal: np.ndarray, snr_in: float) -> np.ndarray:
 
 
 def create_slepian_noise(
-    L: int, slepian_signal: np.ndarray, slepian: SlepianFunctions, snr_in: float
-) -> np.ndarray:
+    L: int,
+    slepian_signal: npt.NDArray[np.complex_ | np.float_],
+    slepian: SlepianFunctions,
+    snr_in: float,
+) -> npt.NDArray[np.complex_]:
     """
     computes Gaussian white noise in Slepian space
     """
@@ -90,8 +100,10 @@ def create_slepian_noise(
 
 
 def _perform_hard_thresholding(
-    f: np.ndarray, sigma_j: float | np.ndarray, n_sigma: int
-) -> np.ndarray:
+    f: npt.NDArray[np.complex_ | np.float_],
+    sigma_j: float | npt.NDArray[np.float_],
+    n_sigma: int,
+) -> npt.NDArray[np.complex_]:
     """
     set pixels in real space to zero if the magnitude is less than the threshold
     """
@@ -100,8 +112,11 @@ def _perform_hard_thresholding(
 
 
 def harmonic_hard_thresholding(
-    L: int, wav_coeffs: np.ndarray, sigma_j: np.ndarray, n_sigma: int
-) -> np.ndarray:
+    L: int,
+    wav_coeffs: npt.NDArray[np.complex_],
+    sigma_j: npt.NDArray[np.float_],
+    n_sigma: int,
+) -> npt.NDArray[np.complex_]:
     """
     perform thresholding in harmonic space
     """
@@ -116,11 +131,11 @@ def harmonic_hard_thresholding(
 
 def slepian_wavelet_hard_thresholding(
     L: int,
-    wav_coeffs: np.ndarray,
-    sigma_j: np.ndarray,
+    wav_coeffs: npt.NDArray[np.complex_ | np.float_],
+    sigma_j: npt.NDArray[np.float_],
     n_sigma: int,
     slepian: SlepianFunctions,
-) -> np.ndarray:
+) -> npt.NDArray[np.complex_ | np.float_]:
     """
     perform thresholding in Slepian wavelet space
     """
@@ -135,11 +150,11 @@ def slepian_wavelet_hard_thresholding(
 
 def slepian_function_hard_thresholding(
     L: int,
-    coefficients: np.ndarray,
+    coefficients: npt.NDArray[np.complex_ | np.float_],
     sigma: float,
     n_sigma: int,
     slepian: SlepianFunctions,
-) -> np.ndarray:
+) -> npt.NDArray[np.complex_]:
     """
     perform thresholding in Slepian function space
     """
@@ -149,7 +164,11 @@ def slepian_function_hard_thresholding(
     return slepian_forward(L, slepian, f=f_thresholded)
 
 
-def compute_sigma_j(signal: np.ndarray, psi_j: np.ndarray, snr_in: float) -> np.ndarray:
+def compute_sigma_j(
+    signal: npt.NDArray[np.complex_ | np.float_],
+    psi_j: npt.NDArray[np.complex_],
+    snr_in: float,
+) -> npt.NDArray[np.float_]:
     """
     compute sigma_j for wavelets used in denoising the signal
     """
@@ -160,11 +179,11 @@ def compute_sigma_j(signal: np.ndarray, psi_j: np.ndarray, snr_in: float) -> np.
 
 def compute_slepian_sigma_j(
     L: int,
-    signal: np.ndarray,
-    psi_j: np.ndarray,
+    signal: npt.NDArray[np.complex_ | np.float_],
+    psi_j: npt.NDArray[np.float_],
     snr_in: float,
     slepian: SlepianFunctions,
-) -> np.ndarray:
+) -> npt.NDArray[np.float_]:
     """
     compute sigma_j for wavelets used in denoising the signal
     """
@@ -175,7 +194,9 @@ def compute_slepian_sigma_j(
     return sigma_noise * np.sqrt(wavelet_power)
 
 
-def create_mesh_noise(u_i: np.ndarray, snr_in: float) -> np.ndarray:
+def create_mesh_noise(
+    u_i: npt.NDArray[np.complex_ | np.float_], snr_in: float
+) -> npt.NDArray[np.float_]:
     """
     computes Gaussian white noise
     """
@@ -196,9 +217,9 @@ def create_mesh_noise(u_i: np.ndarray, snr_in: float) -> np.ndarray:
 
 def create_slepian_mesh_noise(
     mesh_slepian: MeshSlepian,
-    slepian_signal: np.ndarray,
+    slepian_signal: npt.NDArray[np.complex_ | np.float_],
     snr_in: float,
-) -> np.ndarray:
+) -> npt.NDArray[np.float_]:
     """
     computes Gaussian white noise in Slepian space
     """
@@ -218,10 +239,10 @@ def create_slepian_mesh_noise(
 
 def compute_slepian_mesh_sigma_j(
     mesh_slepian: MeshSlepian,
-    signal: np.ndarray,
-    psi_j: np.ndarray,
+    signal: npt.NDArray[np.complex_ | np.float_],
+    psi_j: npt.NDArray[np.float_],
     snr_in: float,
-) -> np.ndarray:
+) -> npt.NDArray[np.float_]:
     """
     compute sigma_j for wavelets used in denoising the signal
     """
@@ -236,10 +257,10 @@ def compute_slepian_mesh_sigma_j(
 
 def slepian_mesh_hard_thresholding(
     mesh_slepian: MeshSlepian,
-    wav_coeffs: np.ndarray,
-    sigma_j: np.ndarray,
+    wav_coeffs: npt.NDArray[np.complex_ | np.float_],
+    sigma_j: npt.NDArray[np.float_],
     n_sigma: int,
-) -> np.ndarray:
+) -> npt.NDArray[np.complex_ | np.float_]:
     """
     perform thresholding in Slepian space
     """
diff --git a/sleplet/utils/parallel_methods.py b/sleplet/utils/parallel_methods.py
index cf361cb39..76c9a619d 100644
--- a/sleplet/utils/parallel_methods.py
+++ b/sleplet/utils/parallel_methods.py
@@ -1,12 +1,13 @@
 import numpy as np
 from multiprocess.shared_memory import SharedMemory
+from numpy import typing as npt
 
 from sleplet.utils.vars import L_MIN_DEFAULT
 
 
 def split_arr_into_chunks(
     arr_max: int, ncpu: int, *, arr_min: int = L_MIN_DEFAULT
-) -> list[np.ndarray]:
+) -> list[npt.NDArray[np.int_]]:
     """
     split L into a list of arrays for parallelism
     """
@@ -16,25 +17,29 @@ def split_arr_into_chunks(
     return [np.sort(arr[i::ncpu]) for i in range(ncpu)]
 
 
-def create_shared_memory_array(array: np.ndarray) -> tuple[np.ndarray, SharedMemory]:
+def create_shared_memory_array(
+    array: npt.NDArray[np.float_],
+) -> tuple[npt.NDArray[np.float_], SharedMemory]:
     """
     creates a shared memory array to be used in a parallel function
     """
-    array_ext: np.ndarray
     ext_shared_memory = SharedMemory(create=True, size=array.nbytes)
-    array_ext = np.ndarray(array.shape, dtype=array.dtype, buffer=ext_shared_memory.buf)
+    array_ext: npt.NDArray[np.float_] = np.ndarray(
+        array.shape, dtype=array.dtype, buffer=ext_shared_memory.buf
+    )
     return array_ext, ext_shared_memory
 
 
 def attach_to_shared_memory_block(
-    array: np.ndarray, ext_shared_memory: SharedMemory
-) -> tuple[np.ndarray, SharedMemory]:
+    array: npt.NDArray[np.float_], ext_shared_memory: SharedMemory
+) -> tuple[npt.NDArray[np.float_], SharedMemory]:
     """
     used within the parallel function to attach an array to the shared memory
     """
-    array_int: np.ndarray
     int_shared_memory = SharedMemory(name=ext_shared_memory.name)
-    array_int = np.ndarray(array.shape, dtype=array.dtype, buffer=int_shared_memory.buf)
+    array_int: npt.NDArray[np.float_] = np.ndarray(
+        array.shape, dtype=array.dtype, buffer=int_shared_memory.buf
+    )
     return array_int, int_shared_memory
 
 
diff --git a/sleplet/utils/plot_methods.py b/sleplet/utils/plot_methods.py
index e9bc4516f..caee56a77 100644
--- a/sleplet/utils/plot_methods.py
+++ b/sleplet/utils/plot_methods.py
@@ -4,6 +4,7 @@
 import pyssht as ssht
 from matplotlib import colors
 from matplotlib import pyplot as plt
+from numpy import typing as npt
 
 from sleplet.functions.coefficients import Coefficients
 from sleplet.utils.config import settings
@@ -112,7 +113,9 @@ def find_max_amplitude(
     return np.abs(create_plot_type(boosted_field, plot_type)).max()
 
 
-def create_plot_type(field: np.ndarray, plot_type: str) -> np.ndarray:
+def create_plot_type(
+    field: npt.NDArray[np.complex_ | np.float_], plot_type: str
+) -> npt.NDArray[np.float_]:
     """
     gets the given plot type of the field
     """
@@ -124,8 +127,8 @@ def create_plot_type(field: np.ndarray, plot_type: str) -> np.ndarray:
 
 
 def set_outside_region_to_minimum(
-    f_plot: np.ndarray, L: int, region: Region
-) -> np.ndarray:
+    f_plot: npt.NDArray[np.float_], L: int, region: Region
+) -> npt.NDArray[np.float_]:
     """
     for the Slepian region set the outisde area to negative infinity
     hence it is clear we are only interested in the coloured region
@@ -141,7 +144,9 @@ def set_outside_region_to_minimum(
     return np.where(closed_mask, f_plot, SPHERE_UNSEEN)
 
 
-def rotate_earth_to_south_america(earth_flm: np.ndarray, L: int) -> np.ndarray:
+def rotate_earth_to_south_america(
+    earth_flm: npt.NDArray[np.complex_ | np.float_], L: int
+) -> npt.NDArray[np.complex_]:
     """
     rotates the flms of the Earth to a view centered on South America
     """
@@ -150,14 +155,18 @@ def rotate_earth_to_south_america(earth_flm: np.ndarray, L: int) -> np.ndarray:
     )
 
 
-def rotate_earth_to_africa(earth_flm: np.ndarray, L: int) -> np.ndarray:
+def rotate_earth_to_africa(
+    earth_flm: npt.NDArray[np.complex_ | np.float_], L: int
+) -> npt.NDArray[np.complex_]:
     """
     rotates the flms of the Earth to a view centered on Africa
     """
     return ssht.rotate_flms(earth_flm, AFRICA_ALPHA, AFRICA_BETA, AFRICA_GAMMA, L)
 
 
-def normalise_function(f: np.ndarray, normalise: bool) -> np.ndarray:
+def normalise_function(
+    f: npt.NDArray[np.float_], normalise: bool
+) -> npt.NDArray[np.float_]:
     """
     normalise function between 0 and 1 for visualisation
     """
@@ -175,8 +184,13 @@ def normalise_function(f: np.ndarray, normalise: bool) -> np.ndarray:
 
 
 def boost_field(
-    field: np.ndarray, L: int, resolution: int, reality: bool, spin: int, upsample: bool
-) -> np.ndarray:
+    field: npt.NDArray[np.complex_ | np.float_],
+    L: int,
+    resolution: int,
+    reality: bool,
+    spin: int,
+    upsample: bool,
+) -> npt.NDArray[np.complex_ | np.float_]:
     """
     inverts and then boosts the field before plotting
     """
diff --git a/sleplet/utils/slepian_arbitrary_methods.py b/sleplet/utils/slepian_arbitrary_methods.py
index 5441f4d61..0654e69d4 100644
--- a/sleplet/utils/slepian_arbitrary_methods.py
+++ b/sleplet/utils/slepian_arbitrary_methods.py
@@ -1,6 +1,7 @@
 from pathlib import Path
 
 import numpy as np
+from numpy import typing as npt
 
 from sleplet.meshes.classes.mesh import Mesh
 from sleplet.utils.array_methods import fill_upper_triangle_of_hermitian_matrix
@@ -8,7 +9,9 @@
 MACHINE_EPSILON = 1e-14
 
 
-def calculate_high_L_matrix(file_loc: Path, L: int, L_ranges: list[int]) -> np.ndarray:
+def calculate_high_L_matrix(
+    file_loc: Path, L: int, L_ranges: list[int]
+) -> npt.NDArray[np.complex_]:
     """
     splits up and calculates intermediate matrices for higher L
     """
@@ -24,7 +27,9 @@ def calculate_high_L_matrix(file_loc: Path, L: int, L_ranges: list[int]) -> np.n
     return D
 
 
-def clean_evals_and_evecs(eigendecomposition: tuple) -> tuple[np.ndarray, np.ndarray]:
+def clean_evals_and_evecs(
+    eigendecomposition: tuple,
+) -> tuple[npt.NDArray[np.float_], npt.NDArray[np.complex_]]:
     """
     need eigenvalues and eigenvectors to be in a certain format
     """
diff --git a/sleplet/utils/slepian_methods.py b/sleplet/utils/slepian_methods.py
index 077881b3d..f0bfb7f3d 100644
--- a/sleplet/utils/slepian_methods.py
+++ b/sleplet/utils/slepian_methods.py
@@ -1,5 +1,6 @@
 import numpy as np
 import pyssht as ssht
+from numpy import typing as npt
 
 from sleplet.meshes.classes.mesh_slepian import MeshSlepian
 from sleplet.meshes.classes.mesh_slepian_decomposition import MeshSlepianDecomposition
@@ -41,7 +42,9 @@ def choose_slepian_method(L: int, region: Region) -> SlepianFunctions:
             raise ValueError(f"{region.region_type} is an invalid region type")
 
 
-def slepian_inverse(f_p: np.ndarray, L: int, slepian: SlepianFunctions) -> np.ndarray:
+def slepian_inverse(
+    f_p: npt.NDArray[np.complex_ | np.float_], L: int, slepian: SlepianFunctions
+) -> npt.NDArray[np.complex_]:
     """
     computes the Slepian inverse transform up to the Shannon number
     """
@@ -54,11 +57,11 @@ def slepian_forward(
     L: int,
     slepian: SlepianFunctions,
     *,
-    f: np.ndarray | None = None,
-    flm: np.ndarray | None = None,
-    mask: np.ndarray | None = None,
+    f: npt.NDArray[np.complex_] | None = None,
+    flm: npt.NDArray[np.complex_ | np.float_] | None = None,
+    mask: npt.NDArray[np.float_] | None = None,
     n_coeffs: int | None = None,
-) -> np.ndarray:
+) -> npt.NDArray[np.complex_]:
     """
     computes the Slepian forward transform for all coefficients
     """
@@ -67,7 +70,7 @@ def slepian_forward(
     return sd.decompose_all(n_coeffs)
 
 
-def compute_s_p_omega(L: int, slepian: SlepianFunctions) -> np.ndarray:
+def compute_s_p_omega(L: int, slepian: SlepianFunctions) -> npt.NDArray[np.complex_]:
     """
     method to calculate Sp(omega) for a given region
     """
@@ -82,7 +85,7 @@ def compute_s_p_omega(L: int, slepian: SlepianFunctions) -> np.ndarray:
 
 def compute_s_p_omega_prime(
     L: int, alpha: float, beta: float, slepian: SlepianFunctions
-) -> np.ndarray:
+) -> npt.NDArray[np.complex_]:
     """
     method to pick out the desired angle from Sp(omega)
     """
@@ -98,11 +101,11 @@ def compute_s_p_omega_prime(
 def slepian_mesh_forward(
     mesh_slepian: MeshSlepian,
     *,
-    u: np.ndarray | None = None,
-    u_i: np.ndarray | None = None,
+    u: npt.NDArray[np.complex_ | np.float_] | None = None,
+    u_i: npt.NDArray[np.complex_ | np.float_] | None = None,
     mask: bool = False,
     n_coeffs: int | None = None,
-) -> np.ndarray:
+) -> npt.NDArray[np.float_]:
     """
     computes the Slepian forward transform for all coefficients
     """
@@ -118,8 +121,8 @@ def slepian_mesh_forward(
 
 def slepian_mesh_inverse(
     mesh_slepian: MeshSlepian,
-    f_p: np.ndarray,
-) -> np.ndarray:
+    f_p: npt.NDArray[np.complex_ | np.float_],
+) -> npt.NDArray[np.complex_ | np.float_]:
     """
     computes the Slepian inverse transform on the mesh up to the Shannon number
     """
@@ -128,7 +131,7 @@ def slepian_mesh_inverse(
     return (f_p_reshape * s_p).sum(axis=0)
 
 
-def compute_mesh_s_p_pixel(mesh_slepian: MeshSlepian) -> np.ndarray:
+def compute_mesh_s_p_pixel(mesh_slepian: MeshSlepian) -> npt.NDArray[np.float_]:
     """
     method to calculate Sp(omega) for a given region
     """
diff --git a/sleplet/utils/smoothing.py b/sleplet/utils/smoothing.py
index 50a790d56..44f9c9efb 100644
--- a/sleplet/utils/smoothing.py
+++ b/sleplet/utils/smoothing.py
@@ -1,12 +1,13 @@
 import numpy as np
 import pyssht as ssht
+from numpy import typing as npt
 
 from sleplet.utils.logger import logger
 
 
 def apply_gaussian_smoothing(
-    flm: np.ndarray, L: int, smoothing_factor: int
-) -> np.ndarray:
+    flm: npt.NDArray[np.complex_], L: int, smoothing_factor: int
+) -> npt.NDArray[np.complex_]:
     """
     applies Gaussian smoothing to the given signal
 
diff --git a/sleplet/utils/wavelet_methods.py b/sleplet/utils/wavelet_methods.py
index 1f75d5b64..f0083724c 100644
--- a/sleplet/utils/wavelet_methods.py
+++ b/sleplet/utils/wavelet_methods.py
@@ -1,5 +1,6 @@
 import numpy as np
 import pyssht as ssht
+from numpy import typing as npt
 from pys2let import axisym_wav_l
 
 from sleplet.slepian.slepian_functions import SlepianFunctions
@@ -8,8 +9,10 @@
 
 
 def slepian_wavelet_forward(
-    f_p: np.ndarray, wavelets: np.ndarray, shannon: int
-) -> np.ndarray:
+    f_p: npt.NDArray[np.complex_ | np.float_],
+    wavelets: npt.NDArray[np.float_],
+    shannon: int,
+) -> npt.NDArray[np.complex_ | np.float_]:
     """
     computes the coefficients of the given tiling function in Slepian space
     """
@@ -19,8 +22,10 @@ def slepian_wavelet_forward(
 
 
 def slepian_wavelet_inverse(
-    wav_coeffs: np.ndarray, wavelets: np.ndarray, shannon: int
-) -> np.ndarray:
+    wav_coeffs: npt.NDArray[np.complex_ | np.float_],
+    wavelets: npt.NDArray[np.float_],
+    shannon: int,
+) -> npt.NDArray[np.complex_ | np.float_]:
     """
     computes the inverse wavelet transform in Slepian space
     """
@@ -33,8 +38,10 @@ def slepian_wavelet_inverse(
 
 
 def axisymmetric_wavelet_forward(
-    L: int, flm: np.ndarray, wavelets: np.ndarray
-) -> np.ndarray:
+    L: int,
+    flm: npt.NDArray[np.complex_ | np.float_],
+    wavelets: npt.NDArray[np.complex_],
+) -> npt.NDArray[np.complex_]:
     """
     computes the coefficients of the axisymmetric wavelets
     """
@@ -49,8 +56,8 @@ def axisymmetric_wavelet_forward(
 
 
 def axisymmetric_wavelet_inverse(
-    L: int, wav_coeffs: np.ndarray, wavelets: np.ndarray
-) -> np.ndarray:
+    L: int, wav_coeffs: npt.NDArray[np.complex_], wavelets: npt.NDArray[np.complex_]
+) -> npt.NDArray[np.complex_]:
     """
     computes the inverse axisymmetric wavelet transform
     """
@@ -65,8 +72,8 @@ def axisymmetric_wavelet_inverse(
 
 
 def compute_wavelet_covariance(
-    L: int, wavelets: np.ndarray, *, var_signal: float
-) -> np.ndarray:
+    L: int, wavelets: npt.NDArray[np.complex_], *, var_signal: float
+) -> npt.NDArray[np.float_]:
     """
     computes the theoretical covariance of the wavelet coefficients
     """
@@ -76,11 +83,11 @@ def compute_wavelet_covariance(
 
 def compute_slepian_wavelet_covariance(
     L: int,
-    wavelets: np.ndarray,
+    wavelets: npt.NDArray[np.float_],
     slepian: SlepianFunctions,
     *,
     var_signal: float,
-) -> np.ndarray:
+) -> npt.NDArray[np.float_]:
     """
     computes the theoretical covariance of the wavelet coefficients
     """
@@ -90,7 +97,9 @@ def compute_slepian_wavelet_covariance(
     return covar_theory * var_signal
 
 
-def create_axisymmetric_wavelets(L: int, B: int, j_min: int) -> np.ndarray:
+def create_axisymmetric_wavelets(
+    L: int, B: int, j_min: int
+) -> npt.NDArray[np.complex_]:
     """
     computes the axisymmetric wavelets
     """
@@ -103,7 +112,7 @@ def create_axisymmetric_wavelets(L: int, B: int, j_min: int) -> np.ndarray:
     return wavelets
 
 
-def create_kappas(xlim: int, B: int, j_min: int) -> np.ndarray:
+def create_kappas(xlim: int, B: int, j_min: int) -> npt.NDArray[np.float_]:
     """
     computes the Slepian wavelets
     """
@@ -112,8 +121,8 @@ def create_kappas(xlim: int, B: int, j_min: int) -> np.ndarray:
 
 
 def find_non_zero_wavelet_coefficients(
-    wav_coeffs: np.ndarray, *, axis: int | tuple[int, ...]
-) -> np.ndarray:
+    wav_coeffs: npt.NDArray[np.complex_ | np.float_], *, axis: int | tuple[int, ...]
+) -> npt.NDArray[np.complex_ | np.float_]:
     """
     finds the coefficients within the shannon number to speed up computations
     """


Test patch:
diff --git a/conftest.py b/conftest.py
index 3c513484b..022212d13 100644
--- a/conftest.py
+++ b/conftest.py
@@ -1,5 +1,6 @@
 import numpy as np
 import pytest
+from numpy import typing as npt
 from numpy.random import default_rng
 
 from sleplet.functions.flm.earth import Earth
@@ -132,7 +133,7 @@ def slepian_wavelets_lim_lat_lon(slepian_lim_lat_lon) -> SlepianWavelets:
 
 
 @pytest.fixture(scope="session")
-def random_flm() -> np.ndarray:
+def random_flm() -> npt.NDArray[np.complex_]:
     """
     creates random flm
     """
@@ -141,7 +142,7 @@ def random_flm() -> np.ndarray:
 
 
 @pytest.fixture(scope="session")
-def random_nd_flm() -> np.ndarray:
+def random_nd_flm() -> npt.NDArray[np.complex_]:
     """
     creates multiple random flm
     """