Source code for microscopic_gating.statistics

r"""
Statistical models for bridge counts and gate probabilities.

This module implements the statistical framework for calculating bridge
number distributions and gate open/closed probabilities based on Poisson
statistics.

Theoretical Foundation
----------------------
For a particle with :math:`M` binding sites and :math:`N_{\text{acc}}` accessible
network sites, the total number of potential bridge pairs is:

.. math::

    N_{\text{pair}} = M \cdot N_{\text{acc}}

Under the **independent-pair approximation** (valid when bridge probability
:math:`p_B` is small or site-site coupling is weak), the bridge count
:math:`n_b` follows a **binomial distribution**:

.. math::

    P(n_b) = \binom{N_{\text{pair}}}{n_b} p_B^{n_b} (1-p_B)^{N_{\text{pair}}-n_b}

In the **Poisson limit** (:math:`N_{\text{pair}} \to \infty`, :math:`p_B \to 0`,
with :math:`\lambda = N_{\text{pair}} p_B` finite):

.. math::

    P(n_b) \approx \frac{\lambda^{n_b} e^{-\lambda}}{n_b!}

where the Poisson intensity (mean bridge count) is:

.. math::

    \lambda(\phi) = N_{\text{pair}} \langle\chi\rangle \kappa_B \mathcal{G}(\phi)
                  \equiv \lambda_0 \mathcal{G}(\phi)

Gate State Definition
---------------------
- **Gate Open**: No bridges present (:math:`n_b = 0`)
- **Gate Closed**: At least one bridge (:math:`n_b \geq 1`)

Under Poisson statistics:

.. math::

    P_{\text{open}}(\phi) = e^{-\lambda(\phi)}

    P_{\text{closed}}(\phi) = 1 - e^{-\lambda(\phi)}

**Important:** The exponential form is exact only in the Poisson limit.
For small :math:`N_{\text{pair}}`, use the full binomial distribution.

Key Parameters
--------------
==================== ============================================================
Parameter            Physical Meaning
==================== ============================================================
:math:`M`            Particle valency (number of binding sites)
:math:`N_{\text{acc}}` Accessible network sites in pore
:math:`\lambda_0`    Maximum bridge statistics strength (:math:`= N_{\text{pair}}\langle\chi\rangle\kappa_B/4` at peak)
:math:`\lambda(\phi)` Concentration-dependent Poisson intensity
==================== ============================================================

Examples
--------
Bridge count statistics:

>>> from microscopic_gating.types import SitePairCount
>>> model = BridgeCountModel(SitePairCount(M=10, N_acc=5))
>>> model.lambda_poisson(0.1)  # Mean bridge count
5.0
>>> model.var_binomial(0.1)  # Variance (binomial)
4.5

Gate probabilities:

>>> gate = GateModel()
>>> gate.P_open(1.0)  # Probability of zero bridges
0.3678...
>>> gate.P_closed(1.0)  # Probability of at least one bridge
0.6321...

See Also
--------
MicroscopicGatingModel : Full model using these statistics
BridgeCountModel : Bridge number distribution
GateModel : Gate state probabilities

References
----------
- Eq. (S9): Binomial distribution for bridge counts
- Eq. (S10): Mean and variance
- Eq. (S11): Poisson limit
- Eq. (S12): Gate open/closed probabilities
- Eq. (S13)-(S14): Poisson intensity definition
"""

from __future__ import annotations

from dataclasses import dataclass

import numpy as np

from .types import ArrayLike, SitePairCount


[docs]@dataclass(frozen=True) class BridgeCountModel: r""" Bridge-number statistics for :math:`N_{\text{pair}}` independent site pairs. Implements Eq. (S9)-(S13): - **Binomial distribution**: Exact distribution with probability :math:`p_B` - **Poisson approximation**: :math:`\lambda = N_{\text{pair}} \cdot p_B` The Poisson approximation is valid when :math:`N_{\text{pair}}` is large and :math:`p_B` is small. Parameters ---------- site_pairs : SitePairCount Site pair counts containing M and N_acc, from which :math:`N_{\text{pair}} = M \\times N_{\text{acc}}` is calculated. See Also -------- GateModel : Converts bridge statistics to gate probabilities. Examples -------- >>> from microscopic_gating.types import SitePairCount >>> model = BridgeCountModel(SitePairCount(M=10, N_acc=5)) >>> model.lambda_poisson(0.1) 5.0 >>> model.mean(0.1) 5.0 References ---------- - Eq. (S9)-(S13): Bridge count statistics derivation """ site_pairs: SitePairCount
[docs] def lambda_poisson(self, p_B: ArrayLike) -> ArrayLike: r""" Calculate Poisson intensity. Parameters ---------- p_B : ArrayLike Bridge probability per site pair (may be vectorized). Returns ------- lam : ArrayLike Poisson intensity :math:`\lambda = N_{\text{pair}} \cdot p_B`, same shape as `p_B`. """ p_B = np.asarray(p_B, dtype=float) return float(self.site_pairs.N_pair) * p_B
[docs] def mean(self, p_B: ArrayLike) -> ArrayLike: r""" Calculate mean bridge count. Parameters ---------- p_B : ArrayLike Bridge probability per site pair. Returns ------- mean : ArrayLike Expected value :math:`E[n_b] = N_{\text{pair}} \cdot p_B`. """ return self.lambda_poisson(p_B)
[docs] def var_binomial(self, p_B: ArrayLike) -> ArrayLike: r""" Calculate binomial variance. Parameters ---------- p_B : ArrayLike Bridge probability per site pair. Returns ------- var : ArrayLike Variance :math:`\text{Var}[n_b] = N_{\text{pair}} \cdot p_B \cdot (1 - p_B)`. """ p_B = np.asarray(p_B, dtype=float) return float(self.site_pairs.N_pair) * p_B * (1.0 - p_B)
[docs]@dataclass(frozen=True) class GateModel: r""" Gate open/closed probabilities from Poisson bridge statistics. Implements Eq. (S12), relating the Poisson intensity to gate state probabilities: .. math:: P_{\text{open}} &= e^{-\lambda} P_{\text{closed}} &= 1 - e^{-\lambda} The gate is considered "open" when there are zero bridges and "closed" when there is at least one bridge. Examples -------- >>> model = GateModel() >>> model.P_open(1.0) 0.3678... >>> model.P_closed(1.0) 0.6321... References ---------- - Eq. (S12): Gate probability from Poisson statistics """
[docs] def P_open(self, lam: ArrayLike) -> ArrayLike: r""" Calculate gate open probability. Parameters ---------- lam : ArrayLike Poisson intensity :math:`\lambda`. Returns ------- P_open : ArrayLike Probability of zero bridges: :math:`P_{\text{open}} = e^{-\lambda}`. """ lam = np.asarray(lam, dtype=float) return np.exp(-lam)
[docs] def P_closed(self, lam: ArrayLike) -> ArrayLike: r""" Calculate gate closed probability. Parameters ---------- lam : ArrayLike Poisson intensity :math:`\lambda`. Returns ------- P_closed : ArrayLike Probability of at least one bridge: :math:`P_{\text{closed}} = 1 - e^{-\lambda}`. """ lam = np.asarray(lam, dtype=float) return 1.0 - np.exp(-lam)