def set_conductance_monitor(self):
     """yep"""
     self.mon_econd_e = bb.StateMonitor(self.Pe,
                                        'ge',
                                        record=self.nrn_meas_e)
     self.mon_icond_e = bb.StateMonitor(self.Pe,
                                        'gi',
                                        record=self.nrn_meas_e)
     self.mon_econd_i = bb.StateMonitor(self.Pi,
                                        'ge',
                                        record=self.nrn_meas_i)
     self.mon_icond_i = bb.StateMonitor(self.Pi,
                                        'gi',
                                        record=self.nrn_meas_i)
     self.network.add(self.mon_econd_e, self.mon_icond_e, self.mon_econd_i,
                      self.mon_icond_i)
Пример #2
0
def simulate_WORM_neuron(input_current,
                         simulation_time=5 * b2.ms,
                         v_leak=V_LEAK,
                         g_leak=G_LEAK,
                         c_m=C_M,
                         rest_pot=R_POT,
                         tau=MEMBRANE_TIME_SCALE,
                         f_t=FIRING_THRESHOLD):

    # differential equation of neuron model
    eqs = """
    dv/dt =
    ( g_leak * (v_leak - v) + input_current(t,i)  ) / c_m : volt 
    """

    # LIF neuron using Brian2 library
    neuron = b2.NeuronGroup(2, model=eqs, threshold='v>f_t', method="linear")
    neuron.v = rest_pot  # set initial value

    # monitoring membrane potential of neuron and injecting current
    state_monitor = b2.StateMonitor(neuron, ["v"], record=True)
    S = b2.Synapses(neuron, neuron, model='w : volt', on_pre='v += w')
    S.connect(i=0, j=1)
    S.w = 0.01 * b2.mV
    # run the simulation
    b2.run(simulation_time)
    return state_monitor
Пример #3
0
def main3():
    # Adding Spikes
    bs.start_scope()

    tau = 10 * bs.ms
    eqs = '''
    dv/dt = (1-v)/tau : 1
    '''

    # conditions for spiking models
    threshold = 'v>0.8'
    reset = 'v = -0.8'
    G = bs.NeuronGroup(1, eqs, threshold=threshold, reset=reset, method='exact')

    M = bs.StateMonitor(G, 'v', record=0)
    bs.run(50 * bs.ms)
    plt.plot(M.t / bs.ms, M.v[0])
    plt.xlabel('Time (ms)')
    plt.ylabel('v')
    plt.show()

    # you can also add spike monitor
    spike_monitor = bs.SpikeMonitor(G)

    bs.run(50 * bs.ms)

    print(f"Spike Times: {spike_monitor.t[:]}")
Пример #4
0
def main1():
    bs.start_scope()
    tau = 10 * bs.ms
    # equations must end with : unit
    # unit is the SI unit of that variable
    # the unit is 1 since the number "1" is unitless
    # v represents voltage, but we just keep it unitless for simplicity
    # 1/s not part of the unit since the unit represents the unit of the variable itself
    # rather than the unit of the equation
    eqs = '''
    dv/dt = (1-v)/tau: 1
    '''

    G = bs.NeuronGroup(1, model=eqs, method='exact')
    # record : bool, sequence of ints
    #     Which indices to record, nothing is recorded for ``False``,
    #     everything is recorded for ``True`` (warning: may use a great deal of
    #     memory), or a specified subset of indices.
    M = bs.StateMonitor(G, 'v', record=0)
    print('Before v = %s' % G.v[0])
    bs.run(100 * bs.ms)  # runs the simulation for 100ms
    print('After v = %s' % G.v[0])

    plt.plot(M.t / bs.ms, M.v[0])
    plt.xlabel('Time (ms)')
    plt.ylabel('v')
    plt.show()
Пример #5
0
def main4():
    # Incorporation of refractory period
    bs.start_scope()

    tau = 10 * bs.ms
    # the (unless refractory) is necessary
    # refer to the documentation for more detail
    eqs = '''
    dv/dt = (1-v)/tau : 1 (unless refractory)
    '''
    equation = bs.Equations(eqs)
    # conditions for spiking models
    threshold = 'v>0.8'
    reset = 'v = -0.8'
    refractory = 5 * bs.ms
    G = bs.NeuronGroup(1, eqs, threshold=threshold, reset=reset, method='exact', refractory=refractory)

    state_monitor = bs.StateMonitor(G, 'v', record=0)
    spike_monitor = bs.SpikeMonitor(G)

    bs.run(50 * bs.ms)
    plt.plot(state_monitor.t / bs.ms, state_monitor.v[0])
    plt.xlabel('Time (ms)')
    plt.ylabel('v')
    plt.show()
Пример #6
0
    def make_classification_network(self, number_of_stimuli, network_name):
        if network_name not in self.networks:
            network_size = number_of_stimuli * self.number_of_neurons
            count_mat = np.zeros((int(self.stimulus_duration / ms * 10), network_size), int)
            target = b2.NeuronGroup(N=number_of_stimuli, model=self.eqs, threshold='v>threshold', reset='v=0',
                                    namespace={'tau': self.tau, 'threshold': self.threshold})
            driving = b2.SpikeGeneratorGroup(N=network_size,
                                             indices=[0], times=[0 * ms])
            # counts = b2.TimedArray(values=_count_mat, dt=b2.defaultclock.dt)
            synapses = b2.Synapses(source=driving, target=target,
                                   model='w: 1', on_pre='v+=w*counts(t, i)')
            i = np.arange(network_size)
            j = np.repeat(range(number_of_stimuli), self.number_of_neurons)
            synapses.connect(j=j, i=i)
            synapses.w = np.tile(self.weights, reps=number_of_stimuli)

            spikes = b2.SpikeMonitor(target, record=True)
            voltage = b2.StateMonitor(target, 'v', record=True)

            net = b2.Network([target, driving, synapses, spikes, voltage])
            net.store()
            self.networks[network_name] = dict(net=net,
                                               count_mat=count_mat,
                                               synapses=synapses,
                                               v_mon=voltage,
                                               spike_mon=spikes,
                                               number_of_stimuli=number_of_stimuli,
                                               driving=driving)
        else:
            self.networks[network_name]['synapses'].w = np.tile(self.weights, reps=number_of_stimuli)
