Ejemplo n.º 1
0
 def get_monitors(pop, monitored_subset_size):
     monitored_subset_size = min(monitored_subset_size, pop.N)
     idx_monitored_neurons = sample(range(pop.N), monitored_subset_size)
     rate_monitor = PopulationRateMonitor(pop)
     spike_monitor = SpikeMonitor(pop, record=idx_monitored_neurons)
     voltage_monitor = StateMonitor(pop, "v", record=idx_monitored_neurons)
     return rate_monitor, spike_monitor, voltage_monitor, idx_monitored_neurons
Ejemplo n.º 2
0
 def get_monitors(pop, nr_monitored, N):
     nr_monitored = min(nr_monitored, (N))
     idx_monitored_neurons = [int(math.ceil(k))
          for k in np.linspace(0, N - 1, nr_monitored + 2)][1:-1]  # sample(range(N), nr_monitored)
     spike_monitor   = SpikeMonitor(pop, record=idx_monitored_neurons)
     synapse_monitor = StateMonitor(syn_excit2excit, "stp", record=syn_excit2excit[stim1_center_idx, stim1_center_idx-10:stim1_center_idx+10], dt=1*ms)
     return spike_monitor, synapse_monitor, idx_monitored_neurons
 def get_monitors(pop, nr_monitored, N):
     nr_monitored = min(nr_monitored, (N))
     idx_monitored_neurons = \
         [int(math.ceil(k))
          for k in numpy.linspace(0, N - 1, nr_monitored + 2)][1:-1]  # sample(range(N), nr_monitored)
     rate_monitor = PopulationRateMonitor(pop)
     # record= some_list is not supported? :-(
     spike_monitor = SpikeMonitor(pop, record=idx_monitored_neurons)
     voltage_monitor = StateMonitor(pop, "v", record=idx_monitored_neurons)
     return rate_monitor, spike_monitor, voltage_monitor, idx_monitored_neurons
Ejemplo n.º 4
0
 def get_monitors(pop, nr_monitored, N):
     nr_monitored = min(nr_monitored, (N))
     idx_monitored_neurons = [
         int(math.ceil(k)) for k in np.linspace(0, N - 1, nr_monitored + 2)
     ][1:-1]  # sample(range(N), nr_monitored)
     rate_monitor = PopulationRateMonitor(pop)
     spike_monitor = SpikeMonitor(pop, record=idx_monitored_neurons)
     voltage_monitor = StateMonitor(pop, "v", dt=1 * ms,
                                    record=0)  #idx_monitored_neurons)
     # synapse_monitor = StateMonitor(pop, "stp", dt=10*ms, record=pop[int(np.ceil(N/2)),:]) #N_excitatory/2,:])
     synapse_monitor = StateMonitor(
         syn_excit2excit,
         "stp",
         dt=10 * ms,
         record=syn_excit2excit[stim1_center_idx, :])  #N_excitatory/2,:])
     return rate_monitor, spike_monitor, voltage_monitor, idx_monitored_neurons, synapse_monitor
Ejemplo n.º 5
0
    def get_monitors(pop, monitored_subset_size):
        """
        Internal helper.
        Args:
            pop:
            monitored_subset_size:

        Returns:

        """
        monitored_subset_size = min(monitored_subset_size, pop.N)
        idx_monitored_neurons = sample(range(pop.N), monitored_subset_size)
        rate_monitor = PopulationRateMonitor(pop)
        # record parameter: record=idx_monitored_neurons is not supported???
        spike_monitor = SpikeMonitor(pop, record=idx_monitored_neurons)
        voltage_monitor = StateMonitor(pop, "v", record=idx_monitored_neurons)
        return rate_monitor, spike_monitor, voltage_monitor, idx_monitored_neurons
