Source code for analyseur.rbcbg.parameters

# ~/analyseur/rbcbg/parameters.py
#
# Documentation by Lungsi 18 Nov 2025
#

from dataclasses import dataclass, field
# from typing import List, Tuple, Set, Dict # Not needed for Python 3.9+
import math


DEFAULT_FREQUENCY_BANDS = {
    "Delta": (1, 4),
    "Theta": (4, 8),
    "Alpha": (8, 12),
    "Beta": (12, 30),
    "Gamma": (30, 100),
    "Low Gamma": (30, 80),
    "High Gamma": (80, 150),
}

[docs] def bin_size_by_rule(total_time=None, rule=None, frequency=None): """ Returns bin size by rule - Square Root Rule (`rule="Square Root"`) - general purpose, quick estimate - Rice Rule (`rule="Rice Rule"`) - suitable for larger datasets - Periodic (`rule="Periodic"`) - for periodic signal ------- Formula ------- .. table:: ============================================ ====================================================== Definitions Interpretation ============================================ ====================================================== duration, :math:`dur` total time in seconds sampling period, :math:`T` sampling period in seconds total samples, :math:`N = dur / T` total number of samples ============================================ ====================================================== Formula: Square Root Rule ------------------------- .. math:: n_{bins} &= \\sqrt(N) \n binsz &= \\frac{dur}{n_{bins}} Formula: Rice Rule ------------------ .. math:: n_{bins} &= 2 \\sqrt[3](N) \n binsz &= \\frac{dur}{n_{bins}} Formula: Periodic Rule ---------------------- Let the periodic signal be oscillating at :math:`\\nu` frequency, then .. math:: T &= \\frac{1}{\\nu} \n binsz &= m \\times T where `m` is the number of periods. Generally, :math:`m=2`. -------- Use Case -------- :: from analyseur.rbcbg.parameters import bin_size_by_rule dur = 10 # seconds nu = 80 # Hz binsz_sqrt = bin_size_by_rule(total_time=dur, rule="Square Root") binsz_rice = bin_size_by_rule(total_time=dur, rule="Rice Rule") binsz_osc = bin_size_by_rule(frequency=nu, rule="Periodic") .. raw:: html <hr style="border: 2px solid red; margin: 20px 0;"> """ match rule: case "Square Root": n_bins = round( math.sqrt(total_time) ) case "Rice Rule": n_bins = round( 2 * math.cbrt(total_time) ) case "Periodic": period = 1 / frequency if rule in ["Square Root", "Rice Rule"]: return total_time / n_bins else: return 2 * period # two periods in one bin
[docs] @dataclass class SimulationParams: """ ================ SimulationParams ================ Default parameters from rBCBG simulation +----------------------+---------------------------------------+ | Parameter name | Value | +======================+=======================================+ | `duration` | `10000` milliseconds | +----------------------+---------------------------------------+ | `dt` | `1.0` milliseconds | +----------------------+---------------------------------------+ | `modelID` | `9` | +----------------------+---------------------------------------+ | `nuclei_ctx` | `["CSN", "PTN", "CTX_E", "CTX_I"]` | +----------------------+---------------------------------------+ | `nuclei_bg` | `["FSI", "STN", "GPe", "GPiSNr",]` | +----------------------+---------------------------------------+ | `nuclei_thal` | `["TRN", "TH"]` | +----------------------+---------------------------------------+ -------- Use Case -------- :: from analyseur.rbcbg.parameters import SimulationParams simparams = SimulationParams() .. raw:: html <hr style="border: 2px solid red; margin: 20px 0;"> """ duration: float = 10000 # ms dt: float = 1.0 # ms modelID: int = 9 nuclei_ctx: list[str] = None nuclei_bg: list[str] = None nuclei_thal: list[str] = None def __post_init__(self): if self.nuclei_ctx is None: self.nuclei_ctx = ["CSN", "PTN", "CTX_E", "CTX_I",] if self.nuclei_bg is None: self.nuclei_bg = ["FSI", "STN", "GPe", "GPiSNr",] if self.nuclei_thal is None: self.nuclei_thal = ["TRN", "TH"]
[docs] @dataclass class SignalAnalysisParams: """ ==================== SignalAnalysisParams ==================== Default parameters for signal analysis +------------------------+---------------------+ | Parameter name | Value | +========================+=====================+ | `_1000ms` | `1000` milliseconds | +------------------------+---------------------+ | `decimal_places` | `3` | +------------------------+---------------------+ | `decimal_places_ephys` | `5` | +------------------------+---------------------+ | `window` | `(0, 10)` seconds | +------------------------+---------------------+ | `sampling_period` | `0.001` seconds | +------------------------+---------------------+ | `sampling_period_ms` | `1.0` milliseconds | +------------------------+---------------------+ | `binsz_sqrt_rule` | `3.333` | +------------------------+---------------------+ | `binsz_rice_rule` | `2.5` | +------------------------+---------------------+ | `binsz_10perbin` | `0.01` | +------------------------+---------------------+ | `binsz_100perbin` | `0.1` | +------------------------+---------------------+ | `binsz_1000perbin` | `1.0` | +------------------------+---------------------+ -------- Use Case -------- :: from analyseur.rbcbg.parameters import SignalAnalysisParams siganal = SignalAnalysisParams() .. raw:: html <hr style="border: 2px solid red; margin: 20px 0;"> """ _1000ms: int = 1000 decimal_places: int = 3 decimal_places_ephys: int = 5 # very small values for disinhibition experiments window: tuple[float, float] = (0, SimulationParams.duration / _1000ms) sampling_period_ms: float = SimulationParams.dt sampling_period: float = SimulationParams.dt / _1000ms binsz_sqrt_rule: float = bin_size_by_rule(SimulationParams.duration / _1000ms, "Square Root") binsz_rice_rule: float = bin_size_by_rule(SimulationParams.duration / _1000ms, "Rice Rule") binsz_10perbin: float = 10 * sampling_period binsz_100perbin: float = 100 * sampling_period binsz_1000perbin: float = 1000 * sampling_period std_Gaussian_kernel: float = 2 freq_bands: dict = field(default_factory=lambda: DEFAULT_FREQUENCY_BANDS.copy()) def validate(self): if any(binsz <= 0 for binsz in [binsz_sqrt_rule, binsz_rice_rule, binsz_10perbin, binsz_100perbin, binsz_1000perbin]): raise ValueError("bin size must be positive") if self.window[1] <= self.window[0]: raise ValueError("time window end must be greater than start")
#custom_param = SpikeAnalysisParams(window=(0,5), binsz=0.02)