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)