Пример #7
0
def run_brian_sim(stim, dt, init_values, param_dict, method = 'exact'):
    # Model specification
    eqs = brian2.Equations("")
    eqs += brian2.Equations("dV/dt = 1 / C * (Ie(t) + I_0 + I_1 - G * (V - El)) : volt (unless refractory)")
    eqs += brian2.Equations("dTh_s/dt = -b_s * Th_s : volt (unless refractory)")
    eqs += brian2.Equations("dTh_v/dt = a_v * (V - El) - b_v * (Th_v - Th_inf) : volt (unless refractory)")
    eqs += brian2.Equations("dI_0/dt = -k_0 * I_0 : amp (unless refractory)")
    eqs += brian2.Equations("dI_1/dt = -k_1 * I_1 : amp (unless refractory)")
    reset = ""
    reset = "\n".join([reset, "V = a_r * V + b_r"])
    reset = "\n".join([reset, "Th_s = Th_s + a_s"])
    reset = "\n".join([reset, "Th_v = Th_v"])
    reset = "\n".join([reset, "I_0 = R_0 * I_0 * exp(-k_0 * (t_ref - dt)) + A_0"])
    reset = "\n".join([reset, "I_1 = R_1 * I_1 * exp(-k_1 * (t_ref - dt)) + A_1"])
    threshold = "V > Th_v + Th_s"
    refractory = param_dict['t_ref']

    Ie = brian2.TimedArray(stim, dt=dt)
    nrn = brian2.NeuronGroup(1, eqs, method=method, reset=reset, threshold=threshold, refractory=refractory, namespace=param_dict)
    nrn.V = init_values['V'] * brian2.units.volt
    nrn.Th_s = init_values['Th_s'] * brian2.units.volt
    nrn.Th_v = init_values['Th_v'] * brian2.units.volt
    nrn.I_0 = init_values['I_0'] * brian2.units.amp
    nrn.I_1 = init_values['I_1'] * brian2.units.amp

    monvars = ['V','Th_s','Th_v','I_0','I_1',]
    mon = brian2.StateMonitor(nrn, monvars, record=True)

    num_step = len(stim)
    brian2.defaultclock.dt = dt
    brian2.run(num_step * dt)

    return (mon.t / brian2.units.second, mon.V[0] / brian2.units.volt, mon.Th_s[0] / brian2.units.volt, mon.Th_v[0] / brian2.units.volt, mon.I_0[0] / brian2.units.amp, mon.I_1[0] / brian2.units.amp, )
 def set_current_monitor(self):
     """yep"""
     self.mon_ecurr_e = bb.StateMonitor(self.Pe,
                                        'Ie',
                                        record=self.nrn_meas_e)
     self.mon_icurr_e = bb.StateMonitor(self.Pe,
                                        'Ii',
                                        record=self.nrn_meas_e)
     self.mon_ecurr_i = bb.StateMonitor(self.Pi,
                                        'Ie',
                                        record=self.nrn_meas_i)
     self.mon_icurr_i = bb.StateMonitor(self.Pi,
                                        'Ii',
                                        record=self.nrn_meas_i)
     self.network.add(self.mon_ecurr_e, self.mon_icurr_e, self.mon_ecurr_i,
                      self.mon_icurr_i)
Пример #9
0
def neuron_sim(stim_V=0.8):
    """simulating the neuron using brian2 library"""
    # initiate stimuli timing
    stimulus = br2.TimedArray(
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, stim_V, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        dt=100 * br2.ms)
    # initiating neurons
    eqs = '''
    dv/dt =  (-v + stimulus(t)-0.1*rand()) / tau  : 1
    tau : second
    '''
    # creating neuron group
    G = br2.NeuronGroup(10, eqs, dt=0.2 * br2.ms)
    # creating different tau's for the neuron model
    G.tau = np.linspace(10, 100, 10) * br2.ms
    # defining state monitor to record voltage
    M = br2.StateMonitor(G, 'v', record=True)
    # creating network
    net = br2.Network(G, M)
    # storing initial state
    net.store()
    # np array to contain data
    data = np.zeros(shape=(10, 10000, 4))
    # producing four repetitions
    for trial in range(4):
        net.restore()  # Restore the initial state
        net.run(2 * br2.second)
        # store the results
        data[:, :, trial] = M.v

    return data
Пример #10
0
def simulate_GPe_cell(par_g, par_sim):

    num = par_g['num']
    input_current = par_g['i_ext']
    b2.defaultclock.dt = par_sim['dt']

    eqs = '''
    i_extg = input_current(t, i): amp

    ainfg = 1 / (1 + exp(-(vg - thetaag*mV) / (sigag*mV))) : 1
    sinfg = 1 / (1 + exp(-(vg - thetasg*mV) / (sigsg*mV))) : 1
    rinfg = 1 / (1 + exp(-(vg - thetarg*mV) / (sigrg*mV))) : 1
    minfg = 1 / (1 + exp(-(vg - thetamg*mV) / (sigmg*mV))) : 1
    ninfg = 1 / (1 + exp(-(vg - thetang*mV) / (signg*mV))) : 1
    hinfg = 1 / (1 + exp(-(vg - thetahg*mV) / (sighg*mV))) : 1
    taung = taun0g + taun1g / (1 + exp(-(vg - thngt*mV) / (sng*mV))) : second
    tauhg = tauh0g + tauh1g / (1 + exp(-(vg - thhgt*mV) / (shg*mV))) : second

    itg = gtg * (ainfg ** 3) * rg * (vg - vcag) : amp
    inag = gnag * (minfg ** 3) * hg * (vg - vnag) : amp
    ikg = gkg * (ng ** 4) * (vg - vkg) : amp
    iahpg = gahpg * (vg - vkg) * cag / (cag + k1g) : amp
    icag = gcag * (sinfg ** 2) * (vg - vcag) : amp
    ilg = glg * (vg - vlg) : amp

    membrane_Im =  -(itg + inag + ikg + iahpg + icag + ilg) + i_extg : amp
    dhg/dt = phihg*(hinfg-hg)/tauhg : 1
    dng/dt = phing*(ninfg-ng)/taung : 1
    drg/dt = phig*(rinfg-rg)/taurg  : 1
    dcag/dt= epsg*((-icag-itg)/pA - kcag*cag) : 1  #! pA 

    dvg/dt = membrane_Im / C : volt
    '''

    neuron = b2.NeuronGroup(
        num,
        eqs,
        method=par_sim['integration_method'],
        dt=par_sim['dt'],
        threshold='vg>-20*mV',
        refractory='vg>-20*mV',
        namespace=par_g,
    )

    neuron.vg = par_g['v0']
    neuron.hg = "hinfg"
    neuron.ng = "ninfg"
    neuron.rg = "rinfg"
    neuron.cag = 0
    # neuron.i_extg = par_g['iapp']

    st_mon = b2.StateMonitor(neuron, ["vg", 'i_extg'], record=True)

    net = b2.Network(neuron)
    net.add(st_mon)
    net.run(par_sim['simulation_time'])

    return st_mon
