diff --git a/sigpy/mri/samp.py b/sigpy/mri/samp.py
index b2877ec..0bc79ef 100644
--- a/sigpy/mri/samp.py
+++ b/sigpy/mri/samp.py
@@ -30,6 +30,9 @@ def poisson(img_shape, accel, K=30, calib=[0, 0], dtype=np.complex,
         SIGGRAPH sketches. 2007.
 
     """
+    if seed is not None:
+        rand_state = np.random.get_state()
+
     y, x = np.mgrid[:img_shape[-2], :img_shape[-1]]
     x = np.maximum(abs(x - img_shape[-1] / 2) - calib[-1] / 2, 0)
     x /= x.max()
@@ -56,6 +59,10 @@ def poisson(img_shape, accel, K=30, calib=[0, 0], dtype=np.complex,
             slope_max = slope
 
     mask = mask.reshape(img_shape).astype(dtype)
+
+    if seed is not None:
+        np.random.set_state(rand_state)
+
     if return_density:
         return mask, R
     else:
@@ -130,24 +137,22 @@ def radial(coord_shape, img_shape, golden=True, dtype=np.float):
 
 
 @nb.jit(nopython=True, cache=True)  # pragma: no cover
-def _poisson(nx, ny, K, R, calib, seed):
+def _poisson(nx, ny, K, R, calib, seed=None):
 
     mask = np.zeros((ny, nx))
     f = ny / nx
 
     if seed is not None:
-        rand_state = np.random.RandomState(int(seed))
-    else:
-        rand_state = np.random
+        np.random.seed(int(seed))
 
     pxs = np.empty(nx * ny, np.int32)
     pys = np.empty(nx * ny, np.int32)
-    pxs[0] = rand_state.randint(0, nx)
-    pys[0] = rand_state.randint(0, ny)
+    pxs[0] = np.random.randint(0, nx)
+    pys[0] = np.random.randint(0, ny)
     m = 1
     while (m > 0):
 
-        i = rand_state.randint(0, m)
+        i = np.random.randint(0, m)
         px = pxs[i]
         py = pys[i]
         rad = R[py, px]
@@ -158,8 +163,8 @@ def _poisson(nx, ny, K, R, calib, seed):
         while not done and k < K:
 
             # Generate point randomly from R and 2R
-            rd = rad * (rand_state.random() * 3 + 1)**0.5
-            t = 2 * np.pi * rand_state.random()
+            rd = rad * (np.random.random() * 3 + 1)**0.5
+            t = 2 * np.pi * np.random.random()
             qx = px + rd * np.cos(t)
             qy = py + rd * f * np.sin(t)
 

RandomState not supported in numba
**Describe the bug**
An [earlier PR](https://github.com/mikgroup/sigpy/pull/55) attempted to resolve an issue where calling `sigpy.mri.samp.poisson` changed the numpy state (#54). However, `numba` only supports a select number of `numpy` operations and no longer supports the `RandomState` class in functions decorated with `nb.jit`. This is likely the source of the error.

**To Reproduce**
```python
from sigpy.mri.samp import poisson

# Not the issue occurs with any arbitrary image size and acceleration.
mask = poisson((320, 320), accel=6, seed=80)
```

**Expected behavior**
Expect to have no error in call while still ensuring that global numpy state does not change when seed is specified in `sigpy.mri.samp.poisson`.


diff --git a/tests/mri/test_samp.py b/tests/mri/test_samp.py
new file mode 100644
index 0000000..6e5d107
--- /dev/null
+++ b/tests/mri/test_samp.py
@@ -0,0 +1,33 @@
+import unittest
+import numpy as np
+import numpy.testing as npt
+
+from sigpy.mri import samp
+
+if __name__ == '__main__':
+    unittest.main()
+
+
+class TestPoisson(unittest.TestCase):
+    """Test poisson undersampling defined in `sigpy.mri.samp.poisson`."""
+
+    def test_numpy_random_state(self):
+        """Verify that random state is unchanged when seed is specified."""
+        np.random.seed(0)
+        expected_state = np.random.get_state()
+
+        _ = samp.poisson((320, 320), accel=6, seed=80)
+
+        state = np.random.get_state()
+        assert (expected_state[1] == state[1]).all()
+
+    def test_reproducibility(self):
+        """Verify that poisson is reproducible."""
+        np.random.seed(45)
+        mask1 = samp.poisson((320, 320), accel=6, seed=80)
+
+        # Changing internal numpy state should not affect mask.
+        np.random.seed(20)
+        mask2 = samp.poisson((320, 320), accel=6, seed=80)
+
+        npt.assert_allclose(mask2, mask1)

pip install -e .
parse_log_pytest
requirements.txt
codecov flake8 sphinx matplotlib pytest
3.7
requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
alabaster==0.7.13
Babel==2.14.0
certifi @ file:///croot/certifi_1671487769961/work/certifi
charset-normalizer==3.4.1
codecov==2.1.13
coverage==7.2.7
cycler==0.11.0
docutils==0.17.1
exceptiongroup==1.2.2
flake8==5.0.4
fonttools==4.38.0
idna==3.10
imagesize==1.4.1
importlib-metadata==4.2.0
iniconfig==2.0.0
Jinja2==3.1.6
kiwisolver==1.4.5
llvmlite==0.39.1
MarkupSafe==2.1.5
matplotlib==3.5.3
mccabe==0.7.0
numba==0.56.4
numpy==1.21.6
packaging==24.0
Pillow==9.5.0
pluggy==1.2.0
pycodestyle==2.9.1
pyflakes==2.5.0
Pygments==2.17.2
pyparsing==3.1.4
pytest==7.4.4
python-dateutil==2.9.0.post0
pytz==2025.2
PyWavelets==1.3.0
requests==2.31.0
scipy==1.7.3
-e git+https://github.com/mikgroup/sigpy.git@a44d3d3b8b958bb276cd15d614406e14b093842e#egg=sigpy
six==1.17.0
snowballstemmer==2.2.0
Sphinx==4.3.2
sphinxcontrib-applehelp==1.0.2
sphinxcontrib-devhelp==1.0.2
sphinxcontrib-htmlhelp==2.0.0
sphinxcontrib-jsmath==1.0.1
sphinxcontrib-qthelp==1.0.3
sphinxcontrib-serializinghtml==1.1.5
tomli==2.0.1
tqdm==4.67.1
typing_extensions==4.7.1
urllib3==2.0.7
zipp==3.15.0

name: sigpy
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2022.12.7=py37h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - pip=22.3.1=py37h06a4308_0
  - python=3.7.16=h7a1cb2a_0
  - readline=8.2=h5eee18b_0
  - setuptools=65.6.3=py37h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - wheel=0.38.4=py37h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - alabaster==0.7.13
      - babel==2.14.0
      - charset-normalizer==3.4.1
      - codecov==2.1.13
      - coverage==7.2.7
      - cycler==0.11.0
      - docutils==0.17.1
      - exceptiongroup==1.2.2
      - flake8==5.0.4
      - fonttools==4.38.0
      - idna==3.10
      - imagesize==1.4.1
      - importlib-metadata==4.2.0
      - iniconfig==2.0.0
      - jinja2==3.1.6
      - kiwisolver==1.4.5
      - llvmlite==0.39.1
      - markupsafe==2.1.5
      - matplotlib==3.5.3
      - mccabe==0.7.0
      - numba==0.56.4
      - numpy==1.21.6
      - packaging==24.0
      - pillow==9.5.0
      - pluggy==1.2.0
      - pycodestyle==2.9.1
      - pyflakes==2.5.0
      - pygments==2.17.2
      - pyparsing==3.1.4
      - pytest==7.4.4
      - python-dateutil==2.9.0.post0
      - pytz==2025.2
      - pywavelets==1.3.0
      - requests==2.31.0
      - scipy==1.7.3
      - six==1.17.0
      - snowballstemmer==2.2.0
      - sphinx==4.3.2
      - sphinxcontrib-applehelp==1.0.2
      - sphinxcontrib-devhelp==1.0.2
      - sphinxcontrib-htmlhelp==2.0.0
      - sphinxcontrib-jsmath==1.0.1
      - sphinxcontrib-qthelp==1.0.3
      - sphinxcontrib-serializinghtml==1.1.5
      - tomli==2.0.1
      - tqdm==4.67.1
      - typing-extensions==4.7.1
      - urllib3==2.0.7
      - zipp==3.15.0
prefix: /opt/conda/envs/sigpy

tests/mri/test_samp.py::TestPoisson::test_numpy_random_state tests/mri/test_samp.py::TestPoisson::test_reproducibility
sigpy/mri/samp.py
sigpy/mri/samp.py