def simulate_wm(
        N_excitatory=4096,
        N_inhibitory=1024,
        N_extern_poisson=1000,
        poisson_firing_rate=1 * b2.Hz,
        features=[120, 240],
        stimulus_width=2,
        strength=0.4 * b2.namp,
        t_stimulus_start=200 * b2.ms,
        t_stimulus_duration=100 * b2.ms,
        sim_time=1500. * b2.ms,
        Jpos_excit2excit=4.02,
        sigma_weight=5.,
        G_inhib2excit=0.6681 * b2.nS,  # 1.336
        G_inhib2inhib=0.512 * b2.nS,  # 1.024
        G_excit2excit=0.1905 * b2.nS,  # 0.381
        G_excit2inhib=0.146 * b2.nS,  # 1.2 * 0.292
        G_extern2excit=2.48 * b2.nS,  # 3.1
        G_extern2inhib=1.9 * b2.nS,  # 2.38 
        scaling_inhib=1,
        scaling_excit=1):
    """
    Args:
        N_excitatory (int): Size of the excitatory population
        N_inhibitory (int): Size of the inhibitory population
        weight_scaling_factor (float): weight prefactor. When increasing the size of the populations,
            the synaptic weights have to be decreased. Using the default values, we have
            N_excitatory*weight_scaling_factor = 2048 and N_inhibitory*weight_scaling_factor=512
        N_extern_poisson (int): Size of the external input population (Poisson input)
        poisson_firing_rate (Quantity): Firing rate of the external population
        sigma_weight_profile (float): standard deviation of the gaussian input profile in
            the excitatory population.
        Jpos_excit2excit (float): Strength of the recurrent input within the excitatory population.
            Jneg_excit2excit is computed from sigma_weight_profile, Jpos_excit2excit and the normalization
            condition.
        features (list): Center of gaussian input in degree([0, 360])
        stimulus_width (float): Sigma of gaussian input
        strength (Quantity): Input current to the neurons at stimulus_center_deg +\- (stimulus_width_deg/2)
        t_stimulus_start (Quantity): time when the input stimulus is turned on
        t_stimulus_duration (Quantity): duration of the stimulus.
        distractor_center_deg (float): Center of the distractor in [0, 360]
        distractor_width_deg (float): width of the distractor. All neurons in
            distractor_center_deg +\- (distractor_width_deg/2) receive the same input current
            distractor_strength (Quantity): Input current to the neurons at
            distractor_center_deg +\- (distractor_width_deg/2)
        t_distractor_start (Quantity): time when the distractor is turned on
        t_distractor_duration (Quantity): duration of the distractor.
        G_inhib2inhib (Quantity): projections from inhibitory to inhibitory population (later
            rescaled by weight_scaling_factor)
        G_inhib2excit (Quantity): projections from inhibitory to excitatory population (later
            rescaled by weight_scaling_factor)
        G_excit2excit (Quantity): projections from excitatory to excitatory population (later
            rescaled by weight_scaling_factor)
        G_excit2inhib (Quantity): projections from excitatory to inhibitory population (later
            rescaled by weight_scaling_factor)
        monitored_subset_size (int): nr of neurons for which a Spike- and Voltage monitor
            is registered.
        sim_time (Quantity): simulation time

    Returns:

       results (tuple):
       rate_monitor_excit (Brian2 PopulationRateMonitor for the excitatory population),
        spike_monitor_excit, voltage_monitor_excit, idx_monitored_neurons_excit,\
        rate_monitor_inhib, spike_monitor_inhib, voltage_monitor_inhib, idx_monitored_neurons_inhib,\
        weight_profile_45 (The weights profile for the neuron with preferred direction = 45deg).
    """
    # =============================================================================
    # 参数设定
    # =============================================================================
    # specify the excitatory pyramidal cells:
    Cm_excit = 0.5 * b2.nF  # membrane capacitance of excitatory neurons
    G_leak_excit = 25.0 * b2.nS  # leak conductance
    E_leak_excit = -70.0 * b2.mV  # reversal potential
    v_firing_threshold_excit = -50.0 * b2.mV  # spike condition
    v_reset_excit = -60.0 * b2.mV  # reset voltage after spike
    t_abs_refract_excit = 2.0 * b2.ms  # absolute refractory period

    # specify the inhibitory interneurons:
    Cm_inhib = 0.2 * b2.nF
    G_leak_inhib = 20.0 * b2.nS
    E_leak_inhib = -70.0 * b2.mV
    v_firing_threshold_inhib = -50.0 * b2.mV
    v_reset_inhib = -60.0 * b2.mV
    t_abs_refract_inhib = 1.0 * b2.ms

    # specify the AMPA synapses
    E_AMPA = 0.0 * b2.mV
    tau_AMPA = 2.0 * b2.ms

    # specify the GABA synapses
    E_GABA = -70.0 * b2.mV
    tau_GABA = 10.0 * b2.ms

    # specify the NMDA synapses
    E_NMDA = 0.0 * b2.mV
    tau_NMDA_s = 100.0 * b2.ms
    tau_NMDA_x = 2.0 * b2.ms
    alpha_NMDA = 0.5 * b2.kHz

    # projectsions from the inhibitory populations
    G_inhib2excit *= scaling_inhib
    G_inhib2inhib *= scaling_inhib

    # projections from the excitatory population
    G_excit2excit *= scaling_excit
    G_excit2inhib *= scaling_excit

    # =============================================================================
    # 感觉1d网络
    # =============================================================================

    # define the inhibitory population
    inhib_lif_dynamics = """
        s_NMDA_total : 1  # the post synaptic sum of s. compare with s_NMDA_presyn
        dv/dt = (
        - G_leak_inhib * (v-E_leak_inhib)
        - G_extern2inhib * s_AMPA * (v-E_AMPA)
        - G_inhib2inhib * s_GABA * (v-E_GABA)
        - G_excit2inhib * s_NMDA_total * (v-E_NMDA) / (1.0+1.0*exp(-0.062*v/volt)/3.57)
        )/Cm_inhib : volt (unless refractory)
        ds_AMPA/dt = -s_AMPA / tau_AMPA : 1
        ds_GABA/dt = -s_GABA / tau_GABA : 1
    """

    # specify the excitatory population:
    excit_lif_dynamics = """
        I_stim : amp
        s_NMDA_total : 1  # the post synaptic sum of s. compare with s_NMDA_presyn
        dv/dt = (
        - G_leak_excit * (v-E_leak_excit)
        - G_extern2excit * s_AMPA * (v-E_AMPA)
        - G_inhib2excit * s_GABA * (v-E_GABA)
        - G_excit2excit * s_NMDA_total * (v-E_NMDA)/(1.0+1.0*exp(-0.062*v/volt)/3.57)
        + I_stim
        )/Cm_excit : volt (unless refractory)
        ds_AMPA/dt = -s_AMPA / tau_AMPA : 1
        ds_GABA/dt = -s_GABA / tau_GABA : 1
        ds_NMDA/dt = -s_NMDA / tau_NMDA_s + alpha_NMDA * x * (1-s_NMDA) : 1
        dx/dt = -x / tau_NMDA_x : 1
    """

    # 抑制神经元群
    inhib_pop = NeuronGroup(N_inhibitory,
                            model=inhib_lif_dynamics,
                            threshold="v>v_firing_threshold_inhib",
                            reset="v=v_reset_inhib",
                            refractory=t_abs_refract_inhib,
                            method="rk2")

    # initialize with random voltages:
    inhib_pop.v = np.random.uniform(v_reset_inhib / b2.mV,
                                    high=v_firing_threshold_inhib / b2.mV,
                                    size=N_inhibitory) * b2.mV
    # set the connections: inhib2inhib
    syn_inhib2inhib = Synapses(inhib_pop,
                               target=inhib_pop,
                               on_pre="s_GABA += 1.0",
                               delay=0.0 * b2.ms)
    syn_inhib2inhib.connect(condition="i!=j", p=1.0)

    # set the connections: extern2inhib
    input_ext2inhib = PoissonInput(target=inhib_pop,
                                   target_var="s_AMPA",
                                   N=N_extern_poisson,
                                   rate=poisson_firing_rate,
                                   weight=1.0)

    #兴奋神经元群
    excit_pop = NeuronGroup(N_excitatory,
                            model=excit_lif_dynamics,
                            threshold="v>v_firing_threshold_excit",
                            reset="v=v_reset_excit; x+=1.0",
                            refractory=t_abs_refract_excit,
                            method="rk2")

    # initialize with random voltages:
    excit_pop.v = np.randomz.uniform(v_reset_excit / b2.mV,
                                     high=v_firing_threshold_excit / b2.mV,
                                     size=N_excitatory) * b2.mV
    excit_pop.I_stim = 0. * b2.namp

    # set the connections: extern2excit
    input_ext2excit = PoissonInput(target=excit_pop,
                                   target_var="s_AMPA",
                                   N=N_extern_poisson,
                                   rate=poisson_firing_rate,
                                   weight=1.0)

    # set the connections: inhibitory to excitatory
    syn_inhib2excit = Synapses(inhib_pop,
                               target=excit_pop,
                               on_pre="s_GABA += 1.0")
    syn_inhib2excit.connect(p=1.0)

    # set the connections: excitatory to inhibitory NMDA connections
    syn_excit2inhib = Synapses(
        excit_pop,
        inhib_pop,
        model="s_NMDA_total_post = s_NMDA_pre : 1 (summed)",
        method="rk2")
    syn_excit2inhib.connect(p=1.0)

    # =============================================================================
    # 开始模拟!
    # =============================================================================
    # precompute the weight profile for the recurrent population
    presyn_weight = structured_connectivity(N_excitatory, Jpos_excit2excit,
                                            sigma_weight)
    fft_presyn_weight = rfft(presyn_weight)

    # set the STRUCTURED recurrent input. use a network_operation
    @network_operation()
    def update_nmda_sum():
        fft_s_NMDA = rfft(excit_pop.s_NMDA)
        fft_s_NMDA_total = np.multiply(fft_presyn_weight, fft_s_NMDA)
        excit_pop.s_NMDA_total_ = irfft(fft_s_NMDA_total)

    stimulus = gaussian_input(N_excitatory, features, stimulus_width)
    t_stimulus_end = t_stimulus_start + t_stimulus_duration

    @network_operation(dt=1 * b2.ms)
    def stimulate_network(t):
        if t >= t_stimulus_start and t < t_stimulus_end:
            excit_pop.I_stim = stimulus * strength
        else:
            excit_pop.I_stim = 0. * b2.namp

    # collect data of a subset of neurons:
    spike_monitor_sensory = SpikeMonitor(excit_pop)
    # spike_monitor_high = SpikeMonitor(high_excit_pop)
    b2.run(sim_time)
    return spike_monitor_sensory  #, spike_monitor_high