Пример #11
0
def simulate_STN_cell(par, par_sim):

    num = par['num']
    input_current = par['i_ext']

    eqs = '''
    I_ext = input_current(t, i): amp 

    minf = 1/(1+exp(-(vs-thetam*mV)/(sigmam*mV))) : 1
    hinf = 1/(1+exp(-(vs-thetah*mV)/(sigmah*mV))) : 1 
    ninf = 1/(1+exp(-(vs-thetan*mV)/(sigman*mV))) : 1
    ainf = 1/(1+exp(-(vs-thetaa*mV)/(sigmaa*mV))) : 1
    binf = 1/(1+exp((r-thetab)/sigmab))-1/(1+exp(-thetab/sigmab)) : 1
    rinf = 1/(1+exp(-(vs-thetar*mV)/(sigmar*mV))) : 1
    sinf = 1/(1+exp(-(vs-thetas*mV)/(sigmas*mV))) : 1
    taun = taun0+taun1/(1+exp(-(vs-thn*mV)/(sigmant*mV))) : second
    tauh = tauh0+tauh1/(1+exp(-(vs-thh*mV)/(sigmaht*mV))) : second
    taur = taur0+taur1/(1+exp(-(vs-thr*mV)/(sigmart*mV))) : second

    il = gl * (vs - vl) : amp
    ina = gna * minf ** 3 * h * (vs - vna) : amp
    ik = gk * n ** 4 * (vs - vk) : amp
    iahp = gahp * ca / (ca + k1) * (vs - vk) : amp 
    ica = gca * sinf ** 2 * (vs - vca) : amp 
    it = gt * ainf ** 3 * binf ** 2 * (vs - vca) : amp 

    dh/dt  = phi * (hinf - h) / tauh  : 1
    dn/dt  = phi * (ninf - n) / taun  : 1
    dr/dt  = phir * (rinf - r) / taur : 1
    dca/dt = eps * ((-ica - it)/pA - kca* ca) : 1    #! pA
    membrane_Im = -(il + ina + ik + it + ica + iahp) + I_ext  : amp
        
    dvs/dt = membrane_Im/C : volt
    '''

    neuron = b2.NeuronGroup(
        num,
        eqs,
        method=par_sim['integration_method'],
        dt=par_sim['dt'],
        threshold='vs>-20*mV',
        refractory='vs>-20*mV',
        namespace=par,
    )

    neuron.vs = par['v0']
    neuron.h = "hinf"
    neuron.n = "ninf"
    neuron.r = "rinf"
    neuron.ca = 0

    st_mon = b2.StateMonitor(neuron, ["vs", "I_ext"], record=True)

    net = b2.Network(neuron)
    net.add(st_mon)
    net.run(par_sim['simulation_time'])

    return st_mon
Пример #12
0
    def make_model(self):
        # Determine the simulation
        if self.clamp_type == 'current':
            eqs_input = '''I_inj = inj_input(t) : amp'''

        elif self.clamp_type == 'dynamic':
            eqs_input = '''I_exc = g_exc(t) * (Er_e - v) : amp
                    I_inh = g_inh(t) * (Er_i - v) : amp
                    I_inj = I_exc + I_inh : amp'''
        tracking = ['v', 'I_inj']

        # Model the neuron with differential equations
        eqs = '''
                # Activation gates Na channel
                m = 1. / (1. + exp(-(v - Vh) / k)) : 1
                Vh = 3.223725 * k - 62.615488*mV : volt

                # Inactivation gates Na channel
                dh/dt = 5. * (alpha_h * (1 - h)- beta_h * h) : 1
                alpha_h = 0.07 * exp(-(v + 58.*mV) / (20.*mV))/ms : Hz
                beta_h = 1. / (exp(-0.1/mV * (v + 28.*mV)) + 1.)/ms : Hz

                # Activation gates K channel
                dn/dt = 5. * (alpha_n * (1. - n) - beta_n * n) : 1
                alpha_n = 0.01/mV * 10*mV / exprel(-(v + 34.*mV) / (10.*mV))/ms : Hz
                beta_n = 0.125 * exp(-(v + 44.*mV) / (80.*mV))/ms : Hz

                # Activation gates K3.1 channel
                dn3/dt = alphan3 * (1. - n3) - betan3 * n3 : 1
                alphan3 = (1. / exp(((param * ((-0.029 * v + (1.9*mV))/mV)))))/ms : Hz
                betan3 = (1. / exp(((param * ((0.021 * v + (1.1*mV))/mV)))))/ms : Hz

                # Currents
                I_leak = -gL * (v - EL) : amp
                I_Na = -gNa * m**3 * h * (v - ENa) : amp
                I_K = -gK * n**4 * (v - EK) : amp
                I_K3 = -gK3 * n3**4 * (v - EK) : amp
                dv/dt = (I_leak + I_Na + I_K + I_K3 + I_inj) / Cm : volt
             '''

        # Neuron & parameter initialization
        neuron = b2.NeuronGroup(1,
                                model=eqs + eqs_input,
                                method='exponential_euler',
                                threshold='m > 0.5',
                                refractory=2 * b2.ms,
                                reset=None,
                                dt=self.dt * b2.ms)
        neuron.v = -65 * b2.mV

        # Track the parameters during simulation
        self.M = b2.StateMonitor(neuron, tracking, record=True)
        self.S = b2.SpikeMonitor(neuron, record=True)
        self.neuron = neuron

        net = b2.Network(neuron)
        net.add(self.M, self.S)
        self.network = net
def init_monitors(neurons, connections, monitor_params):
    """
    Initialise Brian objects monitoring state variables in the network.
    """

    monitors = {
        'spikes': {},
        'neurons': {},
        'connections': {}
    }

    for layer in ['input', 'layer1e']:
        monitors['spikes'][layer] = b2.SpikeMonitor(neurons[layer])

    if 'monitors_dt' not in monitor_params:
        timestep = None
    else:
        timestep = monitor_params['monitors_dt']

    monitors['neurons']['layer1e'] = b2.StateMonitor(
        neurons['layer1e'],
        ['v', 'ge', 'max_ge', 'theta'],
        # record=True is currently broken for standalone simulations
        record=range(len(neurons['layer1e'])),
        dt=timestep
    )
    if 'layer1vis' in neurons:
        monitors['neurons']['layer1vis'] = b2.StateMonitor(
            neurons['layer1vis'],
            ['v'],
            # record=True is currently broken for standalone simulations
            record=range(len(neurons['layer1vis'])),
            dt=b2.second/60
        )

    conn = connections['input-layer1e']
    n_connections = len(conn.target) * len(conn.source)
    monitors['connections']['input-layer1e'] = b2.StateMonitor(
        connections['input-layer1e'],
        ['w', 'post', 'pre'],
        record=range(n_connections),
        dt=timestep
    )

    return monitors
