def simulation(Params):

    #! =================
    #! Import network
    #! =================

    # NEST Kernel and Network settings
    nest.ResetKernel()
    nest.ResetNetwork()
    nest.SetKernelStatus({
        "local_num_threads": Params['threads'],
        'resolution': Params['resolution']
    })
    nest.SetStatus([0], {'print_time': True})

    # import network description
    # import network
    # reload(network)
    # models, layers, conns  = network.get_Network(Params)

    import network_full_keiko
    reload(network_full_keiko)
    models, layers, conns = network_full_keiko.get_Network(Params)

    # Create models
    for m in models:
        nest.CopyModel(m[0], m[1], m[2])

    # Create layers, store layer info in Python variable
    for l in layers:
        exec '%s = tp.CreateLayer(l[1])' % l[0]

    # Create connections, need to insert variable names
    for c in conns:
        eval('tp.ConnectLayers(%s,%s,c[2])' % (c[0], c[1]))

    # --------------------------------------------------------------------#
    # ---------- SET IB NEURONS ----------------------------------------- #
    # --------------------------------------------------------------------#

    # 30% of Cortex L56 excitatory neurons are intrinsically bursting(IB) neuron.
    # That is achieved by setting pacemaker current I_h.
    # So select 30% of L56_exc neuron, and change h_g_peak from 0.0 to 1.0.
    # (Other cortical neuron do not have I_h, thus h_g_peak=0.0)

    L56_vertical_idx = [
        nd for nd in nest.GetLeaves(Vp_vertical)[0]
        if nest.GetStatus([nd], 'model')[0] == 'L56_exc'
    ]
    L56_horizontal_idx = [
        nd for nd in nest.GetLeaves(Vp_horizontal)[0]
        if nest.GetStatus([nd], 'model')[0] == 'L56_exc'
    ]

    num_neuron = len(L56_vertical_idx)
    num_ib = int(num_neuron * 0.3)

    ridx_vertical = np.random.randint(num_neuron, size=(1, num_ib))[0]
    ridx_horizontal = np.random.randint(num_neuron, size=(1, num_ib))[0]

    for i in range(1, num_ib, 1):
        nest.SetStatus([L56_vertical_idx[ridx_vertical[i]]], {'h_g_peak': 1.0})
        nest.SetStatus([L56_horizontal_idx[ridx_horizontal[i]]],
                       {'h_g_peak': 1.0})

    # initiate network activity
    nest.Simulate(500.0)
    #nest.Simulate(100.0)

    #! =================
    #! Recording devices
    #! =================

    nest.CopyModel('multimeter',
                   'RecordingNode',
                   params={
                       'interval':
                       Params['resolution'],
                       'record_from': [
                           'V_m', 'I_syn_AMPA', 'I_syn_NMDA', 'I_syn_GABA_A',
                           'I_syn_GABA_B', 'g_AMPA', 'g_NMDA', 'g_GABAA',
                           'g_GABAB', 'I_h', 'I_NaP', 'I_KNa'
                       ],
                       'record_to': ['memory'],
                       'withgid':
                       True,
                       'withtime':
                       False
                   })

    recorders = []

    nest.CopyModel('multimeter',
                   'RecordingNodeIntrinsic',
                   params={
                       'interval':
                       Params['resolution'],
                       'record_from': [
                           'V_m', 'I_syn_AMPA', 'I_syn_NMDA', 'I_syn_GABA_A',
                           'I_syn_GABA_B', 'g_AMPA', 'g_NMDA', 'g_GABAA',
                           'g_GABAB', 'I_h', 'I_NaP', 'I_KNa'
                       ],
                       'record_to': ['memory'],
                       'withgid':
                       True,
                       'withtime':
                       True
                   })

    recorders2 = []

    for population, model in [(Retina_layer, 'Retina'), (Tp_layer, 'Tp_exc'),
                              (Rp_layer, 'Rp'), (Vp_vertical, 'L23_exc'),
                              (Vp_vertical, 'L23_inh'),
                              (Vp_vertical, 'L4_exc'),
                              (Vp_vertical, 'L56_exc')]:

        rec = nest.Create('RecordingNode')
        recorders.append([rec, population, model])
        if (model == 'Retina'):
            nest.SetStatus(rec, {'record_from': ['rate']})
        tgts = [
            nd for nd in nest.GetLeaves(population)[0]
            if nest.GetStatus([nd], 'model')[0] == model
        ]
        nest.Connect(rec, tgts)

    for population, model in [(Vp_vertical, 'L23_exc')]:
        rec = nest.Create('RecordingNodeIntrinsic')
        recorders2.append([rec, population, model])
        tgts = [
            nd for nd in nest.GetLeaves(population)[0]
            if nest.GetStatus([nd], 'model')[0] == model
        ]
        nest.Connect(rec, tgts)

    #! =================
    #! Spike detector
    #! =================
    detectors = []
    for population, model in [
        (Retina_layer, 'Retina'), (Tp_layer, 'Tp_exc'), (Tp_layer, 'Tp_inh'),
        (Rp_layer, 'Rp'), (Vp_vertical, 'L23_exc'), (Vp_horizontal, 'L23_exc'),
        (Vp_vertical, 'L23_inh'), (Vp_horizontal, 'L23_inh'),
        (Vp_vertical, 'L4_exc'), (Vp_horizontal, 'L4_exc'),
        (Vp_vertical, 'L4_inh'), (Vp_horizontal, 'L4_inh'),
        (Vp_vertical, 'L56_exc'), (Vp_horizontal, 'L56_exc'),
        (Vp_vertical, 'L56_inh'), (Vp_horizontal, 'L56_inh')
    ]:

        rec = nest.Create('spike_detector',
                          params={
                              "withgid": True,
                              "withtime": True
                          })
        #rec = nest.Create('spike_detector')
        detectors.append([rec, population, model])
        tgts = [
            nd for nd in nest.GetLeaves(population)[0]
            if nest.GetStatus([nd], 'model')[0] == model
        ]
        if model == 'Retina':
            for t in tgts:
                try:
                    nest.Connect([t], rec)
                    print('connected %d' % t)
                except:
                    print('%d did not work' % t)
        else:
            nest.Connect(tgts, rec)

    #! ====================
    #! Simulation
    #! ====================

    nest.SetStatus([0], {'print_time': True})
    t_sim = 0

    for t in Params['intervals']:
        if (t_sim == 0):
            gKL = 1.0
            NaP_g_peak = 0.5
            h_g_peak = 1.0
            T_g_peak = 1.0
            KNa_g_peak = 0.5
            I_syn_AMPA_gain = 1.0  # keiko added this parameter in ht_neuron.cpp
            print(t_sim)
        '''
        # Nov23 comment-out
        if (t_sim==1):
            gKL = 1.0 + 0.8/2.0
            NaP_g_peak = 0.5 + 0.75/2.0
            h_g_peak = 1.0 + 1.0/2.0
            T_g_peak = 1.0 + 0.25/2.0
            KNa_g_peak = 0.5 + 0.75/2.0
            I_syn_AMPA_gain = 1.0 + 0.5/2.0 # keiko added this parameter in ht_neuron.cpp
            #I_syn_AMPA_gain = 1.0 + 0.25/2.0 # keiko added this parameter in ht_neuron.cpp
            print(t_sim)
        '''
        if (t_sim == 1):
            gKL = 1.0 + 0.8 * (1.0 / 4.0)
            NaP_g_peak = 0.5 + 0.75 * (1.0 / 4.0)
            h_g_peak = 1.0 + 1.0 * (1.0 / 4.0)
            T_g_peak = 1.0 + 0.25 * (1.0 / 4.0)
            KNa_g_peak = 0.5 + 0.75 * (1.0 / 4.0)
            I_syn_AMPA_gain = 1.0 + 0.25 * (
                1.0 / 4.0)  # keiko added this parameter in ht_neuron.cpp
            #I_syn_AMPA_gain = 1.0 + 0.25/2.0 # keiko added this parameter in ht_neuron.cpp
            print(t_sim)

        if (t_sim == 2):
            gKL = 1.0 + 0.8 * (2.0 / 4.0)
            NaP_g_peak = 0.5 + 0.75 * (2.0 / 4.0)
            h_g_peak = 1.0 + 1.0 * (2.0 / 4.0)
            T_g_peak = 1.0 + 0.25 * (2.0 / 4.0)
            KNa_g_peak = 0.5 + 0.75 * (2.0 / 4.0)
            I_syn_AMPA_gain = 1.0 + 0.25 * (
                2.0 / 4.0)  # keiko added this parameter in ht_neuron.cpp
            #I_syn_AMPA_gain = 1.0 + 0.25/2.0 # keiko added this parameter in ht_neuron.cpp
            print(t_sim)

        if (t_sim == 3):
            gKL = 1.0 + 0.8 * (3.0 / 4.0)
            NaP_g_peak = 0.5 + 0.75 * (3.0 / 4.0)
            h_g_peak = 1.0 + 1.0 * (3.0 / 4.0)
            T_g_peak = 1.0 + 0.25 * (3.0 / 4.0)
            KNa_g_peak = 0.5 + 0.75 * (3.0 / 4.0)
            I_syn_AMPA_gain = 1.0 + 0.25 * (
                3.0 / 4.0)  # keiko added this parameter in ht_neuron.cpp
            #I_syn_AMPA_gain = 1.0 + 0.25/2.0 # keiko added this parameter in ht_neuron.cpp
            print(t_sim)

        if (t_sim == 4):
            gKL = 1.0 + 0.8
            NaP_g_peak = 0.5 + 0.75
            h_g_peak = 1.0 + 1.0
            T_g_peak = 1.0 + 0.25
            KNa_g_peak = 0.5 + 0.75
            I_syn_AMPA_gain = 1.0 + 0.25  # keiko added this parameter in ht_neuron.cpp
            #I_syn_AMPA_gain = 1.0 + 0.25  # keiko added this parameter in ht_neuron.cpp
            print(t_sim)

        t_sim += 1

        # change conductances in all populations
        for l in layers:
            sim_elements = l[1]['elements']
            for m in np.arange(0, np.size(sim_elements), 1):

                if (np.size(sim_elements) == 1):
                    sim_model = sim_elements
                else:
                    sim_model = sim_elements[m]

                exec("la = %s" % l[0])
                pop = [
                    nd for nd in nest.GetLeaves(la)[0]
                    if nest.GetStatus([nd], 'model')[0] == sim_model
                ]
                if (l[0] != 'Retina_layer'):
                    for cell in pop:
                        nest.SetStatus([cell], {'g_KL': gKL})

                        if (nest.GetStatus([cell], 'NaP_g_peak')[0]) > 0.0:
                            nest.SetStatus([cell], {'NaP_g_peak': NaP_g_peak})
                        if (nest.GetStatus([cell], 'h_g_peak')[0]) > 0.0:
                            nest.SetStatus([cell], {'h_g_peak': h_g_peak})
                        if (nest.GetStatus([cell], 'T_g_peak')[0]) > 0.0:
                            nest.SetStatus([cell], {'T_g_peak': T_g_peak})
                        if (nest.GetStatus([cell], 'KNa_g_peak')[0]) > 0.0:
                            nest.SetStatus([cell], {'KNa_g_peak': KNa_g_peak})
                        #if((nest.GetStatus([cell],'I_syn_AMPA_gain')[0])>0.0):
                        #   nest.SetStatus([cell], {'I_syn_AMPA_gain': I_syn_AMPA_gain}) # keiko

                if l[0].__contains__('Vp') or l[0].__contains__('Vs'):
                    #print('%s %s' %(l[0], sim_model))
                    for cell in pop:
                        nest.SetStatus(
                            [cell],
                            {'I_syn_AMPA_gain': I_syn_AMPA_gain})  # keiko

        # simulate interval
        nest.Simulate(t)

    #! ====================
    #! Plot Results
    #! ====================

    print "plotting..."

    rows = 11
    cols = 2

    fig = plt.figure()
    fig.subplots_adjust(hspace=0.4)

    # Plot A: membrane potential rasters

    recorded_models = [(Retina_layer, 'Retina'), (Vp_vertical, 'L23_exc'),
                       (Vp_vertical, 'L4_exc'), (Vp_vertical, 'L56_exc'),
                       (Rp_layer, 'Rp'), (Tp_layer, 'Tp_exc')]

    plotting.potential_raster(fig, recorders, recorded_models, 100,
                              3 * Params['Np'], np.sum(Params['intervals']),
                              Params['resolution'], rows, cols, 0)

    # Plot B: individual intracellular traces

    recorded_models = [(Vp_vertical, 'L23_exc'), (Vp_vertical, 'L23_inh'),
                       (Rp_layer, 'Rp'), (Tp_layer, 'Tp_exc')]

    # original
    #plotting.intracellular_potentials(fig,recorders,recorded_models,100,rows,cols,6)
    # keiko
    total_time = 0.0
    for t in Params['intervals']:
        total_time += t
    plotting.intracellular_potentials(fig, recorders, recorded_models, 100,
                                      rows, cols, 6, total_time)

    # Plot C: topographical activity of the up- and down-states

    recorded_models = [(Vp_vertical, 'L23_exc')]

    labels = ["Upstate"]
    start = 2500.0
    stop = 2510.0
    #start = 900.0
    #stop = 910.0

    plotting.topographic_representation(fig, recorders, recorded_models,
                                        labels, Params['Np'],
                                        np.sum(Params['intervals']),
                                        Params['resolution'], rows, cols,
                                        start, stop, 10, 0)

    labels = ["Downstate"]
    start = 2600.0
    stop = 2610.0
    #start = 1550.0
    #stop = 1560.0

    plotting.topographic_representation(fig, recorders, recorded_models,
                                        labels, Params['Np'],
                                        np.sum(Params['intervals']),
                                        Params['resolution'], rows, cols,
                                        start, stop, 10, 1)

    # Plot D: Intrinsic currents of a selected cell

    recorded_models = [(Vp_vertical, 'L23_exc')]
    plotting.intrinsic_currents(recorders2, recorded_models, 100)
    plotting.synaptic_currents(recorders2, recorded_models, 100)

    plt.show()

    # Plot E: movie

    #labels = ["Osc_Vp_L23_Vertical"]
    #recorded_models = [(Vp_vertical,'L23_exc')]
    #plotting.makeMovie(fig,recorders,recorded_models,labels,Params['Np'],np.sum(Params['intervals']),Params['resolution'])

    #! ====================
    #! Save Results
    #! ====================

    print('save recorders data')
    # Set folder
    rootdir = '/home/kfujii2/newNEST2/ht_model_pablo_based/data/'
    expdir = ''
    # expdir = 'random_full/'
    # expdir = 'structured_full/'
    data_folder = rootdir + expdir
    if not os.path.isdir(data_folder):
        os.makedirs(data_folder)

    # To save spike data, set pairs of population id and its name
    population_name = [{
        'population': Retina_layer,
        'name': 'Retina'
    }, {
        'population': Vp_vertical,
        'name': 'Vp_v'
    }, {
        'population': Vp_horizontal,
        'name': 'Vp_h'
    }, {
        'population': Rp_layer,
        'name': 'Rp'
    }, {
        'population': Tp_layer,
        'name': 'Tp'
    }]

    # vertical
    population = population_name[1]['population']
    name = population_name[1]['name']
    model_list = ['L23_exc', 'L56_exc']
    for model in model_list:
        l = [
            nd for nd in np.arange(0, len(recorders))
            if (recorders[nd][1] == population and recorders[nd][2] == model)
        ][0]
        data = nest.GetStatus(recorders[l][0], keys='events')[0]
        scipy.io.savemat(data_folder + '/recorder_' + name + '_' + model +
                         '.mat',
                         mdict={
                             'senders': data['senders'],
                             'V_m': data['V_m'],
                             'I_syn_AMPA': data['I_syn_AMPA'],
                             'I_syn_NMDA': data['I_syn_NMDA'],
                             'I_syn_GABA_A': data['I_syn_GABA_A'],
                             'I_syn_GABA_B': data['I_syn_GABA_B'],
                             'g_AMPA': data['g_AMPA'],
                             'g_NMDA': data['g_NMDA'],
                             'g_GABAA': data['g_GABAA'],
                             'g_GABAB': data['g_GABAB']
                         })

    print('save raster images')
    plt.close()
    for rec, population, model in detectors:
        spikes = nest.GetStatus(rec, 'events')[0]

        # Get name of population
        for p in range(0, len(population_name), 1):
            if population_name[p]['population'] == population:
                p_name = population_name[p]['name']

        raster = raster_plot.from_device(rec, hist=True)
        pylab.title(p_name + '_' + model)
        f = raster[0].figure
        f.set_size_inches(15, 9)
        f.savefig(data_folder + 'spikes_' + p_name + '_' + model + '.png',
                  dpi=100)
        plt.close()
        '''
        # Set filename and save spike data
        filename = data_folder + 'spike_' + p_name + '_' + model + '.pickle'
        pickle.dump(spikes, open(filename, 'w'))

        filename_AMPA = data_folder + 'connection_' + p_name + '_AMPA_syn' + '.dat'
        filename_NMDA = data_folder + 'connection_' + p_name + '_NMDA_syn' + '.dat'
        filename_GABAA = data_folder + 'connection_' + p_name + '_GABA_A_syn' + '.dat'
        filename_GABAB = data_folder + 'connection_' + p_name + '_GABA_B_syn' + '.dat'
        tp.DumpLayerConnections(population, 'AMPA_syn', filename_AMPA)
        tp.DumpLayerConnections(population, 'NMDA_syn', filename_NMDA)
        tp.DumpLayerConnections(population, 'GABA_A_syn', filename_GABAA)
        tp.DumpLayerConnections(population, 'GABA_B_syn', filename_GABAB)
        '''
    '''
def simulation(Params):

    root_folder = Params['root_folder']
    if not os.path.isdir(root_folder):
        os.makedirs(root_folder)

    net_folder = root_folder + Params['net_folder']
    if not os.path.isdir(net_folder):
        os.makedirs(net_folder)

    data_folder = net_folder + Params['data_folder']
    if not os.path.isdir(data_folder):
        os.makedirs(data_folder)

    #! =================
    #! Import network
    #! =================

    # NEST Kernel and Network settings
    nest.ResetKernel()
    nest.ResetNetwork()
    nest.SetKernelStatus({"local_num_threads": Params['threads'],'resolution': Params['resolution']})
    nest.SetStatus([0],{'print_time': True})

    # initialize random seed
    import time
    # msd = int(round(time.time() * 1000))
    msd = 42
    nest.SetKernelStatus({'grng_seed' : msd})
    # Tom debug
    # nest.SetKernelStatus({'rng_seeds' : range(msd+Params['threads']+1, msd+2*Params['threads']+1)})
    nest.SetKernelStatus({'rng_seeds': range(msd + Params['threads'] + 1, msd + 2 * Params['threads'] + 1)})

    import importlib
    network = importlib.import_module(Params['network'])
    reload(network)
    models, layers, conns  = network.get_Network(Params)
    #import network_full_keiko
    #reload(network_full_keiko)
    # models, layers, conns  = network_full_keiko.get_Network(Params)

    # Create models
    print('Creating models...', end="")
    for m in models:
        print('.', end="")
#        print(m), print('\n')
        nest.CopyModel(m[0], m[1], m[2])
    print(' done.')

    # Create layers, store layer info in Python variable
    print('Creating layers...', end="")
    for l in layers:
        print('.', end="")
        exec '%s = tp.CreateLayer(l[1])' % l[0] in globals(), locals()
    print(' done.')

    # Create connections, need to insert variable names
    print('Creating connectiions...', end="")
    for c in conns:
        print('.', end="")
        eval('tp.ConnectLayers(%s,%s,c[2])' % (c[0], c[1]))
    print(' done.')

    # Check connections
    if Params.has_key('show_center_connectivity_figure') and Params['show_center_connectivity_figure']:

        # this code only gives one element, and you have no control over the
        # model it comes from...
        # tp.PlotTargets(tp.FindCenterElement(Vp_horizontal), Vp_horizontal, 'L56_exc', 'AMPA_syn')
        # tp.PlotTargets(tp.FindCenterElement(Vp_horizontal), Vp_vertical, 'L56_exc', 'AMPA_syn')
        # tp.PlotTargets(tp.FindCenterElement(Vp_vertical), Vp_horizontal, 'L56_exc', 'AMPA_syn')
        # tp.PlotTargets(tp.FindCenterElement(Vp_vertical), Vp_vertical, 'L56_exc', 'AMPA_syn')

        # this way I can get all nodes in the positions, and later filter per Model using GetStatus
        # IMPORTANT: when layer has even number of neurons per line/column
        #            using center (0,0) makes the function return 4 neurons
        #            per postiion since they all have the same distance.
        #            Using (-0,1, 0,1) solves this problem.
        #            When using odd number perhaps this has to change...

        for src_label in ['Tp_layer', 'Vp_vertical', 'Vp_horizontal']:
            for tgt_label in ['Tp_layer', 'Vp_vertical', 'Vp_horizontal']:

                if src_label == 'Tp_layer' and src_label == tgt_label:
                    continue

                print('source population %s' % src_label)
                print('target population %s' % tgt_label)
                n_plot = 0
                f = plt.figure()
                f.canvas.set_window_title('AMPA Connections: %s -> %s' % (src_label, tgt_label))
                all_center = eval('tp.FindNearestElement(%s, (-0.1, 0.1), True)[0]' % src_label)
                for n in all_center:
                    s = nest.GetStatus([n])
                    p = tp.GetPosition([n])
                    # print('%s : (%2.2f, %2.2f)' % (s[0]['model'], p[0][0], p[0][1]))
                    m1 = s[0]['model'].name
                    print('Source neuron model %s' % m1)
                    if m1.find('_exc') > -1:
                        if src_label.find('Tp_') > -1:
                            print( 'found Tp_')
                            # target has to be one of Vp_ or Vs_ models
                            target_models = ['L23_exc', 'L4_exc', 'L56_exc']
                        elif src_label.find('Vp_') > -1 or src_label.find('Vs') > -1:
                            # if target is Vp_ of Vs_ too, then one of those models
                            if tgt_label.find('Vp_') > -1:
                                target_models = ['L23_exc', 'L4_exc', 'L56_exc']
                            elif tgt_label.find('Tp_') > -1:
                                # otherwise it has to be a Tp_target
                                target_models = ['Tp_exc']
                            else:
                                raise ValueError('Invalide target %s for source model: %s' % (tgt_label, src_label))
                        else:
                            raise ValueError('Invalide source model: %s' % (src_label))

                        for m2 in target_models:
                            print('Target neuron model %s' % m2)
                            try:
                                get_targets_command = 'tp.GetTargetNodes([n], %s, m2, "AMPA_syn")[0]' % tgt_label
                                print(get_targets_command)
                                targets = eval(get_targets_command)
                                if len(targets) > 0:
                                    n_plot += 1
                                    f.add_subplot(3,5,n_plot)
                                    eval('tp.PlotTargets([n], %s, m2, "AMPA_syn", f)' % tgt_label)
                                    plt.title('%s -> %s' % (m1, m2), fontsize=9)
                            except:
                                print('didnt work')

                f.savefig(data_folder + '/connectivity_%s_%s.png' % (src_label, tgt_label), dpi=100)


    if Params.has_key('dry_run') and Params['dry_run']:
        print('Only generation, loading and ploting network. No actual simulation done.')
        return

    '''
    # pablo
    # Create vertical grating
    for n in nest.GetLeaves(Retina_layer)[0]:
            retina_0 = (nest.GetLeaves(Retina_layer)[0])[0]
            col = (n-retina_0)/Params['Np']

            cells_per_degree = Params['Np']/Params['visSize']
            cells_per_cycle = cells_per_degree/Params['spatial_frequency']

            nest.SetStatus([n], { "phase": col * 360/(cells_per_cycle-1) })
    '''
    ### keiko
    [nest.SetStatus([n], {"phase": phaseInit(tp.GetPosition([n])[0],
                                             Params["lambda_dg"],
                                             Params["phi_dg"])})
    for n in nest.GetLeaves(Retina_layer)[0]]

    # --------------------------------------------------------------------#
    # ---------- SET IB NEURONS ----------------------------------------- #
    # --------------------------------------------------------------------#

    # 30% of Cortex L56 excitatory neurons are intrinsically bursting(IB) neuron.
    # That is achieved by setting pacemaker current I_h.
    # So select 30% of L56_exc neuron, and change h_g_peak from 0.0 to 1.0.
    # (Other cortical neuron do not have I_h, thus h_g_peak=0.0)

    L56_vertical_idx = [nd for nd in nest.GetLeaves(Vp_vertical)[0] if nest.GetStatus([nd], 'model')[0]=='L56_exc']
    L56_horizontal_idx = [nd for nd in nest.GetLeaves(Vp_horizontal)[0] if nest.GetStatus([nd], 'model')[0]=='L56_exc']

    num_neuron = len(L56_vertical_idx)
    num_ib = int(num_neuron*0.3)

    ridx_vertical = np.random.randint(num_neuron, size=(1,num_ib))[0]
    ridx_horizontal = np.random.randint(num_neuron, size=(1,num_ib))[0]

    for i in range(1,num_ib,1):
        nest.SetStatus([L56_vertical_idx[ridx_vertical[i]]], {'g_peak_h': 1.0})
        nest.SetStatus([L56_horizontal_idx[ridx_horizontal[i]]], {'g_peak_h': 1.0})



    # initiate network activity
    #nest.SetStatus(nest.GetLeaves(Retina_layer)[0], {'rate': Params['ret_rate']})
    nest.SetStatus(nest.GetLeaves(Retina_layer)[0], {'rate': Params['ret_rate']})
    nest.SetStatus(nest.GetLeaves(Retina_layer)[0], {'amplitude': 0.0})
    nest.Simulate(500.0)


    #! =================
    #! Recording devices
    #! =================
    print('Connecting recorders...', end="")
    nest.CopyModel('multimeter', 'RecordingNode',
            params = {'interval'   : Params['resolution'],
            'record_from': ['V_m'],
                            # Put back when plotting synaptic currents, otherwise makes everything slower for no reason
                            # 'I_syn_AMPA',
                            # 'I_syn_NMDA',
                            # 'I_syn_GABA_A',
                            # 'I_syn_GABA_B',
                            # 'g_AMPA',
                            # 'g_NMDA',
                            # 'g_GABA_A',
                            # 'g_GABA_B'],
                            #'I_NaP',
                            #'I_KNa',
                            #'I_T',
                            #'I_h'
                            #]
            'record_to'  : ['memory'],
            'withgid'    : True,
            'withtime'   : True})

    recorders = []
    '''
    for population, model in [(Retina_layer, 'Retina'),
                              (Tp_layer  , 'Tp_exc'),
                              (Tp_layer  , 'Tp_inh'),
                              (Rp_layer  , 'Rp'),
                              (Vp_vertical, 'L23_exc'),
                              (Vp_horizontal, 'L23_exc'),
                              (Vp_vertical, 'L23_inh'),
                              (Vp_horizontal, 'L23_inh'),
                              (Vp_vertical, 'L4_exc'),
                              (Vp_horizontal, 'L4_exc'),
                              (Vp_vertical, 'L4_inh'),
                              (Vp_horizontal, 'L4_inh'),
                              (Vp_vertical, 'L56_exc'),
                              (Vp_horizontal, 'L56_exc'),
                              (Vp_vertical, 'L56_inh'),
                              (Vp_horizontal, 'L56_inh'),
                              (Vs_vertical, 'L23_exc'),
                              (Vs_horizontal, 'L23_exc'),
                              (Vs_vertical, 'L23_inh'),
                              (Vs_horizontal, 'L23_inh'),
                              (Vs_vertical, 'L4_exc'),
                              (Vs_horizontal, 'L4_exc'),
                              (Vs_vertical, 'L4_inh'),
                              (Vs_horizontal, 'L4_inh'),
                              (Vs_vertical, 'L56_exc'),
                              (Vs_horizontal, 'L56_exc'),
                              (Vs_vertical, 'L56_inh'),
                              (Vs_horizontal, 'L56_inh'),
                              (Vs_cross, 'L23_exc'),
                              (Vs_cross, 'L4_exc'),
                              (Vs_cross, 'L4_exc'),


                              ]:
    '''


    for population, model in [(Retina_layer, 'Retina'),
                              (Tp_layer  , 'Tp_exc'),
                              (Rp_layer  , 'Rp'),
                              (Vp_vertical, 'L23_exc'),
                              (Vp_horizontal, 'L23_exc'),
                              (Vp_vertical, 'L23_inh'),
                              (Vp_vertical, 'L4_exc'),
                              (Vp_horizontal, 'L4_exc'),
                              (Vp_vertical, 'L4_inh'),
                              (Vp_vertical, 'L56_exc'),
                              (Vp_horizontal, 'L56_exc'),
                              (Vs_vertical, 'L23_exc'),
                              (Vs_horizontal, 'L23_exc'),
                              (Vs_vertical, 'L4_exc'),
                              (Vs_horizontal, 'L4_exc'),
                              (Vs_vertical, 'L56_exc'),
                              (Vs_horizontal, 'L56_exc'),
                              (Vs_cross, 'L23_exc'),
                              (Vs_cross, 'L4_exc'),
                              (Vs_cross, 'L56_exc'),


                              ]:


        print('.', end="")
        rec = nest.Create('RecordingNode')
        recorders.append([rec,population,model])
        if (model=='Retina'):
            nest.SetStatus(rec,{'record_from': ['rate']})
        tgts = [nd for nd in nest.GetLeaves(population)[0] if nest.GetStatus([nd], 'model')[0]==model]
        #nest.Connect(rec, tgts, None, {'delay': recorders_delay})
        nest.Connect(rec, tgts)
    print('done.')

    #! =================
    #! Spike detector
    #! =================
    print('Connecting detectors...', end="")
    detectors = []
    '''
    for population, model in [(Retina_layer, 'Retina'),
                              (Tp_layer  , 'Tp_exc'),
                              (Tp_layer  , 'Tp_inh'),
                              (Rp_layer  , 'Rp'),
                              (Vp_vertical, 'L23_exc'),
                              (Vp_horizontal, 'L23_exc'),
                              (Vp_vertical, 'L23_inh'),
                              (Vp_horizontal, 'L23_inh'),
                              (Vp_vertical, 'L4_exc'),
                              (Vp_horizontal, 'L4_exc'),
                              (Vp_vertical, 'L4_inh'),
                              (Vp_horizontal, 'L4_inh'),
                              (Vp_vertical, 'L56_exc'),
                              (Vp_horizontal, 'L56_exc'),
                              (Vp_vertical, 'L56_inh'),
                              (Vp_horizontal, 'L56_inh'),
                              (Vs_vertical, 'L23_exc'),
                              (Vs_horizontal, 'L23_exc'),
                              (Vs_vertical, 'L23_inh'),
                              (Vs_horizontal, 'L23_inh'),
                              (Vs_vertical, 'L4_exc'),
                              (Vs_horizontal, 'L4_exc'),
                              (Vs_vertical, 'L4_inh'),
                              (Vs_horizontal, 'L4_inh'),
                              (Vs_vertical, 'L56_exc'),
                              (Vs_horizontal, 'L56_exc'),
                              (Vs_vertical, 'L56_inh'),
                              (Vs_horizontal, 'L56_inh')]:
        '''


    #Tom
    for population, model in [(Retina_layer, 'Retina'),
                              (Tp_layer, 'Tp_exc'),
                              (Tp_layer, 'Tp_inh'),
                              (Vp_vertical, 'L23_exc'),
                              (Vp_vertical, 'L4_exc'),
                              (Vp_vertical, 'L56_exc'),
                              (Vp_vertical, 'L23_inh'),
                              (Vp_vertical, 'L4_inh'),
                              (Vp_vertical, 'L56_inh'),
                              (Vs_vertical, 'L23_exc'),
                              (Vs_vertical, 'L23_inh'),
                              (Vs_vertical, 'L4_exc'),
                              (Vs_vertical, 'L4_inh'),
                              (Vs_vertical, 'L56_exc'),
                              (Vs_vertical, 'L56_inh')]:



        print('.', end="")
        rec = nest.Create('spike_detector', params={"withgid": True, "withtime": True})
        #rec = nest.Create('spike_detector')
        detectors.append([rec,population,model])
        tgts = [nd for nd in nest.GetLeaves(population)[0] if nest.GetStatus([nd], 'model')[0]==model]
        if model == 'Retina':
            for t in tgts:
                try:
                    # nest.Connect([t], rec, None, {'delay':  recorders_delay})
                    nest.Connect([t], rec)
                    print('connected %d' % t)
                except:
                    print('%d did not work' % t)
        else:
            # nest.Connect(tgts, rec, None, {'delay': recorders_delay})
            nest.Connect(tgts, rec)
    print('done.')


    #! ====================
    #! Simulation
    #! ====================
    '''
    # change gKL to 0.8 in all populations (necessary to get a little stronger evoked response)
    for l in layers:
            sim_elements = l[1]['elements']
            for m in np.arange(0,np.size(sim_elements),1):

                    if(np.size(sim_elements)==1):
                        sim_model = sim_elements
                    else:
                        sim_model = sim_elements[m]

                    exec("la = %s" % l[0])
                    pop = [nd for nd in nest.GetLeaves(la)[0] if nest.GetStatus([nd], 'model')[0]==sim_model]
                    if (l[0]!='Retina_layer'):
                            for cell in pop:
                                    nest.SetStatus([cell], {'g_KL':0.8})
    '''
    # Simulate
    for t in Params['intervals']:

        #if (t == 250.0):  # Stimulus ON
        #    # if (t == 1500.0):  # Stimulus ON
        #    nest.SetStatus(nest.GetLeaves(Retina_layer)[0], {'amplitude': 45.0})
        #else:  # Stimulus OFF
        #    nest.SetStatus(nest.GetLeaves(Retina_layer)[0], {'amplitude': 0.0})

        if Params['input_flag']==True:
            nest.SetStatus(nest.GetLeaves(Retina_layer)[0], {'amplitude': Params['ret_rate']})
        else:
            nest.SetStatus(nest.GetLeaves(Retina_layer)[0], {'amplitude': 0.0})

        nest.Simulate(t)



    #! ====================
    #! Plot Results
    #! ====================

    print("Creating figure 3...")

    rows = 9
    cols = 2

    fig = plt.figure(num=None, figsize=(13, 24), dpi=100)
    fig.subplots_adjust(hspace=0.4)

    # Plot A: membrane potential rasters

    recorded_models = [(Retina_layer,'Retina'),
                        (Vp_vertical,'L23_exc'),
                        (Vp_vertical,'L4_exc'),
                        (Vp_vertical,'L56_exc'),
                        (Rp_layer,'Rp'),
                        (Tp_layer,'Tp_exc')]

    #plotting.potential_raster(fig,recorders,recorded_models,0,Params['Np'],np.sum(Params['intervals']),Params['resolution'],rows,cols,0)
    plotting.potential_raster(fig,recorders,recorded_models,0,Params['Np'],
                              np.sum(Params['intervals']),
                              Params['resolution'],
                              rows,cols,0)
    #starting_neuron = 800+1
    #plotting.potential_raster(fig,recorders,recorded_models,starting_neuron,Params['Np'],np.sum(Params['intervals']),Params['resolution'],rows,cols,0)

    plt.title('Evoked')

    # Plot B: individual intracellular traces

    recorded_models =[(Vp_vertical,'L4_exc'),
                      (Vp_vertical,'L4_inh')]

    #plotting.intracellular_potentials(fig, recorders, recorded_models, 21, rows, cols, 6) #original
    # keiko
    total_time = 0.0
    for t in Params['intervals']:
        total_time += t

    #draw_neuron = (Params['Np']*Params['Np']/2)
    #plotting.intracellular_potentials(fig, recorders, recorded_models, draw_neuron, rows, cols, 6, total_time)
    plotting.intracellular_potentials(fig, recorders, recorded_models, 21, rows, cols, 6, total_time)
    #plotting.intracellular_potentials(fig, recorders, recorded_models, 820, rows, cols, 6, total_time)

    # Plot C: topographical activity of the vertical and horizontal layers


    if Params.has_key('start_membrane_potential') and  Params.has_key('end_membrane_potential'):
        start = Params['start_membrane_potential']
        stop = Params['end_membrane_potential']
    else:
        start = 130.0
        stop = 140.0

    recorded_models = [(Vp_vertical,'L23_exc')]
    labels = ["Vertical"]
    plotting.topographic_representation(fig,
                                        recorders,
                                        recorded_models,
                                        labels,
                                        Params['Np'],
                                        np.sum(Params['intervals']),
                                        Params['resolution'],
                                        rows,
                                        cols,
                                        start,
                                        stop,
                                        8,
                                        0)

    recorded_models = [(Vp_horizontal,'L23_exc')]

    labels = ["Horizontal"]

    plotting.topographic_representation(fig,recorders,recorded_models,labels,Params['Np'],np.sum(Params['intervals']),Params['resolution'],rows,cols,start,stop,8,1)

    if Params.has_key('figure_title'):
        fig.suptitle(Params['figure_title'], size = 20)

    fig.savefig(data_folder + '/figure3.png', dpi=100)

    if Params.has_key('show_main_figure') and Params['show_main_figure']:
        plt.show()


    # Plot D: movie

    #labels = ["Evoked_Vp_L23_Vertical","Evoked_Vp_L23_Horizontal"]
    #recorded_models = [(Vp_vertical,'L23_exc'),(Vp_horizontal,'L23_exc')]
    #plotting.makeMovie(fig,recorders,recorded_models,labels,Params['Np'],np.sum(Params['intervals']),Params['resolution'])



    # Plot F: All areas


    if Params.has_key('plot_all_regions') and Params['plot_all_regions']:

        print("Creating plot of all cortical areas")

        #First column
        vertical_models = [(Retina_layer,'Retina'),
                        (Vp_vertical,'L23_exc'),
                        (Vp_vertical,'L4_exc'),
                        (Vp_vertical,'L56_exc'),
                        (Vs_vertical,'L23_exc'),
                        (Vs_vertical, 'L4_exc'),
                        (Vs_vertical, 'L56_exc')]
        #Second column
        horizontal_models = [(Retina_layer,'Retina'),
                        (Vp_horizontal,'L23_exc'),
                        (Vp_horizontal,'L4_exc'),
                        (Vp_horizontal,'L56_exc'),
                        (Vs_horizontal,'L23_exc'),
                        (Vs_horizontal, 'L4_exc'),
                        (Vs_horizontal, 'L56_exc')]
        #Third column
        cross_models = [(Retina_layer,'Retina'),
                        (),
                        (),
                        (),
                        (Vs_cross,'L23_exc'),
                        (Vs_cross, 'L4_exc'),
                        (Vs_cross, 'L56_exc')]

        #Column labels
        labels = ['Vertical', 'Horizontal', 'Cross']

        #Row labels
        areas = ['Retina', 'Primary\nL2/3', 'Primary\nL4', 'Primary\nL5/6', 'Secondary\nL2/3', 'Secondary\nL4', 'Secondary\nL4/6']

        plotcols = [vertical_models, horizontal_models, cross_models]


        fig = plotting.potential_raster_multiple_models(fig, recorders, plotcols, labels, areas, 0, Params['Np'],
                                                  np.sum(Params['intervals']),
                                                  Params['resolution'],
                                                  0)

        fig.savefig(data_folder + '/figure_all_areas.png', dpi=100)







    #! ====================
    #! Save Results
    #! ====================

    print('save recorders data')
    # Set folder
    #rootdir = '/home/kfujii2/newNEST2/ht_model_pablo_based/data/'
    #expdir = 'random/'
    # expdir = 'random_full/'
    # expdir = 'structured_full/'
    # data_folder = rootdir + expdir

    # To save spike data, set pairs of population id and its name
    population_name = [ {'population': Retina_layer, 'name': 'Retina'},
                        {'population': Vp_vertical, 'name': 'Vp_v'},
                        {'population': Vp_horizontal, 'name': 'Vp_h'},
                        {'population': Rp_layer, 'name': 'Rp'},
                        {'population': Tp_layer, 'name': 'Tp'},
                        {'population': Vs_vertical, 'name': 'Vs_v'},
                        {'population': Vs_horizontal, 'name': 'Vs_h'}]

    if Params.has_key('save_recorders') and Params['save_recorders']:
        for rec, population, model in recorders:

            # Get name of population
            for p in range(0, len(population_name), 1):
                if population_name[p]['population'] == population:
                    p_name = population_name[p]['name']

            data = nest.GetStatus(rec)[0]['events']

            if model == 'Retina':
                scipy.io.savemat(data_folder + '/recorder_' + p_name + '_' + model + '.mat',
                                 mdict={'senders': data['senders'],
                                        'rate': data['rate']})
            else:
                scipy.io.savemat(data_folder + '/recorder_' + p_name + '_' + model + '.mat',
                                 mdict={'senders': data['senders'],
                                        'times': data['times'],
                                        'V_m': data['V_m'] #,
                                        #'I_syn_AMPA': data['I_syn_AMPA'],
                                        #'I_syn_NMDA': data['I_syn_NMDA'],
                                        #'I_syn_GABA_A': data['I_syn_GABA_A'],
                                        #'I_syn_GABA_B': data['I_syn_GABA_B'],
                                        # 'g_AMPA': data['g_AMPA'],
                                        # 'g_NMDA': data['g_NMDA'],
                                        # 'g_GABA_A': data['g_GABA_A'],
                                        # 'g_GABA_B': data['g_GABA_B']
                                        } )



    print('save raster images')
    plt.close()
    for rec, population, model in detectors:
        spikes = nest.GetStatus(rec, 'events')[0]

        # Get name of population
        for p in range(0, len(population_name), 1):
            if population_name[p]['population'] == population:
                p_name = population_name[p]['name']

        if len(nest.GetStatus(rec)[0]['events']['senders']) > 3:
            raster = raster_plot.from_device(rec, hist=True)
            pylab.title( p_name + '_' + model )
            f = raster[0].figure
            f.set_size_inches(15, 9)
            f.savefig(data_folder + '/spikes_' + p_name + '_' + model + '.png', dpi=100)
            plt.close()

            # Set filename and save spike data
            filename = data_folder + '/spike_' + p_name + '_' + model + '.pickle'
            pickle.dump(spikes, open(filename, 'w'))
            scipy.io.savemat(data_folder + '/spike_' + p_name + '_' + model + '.mat', mdict={'senders': spikes['senders'], 'times': spikes['times']})

            '''
            filename_AMPA = data_folder + 'connection_' + p_name + '_AMPA_syn' + '.dat'
            filename_NMDA = data_folder + 'connection_' + p_name + '_NMDA_syn' + '.dat'
            filename_GABAA = data_folder + 'connection_' + p_name + '_GABA_A_syn' + '.dat'
            filename_GABAB = data_folder + 'connection_' + p_name + '_GABA_B_syn' + '.dat'
            tp.DumpLayerConnections(population, 'AMPA_syn', filename_AMPA)
            tp.DumpLayerConnections(population, 'NMDA_syn', filename_NMDA)
            tp.DumpLayerConnections(population, 'GABA_A_syn', filename_GABAA)
            tp.DumpLayerConnections(population, 'GABA_B_syn', filename_GABAB)
            '''
    '''
    for p in range(0, len(population_name), 1):

        population = population_name[p]['population']
        p_name = population_name[p]['name']
        filename_nodes = data_folder + '/gid_' + p_name + '.dat'

        tp.DumpLayerNodes(population, filename_nodes)
    '''

    network_script = Params['network'] + '.py'
    shutil.copy2(network_script, data_folder + '/' + network_script)

    print('end')
def simulation(Params):

    root_folder = Params['root_folder']
    if not os.path.isdir(root_folder):
        os.makedirs(root_folder)

    net_folder = root_folder + Params['net_folder']
    if not os.path.isdir(net_folder):
        os.makedirs(net_folder)

    conn_folder = net_folder + '/connections'
    if not os.path.isdir(conn_folder):
        os.makedirs(conn_folder)

    data_folder = net_folder + Params['data_folder']
    if not os.path.isdir(data_folder):
        os.makedirs(data_folder)

    #! =================
    #! Import network
    #! =================

    # NEST Kernel and Network settings
    nest.ResetKernel()
    nest.ResetNetwork()
    nest.SetKernelStatus({"local_num_threads": Params['threads'],'resolution': Params['resolution']})
    nest.SetStatus([0],{'print_time': True})

    # initialize random seed
    import time
    msd = int(round(time.time() * 1000))
    nest.SetKernelStatus({'grng_seed' : msd})
    # Tom debug
    # nest.SetKernelStatus({'rng_seeds' : range(msd+Params['threads']+1, msd+2*Params['threads']+1)})
    nest.SetKernelStatus({'rng_seeds': range(msd + Params['threads'] + 1, msd + 2 * Params['threads'] + 1)})

    import importlib
    network = importlib.import_module(Params['network'])
    reload(network)
    models, layers, conns  = network.get_Network(Params)
    #import network_full_keiko
    #reload(network_full_keiko)
    # models, layers, conns  = network_full_keiko.get_Network(Params)

    # TODO this should come from network file
    synapse_models = ['AMPA_syn', 'NMDA_syn', 'GABA_A_syn', 'GABA_B_syn', 'reticular_projection']
    # synapse_models = ['AMPA_syn', 'NMDA_syn', 'GABA_A_syn', 'GABA_B_syn']

    # Create models
    print('Creating models...', end="")
    for m in models:
        print('.', end="")
#        print(m), print('\n')
        nest.CopyModel(m[0], m[1], m[2])
    print(' done.')

    # Create layers, store layer info in Python variable
    print('Creating layers...', end="")
    for l in layers:
        print('.', end="")
        exec '%s = tp.CreateLayer(l[1])' % l[0] in globals(), locals()
    print(' done.')

    # now either create brand new connections, or load connectivity files from
    # connections_file
    connections_file =  conn_folder + '/connections.pickle'

    # assume alread runned before, and it is going to load connections and layers
    if Params.has_key('load_connections') and Params['load_connections']:

        if not os.path.isfile(connections_file):
            raise IOError('File with connections was never created: %s' % connections_file)

        print('Loading connections...', end="")
        with open(connections_file) as f:
            (pre, post_intact, post_scrambled, w, d, syn) = pickle.load(f)
        print(' done.')

        if Params['scrambled']:
            post = post_scrambled
        else:
            post = post_intact

        print('Connecting neurons...', end="")
        con_dict = {'rule': 'one_to_one'}
        for (pi, ti, wi, di, syni) in zip(pre, post, w, d, syn):
            print('.', end="")
            # print(syni)

            syn_dict = {"model": syni,
                        'weight': wi,
                        'delay': di
                        }
            nest.Connect(pi, ti, con_dict, syn_dict)
        print(' done.')

        # print('Connection retina...', end="")
        # # Create connections, need to insert variable names
        # for c in conns:
        #     if c[0]=='Retina_layer':
        #         eval('tp.ConnectLayers(%s,%s,c[2])' % (c[0], c[1]))
        # print('done.')

    else:
        # Create connections, need to insert variable names
        print('Creating connections...', end="")
        for c in conns:
            if Params['Np'] < 40:
                print('%s -> %s' % (c[0], c[1]))
                c[2]['allow_oversized_mask'] = True
            else:
                print('.', end="")
            eval('tp.ConnectLayers(%s,%s,c[2])' % (c[0], c[1]))
        print(' done.')

    if Params.has_key('dump_connections') and Params['dump_connections']:

        import glob

        # First dump all nodes and connections to files
        for l in layers:
            print('dumping connections for %s' % l[0])
            eval("tp.DumpLayerNodes(%s, conn_folder + '/nodes_%s.dump')" % (l[0], l[0]) )
            for synapse in synapse_models:
                 eval("tp.DumpLayerConnections(%s, '%s', conn_folder + '/connections_%s_%s.dump')" % (l[0], synapse, l[0], synapse) )

        # Now load all nodes, and mark which physical layer they belong to
        all_nodes_files = glob.glob(conn_folder + "/nodes_*.dump")
        if len(all_nodes_files) < 1:
            raise ValueError('No files save for this configuration. First '
                             'run with load_connection = False')

        pop_nodes = [None] * len(all_nodes_files)
        pop_names = [None] * len(all_nodes_files)
        perm_pop_nodes = [None] * len(all_nodes_files)
        for (idx, pop_file) in enumerate(all_nodes_files):

            population = pop_file[pop_file.find('nodes_')+6:-5]
            pop_names[idx] = population
            print('Loading nodes for population %s' % population)
            pop_nodes[idx] = np.loadtxt(pop_file)

            # identify physical layers
            n_layer = 0
            n_nodes = pop_nodes[idx].shape[0]
            layers = np.zeros((n_nodes,1))
            for i_line in range(n_nodes):
                if pop_nodes[idx][i_line, 1] == -3.9 and pop_nodes[idx][i_line, 2] == 3.9:
                    n_layer += 1
                layers[i_line] = n_layer
            pop_nodes[idx] = np.append(pop_nodes[idx], layers, 1)

        # Finally, load connections and save a big vector for each one of the 5
        # parameters needed by nest.Connect: pre, post, w, d, and synapse_model
        # Save unmodified and scrambled versions in network.pickle

        all_conn_files = glob.glob(conn_folder + "/connections_*.dump")

        pre = []
        post_intact = []
        post_scrambled = []
        w = []
        d = []
        syn = []
        for (idx, pop_conn_file) in enumerate(all_conn_files):

            population = pop_conn_file[pop_conn_file.find('connections_')+12:-5]
            print('Scrambling connections for %s (%d out of %d files)' % (population, idx+1, len(all_conn_files)))

            synapse_model = [s for i,s in enumerate(synapse_models) if s in population][0]

            print('Loading file')
            pop_conns = np.loadtxt(pop_conn_file)
            tn_lines = pop_conns.shape[0]

            if tn_lines > 0:

                syn.append(synapse_model)

                pre.append(pop_conns[:,0].astype(int))
                post_intact.append(pop_conns[:,1].astype(int))
                w.append(pop_conns[:,2])
                d.append(pop_conns[:,3].astype(int))

                # Do the actual scrfambling
                # TODO this should be optimized, it is way too slow
                if any(w == population[0:2] for w in ['Vs', 'Vp']):
                    print('Scrambling...', end="")
                    for i_line in range(tn_lines):
                        if not i_line % round(tn_lines/10.):
                            print('%d%%, ' % (round(100.*i_line/tn_lines) if i_line > 0 else 0), end="")

                        for (i_pop, this_pop) in enumerate(pop_nodes):
                            t_idx = np.where(this_pop[:,0] == pop_conns[i_line, 1])[0]
                            if t_idx.size:
                                break
                        if not t_idx.size:
                            raise ValueError('Could not find tartget %s for node %s' % (pop_conns[i_line, 1], pop_conns[i_line, 0]))
                        if len(t_idx) > 1:
                            raise ValueError('Target %s apears in more than one population' % (pop_conns[i_line, 1], pop_conns[i_line, 0]))
                        new_t_idx = t_idx[0]

                        # For the moment, only scramble connections within the visual cortex
                        if any(w == pop_names[i_pop][0:2] for w in ['Vs', 'Vp']):
                            possible_targets = pop_nodes[i_pop][pop_nodes[i_pop][:,3] == pop_nodes[i_pop][new_t_idx,3], 0]
                            pop_conns[i_line, 1] = np.random.permutation(possible_targets)[0]

                print('done.')

                post_scrambled.append(pop_conns[:,1].astype(int))

        # save results
        print('Saving results...', end="")
        with open(connections_file, 'w') as f:
            pickle.dump((pre, post_intact, post_scrambled, w, d, syn), f)
        print(' done.')

    if Params.has_key('show_V4_num_conn_figure') and Params['show_V4_num_conn_figure']:

        horizontal_nodes = nest.GetLeaves(Vp_horizontal, properties={'model': 'L4_exc'}, local_only=True)[0]
        vertical_nodes = nest.GetLeaves(Vp_vertical, properties={'model': 'L4_exc'}, local_only=True)[0]

        n_conns_hor = []
        for (idx, horizontal_node) in enumerate(horizontal_nodes):
            tgt_map = []
            this_conns = nest.GetConnections([horizontal_node], horizontal_nodes, synapse_model='AMPA_syn')
            tgt_map.extend([conn[1] for conn in this_conns])
            n_conns_hor.append(len(tgt_map))

        plt.figure()
        plt.hist(n_conns_hor, range(0, max(n_conns_hor + [30])))
        plt.title('# of connections Vp(h) L4pyr -> Vp(h) L4Pyr')

        n_conns_hor = []
        for (idx, horizontal_node) in enumerate(horizontal_nodes):
            tgt_map = []
            this_conns = nest.GetConnections([horizontal_node], vertical_nodes, synapse_model='AMPA_syn')
            tgt_map.extend([conn[1] for conn in this_conns])
            n_conns_hor.append(len(tgt_map))

            # nest.DisconnectOneToOne(tp_node, tgt_map[0], {"synapse_model": "AMPA_syn"})
            #nest.Disconnect([tp_node], tgt_map, 'one_to_one', {"synapse_model": "AMPA_syn"})

        plt.figure()
        plt.hist(n_conns_hor, range(0, max(n_conns_hor + [30])))
        plt.title('# of connections Vp(h) L4pyr -> Vp(v) L4Pyr')

        n_conns_ver = []
        for (idx, vertical_node) in enumerate(vertical_nodes):
            tgt_map = []
            this_conns = nest.GetConnections([vertical_node], vertical_nodes, synapse_model='AMPA_syn')
            tgt_map.extend([conn[1] for conn in this_conns])
            n_conns_ver.append(len(tgt_map))

        plt.figure()
        plt.hist(n_conns_ver, range(0, max(n_conns_ver + [30])))
        plt.title('# of connections Vp(v) L4pyr -> Vp(v) L4Pyr')

        n_conns_ver = []
        for (idx, vertical_node) in enumerate(vertical_nodes):
            tgt_map = []
            this_conns = nest.GetConnections([vertical_node], horizontal_nodes, synapse_model='AMPA_syn')
            tgt_map.extend([conn[1] for conn in this_conns])
            n_conns_ver.append(len(tgt_map))

        plt.figure()
        plt.hist(n_conns_ver, range(0, max(n_conns_ver + [30])))
        plt.title('# of connections Vp(v) L4pyr -> Vp(h) L4Pyr')

        plt.show()

    # Check connections


    if Params.has_key('show_center_connectivity_figure') and Params['show_center_connectivity_figure']:

        # this code only gives one element, and you have no control over the
        # model it comes from...
        # tp.PlotTargets(tp.FindCenterElement(Vp_horizontal), Vp_horizontal, 'L56_exc', 'AMPA_syn')
        # tp.PlotTargets(tp.FindCenterElement(Vp_horizontal), Vp_vertical, 'L56_exc', 'AMPA_syn')
        # tp.PlotTargets(tp.FindCenterElement(Vp_vertical), Vp_horizontal, 'L56_exc', 'AMPA_syn')
        # tp.PlotTargets(tp.FindCenterElement(Vp_vertical), Vp_vertical, 'L56_exc', 'AMPA_syn')

        # this way I can get all nodes in the positions, and later filter per Model using GetStatus
        # IMPORTANT: when layer has even number of neurons per line/column
        #            using center (0,0) makes the function return 4 neurons
        #            per postiion since they all have the same distance.
        #            Using (-0,1, 0,1) solves this problem.
        #            When using odd number perhaps this has to change...

        for src_label in ['Tp_layer', 'Vp_vertical', 'Vp_horizontal']:
            for tgt_label in ['Tp_layer', 'Vp_vertical', 'Vp_horizontal']:

                if src_label == 'Tp_layer' and src_label == tgt_label:
                    continue

                print('source population %s' % src_label)
                print('target population %s' % tgt_label)
                n_plot = 0
                f = plt.figure()
                f.canvas.set_window_title('AMPA Connections: %s -> %s' % (src_label, tgt_label))
                all_center = eval('tp.FindNearestElement(%s, (-0.1, 0.1), True)[0]' % src_label)
                for n in all_center:
                    s = nest.GetStatus([n])
                    p = tp.GetPosition([n])
                    # print('%s : (%2.2f, %2.2f)' % (s[0]['model'], p[0][0], p[0][1]))
                    m1 = s[0]['model'].name
                    print('Source neuron model %s' % m1)
                    if m1.find('_exc') > -1:
                        if src_label.find('Tp_') > -1:
                            print( 'found Tp_')
                            # target has to be one of Vp_ or Vs_ models
                            target_models = ['L23_exc', 'L4_exc', 'L56_exc']
                        elif src_label.find('Vp_') > -1 or src_label.find('Vs') > -1:
                            # if target is Vp_ of Vs_ too, then one of those models
                            if tgt_label.find('Vp_') > -1:
                                target_models = ['L23_exc', 'L4_exc', 'L56_exc']
                            elif tgt_label.find('Tp_') > -1:
                                # otherwise it has to be a Tp_target
                                target_models = ['Tp_exc']
                            else:
                                raise ValueError('Invalide target %s for source model: %s' % (tgt_label, src_label))
                        else:
                            raise ValueError('Invalide source model: %s' % (src_label))

                        for m2 in target_models:
                            print('Target neuron model %s' % m2)
                            try:
                                get_targets_command = 'tp.GetTargetNodes([n], %s, m2, "AMPA_syn")[0]' % tgt_label
                                print(get_targets_command)
                                targets = eval(get_targets_command)
                                if len(targets) > 0:
                                    n_plot += 1
                                    f.add_subplot(3,5,n_plot)
                                    eval('tp.PlotTargets([n], %s, m2, "AMPA_syn", f)' % tgt_label)
                                    plt.title('%s -> %s' % (m1, m2), fontsize=9)
                            except:
                                print('didnt work')

                f.savefig(data_folder + '/connectivity_%s_%s.png' % (src_label, tgt_label), dpi=100)

    if Params.has_key('show_V4_connectivity_figure') and Params['show_V4_connectivity_figure']:

        Vp_hor_gids = tp.GetElement(Vp_horizontal, [0,0])
        n_Vp_hor = len(Vp_hor_gids)

        f = []
        for idx in range(n_Vp_hor):
            f.append(plt.figure())

        positions = range(0,41,10)
        positions[-1] -= 1
        for xi in range(len(positions)):
            for yi in range(len(positions)):
                print("Position [%d,%d] : %d" %(xi,yi,yi*(len(positions))+xi+1))
                x = positions[xi]
                y = positions[yi]
                Vp_hor_gids = tp.GetElement(Vp_horizontal, [x,y])
                Vp_hor_status = nest.GetStatus(Vp_hor_gids)
                for (idx, n) in enumerate(Vp_hor_status):
                    if n['Tau_theta'] == 2.0:
                        print(idx)
                        try:
                            f[idx].add_subplot(len(positions), len(positions), yi*(len(positions))+xi+1)
                            tp.PlotTargets([Vp_hor_gids[idx]], Vp_horizontal, 'L4_exc', 'AMPA_syn', f[idx])
                        except:
                            print('%i bad' % Vp_hor_gids[idx])
        plt.show()

    if Params.has_key('dry_run') and Params['dry_run']:
        print('Only generation, loading and ploting network. No actual simulation done.')
        return

    '''
    # pablo
    # Create vertical grating
    for n in nest.GetLeaves(Retina_layer)[0]:
            retina_0 = (nest.GetLeaves(Retina_layer)[0])[0]
            col = (n-retina_0)/Params['Np']

            cells_per_degree = Params['Np']/Params['visSize']
            cells_per_cycle = cells_per_degree/Params['spatial_frequency']

            nest.SetStatus([n], { "phase": col * 360/(cells_per_cycle-1) })
    '''
    ### keiko
    if Params['lambda_dg'] >= 0:
        [nest.SetStatus([n], {"phase": phaseInit(tp.GetPosition([n])[0],
                                                 Params["lambda_dg"],
                                                 Params["phi_dg"])})
        for n in nest.GetLeaves(Retina_layer)[0]]
    else:
        # Leonardo: Random retina input
        [nest.SetStatus([n], {"phase": phaseInit(tp.GetPosition([n])[0],
                                                 np.pi * np.random.rand(),
                                                 np.pi * np.random.rand())})
         for n in nest.GetLeaves(Retina_layer)[0]]


    # --------------------------------------------------------------------#
    # ---------- SET IB NEURONS ----------------------------------------- #
    # --------------------------------------------------------------------#

    # 30% of Cortex L56 excitatory neurons are intrinsically bursting(IB) neuron.
    # That is achieved by setting pacemaker current I_h.
    # So select 30% of L56_exc neuron, and change h_g_peak from 0.0 to 1.0.
    # (Other cortical neuron do not have I_h, thus h_g_peak=0.0)

    L56_vertical_idx = [nd for nd in nest.GetLeaves(Vp_vertical)[0] if nest.GetStatus([nd], 'model')[0]=='L56_exc']
    L56_horizontal_idx = [nd for nd in nest.GetLeaves(Vp_horizontal)[0] if nest.GetStatus([nd], 'model')[0]=='L56_exc']

    num_neuron = len(L56_vertical_idx)
    num_ib = int(num_neuron*0.3)

    ridx_vertical = np.random.randint(num_neuron, size=(1,num_ib))[0]
    ridx_horizontal = np.random.randint(num_neuron, size=(1,num_ib))[0]

    for i in range(1,num_ib,1):
        nest.SetStatus([L56_vertical_idx[ridx_vertical[i]]], {'g_peak_h': 1.0})
        nest.SetStatus([L56_horizontal_idx[ridx_horizontal[i]]], {'g_peak_h': 1.0})



    # initiate network activity
    #nest.SetStatus(nest.GetLeaves(Retina_layer)[0], {'rate': Params['ret_rate']})
    nest.SetStatus(nest.GetLeaves(Retina_layer)[0], {'rate': Params['ret_rate']})
    nest.SetStatus(nest.GetLeaves(Retina_layer)[0], {'amplitude': 0.0})
    nest.Simulate(500.0)


    #! =================
    #! Recording devices
    #! =================
    print('Connecting recorders...', end="")
    nest.CopyModel('multimeter', 'RecordingNode',
            params = {'interval'   : Params['resolution'],
            'record_from': ['V_m'],#,
                            # Put back when plotting synaptic currents, otherwise makes everything slower for no reason
                            # 'I_syn_AMPA',
                            # 'I_syn_NMDA',
                            # 'I_syn_GABA_A',
                            # 'I_syn_GABA_B',
                            # 'g_AMPA',
                            # 'g_NMDA',
                            # 'g_GABA_A',
                            # 'g_GABA_B'],
                            #'I_NaP',
                            #'I_KNa',
                            #'I_T',
                            #'I_h'
                            #]
            'record_to'  : ['memory'],
            'withgid'    : True,
            'withtime'   : True})

    recorders = []
    '''
    for population, model in [(Retina_layer, 'Retina'),
                              (Tp_layer  , 'Tp_exc'),
                              (Tp_layer  , 'Tp_inh'),
                              (Rp_layer  , 'Rp'),
                              (Vp_vertical, 'L23_exc'),
                              (Vp_horizontal, 'L23_exc'),
                              (Vp_vertical, 'L23_inh'),
                              (Vp_horizontal, 'L23_inh'),
                              (Vp_vertical, 'L4_exc'),
                              (Vp_horizontal, 'L4_exc'),
                              (Vp_vertical, 'L4_inh'),
                              (Vp_horizontal, 'L4_inh'),
                              (Vp_vertical, 'L56_exc'),
                              (Vp_horizontal, 'L56_exc'),
                              (Vp_vertical, 'L56_inh'),
                              (Vp_horizontal, 'L56_inh'),
                              (Vs_vertical, 'L23_exc'),
                              (Vs_horizontal, 'L23_exc'),
                              (Vs_vertical, 'L23_inh'),
                              (Vs_horizontal, 'L23_inh'),
                              (Vs_vertical, 'L4_exc'),
                              (Vs_horizontal, 'L4_exc'),
                              (Vs_vertical, 'L4_inh'),
                              (Vs_horizontal, 'L4_inh'),
                              (Vs_vertical, 'L56_exc'),
                              (Vs_horizontal, 'L56_exc'),
                              (Vs_vertical, 'L56_inh'),
                              (Vs_horizontal, 'L56_inh')]:
    '''
    # for population, model in [(Retina_layer, 'Retina'),
    #                           (Tp_layer  , 'Tp_exc'),
    #                           (Tp_layer  , 'Tp_inh'),
    #                           (Vp_vertical, 'L4_exc'),
    #                           (Vp_vertical, 'L4_inh'),
    #                           (Vp_horizontal, 'L4_exc'),
    #                           (Vp_vertical, 'L23_exc'),
    #                           (Vp_horizontal, 'L23_exc'),
    #                           (Vp_vertical, 'L56_exc'),
    #                           (Rp_layer, 'Rp')]:
    for population, model in [(Retina_layer, 'Retina'),
                              # (Tp_layer  , 'Tp_exc'),
                              # (Tp_layer  , 'Tp_inh'),
                              (Vp_vertical, 'L4_inh'),
                              (Vp_horizontal, 'L4_exc'),
                              (Vp_horizontal, 'L23_exc'),
                              # (Rp_layer, 'Rp'),
                              (Vp_vertical, 'L23_exc'),
                              (Vp_vertical, 'L4_exc'),
                              (Vp_vertical, 'L56_exc'),
                              (Vs_vertical, 'L23_exc'),
                              (Vs_vertical, 'L4_exc'),
                              (Vs_vertical, 'L56_exc'),

                              ]:


        print('.', end="")
        rec = nest.Create('RecordingNode')
        recorders.append([rec,population,model])
        if (model=='Retina'):
            nest.SetStatus(rec,{'record_from': ['rate']})
        tgts = [nd for nd in nest.GetLeaves(population)[0] if nest.GetStatus([nd], 'model')[0]==model]
        #nest.Connect(rec, tgts, None, {'delay': recorders_delay})
        nest.Connect(rec, tgts)
    print('done.')

    #! =================
    #! Spike detector
    #! =================
    print('Connecting detectors...', end="")
    detectors = []
    '''
    for population, model in [(Retina_layer, 'Retina'),
                              (Tp_layer  , 'Tp_exc'),
                              (Tp_layer  , 'Tp_inh'),
                              (Rp_layer  , 'Rp'),
                              (Vp_vertical, 'L23_exc'),
                              (Vp_horizontal, 'L23_exc'),
                              (Vp_vertical, 'L23_inh'),
                              (Vp_horizontal, 'L23_inh'),
                              (Vp_vertical, 'L4_exc'),
                              (Vp_horizontal, 'L4_exc'),
                              (Vp_vertical, 'L4_inh'),
                              (Vp_horizontal, 'L4_inh'),
                              (Vp_vertical, 'L56_exc'),
                              (Vp_horizontal, 'L56_exc'),
                              (Vp_vertical, 'L56_inh'),
                              (Vp_horizontal, 'L56_inh'),
                              (Vs_vertical, 'L23_exc'),
                              (Vs_horizontal, 'L23_exc'),
                              (Vs_vertical, 'L23_inh'),
                              (Vs_horizontal, 'L23_inh'),
                              (Vs_vertical, 'L4_exc'),
                              (Vs_horizontal, 'L4_exc'),
                              (Vs_vertical, 'L4_inh'),
                              (Vs_horizontal, 'L4_inh'),
                              (Vs_vertical, 'L56_exc'),
                              (Vs_horizontal, 'L56_exc'),
                              (Vs_vertical, 'L56_inh'),
                              (Vs_horizontal, 'L56_inh')]:
        '''
    '''
    for population, model in [(Retina_layer, 'Retina'),
                              (Tp_layer  , 'Tp_exc'),
                              (Tp_layer  , 'Tp_inh'),
                              (Vp_vertical, 'L23_exc'),
                              (Vp_horizontal, 'L23_exc'),
                              (Vp_vertical, 'L4_exc'),
                              (Vp_horizontal, 'L4_exc')]:
        '''

    #Tom
    for population, model in [(Retina_layer, 'Retina'),
                              # (Tp_layer, 'Tp_exc'),
                              # (Tp_layer, 'Tp_inh'),
                              (Vp_vertical, 'L23_exc'),
                              (Vp_vertical, 'L4_exc'),
                              (Vp_vertical, 'L56_exc'),
                              (Vp_vertical, 'L23_inh'),
                              (Vp_vertical, 'L4_inh'),
                              (Vp_vertical, 'L56_inh'),
                              (Vs_vertical, 'L23_exc'),
                              (Vs_vertical, 'L23_inh'),
                              (Vs_vertical, 'L4_exc'),
                              (Vs_vertical, 'L4_inh'),
                              (Vs_vertical, 'L56_exc'),
                              (Vs_vertical, 'L56_inh')]:



        print('.', end="")
        rec = nest.Create('spike_detector', params={"withgid": True, "withtime": True})
        #rec = nest.Create('spike_detector')
        detectors.append([rec,population,model])
        tgts = [nd for nd in nest.GetLeaves(population)[0] if nest.GetStatus([nd], 'model')[0]==model]
        if model == 'Retina':
            for t in tgts:
                try:
                    # nest.Connect([t], rec, None, {'delay':  recorders_delay})
                    nest.Connect([t], rec)
                    print('connected %d' % t)
                except:
                    print('%d did not work' % t)
        else:
            # nest.Connect(tgts, rec, None, {'delay': recorders_delay})
            nest.Connect(tgts, rec)
    print('done.')


    #! ====================
    #! Simulation
    #! ====================
    '''
    # change gKL to 0.8 in all populations (necessary to get a little stronger evoked response)
    for l in layers:
            sim_elements = l[1]['elements']
            for m in np.arange(0,np.size(sim_elements),1):

                    if(np.size(sim_elements)==1):
                        sim_model = sim_elements
                    else:
                        sim_model = sim_elements[m]

                    exec("la = %s" % l[0])
                    pop = [nd for nd in nest.GetLeaves(la)[0] if nest.GetStatus([nd], 'model')[0]==sim_model]
                    if (l[0]!='Retina_layer'):
                            for cell in pop:
                                    nest.SetStatus([cell], {'g_KL':0.8})
    '''
    # Simulate
    for t in Params['intervals']:

        #if (t == 250.0):  # Stimulus ON
        #    # if (t == 1500.0):  # Stimulus ON
        #    nest.SetStatus(nest.GetLeaves(Retina_layer)[0], {'amplitude': 45.0})
        #else:  # Stimulus OFF
        #    nest.SetStatus(nest.GetLeaves(Retina_layer)[0], {'amplitude': 0.0})

        if Params['input_flag']==True:
            nest.SetStatus(nest.GetLeaves(Retina_layer)[0], {'amplitude': Params['ret_rate']})
        else:
            nest.SetStatus(nest.GetLeaves(Retina_layer)[0], {'amplitude': 0.0})

        nest.Simulate(t)



    #! ====================
    #! Plot Results
    #! ====================

    print("Creating figure 3...")

    rows = 9
    cols = 2

    fig = plt.figure(num=None, figsize=(13, 24), dpi=100)
    fig.subplots_adjust(hspace=0.4)

    # Plot A: membrane potential rasters

    recorded_models = [(Retina_layer,'Retina'),
                        (Vp_vertical,'L23_exc'),
                        (Vp_vertical,'L4_exc'),
                        (Vp_vertical,'L56_exc'),
                        (Vs_vertical,'L23_exc'),
                        (Vs_vertical,'L4_exc')]

    #plotting.potential_raster(fig,recorders,recorded_models,0,Params['Np'],np.sum(Params['intervals']),Params['resolution'],rows,cols,0)
    plotting.potential_raster(fig,recorders,recorded_models,0,Params['Np'],
                              np.sum(Params['intervals']),
                              Params['resolution'],
                              rows,cols,0)
    #starting_neuron = 800+1
    #plotting.potential_raster(fig,recorders,recorded_models,starting_neuron,Params['Np'],np.sum(Params['intervals']),Params['resolution'],rows,cols,0)

    plt.title('Evoked')

    # Plot B: individual intracellular traces

    recorded_models =[(Vp_vertical,'L4_exc'),
                      (Vp_vertical,'L4_inh')]

    #plotting.intracellular_potentials(fig, recorders, recorded_models, 21, rows, cols, 6) #original
    # keiko
    total_time = 0.0
    for t in Params['intervals']:
        total_time += t

    #draw_neuron = (Params['Np']*Params['Np']/2)
    #plotting.intracellular_potentials(fig, recorders, recorded_models, draw_neuron, rows, cols, 6, total_time)
    plotting.intracellular_potentials(fig, recorders, recorded_models, 21, rows, cols, 6, total_time)
    #plotting.intracellular_potentials(fig, recorders, recorded_models, 820, rows, cols, 6, total_time)

    # Plot C: topographical activity of the vertical and horizontal layers


    if Params.has_key('start_membrane_potential') and  Params.has_key('end_membrane_potential'):
        start = Params['start_membrane_potential']
        stop = Params['end_membrane_potential']
    else:
        start = 130.0
        stop = 140.0

    recorded_models = [(Vp_vertical,'L23_exc')]
    labels = ["Vertical"]
    plotting.topographic_representation(fig,
                                        recorders,
                                        recorded_models,
                                        labels,
                                        Params['Np'],
                                        np.sum(Params['intervals']),
                                        Params['resolution'],
                                        rows,
                                        cols,
                                        start,
                                        stop,
                                        8,
                                        0)

    recorded_models = [(Vp_horizontal,'L23_exc')]

    labels = ["Horizontal"]

    plotting.topographic_representation(fig,recorders,recorded_models,labels,Params['Np'],np.sum(Params['intervals']),Params['resolution'],rows,cols,start,stop,8,1)

    fig.savefig(data_folder + '/figure3.png', dpi=100)

    if Params.has_key('show_main_figure') and Params['show_main_figure']:
        plt.show()


    # Plot D: movie

    #labels = ["Evoked_Vp_L23_Vertical","Evoked_Vp_L23_Horizontal"]
    #recorded_models = [(Vp_vertical,'L23_exc'),(Vp_horizontal,'L23_exc')]
    #plotting.makeMovie(fig,recorders,recorded_models,labels,Params['Np'],np.sum(Params['intervals']),Params['resolution'])


    #! ====================
    #! Save Results
    #! ====================

    print('save recorders data')
    # Set folder
    #rootdir = '/home/kfujii2/newNEST2/ht_model_pablo_based/data/'
    #expdir = 'random/'
    # expdir = 'random_full/'
    # expdir = 'structured_full/'
    # data_folder = rootdir + expdir

    # To save spike data, set pairs of population id and its name
    population_name = [ {'population': Retina_layer, 'name': 'Retina'},
                        {'population': Vp_vertical, 'name': 'Vp_v'},
                        {'population': Vp_horizontal, 'name': 'Vp_h'},
                        # {'population': Rp_layer, 'name': 'Rp'},
                        # {'population': Tp_layer, 'name': 'Tp'},
                        {'population': Vs_vertical, 'name': 'Vs_v'},
                        {'population': Vs_horizontal, 'name': 'Vs_h'}]

    if Params.has_key('save_recorders') and Params['save_recorders']:
        for rec, population, model in recorders:

            # Get name of population
            for p in range(0, len(population_name), 1):
                if population_name[p]['population'] == population:
                    p_name = population_name[p]['name']

            data = nest.GetStatus(rec)[0]['events']

            if model == 'Retina':
                scipy.io.savemat(data_folder + '/recorder_' + p_name + '_' + model + '.mat',
                                 mdict={'senders': data['senders'],
                                        'rate': data['rate']})
            else:
                scipy.io.savemat(data_folder + '/recorder_' + p_name + '_' + model + '.mat',
                                 mdict={'senders': data['senders'],
                                        'times': data['times'],
                                        'V_m': data['V_m'],
                                        #'I_syn_AMPA': data['I_syn_AMPA'],
                                        #'I_syn_NMDA': data['I_syn_NMDA'],
                                        #'I_syn_GABA_A': data['I_syn_GABA_A'],
                                        #'I_syn_GABA_B': data['I_syn_GABA_B'],
                                        # 'g_AMPA': data['g_AMPA'],
                                        # 'g_NMDA': data['g_NMDA'],
                                        # 'g_GABA_A': data['g_GABA_A'],
                                        # 'g_GABA_B': data['g_GABA_B']
                                        } )



    print('save raster images')
    plt.close()
    for rec, population, model in detectors:
        spikes = nest.GetStatus(rec, 'events')[0]

        # Get name of population
        for p in range(0, len(population_name), 1):
            if population_name[p]['population'] == population:
                p_name = population_name[p]['name']

        if len(nest.GetStatus(rec)[0]['events']['senders']) > 3:
            raster = raster_plot.from_device(rec, hist=True)
            pylab.title( p_name + '_' + model )
            f = raster[0].figure
            f.set_size_inches(15, 9)
            f.savefig(data_folder + '/spikes_' + p_name + '_' + model + '.png', dpi=100)
            plt.close()

            # Set filename and save spike data
            filename = data_folder + '/spike_' + p_name + '_' + model + '.pickle'
            pickle.dump(spikes, open(filename, 'w'))
            scipy.io.savemat(data_folder + '/spike_' + p_name + '_' + model + '.mat', mdict={'senders': spikes['senders'], 'times': spikes['times']})

            '''
            filename_AMPA = data_folder + 'connection_' + p_name + '_AMPA_syn' + '.dat'
            filename_NMDA = data_folder + 'connection_' + p_name + '_NMDA_syn' + '.dat'
            filename_GABAA = data_folder + 'connection_' + p_name + '_GABA_A_syn' + '.dat'
            filename_GABAB = data_folder + 'connection_' + p_name + '_GABA_B_syn' + '.dat'
            tp.DumpLayerConnections(population, 'AMPA_syn', filename_AMPA)
            tp.DumpLayerConnections(population, 'NMDA_syn', filename_NMDA)
            tp.DumpLayerConnections(population, 'GABA_A_syn', filename_GABAA)
            tp.DumpLayerConnections(population, 'GABA_B_syn', filename_GABAB)
            '''
    '''
    for p in range(0, len(population_name), 1):

        population = population_name[p]['population']
        p_name = population_name[p]['name']
        filename_nodes = data_folder + '/gid_' + p_name + '.dat'

        tp.DumpLayerNodes(population, filename_nodes)
    '''

    network_script = Params['network'] + '.py'
    shutil.copy2(network_script, data_folder + '/' + network_script)
    shutil.copy2(network_script, conn_folder + '/' + network_script)

    print('end')
def simulation(Params):

    root_folder = Params['root_folder']
    if not os.path.isdir(root_folder):
        os.makedirs(root_folder)

    net_folder = root_folder + Params['net_folder']
    if not os.path.isdir(net_folder):
        os.makedirs(net_folder)

    conn_folder = net_folder + '/connections'
    if not os.path.isdir(conn_folder):
        os.makedirs(conn_folder)

    data_folder = net_folder + Params['data_folder']
    if not os.path.isdir(data_folder):
        os.makedirs(data_folder)

    #! =================
    #! Import network
    #! =================

    # NEST Kernel and Network settings
    nest.ResetKernel()
    nest.ResetNetwork()
    nest.SetKernelStatus({"local_num_threads": Params['threads'],'resolution': Params['resolution']})
    nest.SetStatus([0],{'print_time': True})

    # initialize random seed
    import time
    msd = int(round(time.time() * 1000))
    nest.SetKernelStatus({'grng_seed' : msd})
    nest.SetKernelStatus({'rng_seeds' : range(msd+Params['threads']+1, msd+2*Params['threads']+1)})

    import importlib
    network = importlib.import_module(Params['network'])
    reload(network)
    models, layers, conns  = network.get_Network(Params)


    # TODO this should come from network file
    synapse_models = ['AMPA_syn', 'NMDA_syn', 'GABA_A_syn', 'GABA_B_syn', 'reticular_projection']
    # synapse_models = ['AMPA_syn', 'NMDA_syn', 'GABA_A_syn', 'GABA_B_syn']

    # Create models
    print('Creating models...', end="")
    for m in models:
        print('.', end="")
#        print(m), print('\n')
        nest.CopyModel(m[0], m[1], m[2])
    print(' done.')

    # Create layers, store layer info in Python variable
    print('Creating layers...', end="")
    for l in layers:
        print('.', end="")
        exec '%s = tp.CreateLayer(l[1])' % l[0] in globals(), locals()
    print(' done.')

    # Create connections, need to insert variable names
    print('Creating connections...', end="")
    for c in conns:
        print('.', end="")
        eval('tp.ConnectLayers(%s,%s,c[2])' % (c[0], c[1]))
    print(' done.')


    # --------------------------------------------------------------------#
    # ---------- SET IB NEURONS ----------------------------------------- #
    # --------------------------------------------------------------------#

    print('Set IB neurons')
    # 30% of Cortex L56 excitatory neurons are intrinsically bursting(IB) neuron.
    # That is achieved by setting pacemaker current I_h.
    # So select 30% of L56_exc neuron, and change h_g_peak from 0.0 to 1.0.
    # (Other cortical neuron do not have I_h, thus h_g_peak=0.0)

    L56_vertical_idx = [nd for nd in nest.GetLeaves(Vp_vertical)[0] if nest.GetStatus([nd], 'model')[0]=='L56_exc']
    L56_horizontal_idx = [nd for nd in nest.GetLeaves(Vp_horizontal)[0] if nest.GetStatus([nd], 'model')[0]=='L56_exc']

    num_neuron = len(L56_vertical_idx)
    num_ib = int(num_neuron*0.3)

    ridx_vertical = np.random.randint(num_neuron, size=(1,num_ib))[0]
    ridx_horizontal = np.random.randint(num_neuron, size=(1,num_ib))[0]

    for i in range(1,num_ib,1):
        nest.SetStatus([L56_vertical_idx[ridx_vertical[i]]], {'g_peak_h': 1.0})
        nest.SetStatus([L56_horizontal_idx[ridx_horizontal[i]]], {'g_peak_h': 1.0})







    # --------------------------------------------------------------------#
    # ---------- SET RETINA STATIC FIRING RATE -------------------------- #
    # --------------------------------------------------------------------#
    print('Set Retina inputs neurons')
    if not Params['new_image']: #Read
        with open(Params['image_folder']+Params['image_name']+'.pickle', 'rb') as handle:
            image_dic = pickle.load(handle)
    else:
        image_dic = static_input_utils.create_default_image(Params['new_image_elements'], Params['Np'])
        if not Params['image_name']=='':
            static_input_utils.save_new_image_dic(Params['image_folder'] + Params['image_name'], image_dic)

    luminances = image_dic['luminances']
    fig = plt.figure()
    plt.imshow(luminances, interpolation='nearest')
    fig.savefig(data_folder + '/input_image.png', dpi=100)


    if not np.shape(luminances) == (Params['Np'], Params['Np']):
        raise ValueError('Wrong definition for the input image %s' % (Params['image_folder']+Params['image_name']))

    # For each 'pixel' (retina neuron) we set the rate of the poisson generator to maxrate * ret_rate + minrate
    #if 'automatic_min_rate', minrate is determined so that mean retinal activity is mean_rate
    #Iterate over indices of image.
    if Params['automatic_min_rate']:
        N_on = np.sum(luminances)
        N_tot = (Params['Np'] ** 2)
        minrate = (N_tot * Params['mean_rate'] - N_on * Params['ret_rate'] )/ ( N_tot - N_on)
    else:
        minrate = Params['ret_rate_baseline']

    for i in range(Params['Np']):
        for j in range(Params['Np']):
            #Get node, set corresponding luminance
            currnode = tp.GetElement(Retina_layer, (j, i))[0] #NB: Because of the inconsistency of the GetElement function we have to transpose.
            if luminances[i,j] > 0.:
                nest.SetStatus([currnode], {"rate": Params['ret_rate']})
            else:
                nest.SetStatus([currnode], {"rate": minrate})



     # --------------------------------------------------------------------#
     # ---------------------------- INITIATE  ---------------------------- #
     # --------------------------------------------------------------------#
    print('Simulate %i secs' % Params['initiation_time'])
    nest.Simulate(Params['initiation_time'])



    #! =================
    #! Recording devices
    #! =================
    print('Connecting recorders...', end="")
    nest.CopyModel('multimeter', 'RecordingNode',
            params = {'interval'   : Params['resolution'],
            'record_from': ['V_m'
                            # Put back when plotting synaptic currents, otherwise makes everything slower for no reason
                            # 'I_syn_AMPA',
                            # 'I_syn_NMDA',
                            # 'I_syn_GABA_A',
                            # 'I_syn_GABA_B',
                            #'g_AMPA',
                            #'g_NMDA',
                            #'g_GABAA',
                            #'g_GABAB',
                            #'I_NaP',
                            #'I_KNa',
                            #'I_T',
                            #'I_h'
                            ],
            'record_to'  : ['memory'],
            'withgid'    : True,
            'withtime'   : True})

    recorders = []
    for population, model in [(Retina_layer, 'Retina'),
                              (Tp_layer  , 'Tp_exc'),
                              (Rp_layer  , 'Rp'),
                              (Vp_vertical, 'L23_exc'),
                              (Vp_horizontal, 'L23_exc'),
                              (Vp_vertical, 'L23_inh'),
                              (Vp_vertical, 'L4_exc'),
                              (Vp_horizontal, 'L4_exc'),
                              (Vp_vertical, 'L4_inh'),
                              (Vp_vertical, 'L56_exc'),
                              (Vp_horizontal, 'L56_exc'),
                              (Vs_vertical, 'L23_exc'),
                              (Vs_horizontal, 'L23_exc'),
                              (Vs_vertical, 'L4_exc'),
                              (Vs_horizontal, 'L4_exc'),
                              (Vs_vertical, 'L56_exc'),
                              (Vs_horizontal, 'L56_exc'),
                              (Vs_cross, 'L23_exc'),
                              (Vs_cross, 'L4_exc'),
                              (Vs_cross, 'L56_exc'),


                              ]:
        rec = nest.Create('RecordingNode')
        recorders.append([rec,population,model])
        if (model=='Retina'):
            nest.SetStatus(rec,{'record_from': ['rate']})
        tgts = [nd for nd in nest.GetLeaves(population)[0] if nest.GetStatus([nd], 'model')[0]==model]
        nest.Connect(rec, tgts)
    print('done.')

    #! =================
    #! Spike detector
    #! =================
    print('Connecting detectors...', end="")
    detectors = []
    retina_failed_detectors = []
    for population, model in [(Retina_layer, 'Retina'),
                              (Tp_layer  , 'Tp_exc'),
                              (Tp_layer  , 'Tp_inh'),
                              (Vp_vertical, 'L4_exc'),
                              (Vp_horizontal, 'L4_exc'),
                              (Vs_cross, 'L4_exc')]:

        rec = nest.Create('spike_detector', params={"withgid": True, "withtime": True})
        #rec = nest.Create('spike_detector')
        detectors.append([rec,population,model])
        tgts = [nd for nd in nest.GetLeaves(population)[0] if nest.GetStatus([nd], 'model')[0]==model]
        if model == 'Retina':
            for t in tgts:
                try:
                    # nest.Connect([t], rec, None, {'delay':  recorders_delay})
                    nest.Connect([t], rec)
                    #print('connected %d' % t)
                except:
                    print('%d did not work' % t)
                    retina_failed_detectors.append(t)
        else:
            nest.Connect(tgts, rec)

    sg = [nd for nd in nest.GetLeaves(Retina_layer)[0] if nest.GetStatus([nd], 'model')[0] == 'Retina']






    #! ====================
    #! Simulation
    #! ====================
    # Simulate
    for t in Params['intervals']:

        # TODO: useless as is
        # if Params['input_flag']==True:
        #     nest.SetStatus(nest.GetLeaves(Retina_layer)[0], {'amplitude': Params['ret_rate']})
        # else:
        #     nest.SetStatus(nest.GetLeaves(Retina_layer)[0], {'amplitude': 0.0})

        nest.Simulate(t)



    #! ====================
    #! Plot Results
    #! ====================

    print("Creating figure 3...")

    rows = 9
    cols = 2

    #Tom: We plot temporal data for the column to which the vertical line in the image is presented
    #nest.GetLeaves() numbers the elements starting top left and descending vertically.
    # Therefore starting_neuron (given to plotting.potential_rater) must be the index of the node in the first row.
    # starting_neuron = 0 plots the first column, starting_neuron = 40 the second, etc
    vertical_bar_column = image_dic['vertical'][1]
    starting_neuron_Vp = Params['Np']*vertical_bar_column




    fig = plt.figure(num=None, figsize=(13, 24), dpi=100)
    fig.subplots_adjust(hspace=0.4)

    # Plot A: membrane potential rasters

    recorded_models = [(Retina_layer,'Retina'),
                        (Vp_vertical,'L23_exc'),
                        (Vp_vertical,'L4_exc'),
                        (Vp_vertical,'L56_exc'),
                        (Rp_layer,'Rp'),
                        (Tp_layer,'Tp_exc')]

    #plotting.potential_raster(fig,recorders,recorded_models,0,Params['Np'],np.sum(Params['intervals']),Params['resolution'],rows,cols,0)
    plotting.potential_raster(fig,recorders,recorded_models,starting_neuron_Vp,Params['Np'],
                              np.sum(Params['intervals']),
                              Params['resolution'],
                              rows,cols,0)
    #starting_neuron = 800+1
    #plotting.potential_raster(fig,recorders,recorded_models,starting_neuron,Params['Np'],np.sum(Params['intervals']),Params['resolution'],rows,cols,0)

    plt.title('Evoked')

    # Plot B: individual intracellular traces

    recorded_models =[(Vp_vertical,'L4_exc'),
                      (Vp_vertical,'L4_inh')]

    #plotting.intracellular_potentials(fig, recorders, recorded_models, 21, rows, cols, 6) #original
    # keiko
    total_time = 0.0
    for t in Params['intervals']:
        total_time += t

    #draw_neuron = (Params['Np']*Params['Np']/2)
    #plotting.intracellular_potentials(fig, recorders, recorded_models, draw_neuron, rows, cols, 6, total_time)
    plotting.intracellular_potentials(fig, recorders, recorded_models, 21, rows, cols, 6, total_time)
    #plotting.intracellular_potentials(fig, recorders, recorded_models, 820, rows, cols, 6, total_time)

    # Plot C: topographical activity of the vertical and horizontal layers


    if Params.has_key('start_membrane_potential') and  Params.has_key('end_membrane_potential'):
        start = Params['start_membrane_potential']
        stop = Params['end_membrane_potential']
    else:
        start = 130.0
        stop = 140.0

    recorded_models = [(Vp_vertical,'L23_exc')]
    labels = ["Vertical"]
    plotting.topographic_representation(fig,
                                        recorders,
                                        recorded_models,
                                        labels,
                                        Params['Np'],
                                        np.sum(Params['intervals']),
                                        Params['resolution'],
                                        rows,
                                        cols,
                                        start,
                                        stop,
                                        8,
                                        0)

    recorded_models = [(Vp_horizontal,'L23_exc')]

    labels = ["Horizontal"]

    plotting.topographic_representation(fig,recorders,recorded_models,labels,Params['Np'],np.sum(Params['intervals']),Params['resolution'],rows,cols,start,stop,8,1)

    fig.savefig(data_folder + '/figure3.png', dpi=100)

    if Params.has_key('show_main_figure') and Params['show_main_figure']:
        plt.show()







    # Plot C: topographical activity of all layers

    if Params.has_key('plot_topo_all_regions') and Params['plot_topo_all_regions']:

        if Params.has_key('start_membrane_potential') and Params.has_key('end_membrane_potential'):
            start = Params['start_membrane_potential']
            stop = Params['end_membrane_potential']
        else:
            start = 130.0
            stop = 140.0

        ####### USER INPUT

        # First column
        vertical_models = [(Retina_layer, 'Retina'),
                           (Vp_vertical, 'L23_exc'),
                           (Vp_vertical, 'L4_exc'),
                           (Vp_vertical, 'L56_exc'),
                           (Vs_vertical, 'L23_exc'),
                           (Vs_vertical, 'L4_exc'),
                           (Vs_vertical, 'L56_exc')]
        # Second column
        horizontal_models = [(Retina_layer, 'Retina'),
                             (Vp_horizontal, 'L23_exc'),
                             (Vp_horizontal, 'L4_exc'),
                             (Vp_horizontal, 'L56_exc'),
                             (Vs_horizontal, 'L23_exc'),
                             (Vs_horizontal, 'L4_exc'),
                             (Vs_horizontal, 'L56_exc')]
        # Third column
        cross_models = [(Retina_layer, 'Retina'),
                        (),
                        (),
                        (),
                        (Vs_cross, 'L23_exc'),
                        (Vs_cross, 'L4_exc'),
                        (Vs_cross, 'L56_exc')]

        # Column labels
        labels = ['Vertical', 'Horizontal', 'Cross']

        # Row labels
        areas = ['Retina', 'Primary\nL2/3', 'Primary\nL4', 'Primary\nL5/6', 'Secondary\nL2/3', 'Secondary\nL4',
                 'Secondary\nL4/6']

        # Number of neurons in each plotted layer:
        Np, Ns = Params['Np'], Params['Ns']
        n_neurons = [Np, Np, Np, Np, Ns, Ns, Ns]

        recorded_models = [vertical_models, horizontal_models, cross_models]

        ######## end USER INPUT

        fig = plotting.all_topographic(recorders, recorded_models, labels, areas,
                                            n_neurons,
                                            np.sum(Params['intervals']),
                                            Params['resolution'], start, stop)



        fig.savefig(data_folder + '/figure_all_topo.png', dpi=100)

        if Params.has_key('show_main_figure') and Params['show_main_figure']:
            plt.show()




    # Plot F: All areas


    if Params.has_key('plot_all_regions') and Params['plot_all_regions']:

        print("Creating plot of all areas")

        vertical_bar_column_Vp = image_dic['vertical'][1]
        vertical_bar_column_Vs = vertical_bar_column_Vp * Params['Ns']/Params['Np']
        starting_neuron_Vp = Params['Np'] * vertical_bar_column_Vp
        starting_neuron_Vs = Params['Ns'] * vertical_bar_column_Vs

        #### USER INPUT

        vertical_models = [(Retina_layer,'Retina'),
                        (Vp_vertical,'L23_exc'),
                        (Vp_vertical,'L4_exc'),
                        (Vp_vertical,'L56_exc'),
                        (Vs_vertical,'L23_exc'),
                        (Vs_vertical, 'L4_exc'),
                        (Vs_vertical, 'L56_exc')]

        horizontal_models = [(Retina_layer,'Retina'),
                        (Vp_horizontal,'L23_exc'),
                        (Vp_horizontal,'L4_exc'),
                        (Vp_horizontal,'L56_exc'),
                        (Vs_horizontal,'L23_exc'),
                        (Vs_horizontal, 'L4_exc'),
                        (Vs_horizontal, 'L56_exc')]

        cross_models = [(Retina_layer,'Retina'),
                        (),
                        (),
                        (),
                        (Vs_cross,'L23_exc'),
                        (Vs_cross, 'L4_exc'),
                        (Vs_cross, 'L56_exc')]

        labels = ['Vertical', 'Horizontal', 'Cross']

        # Row labels
        areas = ['Retina', 'Primary\nL2/3', 'Primary\nL4', 'Primary\nL5/6', 'Secondary\nL2/3', 'Secondary\nL4',
                 'Secondary\nL4/6']

        #TODO: make this look nicer
        # Number of neurons in each plotted layer:
        Np, Ns = Params['Np'], Params['Ns']
        n_neurons = [Np, Np, Np, Np, Ns, Ns, Ns]

        # Starting neuron in each plotted layer:
        starting_neurons = [starting_neuron_Vp, starting_neuron_Vp, starting_neuron_Vp, starting_neuron_Vp, starting_neuron_Vs, starting_neuron_Vs, starting_neuron_Vs]

        plotcols = [vertical_models, horizontal_models, cross_models]

        #### end USER INPUT


        fig = plotting.potential_raster_multiple_models(fig, recorders, plotcols, labels, areas, starting_neurons, n_neurons,
                                                  np.sum(Params['intervals']),
                                                  Params['resolution'],
                                                  0)

        fig.savefig(data_folder + '/figure_all_areas.png', dpi=100)



    #! ====================
    #! Save Results
    #! ====================

    print('save recorders data')
    # Set folder
    #rootdir = '/home/kfujii2/newNEST2/ht_model_pablo_based/data/'
    #expdir = 'random/'
    # expdir = 'random_full/'
    # expdir = 'structured_full/'
    # data_folder = rootdir + expdir

    # To save spike data, set pairs of population id and its name
    population_name = [ {'population': Retina_layer, 'name': 'Retina'},
                        {'population': Vp_vertical, 'name': 'Vp_v'},
                        {'population': Vp_horizontal, 'name': 'Vp_h'},
                        {'population': Rp_layer, 'name': 'Rp'},
                        {'population': Tp_layer, 'name': 'Tp'},
                        {'population': Vs_vertical, 'name': 'Vs_v'},
                        {'population': Vs_horizontal, 'name': 'Vs_h'},
                        {'population': Vs_cross, 'name': 'Vs_c'}]

    if Params.has_key('save_recorders') and Params['save_recorders']:
        for rec, population, model in recorders:

            # Get name of population
            for p in range(0, len(population_name), 1):
                if population_name[p]['population'] == population:
                    p_name = population_name[p]['name']

            data = nest.GetStatus(rec)[0]['events']

            if model == 'Retina':
                scipy.io.savemat(data_folder + '/recorder_' + p_name + '_' + model + '.mat',
                                 mdict={'senders': data['senders'],
                                        'rate': data['rate']})
            else:
                scipy.io.savemat(data_folder + '/recorder_' + p_name + '_' + model + '.mat',
                                 mdict={'senders': data['senders'],
                                        'times': data['times'],
                                        'V_m': data['V_m']
                                        #'I_syn_AMPA': data['I_syn_AMPA'],
                                        #'I_syn_NMDA': data['I_syn_NMDA'],
                                        #'I_syn_GABA_A': data['I_syn_GABA_A'],
                                        #'I_syn_GABA_B': data['I_syn_GABA_B'],
                                        # 'g_AMPA': data['g_AMPA'],
                                        # 'g_NMDA': data['g_NMDA'],
                                        # 'g_GABA_A': data['g_GABA_A'],
                                        # 'g_GABA_B': data['g_GABA_B']
                                        } )



    print('save raster images')
    plt.close()
    for rec, population, model in detectors:
        spikes = nest.GetStatus(rec, 'events')[0]

        # Get name of population
        for p in range(0, len(population_name), 1):
            if population_name[p]['population'] == population:
                p_name = population_name[p]['name']

        if len(nest.GetStatus(rec)[0]['events']['senders']) > 3:
            raster = raster_plot.from_device(rec, hist=True)
            pylab.title( p_name + '_' + model )
            f = raster[0].figure
            f.set_size_inches(15, 9)
            f.savefig(data_folder + '/spikes_' + p_name + '_' + model + '.png', dpi=100)
            plt.close()

            # Set filename and save spike data
            filename = data_folder + '/spike_' + p_name + '_' + model + '.pickle'
            pickle.dump(spikes, open(filename, 'w'))
            scipy.io.savemat(data_folder + '/spike_' + p_name + '_' + model + '.mat', mdict={'senders': spikes['senders'], 'times': spikes['times']})

            '''
            filename_AMPA = data_folder + 'connection_' + p_name + '_AMPA_syn' + '.dat'
            filename_NMDA = data_folder + 'connection_' + p_name + '_NMDA_syn' + '.dat'
            filename_GABAA = data_folder + 'connection_' + p_name + '_GABA_A_syn' + '.dat'
            filename_GABAB = data_folder + 'connection_' + p_name + '_GABA_B_syn' + '.dat'
            tp.DumpLayerConnections(population, 'AMPA_syn', filename_AMPA)
            tp.DumpLayerConnections(population, 'NMDA_syn', filename_NMDA)
            tp.DumpLayerConnections(population, 'GABA_A_syn', filename_GABAA)
            tp.DumpLayerConnections(population, 'GABA_B_syn', filename_GABAB)
            '''
    '''
    for p in range(0, len(population_name), 1):

        population = population_name[p]['population']
        p_name = population_name[p]['name']
        filename_nodes = data_folder + '/gid_' + p_name + '.dat'

        tp.DumpLayerNodes(population, filename_nodes)
    '''

    network_script = Params['network'] + '.py'
    shutil.copy2(network_script, data_folder + '/' + network_script)
    shutil.copy2(network_script, conn_folder + '/' + network_script)

    print('end')
Exemple #5
0
def simulation(Params):

    #! =================
    #! Import network
    #! =================

    import importlib
    import time

    #network_names = ['network_full_keiko',  'network_full_leonardo']
    network_names = ['network_full_keiko', 'network_full_keiko']

    colors = [[0, 0, 1, .5], [0, 1, 0, .5]]
    fig, axs = plt.subplots(2, 2)
    for (inet, netname) in enumerate(network_names):

        # NEST Kernel and Network settings
        nest.ResetKernel()
        nest.ResetNetwork()
        nest.SetKernelStatus({
            "local_num_threads": Params['threads'],
            'resolution': Params['resolution']
        })
        nest.SetStatus([0], {'print_time': True})

        # initialize random seed
        msd = int(round(time.time() * 1000))
        nest.SetKernelStatus({'grng_seed': msd})
        nest.SetKernelStatus({
            'rng_seeds':
            range(msd + Params['threads'] + 1, msd + 2 * Params['threads'] + 1)
        })

        network = importlib.import_module(netname)
        reload(network)
        models, layers, conns = network.get_Network(Params)
        # import network_full_keiko
        # reload(network_full_keiko)
        # models, layers, conns  = network_full_keiko.get_Network(Params)

        # Create models
        for m in models:
            nest.CopyModel(m[0], m[1], m[2])

        # Create layers, store layer info in Python variable
        for l in layers:
            exec '%s = tp.CreateLayer(l[1])' % l[0]

        # Create connections, need to insert variable names
        for c in conns:
            eval('tp.ConnectLayers(%s,%s,c[2])' % (c[0], c[1]))

        if Params.has_key('show_V4_num_conn_figure'
                          ) and Params['show_V4_num_conn_figure']:

            horizontal_nodes = nest.GetLeaves(Vp_horizontal,
                                              properties={'model': 'L4_exc'},
                                              local_only=True)[0]
            vertical_nodes = nest.GetLeaves(Vp_vertical,
                                            properties={'model': 'L4_exc'},
                                            local_only=True)[0]

            print('Ploting #1')
            n_conns_hor = []
            for (idx, horizontal_node) in enumerate(horizontal_nodes):
                tgt_map = []
                this_conns = nest.GetConnections([horizontal_node],
                                                 horizontal_nodes,
                                                 synapse_model='AMPA_syn')
                tgt_map.extend([conn[1] for conn in this_conns])
                n_conns_hor.append(len(tgt_map))

            plt.axes(axs[0, 0])
            plt.hist(n_conns_hor,
                     range(0, max(n_conns_hor + [30])),
                     fc=colors[inet])
            plt.title('# of connections Vp(h) L4pyr -> Vp(h) L4Pyr')

            print('Ploting #2')
            n_conns_hor = []
            for (idx, horizontal_node) in enumerate(horizontal_nodes):
                tgt_map = []
                this_conns = nest.GetConnections([horizontal_node],
                                                 vertical_nodes,
                                                 synapse_model='AMPA_syn')
                tgt_map.extend([conn[1] for conn in this_conns])
                n_conns_hor.append(len(tgt_map))

                # nest.DisconnectOneToOne(tp_node, tgt_map[0], {"synapse_model": "AMPA_syn"})
                #nest.Disconnect([tp_node], tgt_map, 'one_to_one', {"synapse_model": "AMPA_syn"})

            plt.axes(axs[0, 1])
            plt.hist(n_conns_hor,
                     range(0, max(n_conns_hor + [30])),
                     fc=colors[inet])
            plt.title('# of connections Vp(h) L4pyr -> Vp(v) L4Pyr')

            print('Ploting #3')
            n_conns_ver = []
            for (idx, vertical_node) in enumerate(vertical_nodes):
                tgt_map = []
                this_conns = nest.GetConnections([vertical_node],
                                                 vertical_nodes,
                                                 synapse_model='AMPA_syn')
                tgt_map.extend([conn[1] for conn in this_conns])
                n_conns_ver.append(len(tgt_map))

            plt.axes(axs[1, 1])
            plt.hist(n_conns_ver,
                     range(0, max(n_conns_ver + [30])),
                     fc=colors[inet])
            plt.title('# of connections Vp(v) L4pyr -> Vp(v) L4Pyr')

            print('Ploting #4')
            n_conns_ver = []
            for (idx, vertical_node) in enumerate(vertical_nodes):
                tgt_map = []
                this_conns = nest.GetConnections([vertical_node],
                                                 horizontal_nodes,
                                                 synapse_model='AMPA_syn')
                tgt_map.extend([conn[1] for conn in this_conns])
                n_conns_ver.append(len(tgt_map))

            plt.axes(axs[1, 0])
            plt.hist(n_conns_ver,
                     range(0, max(n_conns_ver + [30])),
                     fc=colors[inet])
            plt.title('# of connections Vp(v) L4pyr -> Vp(h) L4Pyr')

    plt.show()

    # Check connections

    # Connections from Retina to TpRelay
    # tp.PlotTargets(tp.FindCenterElement(Retina_layer), Tp_layer)

    if Params.has_key('show_V4_connectivity_figure'
                      ) and Params['show_V4_connectivity_figure']:

        Vp_hor_gids = tp.GetElement(Vp_horizontal, [0, 0])
        n_Vp_hor = len(Vp_hor_gids)

        f = []
        for idx in range(n_Vp_hor):
            f.append(plt.figure())

        positions = range(0, 41, 10)
        positions[-1] -= 1
        for xi in range(len(positions)):
            for yi in range(len(positions)):
                print("Position [%d,%d] : %d" % (xi, yi, yi *
                                                 (len(positions)) + xi + 1))
                x = positions[xi]
                y = positions[yi]
                Vp_hor_gids = tp.GetElement(Vp_horizontal, [x, y])
                Vp_hor_status = nest.GetStatus(Vp_hor_gids)
                for (idx, n) in enumerate(Vp_hor_status):
                    if n['Tau_theta'] == 2.0:
                        print idx
                        try:
                            f[idx].add_subplot(len(positions), len(positions),
                                               yi * (len(positions)) + xi + 1)
                            tp.PlotTargets([Vp_hor_gids[idx]], Vp_horizontal,
                                           'L4_exc', 'AMPA_syn', f[idx])
                        except:
                            print('%i bad' % Vp_hor_gids[idx])
        plt.show()

    # Connections from TpRelay to L4pyr in Vp (horizontally tuned)
    #topo.PlotTargets(topo.FindCenterElement(Tp), Vp_h, 'L4pyr', 'AMPA')
    #pylab.title('Connections TpRelay -> Vp(h) L4pyr')
    #pylab.show()

    # Connections from TpRelay to L4pyr in Vp (vertically tuned)
    #topo.PlotTargets(topo.FindCenterElement(Tp), Vp_v, 'L4pyr', 'AMPA')
    #pylab.title('Connections TpRelay -> Vp(v) L4pyr')
    #pylab.show()
    '''
    # pablo
    # Create vertical grating
    for n in nest.GetLeaves(Retina_layer)[0]:
            retina_0 = (nest.GetLeaves(Retina_layer)[0])[0]
            col = (n-retina_0)/Params['Np']

            cells_per_degree = Params['Np']/Params['visSize']
            cells_per_cycle = cells_per_degree/Params['spatial_frequency']

            nest.SetStatus([n], { "phase": col * 360/(cells_per_cycle-1) })
    '''
    ### keiko
    if Params['lambda_dg'] >= 0:
        [
            nest.SetStatus(
                [n], {
                    "phase":
                    phaseInit(
                        tp.GetPosition([n])[0], Params["lambda_dg"],
                        Params["phi_dg"])
                }) for n in nest.GetLeaves(Retina_layer)[0]
        ]
    else:
        # Leonardo: Random retina input
        [
            nest.SetStatus(
                [n], {
                    "phase":
                    phaseInit(
                        tp.GetPosition([n])[0], np.pi * np.random.rand(),
                        np.pi * np.random.rand())
                }) for n in nest.GetLeaves(Retina_layer)[0]
        ]

    # --------------------------------------------------------------------#
    # ---------- SET IB NEURONS ----------------------------------------- #
    # --------------------------------------------------------------------#

    # 30% of Cortex L56 excitatory neurons are intrinsically bursting(IB) neuron.
    # That is achieved by setting pacemaker current I_h.
    # So select 30% of L56_exc neuron, and change h_g_peak from 0.0 to 1.0.
    # (Other cortical neuron do not have I_h, thus h_g_peak=0.0)

    L56_vertical_idx = [
        nd for nd in nest.GetLeaves(Vp_vertical)[0]
        if nest.GetStatus([nd], 'model')[0] == 'L56_exc'
    ]
    L56_horizontal_idx = [
        nd for nd in nest.GetLeaves(Vp_horizontal)[0]
        if nest.GetStatus([nd], 'model')[0] == 'L56_exc'
    ]

    num_neuron = len(L56_vertical_idx)
    num_ib = int(num_neuron * 0.3)

    ridx_vertical = np.random.randint(num_neuron, size=(1, num_ib))[0]
    ridx_horizontal = np.random.randint(num_neuron, size=(1, num_ib))[0]

    for i in range(1, num_ib, 1):
        nest.SetStatus([L56_vertical_idx[ridx_vertical[i]]], {'h_g_peak': 1.0})
        nest.SetStatus([L56_horizontal_idx[ridx_horizontal[i]]],
                       {'h_g_peak': 1.0})

    # initiate network activity
    #nest.SetStatus(nest.GetLeaves(Retina_layer)[0], {'rate': Params['ret_rate']})
    nest.SetStatus(
        nest.GetLeaves(Retina_layer)[0], {'rate': Params['ret_rate']})
    nest.SetStatus(nest.GetLeaves(Retina_layer)[0], {'amplitude': 0.0})
    nest.Simulate(500.0)

    #! =================
    #! Recording devices
    #! =================

    nest.CopyModel(
        'multimeter',
        'RecordingNode',
        params={
            'interval':
            Params['resolution'],
            #'record_from': ['V_m'],
            'record_from': [
                'V_m', 'I_syn_AMPA', 'I_syn_NMDA', 'I_syn_GABA_A',
                'I_syn_GABA_B', 'g_AMPA', 'g_NMDA', 'g_GABAA', 'g_GABAB',
                'I_NaP', 'I_KNa', 'I_T', 'I_h'
            ],
            'record_to': ['memory'],
            'withgid':
            True,
            'withtime':
            True
        })

    recorders = []
    '''
    for population, model in [(Retina_layer, 'Retina'),
                              (Tp_layer  , 'Tp_exc'),
                              (Tp_layer  , 'Tp_inh'),
                              (Rp_layer  , 'Rp'),
                              (Vp_vertical, 'L23_exc'),
                              (Vp_horizontal, 'L23_exc'),
                              (Vp_vertical, 'L23_inh'),
                              (Vp_horizontal, 'L23_inh'),
                              (Vp_vertical, 'L4_exc'),
                              (Vp_horizontal, 'L4_exc'),
                              (Vp_vertical, 'L4_inh'),
                              (Vp_horizontal, 'L4_inh'),
                              (Vp_vertical, 'L56_exc'),
                              (Vp_horizontal, 'L56_exc'),
                              (Vp_vertical, 'L56_inh'),
                              (Vp_horizontal, 'L56_inh'),
                              (Vs_vertical, 'L23_exc'),
                              (Vs_horizontal, 'L23_exc'),
                              (Vs_vertical, 'L23_inh'),
                              (Vs_horizontal, 'L23_inh'),
                              (Vs_vertical, 'L4_exc'),
                              (Vs_horizontal, 'L4_exc'),
                              (Vs_vertical, 'L4_inh'),
                              (Vs_horizontal, 'L4_inh'),
                              (Vs_vertical, 'L56_exc'),
                              (Vs_horizontal, 'L56_exc'),
                              (Vs_vertical, 'L56_inh'),
                              (Vs_horizontal, 'L56_inh')]:
    '''
    for population, model in [(Retina_layer, 'Retina'), (Tp_layer, 'Tp_exc'),
                              (Tp_layer, 'Tp_inh'), (Vp_vertical, 'L4_exc'),
                              (Vp_vertical, 'L4_inh'),
                              (Vp_horizontal, 'L4_exc'),
                              (Vp_vertical, 'L23_exc'),
                              (Vp_horizontal, 'L23_exc'),
                              (Vp_vertical, 'L56_exc'), (Rp_layer, 'Rp')]:
        rec = nest.Create('RecordingNode')
        recorders.append([rec, population, model])
        if (model == 'Retina'):
            nest.SetStatus(rec, {'record_from': ['rate']})
        tgts = [
            nd for nd in nest.GetLeaves(population)[0]
            if nest.GetStatus([nd], 'model')[0] == model
        ]
        nest.Connect(rec, tgts)

    #! =================
    #! Spike detector
    #! =================
    detectors = []
    '''
    for population, model in [(Retina_layer, 'Retina'),
                              (Tp_layer  , 'Tp_exc'),
                              (Tp_layer  , 'Tp_inh'),
                              (Rp_layer  , 'Rp'),
                              (Vp_vertical, 'L23_exc'),
                              (Vp_horizontal, 'L23_exc'),
                              (Vp_vertical, 'L23_inh'),
                              (Vp_horizontal, 'L23_inh'),
                              (Vp_vertical, 'L4_exc'),
                              (Vp_horizontal, 'L4_exc'),
                              (Vp_vertical, 'L4_inh'),
                              (Vp_horizontal, 'L4_inh'),
                              (Vp_vertical, 'L56_exc'),
                              (Vp_horizontal, 'L56_exc'),
                              (Vp_vertical, 'L56_inh'),
                              (Vp_horizontal, 'L56_inh'),
                              (Vs_vertical, 'L23_exc'),
                              (Vs_horizontal, 'L23_exc'),
                              (Vs_vertical, 'L23_inh'),
                              (Vs_horizontal, 'L23_inh'),
                              (Vs_vertical, 'L4_exc'),
                              (Vs_horizontal, 'L4_exc'),
                              (Vs_vertical, 'L4_inh'),
                              (Vs_horizontal, 'L4_inh'),
                              (Vs_vertical, 'L56_exc'),
                              (Vs_horizontal, 'L56_exc'),
                              (Vs_vertical, 'L56_inh'),
                              (Vs_horizontal, 'L56_inh')]:
        '''

    for population, model in [(Retina_layer, 'Retina'), (Tp_layer, 'Tp_exc'),
                              (Tp_layer, 'Tp_inh'), (Vp_vertical, 'L4_exc'),
                              (Vp_horizontal, 'L4_exc')]:
        rec = nest.Create('spike_detector',
                          params={
                              "withgid": True,
                              "withtime": True
                          })
        #rec = nest.Create('spike_detector')
        detectors.append([rec, population, model])
        tgts = [
            nd for nd in nest.GetLeaves(population)[0]
            if nest.GetStatus([nd], 'model')[0] == model
        ]
        if model == 'Retina':
            for t in tgts:
                try:
                    nest.Connect([t], rec)
                    print('connected %d' % t)
                except:
                    print('%d did not work' % t)
        else:
            nest.Connect(tgts, rec)

    #! ====================
    #! Simulation
    #! ====================
    '''
    # change gKL to 0.8 in all populations (necessary to get a little stronger evoked response)
    for l in layers:
            sim_elements = l[1]['elements']
            for m in np.arange(0,np.size(sim_elements),1):

                    if(np.size(sim_elements)==1):
                        sim_model = sim_elements
                    else:
                        sim_model = sim_elements[m]

                    exec("la = %s" % l[0])
                    pop = [nd for nd in nest.GetLeaves(la)[0] if nest.GetStatus([nd], 'model')[0]==sim_model]
                    if (l[0]!='Retina_layer'):
                            for cell in pop:
                                    nest.SetStatus([cell], {'g_KL':0.8})
    '''
    # Simulate
    for t in Params['intervals']:

        #if (t == 250.0):  # Stimulus ON
        #    # if (t == 1500.0):  # Stimulus ON
        #    nest.SetStatus(nest.GetLeaves(Retina_layer)[0], {'amplitude': 45.0})
        #else:  # Stimulus OFF
        #    nest.SetStatus(nest.GetLeaves(Retina_layer)[0], {'amplitude': 0.0})

        if Params['input_flag'] == True:
            nest.SetStatus(
                nest.GetLeaves(Retina_layer)[0],
                {'amplitude': Params['ret_rate']})
        else:
            nest.SetStatus(nest.GetLeaves(Retina_layer)[0], {'amplitude': 0.0})

        nest.Simulate(t)

    #! ====================
    #! Plot Results
    #! ====================

    if Params.has_key('show_main_figure') and Params['show_main_figure']:
        print "plotting..."

        rows = 9
        cols = 2

        fig = plt.figure()
        fig.subplots_adjust(hspace=0.4)

        # Plot A: membrane potential rasters

        recorded_models = [(Retina_layer, 'Retina'), (Vp_vertical, 'L23_exc'),
                           (Vp_vertical, 'L4_exc'), (Vp_vertical, 'L56_exc'),
                           (Rp_layer, 'Rp'), (Tp_layer, 'Tp_exc')]

        #plotting.potential_raster(fig,recorders,recorded_models,0,Params['Np'],np.sum(Params['intervals']),Params['resolution'],rows,cols,0)
        plotting.potential_raster(fig, recorders, recorded_models, 0,
                                  Params['Np'], np.sum(Params['intervals']),
                                  Params['resolution'], rows, cols, 0)
        #starting_neuron = 800+1
        #plotting.potential_raster(fig,recorders,recorded_models,starting_neuron,Params['Np'],np.sum(Params['intervals']),Params['resolution'],rows,cols,0)

        plt.title('Evoked')

        # Plot B: individual intracellular traces

        recorded_models = [(Vp_vertical, 'L4_exc'), (Vp_vertical, 'L4_inh')]

        #plotting.intracellular_potentials(fig, recorders, recorded_models, 21, rows, cols, 6) #original
        # keiko
        total_time = 0.0
        for t in Params['intervals']:
            total_time += t

        #draw_neuron = (Params['Np']*Params['Np']/2)
        #plotting.intracellular_potentials(fig, recorders, recorded_models, draw_neuron, rows, cols, 6, total_time)
        plotting.intracellular_potentials(fig, recorders, recorded_models, 21,
                                          rows, cols, 6, total_time)
        #plotting.intracellular_potentials(fig, recorders, recorded_models, 820, rows, cols, 6, total_time)

        # Plot C: topographical activity of the vertical and horizontal layers

        recorded_models = [(Vp_vertical, 'L23_exc')]

        labels = ["Vertical"]
        start = 130.0
        stop = 140.0
        #start = 650.0
        #stop = 660.0
        plotting.topographic_representation(fig, recorders, recorded_models,
                                            labels, Params['Np'],
                                            np.sum(Params['intervals']),
                                            Params['resolution'], rows, cols,
                                            start, stop, 8, 0)

        recorded_models = [(Vp_horizontal, 'L23_exc')]

        labels = ["Horizontal"]
        start = 130.0
        stop = 140.0
        #start = 650.0
        #stop = 660.0

        plotting.topographic_representation(fig, recorders, recorded_models,
                                            labels, Params['Np'],
                                            np.sum(Params['intervals']),
                                            Params['resolution'], rows, cols,
                                            start, stop, 8, 1)

        plt.show()

    # Plot D: movie

    #labels = ["Evoked_Vp_L23_Vertical","Evoked_Vp_L23_Horizontal"]
    #recorded_models = [(Vp_vertical,'L23_exc'),(Vp_horizontal,'L23_exc')]
    #plotting.makeMovie(fig,recorders,recorded_models,labels,Params['Np'],np.sum(Params['intervals']),Params['resolution'])

    #! ====================
    #! Save Results
    #! ====================

    print('save recorders data')
    # Set folder
    #rootdir = '/home/kfujii2/newNEST2/ht_model_pablo_based/data/'
    #expdir = 'random/'
    # expdir = 'random_full/'
    # expdir = 'structured_full/'
    # data_folder = rootdir + expdir
    data_folder = Params['data_folder']

    if not os.path.isdir(data_folder):
        os.makedirs(data_folder)

    # To save spike data, set pairs of population id and its name
    population_name = [{
        'population': Retina_layer,
        'name': 'Retina'
    }, {
        'population': Vp_vertical,
        'name': 'Vp_v'
    }, {
        'population': Vp_horizontal,
        'name': 'Vp_h'
    }, {
        'population': Rp_layer,
        'name': 'Rp'
    }, {
        'population': Tp_layer,
        'name': 'Tp'
    }, {
        'population': Vs_vertical,
        'name': 'Vs_v'
    }, {
        'population': Vs_horizontal,
        'name': 'Vs_h'
    }]

    for rec, population, model in recorders:

        # Get name of population
        for p in range(0, len(population_name), 1):
            if population_name[p]['population'] == population:
                p_name = population_name[p]['name']

        data = nest.GetStatus(rec)[0]['events']

        if model == 'Retina':
            scipy.io.savemat(data_folder + '/recorder_' + p_name + '_' +
                             model + '.mat',
                             mdict={
                                 'senders': data['senders'],
                                 'rate': data['rate']
                             })
        else:
            scipy.io.savemat(data_folder + '/recorder_' + p_name + '_' +
                             model + '.mat',
                             mdict={
                                 'senders': data['senders'],
                                 'V_m': data['V_m'],
                                 'I_syn_AMPA': data['I_syn_AMPA'],
                                 'I_syn_NMDA': data['I_syn_NMDA'],
                                 'I_syn_GABA_A': data['I_syn_GABA_A'],
                                 'I_syn_GABA_B': data['I_syn_GABA_B'],
                                 'g_AMPA': data['g_AMPA'],
                                 'g_NMDA': data['g_NMDA'],
                                 'g_GABAA': data['g_GABAA'],
                                 'g_GABAB': data['g_GABAB']
                             })

    print('save raster images')
    plt.close()
    for rec, population, model in detectors:
        spikes = nest.GetStatus(rec, 'events')[0]

        # Get name of population
        for p in range(0, len(population_name), 1):
            if population_name[p]['population'] == population:
                p_name = population_name[p]['name']

        if len(nest.GetStatus(rec)[0]['events']['senders']) > 3:
            raster = raster_plot.from_device(rec, hist=True)
            pylab.title(p_name + '_' + model)
            f = raster[0].figure
            f.set_size_inches(15, 9)
            f.savefig(data_folder + 'spikes_' + p_name + '_' + model + '.png',
                      dpi=100)
            plt.close()

            # Set filename and save spike data
            filename = data_folder + 'spike_' + p_name + '_' + model + '.pickle'
            pickle.dump(spikes, open(filename, 'w'))
            scipy.io.savemat(data_folder + '/spike_' + p_name + '_' + model +
                             '.mat',
                             mdict={
                                 'senders': spikes['senders'],
                                 'times': spikes['times']
                             })
            '''
            filename_AMPA = data_folder + 'connection_' + p_name + '_AMPA_syn' + '.dat'
            filename_NMDA = data_folder + 'connection_' + p_name + '_NMDA_syn' + '.dat'
            filename_GABAA = data_folder + 'connection_' + p_name + '_GABA_A_syn' + '.dat'
            filename_GABAB = data_folder + 'connection_' + p_name + '_GABA_B_syn' + '.dat'
            tp.DumpLayerConnections(population, 'AMPA_syn', filename_AMPA)
            tp.DumpLayerConnections(population, 'NMDA_syn', filename_NMDA)
            tp.DumpLayerConnections(population, 'GABA_A_syn', filename_GABAA)
            tp.DumpLayerConnections(population, 'GABA_B_syn', filename_GABAB)
            '''
    '''
    for p in range(0, len(population_name), 1):

        population = population_name[p]['population']
        p_name = population_name[p]['name']
        filename_nodes = data_folder + '/gid_' + p_name + '.dat'

        tp.DumpLayerNodes(population, filename_nodes)
    '''

    network_script = Params['network'] + '.py'
    shutil.copy2(network_script, Params['data_folder'] + network_script)

    print('end')
Exemple #6
0
def simulation(Params):


    #! =================
    #! Import network
    #! =================

    # NEST Kernel and Network settings
    nest.ResetKernel()
    nest.ResetNetwork()
    nest.SetKernelStatus({"local_num_threads": Params['threads'],'resolution': Params['resolution']})
    nest.SetStatus([0],{'print_time': True})

    # initialize random seed
    import time
    msd = int(round(time.time() * 1000))
    nest.SetKernelStatus({'grng_seed' : msd})
    nest.SetKernelStatus({'rng_seeds' : range(msd+Params['threads']+1, msd+2*Params['threads']+1)})


    import importlib
    network = importlib.import_module(Params['network'])
    reload(network)
    models, layers, conns  = network.get_Network(Params)
    #import network_full_keiko
    #reload(network_full_keiko)
    # models, layers, conns  = network_full_keiko.get_Network(Params)

    # Create models
    for m in models:
            nest.CopyModel(m[0], m[1], m[2])

    # Create layers, store layer info in Python variable
    for l in layers:
            exec '%s = tp.CreateLayer(l[1])' % l[0]

    # Create connections, need to insert variable names
    for c in conns:
            eval('tp.ConnectLayers(%s,%s,c[2])' % (c[0], c[1]))


    # Prepare for file IO
    import glob
    # --- Set folder information
    data_folder = Params['data_folder']
    if not os.path.isdir(data_folder):
        os.makedirs(data_folder)

    # --- To save spike data, set pairs of population id and its name
    population_name = [ {'population': Retina_layer, 'name': 'Retina'},
                        {'population': Vp_vertical, 'name': 'Vp_v'},
                        {'population': Vp_horizontal, 'name': 'Vp_h'},
                        {'population': Rp_layer, 'name': 'Rp'},
                        {'population': Tp_layer, 'name': 'Tp'},
                        {'population': Vs_vertical, 'name': 'Vs_v'},
                        {'population': Vs_horizontal, 'name': 'Vs_h'}]


    if Params.has_key('load_connections_from_file') and Params['load_connections_from_file']:

        # Preparation
        scramble_populations = [(Vp_vertical, 'Vp_vertical'),
                                (Vp_horizontal, 'Vp_horizontal')]
        scramble_layers = ['L23_exc',
                           'L23_inh',
                           'L4_exc',
                           'L4_inh',
                           'L56_exc',
                           'L56_inh']
        #scramble_layers = ['L4_exc']

        # Get min &max index of each layer
        h_min_idx = {}
        h_max_idx = {}
        v_min_idx = {}
        v_max_idx = {}
        target_neurons = []
        for tmp_model in scramble_layers:
            tmp_h = nest.GetLeaves(Vp_horizontal, properties={'model': tmp_model}, local_only=True)[0]
            tmp_v = nest.GetLeaves(Vp_vertical, properties={'model': tmp_model}, local_only=True)[0]
            h_min_idx[tmp_model] = min(tmp_h)
            h_max_idx[tmp_model] = max(tmp_h)
            v_min_idx[tmp_model] = min(tmp_v)
            v_max_idx[tmp_model] = max(tmp_v)
            target_neurons = target_neurons + range(h_min_idx[tmp_model], h_max_idx[tmp_model]+1) + range(v_min_idx[tmp_model], v_max_idx[tmp_model]+1)

        # Save intact network information
        for p in range(0, len(population_name), 1):

            population = population_name[p]['population']
            p_name = population_name[p]['name']
            filename_AMPA = data_folder + 'connection_' + p_name + '_AMPA_syn' + '_intact.dat'
            filename_NMDA = data_folder + 'connection_' + p_name + '_NMDA_syn' + '_intact.dat'
            filename_GABAA = data_folder + 'connection_' + p_name + '_GABA_A_syn' + '_intact.dat'
            filename_GABAB = data_folder + 'connection_' + p_name + '_GABA_B_syn' + '_intact.dat'
            tp.DumpLayerConnections(population, 'AMPA_syn', filename_AMPA)
            tp.DumpLayerConnections(population, 'NMDA_syn', filename_NMDA)
            tp.DumpLayerConnections(population, 'GABA_A_syn', filename_GABAA)
            tp.DumpLayerConnections(population, 'GABA_B_syn', filename_GABAB)

        # Reset network
        nest.ResetNetwork()

        '''
        # The following code works, but takes time longer

        # Get the list of connection_file
        file_list = glob.glob(data_folder+'connection_*_intact.dat')

        # Remove a file if the size is zero
        remove_idx = []
        for file_idx in range(0,len(file_list)):
            intact_filename = file_list[file_idx]
            fsize=os.path.getsize(intact_filename)
            if fsize == 0:
                remove_idx = remove_idx + [file_idx]

        remove_idx.sort()
        remove_idx.reverse()
        for i in remove_idx:
            del file_list[i]
        '''

        # TODO : put GABA_A, GABA_B and NMDA connection files
        file_list = []
        file_list.append({'filename': data_folder + 'connection_Vp_h_AMPA_syn_intact.dat',
                           'synapse': 'AMPA'})
        file_list.append({'filename': data_folder + 'connection_Vp_v_AMPA_syn_intact.dat',
                           'synapse': 'AMPA'})


        # Do the following procedure for all connection files
        for file_idx in range(0,len(file_list)):

            # Set filenames
            intact_filename = file_list[file_idx]['filename']
            receptors = nest.GetDefaults('ht_neuron')['receptor_types']
            syn_model = receptors[ file_list[file_idx]['synapse'] ]

            scrambled_filename = intact_filename.replace('intact', 'scrambled')
            print(intact_filename)

            # Get original(intact) connectivity data
            src_network = np.loadtxt(open(intact_filename,'rb'))
            np_pre = src_network[:, 0].astype(int)
            np_post = src_network[:, 1].astype(int)
            np_w = src_network[:, 2]
            np_d = src_network[:, 3]

            if Params['scrambled']:

                # Preserve the original structure if
                # -- pre neruons are not in target populations (i.e. scramble_layers)
                # -- OR
                # -- post neurons are not in target populations(i.e. scramble_layers)
                preserved_rows = np.where( ~np.in1d(np_pre,target_neurons) | ~np.in1d(np_post,target_neurons) )[0]
                preserved_pre = np_pre[preserved_rows]
                preserved_post = np_post[preserved_rows]
                preserved_w = np_w[preserved_rows]
                preserved_d = np_d[preserved_rows]

                # If len(preserved_rows)==len(np_pre), that means all neurons do not belong to scramble target areas.
                # If len(preserved_rows) < len(np_pre), that means there are some neurons which need to be scrambled.
                if len(preserved_rows) > len(np_pre):
                    print('ERROR: preserved_rows should not be larger than np_pre')

                elif len(preserved_rows) == len(np_pre):
                    scrambled_pre = preserved_pre.tolist()
                    scrambled_post = preserved_post.tolist()
                    scrambled_w = preserved_w.tolist()
                    scrambled_d = preserved_d.tolist()

                else:  # --- len(preserved_rows) < len(np_pre)

                    scrambled_pre = []
                    scrambled_post = []
                    scrambled_w = []
                    scrambled_d = []

                    for tmp_model_pre in scramble_layers:

                        for tmp_model_post in scramble_layers:

                            # Get row index such that
                            # --- pre_neuron is in "tmp_model_pre"
                            # --- AND
                            # --- post_neuron is in "tmp_model_post"
                            bool_pre_h = np.in1d(np_pre, range(h_min_idx[tmp_model_pre], h_max_idx[tmp_model_pre]+1))
                            bool_pre_v = np.in1d(np_pre, range(v_min_idx[tmp_model_pre], v_max_idx[tmp_model_pre]+1))
                            bool_post_h = np.in1d(np_post, range(h_min_idx[tmp_model_post], h_max_idx[tmp_model_post]+1))
                            bool_post_v = np.in1d(np_post, range(v_min_idx[tmp_model_post], v_max_idx[tmp_model_post]+1))

                            tmp_rows_pre_h = np.where(bool_pre_h & (bool_post_h|bool_post_v))[0]
                            tmp_rows_pre_v = np.where(bool_pre_v & (bool_post_h|bool_post_v))[0]

                            # Get connectivity data such that pre neuron is in "tmp_model_pre"
                            # --- pre, w and d information should be kept.
                            # --- post index should be scrambled.
                            tmp_pre = np_pre[np.append(tmp_rows_pre_h, tmp_rows_pre_v)].tolist()
                            tmp_w = np_w[np.append(tmp_rows_pre_h, tmp_rows_pre_v)].tolist()
                            tmp_d = np_d[np.append(tmp_rows_pre_h, tmp_rows_pre_v)].tolist()
                            tmp_post = []

                            num_pre_h = len(tmp_rows_pre_h)
                            num_pre_v = len(tmp_rows_pre_v)

                            # --- pre : population = horizontal, model = "tmp_model_pre"
                            # --- post: population = horizontal(1/2)+vertical(1/2), model = "tmp_model_post"
                            if num_pre_h > 0:
                                # Assign the same number of connections for horizontal population and vertical population
                                num_scrambled_h = int(round(num_pre_h / 2))
                                num_scrambled_v = num_pre_h - num_scrambled_h

                                # Choose post neuron index randomly
                                scrambled_h_idx = rd.randint(low =h_min_idx[tmp_model_post],
                                                             high=h_max_idx[tmp_model_post],
                                                             size=[num_scrambled_h, 1])
                                scrambled_v_idx = rd.randint(low =v_min_idx[tmp_model_post],
                                                             high=v_max_idx[tmp_model_post],
                                                             size=[num_scrambled_v, 1])

                                # append scrambled post index
                                tmp_post = tmp_post + np.append(scrambled_h_idx, scrambled_v_idx).tolist()

                            # --- pre : population = vertical, model = "tmp_model_pre"
                            # --- post: population = horizontal(1/2)+vertical(1/2), model = "tmp_model_post"
                            if num_pre_v > 0:
                                # Assign the same number of connections for horizontal population and vertical population
                                num_scrambled_h = int(round(num_pre_v / 2))
                                num_scrambled_v = num_pre_v - num_scrambled_h

                                # Choose post neuron index randomly
                                scrambled_h_idx = rd.randint(low =h_min_idx[tmp_model_post],
                                                             high=h_max_idx[tmp_model_post],
                                                             size=[num_scrambled_h, 1])
                                scrambled_v_idx = rd.randint(low =v_min_idx[tmp_model_post],
                                                             high=v_max_idx[tmp_model_post],
                                                             size=[num_scrambled_v, 1])

                                # append scrambled post index
                                tmp_post = tmp_post + np.append(scrambled_h_idx, scrambled_v_idx).tolist()

                            scrambled_pre = scrambled_pre + tmp_pre
                            scrambled_post = scrambled_post + tmp_post
                            scrambled_w = scrambled_w + tmp_w
                            scrambled_d = scrambled_d +tmp_d

                    # append preserved connection data
                    scrambled_pre = scrambled_pre + preserved_pre.tolist()
                    scrambled_post = scrambled_post + preserved_post.tolist()
                    scrambled_w = scrambled_w + preserved_w.tolist()
                    scrambled_d = scrambled_d + preserved_d.tolist()

                    # Save scrambled_data
                    scrambled_all_data = np.zeros([len(scrambled_pre), 4])
                    scrambled_all_data[:, 0] = scrambled_pre
                    scrambled_all_data[:, 1] = scrambled_post
                    scrambled_all_data[:, 2] = scrambled_w
                    scrambled_all_data[:, 3] = scrambled_d
                    np.savetxt(scrambled_filename, scrambled_all_data, fmt='%.6f')

                # Connect
                con_dict = {'rule': 'one_to_one'}
                syn_dict = {"model": "ht_synapse",
                            'receptor_type': syn_model,
                            'weight': scrambled_w,
                            'delay': scrambled_d,
                            }
                nest.Connect(scrambled_pre, scrambled_post, con_dict, syn_dict)


            else:
                # just convert data type(ndarray->list) and connect based on the original data
                pre = np_pre.tolist()
                post = np_post.tolist()
                w = np_w.tolist()
                d = np_d.tolist()

                # Connect
                con_dict = {'rule': 'one_to_one'}
                syn_dict = {"model": "ht_synapse",
                            'receptor_type': 1,
                            'weight': w,
                            'delay': d,
                            }
                nest.Connect(pre, post, con_dict, syn_dict)

    # nest.DisconnectOneToOne(tp_node, tgt_map[0], {"synapse_model": "AMPA_syn"})
    #nest.Disconnect([tp_node], tgt_map, 'one_to_one', {"synapse_model": "AMPA_syn"})

    # Get target nodes for the vertical population
    # tp_nodes = nest.GetLeaves(Tp_layer, local_only=True)[0]

    if Params.has_key('show_V4_num_conn_figure') and Params['show_V4_num_conn_figure']:

        horizontal_nodes = nest.GetLeaves(Vp_horizontal, properties={'model': 'L4_exc'}, local_only=True)[0]
        vertical_nodes = nest.GetLeaves(Vp_vertical, properties={'model': 'L4_exc'}, local_only=True)[0]

        n_conns_hor = []
        for (idx, horizontal_node) in enumerate(horizontal_nodes):
            tgt_map = []
            this_conns = nest.GetConnections([horizontal_node], horizontal_nodes, synapse_model='AMPA_syn')
            tgt_map.extend([conn[1] for conn in this_conns])
            n_conns_hor.append(len(tgt_map))

        plt.figure()
        plt.hist(n_conns_hor, range(0, max(n_conns_hor + [30])))
        plt.title('# of connections Vp(h) L4pyr -> Vp(h) L4Pyr')

        n_conns_hor = []
        for (idx, horizontal_node) in enumerate(horizontal_nodes):
            tgt_map = []
            this_conns = nest.GetConnections([horizontal_node], vertical_nodes, synapse_model='AMPA_syn')
            tgt_map.extend([conn[1] for conn in this_conns])
            n_conns_hor.append(len(tgt_map))

            # nest.DisconnectOneToOne(tp_node, tgt_map[0], {"synapse_model": "AMPA_syn"})
            #nest.Disconnect([tp_node], tgt_map, 'one_to_one', {"synapse_model": "AMPA_syn"})

        plt.figure()
        plt.hist(n_conns_hor, range(0, max(n_conns_hor + [30])))
        plt.title('# of connections Vp(h) L4pyr -> Vp(v) L4Pyr')

        n_conns_ver = []
        for (idx, vertical_node) in enumerate(vertical_nodes):
            tgt_map = []
            this_conns = nest.GetConnections([vertical_node], vertical_nodes, synapse_model='AMPA_syn')
            tgt_map.extend([conn[1] for conn in this_conns])
            n_conns_ver.append(len(tgt_map))

        plt.figure()
        plt.hist(n_conns_ver, range(0, max(n_conns_ver + [30])))
        plt.title('# of connections Vp(v) L4pyr -> Vp(v) L4Pyr')

        n_conns_ver = []
        for (idx, vertical_node) in enumerate(vertical_nodes):
            tgt_map = []
            this_conns = nest.GetConnections([vertical_node], horizontal_nodes, synapse_model='AMPA_syn')
            tgt_map.extend([conn[1] for conn in this_conns])
            n_conns_ver.append(len(tgt_map))

        plt.figure()
        plt.hist(n_conns_ver, range(0, max(n_conns_ver + [30])))
        plt.title('# of connections Vp(v) L4pyr -> Vp(h) L4Pyr')

        plt.show()

    # Check connections

    # Connections from Retina to TpRelay
    # tp.PlotTargets(tp.FindCenterElement(Retina_layer), Tp_layer)

    if Params.has_key('show_V4_connectivity_figure') and Params['show_V4_connectivity_figure']:

        Vp_hor_gids = tp.GetElement(Vp_horizontal, [0,0])
        n_Vp_hor = len(Vp_hor_gids)

        f = []
        for idx in range(n_Vp_hor):
            f.append(plt.figure())

        positions = range(0,41,10)
        positions[-1] -= 1
        for xi in range(len(positions)):
            for yi in range(len(positions)):
                print("Position [%d,%d] : %d" %(xi,yi,yi*(len(positions))+xi+1))
                x = positions[xi]
                y = positions[yi]
                Vp_hor_gids = tp.GetElement(Vp_horizontal, [x,y])
                Vp_hor_status = nest.GetStatus(Vp_hor_gids)
                for (idx, n) in enumerate(Vp_hor_status):
                    if n['Tau_theta'] == 2.0:
                        print idx
                        try:
                            f[idx].add_subplot(len(positions), len(positions), yi*(len(positions))+xi+1)
                            tp.PlotTargets([Vp_hor_gids[idx]], Vp_horizontal, 'L4_exc', 'AMPA_syn', f[idx])
                        except:
                            print('%i bad' % Vp_hor_gids[idx])
        plt.show()

    # Connections from TpRelay to L4pyr in Vp (horizontally tuned)
    #topo.PlotTargets(topo.FindCenterElement(Tp), Vp_h, 'L4pyr', 'AMPA')
    #pylab.title('Connections TpRelay -> Vp(h) L4pyr')
    #pylab.show()

    # Connections from TpRelay to L4pyr in Vp (vertically tuned)
    #topo.PlotTargets(topo.FindCenterElement(Tp), Vp_v, 'L4pyr', 'AMPA')
    #pylab.title('Connections TpRelay -> Vp(v) L4pyr')
    #pylab.show()

    '''
    # pablo
    # Create vertical grating
    for n in nest.GetLeaves(Retina_layer)[0]:
            retina_0 = (nest.GetLeaves(Retina_layer)[0])[0]
            col = (n-retina_0)/Params['Np']

            cells_per_degree = Params['Np']/Params['visSize']
            cells_per_cycle = cells_per_degree/Params['spatial_frequency']

            nest.SetStatus([n], { "phase": col * 360/(cells_per_cycle-1) })
    '''
    ### keiko
    if Params['lambda_dg'] >= 0:
        [nest.SetStatus([n], {"phase": phaseInit(tp.GetPosition([n])[0],
                                                 Params["lambda_dg"],
                                                 Params["phi_dg"])})
        for n in nest.GetLeaves(Retina_layer)[0]]
    else:
        # Leonardo: Random retina input
        [nest.SetStatus([n], {"phase": phaseInit(tp.GetPosition([n])[0],
                                                 np.pi * np.random.rand(),
                                                 np.pi * np.random.rand())})
         for n in nest.GetLeaves(Retina_layer)[0]]


    # --------------------------------------------------------------------#
    # ---------- SET IB NEURONS ----------------------------------------- #
    # --------------------------------------------------------------------#

    # 30% of Cortex L56 excitatory neurons are intrinsically bursting(IB) neuron.
    # That is achieved by setting pacemaker current I_h.
    # So select 30% of L56_exc neuron, and change h_g_peak from 0.0 to 1.0.
    # (Other cortical neuron do not have I_h, thus h_g_peak=0.0)

    L56_vertical_idx = [nd for nd in nest.GetLeaves(Vp_vertical)[0] if nest.GetStatus([nd], 'model')[0]=='L56_exc']
    L56_horizontal_idx = [nd for nd in nest.GetLeaves(Vp_horizontal)[0] if nest.GetStatus([nd], 'model')[0]=='L56_exc']

    num_neuron = len(L56_vertical_idx)
    num_ib = int(num_neuron*0.3)

    ridx_vertical = np.random.randint(num_neuron, size=(1,num_ib))[0]
    ridx_horizontal = np.random.randint(num_neuron, size=(1,num_ib))[0]

    for i in range(1,num_ib,1):
        nest.SetStatus([L56_vertical_idx[ridx_vertical[i]]], {'h_g_peak': 1.0})
        nest.SetStatus([L56_horizontal_idx[ridx_horizontal[i]]], {'h_g_peak': 1.0})



    # initiate network activity
    #nest.SetStatus(nest.GetLeaves(Retina_layer)[0], {'rate': Params['ret_rate']})
    nest.SetStatus(nest.GetLeaves(Retina_layer)[0], {'rate': Params['ret_rate']})
    nest.SetStatus(nest.GetLeaves(Retina_layer)[0], {'amplitude': 0.0})
    nest.Simulate(500.0)


    #! =================
    #! Recording devices
    #! =================

    nest.CopyModel('multimeter', 'RecordingNode',
            params = {'interval'   : Params['resolution'],
            #'record_from': ['V_m'],
            'record_from': ['V_m',
                            'I_syn_AMPA',
                            'I_syn_NMDA',
                            'I_syn_GABA_A',
                            'I_syn_GABA_B',
                            'g_AMPA',
                            'g_NMDA',
                            'g_GABAA',
                            'g_GABAB',
                            'I_NaP',
                            'I_KNa',
                            'I_T',
                            'I_h'],
            'record_to'  : ['memory'],
            'withgid'    : True,
            'withtime'   : True})

    recorders = []
    '''
    for population, model in [(Retina_layer, 'Retina'),
                              (Tp_layer  , 'Tp_exc'),
                              (Tp_layer  , 'Tp_inh'),
                              (Rp_layer  , 'Rp'),
                              (Vp_vertical, 'L23_exc'),
                              (Vp_horizontal, 'L23_exc'),
                              (Vp_vertical, 'L23_inh'),
                              (Vp_horizontal, 'L23_inh'),
                              (Vp_vertical, 'L4_exc'),
                              (Vp_horizontal, 'L4_exc'),
                              (Vp_vertical, 'L4_inh'),
                              (Vp_horizontal, 'L4_inh'),
                              (Vp_vertical, 'L56_exc'),
                              (Vp_horizontal, 'L56_exc'),
                              (Vp_vertical, 'L56_inh'),
                              (Vp_horizontal, 'L56_inh'),
                              (Vs_vertical, 'L23_exc'),
                              (Vs_horizontal, 'L23_exc'),
                              (Vs_vertical, 'L23_inh'),
                              (Vs_horizontal, 'L23_inh'),
                              (Vs_vertical, 'L4_exc'),
                              (Vs_horizontal, 'L4_exc'),
                              (Vs_vertical, 'L4_inh'),
                              (Vs_horizontal, 'L4_inh'),
                              (Vs_vertical, 'L56_exc'),
                              (Vs_horizontal, 'L56_exc'),
                              (Vs_vertical, 'L56_inh'),
                              (Vs_horizontal, 'L56_inh')]:
    '''
    for population, model in [(Retina_layer, 'Retina'),
                              (Tp_layer  , 'Tp_exc'),
                              (Tp_layer  , 'Tp_inh'),
                              (Vp_vertical, 'L4_exc'),
                              (Vp_vertical, 'L4_inh'),
                              (Vp_horizontal, 'L4_exc'),
                              (Vp_vertical, 'L23_exc'),
                              (Vp_horizontal, 'L23_exc'),
                              (Vp_vertical, 'L56_exc'),
                              (Rp_layer, 'Rp')]:
        rec = nest.Create('RecordingNode')
        recorders.append([rec,population,model])
        if (model=='Retina'):
            nest.SetStatus(rec,{'record_from': ['rate']})
        tgts = [nd for nd in nest.GetLeaves(population)[0] if nest.GetStatus([nd], 'model')[0]==model]
        nest.Connect(rec, tgts)

    #! =================
    #! Spike detector
    #! =================
    detectors = []
    '''
    for population, model in [(Retina_layer, 'Retina'),
                              (Tp_layer  , 'Tp_exc'),
                              (Tp_layer  , 'Tp_inh'),
                              (Rp_layer  , 'Rp'),
                              (Vp_vertical, 'L23_exc'),
                              (Vp_horizontal, 'L23_exc'),
                              (Vp_vertical, 'L23_inh'),
                              (Vp_horizontal, 'L23_inh'),
                              (Vp_vertical, 'L4_exc'),
                              (Vp_horizontal, 'L4_exc'),
                              (Vp_vertical, 'L4_inh'),
                              (Vp_horizontal, 'L4_inh'),
                              (Vp_vertical, 'L56_exc'),
                              (Vp_horizontal, 'L56_exc'),
                              (Vp_vertical, 'L56_inh'),
                              (Vp_horizontal, 'L56_inh'),
                              (Vs_vertical, 'L23_exc'),
                              (Vs_horizontal, 'L23_exc'),
                              (Vs_vertical, 'L23_inh'),
                              (Vs_horizontal, 'L23_inh'),
                              (Vs_vertical, 'L4_exc'),
                              (Vs_horizontal, 'L4_exc'),
                              (Vs_vertical, 'L4_inh'),
                              (Vs_horizontal, 'L4_inh'),
                              (Vs_vertical, 'L56_exc'),
                              (Vs_horizontal, 'L56_exc'),
                              (Vs_vertical, 'L56_inh'),
                              (Vs_horizontal, 'L56_inh')]:
        '''

    for population, model in [(Retina_layer, 'Retina'),
                              (Tp_layer  , 'Tp_exc'),
                              (Tp_layer  , 'Tp_inh'),
                              (Vp_vertical, 'L4_exc'),
                              (Vp_horizontal, 'L4_exc')]:
        rec = nest.Create('spike_detector', params={"withgid": True, "withtime": True})
        #rec = nest.Create('spike_detector')
        detectors.append([rec,population,model])
        tgts = [nd for nd in nest.GetLeaves(population)[0] if nest.GetStatus([nd], 'model')[0]==model]
        if model == 'Retina':
            for t in tgts:
                try:
                    nest.Connect([t], rec)
                    print('connected %d' % t)
                except:
                    print('%d did not work' % t)
        else:
            nest.Connect(tgts, rec)


    #! ====================
    #! Simulation
    #! ====================
    '''
    # change gKL to 0.8 in all populations (necessary to get a little stronger evoked response)
    for l in layers:
            sim_elements = l[1]['elements']
            for m in np.arange(0,np.size(sim_elements),1):

                    if(np.size(sim_elements)==1):
                        sim_model = sim_elements
                    else:
                        sim_model = sim_elements[m]

                    exec("la = %s" % l[0])
                    pop = [nd for nd in nest.GetLeaves(la)[0] if nest.GetStatus([nd], 'model')[0]==sim_model]
                    if (l[0]!='Retina_layer'):
                            for cell in pop:
                                    nest.SetStatus([cell], {'g_KL':0.8})
    '''
    # Simulate
    for t in Params['intervals']:

        #if (t == 250.0):  # Stimulus ON
        #    # if (t == 1500.0):  # Stimulus ON
        #    nest.SetStatus(nest.GetLeaves(Retina_layer)[0], {'amplitude': 45.0})
        #else:  # Stimulus OFF
        #    nest.SetStatus(nest.GetLeaves(Retina_layer)[0], {'amplitude': 0.0})

        if Params['input_flag']==True:
            nest.SetStatus(nest.GetLeaves(Retina_layer)[0], {'amplitude': Params['ret_rate']})
        else:
            nest.SetStatus(nest.GetLeaves(Retina_layer)[0], {'amplitude': 0.0})

        nest.Simulate(t)

    '''
    data_folder = Params['data_folder']
    if not os.path.isdir(data_folder):
        os.makedirs(data_folder)
    '''

    #! ====================
    #! Plot Results
    #! ====================

    if Params.has_key('show_main_figure') and Params['show_main_figure']:
        print "plotting..."

        rows = 9
        cols = 2

        fig = plt.figure(num=None, figsize=(13, 24), dpi=100)
        fig.subplots_adjust(hspace=0.4)

        # Plot A: membrane potential rasters

        recorded_models = [(Retina_layer,'Retina'),
                            (Vp_vertical,'L23_exc'),
                            (Vp_vertical,'L4_exc'),
                            (Vp_vertical,'L56_exc'),
                            (Rp_layer,'Rp'),
                            (Tp_layer,'Tp_exc')]

        #plotting.potential_raster(fig,recorders,recorded_models,0,Params['Np'],np.sum(Params['intervals']),Params['resolution'],rows,cols,0)
        plotting.potential_raster(fig,recorders,recorded_models,0,Params['Np'],np.sum(Params['intervals']),Params['resolution'],rows,cols,0)
        #starting_neuron = 800+1
        #plotting.potential_raster(fig,recorders,recorded_models,starting_neuron,Params['Np'],np.sum(Params['intervals']),Params['resolution'],rows,cols,0)

        plt.title('Evoked')

        # Plot B: individual intracellular traces

        recorded_models =[(Vp_vertical,'L4_exc'),
                          (Vp_vertical,'L4_inh')]

        #plotting.intracellular_potentials(fig, recorders, recorded_models, 21, rows, cols, 6) #original
        # keiko
        total_time = 0.0
        for t in Params['intervals']:
            total_time += t

        #draw_neuron = (Params['Np']*Params['Np']/2)
        #plotting.intracellular_potentials(fig, recorders, recorded_models, draw_neuron, rows, cols, 6, total_time)
        plotting.intracellular_potentials(fig, recorders, recorded_models, 21, rows, cols, 6, total_time)
        #plotting.intracellular_potentials(fig, recorders, recorded_models, 820, rows, cols, 6, total_time)

        # Plot C: topographical activity of the vertical and horizontal layers


        if Params.has_key('start_membrane_potential') and  Params.has_key('end_membrane_potential'):
            start = Params['start_membrane_potential']
            stop = Params['end_membrane_potential']
        else:
            start = 130.0
            stop = 140.0

        recorded_models = [(Vp_vertical,'L23_exc')]
        labels = ["Vertical"]
        plotting.topographic_representation(fig,
                                            recorders,
                                            recorded_models,
                                            labels,
                                            Params['Np'],
                                            np.sum(Params['intervals']),
                                            Params['resolution'],
                                            rows,
                                            cols,
                                            start,
                                            stop,
                                            8,
                                            0)

        recorded_models = [(Vp_horizontal,'L23_exc')]

        labels = ["Horizontal"]

        plotting.topographic_representation(fig,recorders,recorded_models,labels,Params['Np'],np.sum(Params['intervals']),Params['resolution'],rows,cols,start,stop,8,1)

        fig.savefig(data_folder + 'figure3.png', dpi=100)
        plt.show()


    # Plot D: movie

    #labels = ["Evoked_Vp_L23_Vertical","Evoked_Vp_L23_Horizontal"]
    #recorded_models = [(Vp_vertical,'L23_exc'),(Vp_horizontal,'L23_exc')]
    #plotting.makeMovie(fig,recorders,recorded_models,labels,Params['Np'],np.sum(Params['intervals']),Params['resolution'])


    #! ====================
    #! Save Results
    #! ====================

    print('save recorders data')

    for rec, population, model in recorders:

        # Get name of population
        for p in range(0, len(population_name), 1):
            if population_name[p]['population'] == population:
                p_name = population_name[p]['name']

        data = nest.GetStatus(rec)[0]['events']

        if model == 'Retina':
            scipy.io.savemat(data_folder + '/recorder_' + p_name + '_' + model + '.mat',
                             mdict={'senders': data['senders'],
                                    'rate': data['rate']})
        else:
            scipy.io.savemat(data_folder + '/recorder_' + p_name + '_' + model + '.mat',
                             mdict={'senders': data['senders'],
                                    'V_m': data['V_m'],
                                    'I_syn_AMPA': data['I_syn_AMPA'],
                                    'I_syn_NMDA': data['I_syn_NMDA'],
                                    'I_syn_GABA_A': data['I_syn_GABA_A'],
                                    'I_syn_GABA_B': data['I_syn_GABA_B'],
                                    'g_AMPA': data['g_AMPA'],
                                    'g_NMDA': data['g_NMDA'],
                                    'g_GABAA': data['g_GABAA'],
                                    'g_GABAB': data['g_GABAB']} )



    print('save raster images')
    plt.close()
    for rec, population, model in detectors:
        spikes = nest.GetStatus(rec, 'events')[0]

        # Get name of population
        for p in range(0, len(population_name), 1):
            if population_name[p]['population'] == population:
                p_name = population_name[p]['name']

        if len(nest.GetStatus(rec)[0]['events']['senders']) > 3:
            raster = raster_plot.from_device(rec, hist=True)
            pylab.title( p_name + '_' + model )
            f = raster[0].figure
            f.set_size_inches(15, 9)
            f.savefig(data_folder + 'spikes_' + p_name + '_' + model + '.png', dpi=100)
            plt.close()

            # Set filename and save spike data
            filename = data_folder + 'spike_' + p_name + '_' + model + '.pickle'
            pickle.dump(spikes, open(filename, 'w'))
            scipy.io.savemat(data_folder + '/spike_' + p_name + '_' + model + '.mat', mdict={'senders': spikes['senders'], 'times': spikes['times']})

            #filename_AMPA = data_folder + 'connection_' + p_name + '_AMPA_syn' + '.dat'
            #tp.DumpLayerConnections(population, 'AMPA_syn', filename_AMPA)

            '''
            filename_AMPA = data_folder + 'connection_' + p_name + '_AMPA_syn' + '.dat'
            filename_NMDA = data_folder + 'connection_' + p_name + '_NMDA_syn' + '.dat'
            filename_GABAA = data_folder + 'connection_' + p_name + '_GABA_A_syn' + '.dat'
            filename_GABAB = data_folder + 'connection_' + p_name + '_GABA_B_syn' + '.dat'
            tp.DumpLayerConnections(population, 'AMPA_syn', filename_AMPA)
            tp.DumpLayerConnections(population, 'NMDA_syn', filename_NMDA)
            tp.DumpLayerConnections(population, 'GABA_A_syn', filename_GABAA)
            tp.DumpLayerConnections(population, 'GABA_B_syn', filename_GABAB)
            '''
    '''
    for p in range(0, len(population_name), 1):

        population = population_name[p]['population']
        p_name = population_name[p]['name']
        filename_nodes = data_folder + '/gid_' + p_name + '.dat'

        tp.DumpLayerNodes(population, filename_nodes)
    '''

    network_script = Params['network'] + '.py'
    shutil.copy2(network_script, Params['data_folder'] + network_script)

    print('end')