Repository: pints-team/pints

Issue:
Deprecation warning: pints.UniformLogPrior
```python
In [13]: # Define log-posterior
    ...: log_prior = pints.ComposedLogPrior(
    ...:     pints.UniformLogPrior(0, 20),  # Initial drug amount
    ...:     pints.UniformLogPrior(0, 20),  # Compartment volume
    ...:     pints.UniformLogPrior(0, 20),  # Elimination rate
    ...:     pints.UniformLogPrior(0, 20)   # Sigma
    ...: )
    ...: log_posterior = chi.LogPosterior(log_likelihood, log_prior)
    ...: 
    ...: # Evaluate log-posterior
    ...: score_1 = log_posterior(madeup_parameters)
    ...: score_2 = log_posterior(true_parameters)
<ipython-input-13-919134d94722>:3: DeprecationWarning:

`product` is deprecated as of NumPy 1.25.0, and will be removed in NumPy 2.0. Please use `prod` instead.

<ipython-input-13-919134d94722>:4: DeprecationWarning:

`product` is deprecated as of NumPy 1.25.0, and will be removed in NumPy 2.0. Please use `prod` instead.

<ipython-input-13-919134d94722>:5: DeprecationWarning:

`product` is deprecated as of NumPy 1.25.0, and will be removed in NumPy 2.0. Please use `prod` instead.

<ipython-input-13-919134d94722>:6: DeprecationWarning:

`product` is deprecated as of NumPy 1.25.0, and will be removed in NumPy 2.0. Please use `prod` instead.


In [14]: np.__version__
Out[14]: '1.26.0'
```