Пример #14
0
def StateMonitors(neuron_groups, index_str, index_record=0):

    index = _neuron_group_index(index_str)
    if index_str == 'input':
        M = br.StateMonitor(neuron_groups[index], 'v', record=index_record, \
                    name=(index_str + '_v'))

        return M

    elif index_str == 'hidden':
        Mge = br.StateMonitor(neuron_groups[index][0], 'ge', record=index_record, \
                    name=(index_str + '_ge' + str(index_record)))
        Mv = br.StateMonitor(neuron_groups[index][0], 'v', record=index_record, \
                    name=(index_str + '_v' + str(index_record)))
        Mu = br.StateMonitor(neuron_groups[index][0], 'u', record=index_record, \
                    name=(index_str + '_u' + str(index_record)))
    else:
        Mge = br.StateMonitor(neuron_groups[index], 'ge', record=index_record, \
                    name=(index_str + '_ge' + str(index_record)))
        Mv = br.StateMonitor(neuron_groups[index], 'v', record=index_record, \
                    name=(index_str + '_v' + str(index_record)))
        Mu = br.StateMonitor(neuron_groups[index], 'u', record=index_record, \
                    name=(index_str + '_u' + str(index_record)))

    return Mv, Mu, Mge
Пример #15
0
def simulate_Thl_cell_fig3(par, par_sim):
    num = par_sim['num']
    i_sensory_motor = par_sim['I_sm']

    # b2.set_device('cpp_standalone')
    b2.start_scope()

    eqs = b2.Equations('''    
    minfthl = 1/(1+exp(-(vt-thtmthl*mV)/(sigmthl*mV))): 1
    hinfthl =  1/(1+exp((vt-thththl*mV)/(sighthl*mV))): 1
    pinfthl = 1/(1+exp(-(vt-thtpthl*mV)/(sigpthl*mV))) :1
    rinfthl = 1/(1+exp((vt-thtrthl*mV)/(sigrthl*mV))) :1
    ahthl =  ah0thl*exp(-(vt-thtahthl*mV)/(sigahthl*mV)) :1
    bhthl =  bh0thl/(1+exp(-(vt-thtbhthl*mV)/(sigbhthl*mV))) :1
    tauhthl =  1/(ahthl+bhthl) *ms :second
    taurthl = taur0thl+taur1thl*exp(-(vt-thtrtauthl*mV)/(sigrtauthl*mV)) :second

    ilthl=glthl*(vt-vlthl):amp
    inathl=gnathl*minfthl*minfthl*minfthl*hthl*(vt-vnathl) :amp
    ikthl=gkthl*((0.75*(1-hthl))**4)*(vt-vkthl) :amp
    itthl=gtthl*pinfthl*pinfthl*rthl*(vt-vtthl) :amp
    iextthl:amp

    tmp_thl1 = sin(2*pi*(t-dsmthl)/tmsmthl) :1
    tmp_thl2 = sin(2*pi*(t-dsmthl+wsmthl)/tmsmthl) :1
    ym_thl1=1/(1+exp(-tmp_thl1/sigym)):1
    ym_thl2=1/(1+exp(-tmp_thl2/sigym)):1
    ithl_sm=imsmthl*ym_thl1*(1-ym_thl2) :amp
    
    membrane_Ithl = -(ilthl+inathl+ikthl+itthl)+iextthl+ithl_sm:amp    
    drthl/dt=phirthl*(rinfthl-rthl)/taurthl :1
    dhthl/dt=phihthl*(hinfthl-hthl)/tauhthl :1 
    dvt/dt = membrane_Ithl/cmthl : volt
    ''')

    neuron = b2.NeuronGroup(
        num,
        eqs,
        method=par_sim['integration_method'],
        dt=par_sim['dt'],
        threshold='vt>-55*mV',
        refractory='vt>-55*mV',
        namespace=par,
    )

    neuron.vt = par['v0']
    neuron.hthl = "hinfthl"
    neuron.rthl = "rinfthl"
    neuron.iextthl = par['iext']

    state_monitor = b2.StateMonitor(neuron, ["vt", "ithl_sm"], record=True)

    net = b2.Network(neuron)
    net.add(state_monitor)
    net.run(par_sim['simulation_time'])

    return state_monitor
Пример #16
0
def simulate_HH_neuron(I_e, simulation_time):
    """A Hodgkin-Huxley neuron implemented in Brian2.

    Args:
        I_e: Input current injected into the HH neuron
        simulation_time (float): Simulation time [seconds]

    Returns:
        StateMonitor: Brian2 StateMonitor with recorded field "vm"
    """

    # neuron parameters
    El = -59. * b2.mV
    EK = -82. * b2.mV
    ENa = 45. * b2.mV
    gl = 0.3 * b2.msiemens
    gK = 36. * b2.msiemens
    gNa = 120. * b2.msiemens
    C = 1. * b2.ufarad

    # forming HH model with differential equations
    eqs = """
    membrane_Im = I_e + gNa*m**3*h*(ENa-vm) + \
        gl*(El-vm) + gK*n**4*(EK-vm) : amp
    
    alphan = 0.01/mV * (-60.0*mV - vm) / (exp((-60.0*mV - vm) / (10.0*mV)) - 1.0)/ms: Hz
    alpham = (vm + 45.0*mV) / (10.0*mV) / (1.0 - exp(-(vm + 45.0*mV) / (10.0*mV)))/ms : Hz
    alphah = 0.07*exp(-(vm + 70.*mV)/(20.*mV))/ms : Hz
    
    betan = 0.125 * exp(-(vm + 70.0*mV) / (80.0*mV))/ms: Hz
    betam = 4.0 * exp(-(vm + 70.0*mV) / (18.0*mV))/ms: Hz
    betah = 1. / (exp(-(vm + 40.0*mV) / (10.0*mV)) + 1.0)/ms : Hz
    
    dn/dt = alphan*(1-n)-betan*n : 1
    dm/dt = alpham*(1-m)-betam*m : 1
    dh/dt = alphah*(1-h)-betah*h : 1
    
    dvm/dt = membrane_Im/C : volt
    """

    neuron = b2.NeuronGroup(1, eqs, method="exponential_euler")

    # parameter initialization [come from x_inf(v) {x:m,n,h}]
    neuron.vm = -70. * b2.mV
    neuron.m = 0.05
    neuron.h = 0.60
    neuron.n = 0.32

    # tracking parameters
    st_mon = b2.StateMonitor(neuron, "vm", record=True)

    # running the simulation
    hh_net = b2.Network(neuron)
    hh_net.add(st_mon)
    hh_net.run(simulation_time)

    return st_mon
