Repository: owkin/PyDESeq2
Pull request #282 (2024-05-25 20:41:56)

Replace np.NaN with np.nan -> numpy 2.0 compat
#### What does your PR implement? Be specific.

Our pre-release complains about:

> E           AttributeError: `np.NaN` was removed in the NumPy 2.0 release. Use `np.nan` instead.




Patch:
diff --git a/pydeseq2/dds.py b/pydeseq2/dds.py
index 990d506..281657b 100644
--- a/pydeseq2/dds.py
+++ b/pydeseq2/dds.py
@@ -545,7 +545,7 @@ class DeseqDataSet(ad.AnnData):
                 beta_tol=self.beta_tol,
             )
 
-        self.layers["_mu_hat"] = np.full((self.n_obs, self.n_vars), np.NaN)
+        self.layers["_mu_hat"] = np.full((self.n_obs, self.n_vars), np.nan)
         self.layers["_mu_hat"][:, self.varm["non_zero"]] = mu_hat_
 
         if not self.quiet:
@@ -564,12 +564,12 @@ class DeseqDataSet(ad.AnnData):
         if not self.quiet:
             print(f"... done in {end - start:.2f} seconds.\n", file=sys.stderr)
 
-        self.varm["genewise_dispersions"] = np.full(self.n_vars, np.NaN)
+        self.varm["genewise_dispersions"] = np.full(self.n_vars, np.nan)
         self.varm["genewise_dispersions"][self.varm["non_zero"]] = np.clip(
             dispersions_, self.min_disp, self.max_disp
         )
 
-        self.varm["_genewise_converged"] = np.full(self.n_vars, np.NaN)
+        self.varm["_genewise_converged"] = np.full(self.n_vars, np.nan)
         self.varm["_genewise_converged"][self.varm["non_zero"]] = l_bfgs_b_converged_
 
     def fit_dispersion_trend(self) -> None:
@@ -684,12 +684,12 @@ class DeseqDataSet(ad.AnnData):
         if not self.quiet:
             print(f"... done in {end-start:.2f} seconds.\n", file=sys.stderr)
 
-        self.varm["MAP_dispersions"] = np.full(self.n_vars, np.NaN)
+        self.varm["MAP_dispersions"] = np.full(self.n_vars, np.nan)
         self.varm["MAP_dispersions"][self.varm["non_zero"]] = np.clip(
             dispersions_, self.min_disp, self.max_disp
         )
 
-        self.varm["_MAP_converged"] = np.full(self.n_vars, np.NaN)
+        self.varm["_MAP_converged"] = np.full(self.n_vars, np.nan)
         self.varm["_MAP_converged"][self.varm["non_zero"]] = l_bfgs_b_converged_
 
         # Filter outlier genes for which we won't apply shrinkage
@@ -731,7 +731,7 @@ class DeseqDataSet(ad.AnnData):
             print(f"... done in {end-start:.2f} seconds.\n", file=sys.stderr)
 
         self.varm["LFC"] = pd.DataFrame(
-            np.NaN,
+            np.nan,
             index=self.var_names,
             columns=self.obsm["design_matrix"].columns,
         )
@@ -744,13 +744,13 @@ class DeseqDataSet(ad.AnnData):
             )
         )
 
-        self.layers["_mu_LFC"] = np.full((self.n_obs, self.n_vars), np.NaN)
+        self.layers["_mu_LFC"] = np.full((self.n_obs, self.n_vars), np.nan)
         self.layers["_mu_LFC"][:, self.varm["non_zero"]] = mu_
 
-        self.layers["_hat_diagonals"] = np.full((self.n_obs, self.n_vars), np.NaN)
+        self.layers["_hat_diagonals"] = np.full((self.n_obs, self.n_vars), np.nan)
         self.layers["_hat_diagonals"][:, self.varm["non_zero"]] = hat_diagonals_
 