Discussion:

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4049e5fd..da773654 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -42,6 +42,7 @@ All notable changes to this project will be documented in this file.
 - [#1424](https://github.com/pints-team/pints/pull/1424) Removed the `TriangleWaveTransform` class previously used in some optimisers.
 
 ### Fixed
+- [#1497](https://github.com/pints-team/pints/pull/1497) Fixed deprecation warning of `np.product` globally in pints.
 - [#1457](https://github.com/pints-team/pints/pull/1457) Fixed typo in deprecation warning for `UnknownNoiseLikelihood`.
 - [#1455](https://github.com/pints-team/pints/pull/1455) The `s` and `inv_s` properties of `ScalingTransformation` have been replaced with private properties `_s` and `_inv_s`.
 - [#1450](https://github.com/pints-team/pints/pull/1450) Made `TransformedBoundaries` consistent with `Boundaries` by removing `range()` and adding `sample()`.
diff --git a/pints/_error_measures.py b/pints/_error_measures.py
index b04d128c..6ceae641 100644
--- a/pints/_error_measures.py
+++ b/pints/_error_measures.py
@@ -88,7 +88,7 @@ class MeanSquaredError(ProblemErrorMeasure):
     """
     def __init__(self, problem, weights=None):
         super(MeanSquaredError, self).__init__(problem)
-        self._ninv = 1.0 / np.product(self._values.shape)
+        self._ninv = 1.0 / np.prod(self._values.shape)
 
         if weights is None:
             weights = [1] * self._n_outputs
diff --git a/pints/_log_likelihoods.py b/pints/_log_likelihoods.py
index 3c7792a7..d0e37a2c 100644
--- a/pints/_log_likelihoods.py
+++ b/pints/_log_likelihoods.py
@@ -1120,7 +1120,7 @@ class ScaledLogLikelihood(pints.ProblemLogLikelihood):
         self._log_likelihood = log_likelihood
 
         # Pre-calculate parts
-        self._f = 1.0 / np.product(self._values.shape)
+        self._f = 1.0 / np.prod(self._values.shape)
 
     def __call__(self, x):
         return self._f * self._log_likelihood(x)
diff --git a/pints/_log_priors.py b/pints/_log_priors.py
index 99311fb7..eb669ab9 100644
--- a/pints/_log_priors.py
+++ b/pints/_log_priors.py
@@ -1245,7 +1245,7 @@ class UniformLogPrior(pints.LogPrior):
         # Use normalised value (1/area) for rectangular boundaries,
         # otherwise just use 1.
         if isinstance(self._boundaries, pints.RectangularBoundaries):
-            self._value = -np.log(np.product(self._boundaries.range()))
+            self._value = -np.log(np.prod(self._boundaries.range()))
         else:
             self._value = 1
 
diff --git a/pints/_mcmc/__init__.py b/pints/_mcmc/__init__.py
index f6514036..f0ec64ba 100644
--- a/pints/_mcmc/__init__.py
+++ b/pints/_mcmc/__init__.py
@@ -90,7 +90,7 @@ class SingleChainMCMC(MCMCSampler):
             self._sigma0 = np.diag(0.01 * self._sigma0)
         else:
             self._sigma0 = np.array(sigma0, copy=True)
-            if np.product(self._sigma0.shape) == self._n_parameters:
+            if np.prod(self._sigma0.shape) == self._n_parameters:
                 # Convert from 1d array
                 self._sigma0 = self._sigma0.reshape((self._n_parameters,))
                 self._sigma0 = np.diag(self._sigma0)
@@ -192,7 +192,7 @@ class MultiChainMCMC(MCMCSampler):
             self._sigma0 = np.diag(0.01 * self._sigma0)
         else:
             self._sigma0 = np.array(sigma0, copy=True)
-            if np.product(self._sigma0.shape) == self._n_parameters:
+            if np.prod(self._sigma0.shape) == self._n_parameters:
                 # Convert from 1d array
                 self._sigma0 = self._sigma0.reshape((self._n_parameters,))
                 self._sigma0 = np.diag(self._sigma0)
@@ -352,7 +352,7 @@ class MCMCController(object):
                 else:
                     n_parameters = log_pdf[0].n_parameters()
                 # Make sure sigma0 is a (covariance) matrix
-                if np.product(sigma0.shape) == n_parameters:
+                if np.prod(sigma0.shape) == n_parameters:
                     # Convert from 1d array
                     sigma0 = sigma0.reshape((n_parameters,))
                     sigma0 = np.diag(sigma0)
diff --git a/pints/_optimisers/__init__.py b/pints/_optimisers/__init__.py
index e95c31a6..5887051d 100644
--- a/pints/_optimisers/__init__.py
+++ b/pints/_optimisers/__init__.py
@@ -1125,7 +1125,7 @@ class _CurveFitError(pints.ErrorMeasure):
         self.d = dimension
         self.x = x
         self.y = y
-        self.n = 1 / np.product(y.shape)    # Total number of points in data
+        self.n = 1 / np.prod(y.shape)    # Total number of points in data
 
     def n_parameters(self):
         return self.d


Test patch:
diff --git a/pints/tests/test_log_priors.py b/pints/tests/test_log_priors.py
index a77c9fca..499ac341 100755
--- a/pints/tests/test_log_priors.py
+++ b/pints/tests/test_log_priors.py
@@ -1081,7 +1081,7 @@ class TestPrior(unittest.TestCase):
         self.assertEqual(p([10, 10]), m)
         self.assertEqual(p([5, 20]), m)
 
-        w = -np.log(np.product(upper - lower))
+        w = -np.log(np.prod(upper - lower))
         self.assertEqual(p([1, 2]), w)
         self.assertEqual(p([1, 5]), w)
         self.assertEqual(p([1, 20 - 1e-14]), w)
@@ -1110,7 +1110,7 @@ class TestPrior(unittest.TestCase):
         self.assertEqual(p([10, 10]), m)
         self.assertEqual(p([5, 20]), m)
 
-        w = -np.log(np.product(upper - lower))
+        w = -np.log(np.prod(upper - lower))
         self.assertEqual(p([1, 2]), w)
         self.assertEqual(p([1, 5]), w)
         self.assertEqual(p([1, 20 - 1e-14]), w)