Source code for analyseur.cbgtc.parameters

# ~/analyseur/cbgtc/parameters.py
#
# Documentation by Lungsi 20 Oct 2025
#
# This contains function for loading the files
#

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

DEFAULT_CONDUCTANCES = {
    "cortex": { # 0.05
        "g_L": 1.0, # This is called g_L_mean in CBGTC and unit is mS.cm-2
    },
    "bg": {},
    "thalamus": {
        "g_L": 0.05, # This is called g_L_mean in CBGTC and unit is mS.cm-2
    },
}

DEFAULT_FEEDFORWORD_CURRENTS = {
    "cortex": { # Case: NOT 'cortex_alone'
        "CSN": 1.124,
        "PTN": 1.25,
        "IN": 1.178,
    },
    "bg": { # Case: NOT 'bg_alone'
        "MSN": 28.3, # * mvolt
        "FSI": 12.0, # * mvolt
        "STN": 19.5, # * mvolt
        "GPe": 26.0, # * mvolt
        "GPi": 15.0, # * mvolt
        # NOTE: for bg these are NOT current values
    },
    "thalamus": { # Case: NOT 'thalamus_alone'
        "MD": 1.15,
        "TRN": 1.2,
    },
}

DEFAULT_EQUILIBRIUM_POTENTIALS = {
    "cortex": {
        "V_L": -70.0, # mV
        "V_AMPA": 0.0, # mV
        "V_GABAA": -70.0, # mV
        "V_NMDA": 0.0, # mV
        "V_GABAB": -90.0, # mV
    },
    "bg": {
        "V_L": -70.0, # mV
        "V_AMPA": 0.0, # mV
        "V_NMDA": 0.0, # mV
        "V_GABAA": -70.0, # mV
        "V_GABAB": -90.0, # mV
    },
    "thalamus": {
        "V_L": -70.0, # mV
        "V_AMPA": 0.0, # mV
        "V_GABAA": -70.0, # mV
        "V_NMDA": 0.0, # mV
        "V_GABAB": -90.0, # mV
    }
}

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),
}

DEFAULT_SIZE_INFO = {
    "cortex": {
        "TOTAL_NUMBER_OF_POPULATIONS": 4,  # TOTAL_NUMBER_OF_CHANNELS_MODEL
        "scale": 4,  # The number of neurons will be multiplied by this value
        "TOTAL_NUMBER_OF_CHANNELS": 4,
    },
    "bg": {
        "TOTAL_NUMBER_OF_POPULATIONS": 4,
        "scale": 4,
        "TOTAL_NUMBER_OF_CHANNELS": 4,
    },
    "thalamus": {
        "TOTAL_NUMBER_OF_POPULATIONS": 4,
        "scale": 4,
        "TOTAL_NUMBER_OF_CHANNELS": 4,
    }
}

DEFAULT_PROJECTIONS_TYPES = {
    "bg": {
        'MD->MSN' : 'focused', # TODO check if should be diffuse instead?
        'MD->FSI' : 'focused', # TODO check if should be diffuse instead?
        'ProtGPe->STN':          'focused', # ^
        'GPe->STN':           'focused', # ^
        'PTN->MSN':           'focused', # ^
        'CSN->MSN':           'focused', #
        'CMPf->MSN':          'diffuse', # ^
        'MSN->MSN':           'diffuse', # ^
        'FSI->MSN':           'diffuse', # ^
        'STN->MSN':           'diffuse', # ^
        'GPe->MSN':           'diffuse', # ^
        'CSN->FSI':           'focused', # ^
        'PTN->FSI':           'focused', # ^
        'CMPf->FSI':          'diffuse', # ^
        'FSI->FSI':           'diffuse', # ^
        'STN->FSI':           'diffuse', # ^
        'GPe->FSI':           'diffuse', # ^
        'PTN->STN':           'focused', # ^
        'CMPf->STN':          'diffuse', # ^
        'GPe->STN':           'focused', # ^
        'CMPf->GPe':          'diffuse', # ^
        'MSN->GPe':           'focused', # ^
        'STN->GPe':           'diffuse', # ^
        'GPe->GPe':           'diffuse', # ^
        'CMPf->GPi':          'diffuse', # ^
        'MSN->GPi':           'focused', # ^
        'STN->GPi':           'diffuse', # ^
        'GPe->GPi':           'diffuse', #
        'ArkyGPe->MSN':          'diffuse', # ^
        'ArkyGPe->FSI':          'diffuse', # ^
        'CMPf->ArkyGPe':         'diffuse', # ^
        'MSN->ArkyGPe':          'focused', # ^
        'STN->ArkyGPe':          'diffuse', # ^
        'ArkyGPe->ArkyGPe':         'diffuse', # ^
        'ProtGPe->ArkyGPe':         'diffuse', # ^
        'CMPf->ProtGPe':         'diffuse', # ^
        'MSN->ProtGPe':          'focused', # ^
        'STN->ProtGPe':          'diffuse', # ^
        'ArkyGPe->ProtGPe':         'diffuse', # ^
        'ProtGPe->ProtGPe':         'diffuse', # ^
        'ProtGPe->GPi':          'diffuse', # ^
    },
    "cortex": {
        'CSN->CSN': 'diffuse',
        'CSN->PTN': 'diffuse',
        'CSN->IN': 'diffuse',
        'PTN->CSN': 'diffuse',
        'PTN->PTN': 'diffuse',
        'PTN->IN': 'diffuse',
        'IN->CSN': 'diffuse',
        'IN->IN': 'diffuse',
        'IN->PTN': 'diffuse',
        'MD->IN': 'diffuse',
        'MD->PTN': 'focused',
        'MD->CSN': 'focused'
    },
    "thalamus": {
        'TRN->MD': 'diffuse',
        'MD->TRN': 'focused',
        'TRN->TRN' : 'diffuse',
        'GPi->MD': 'focused',
        'PTN->MD': 'focused',
        'PTN->TRN': 'focused',
        'CMPf->TRN': 'diffuse'
    },
}

DEFAULT_CONNECTED_REGIONS = {
    ("Cortex", "Cortex"),
    ("Cortex", "BasalGanglia"),
    ("Cortex", "Thalamus"),
    ("BasalGanglia", "Thalamus"),
    ("Thalamus", "Cortex"),
    ("BasalGanglia", "BasalGanglia"),
    ("Thalamus", "Thalamus"),
}


[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.cbgtc.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 CBGT simulation +----------------------+---------------------------------------+ | Parameter name | Value | +======================+=======================================+ | `duration` | `10000` milliseconds | +----------------------+---------------------------------------+ | `t_start_recording` | `2000` milliseconds | +----------------------+---------------------------------------+ | `dt` | `0.1` milliseconds | +----------------------+---------------------------------------+ | `nuclei_ctx` | `["CSN", "PTN", "IN"]` | +----------------------+---------------------------------------+ | `nuclei_bg` | `["FSI", "GPe", "GPi", "MSN", "STN"]` | +----------------------+---------------------------------------+ | `nuclei_thal` | `["TRN", "MD"]` | +----------------------+---------------------------------------+ | `neurotrans` | `['AMPA', 'NMDA', 'GABAA', 'GABAB']` | +----------------------+---------------------------------------+ | `conductance` | `DEFAULT_CONDUCTANCES` | +----------------------+---------------------------------------+ | `ff_currents` | `DEFAULT_FEEDFORWORD_CURRENTS` | +----------------------+---------------------------------------+ -------- Use Case -------- :: from analyseur.cbgtc.parameters import SimulationParams simparams = SimulationParams() .. raw:: html <hr style="border: 2px solid red; margin: 20px 0;"> """ # --- Class constants --- REGION_ALIASES = {"cortex": "Cortex", "ctx": "Cortex", "basalganglia": "BasalGanglia", "bg": "BasalGanglia", "basal_ganglia": "BasalGanglia", "thalamus": "Thalamus", "thal": "Thalamus",} # --- Instance fields --- duration: float = 10000 # ms t_start_recording = 2000 # ms dt: float = 0.1 # ms nuclei_ctx: list[str] = None nuclei_bg: list[str] = None nuclei_thal: list[str] = None neurotrans: list[str] = None conductance: dict = field(default_factory=lambda: DEFAULT_CONDUCTANCES.copy()) ff_currents: dict = field(default_factory=lambda: DEFAULT_FEEDFORWORD_CURRENTS.copy()) size_info: dict = field(default_factory=lambda: DEFAULT_SIZE_INFO.copy()) modelParamsID: int = 9 projection_types: dict = field(default_factory=lambda: DEFAULT_PROJECTIONS_TYPES.copy()) connected_regions: set[tuple[str, str]] = field(default_factory=lambda: DEFAULT_CONNECTED_REGIONS.copy()) def __post_init__(self): if self.nuclei_ctx is None: self.nuclei_ctx = ["CSN", "PTN", "IN",] if self.nuclei_bg is None: self.nuclei_bg = ["FSI", "GPe", "GPi", "MSN", "STN",] if self.nuclei_thal is None: self.nuclei_thal = ["MD", "TRN",] # "CMPf" is not accompanied with myriad raw datasets if self.neurotrans is None: self.neurotrans = ['AMPA', 'NMDA', 'GABAA', 'GABAB']
[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.0001` seconds | +------------------------+---------------------+ | `sampling_period_ms` | `0.1` milliseconds | +------------------------+---------------------+ | `binsz_sqrt_rule` | `100` | +------------------------+---------------------+ | `binsz_rice_rule` | `232.558` | +------------------------+---------------------+ | `binsz_10perbin` | `0.001` | +------------------------+---------------------+ | `binsz_100perbin` | `0.01` | +------------------------+---------------------+ | `binsz_1000perbin` | `0.1` | +------------------------+---------------------+ -------- Use Case -------- :: from analyseur.cbgtc.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)