-        self.varm["_LFC_converged"] = np.full(self.n_vars, np.NaN)
+        self.varm["_LFC_converged"] = np.full(self.n_vars, np.nan)
         self.varm["_LFC_converged"][self.varm["non_zero"]] = converged_
 
     def calculate_cooks(self) -> None:
@@ -786,7 +786,7 @@ class DeseqDataSet(ad.AnnData):
             / (1 - nonzero_data.layers["_hat_diagonals"]) ** 2
         )
 
-        self.layers["cooks"] = np.full((self.n_obs, self.n_vars), np.NaN)
+        self.layers["cooks"] = np.full((self.n_obs, self.n_vars), np.nan)
         self.layers["cooks"][:, self.varm["non_zero"]] = (
             squared_pearson_res / num_vars * diag_mul
         )
@@ -834,7 +834,7 @@ class DeseqDataSet(ad.AnnData):
         )
         alpha_hat = np.minimum(rde, mde)
 
-        self.varm["_MoM_dispersions"] = np.full(self.n_vars, np.NaN)
+        self.varm["_MoM_dispersions"] = np.full(self.n_vars, np.nan)
         self.varm["_MoM_dispersions"][self.varm["non_zero"]] = np.clip(
             alpha_hat, self.min_disp, self.max_disp
         )
@@ -934,7 +934,7 @@ class DeseqDataSet(ad.AnnData):
             )
         self.uns["trend_coeffs"] = pd.Series(coeffs, index=["a0", "a1"])
 
-        self.varm["fitted_dispersions"] = np.full(self.n_vars, np.NaN)
+        self.varm["fitted_dispersions"] = np.full(self.n_vars, np.nan)
         self.uns["disp_function_type"] = "parametric"
         self.varm["fitted_dispersions"][self.varm["non_zero"]] = self.disp_function(
             self.varm["_normed_means"][self.varm["non_zero"]]
diff --git a/pydeseq2/ds.py b/pydeseq2/ds.py
index dda8a79..c127de8 100644
--- a/pydeseq2/ds.py
+++ b/pydeseq2/ds.py
@@ -436,7 +436,7 @@ class DeseqStats:
             )
         )
 
-        self._LFC_shrink_converged = pd.Series(np.NaN, index=self.dds.var_names)
+        self._LFC_shrink_converged = pd.Series(np.nan, index=self.dds.var_names)
         self._LFC_shrink_converged.update(
             pd.Series(l_bfgs_b_converged_, index=self.dds.non_zero_genes)
         )


Test patch:
diff --git a/tests/test_edge_cases.py b/tests/test_edge_cases.py
index 6517c25..494da4c 100644
--- a/tests/test_edge_cases.py
+++ b/tests/test_edge_cases.py
@@ -107,7 +107,7 @@ def test_nan_factors():
     counts_df = pd.DataFrame(
         {"gene1": [0, 1], "gene2": [4, 12]}, index=["sample1", "sample2"]
     )
-    metadata = pd.DataFrame({"condition": [0, np.NaN]}, index=["sample1", "sample2"])
+    metadata = pd.DataFrame({"condition": [0, np.nan]}, index=["sample1", "sample2"])
 
     with pytest.raises(ValueError):
         DeseqDataSet(counts=counts_df, metadata=metadata, design_factors="condition")
diff --git a/tests/test_pydeseq2.py b/tests/test_pydeseq2.py
index 472ee85..7f44a0b 100644
--- a/tests/test_pydeseq2.py
+++ b/tests/test_pydeseq2.py
@@ -671,7 +671,7 @@ def test_ref_level(counts_df, metadata):
     assert (
         dds.obsm["design_matrix"]["group_X_vs_Y"]
         == metadata["group"].apply(
-            lambda x: 1 if x == "X" else 0 if x == "Y" else np.NaN
+            lambda x: 1 if x == "X" else 0 if x == "Y" else np.nan
         )
     ).all()