File size: 1,440 Bytes
c30b460
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
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
from __future__ import annotations

import numpy as np

from .silverstein import df2, solve_kappa


def diamond(eigenvalues: np.ndarray, kappa: float, vector: np.ndarray) -> float:
    eig = np.asarray(eigenvalues, dtype=np.float64)
    vec = np.asarray(vector, dtype=np.float64)
    weights = eig / (eig + kappa) ** 2
    return float(np.sum(vec**2 * weights))


def denoiser_variance_prediction(
    eigenvalues: np.ndarray,
    noise_variance: float,
    n_samples: int,
    probe_index: int,
    location: np.ndarray,
) -> float:
    eig = np.asarray(eigenvalues, dtype=np.float64)
    if not 0 <= probe_index < eig.size:
        raise IndexError("probe_index out of bounds")
    kappa = solve_kappa(eig, noise_variance, n_samples)
    probe = np.zeros_like(eig)
    probe[probe_index] = 1.0
    denominator = float(n_samples) - df2(eig, kappa)
    if denominator <= 0:
        raise ValueError("n_samples must exceed df2(kappa)")
    return (kappa**2 / denominator) * diamond(eig, kappa, probe) * diamond(
        eig, kappa, location
    )


def denoiser_anisotropy_profile(
    eigenvalues: np.ndarray, noise_variance: float, n_samples: int, location: np.ndarray
) -> np.ndarray:
    eig = np.asarray(eigenvalues, dtype=np.float64)
    return np.array(
        [
            denoiser_variance_prediction(eig, noise_variance, n_samples, idx, location)
            for idx in range(eig.size)
        ],
        dtype=np.float64,
    )