| | 94 | def make_kernel(form, sigma, time_stamp_resolution, direction=1, kernel=None, |
| | 95 | m_idx=None): |
| | 96 | """ |
| | 97 | Constructs a numeric linear convolution kernel of basic shape to be used |
| | 98 | for data smoothing (linear low pass filtering) and firing rate estimation |
| | 99 | from single trial or trial-averaged spike trains. |
| | 100 | |
| | 101 | Exponential and alpha kernels may also be used to represent postynaptic |
| | 102 | currents / potentials in a linear (current-based) model. |
| | 103 | |
| | 104 | Adapted from original script written by Martin P. Nawrot for the FIND MATLAB |
| | 105 | toolbox. |
| | 106 | See FIND - a unified framework for neural data analysis, |
| | 107 | Meier R, Egert U, Aertsen A, Nawrot MP; Neural Netw. 2008 Oct; |
| | 108 | 21(8):1085-93. |
| | 109 | |
| | 110 | Nawrot M, Aertsen A, Rotter S (1999) |
| | 111 | Single-trial estimation of neuronal firing rates - From single neuron |
| | 112 | spike trains to population activity. |
| | 113 | J Neurosci Meth 94: 81-92 |
| | 114 | |
| | 115 | Inputs: |
| | 116 | form - kernel form (string) Currently implemented forms |
| | 117 | are BOX - boxcar, TRI - triangle, GAU - gaussian |
| | 118 | , EPA - epanechnikov, EXP - exponential, ALP - |
| | 119 | alpha function. |
| | 120 | EXP and ALP are aymmetric kernel forms and |
| | 121 | assume optional parameter 'direction' |
| | 122 | sigma - standard deviation of the distribution |
| | 123 | associated with kernel shape. This parameter |
| | 124 | defines the time resolution of the kernel |
| | 125 | estimate and makes different kernels comparable |
| | 126 | (cf. [1] for symetric kernels). This is used |
| | 127 | here as an alternative definition to the cut-off |
| | 128 | frequency of the associated linear filter. |
| | 129 | time_stamp_resolution - temporal resolution of input and output in SI |
| | 130 | units. E.g. value 0.001 means 1ms time |
| | 131 | resolution |
| | 132 | direction - Asymmetric kernels have two possible directions. |
| | 133 | The values are -1 or 1, default is 1. The |
| | 134 | definition here is that for direction = 1 the |
| | 135 | kernel represents the impulse response function |
| | 136 | of the linear filter. Default value is 1. |
| | 137 | |
| | 138 | Outputs: |
| | 139 | kernel - array of kernel. The length of this array is always an odd |
| | 140 | number to represent symmetric kernels such that the center bin |
| | 141 | coincides with the median of the numeric array, i.e for a |
| | 142 | triangle, the maximum will be at the center bin with equal |
| | 143 | number of bins to the right and to the left. |
| | 144 | norm - for rate estimates. The kernel vector is normalized such that |
| | 145 | the sum of all entries equals unity sum(kernel)=1. When |
| | 146 | estimating rate functions from discrete spike data (0/1) the |
| | 147 | additional parameter 'norm' allows for the normalization to |
| | 148 | rate in spikes per second. |
| | 149 | Use: rate = norm * scipy.signal.lfilter(kernel, 1, spike_data) |
| | 150 | m_idx - index of the numerically determined median (center of gravity) |
| | 151 | of the kernel function |
| | 152 | """ |
| | 153 | assert form.upper() in ('BOX','TRI','GAU','EPA','EXP','ALP'), "form must \ |
| | 154 | be one either 'BOX','TRI','GAU','EPA','EXP' or 'ALP'!" |
| | 155 | |
| | 156 | assert direction in (1,-1), "direction must be either 1 or -1" |
| | 157 | |
| | 158 | norm = 1./time_stamp_resolution |
| | 159 | |
| | 160 | if form.upper() == 'BOX': |
| | 161 | w = 2.0 * sigma * numpy.sqrt(3) |
| | 162 | width = 2 * numpy.floor(w / 2.0 / time_stamp_resolution) + 1 # always odd number of bins |
| | 163 | height = 1. / width |
| | 164 | kernel = numpy.ones((1, width)) * height # area = 1 |
| | 165 | |
| | 166 | elif form.upper() == 'TRI': |
| | 167 | w = 2 * sigma * numpy.sqrt(6) |
| | 168 | halfwidth = numpy.floor(w / 2.0 / time_stamp_resolution) |
| | 169 | trileft = numpy.arange(1, halfwidth + 2) |
| | 170 | triright = numpy.arange(halfwidth, 0, -1) # odd number of bins |
| | 171 | triangle = numpy.append(trileft, triright) |
| | 172 | kernel = triangle / triangle.sum() # area = 1 |
| | 173 | |
| | 174 | elif form.upper() == 'EPA': |
| | 175 | w = 2.0 * sigma * numpy.sqrt(5) |
| | 176 | halfwidth = numpy.floor(w / 2.0 / time_stamp_resolution) |
| | 177 | base = numpy.arange(-halfwidth, halfwidth + 1) |
| | 178 | parabula = base**2 |
| | 179 | epanech = parabula.max() - parabula # inverse parabula |
| | 180 | kernel = epanech / epanech.sum() # area = 1 |
| | 181 | |
| | 182 | elif form.upper() == 'GAU': |
| | 183 | SI_sigma = sigma / 1000.0 |
| | 184 | w = 2.0 * sigma * 2.7 # > 99% of distribution weight |
| | 185 | halfwidth = numpy.floor(w / 2.0 / time_stamp_resolution) # always odd |
| | 186 | base = numpy.arange(-halfwidth, halfwidth + 1) / 1000.0 * ( |
| | 187 | time_stamp_resolution) |
| | 188 | g = numpy.exp(-(base**2) / 2.0 / SI_sigma**2) / SI_sigma / numpy.sqrt( |
| | 189 | 2.0 * numpy.pi) |
| | 190 | kernel = g / g.sum() |
| | 191 | |
| | 192 | elif form.upper() == 'ALP': |
| | 193 | SI_sigma = sigma / 1000.0 |
| | 194 | w = 5.0 * sigma |
| | 195 | alpha = numpy.arange(1, (2.0 * numpy.floor( |
| | 196 | (w / time_stamp_resolution / 2.0)) + 1) + 1) / 1000.0 * \ |
| | 197 | time_stamp_resolution |
| | 198 | alpha = (2.0 / SI_sigma**2) * alpha * numpy.exp(-alpha * numpy.sqrt(2) \ |
| | 199 | / SI_sigma) |
| | 200 | kernel = alpha / alpha.sum() # normalization |
| | 201 | if direction == -1: |
| | 202 | kernel = numpy.flipud(kernel) |
| | 203 | |
| | 204 | elif form.upper() == 'EXP': |
| | 205 | SI_sigma = sigma / 1000.0 |
| | 206 | w = 5.0 * sigma |
| | 207 | expo = numpy.arange(1, (2.0 * numpy.floor(w / time_stamp_resolution / ( |
| | 208 | 2.0)) + 1) + 1) / 1000.0 * time_stamp_resolution |
| | 209 | expo = numpy.exp(-expo / SI_sigma) |
| | 210 | kernel = expo / expo.sum() |
| | 211 | if direction == -1: |
| | 212 | kernel = numpy.flipud(kernel) |
| | 213 | |
| | 214 | kernel = kernel.ravel() |
| | 215 | m_idx = numpy.nonzero(kernel.cumsum() >= 0.5)[0].min() |
| | 216 | |
| | 217 | return kernel, norm, m_idx |
| | 218 | |