From 8572ecb1b38616f98f2af6462aa4fe5a3a8871ae Mon Sep 17 00:00:00 2001 From: "Philipp A." Date: Tue, 30 Apr 2024 14:03:00 +0200 Subject: [PATCH] Use modern RNG --- scanpy/_utils/__init__.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/scanpy/_utils/__init__.py b/scanpy/_utils/__init__.py index 947ba67003..9a2c402a5e 100644 --- a/scanpy/_utils/__init__.py +++ b/scanpy/_utils/__init__.py @@ -33,6 +33,8 @@ import numpy as np from anndata import AnnData from anndata import __version__ as anndata_version +from numpy.random import MT19937 +from numpy.random import Generator as NPGenerator from numpy.typing import NDArray from packaging import version from scipy import sparse @@ -68,11 +70,19 @@ class RNGIgraph: See :func:`igraph.set_random_number_generator` for the requirements. """ - def __init__(self, random_state: int = 0) -> None: - self._rng = check_random_state(random_state) + def __init__(self, random_state: AnyRandom = 0) -> None: + mt = MT19937() + mt.state = check_random_state(random_state).get_state() + self._rng = NPGenerator(mt) - def __getattr__(self, attr: str): - return getattr(self._rng, "normal" if attr == "gauss" else attr) + self.gauss = self._rng.normal + self.random = self._rng.uniform + self.randint = self._rng.integers + + def getrandbits(self, k: int) -> int: + numbytes = (k + 7) // 8 # bits / 8 and rounded up + x = int.from_bytes(self._rng.bytes(numbytes), "big") + return x >> (numbytes * 8 - k) # trim excess bits def ensure_igraph() -> None: