# ~/analyseur/cbgtc/stat/variation.py
#
# Documentation by Lungsi 2 Oct 2025
#
#
import numpy as np
# from compute_shared import compute_grand_mean as cgm
from analyseur.cbgtc.stats.compute_shared import compute_grand_mean as cgm
[docs]
class Variations(object):
"""
Computes variation or dispersion in the data
+------------------------+---------------------------------------------------------------------------------------------+
| Methods | Argument |
+========================+=============================================================================================+
| :py:meth:`.computeCV` | `isi_set`: Dictionary returned; see :class:`~analyseur.cbgtc.stats.isi.InterSpikeInterval` |
+------------------------+---------------------------------------------------------------------------------------------+
| :py:meth:`.computeCV2` | `isi_set`: Dictionary returned; see :class:`~analyseur.cbgtc.stats.isi.InterSpikeInterval` |
+------------------------+---------------------------------------------------------------------------------------------+
| :py:meth:`.computeLV` | `isi_set`: Dictionary returned; see :class:`~analyseur.cbgtc.stats.isi.InterSpikeInterval` |
+------------------------+---------------------------------------------------------------------------------------------+
| :py:meth:`grandCV` | `isi_set`: Dictionary returned; see :class:`~analyseur.cbgtc.stats.isi.InterSpikeInterval` |
+------------------------+---------------------------------------------------------------------------------------------+
| :py:meth:`grandCV2` | `isi_set`: Dictionary returned; see :class:`~analyseur.cbgtc.stats.isi.InterSpikeInterval` |
+------------------------+---------------------------------------------------------------------------------------------+
| :py:meth:`grandLV` | `isi_set`: Dictionary returned; see :class:`~analyseur.cbgtc.stats.isi.InterSpikeInterval` |
+------------------------+---------------------------------------------------------------------------------------------+
=========
Use Cases
=========
------------------
1. Pre-requisites
------------------
1.1. Import Modules
````````````````````
::
from analyseur.cbgtc.loader import LoadSpikeTimes
from analyseur.cbgtc.stats.isi import InterSpikeInterval
from analyseur.cbgtc.stats.variation import Variations
1.2. Load file and get spike times
```````````````````````````````````
::
loadST = LoadSpikeTimes("spikes_GPi.csv")
spiketimes_superset = loadST.get_spiketimes_superset()
1.3. Compute the Inter-Spike Intervals
``````````````````````````````````````
::
[I, _] = InterSpikeInterval.compute(spiketimes_superset)
---------
2. Cases
---------
2.1. Compute for variations
```````````````````````````
::
CV = Variations.computeCV(I)
CV2 = Variations.computeCV2(I)
LV = Variations.computeLV(I)
This returns the respective values for
- :math:`\\overrightarrow{CV} = \\left[cv^{(i)}\\right]_{\\forall{i \\in [1, n_{nuc}]}}`
- :math:`\\overrightarrow{CV_2} = \\left[cv_2^{(i)}\\right]_{\\forall{i \\in [1, n_{nuc}]}}`
- :math:`\\overrightarrow{LV} = \\left[lv^{(i)}\\right]_{\\forall{i \\in [1, n_{nuc}]}}`
2.2. Compute Global Values
``````````````````````````
::
grand_CV = Variations.grandCV(I)
grand_CV2 = Variations.grandCV2(I)
grand_LV = Variations.grandLV(I)
This returns the respective values for
- :math:`\\overline{CV} = \\mu\\left(\\overrightarrow{CV}\\right)`
- :math:`\\overline{CV_2} = \\mu\\left(\\overrightarrow{CV_2}\\right)`
- :math:`\\overline{LV} = \\mu\\left(\\overrightarrow{LV}\\right)`
.. raw:: html
<hr style="border: 2px solid red; margin: 20px 0;">
"""
[docs]
@classmethod
def computeCV(cls, isi_set=None):
"""
.. math::
\\overrightarrow{cv}^{(i)} = \\begin{cases}
\\text{NaN} & \\text{if } n_{ISI}^{(i)} = 0 \n
\\frac{\\sqrt{\\frac{1}{n_{ISI}^{(i)}} \\sum_{k=1}^{n_{ISI}^{(i)}} \\left(isi_k^{(i)} - \\mu_i\\right)^2 }}{\\text{max}\\left(\\frac{1}{n_{ISI}^{(i)}} \\sum_{k=1}^{n_{ISI}^{(i)}} isi_k^{(i)}, 10^{-8} \\right)} & \\text{otherwise}
\\end{cases}
Returns the coefficient of variation for all individual neurons.
:param isi_set: Dictionary returned using :meth:`analyseur.cbgtc.stats.isi.InterSpikeInterval.compute`
:return: dictionary of individual neurons whose values are their respective coefficient of variation value
**Formula**
.. table:: Formula_computeCV_1.2
================================================================================================== ======================================================
Definitions Interpretation
================================================================================================== ======================================================
total neurons, :math:`n_{nuc}` total number of neurons in the Nucleus
neuron index, :math:`i` i-th neuron in the pool of :math:`n_{Nuc}` neurons
total spikes, :math:`n_{spk}^{(i)}` total number of spikes (spike times) by i-th neuron
interspike interval, :math:`isi_{k}^{(i)}` k-th absolute interval between successive spike times
:math:`\\overrightarrow{ISI}^{(i)} = \\left[isi_k^{(i)}\\right]_{\\forall{k \\in [1, n_{spk}^{(i)})}}` array of all interspike intervals of i-th neuron
:math:`I = \\left\\{\\overrightarrow{ISI}^{(i)} \\mid \\forall{i \\in [1, n_{nuc}]} \\right\\}` set of array interspike intervals of all neurons
================================================================================================== ======================================================
Then, the coefficient of variation of the i-th neuron is
.. math::
cv^{(i)} = \\frac{\\sigma\\left(\\overrightarrow{ISI}^{(i)}\\right)}{\\mu\\left(\\overrightarrow{ISI}^{(i)}\\right)}
where, :math:`\\sigma(\\cdot)` is the `standard deviation function <https://numpy.org/doc/stable/reference/generated/numpy.std.html>`_ over the given dimension and
:math:`\\mu(\\cdot)` is the `arithmetic mean function <https://numpy.org/doc/stable/reference/generated/numpy.mean.html>`_ over the given dimension.
We therefore get
.. table:: Formula_computeCV_1.2
================================================================================== ======================================================
Definitions Interpretation
================================================================================== ======================================================
:math:`cv^{(i)}` coefficient of variation of i-th neuron
:math:`\\overrightarrow{CV} = \\left[cv^{(i)}\\right]_{\\forall{i \\in [1, n_{nuc}]}}` array of coefficient of variation of all neurons
================================================================================== ======================================================
.. raw:: html
<hr style="border: 2px solid red; margin: 20px 0;">
"""
all_CV = {}
for n_id, isi in isi_set.items():
if len(isi) == 0:
all_CV[n_id] = np.nan # np.float(0.) to avoid error
else:
all_CV[n_id] = np.std(isi) / np.maximum(np.mean(isi), 1e-8)
return all_CV
[docs]
@classmethod
def computeCV2(cls, isi_set=None):
"""
.. math::
\\overrightarrow{cv}_2^{(i)} = \\begin{cases}
\\text{NaN} & \\text{if } n_{ISI}^{(i)} \\le 1 \n
\\frac{1}{\\left(n_{ISI}^{(i)} - 1\\right)} \\sum_{k=2}^{n_{ISI}^{(i)}} \\left[2 \\cdot \\frac{\\left| isi_k^{(i)} - isi_{k-1}^{(i)} \\right|}{\\text{max}\\left(isi_k^{(i)} - isi_{k-1}^{(i)}, 10^{-8} \\right)}\\right] & \\text{otherwise}
\\end{cases}
Returns the local coefficient of variation for all individual neurons.
:param isi_set: Dictionary returned using :meth:`analyseur.cbgtc.stats.isi.InterSpikeInterval.compute`
:return: dictionary of individual neurons whose values are their respective local coefficient of variation value
**Formula**
.. table:: Formula_computeCV2_1.2
================================================================================================== ======================================================
Definitions Interpretation
================================================================================================== ======================================================
total neurons, :math:`n_{nuc}` total number of neurons in the Nucleus
neuron index, :math:`i` i-th neuron in the pool of :math:`n_{Nuc}` neurons
total spikes, :math:`n_{spk}^{(i)}` total number of spikes (spike times) by i-th neuron
interspike interval, :math:`isi_{k}^{(i)}` k-th absolute interval between successive spike times
:math:`\\overrightarrow{ISI}^{(i)} = \\left[isi_k^{(i)}\\right]_{\\forall{k \\in [1, n_{spk}^{(i)})}}` array of all interspike intervals of i-th neuron
:math:`I = \\left\\{\\overrightarrow{ISI}^{(i)} \\mid \\forall{i \\in [1, n_{nuc}]} \\right\\}` set of array interspike intervals of all neurons
================================================================================================== ======================================================
Then, the coefficient of variation of the i-th neuron is
.. math::
cv_2^{(i)} = \\mu\\left(2\\frac{\\left[\\left|isi^{(i)}_k - isi^{(i)}_{k-1}\\right|\\right]_{\\forall{k \\in [1, n_{spk}^{(i)})}}}{\\left[isi^{(i)}_k + isi^{(i)}_{k-1}\\right]_{\\forall{k \\in [1, n_{spk}^{(i)})}}}\\right)
where, :math:`\\mu(\\cdot)` is the `arithmetic mean function <https://numpy.org/doc/stable/reference/generated/numpy.mean.html>`_ over the given dimension.
We therefore get
.. table:: Formula_computeCV2_1.2
======================================================================================= ======================================================
Definitions Interpretation
======================================================================================= ======================================================
:math:`cv_2^{(i)}` local coefficient of variation of the i-th neuron
:math:`\\overrightarrow{CV_2} = \\left[cv_2^{(i)}\\right]_{\\forall{i \\in [1, n_{nuc}]}}` array of local coefficient of variation of all neurons
======================================================================================= ======================================================
.. raw:: html
<hr style="border: 2px solid red; margin: 20px 0;">
"""
all_CV2 = {}
for n_id, isi in isi_set.items():
if len(isi) == 0:
all_CV2[n_id] = np.nan # np.float(0.) to avoid error
else:
abs_diff_over_sum = np.abs( np.diff(isi) ) / np.maximum((isi[1:] + isi[:-1]), 1e-8)
if len(abs_diff_over_sum) == 0:
all_CV2[n_id] = np.nan
else:
all_CV2[n_id] = np.mean(2 * abs_diff_over_sum)
return all_CV2
[docs]
@classmethod
def computeLV(cls, isi_set=None):
"""
.. math::
\\overrightarrow{lv}^{(i)} = \\begin{cases}
\\text{NaN} & \\text{if } n_{ISI}^{(i)} \\le 1 \n
\\frac{1}{\\left(n_{ISI}^{(i)} - 1\\right)} \\sum_{k=2}^{n_{ISI}^{(i)}} \\left[3 \\cdot \\frac{\\left(isi_k^{(i)} - isi_{k-1}^{(i)}\\right)^2}{\\text{max}\\left(\\left(isi_k^{(i)} - isi_{k-1}^{(i)}\\right)^2, 10^{-8} \\right)}\\right] & \\text{otherwise}
\\end{cases}
Returns the local variation for all individual neurons.
:param isi_set: Dictionary returned using :meth:`analyseur.cbgtc.stats.isi.InterSpikeInterval.compute`
:return: dictionary of individual neurons whose values are their respective local variation value
**Formula**
.. table:: Formula_computeLV_1.2
================================================================================================== ======================================================
Definitions Interpretation
================================================================================================== ======================================================
total neurons, :math:`n_{nuc}` total number of neurons in the Nucleus
neuron index, :math:`i` i-th neuron in the pool of :math:`n_{Nuc}` neurons
total spikes, :math:`n_{spk}^{(i)}` total number of spikes (spike times) by i-th neuron
interspike interval, :math:`isi_{k}^{(i)}` k-th absolute interval between successive spike times
:math:`\\overrightarrow{ISI}^{(i)} = \\left[isi_k^{(i)}\\right]_{\\forall{k \\in [1, n_{spk}^{(i)})}}` array of all interspike intervals of i-th neuron
:math:`I = \\left\\{\\overrightarrow{ISI}^{(i)} \\mid \\forall{i \\in [1, n_{nuc}]} \\right\\}` set of array interspike intervals of all neurons
================================================================================================== ======================================================
Then, the local variation of the i-th neuron is
.. math::
lv^{(i)} = \\mu\\left(3\\frac{\\left[\\left(isi^{(i)}_k - isi^{(i)}_{k-1}\\right)^2\\right]_{\\forall{k \\in [1, n_{spk}^{(i)})}}}{\\left[\\left(isi^{(i)}_k + isi^{(i)}_{k-1}\\right)^2\\right]_{\\forall{k \\in [1, n_{spk}^{(i)})}}}\\right)
where, :math:`\\mu(\\cdot)` is the `arithmetic mean function <https://numpy.org/doc/stable/reference/generated/numpy.mean.html>`_ over the given dimension.
We therefore get
.. table:: Formula_computeLV_1.2
======================================================================================= ======================================================
Definitions Interpretation
======================================================================================= ======================================================
:math:`lv^{(i)}` local variation of the i-th neuron
:math:`\\overrightarrow{LV} = \\left[lv^{(i)}\\right]_{\\forall{i \\in [1, n_{nuc}]}}` array of local coefficient of variation of all neurons
======================================================================================= ======================================================
.. raw:: html
<hr style="border: 2px solid red; margin: 20px 0;">
"""
all_LV = {}
for n_id, isi in isi_set.items():
if len(isi) == 0:
all_LV[n_id] = np.nan # np.float(0.) to avoid error
else:
sq_diff_over_sum = np.square(np.diff(isi)) / np.maximum(np.square((isi[1:] + isi[:-1])), 1e-8)
if len(sq_diff_over_sum) == 0:
all_LV[n_id] = np.nan
else:
all_LV[n_id] = np.mean(3 * sq_diff_over_sum)
return all_LV
[docs]
@classmethod
def grandCV(cls, isi_set=None):
"""
Returns the grand coefficient of variation which is the mean of coefficient of variation of all the neurons
:param isi_set: Dictionary returned using :meth:`analyseur.cbgtc.stats.isi.InterSpikeInterval.compute`
:return: a number
**Formula**
.. table:: Formula
=============================================================================================== ======================================================
Definitions Interpretation
=============================================================================================== ======================================================
total neurons, :math:`n_{Nuc}` total number of neurons in the Nucleus
neuron index, :math:`i` i-th neuron in the pool of :math:`n_{Nuc}` neurons
coefficient of variation, :math:`\\overline{cv^{(i)}}` coefficient of variation of i-th neuron
:math:`\\overrightarrow{CV} = \\left[cv^{(i)}\\right]_{\\forall{i \\in [1, n_{nuc}]}}` array of coefficient of variation of all neurons
grand coefficient of variation, :math:`\\overline{CV} = \\mu\\left(\\overrightarrow{CV}\\right)` grand or global coefficient of variation
=============================================================================================== ======================================================
where, :math:`\\mu(\\cdot)` is the `arithmetic mean function <https://numpy.org/doc/stable/reference/generated/numpy.mean.html>`_ over the given dimension.
NOTE: The array :math:`\\overrightarrow{CV}` is obtained by calling :py:meth:`.computeCV`
.. raw:: html
<hr style="border: 2px solid red; margin: 20px 0;">
"""
all_neurons_CV = cls.computeCV(isi_set)
return cgm(all_neurons_CV)
[docs]
@classmethod
def grandCV2(cls, isi_set=None):
"""
Returns the grand local coefficient of variation which is the mean of local coefficient of variation of all the neurons
:param isi_set: Dictionary returned using :meth:`analyseur.cbgtc.stats.isi.InterSpikeInterval.compute`
:return: a number
**Formula**
.. table:: Formula
====================================================================================================== ======================================================
Definitions Interpretation
====================================================================================================== ======================================================
total neurons, :math:`n_{Nuc}` total number of neurons in the Nucleus
neuron index, :math:`i` i-th neuron in the pool of :math:`n_{Nuc}` neurons
local coefficient of variation, :math:`\\overline{cv^{(i)}}` local coefficient of variation of i-th neuron
:math:`\\overrightarrow{CV_2} = \\left[cv_2^{(i)}\\right]_{\\forall{i \\in [1, n_{nuc}]}}` array of local coefficient of variation of all neurons
grand local coefficient of variation, :math:`\\overline{CV_2} = \\mu\\left(\\overrightarrow{CV_2}\\right)` grand or global local coefficient of variation
====================================================================================================== ======================================================
where, :math:`\\mu(\\cdot)` is the `arithmetic mean function <https://numpy.org/doc/stable/reference/generated/numpy.mean.html>`_ over the given dimension.
NOTE: The array :math:`\\overrightarrow{CV_2}` is obtained by calling :py:meth:`.computeCV2`
.. raw:: html
<hr style="border: 2px solid red; margin: 20px 0;">
"""
all_neurons_CV2 = cls.computeCV2(isi_set)
return cgm(all_neurons_CV2)
[docs]
@classmethod
def grandLV(cls, isi_set=None):
"""
Returns the grand local variation which is the mean of local variation of all the neurons
:param isi_set: Dictionary returned using :meth:`analyseur.cbgtc.stats.isi.InterSpikeInterval.compute`
:return: a number
**Formula**
.. table:: Formula
======================================================================================== ======================================================
Definitions Interpretation
======================================================================================== ======================================================
total neurons, :math:`n_{Nuc}` total number of neurons in the Nucleus
neuron index, :math:`i` i-th neuron in the pool of :math:`n_{Nuc}` neurons
local variation, :math:`\\overline{cv^{(i)}}` local variation of i-th neuron
:math:`\\overrightarrow{LV} = \\left[lv^{(i)}\\right]_{\\forall{i \\in [1, n_{nuc}]}}` array of local variation of all neurons
grand local variation, :math:`\\overline{LV} = \\mu\\left(\\overrightarrow{LV}\\right)` grand or global local variation
======================================================================================== ======================================================
where, :math:`\\mu(\\cdot)` is the `arithmetic mean function <https://numpy.org/doc/stable/reference/generated/numpy.mean.html>`_ over the given dimension.
NOTE: The array :math:`\\overrightarrow{LV}` is obtained by calling :py:meth:`.computeLV`
.. raw:: html
<hr style="border: 2px solid red; margin: 20px 0;">
"""
all_neurons_LV = cls.computeLV(isi_set)
return cgm(all_neurons_LV)