clenspy.selection.richness_kernel.emg_cdf

clenspy.selection.richness_kernel.emg_cdf(x, mu, sigma, tau)[source]

The EMG CDF \(F_{\rm EMG}(x;\mu,\sigma,\tau)\), dimensionless.

Let \(X = G + E\) with \(G\sim\mathcal N(\mu,\sigma^2)\) and \(E\sim{\rm Exp}(\tau)\) independent. Conditioning on \(G\) and completing the square gives

\[F_{\rm EMG}(x) = \Phi(z) - e^{A}\,\Phi(z - \tau\sigma), \qquad z = \frac{x-\mu}{\sigma}, \qquad A = -\tau(x-\mu) + \tfrac12\tau^2\sigma^2\]

The evaluated form. Write \(u = (\tau\sigma - z)/\sqrt2\), so that \(\Phi(z-\tau\sigma) = \tfrac12\operatorname{erfc}(u)\). Using \(\operatorname{erfc}(u) = e^{-u^2}\operatorname{erfcx}(u)\) and the algebraic identity

\[A - u^2 = -\tau\sigma z + \tfrac12\tau^2\sigma^2 - \tfrac12(\tau\sigma - z)^2 = -\tfrac12 z^2\]

the whole product collapses to

\[e^{A}\,\Phi(z-\tau\sigma) = \tfrac12\operatorname{erfcx}(u)\,e^{-z^2/2}\]

with no large exponential anywhere: the divergent \(e^{A}\) and the vanishing \(\Phi\) have cancelled identically. For \(u < 0\), where \(\operatorname{erfcx}\) itself overflows, the reflection \(\operatorname{erfc}(u) = 2 - e^{-u^2}\operatorname{erfcx}(|u|)\) gives

\[e^{A}\Phi(z-\tau\sigma) = e^{A} - \tfrac12\operatorname{erfcx}(|u|)\,e^{-z^2/2}\]

which is the only branch where an exponential is evaluated at all.

NOTE: exact for every argument, not asymptotic. The two branches meet at \(u = 0\) where both reduce to \(\tfrac12 e^{-z^2/2}\operatorname{erfcx}(0) = \tfrac12 e^{-z^2/2}\).

NOTE: the result is clipped to \([0,1]\). It is a CDF, and the subtraction can leave \(O(\epsilon)\) excursions outside the bound that would otherwise propagate as a negative probability.

Parameters:
  • x (float or array-like) – Observed richness at which to evaluate the CDF.

  • mu (float or array-like) – Gaussian mean, \(\mu = \lambda^{\rm tr} + \Delta\mu\).

  • sigma (float or array-like) – Gaussian width, in richness units. Positive.

  • tau (float or array-like) – Exponential rate, inverse richness. Positive; the tail mean is \(1/\tau\).

Returns:

np.ndarray – \(F_{\rm EMG} \in [0, 1]\), broadcast over the inputs.