# Licensed under a 3-clause BSD style license - see LICENSE.rst
"""
This module provides tools for including noise in simulated data.
"""
import numpy as np
__all__ = ['apply_poisson_noise', 'make_noise_image']
[docs]
def apply_poisson_noise(data, seed=None):
"""
Apply Poisson noise to an array, where the value of each element in
the input array represents the expected number of counts.
Each pixel in the output array is generated by drawing a random
sample from a Poisson distribution whose expectation value is given
by the pixel value in the input array.
Parameters
----------
data : array_like
The array on which to apply Poisson noise. Every pixel in the
array must have a positive value (i.e., counts).
seed : int, optional
A seed to initialize the `numpy.random.BitGenerator`. If `None`,
then fresh, unpredictable entropy will be pulled from the OS.
Returns
-------
result : `~numpy.ndarray`
The data array after applying Poisson noise.
See Also
--------
make_noise_image
Examples
--------
.. plot::
:include-source:
import matplotlib.pyplot as plt
from photutils.datasets import (apply_poisson_noise,
make_4gaussians_image)
data1 = make_4gaussians_image(noise=False)
data2 = apply_poisson_noise(data1, seed=0)
# plot the images
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(8, 8))
ax1.imshow(data1, origin='lower', interpolation='nearest')
ax1.set_title('Original image')
ax2.imshow(data2, origin='lower', interpolation='nearest')
ax2.set_title('Original image with Poisson noise applied')
"""
data = np.asanyarray(data)
if np.any(data < 0):
raise ValueError('data must not contain any negative values')
rng = np.random.default_rng(seed)
return rng.poisson(data)
[docs]
def make_noise_image(shape, distribution='gaussian', mean=None, stddev=None,
seed=None):
r"""
Make a noise image containing Gaussian or Poisson noise.
This function simply takes random samples from a Gaussian
or Poisson distribution with the given parameters. If you
want to apply Poisson noise to existing sources, see the
`~photutils.datasets.apply_poisson_noise` function.
Parameters
----------
shape : 2-tuple of int
The shape of the output 2D image.
distribution : {'gaussian', 'poisson'}
The distribution used to generate the random noise:
* ``'gaussian'``: Gaussian distributed noise.
* ``'poisson'``: Poisson distributed noise.
mean : float
The mean of the random distribution. Required for both Gaussian
and Poisson noise. The default is 0.
stddev : float, optional
The standard deviation of the Gaussian noise to add to the
output image. Required for Gaussian noise and ignored for
Poisson noise (the variance of the Poisson distribution is equal
to its mean).
seed : int, optional
A seed to initialize the `numpy.random.BitGenerator`. If `None`,
then fresh, unpredictable entropy will be pulled from the OS.
Returns
-------
image : 2D `~numpy.ndarray`
Image containing random noise.
See Also
--------
apply_poisson_noise
Examples
--------
.. plot::
:include-source:
import matplotlib.pyplot as plt
from photutils.datasets import make_noise_image
# make Gaussian and Poisson noise images
shape = (100, 100)
image1 = make_noise_image(shape, distribution='gaussian', mean=0.,
stddev=5.)
image2 = make_noise_image(shape, distribution='poisson', mean=5.)
# plot the images
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(8, 4))
ax1.imshow(image1, origin='lower', interpolation='nearest')
ax1.set_title(r'Gaussian noise ($\mu=0$, $\sigma=5.$)')
ax2.imshow(image2, origin='lower', interpolation='nearest')
ax2.set_title(r'Poisson noise ($\mu=5$)')
"""
if mean is None:
raise ValueError('"mean" must be input')
rng = np.random.default_rng(seed)
if distribution == 'gaussian':
if stddev is None:
raise ValueError('"stddev" must be input for Gaussian noise')
image = rng.normal(loc=mean, scale=stddev, size=shape)
elif distribution == 'poisson':
image = rng.poisson(lam=mean, size=shape)
else:
raise ValueError(f'Invalid distribution: {distribution}. Use either '
'"gaussian" or "poisson".')
return image