cubic.py 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. # -*- coding: utf-8 -*-
  2. '''
  3. CuBIC is a statistical method for the detection of higher order of
  4. correlations in parallel spike trains based on the analysis of the
  5. cumulants of the population count.
  6. Given a list sts of SpikeTrains, the analysis comprises the following
  7. steps:
  8. 1) compute the population histogram (PSTH) with the desired bin size
  9. >>> bin_size = 5 * pq.ms
  10. >>> pop_count = elephant.statistics.time_histogram(sts, bin_size)
  11. 2) apply CuBIC to the population count
  12. >>> alpha = 0.05 # significance level of the tests used
  13. >>> xi, p_val, k = cubic(data, max_iterations=100, alpha=0.05,
  14. ... errorval=4.):
  15. :copyright: Copyright 2016 by the Elephant team, see `doc/authors.rst`.
  16. :license: BSD, see LICENSE.txt for details.
  17. '''
  18. # -*- coding: utf-8 -*-
  19. from __future__ import division, print_function, unicode_literals
  20. import scipy.stats
  21. import scipy.special
  22. import math
  23. import warnings
  24. from elephant.utils import deprecated_alias
  25. __all__ = [
  26. "cubic"
  27. ]
  28. # Based on matlab code by Benjamin Staude
  29. # Adaptation to python by Pietro Quaglio and Emiliano Torre
  30. @deprecated_alias(data='histogram', ximax='max_iterations')
  31. def cubic(histogram, max_iterations=100, alpha=0.05):
  32. r"""
  33. Performs the CuBIC analysis [1]_ on a population histogram, calculated
  34. from a population of spiking neurons.
  35. The null hypothesis :math:`H_0: k_3(data)<=k^*_{3,\xi}` is iteratively
  36. tested with increasing correlation order :math:`\xi` until it is possible
  37. to accept, with a significance level `alpha`, that :math:`\hat{\xi}` is
  38. the minimum order of correlation necessary to explain the third cumulant
  39. :math:`k_3(data)`.
  40. :math:`k^*_{3,\xi}` is the maximized third cumulant, supposing a Compound
  41. Poisson Process (CPP) model for correlated spike trains (see [1]_)
  42. with maximum order of correlation equal to :math:`\xi`.
  43. Parameters
  44. ----------
  45. histogram : neo.AnalogSignal
  46. The population histogram (count of spikes per time bin) of the entire
  47. population of neurons.
  48. max_iterations : int, optional
  49. The maximum number of iterations of the hypothesis test. Corresponds
  50. to the :math:`\hat{\xi_{\text{max}}}` in [1]_. If it is not possible
  51. to compute the :math:`\hat{\xi}` before `max_iterations` iteration,
  52. the CuBIC procedure is aborted.
  53. Default: 100.
  54. alpha : float, optional
  55. The significance level of the hypothesis tests performed.
  56. Default: 0.05.
  57. Returns
  58. -------
  59. xi_hat : int
  60. The minimum correlation order estimated by CuBIC, necessary to
  61. explain the value of the third cumulant calculated from the population.
  62. p : list
  63. The ordered list of all the p-values of the hypothesis tests that have
  64. been performed. If the maximum number of iteration `max_iterations` is
  65. reached, the last p-value is set to -4.
  66. kappa : list
  67. The list of the first three cumulants of the data.
  68. test_aborted : bool
  69. Whether the test was aborted because reached the maximum number of
  70. iteration, `max_iterations`.
  71. References
  72. ----------
  73. .. [1] Staude, Rotter, Gruen, (2009) J. Comp. Neurosci
  74. """
  75. # alpha in in the interval [0,1]
  76. if alpha < 0 or alpha > 1:
  77. raise ValueError(
  78. 'the significance level alpha (= %s) has to be in [0,1]' % alpha)
  79. if not isinstance(max_iterations, int) or max_iterations < 0:
  80. raise ValueError("'max_iterations' ({}) has to be a positive integer"
  81. .format(max_iterations))
  82. # dict of all possible rate functions
  83. try:
  84. histogram = histogram.magnitude
  85. except AttributeError:
  86. pass
  87. L = len(histogram)
  88. # compute first three cumulants
  89. kappa = _kstat(histogram)
  90. xi_hat = 1
  91. xi = 1
  92. pval = 0.
  93. p = []
  94. test_aborted = False
  95. # compute xi_hat iteratively
  96. while pval < alpha:
  97. xi_hat = xi
  98. if xi > max_iterations:
  99. warnings.warn('Test aborted, xihat= %i > ximax= %i' % (
  100. xi, max_iterations))
  101. test_aborted = True
  102. break
  103. # compute p-value
  104. pval = _H03xi(kappa, xi, L)
  105. p.append(pval)
  106. xi = xi + 1
  107. return xi_hat, p, kappa, test_aborted
  108. def _H03xi(kappa, xi, L):
  109. '''
  110. Computes the p_value for testing the :math:`H_0: k_3(data)<=k^*_{3,\\xi}`
  111. hypothesis of CuBIC in the stationary rate version
  112. Parameters
  113. -----
  114. kappa : list
  115. The first three cumulants of the populaton of spike trains
  116. xi : int
  117. The the maximum order of correlation :math:`\\xi` supposed in the
  118. hypothesis for which is computed the p value of :math:`H_0`
  119. L : float
  120. The length of the orginal population histogram on which is performed
  121. the CuBIC analysis
  122. Returns
  123. -----
  124. p : float
  125. The p-value of the hypothesis tests
  126. '''
  127. # Check the order condition of the cumulants necessary to perform CuBIC
  128. if kappa[1] < kappa[0]:
  129. raise ValueError(
  130. 'H_0 can not be tested:'
  131. 'kappa(2) = %f < %f = kappa(1)!!!' % (kappa[1], kappa[0]))
  132. else:
  133. # computation of the maximized cumulants
  134. kstar = [_kappamstar(kappa[:2], i, xi) for i in range(2, 7)]
  135. k3star = kstar[1]
  136. # variance of third cumulant (from Stuart & Ord)
  137. sigmak3star = math.sqrt(
  138. kstar[4] / L + 9 * (kstar[2] * kstar[0] + kstar[1] ** 2) /
  139. (L - 1) + 6 * L * kstar[0] ** 3 / ((L - 1) * (L - 2)))
  140. # computation of the p-value (the third cumulant is supposed to
  141. # be gaussian distributed)
  142. p = 1 - scipy.stats.norm(k3star, sigmak3star).cdf(kappa[2])
  143. return p
  144. def _kappamstar(kappa, m, xi):
  145. '''
  146. Computes maximized cumulant of order m
  147. Parameters
  148. -----
  149. kappa : list
  150. The first two cumulants of the data
  151. xi : int
  152. The :math:`\\xi` for which is computed the p value of :math:`H_0`
  153. m : float
  154. The order of the cumulant
  155. Returns
  156. -----
  157. k_out : list
  158. The maximized cumulant of order m
  159. '''
  160. if xi == 1:
  161. kappa_out = kappa[1]
  162. else:
  163. kappa_out = \
  164. (kappa[1] * (xi ** (m - 1) - 1) -
  165. kappa[0] * (xi ** (m - 1) - xi)) / (xi - 1)
  166. return kappa_out
  167. def _kstat(data):
  168. '''
  169. Compute first three cumulants of a population count of a population of
  170. spiking
  171. See http://mathworld.wolfram.com/k-Statistic.html
  172. Parameters
  173. -----
  174. data : numpy.ndarray
  175. The population histogram of the population on which are computed
  176. the cumulants
  177. Returns
  178. -----
  179. moments : list
  180. The first three unbiased cumulants of the population count
  181. '''
  182. if len(data) == 0:
  183. raise ValueError('The input data must be a non-empty array')
  184. moments = [scipy.stats.kstat(data, n=n) for n in [1, 2, 3]]
  185. return moments