Пример #17
0
def simulate_FSI_cell(par, par_sim):

    pid = os.getpid()
    b2.set_device('cpp_standalone', directory=join(
        "output", f"standalone-{pid}"))
    b2.get_device().reinit()
    b2.get_device().activate(
        directory=join("output", f"standalone-{pid}"))

    num = par['num']
    input_current = par['i_ext']

    eqs = '''
    Iapp = input_current(t, i): amp 

    m_inf = 1.0/(1.0+exp(-(vf+24*mV)/(11.5*mV))):1
    h_inf = 1.0/(1.0+exp(-(vf+58.3*mV)/(-6.7*mV))):1
    n_inf = 1.0/(1.0+exp(-(vf+12.4*mV)/(6.8*mV))):1
    a_inf = 1.0/(1.0+exp(-(vf+50*mV)/(20.*mV))):1
    b_inf = 1.0/(1.0+exp(-(vf+70*mV)/(-6.*mV))):1
    tau_h=0.5*ms+14.0*ms/(1.0+exp(-(vf+60*mV)/(-12.*mV))):second
    tau_n=(0.087*ms+11.4*ms/(1.0+exp(-(vf+14.6*mV)/(-8.6*mV))))
         *(0.087+11.4/(1.0+exp(-(vf-1.3*mV)/(18.7*mV)))) :second

    membrain_Im = -gNa*m_inf**3 *h*(vf-50*mV)
                  -gK*(n**power_n)*(vf+90*mV)
                  -gL*(vf+70*mV)-gA*a**3*b*(vf+90*mV)+Iapp:amp
    dh/dt=(h_inf-h)/tau_h :1
    dn/dt=(n_inf-n)/tau_n :1
    da/dt=(a_inf-a)/(2.*ms) :1
    db/dt=(b_inf-b)/(150.*ms) :1
    dvf/dt=membrain_Im/Cm :volt
    '''

    neuron = b2.NeuronGroup(num,
                            eqs,
                            method=par_sim['integration_method'],
                            dt=par_sim['dt'],
                            threshold='vf>-20*mV',
                            refractory='vf>-20*mV',
                            namespace=par,
                            )

    neuron.vf = par['v0']
    neuron.h = "h_inf"
    neuron.n = "n_inf"
    neuron.a = "a_inf"
    neuron.b = "b_inf"

    st_mon = b2.StateMonitor(neuron, ["vf", "Iapp"], record=True)

    net = b2.Network(neuron)
    net.add(st_mon)
    net.run(par_sim['simulation_time'])

    return st_mon
Пример #18
0
def simulate_HH_neuron(input_current, simulation_time):
    """A Hodgkin-Huxley neuron implemented in Brian2.

    Args:
        input_current (TimedArray): Input current injected into the HH neuron
        simulation_time (float): Simulation time [seconds]

    Returns:
        StateMonitor: Brian2 StateMonitor with recorded fields
        ["vm", "I_e", "m", "n", "h"]
    """

    # neuron parameters
    El = 10.6 * b2.mV
    EK = -12 * b2.mV
    ENa = 115 * b2.mV
    gl = 0.3 * b2.msiemens
    gK = 36 * b2.msiemens
    gNa = 120 * b2.msiemens
    C = 1 * b2.ufarad

    # forming HH model with differential equations
    eqs = """
    I_e = input_current(t,i) : amp
    membrane_Im = I_e + gNa*m**3*h*(ENa-vm) + \
        gl*(El-vm) + gK*n**4*(EK-vm) : amp
    alphah = .07*exp(-.05*vm/mV)/ms    : Hz
    alpham = .1*(25*mV-vm)/(exp(2.5-.1*vm/mV)-1)/mV/ms : Hz
    alphan = .01*(10*mV-vm)/(exp(1-.1*vm/mV)-1)/mV/ms : Hz
    betah = 1./(1+exp(3.-.1*vm/mV))/ms : Hz
    betam = 4*exp(-.0556*vm/mV)/ms : Hz
    betan = .125*exp(-.0125*vm/mV)/ms : Hz
    dh/dt = alphah*(1-h)-betah*h : 1
    dm/dt = alpham*(1-m)-betam*m : 1
    dn/dt = alphan*(1-n)-betan*n : 1
    dvm/dt = membrane_Im/C : volt
    """

    neuron = b2.NeuronGroup(1, eqs, method="exponential_euler")

    # parameter initialization
    neuron.vm = 0
    neuron.m = 0.05
    neuron.h = 0.60
    neuron.n = 0.32

    # tracking parameters
    st_mon = b2.StateMonitor(neuron, ["vm", "I_e", "m", "n", "h"], record=True)

    # running the simulation
    hh_net = b2.Network(neuron)
    hh_net.add(st_mon)
    hh_net.run(simulation_time)

    return st_mon
def current_pulse_sim_with_opto(args, params=None):
    
    if params is None:
        params = get_neuron_params(args['NRN'])
    params['Vclamp'] = -80
        
    neurons, eqs = get_membrane_equation(params, [],\
                                         return_equations=True)
    if args['verbose']:
        print(eqs)

    fig, ax = brian2.subplots(figsize=(5,3))

    # V value initialization
    neurons.V = params['El']*brian2.mV
    trace = brian2.StateMonitor(neurons, 'V', record=0)
    spikes = brian2.SpikeMonitor(neurons)
    # rest run
    brian2.run(args['delay'] * brian2.ms)
    # first pulse
    neurons.I0 = args['amp']*brian2.pA
    brian2.run(args['duration']/3. * brian2.ms)
    neurons.Gclamp = 1e3*brian2.nS
    brian2.run(args['duration']/3. * brian2.ms)
    neurons.Gclamp = 0*brian2.nS
    brian2.run(args['duration']/3. * brian2.ms)
    # second pulse
    neurons.I0 = 0
    brian2.run(args['delay'] * brian2.ms)
    # We draw nicer spikes
    Vm = trace[0].V[:]
    for t in spikes.t:
        ax.plot(t/brian2.ms*np.ones(2),
                [Vm[int(t/brian2.defaultclock.dt)]/brian2.mV,-10],
                '--', color=args['color'])
    ax.plot(trace.t / brian2.ms, Vm / brian2.mV, color=args['color'])
    
    if 'NRN' in args.keys():
        ax.set_title(args['NRN'])

    ax.annotate(str(int(params['El']))+'mV', (-50,params['El']-5))
    ax.plot([-20], [params['El']], 'k>')
    ax.plot([0,50], [-50, -50], 'k-', lw=4)
    ax.plot([0,0], [-50, -40], 'k-', lw=4)
    ax.annotate('10mV', (-50,-38))
    ax.annotate('50ms', (0,-55))
    # set_plot(ax, [], xticks=[], yticks=[])
    # show()
    if 'save' in args.keys():
        fig.savefig(args['save'])
    return fig
