Skip to content

Utilities

sies.utils

Small numerical utilities shared across the library.

add_white_noise

add_white_noise(data, level, rng=None, per_row=True)

Add white Gaussian noise to a real data matrix.

The noise standard deviation is calibrated relative to the energy of the signal: a level of 0.1 corresponds to 10% noise.

Parameters:

Name Type Description Default
data (ndarray, shape(m, n))

Input data matrix (real).

required
level float

Noise level, relative to the root mean square of the data.

required
rng Generator

Random generator, for reproducibility.

None
per_row bool

If True, each row is corrupted independently with a noise level proportional to its own energy.

True

Returns:

Name Type Description
noisy (ndarray, shape(m, n))

The noisy data.

sigma float

Global standard deviation of the added noise, norm(data) / sqrt(data.size) * level.

Raises:

Type Description
ValueError

If level is negative or data is not a 2D array.

Source code in src/sies/utils.py
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
def add_white_noise(
    data: NDArray,
    level: float,
    rng: np.random.Generator | None = None,
    per_row: bool = True,
) -> tuple[NDArray, float]:
    """Add white Gaussian noise to a real data matrix.

    The noise standard deviation is calibrated relative to the energy of
    the signal: a `level` of ``0.1`` corresponds to 10% noise.

    Parameters
    ----------
    data : ndarray, shape (m, n)
        Input data matrix (real).
    level : float
        Noise level, relative to the root mean square of the data.
    rng : numpy.random.Generator, optional
        Random generator, for reproducibility.
    per_row : bool, default True
        If True, each row is corrupted independently with a noise level
        proportional to its own energy.

    Returns
    -------
    noisy : ndarray, shape (m, n)
        The noisy data.
    sigma : float
        Global standard deviation of the added noise,
        ``norm(data) / sqrt(data.size) * level``.

    Raises
    ------
    ValueError
        If `level` is negative or `data` is not a 2D array.
    """
    rng = rng or np.random.default_rng()
    data = np.asarray(data)
    if level < 0:
        raise ValueError("Noise level must be nonnegative.")
    if data.ndim != 2:
        raise ValueError("Data must be a 2D array.")

    if per_row:
        scale = np.linalg.norm(data, axis=1, keepdims=True) / np.sqrt(data.shape[1])
    else:
        scale = np.linalg.norm(data) / np.sqrt(data.size)
    noisy = data + rng.standard_normal(data.shape) * scale * level

    sigma = float(np.linalg.norm(data) / np.sqrt(data.size) * level)
    return noisy, sigma