sdr.h0(sigma2: float = 1.0, detector: 'coherent' | 'linear' | 'square-law' = 'square-law', complex: bool = True, n_c: int = 1, n_nc: int | None = None) rv_continuous

Computes the statistical distribution under the null hypothesis \(\mathcal{H}_0\).

Parameters:
sigma2: float = 1.0

The noise variance \(\sigma^2\) in linear units.

detector: 'coherent' | 'linear' | 'square-law' = 'square-law'

The detector type.

  • "coherent": A coherent detector,

    \[T(x) = \mathrm{Re}\left\{\sum_{i=0}^{N_c-1} x[n-i]\right\} .\]

  • "linear": A linear detector,

    \[T(x) = \sum_{j=0}^{N_{nc}-1}\left|\sum_{i=0}^{N_c-1} x[n-i-jN_c]\right| .\]

  • "square-law": A square-law detector,

    \[T(x) = \sum_{j=0}^{N_{nc}-1}\left|\sum_{i=0}^{N_c-1} x[n-i-jN_c]\right|^2 .\]

complex: bool = True

Indicates whether the input signal is real or complex. This affects how the SNR is converted to noise variance.

n_c: int = 1

The number of samples to coherently integrate \(N_c\).

n_nc: int | None = None

The number of samples to non-coherently integrate \(N_{nc}\). Non-coherent integration is only allowable for linear and square-law detectors.

Returns:

The distribution under the null hypothesis \(\mathcal{H}_0\).

Examples

In [1]: snr = 5  # Signal-to-noise ratio in dB

In [2]: sigma2 = 1  # Noise variance

In [3]: p_fa = 1e-1  # Probability of false alarm

Compare the detection statistics for complex signals.

In [4]: A2 = sdr.linear(snr) * sigma2; A2  # Signal power, A^2
Out[4]: 3.1622776601683795

In [5]: x_h0 = rng.normal(size=100_000, scale=np.sqrt(sigma2 / 2)) + 1j * rng.normal(size=100_000, scale=np.sqrt(sigma2 / 2)); \
   ...: x_h1 = np.sqrt(A2) + x_h0
   ...: 
In [6]: detector = "coherent"; \
   ...: h0 = sdr.h0(sigma2, detector); \
   ...: h1 = sdr.h1(snr, sigma2, detector)
   ...: 

In [7]: threshold = sdr.threshold(p_fa, sigma2, detector); threshold
Out[7]: 0.9061938024368232

In [8]: p_d = sdr.p_d(snr, p_fa, detector); p_d
Out[8]: 0.8912709229530473

In [9]: z_h0 = np.real(x_h0); \
   ...: z_h1 = np.real(x_h1)
   ...: 

In [10]: plt.figure(); \
   ....: sdr.plot.detector_pdfs(h0, h1, threshold); \
   ....: plt.gca().set_prop_cycle(None); \
   ....: plt.hist(z_h0, bins=101, histtype="step", density=True); \
   ....: plt.hist(z_h1, bins=101, histtype="step", density=True); \
   ....: plt.title("Coherent Detector: Probability density functions");
   ....: 
../../_images/sdr_h0_1.png
In [11]: detector = "linear"; \
   ....: h0 = sdr.h0(sigma2, detector); \
   ....: h1 = sdr.h1(snr, sigma2, detector)
   ....: 

In [12]: threshold = sdr.threshold(p_fa, sigma2, detector); threshold
Out[12]: 1.5174271293851465

In [13]: p_d = sdr.p_d(snr, p_fa, detector); p_d
Out[13]: 0.7229165664874564

In [14]: z_h0 = np.abs(x_h0); \
   ....: z_h1 = np.abs(x_h1)
   ....: 

In [15]: plt.figure(); \
   ....: sdr.plot.detector_pdfs(h0, h1, threshold); \
   ....: plt.gca().set_prop_cycle(None); \
   ....: plt.hist(z_h0, bins=101, histtype="step", density=True); \
   ....: plt.hist(z_h1, bins=101, histtype="step", density=True); \
   ....: plt.title("Linear Detector: Probability density functions");
   ....: 
../../_images/sdr_h0_2.png
In [16]: detector = "square-law"; \
   ....: h0 = sdr.h0(sigma2, detector); \
   ....: h1 = sdr.h1(snr, sigma2, detector)
   ....: 

In [17]: threshold = sdr.threshold(p_fa, sigma2, detector); threshold
Out[17]: 2.302585092994046