Пример #20
0
def main2():
    # setting synaptic weight
    bs.start_scope()
    n_neurons = 3
    eqs = '''
    dv/dt = (I-v)/tau : 1 (unless refractory)
    I : 1
    tau: second
    '''
    threshold = 'v>1'
    reset = 'v = 0'
    refractory = 10 * bs.ms
    G = bs.NeuronGroup(N=n_neurons,
                       model=eqs,
                       threshold=threshold,
                       reset=reset,
                       method='exact',
                       refractory=refractory)

    G.I = [2, 0, 0]  # represents the I in eqs
    # driving current should be bigger than the threshold, otherwise it wont spike at all

    # I = 0 means that the voltage wont change since there is no driving current
    G.tau = [10, 100, 100] * bs.ms  # represents the tau in eqs
    # unlike last time, the tau is defined with the neuron so we see the effects of different values

    #     model : `str`, `Equations`, optional
    #         The model equations for the synapses.
    # you need to set this as model= in Synapses in order to incorporate weight
    synapse_model = 'w : 1'

    # So in total, what this model says is that whenever two neurons in G are connected by a synapse,
    # when the source neuron fires a spike the target neuron will have its value of v increased by 0.2.
    S = bs.Synapses(source=G,
                    target=G,
                    model=synapse_model,
                    on_pre='v_post +=  w')
    S.connect(i=0, j=[1, 2])
    # So this will give a synaptic connection from 0 to 1 with weight 0.2=0.2*1 and from 0 to 2 with weight 0.4=0.2*2.
    S.w = 'j*0.2'

    state_monitor = bs.StateMonitor(G, 'v', record=True)
    bs.run(100 * bs.ms)

    plt.plot(state_monitor.t / bs.ms, state_monitor.v[0], label='Neuron 0')
    plt.plot(state_monitor.t / bs.ms, state_monitor.v[1], label='Neuron 1')
    plt.plot(state_monitor.t / bs.ms, state_monitor.v[2], label='Neuron 2')
    plt.xlabel('Time (ms)')
    plt.ylabel('v')
    plt.legend()
    plt.show()
Пример #21
0
def simulate(runtime=0.5*b2.second, N=1):
    b2.start_scope()

    namespace['sigma'] = 2 * b2.mV
    namespace['tau_m_E'] = namespace['C_m_E'] / namespace['g_m_E']
    # I_1 = -2*b2.namp
    # I_2 = -20*b2.namp
    I_1 = namespace['g_m_E'] * (namespace['V_L'] - (2.5*b2.mV + namespace['V_thr']))
    I_2 = namespace['g_m_E'] * (namespace['V_L'] - (-2.5*b2.mV + namespace['V_thr']))

    eqn = """
    dV/dt = (- g_m_E * (V - V_L) - I) / C_m_E + sigma*xi*tau_m_E**-0.5: volt (unless refractory)
    I : amp
    """
    N1 = b2.NeuronGroup(
        N, eqn, threshold='V>V_thr',
        reset='V = V_reset',
        refractory=namespace['tau_rp_E'],
        method='euler')
    N1.V = namespace['V_reset']
    N1.I = I_1

    N2 = b2.NeuronGroup(
        N, eqn, threshold='V>V_thr',
        reset='V = V_reset',
        refractory=namespace['tau_rp_E'],
        method='euler')
    N2.V = namespace['V_reset']
    N2.I = I_2
    
    st1 = b2.StateMonitor(N1, variables='V', record=True, name='st1')
    st2 = b2.StateMonitor(N2, variables='V', record=True, name='st2')
    sp1 = b2.SpikeMonitor(N1, name='sp1')
    sp2 = b2.SpikeMonitor(N2, name='sp2')

    net = b2.Network(b2.collect())
    net.run(runtime, namespace=namespace, report='stdout')
    return net
Пример #22
0
def main1():
    bs.start_scope()
    # Parameters
    area = 20000 * bs.umetre**2
    Cm = 1 * bs.ufarad * bs.cm**-2 * area
    gl = 5e-5 * bs.siemens * bs.cm**-2 * area
    El = -65 * bs.mV
    EK = -90 * bs.mV
    ENa = 50 * bs.mV
    g_na = 100 * bs.msiemens * bs.cm**-2 * area
    g_kd = 30 * bs.msiemens * bs.cm**-2 * area
    VT = -63 * bs.mV

    # HH stands for Hudgkin-Huxley
    eqs_HH = '''
    dv/dt = (gl*(El-v) - g_na*(m*m*m)*h*(v-ENa) - g_kd*(n*n*n*n)*(v-EK) + I)/Cm : volt
    
    dm/dt = 0.32*(mV**-1)*(13.*mV-v+VT)/
        (exp((13.*mV-v+VT)/(4.*mV))-1.)/ms*(1-m)-0.28*(mV**-1)*(v-VT-40.*mV)/
        (exp((v-VT-40.*mV)/(5.*mV))-1.)/ms*m : 1
        
    dn/dt = 0.032*(mV**-1)*(15.*mV-v+VT)/
        (exp((15.*mV-v+VT)/(5.*mV))-1.)/ms*(1.-n)-.5*exp((10.*mV-v+VT)/(40.*mV))/ms*n : 1
        
    dh/dt = 0.128*exp((17.*mV-v+VT)/(18.*mV))/ms*(1.-h)-4./(1+exp((40.*mV-v+VT)/(5.*mV)))/ms*h : 1
    
    I : amp
    '''

    group = bs.NeuronGroup(1,
                           eqs_HH,
                           threshold='v > -40*mV',
                           refractory='v > -40*mV',
                           method='exponential_euler')
    group.v = El
    state_monitor = bs.StateMonitor(group, 'v', record=True)
    spike_monitor = bs.SpikeMonitor(group, variables='v')
    plt.figure(figsize=(9, 4))
    for l in range(5):
        group.I = bs.rand() * 50 * bs.nA
        bs.run(10 * bs.ms)
        bs.axvline(l * 10, ls='--', c='k')
    bs.axhline(El / bs.mV, ls='-', c='lightgray', lw=3)
    state_time = state_monitor.t
    spike_time = spike_monitor.t
    plt.plot(state_time / bs.ms, spike_monitor.v[0] / bs.mV, '-b')
    plt.plot(spike_time / bs.ms, spike_monitor.v / bs.mV, 'ob')
    plt.xlabel('Time (ms)')
    plt.ylabel('v (mV)')
    plt.show()
