Source code for navis.connectivity.cnmetrics
# This script is part of navis (http://www.github.com/navis-org/navis).
# Copyright (C) 2018 Philipp Schlegel
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
""" This module contains functions to analyse connectivity.
"""
import numpy as np
import pandas as pd
from typing import Union
from typing_extensions import Literal
[docs]
def connectivity_sparseness(x: Union[pd.DataFrame, np.ndarray],
which: Union[Literal['LTS'],
Literal['LTK'],
Literal['activity_ratio']] = 'LTS') -> Union[pd.Series, np.ndarray]:
r"""Calculate sparseness.
Sparseness comes in three flavors:
**Lifetime kurtosis (LTK)** quantifies the widths of tuning curves
(according to Muench & Galizia, 2016):
.. math::
S = \Bigg\{ \frac{1}{N} \sum^N_{i=1} \Big[ \frac{r_i - \overline{r}}{\sigma_r} \Big] ^4 \Bigg\} - 3
where :math:`N` is the number of observations, :math:`r_i` the value of
observation :math:`i`, and :math:`\overline{r}` and
:math:`\sigma_r` the mean and the standard deviation of the observations'
values, respectively. LTK is assuming a normal, or at least symmetric
distribution.
**Lifetime sparseness (LTS)** quantifies selectivity
(Bhandawat et al., 2007):
.. math::
S = \frac{1}{1-1/N} \Bigg[1- \frac{\big(\sum^N_{j=1} r_j / N\big)^2}{\sum^N_{j=1} r_j^2 / N} \Bigg]
where :math:`N` is the number of observations, and :math:`r_j` is the
value of an observation.
**Activity ratio** describes distributions with heavy tails (Rolls and
Tovee, 1995).
Notes
-----
``NaN`` values will be ignored. You can use that to e.g. ignore zero
values in a large connectivity matrix by changing these values to ``NaN``
before passing it to ``navis.sparseness``.
Parameters
----------
x : DataFrame | array-like
(N, M) dataset with N (rows) observations for M (columns)
neurons. One-dimensional data will be converted to two
dimensions (N rows, 1 column).
which : "LTS" | "LTK" | "activity_ratio"
Determines whether lifetime sparseness (LTS) or lifetime
kurtosis (LTK) is returned.
Returns
-------
sparseness
``pandas.Series`` if input was pandas DataFrame, else
``numpy.array``.
Examples
--------
Calculate sparseness of olfactory inputs to group of neurons:
>>> import navis
>>> import numpy as np
>>> import matplotlib.pyplot as plt
>>> # Get ORN response matrix from DoOR database
>>> url = 'https://raw.githubusercontent.com/ropensci/DoOR.data/master/data/door_response_matrix.csv'
>>> adj = pd.read_csv(url, delimiter=';')
>>> # Calculate lifetime sparseness
>>> S = navis.connectivity_sparseness(adj, which='LTS')
>>> # Plot distribution
>>> ax = S.plot.hist(bins=np.arange(0, 1, .1))
>>> _ = ax.set_xlabel('LTS')
>>> plt.show() # doctest: +SKIP
"""
if not isinstance(x, (pd.DataFrame, np.ndarray)):
x = np.array(x)
# Make sure we are working with 2 dimensional data
if isinstance(x, np.ndarray) and x.ndim == 1:
x = x.reshape(x.shape[0], 1)
N = np.sum(~np.isnan(x), axis=0)
if which == 'LTK':
return np.nansum(((x - np.nanmean(x, axis=0)) / np.nanstd(x, axis=0)) ** 4, axis=0) / N - 3
elif which == 'LTS':
return 1 / (1 - (1 / N)) * (1 - np.nansum(x / N, axis=0) ** 2 / np.nansum(x**2 / N, axis=0))
elif which == 'activity_ratio':
a = (np.nansum(x, axis=0) / N) ** 2 / (np.nansum(x, axis=0) ** 2 / N)
return 1 - a
else:
raise ValueError('Parameter "which" must be either "LTS", "LTK" or '
'"activity_ratio"')