In [18]: p_d = sdr.p_d(snr, p_fa, detector); p_d
Out[18]: 0.7229165664874556

In [19]: z_h0 = np.abs(x_h0) ** 2; \
   ....: z_h1 = np.abs(x_h1) ** 2
   ....: 

In [20]: plt.figure(); \
   ....: sdr.plot.detector_pdfs(h0, h1, threshold); \
   ....: plt.gca().set_prop_cycle(None); \
   ....: plt.hist(z_h0, bins=101, histtype="step", density=True); \
   ....: plt.hist(z_h1, bins=101, histtype="step", density=True); \
   ....: plt.title("Square-Law Detector: Probability density functions");
   ....: 
../../_images/sdr_h0_3.png

Compare the detection statistics for real signals.

In [21]: A2 = sdr.linear(snr) * sigma2; A2  # Signal power, A^2
Out[21]: 3.1622776601683795

In [22]: x_h0 = rng.normal(size=100_000, scale=np.sqrt(sigma2)); \
   ....: x_h1 = np.sqrt(A2) + x_h0
   ....: 
In [23]: detector = "coherent"; \
   ....: h0 = sdr.h0(sigma2, detector, complex=False); \
   ....: h1 = sdr.h1(snr, sigma2, detector, complex=False)
   ....: 

In [24]: threshold = sdr.threshold(p_fa, sigma2, detector, complex=False); threshold
Out[24]: 1.2815515655446004

In [25]: p_d = sdr.p_d(snr, p_fa, detector, complex=False); p_d
Out[25]: 0.6903095079298097

In [26]: z_h0 = np.real(x_h0); \
   ....: z_h1 = np.real(x_h1)
   ....: 

In [27]: plt.figure(); \
   ....: sdr.plot.detector_pdfs(h0, h1, threshold); \
   ....: plt.gca().set_prop_cycle(None); \
   ....: plt.hist(z_h0, bins=101, histtype="step", density=True); \
   ....: plt.hist(z_h1, bins=101, histtype="step", density=True); \
   ....: plt.title("Coherent Detector: Probability density functions");
   ....: 
../../_images/sdr_h0_4.png
In [28]: detector = "linear"; \
   ....: h0 = sdr.h0(sigma2, detector, complex=False); \
   ....: h1 = sdr.h1(snr, sigma2, detector, complex=False)
   ....: 

In [29]: threshold = sdr.threshold(p_fa, sigma2, detector, complex=False); threshold
Out[29]: 1.6448536269514744

In [30]: p_d = sdr.p_d(snr, p_fa, detector, complex=False); p_d
Out[30]: 0.5533811909871471

In [31]: z_h0 = np.abs(x_h0); \
   ....: z_h1 = np.abs(x_h1)
   ....: 

In [32]: plt.figure(); \
   ....: sdr.plot.detector_pdfs(h0, h1, threshold); \
   ....: plt.gca().set_prop_cycle(None); \
   ....: plt.hist(z_h0, bins=101, histtype="step", density=True); \
   ....: plt.hist(z_h1, bins=101, histtype="step", density=True); \
   ....: plt.title("Linear Detector: Probability density functions");
   ....: 
../../_images/sdr_h0_5.png
In [33]: detector = "square-law"; \
   ....: h0 = sdr.h0(sigma2, detector, complex=False); \
   ....: h1 = sdr.h1(snr, sigma2, detector, complex=False)
   ....: 

In [34]: threshold = sdr.threshold(p_fa, sigma2, detector, complex=False); threshold
Out[34]: 2.70554345409542

In [35]: p_d = sdr.p_d(snr, p_fa, detector, complex=False); p_d
Out[35]: 0.5533811909871473

In [36]: z_h0 = np.abs(x_h0) ** 2; \
   ....: z_h1 = np.abs(x_h1) ** 2
   ....: 

In [37]: plt.figure(); \
   ....: sdr.plot.detector_pdfs(h0, h1, threshold, x=np.linspace(0, 15, 1001)); \
   ....: plt.gca().set_prop_cycle(None); \
   ....: plt.hist(z_h0, bins=101, histtype="step", density=True); \
   ....: plt.hist(z_h1, bins=101, histtype="step", density=True); \
   ....: plt.xlim(0, 15); \
   ....: plt.ylim(0, 0.5); \
   ....: plt.title("Square-Law Detector: Probability density functions");
   ....: 
../../_images/sdr_h0_6.png