Пример #23
0
 def _create_device(self, group, variable):
     """Create a Brian2 recording device."""
     # Brian2 records in the 'start' scheduling slot by default
     if variable == 'spikes':
         self._devices[variable] = brian2.SpikeMonitor(group, record=self.recorded)
     else:
         varname = self.population.celltype.state_variable_translations[variable]['translated_name']
         neurons_to_record = np.sort(np.fromiter(
             self.recorded[variable], dtype=int)) - self.population.first_id
         self._devices[variable] = brian2.StateMonitor(group, varname,
                                                       record=neurons_to_record,
                                                       when='end',
                                                       dt=self.sampling_interval * ms)
     simulator.state.network.add(self._devices[variable])
   def simulate(self,
                current=input_factory.get_zero_current(),
                time=10 * b2.ms,
                rheo_threshold=None,
                v_rest=None,
                v_reset=None,
                delta_t=None,
                time_scale=None,
                resistance=None,
                threshold=None,
                adapt_volt_c=None,
                adapt_tau=None,
                adapt_incr=None):
       if (v_rest == None):
           v_rest = self.rest_pot
       if (v_reset == None):
           v_reset = self.reset_pot
       if (rheo_threshold == None):
           rheo_threshold = self.rheo_threshold
       if (delta_t == None):
           delta_t = self.delta_t
       if (time_scale == None):
           time_scale = self.time_scale
       if (resistance == None):
           resistance = self.resistance
       if (threshold == None):
           threshold = self.threshold
       if (adapt_volt_c == None):
           adapt_volt_c = self.adapt_volt_c
       if (adapt_tau == None):
           adapt_tau = self.adapt_tau
       if (adapt_incr == None):
           adapt_incr = self.adapt_incr
       v_spike_str = "v>{:f}*mvolt".format(threshold / b2.mvolt)
       eqs = """
 			dv/dt = (-(v-v_rest) +delta_t*exp((v-rheo_threshold)/delta_t)+ resistance * current(t,i) - resistance * w)/(time_scale) : volt
       	dw/dt=(adapt_volt_c*(v-v_rest)-w)/adapt_tau : amp
       	"""
       neuron = b2.NeuronGroup(1,
                               model=eqs,
                               threshold=v_spike_str,
                               reset="v=v_reset;w+=adapt_incr",
                               method="euler")
       neuron.v = v_rest
       neuron.w = 0.0 * b2.pA
       state_monitor = b2.StateMonitor(neuron, ["v", "w"], record=True)
       spike_monitor = b2.SpikeMonitor(neuron)
       b2.run(time)
       return state_monitor, spike_monitor
Пример #25
0
    def simulate_neuron(self,
                        I_stim=input_factory.get_zero_current(),
                        simulation_time=1000 * ms,
                        **kwargs):
        """
        Simulate/stimulate the neuron

        :param I_stim: input stimulus (use the input_factory to create the stimulus)
        :param simulation_time: duration (usually in milliseconds, eg. 3000*ms)
        :param kwargs: custom neuron parameters can be given as arguments
        :return: b2.StateMonitor, b2.SpikeMonitor
        """

        neuron_parameters = dict(
            self.neuron_parameters
        )  # Make a copy of parameters; otherwise will change object params
        neuron_parameters.update(kwargs)
        refractory_period = neuron_parameters['refractory_period']

        stim_string = '+ I_stim(t,i)'
        old_model_defns = dict(self.full_model_defns)
        self.add_model_definition('EXT_CURRENTS', stim_string)
        eqs = self.get_membrane_equation()
        self.full_model_defns = old_model_defns

        # Create a neuron group
        neuron = b2.NeuronGroup(1,
                                model=eqs,
                                namespace=neuron_parameters,
                                reset=self.reset_statements,
                                threshold=self.threshold_condition,
                                refractory=refractory_period,
                                method=self.integration_method)

        # Set initial values
        initial_values = self.get_initial_values()
        neuron.set_states(initial_values)

        # Set what to monitor
        state_monitor = b2.StateMonitor(neuron,
                                        self.get_states_to_monitor(),
                                        record=True)
        spike_monitor = b2.SpikeMonitor(neuron)

        # Run the simulation
        net = b2.Network(neuron, state_monitor, spike_monitor)
        net.run(simulation_time)

        return state_monitor, spike_monitor
Пример #26
0
def main2():
    tau = 10 * bs.ms
    eqs = '''
    dv/dt = (sin(2*pi*100*Hz*t)-v)/tau : 1
    '''
    G = bs.NeuronGroup(1, eqs, method="euler")
    G.v = 5  # we can set the initial value
    M = bs.StateMonitor(G, 'v', record=0)

    bs.run(60 * bs.ms)

    plt.plot(M.t / bs.ms, M.v[0])
    plt.xlabel('Time (ms)')
    plt.ylabel('v')
    plt.show()
Пример #27
0
def main3():
    # introducing delay
    bs.start_scope()
    n_neurons = 3
    eqs = '''
    dv/dt = (I-v)/tau : 1 (unless refractory)
    I : 1
    tau: second
    '''
    threshold = 'v>1'
    reset = 'v = 0'
    refractory = 10 * bs.ms
    G = bs.NeuronGroup(N=n_neurons,
                       model=eqs,
                       threshold=threshold,
                       reset=reset,
                       method='exact',
                       refractory=refractory)

    G.I = [2, 0, 0]  # represents the I in eqs
    # driving current should be bigger than the threshold, otherwise it wont spike at all

    # I = 0 means that the voltage wont change since there is no driving current
    G.tau = [10, 100, 100] * bs.ms  # represents the tau in eqs
    # unlike last time, the tau is defined with the neuron so we see the effects of different values

    synapse_model = 'w : 1'

    # So in total, what this model says is that whenever two neurons in G are connected by a synapse,
    # when the source neuron fires a spike the target neuron will have its value of v increased by 0.2.
    S = bs.Synapses(source=G,
                    target=G,
                    model=synapse_model,
                    on_pre='v_post +=  w')
    S.connect(i=0, j=[1, 2])
    S.w = 'j*0.2'
    S.delay = 'j*2*ms'

    state_monitor = bs.StateMonitor(G, 'v', record=True)
    bs.run(100 * bs.ms)

    plt.plot(state_monitor.t / bs.ms, state_monitor.v[0], label='Neuron 0')
    plt.plot(state_monitor.t / bs.ms, state_monitor.v[1], label='Neuron 1')
    plt.plot(state_monitor.t / bs.ms, state_monitor.v[2], label='Neuron 2')
    plt.xlabel('Time (ms)')
    plt.ylabel('v')
    plt.legend()
    plt.show()
