def firing_rates_integration(self): '''Returns vector of population firing rates in Hz.''' print 'Calculate firing rates.' # conversion factor for currents to voltages # JS: In the conversion factor tau_s should also appear, but I think it is absorbed in the weights, right? Should we just take out the comment here? fac = 1 / (self.params['C']) # conversion from ms to s taum = self.params['taum'] * 1e-3 tauf = self.params['tauf'] * 1e-3 taur = self.params['taur'] * 1e-3 dV = self.params['Vth'] - self.params['V0'] rate_function = lambda mu, sigma: siegert.nu0_fb433( taum, tauf, taur, dV, 0., mu, sigma) def get_rate_difference(rates): mu = self.get_mean(rates) sigma = np.sqrt(self.get_variance(rates)) new_rates = np.array( map(rate_function, taum * fac * mu, np.sqrt(taum) * fac * sigma)) return -rates + new_rates dt = 0.05 y = np.zeros((2, self.dimension)) eps = 1.0 while eps >= 1e-5: delta_y = get_rate_difference(y[0]) y[1] = y[0] + delta_y * dt epsilon = (y[1] - y[0]) eps = max(np.abs(epsilon)) y[0] = y[1] return y[1]
def firing_rates_integration(self): '''Returns vector of population firing rates in Hz.''' print 'Calculate firing rates.' fac = 1 / (self.params['C']) # conversion from ms to s taum = self.params['taum'] * 1e-3 tauf = self.params['tauf'] * 1e-3 taur = self.params['taur'] * 1e-3 dV = self.params['Vth'] - self.params['V0'] rate_function = lambda mu, sigma: siegert.nu0_fb433( taum, tauf, taur, dV, 0., mu, sigma) def get_rate_difference(rates): mu = self.get_mean(rates) sigma = np.sqrt(self.get_variance(rates)) new_rates = np.array(map(rate_function, taum*fac*mu, np.sqrt(taum)*fac*sigma)) return -rates + new_rates dt = 0.05 y = np.zeros((2, self.dimension)) eps = 1.0 while eps >= 1e-5: delta_y = get_rate_difference(y[0]) y[1] = y[0] + delta_y*dt epsilon = (y[1] - y[0]) eps = max(np.abs(epsilon)) y[0] = y[1] return y[1]
def transfer_function(omega, params, mu, sigma): """Calculates transfer function of leaky-integrate and fire neuron model subjected to colored noise according to Eq. 93 in Schuecker et al. (2014) "Reduction of colored noise in excitable systems to white noise and dynamic boundary conditions" arXiv:1410.8799v3 """ taum = params['taum'] * 1e-3 taus = params['tauf'] * 1e-3 taur = params['taur'] * 1e-3 V0 = 0.0 dV = params['Vth'] - params['V0'] if omega == 0.: # print siegert.d_nu_d_mu_fb433(taum, taus, taur, dV, V0, mu, sigma) # print siegert.d_nu_d_mu_numerical(taum, taus, taur, dV, V0, mu, sigma) # return siegert.d_nu_d_mu_fb433(taum, taus, taur, dV, V0, mu, sigma) return siegert.d_nu_d_mu_numerical(taum, taus, taur, dV, V0, mu, sigma) else: nu0 = siegert.nu_0(taum, taur, dV, V0, mu, sigma) nu0_fb = siegert.nu0_fb433(taum, taus, taur, dV, V0, mu, sigma) x_t = np.sqrt(2.) * (dV - mu) / sigma x_r = np.sqrt(2.) * (V0 - mu) / sigma z = complex(-0.5, complex(omega * taum)) alpha = np.sqrt(2) * abs(zetac(0.5) + 1) k = np.sqrt(taus / taum) A = alpha * taum * nu0 * k / np.sqrt(2) def Phi_x_r(x, y): return Phi(z, x) - Phi(z, y) def dPhi_x_r(x, y): return d_Phi(z, x) - d_Phi(z, y) def d2Phi_x_r(x, y): return d_2_Phi(z, x) - d_2_Phi(z, y) a0 = Phi_x_r(x_t, x_r) a1 = dPhi_x_r(x_t, x_r) / a0 a3 = A / taum / nu0_fb * (-a1**2 + d2Phi_x_r(x_t, x_r) / a0) result = np.sqrt(2.) / sigma * nu0_fb / \ complex(1., omega * taum) * (a1 + a3) return result
def Next_integration(self, rates): '''Returns vector of population firing rates in Hz.''' print 'Calculate external input.' # conversion factor for currents to voltages fac = 1 / (self.params['C']) # conversion from ms to s taum = self.params['taum'] * 1e-3 tauf = self.params['tauf'] * 1e-3 taur = self.params['taur'] * 1e-3 facb = 2 * self.tauf / self.C * taum dV = self.params['Vth'] - self.params['V0'] if self.params['Wilson-Cowan']: rate_function = lambda mu, sigma: siegert.WC( taum, tauf, taur, dV, 0., mu, sigma) transfer_function = lambda mu, sigma: siegert.d_nu_WC_d_mu_numerical( taum, tauf, taur, dV, 0, mu, sigma) else: rate_function = lambda mu, sigma: siegert.nu0_fb433( taum, tauf, taur, dV, 0., mu, sigma) transfer_function = lambda mu, sigma: siegert.d_nu_d_mu_numerical( taum, tauf, taur, dV, 0, mu, sigma) def get_rate_difference(Next): mu = self.get_mean_Next(rates, Next) sigma = np.sqrt(self.get_variance_Next(rates, Next)) new_rates = np.array( map(rate_function, taum * fac * mu, np.sqrt(taum) * fac * sigma)) return -rates + new_rates z = fsolve(get_rate_difference, self.Next, full_output=True) # set external input to zero if fsolve did not converge if z[2] == 1: Next = z[0] mu = self.get_mean_Next(rates, Next) sigma = np.sqrt(self.get_variance(rates)) betas = 2 * self.tauf / self.C * taum * np.array( map(transfer_function, taum * fac * mu, np.sqrt(taum) * fac * sigma)) else: Next = np.zeros(self.dimension) betas = np.zeros(self.dimension) return Next, betas
def firing_rates_integration(self): '''Returns vector of population firing rates in Hz.''' print 'Calculate firing rates.' # conversion factor for currents to voltages fac = 1 / (self.params['C']) # conversion from ms to s taum = self.params['taum'] * 1e-3 tauf = self.params['tauf'] * 1e-3 taur = self.params['taur'] * 1e-3 dV = self.params['Vth'] - self.params['V0'] if self.params['Wilson-Cowan']: rate_function = lambda mu, sigma: siegert.WC( taum, tauf, taur, dV, 0., mu, sigma) else: rate_function = lambda mu, sigma: siegert.nu0_fb433( taum, tauf, taur, dV, 0., mu, sigma) def get_rate_difference(rates): mu = self.get_mean(rates) sigma = np.sqrt(self.get_variance(rates)) new_rates = np.array( map(rate_function, taum * fac * mu, np.sqrt(taum) * fac * sigma)) return -rates + new_rates dt = 0.01 y = np.zeros((2, self.dimension)) y[0] = np.array([2, 3, 0]) eps = 1.0 n = 0 while eps >= 1e-5: n += 1 delta_y = get_rate_difference(y[0]) y[1] = y[0] + delta_y * dt epsilon = (y[1] - y[0]) eps = max(np.abs(epsilon)) y[0] = y[1] if n > 50000: print 'stopped' return np.zeros(self.dimension) return y[1]
def rate_function(mu, sigmas, sigmaf): sigma_I = sigmas / np.sqrt(2.0 * taus) def F(z): return siegert.nu0_fb433(taum, tauf, taur, dV, 0.0, taum / C * (sigma_I * z + mu), np.sqrt(taum) / C * sigmaf) def integrand(z): return np.exp(-z * z / 2.0) * F(z) * 1.0 / np.sqrt(2 * np.pi) if sigma_I == 0.0: result = siegert.nu0_fb433(taum, tauf, taur, dV, 0.0, taum / C * mu, np.sqrt(taum) / C * sigmaf) else: # result = integrate.quad(integrand, -40.0, 40.0)[0] result = integrate.quad(integrand, -5.0, 5.0)[0] # convert firing rate to Hz return result * 1000.0
def transfer_function_taylor(omega, params, mu, sigma): """ Calculates transfer function according to Eq. 93 in [2]. The results in [3] were obtained with this expression and it is used throughout this package """ # convert from ms to s taum = params['taum'] * 1e-3 tauf = params['tauf'] * 1e-3 taur = params['taur'] * 1e-3 Vth = params['Vth'] V0 = params['V0'] # convert mu to absolute values (not relative to reset) mu += V0 # for frequency zero the exact expression is given by the derivative of # f-I-curve if np.abs(omega - 0.) < 1e-15: return siegert.d_nu_d_mu_fb433(taum, tauf, taur, Vth, V0, mu, sigma) else: nu0 = siegert.nu_0(taum, taur, Vth, V0, mu, sigma) nu0_fb = siegert.nu0_fb433(taum, tauf, taur, Vth, V0, mu, sigma) x_t = np.sqrt(2.) * (Vth - mu) / sigma x_r = np.sqrt(2.) * (V0 - mu) / sigma z = complex(-0.5, complex(omega * taum)) alpha = np.sqrt(2) * abs(zetac(0.5) + 1) k = np.sqrt(tauf / taum) A = alpha * taum * nu0 * k / np.sqrt(2) a0 = Phi_x_r(z, x_t, x_r) a1 = dPhi_x_r(z, x_t, x_r) / a0 a3 = A / taum / nu0_fb * (-a1**2 + d2Phi_x_r(z, x_t, x_r) / a0) result = np.sqrt(2.) / sigma * nu0_fb / \ complex(1., omega * taum) * (a1 + a3) return result
def plot_PRE_Schuecker_Fig4(frequencies, sigma_1, mean_input_1, sigma_2, mean_input_2): results_dict = defaultdict(str) results_dict['sigma'] = defaultdict(dict) for index in [1, 2]: sigma = eval('sigma_' + str(index)) results_dict['sigma'][sigma]['mu'] = defaultdict(dict) for idx, mu in enumerate(eval('mean_input_' + str(index))): # Stationary firing rates for delta shaped PSCs. nu_0 = siegert.nu_0(tau_m, tau_r, theta, V_reset, mu, sigma) # Stationary firing rates for filtered synapses (via Taylor) nu0_fb = siegert.nu0_fb(tau_m, tau_s, tau_r, theta, V_reset, mu, sigma) # Stationary firing rates for exp PSCs. (via shift) nu0_fb433 = siegert.nu0_fb433(tau_m, tau_s, tau_r, theta, V_reset, mu, sigma) # colored noise zero-frequency limit of transfer function # colored noise transfer_function_zero_freq = siegert.d_nu_d_mu_fb433( tau_m, tau_s, tau_r, theta, V_reset, mu, sigma) transfer_function = [ transfer_FP_algebra_j1_shift((2. * np.pi) * f, tau_m, tau_s, tau_r, nu0_fb, theta, V_reset, mu, sigma) for f in frequencies ] results_dict['sigma'][sigma]['mu'][mu] = { 'frequencies': frequencies, 'absolute_value': np.abs(transfer_function), 'phase': np.angle(transfer_function) / 2 / np.pi * 360, 'zero_freq': transfer_function_zero_freq, 'nu_0': nu_0, 'nu0_fb': nu0_fb, 'nu0_fb433': nu0_fb433 } colors = ['black', 'grey'] lw = 4 markersize_cross = 4 if sigma == 4.0: ls = '-' else: ls = '--' axA.semilogx(frequencies, np.abs(transfer_function), color=colors[idx], linestyle=ls, linewidth=lw, label=r'$\nu=$ {} Hz'.format(nu0_fb)) axB.semilogx(frequencies, np.angle(transfer_function) / 2 / np.pi * 360, color=colors[idx], linestyle=ls, linewidth=lw, label=r'$\mu=$ ' + str(mu)) axA.semilogx(zero_freq, transfer_function_zero_freq, '+', color=colors[idx], markersize=markersize_cross) axA.set_xlabel(r'frequency $\omega/2\pi\quad(1/\mathrm{s})$') axA.set_ylabel( r'$|\frac{n(\omega)\nu}{\epsilon\mu}|\quad(\mathrm{s}\,' '\mathrm{mV})^{-1}$', labelpad=0) axB.set_xlabel(r'frequency $\omega/2\pi\quad(1/\mathrm{s})$') axB.set_ylabel(r'$-\angle n(\omega)\quad(^{\circ})$', labelpad=2) axA.legend() axB.legend() return results_dict
def F(z): return siegert.nu0_fb433(taum, tauf, 0.1, dV, 0.0, taum / C * (sigma_I * z + mu), np.sqrt(taum) / C * sigmaf)