cubic.py 6.7 KB

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