Пример #28
0
def main6():
    # neurons with parameters
    n_neurons = 100
    tau = 10 * bs.ms
    v0_max = 3.0
    duration = 1000 * bs.ms
    # v0: 1 declares a new per-neuron parameter v0
    eqs = """
    dv/dt = (v0-v)/tau: 1 (unless refractory)
    v0 : 1
    """

    # conditions for spiking models
    threshold = 'v>1'
    reset = 'v = 0'
    refractory = 5 * bs.ms
    G = bs.NeuronGroup(N=n_neurons, model=eqs, threshold=threshold, reset=reset, method='exact', refractory=refractory)

    state_monitor = bs.StateMonitor(G, 'v', record=True)
    spike_monitor = bs.SpikeMonitor(G)
    """
    The line G.v0 = 'i*v0_max/(N-1)' initialises the value of v0 for each neuron varying from 0 up to v0_max. 
    The symbol i when it appears in strings like this refers to the neuron index.
    """
    G.v0 = 'i*v0_max/(N-1)'
    bs.run(duration=duration)

    plt.figure(figsize=(12, 4))
    plt.subplot(121)
    plt.plot(spike_monitor.t / bs.ms, spike_monitor.i, '.k')
    plt.xlabel('Time (ms)')
    plt.ylabel('Neuron index')
    plt.subplot(122)
    plt.plot(G.v0, spike_monitor.count / duration)
    plt.xlabel('v0')
    plt.ylabel('Firing rate (sp/s)')
    plt.show()

    plt.clf()
    # plt.plot(state_monitor.t / bs.ms, state_monitor.v[0])
    # plt.plot(state_monitor.t / bs.ms, state_monitor.v[10])
    # plt.plot(state_monitor.t / bs.ms, state_monitor.v[50])
    plt.plot(state_monitor.t / bs.ms, state_monitor.v[30])
    plt.plot(state_monitor.t / bs.ms, state_monitor.v[40])
    plt.plot(state_monitor.t / bs.ms, state_monitor.v[70])
    plt.xlabel('Time (ms)')
    plt.ylabel('v')
    plt.show()
def simulate_exponential_IF_neuron(tau=MEMBRANE_TIME_SCALE_tau,
                                   R=MEMBRANE_RESISTANCE_R,
                                   v_rest=V_REST,
                                   v_reset=V_RESET,
                                   v_rheobase=RHEOBASE_THRESHOLD_v_rh,
                                   v_spike=FIRING_THRESHOLD_v_spike,
                                   delta_T=SHARPNESS_delta_T,
                                   I_stim=input_factory.get_zero_current(),
                                   simulation_time=200 * b2.ms):
    """
    Implements the dynamics of the exponential Integrate-and-fire model

    Args:
        tau (Quantity): Membrane time constant
        R (Quantity): Membrane resistance
        v_rest (Quantity): Resting potential
        v_reset (Quantity): Reset value (vm after spike)
        v_rheobase (Quantity): Rheobase threshold
        v_spike (Quantity) : voltage threshold for the spike condition
        delta_T (Quantity): Sharpness of the exponential term
        I_stim (TimedArray): Input current
        simulation_time (Quantity): Duration for which the model is simulated

    Returns:
        (voltage_monitor, spike_monitor):
        A b2.StateMonitor for the variable "v" and a b2.SpikeMonitor
    """

    eqs = """
    dv/dt = (-(v-v_rest) +delta_T*exp((v-v_rheobase)/delta_T)+ R * I_stim(t,i))/(tau) : volt
    """
    neuron = b2.NeuronGroup(1,
                            model=eqs,
                            reset="v=v_reset",
                            threshold="v>v_spike",
                            method="euler")
    neuron.v = v_rest
    # monitoring membrane potential of neuron and injecting current
    voltage_monitor = b2.StateMonitor(neuron, ["v"], record=True)
    spike_monitor = b2.SpikeMonitor(neuron)

    # run the simulation
    net = b2.Network(neuron, voltage_monitor, spike_monitor)
    net.run(simulation_time)

    return voltage_monitor, spike_monitor
Пример #30
0
    def make_model(self):
        # Determine the simulation
        if self.clamp_type == 'current':
            eqs_input = '''I_inj = inj_input(t) : amp'''

        elif self.clamp_type == 'dynamic':
            eqs_input = '''I_exc = g_exc(t) * (Er_e - v) : amp
                    I_inh = g_inh(t) * (Er_i - v) : amp
                    I_inj = I_exc + I_inh : amp'''
        tracking = ['v', 'I_inj']

        # Model the neuron with differential equations
        eqs = '''
            Vh_m = 3.583881 * k_m - 53.294454*mV : volt
            m = 1 / (1 + exp(-(v - Vh_m) / k_m)) : 1
            h = 1 / (1 + exp((v - Vh_h) / k_h)) : 1

            alpha_n = (0.032 * 5. / exprel((15. -v/mV + VT/mV) / 5.))/ms : Hz
            beta_n = (0.5 * exp((10. - v/mV + VT/mV) / 40.))/ms : Hz
            dn/dt = alpha_n * (1 - n) - beta_n * n : 1

            I_leak = -gL * (v - EL) : amp
            I_Na = -gNa * m**3 * h * (v - ENa) : amp
            I_K = -gK * n**4 * (v - EK) : amp

            dv/dt = (I_leak + I_Na + I_K + I_inj) / Cm : volt
            '''

        # Neuron & parameter initialization
        neuron = b2.NeuronGroup(1,
                                model=eqs + eqs_input,
                                method='exponential_euler',
                                threshold='m > 0.5',
                                refractory=2 * b2.ms,
                                reset=None,
                                dt=self.dt * b2.ms)
        neuron.v = -65 * b2.mV

        # Track the parameters during simulation
        self.M = b2.StateMonitor(neuron, tracking, record=True)
        self.S = b2.SpikeMonitor(neuron, record=True)
        self.neuron = neuron

        net = b2.Network(neuron)
        net.add(self.M, self.S)
        self.network = net