Ejemplo n.º 7
0
def simulate_brunel_network(
        N_Excit=5000,
        N_Inhib=None,
        N_extern=N_POISSON_INPUT,
        connection_probability=CONNECTION_PROBABILITY_EPSILON,
        w0=SYNAPTIC_WEIGHT_W0,
        g=RELATIVE_INHIBITORY_STRENGTH_G,
        synaptic_delay=SYNAPTIC_DELAY,
        poisson_input_rate=POISSON_INPUT_RATE,
        w_external=None,
        v_rest=V_REST,
        v_reset=V_RESET,
        firing_threshold=FIRING_THRESHOLD,
        membrane_time_scale=MEMBRANE_TIME_SCALE,
        abs_refractory_period=ABSOLUTE_REFRACTORY_PERIOD,
        monitored_subset_size=100,
        random_vm_init=False,
        sim_time=100.*b2.ms):
    """
    Fully parametrized implementation of a sparsely connected network of LIF neurons (Brunel 2000)

    Args:
        N_Excit (int): Size of the excitatory popluation
        N_Inhib (int): optional. Size of the inhibitory population.
            If not set (=None), N_Inhib is set to N_excit/4.
        N_extern (int): optional. Number of presynaptic excitatory poisson neurons. Note: if set to a value,
            this number does NOT depend on N_Excit and NOT depend on connection_probability (this is different
            from the book and paper. Only if N_extern is set to 'None', then N_extern is computed as
            N_Excit*connection_probability.
        connection_probability (float): probability to connect to any of the (N_Excit+N_Inhib) neurons
            CE = connection_probability*N_Excit
            CI = connection_probability*N_Inhib
            Cexternal = N_extern
        w0 (float): Synaptic strength J
        g (float): relative importance of inhibition. J_exc = w0. J_inhib = -g*w0
        synaptic_delay (Quantity): Delay between presynaptic spike and postsynaptic increase of v_m
        poisson_input_rate (Quantity): Poisson rate of the external population
        w_external (float): optional. Synaptic weight of the excitatory external poisson neurons onto all
            neurons in the network. Default is None, in that case w_external is set to w0, which is the
            standard value in the book and in the paper Brunel2000.
            The purpose of this parameter is to see the effect of external input in the
            absence of network feedback(setting w0 to 0mV and w_external>0).
        v_rest (Quantity): Resting potential
        v_reset (Quantity): Reset potential
        firing_threshold (Quantity): Spike threshold
        membrane_time_scale (Quantity): tau_m
        abs_refractory_period (Quantity): absolute refractory period, tau_ref
        monitored_subset_size (int): nr of neurons for which a VoltageMonitor is recording Vm
        random_vm_init (bool): if true, the membrane voltage of each neuron is initialized with a
            random value drawn from Uniform(v_rest, firing_threshold)
        sim_time (Quantity): Simulation time

    Returns:
        (rate_monitor, spike_monitor, voltage_monitor, idx_monitored_neurons)
        PopulationRateMonitor: Rate Monitor
        SpikeMonitor: SpikeMonitor for ALL (N_Excit+N_Inhib) neurons
        StateMonitor: membrane voltage for a selected subset of neurons
        list: index of monitored neurons. length = monitored_subset_size
    """
    if N_Inhib is None:
        N_Inhib = int(N_Excit/4)
    if N_extern is None:
        N_extern = int(N_Excit*connection_probability)
    if w_external is None:
        w_external = w0

    J_excit = w0
    J_inhib = -g*w0

    lif_dynamics = """
    dv/dt = -(v-v_rest) / membrane_time_scale : volt (unless refractory)"""

    network = NeuronGroup(
        N_Excit+N_Inhib, model=lif_dynamics,
        threshold="v>firing_threshold", reset="v=v_reset", refractory=abs_refractory_period,
        method="linear")
    if random_vm_init:
        network.v = random.uniform(v_rest/b2.mV, high=firing_threshold/b2.mV, size=(N_Excit+N_Inhib))*b2.mV
    else:
        network.v = v_rest
    excitatory_population = network[:N_Excit]
    inhibitory_population = network[N_Excit:]

    exc_synapses = Synapses(excitatory_population, target=network, on_pre="v += J_excit", delay=synaptic_delay)
    exc_synapses.connect(p=connection_probability)

    inhib_synapses = Synapses(inhibitory_population, target=network, on_pre="v += J_inhib", delay=synaptic_delay)
    inhib_synapses.connect(p=connection_probability)

    external_poisson_input = PoissonInput(target=network, target_var="v", N=N_extern,
                                          rate=poisson_input_rate, weight=w_external)

    # collect data of a subset of neurons:
    monitored_subset_size = min(monitored_subset_size, (N_Excit+N_Inhib))
    idx_monitored_neurons = sample(range(N_Excit+N_Inhib), monitored_subset_size)
    rate_monitor = PopulationRateMonitor(network)
    # record= some_list is not supported? :-(
    spike_monitor = SpikeMonitor(network, record=idx_monitored_neurons)
    voltage_monitor = StateMonitor(network, "v", record=idx_monitored_neurons)

    b2.run(sim_time)
    return rate_monitor, spike_monitor, voltage_monitor, idx_monitored_neurons
def run_task_hierarchical(task_info, taskdir, tempdir):
    # imports
    from brian2 import defaultclock, set_device, seed, TimedArray, Network, profiling_summary
    from brian2.monitors import SpikeMonitor, PopulationRateMonitor, StateMonitor
    from brian2.synapses import Synapses
    from brian2.core.magic import start_scope
    from brian2.units import second, ms, amp
    from integration_circuit import mk_intcircuit
    from sensory_circuit import mk_sencircuit, mk_sencircuit_2c, mk_sencircuit_2cplastic
    from burstQuant import spks2neurometric
    from scipy import interpolate

    # if you want to put something in the taskdir, you must create it first
    os.mkdir(taskdir)
    print(taskdir)

    # parallel code and flag to start
    set_device('cpp_standalone', directory=tempdir)
    #prefs.devices.cpp_standalone.openmp_threads = max_tasks
    start_scope()

    # simulation parameters
    seedcon = task_info['simulation']['seedcon']
    runtime = task_info['simulation']['runtime']
    runtime_ = runtime / second
    settletime = task_info['simulation']['settletime']
    settletime_ = settletime / second
    stimon = task_info['simulation']['stimon']
    stimoff = task_info['simulation']['stimoff']
    stimoff_ = stimoff / second
    stimdur = stimoff - stimon
    smoothwin = task_info['simulation']['smoothwin']
    nummethod = task_info['simulation']['nummethod']

    # -------------------------------------
    # Construct hierarchical network
    # -------------------------------------
    # set connection seed
    seed(
        seedcon
    )  # set specific seed to test the same network, this way we also have the same synapses!

    # decision circuit
    Dgroups, Dsynapses, Dsubgroups = mk_intcircuit(task_info)
    decE = Dgroups['DE']
    decI = Dgroups['DI']
    decE1 = Dsubgroups['DE1']
    decE2 = Dsubgroups['DE2']

    # sensory circuit, ff and fb connections
    eps = 0.2  # connection probability
    d = 1 * ms  # transmission delays of E synapses
    if task_info['simulation']['2cmodel']:
        if task_info['simulation']['plasticdend']:
            # plasticity rule in dendrites --> FB synapses will be removed from the network!
            Sgroups, Ssynapses, Ssubgroups = mk_sencircuit_2cplastic(task_info)

        else:
            # 2c model (Naud)
            Sgroups, Ssynapses, Ssubgroups = mk_sencircuit_2c(task_info)

        senE = Sgroups['soma']
        dend = Sgroups['dend']
        senI = Sgroups['SI']
        senE1 = Ssubgroups['soma1']
        senE2 = Ssubgroups['soma2']
        dend1 = Ssubgroups['dend1']
        dend2 = Ssubgroups['dend2']

        # FB
        wDS = 0.003  # synaptic weight of FB synapses, 0.0668 nS when scaled by gleakE of sencircuit_2c
        synDE1SE1 = Synapses(decE1,
                             dend1,
                             model='w : 1',
                             method=nummethod,
                             on_pre='x_ea += w',
                             delay=d)
        synDE2SE2 = Synapses(decE2,
                             dend2,
                             model='w : 1',
                             method=nummethod,
                             on_pre='x_ea += w',
                             delay=d)

    else:
        # normal sensory circuit (Wimmer)
        Sgroups, Ssynapses, Ssubgroups = mk_sencircuit(task_info)
        senE = Sgroups['SE']
        senI = Sgroups['SI']
        senE1 = Ssubgroups['SE1']
        senE2 = Ssubgroups['SE2']

        # FB
        wDS = 0.004  # synaptic weight of FB synapses, 0.0668 nS when scaled by gleakE of sencircuit
        synDE1SE1 = Synapses(decE1,
                             senE1,
                             model='w : 1',
                             method=nummethod,
                             on_pre='x_ea += w',
                             delay=d)
        synDE2SE2 = Synapses(decE2,
                             senE2,
                             model='w : 1',
                             method=nummethod,
                             on_pre='x_ea += w',
                             delay=d)

    # feedforward synapses from sensory to integration
    wSD = 0.0036  # synaptic weight of FF synapses, 0.09 nS when scaled by gleakE of intcircuit
    synSE1DE1 = Synapses(senE1,
                         decE1,
                         model='w : 1',
                         method=nummethod,
                         on_pre='g_ea += w',
                         delay=d)
    synSE1DE1.connect(p='eps')
    synSE1DE1.w = 'wSD'
    synSE2DE2 = Synapses(senE2,
                         decE2,
                         model='w : 1',
                         method=nummethod,
                         on_pre='g_ea += w',
                         delay=d)
    synSE2DE2.connect(p='eps')
    synSE2DE2.w = 'wSD'

    # feedback synapses from integration to sensory
    b_fb = task_info['bfb']  # feedback strength, between 0 and 6
    wDS *= b_fb  # synaptic weight of FB synapses, 0.0668 nS when scaled by gleakE of sencircuit
    synDE1SE1.connect(p='eps')
    synDE1SE1.w = 'wDS'
    synDE2SE2.connect(p='eps')
    synDE2SE2.w = 'wDS'

    # -------------------------------------
    # Create stimuli
    # -------------------------------------
    if task_info['stimulus']['replicate']:
        # replicated stimuli across iters()
        np.random.seed(task_info['seed'])  # numpy seed for OU process
    else:
        # every trials has different stimuli
        np.random.seed()
    # Note that in standalone we need to specify np seed because it's not taken care with Brian's seed() function!

    if task_info['simulation']['2cmodel']:
        I0 = task_info['stimulus']['I0s']
        last_muOUd = np.loadtxt("last_muOUd.csv")  # save the mean
    else:
        I0 = task_info['stimulus'][
            'I0']  # mean input current for zero-coherence stim
    c = task_info['c']  # stim coherence (between 0 and 1)
    mu1 = task_info['stimulus'][
        'mu1']  # av. additional input current to senE1 at highest coherence (c=1)
    mu2 = task_info['stimulus'][
        'mu2']  # av. additional input current to senE2 at highest coherence (c=1)
    sigma = task_info['stimulus'][
        'sigma']  # amplitude of temporal modulations of stim
    sigmastim = 0.212 * sigma  # std of modulation of stim inputs
    sigmaind = 0.212 * sigma  # std of modulations in individual inputs
    taustim = task_info['stimulus'][
        'taustim']  # correlation time constant of Ornstein-Uhlenbeck process

    # generate stim from OU process
    N_stim = int(senE1.__len__())
    z1, z2, zk1, zk2 = generate_stim(N_stim, stimdur, taustim)

    # stim2exc
    i1 = I0 * (1 + c * mu1 + sigmastim * z1 + sigmaind * zk1)
    i2 = I0 * (1 + c * mu2 + sigmastim * z2 + sigmaind * zk2)
    stim_dt = 1 * ms
    i1t = np.concatenate((np.zeros((int(stimon / ms), N_stim)), i1.T,
                          np.zeros((int(
                              (runtime - stimoff) / stim_dt), N_stim))),
                         axis=0)
    i2t = np.concatenate((np.zeros((int(stimon / ms), N_stim)), i2.T,
                          np.zeros((int(
                              (runtime - stimoff) / stim_dt), N_stim))),
                         axis=0)
    Irec = TimedArray(np.concatenate((i1t, i2t), axis=1) * amp, dt=stim_dt)

    # -------------------------------------
    # Simulation
    # -------------------------------------
    # set initial conditions (different for evert trial)
    seed()
    decE.g_ea = '0.2 * rand()'
    decI.g_ea = '0.2 * rand()'
    decE.V = '-52*mV + 2*mV * rand()'
    decI.V = '-52*mV + 2*mV * rand()'  # random initialization near 0, prevent an early decision!
    senE.g_ea = '0.05 * (1 + 0.2*rand())'
    senI.g_ea = '0.05 * (1 + 0.2*rand())'
    senE.V = '-52*mV + 2*mV*rand()'  # random initialization near Vt, avoid initial bump!
    senI.V = '-52*mV + 2*mV*rand()'

    if task_info['simulation']['2cmodel']:
        dend.g_ea = '0.05 * (1 + 0.2*rand())'
        dend.V_d = '-72*mV + 2*mV*rand()'
        dend.muOUd = np.tile(last_muOUd, 2) * amp

    # create monitors
    rateDE1 = PopulationRateMonitor(decE1)
    rateDE2 = PopulationRateMonitor(decE2)

    rateSE1 = PopulationRateMonitor(senE1)
    rateSE2 = PopulationRateMonitor(senE2)
    subSE = int(senE1.__len__())
    spksSE = SpikeMonitor(senE[subSE - 100:subSE +
                               100])  # last 100 of SE1 and first 100 of SE2

    # construct network
    net = Network(Dgroups.values(),
                  Dsynapses.values(),
                  Sgroups.values(),
                  Ssynapses.values(),
                  synSE1DE1,
                  synSE2DE2,
                  synDE1SE1,
                  synDE2SE2,
                  rateDE1,
                  rateDE2,
                  rateSE1,
                  rateSE2,
                  spksSE,
                  name='hierarchicalnet')

    # create more monitors for plot
    if task_info['simulation']['pltfig1']:
        # inh
        rateDI = PopulationRateMonitor(decI)
        rateSI = PopulationRateMonitor(senI)

        # spk monitors
        subDE = int(decE1.__len__() * 2)
        spksDE = SpikeMonitor(decE[:subDE])
        spksSE = SpikeMonitor(senE)

        # state mons no more, just the arrays
        stim1 = i1t.T
        stim2 = i2t.T
        stimtime = np.linspace(0, runtime_, stim1.shape[1])

        # construct network
        net = Network(Dgroups.values(),
                      Dsynapses.values(),
                      Sgroups.values(),
                      Ssynapses.values(),
                      synSE1DE1,
                      synSE2DE2,
                      synDE1SE1,
                      synDE2SE2,
                      spksDE,
                      rateDE1,
                      rateDE2,
                      rateDI,
                      spksSE,
                      rateSE1,
                      rateSE2,
                      rateSI,
                      name='hierarchicalnet')

    if task_info['simulation']['plasticdend']:
        # create state monitor to follow muOUd and add it to the networks
        dend_mon = StateMonitor(dend1,
                                variables=['muOUd', 'Ibg', 'g_ea', 'B'],
                                record=True,
                                dt=1 * ms)
        net.add(dend_mon)

        # remove FB synapses!
        net.remove([synDE1SE1, synDE2SE2, Dsynapses.values()])
        print(
            "   FB synapses and synapses of decision circuit are ignored in this simulation!"
        )

    # run hierarchical net
    net.run(runtime, report='stdout', profile=True)
    print(profiling_summary(net=net, show=10))

    # nice plots on cluster
    if task_info['simulation']['pltfig1']:
        plot_fig1b([
            rateDE1, rateDE2, rateDI, spksDE, rateSE1, rateSE2, rateSI, spksSE,
            stim1, stim2, stimtime
        ], smoothwin, taskdir)

    # -------------------------------------
    # Burst quantification
    # -------------------------------------
    events = np.zeros(1)
    bursts = np.zeros(1)
    singles = np.zeros(1)
    spikes = np.zeros(1)
    last_muOUd = np.zeros(1)

    # neurometric params
    dt = spksSE.clock.dt
    validburst = task_info['sen']['2c']['validburst']
    smoothwin_ = smoothwin / second

    if task_info['simulation']['burstanalysis']:

        if task_info['simulation']['2cmodel']:
            last_muOUd = np.array(dend_mon.muOUd[:, -int(1e3):].mean(axis=1))

        if task_info['simulation']['plasticdend']:
            # calculate neurometric info per population
            events, bursts, singles, spikes, isis = spks2neurometric(
                spksSE,
                runtime,
                settletime,
                validburst,
                smoothwin=smoothwin_,
                raster=False)

            # plot & save weigths after convergence
            eta0 = task_info['sen']['2c']['eta0']
            tauB = task_info['sen']['2c']['tauB']
            targetB = task_info['targetB']
            B0 = tauB * targetB
            tau_update = task_info['sen']['2c']['tau_update']
            eta = eta0 * tau_update / tauB
            plot_weights(dend_mon, events, bursts, spikes,
                         [targetB, B0, eta, tauB, tau_update, smoothwin_],
                         taskdir)
            plot_rasters(spksSE, bursts, targetB, isis, runtime_, taskdir)
        else:
            # calculate neurometric per neuron
            events, bursts, singles, spikes, isis = spks2neurometric(
                spksSE,
                runtime,
                settletime,
                validburst,
                smoothwin=smoothwin_,
                raster=True)
            plot_neurometric(events, bursts, spikes, stim1, stim2, stimtime,
                             (settletime_, runtime_), taskdir, smoothwin_)
            plot_isis(isis, bursts, events, (settletime_, runtime_), taskdir)

    # -------------------------------------
    # Choice selection
    # -------------------------------------
    # population rates and downsample
    originaltime = rateDE1.t / second
    interptime = np.linspace(0, originaltime[-1],
                             originaltime[-1] * 100)  # every 10 ms
    fDE1 = interpolate.interp1d(
        originaltime, rateDE1.smooth_rate(window='flat', width=smoothwin))
    fDE2 = interpolate.interp1d(
        originaltime, rateDE2.smooth_rate(window='flat', width=smoothwin))
    fSE1 = interpolate.interp1d(
        originaltime, rateSE1.smooth_rate(window='flat', width=smoothwin))
    fSE2 = interpolate.interp1d(
        originaltime, rateSE2.smooth_rate(window='flat', width=smoothwin))
    rateDE = np.array([f(interptime) for f in [fDE1, fDE2]])
    rateSE = np.array([f(interptime) for f in [fSE1, fSE2]])

    # select the last half second of the stimulus
    newdt = runtime_ / rateDE.shape[1]
    settletimeidx = int(settletime_ / newdt)
    dec_ival = np.array([(stimoff_ - 0.5) / newdt, stimoff_ / newdt],
                        dtype=int)
    who_wins = rateDE[:, dec_ival[0]:dec_ival[1]].mean(axis=1)

    # divide trls into preferred and non-preferred
    pref_msk = np.argmax(who_wins)
    poprates_dec = np.array([rateDE[pref_msk],
                             rateDE[~pref_msk]])  # 0: pref, 1: npref
    poprates_sen = np.array([rateSE[pref_msk], rateSE[~pref_msk]])

    results = {
        'raw_data': {
            'poprates_dec': poprates_dec[:, settletimeidx:],
            'poprates_sen': poprates_sen[:, settletimeidx:],
            'pref_msk': np.array([pref_msk]),
            'last_muOUd': last_muOUd
        },
        'sim_state': np.zeros(1),
        'computed': {
            'events': events,
            'bursts': bursts,
            'singles': singles,
            'spikes': spikes,
            'isis': np.array(isis)
        }
    }

    return results