'''
Neuron simulator export for:

Components:
    null (Type: notes)
    synInput (Type: expTwoSynapse:  tauRise=0.001 (SI time) tauDecay=0.005 (SI time) peakTime=0.002011797390542625 (SI time) waveformFactor=1.8691859765265255 (dimensionless) gbase=8.0E-9 (SI conductance) erev=0.02 (SI voltage))
    iclamp0 (Type: pulseGenerator:  delay=0.02 (SI time) duration=0.8 (SI time) amplitude=1.0000000000000002E-10 (SI current))
    spikeGenPoisson (Type: spikeGeneratorPoisson:  averageRate=50.0 (SI per_time) SMALL_TIME=1.0000000000000002E-12 (SI time))
    poissonFiringSyn (Type: poissonFiringSynapse:  averageRate=10.0 (SI per_time) averageIsi=0.1 (SI time) SMALL_TIME=1.0000000000000002E-12 (SI time))
    poissonFiringSyn100Hz (Type: poissonFiringSynapse:  averageRate=100.0 (SI per_time) averageIsi=0.01 (SI time) SMALL_TIME=1.0000000000000002E-12 (SI time))
    passiveChan (Type: ionChannelHH:  conductance=1.0E-11 (SI conductance))
    naChan (Type: ionChannelHH:  conductance=1.0E-11 (SI conductance))
    kChan (Type: ionChannelHH:  conductance=1.0E-11 (SI conductance))
    hhcell (Type: cell)
    ampa (Type: expTwoSynapse:  tauRise=0.001 (SI time) tauDecay=0.002 (SI time) peakTime=0.0013862943611198907 (SI time) waveformFactor=4.0 (dimensionless) gbase=2.0E-9 (SI conductance) erev=0.0 (SI voltage))
    Example3_Network (Type: network)
    SimExample3 (Type: Simulation:  length=1.0 (SI time) step=2.5E-5 (SI time))


    This NEURON file has been generated by org.neuroml.export (see https://github.com/NeuroML/org.neuroml.export)
         org.neuroml.export  v1.8.1
         org.neuroml.model   v1.8.1
         jLEMS               v0.10.6

'''

import neuron

import time
import datetime
import sys

import hashlib
h = neuron.h
h.load_file("stdlib.hoc")

h.load_file("stdgui.hoc")

h("objref p")
h("p = new PythonObject()")

class NeuronSimulation():

    def __init__(self, tstop, dt, seed=5678):

        print("\n    Starting simulation in NEURON of %sms generated from NeuroML2 model...\n"%tstop)

        self.setup_start = time.time()
        self.seed = seed
        import socket
        self.report_file = open('report.SimExample3.txt','w')
        print('Simulator version:  %s'%h.nrnversion())
        self.report_file.write('# Report of running simulation with %s\n'%h.nrnversion())
        self.report_file.write('Simulator=NEURON\n')
        self.report_file.write('SimulatorVersion=%s\n'%h.nrnversion())

        self.report_file.write('SimulationFile=%s\n'%__file__)
        self.report_file.write('PythonVersion=%s\n'%sys.version.replace('\n',' '))
        print('Python version:     %s'%sys.version.replace('\n',' '))
        self.report_file.write('NeuroMLExportVersion=1.8.1\n')
        self.report_file.write('SimulationSeed=%s\n'%self.seed)
        self.report_file.write('Hostname=%s\n'%socket.gethostname())
        self.randoms = []
        self.next_global_id = 0  # Used in Random123 classes for elements using random(), etc. 

        self.next_spiking_input_id = 0  # Used in Random123 classes for elements using random(), etc. 

        '''
        Adding simulation Component(id=SimExample3 type=Simulation) of network/component: Example3_Network (Type: network)
        
        '''
        # ######################   Population: pop0
        print("Population pop0 contains 5 instance(s) of component: hhcell of type: cell")

        h.load_file("hhcell.hoc")
        a_pop0 = []
        h("{ n_pop0 = 5 }")
        h("objectvar a_pop0[n_pop0]")
        for i in range(int(h.n_pop0)):
            h("a_pop0[%i] = new hhcell()"%i)
            h("access a_pop0[%i].soma"%i)

            self.next_global_id+=1

        h("{ a_pop0[0].position(966.45355, 44.07326, 7.49147) }")
        h("{ a_pop0[1].position(910.97595, 93.9269, 582.2276) }")
        h("{ a_pop0[2].position(671.5635, 8.393823, 766.48096) }")
        h("{ a_pop0[3].position(236.80977, 3.081402, 788.7727) }")
        h("{ a_pop0[4].position(346.08896, 62.328148, 615.8157) }")

        h("proc initialiseV_pop0() { for i = 0, n_pop0-1 { a_pop0[i].set_initial_v() } }")
        h("objref fih_pop0")
        h('{fih_pop0 = new FInitializeHandler(0, "initialiseV_pop0()")}')

        h("proc initialiseIons_pop0() { for i = 0, n_pop0-1 { a_pop0[i].set_initial_ion_properties() } }")
        h("objref fih_ion_pop0")
        h('{fih_ion_pop0 = new FInitializeHandler(1, "initialiseIons_pop0()")}')

        # ######################   Population: pop1
        print("Population pop1 contains 10 instance(s) of component: hhcell of type: cell")

        h.load_file("hhcell.hoc")
        a_pop1 = []
        h("{ n_pop1 = 10 }")
        h("objectvar a_pop1[n_pop1]")
        for i in range(int(h.n_pop1)):
            h("a_pop1[%i] = new hhcell()"%i)
            h("access a_pop1[%i].soma"%i)

            self.next_global_id+=1

        h("{ a_pop1[0].position(148.55464, 218.30907, 114.41297) }")
        h("{ a_pop1[1].position(14.61878, 248.67516, 964.90155) }")
        h("{ a_pop1[2].position(64.56228, 254.10883, 465.89856) }")
        h("{ a_pop1[3].position(601.46344, 208.89288, 579.0027) }")
        h("{ a_pop1[4].position(269.5855, 255.64325, 644.6342) }")
        h("{ a_pop1[5].position(481.03638, 235.52391, 249.15211) }")
        h("{ a_pop1[6].position(933.5155, 245.3388, 530.1612) }")
        h("{ a_pop1[7].position(19.299566, 250.8102, 5.780237) }")
        h("{ a_pop1[8].position(143.76843, 247.2827, 377.34744) }")
        h("{ a_pop1[9].position(54.175198, 258.75284, 164.00322) }")

        h("proc initialiseV_pop1() { for i = 0, n_pop1-1 { a_pop1[i].set_initial_v() } }")
        h("objref fih_pop1")
        h('{fih_pop1 = new FInitializeHandler(0, "initialiseV_pop1()")}')

        h("proc initialiseIons_pop1() { for i = 0, n_pop1-1 { a_pop1[i].set_initial_ion_properties() } }")
        h("objref fih_ion_pop1")
        h('{fih_ion_pop1 = new FInitializeHandler(1, "initialiseIons_pop1()")}')

        # ######################   Projection: proj0
        print("Adding projection: proj0, from pop0 to pop1 with synapse ampa, 26 connection(s)")

        h("objectvar syn_proj0_ampa[26]")

        h("objectvar netConn_proj0_ampa[26]")

        # Connection 0: cell 0, seg 0 (0.5) [0.5 on a_pop0[0].soma] -> cell 1, seg 0 (0.5) [0.5 on a_pop1[1].soma], weight: 1.0, delay 0.0
        h("a_pop1[1].soma syn_proj0_ampa[0] = new ampa(0.5)")
        h("a_pop0[0].soma a_pop1[1].synlist.append(new NetCon(&v(0.5), syn_proj0_ampa[0], -20.0, 0.0, 1.0))") # *->cell

        # Connection 1: cell 0, seg 0 (0.5) [0.5 on a_pop0[0].soma] -> cell 5, seg 0 (0.5) [0.5 on a_pop1[5].soma], weight: 1.0, delay 0.0
        h("a_pop1[5].soma syn_proj0_ampa[1] = new ampa(0.5)")
        h("a_pop0[0].soma a_pop1[5].synlist.append(new NetCon(&v(0.5), syn_proj0_ampa[1], -20.0, 0.0, 1.0))") # *->cell

        # Connection 2: cell 0, seg 0 (0.5) [0.5 on a_pop0[0].soma] -> cell 6, seg 0 (0.5) [0.5 on a_pop1[6].soma], weight: 1.0, delay 0.0
        h("a_pop1[6].soma syn_proj0_ampa[2] = new ampa(0.5)")
        h("a_pop0[0].soma a_pop1[6].synlist.append(new NetCon(&v(0.5), syn_proj0_ampa[2], -20.0, 0.0, 1.0))") # *->cell

        # Connection 3: cell 0, seg 0 (0.5) [0.5 on a_pop0[0].soma] -> cell 7, seg 0 (0.5) [0.5 on a_pop1[7].soma], weight: 1.0, delay 0.0
        h("a_pop1[7].soma syn_proj0_ampa[3] = new ampa(0.5)")
        h("a_pop0[0].soma a_pop1[7].synlist.append(new NetCon(&v(0.5), syn_proj0_ampa[3], -20.0, 0.0, 1.0))") # *->cell

        # Connection 4: cell 0, seg 0 (0.5) [0.5 on a_pop0[0].soma] -> cell 8, seg 0 (0.5) [0.5 on a_pop1[8].soma], weight: 1.0, delay 0.0
        h("a_pop1[8].soma syn_proj0_ampa[4] = new ampa(0.5)")
        h("a_pop0[0].soma a_pop1[8].synlist.append(new NetCon(&v(0.5), syn_proj0_ampa[4], -20.0, 0.0, 1.0))") # *->cell

        # Connection 5: cell 1, seg 0 (0.5) [0.5 on a_pop0[1].soma] -> cell 0, seg 0 (0.5) [0.5 on a_pop1[0].soma], weight: 1.0, delay 0.0
        h("a_pop1[0].soma syn_proj0_ampa[5] = new ampa(0.5)")
        h("a_pop0[1].soma a_pop1[0].synlist.append(new NetCon(&v(0.5), syn_proj0_ampa[5], -20.0, 0.0, 1.0))") # *->cell

        # Connection 6: cell 1, seg 0 (0.5) [0.5 on a_pop0[1].soma] -> cell 1, seg 0 (0.5) [0.5 on a_pop1[1].soma], weight: 1.0, delay 0.0
        h("a_pop1[1].soma syn_proj0_ampa[6] = new ampa(0.5)")
        h("a_pop0[1].soma a_pop1[1].synlist.append(new NetCon(&v(0.5), syn_proj0_ampa[6], -20.0, 0.0, 1.0))") # *->cell

        # Connection 7: cell 1, seg 0 (0.5) [0.5 on a_pop0[1].soma] -> cell 3, seg 0 (0.5) [0.5 on a_pop1[3].soma], weight: 1.0, delay 0.0
        h("a_pop1[3].soma syn_proj0_ampa[7] = new ampa(0.5)")
        h("a_pop0[1].soma a_pop1[3].synlist.append(new NetCon(&v(0.5), syn_proj0_ampa[7], -20.0, 0.0, 1.0))") # *->cell

        # Connection 8: cell 1, seg 0 (0.5) [0.5 on a_pop0[1].soma] -> cell 5, seg 0 (0.5) [0.5 on a_pop1[5].soma], weight: 1.0, delay 0.0
        h("a_pop1[5].soma syn_proj0_ampa[8] = new ampa(0.5)")
        h("a_pop0[1].soma a_pop1[5].synlist.append(new NetCon(&v(0.5), syn_proj0_ampa[8], -20.0, 0.0, 1.0))") # *->cell

        # Connection 9: cell 1, seg 0 (0.5) [0.5 on a_pop0[1].soma] -> cell 6, seg 0 (0.5) [0.5 on a_pop1[6].soma], weight: 1.0, delay 0.0
        h("a_pop1[6].soma syn_proj0_ampa[9] = new ampa(0.5)")
        h("a_pop0[1].soma a_pop1[6].synlist.append(new NetCon(&v(0.5), syn_proj0_ampa[9], -20.0, 0.0, 1.0))") # *->cell

        # Connection 10: cell 1, seg 0 (0.5) [0.5 on a_pop0[1].soma] -> cell 7, seg 0 (0.5) [0.5 on a_pop1[7].soma], weight: 1.0, delay 0.0
        h("a_pop1[7].soma syn_proj0_ampa[10] = new ampa(0.5)")
        h("a_pop0[1].soma a_pop1[7].synlist.append(new NetCon(&v(0.5), syn_proj0_ampa[10], -20.0, 0.0, 1.0))") # *->cell

        # Connection 11: cell 1, seg 0 (0.5) [0.5 on a_pop0[1].soma] -> cell 8, seg 0 (0.5) [0.5 on a_pop1[8].soma], weight: 1.0, delay 0.0
        h("a_pop1[8].soma syn_proj0_ampa[11] = new ampa(0.5)")
        h("a_pop0[1].soma a_pop1[8].synlist.append(new NetCon(&v(0.5), syn_proj0_ampa[11], -20.0, 0.0, 1.0))") # *->cell

        # Connection 12: cell 2, seg 0 (0.5) [0.5 on a_pop0[2].soma] -> cell 0, seg 0 (0.5) [0.5 on a_pop1[0].soma], weight: 1.0, delay 0.0
        h("a_pop1[0].soma syn_proj0_ampa[12] = new ampa(0.5)")
        h("a_pop0[2].soma a_pop1[0].synlist.append(new NetCon(&v(0.5), syn_proj0_ampa[12], -20.0, 0.0, 1.0))") # *->cell

        # Connection 13: cell 2, seg 0 (0.5) [0.5 on a_pop0[2].soma] -> cell 2, seg 0 (0.5) [0.5 on a_pop1[2].soma], weight: 1.0, delay 0.0
        h("a_pop1[2].soma syn_proj0_ampa[13] = new ampa(0.5)")
        h("a_pop0[2].soma a_pop1[2].synlist.append(new NetCon(&v(0.5), syn_proj0_ampa[13], -20.0, 0.0, 1.0))") # *->cell

        # Connection 14: cell 2, seg 0 (0.5) [0.5 on a_pop0[2].soma] -> cell 5, seg 0 (0.5) [0.5 on a_pop1[5].soma], weight: 1.0, delay 0.0
        h("a_pop1[5].soma syn_proj0_ampa[14] = new ampa(0.5)")
        h("a_pop0[2].soma a_pop1[5].synlist.append(new NetCon(&v(0.5), syn_proj0_ampa[14], -20.0, 0.0, 1.0))") # *->cell

        # Connection 15: cell 2, seg 0 (0.5) [0.5 on a_pop0[2].soma] -> cell 8, seg 0 (0.5) [0.5 on a_pop1[8].soma], weight: 1.0, delay 0.0
        h("a_pop1[8].soma syn_proj0_ampa[15] = new ampa(0.5)")
        h("a_pop0[2].soma a_pop1[8].synlist.append(new NetCon(&v(0.5), syn_proj0_ampa[15], -20.0, 0.0, 1.0))") # *->cell

        # Connection 16: cell 2, seg 0 (0.5) [0.5 on a_pop0[2].soma] -> cell 9, seg 0 (0.5) [0.5 on a_pop1[9].soma], weight: 1.0, delay 0.0
        h("a_pop1[9].soma syn_proj0_ampa[16] = new ampa(0.5)")
        h("a_pop0[2].soma a_pop1[9].synlist.append(new NetCon(&v(0.5), syn_proj0_ampa[16], -20.0, 0.0, 1.0))") # *->cell

        # Connection 17: cell 3, seg 0 (0.5) [0.5 on a_pop0[3].soma] -> cell 0, seg 0 (0.5) [0.5 on a_pop1[0].soma], weight: 1.0, delay 0.0
        h("a_pop1[0].soma syn_proj0_ampa[17] = new ampa(0.5)")
        h("a_pop0[3].soma a_pop1[0].synlist.append(new NetCon(&v(0.5), syn_proj0_ampa[17], -20.0, 0.0, 1.0))") # *->cell

        # Connection 18: cell 3, seg 0 (0.5) [0.5 on a_pop0[3].soma] -> cell 1, seg 0 (0.5) [0.5 on a_pop1[1].soma], weight: 1.0, delay 0.0
        h("a_pop1[1].soma syn_proj0_ampa[18] = new ampa(0.5)")
        h("a_pop0[3].soma a_pop1[1].synlist.append(new NetCon(&v(0.5), syn_proj0_ampa[18], -20.0, 0.0, 1.0))") # *->cell

        # Connection 19: cell 3, seg 0 (0.5) [0.5 on a_pop0[3].soma] -> cell 2, seg 0 (0.5) [0.5 on a_pop1[2].soma], weight: 1.0, delay 0.0
        h("a_pop1[2].soma syn_proj0_ampa[19] = new ampa(0.5)")
        h("a_pop0[3].soma a_pop1[2].synlist.append(new NetCon(&v(0.5), syn_proj0_ampa[19], -20.0, 0.0, 1.0))") # *->cell

        # Connection 20: cell 3, seg 0 (0.5) [0.5 on a_pop0[3].soma] -> cell 5, seg 0 (0.5) [0.5 on a_pop1[5].soma], weight: 1.0, delay 0.0
        h("a_pop1[5].soma syn_proj0_ampa[20] = new ampa(0.5)")
        h("a_pop0[3].soma a_pop1[5].synlist.append(new NetCon(&v(0.5), syn_proj0_ampa[20], -20.0, 0.0, 1.0))") # *->cell

        # Connection 21: cell 3, seg 0 (0.5) [0.5 on a_pop0[3].soma] -> cell 9, seg 0 (0.5) [0.5 on a_pop1[9].soma], weight: 1.0, delay 0.0
        h("a_pop1[9].soma syn_proj0_ampa[21] = new ampa(0.5)")
        h("a_pop0[3].soma a_pop1[9].synlist.append(new NetCon(&v(0.5), syn_proj0_ampa[21], -20.0, 0.0, 1.0))") # *->cell

        # Connection 22: cell 4, seg 0 (0.5) [0.5 on a_pop0[4].soma] -> cell 2, seg 0 (0.5) [0.5 on a_pop1[2].soma], weight: 1.0, delay 0.0
        h("a_pop1[2].soma syn_proj0_ampa[22] = new ampa(0.5)")
        h("a_pop0[4].soma a_pop1[2].synlist.append(new NetCon(&v(0.5), syn_proj0_ampa[22], -20.0, 0.0, 1.0))") # *->cell

        # Connection 23: cell 4, seg 0 (0.5) [0.5 on a_pop0[4].soma] -> cell 4, seg 0 (0.5) [0.5 on a_pop1[4].soma], weight: 1.0, delay 0.0
        h("a_pop1[4].soma syn_proj0_ampa[23] = new ampa(0.5)")
        h("a_pop0[4].soma a_pop1[4].synlist.append(new NetCon(&v(0.5), syn_proj0_ampa[23], -20.0, 0.0, 1.0))") # *->cell

        # Connection 24: cell 4, seg 0 (0.5) [0.5 on a_pop0[4].soma] -> cell 5, seg 0 (0.5) [0.5 on a_pop1[5].soma], weight: 1.0, delay 0.0
        h("a_pop1[5].soma syn_proj0_ampa[24] = new ampa(0.5)")
        h("a_pop0[4].soma a_pop1[5].synlist.append(new NetCon(&v(0.5), syn_proj0_ampa[24], -20.0, 0.0, 1.0))") # *->cell

        # Connection 25: cell 4, seg 0 (0.5) [0.5 on a_pop0[4].soma] -> cell 9, seg 0 (0.5) [0.5 on a_pop1[9].soma], weight: 1.0, delay 0.0
        h("a_pop1[9].soma syn_proj0_ampa[25] = new ampa(0.5)")
        h("a_pop0[4].soma a_pop1[9].synlist.append(new NetCon(&v(0.5), syn_proj0_ampa[25], -20.0, 0.0, 1.0))") # *->cell

        print("Processing 1 input lists")

        # ######################   Input List: stim_pop0
        # Adding single input: Component(id=0 type=input)
        h("objref stim_pop0_0")
        h("a_pop0[0].soma { stim_pop0_0 = new poissonFiringSyn(0.5) } ")
        rand = h.Random()
        self.randoms.append(rand)
        #print("Seeding random generator on stim_pop0_0 with stim seed %s"%(self.seed))
        self._init_stim_randomizer(rand,"stim_pop0",0, self.seed)
        rand.negexp(1)
        h.stim_pop0_0.noiseFromRandom(rand)
        self.next_spiking_input_id+=1

        # Adding single input: Component(id=1 type=input)
        h("objref stim_pop0_1")
        h("a_pop0[1].soma { stim_pop0_1 = new poissonFiringSyn(0.5) } ")
        rand = h.Random()
        self.randoms.append(rand)
        #print("Seeding random generator on stim_pop0_1 with stim seed %s"%(self.seed))
        self._init_stim_randomizer(rand,"stim_pop0",1, self.seed)
        rand.negexp(1)
        h.stim_pop0_1.noiseFromRandom(rand)
        self.next_spiking_input_id+=1

        # Adding single input: Component(id=2 type=input)
        h("objref stim_pop0_2")
        h("a_pop0[2].soma { stim_pop0_2 = new poissonFiringSyn(0.5) } ")
        rand = h.Random()
        self.randoms.append(rand)
        #print("Seeding random generator on stim_pop0_2 with stim seed %s"%(self.seed))
        self._init_stim_randomizer(rand,"stim_pop0",2, self.seed)
        rand.negexp(1)
        h.stim_pop0_2.noiseFromRandom(rand)
        self.next_spiking_input_id+=1

        # Adding single input: Component(id=3 type=input)
        h("objref stim_pop0_3")
        h("a_pop0[3].soma { stim_pop0_3 = new poissonFiringSyn(0.5) } ")
        rand = h.Random()
        self.randoms.append(rand)
        #print("Seeding random generator on stim_pop0_3 with stim seed %s"%(self.seed))
        self._init_stim_randomizer(rand,"stim_pop0",3, self.seed)
        rand.negexp(1)
        h.stim_pop0_3.noiseFromRandom(rand)
        self.next_spiking_input_id+=1

        # Adding single input: Component(id=4 type=input)
        h("objref stim_pop0_4")
        h("a_pop0[4].soma { stim_pop0_4 = new poissonFiringSyn(0.5) } ")
        rand = h.Random()
        self.randoms.append(rand)
        #print("Seeding random generator on stim_pop0_4 with stim seed %s"%(self.seed))
        self._init_stim_randomizer(rand,"stim_pop0",4, self.seed)
        rand.negexp(1)
        h.stim_pop0_4.noiseFromRandom(rand)
        self.next_spiking_input_id+=1

        print("Finished processing 1 input lists")

        trec = h.Vector()
        trec.record(h._ref_t)

        h.tstop = tstop

        h.dt = dt

        h.steps_per_ms = 1/h.dt



        # ######################   File to save: SimExample3.pop0.v.dat (SimExample3_pop0_v_dat)
        # Column: pop0/0/hhcell/v
        h(' objectvar v_pop0_0_hhcell_v_SimExample3_pop0_v_dat ')
        h(' { v_pop0_0_hhcell_v_SimExample3_pop0_v_dat = new Vector() } ')
        h(' { v_pop0_0_hhcell_v_SimExample3_pop0_v_dat.record(&a_pop0[0].soma.v(0.5)) } ')
        h.v_pop0_0_hhcell_v_SimExample3_pop0_v_dat.resize((h.tstop * h.steps_per_ms) + 1)
        # Column: pop0/1/hhcell/v
        h(' objectvar v_pop0_1_hhcell_v_SimExample3_pop0_v_dat ')
        h(' { v_pop0_1_hhcell_v_SimExample3_pop0_v_dat = new Vector() } ')
        h(' { v_pop0_1_hhcell_v_SimExample3_pop0_v_dat.record(&a_pop0[1].soma.v(0.5)) } ')
        h.v_pop0_1_hhcell_v_SimExample3_pop0_v_dat.resize((h.tstop * h.steps_per_ms) + 1)
        # Column: pop0/2/hhcell/v
        h(' objectvar v_pop0_2_hhcell_v_SimExample3_pop0_v_dat ')
        h(' { v_pop0_2_hhcell_v_SimExample3_pop0_v_dat = new Vector() } ')
        h(' { v_pop0_2_hhcell_v_SimExample3_pop0_v_dat.record(&a_pop0[2].soma.v(0.5)) } ')
        h.v_pop0_2_hhcell_v_SimExample3_pop0_v_dat.resize((h.tstop * h.steps_per_ms) + 1)
        # Column: pop0/3/hhcell/v
        h(' objectvar v_pop0_3_hhcell_v_SimExample3_pop0_v_dat ')
        h(' { v_pop0_3_hhcell_v_SimExample3_pop0_v_dat = new Vector() } ')
        h(' { v_pop0_3_hhcell_v_SimExample3_pop0_v_dat.record(&a_pop0[3].soma.v(0.5)) } ')
        h.v_pop0_3_hhcell_v_SimExample3_pop0_v_dat.resize((h.tstop * h.steps_per_ms) + 1)
        # Column: pop0/4/hhcell/v
        h(' objectvar v_pop0_4_hhcell_v_SimExample3_pop0_v_dat ')
        h(' { v_pop0_4_hhcell_v_SimExample3_pop0_v_dat = new Vector() } ')
        h(' { v_pop0_4_hhcell_v_SimExample3_pop0_v_dat.record(&a_pop0[4].soma.v(0.5)) } ')
        h.v_pop0_4_hhcell_v_SimExample3_pop0_v_dat.resize((h.tstop * h.steps_per_ms) + 1)

        # ######################   File to save: time.dat (time)
        # Column: time
        h(' objectvar v_time ')
        h(' { v_time = new Vector() } ')
        h(' { v_time.record(&t) } ')
        h.v_time.resize((h.tstop * h.steps_per_ms) + 1)

        # ######################   File to save: SimExample3.pop1.v.dat (SimExample3_pop1_v_dat)
        # Column: pop1/0/hhcell/v
        h(' objectvar v_pop1_0_hhcell_v_SimExample3_pop1_v_dat ')
        h(' { v_pop1_0_hhcell_v_SimExample3_pop1_v_dat = new Vector() } ')
        h(' { v_pop1_0_hhcell_v_SimExample3_pop1_v_dat.record(&a_pop1[0].soma.v(0.5)) } ')
        h.v_pop1_0_hhcell_v_SimExample3_pop1_v_dat.resize((h.tstop * h.steps_per_ms) + 1)
        # Column: pop1/1/hhcell/v
        h(' objectvar v_pop1_1_hhcell_v_SimExample3_pop1_v_dat ')
        h(' { v_pop1_1_hhcell_v_SimExample3_pop1_v_dat = new Vector() } ')
        h(' { v_pop1_1_hhcell_v_SimExample3_pop1_v_dat.record(&a_pop1[1].soma.v(0.5)) } ')
        h.v_pop1_1_hhcell_v_SimExample3_pop1_v_dat.resize((h.tstop * h.steps_per_ms) + 1)
        # Column: pop1/2/hhcell/v
        h(' objectvar v_pop1_2_hhcell_v_SimExample3_pop1_v_dat ')
        h(' { v_pop1_2_hhcell_v_SimExample3_pop1_v_dat = new Vector() } ')
        h(' { v_pop1_2_hhcell_v_SimExample3_pop1_v_dat.record(&a_pop1[2].soma.v(0.5)) } ')
        h.v_pop1_2_hhcell_v_SimExample3_pop1_v_dat.resize((h.tstop * h.steps_per_ms) + 1)
        # Column: pop1/3/hhcell/v
        h(' objectvar v_pop1_3_hhcell_v_SimExample3_pop1_v_dat ')
        h(' { v_pop1_3_hhcell_v_SimExample3_pop1_v_dat = new Vector() } ')
        h(' { v_pop1_3_hhcell_v_SimExample3_pop1_v_dat.record(&a_pop1[3].soma.v(0.5)) } ')
        h.v_pop1_3_hhcell_v_SimExample3_pop1_v_dat.resize((h.tstop * h.steps_per_ms) + 1)
        # Column: pop1/4/hhcell/v
        h(' objectvar v_pop1_4_hhcell_v_SimExample3_pop1_v_dat ')
        h(' { v_pop1_4_hhcell_v_SimExample3_pop1_v_dat = new Vector() } ')
        h(' { v_pop1_4_hhcell_v_SimExample3_pop1_v_dat.record(&a_pop1[4].soma.v(0.5)) } ')
        h.v_pop1_4_hhcell_v_SimExample3_pop1_v_dat.resize((h.tstop * h.steps_per_ms) + 1)
        # Column: pop1/5/hhcell/v
        h(' objectvar v_pop1_5_hhcell_v_SimExample3_pop1_v_dat ')
        h(' { v_pop1_5_hhcell_v_SimExample3_pop1_v_dat = new Vector() } ')
        h(' { v_pop1_5_hhcell_v_SimExample3_pop1_v_dat.record(&a_pop1[5].soma.v(0.5)) } ')
        h.v_pop1_5_hhcell_v_SimExample3_pop1_v_dat.resize((h.tstop * h.steps_per_ms) + 1)
        # Column: pop1/6/hhcell/v
        h(' objectvar v_pop1_6_hhcell_v_SimExample3_pop1_v_dat ')
        h(' { v_pop1_6_hhcell_v_SimExample3_pop1_v_dat = new Vector() } ')
        h(' { v_pop1_6_hhcell_v_SimExample3_pop1_v_dat.record(&a_pop1[6].soma.v(0.5)) } ')
        h.v_pop1_6_hhcell_v_SimExample3_pop1_v_dat.resize((h.tstop * h.steps_per_ms) + 1)
        # Column: pop1/7/hhcell/v
        h(' objectvar v_pop1_7_hhcell_v_SimExample3_pop1_v_dat ')
        h(' { v_pop1_7_hhcell_v_SimExample3_pop1_v_dat = new Vector() } ')
        h(' { v_pop1_7_hhcell_v_SimExample3_pop1_v_dat.record(&a_pop1[7].soma.v(0.5)) } ')
        h.v_pop1_7_hhcell_v_SimExample3_pop1_v_dat.resize((h.tstop * h.steps_per_ms) + 1)
        # Column: pop1/8/hhcell/v
        h(' objectvar v_pop1_8_hhcell_v_SimExample3_pop1_v_dat ')
        h(' { v_pop1_8_hhcell_v_SimExample3_pop1_v_dat = new Vector() } ')
        h(' { v_pop1_8_hhcell_v_SimExample3_pop1_v_dat.record(&a_pop1[8].soma.v(0.5)) } ')
        h.v_pop1_8_hhcell_v_SimExample3_pop1_v_dat.resize((h.tstop * h.steps_per_ms) + 1)
        # Column: pop1/9/hhcell/v
        h(' objectvar v_pop1_9_hhcell_v_SimExample3_pop1_v_dat ')
        h(' { v_pop1_9_hhcell_v_SimExample3_pop1_v_dat = new Vector() } ')
        h(' { v_pop1_9_hhcell_v_SimExample3_pop1_v_dat.record(&a_pop1[9].soma.v(0.5)) } ')
        h.v_pop1_9_hhcell_v_SimExample3_pop1_v_dat.resize((h.tstop * h.steps_per_ms) + 1)

        self.initialized = False

        self.sim_end = -1 # will be overwritten

        setup_end = time.time()
        self.setup_time = setup_end - self.setup_start
        print("Setting up the network to simulate took %f seconds"%(self.setup_time))

    def run(self):

        self.initialized = True
        sim_start = time.time()
        print("Running a simulation of %sms (dt = %sms; seed=%s)" % (h.tstop, h.dt, self.seed))

        try:
            h.run()
        except Exception as e:
            print("Exception running NEURON: %s" % (e))
            quit()


        self.sim_end = time.time()
        self.sim_time = self.sim_end - sim_start
        print("Finished NEURON simulation in %f seconds (%f mins)..."%(self.sim_time, self.sim_time/60.0))

        try:
            self.save_results()
        except Exception as e:
            print("Exception saving results of NEURON simulation: %s" % (e))
            quit()


    def advance(self):

        if not self.initialized:
            h.finitialize()
            self.initialized = True

        h.fadvance()


    ###############################################################################
    # Hash function to use in generation of random value
    # This is copied from NetPyNE: https://github.com/Neurosim-lab/netpyne/blob/master/netpyne/simFuncs.py
    ###############################################################################
    def _id32 (self,obj): 
        return int(hashlib.md5(obj.encode('utf-8')).hexdigest()[0:8],16)  # convert 8 first chars of md5 hash in base 16 to int


    ###############################################################################
    # Initialize the stim randomizer
    # This is copied from NetPyNE: https://github.com/Neurosim-lab/netpyne/blob/master/netpyne/simFuncs.py
    ###############################################################################
    def _init_stim_randomizer(self,rand, stimType, gid, seed): 
        #print("INIT STIM  %s; %s; %s; %s"%(rand, stimType, gid, seed))
        rand.Random123(self._id32(stimType), gid, seed)


    def save_results(self):

        print("Saving results at t=%s..."%h.t)

        if self.sim_end < 0: self.sim_end = time.time()


        # ######################   File to save: time.dat (time)
        py_v_time = [ t/1000 for t in h.v_time.to_python() ]  # Convert to Python list for speed...

        f_time_f2 = open('time.dat', 'w')
        num_points = len(py_v_time)  # Simulation may have been stopped before tstop...

        for i in range(num_points):
            f_time_f2.write('%f'% py_v_time[i])  # Save in SI units...
        f_time_f2.close()
        print("Saved data to: time.dat")

        # ######################   File to save: SimExample3.pop0.v.dat (SimExample3_pop0_v_dat)
        py_v_pop0_0_hhcell_v_SimExample3_pop0_v_dat = [ float(x  / 1000.0) for x in h.v_pop0_0_hhcell_v_SimExample3_pop0_v_dat.to_python() ]  # Convert to Python list for speed, variable has dim: voltage
        py_v_pop0_1_hhcell_v_SimExample3_pop0_v_dat = [ float(x  / 1000.0) for x in h.v_pop0_1_hhcell_v_SimExample3_pop0_v_dat.to_python() ]  # Convert to Python list for speed, variable has dim: voltage
        py_v_pop0_2_hhcell_v_SimExample3_pop0_v_dat = [ float(x  / 1000.0) for x in h.v_pop0_2_hhcell_v_SimExample3_pop0_v_dat.to_python() ]  # Convert to Python list for speed, variable has dim: voltage
        py_v_pop0_3_hhcell_v_SimExample3_pop0_v_dat = [ float(x  / 1000.0) for x in h.v_pop0_3_hhcell_v_SimExample3_pop0_v_dat.to_python() ]  # Convert to Python list for speed, variable has dim: voltage
        py_v_pop0_4_hhcell_v_SimExample3_pop0_v_dat = [ float(x  / 1000.0) for x in h.v_pop0_4_hhcell_v_SimExample3_pop0_v_dat.to_python() ]  # Convert to Python list for speed, variable has dim: voltage

        f_SimExample3_pop0_v_dat_f2 = open('SimExample3.pop0.v.dat', 'w')
        num_points = len(py_v_time)  # Simulation may have been stopped before tstop...

        for i in range(num_points):
            f_SimExample3_pop0_v_dat_f2.write('%e\t%e\t%e\t%e\t%e\t%e\t\n' % (py_v_time[i], py_v_pop0_0_hhcell_v_SimExample3_pop0_v_dat[i], py_v_pop0_1_hhcell_v_SimExample3_pop0_v_dat[i], py_v_pop0_2_hhcell_v_SimExample3_pop0_v_dat[i], py_v_pop0_3_hhcell_v_SimExample3_pop0_v_dat[i], py_v_pop0_4_hhcell_v_SimExample3_pop0_v_dat[i], ))
        f_SimExample3_pop0_v_dat_f2.close()
        print("Saved data to: SimExample3.pop0.v.dat")

        # ######################   File to save: SimExample3.pop1.v.dat (SimExample3_pop1_v_dat)
        py_v_pop1_0_hhcell_v_SimExample3_pop1_v_dat = [ float(x  / 1000.0) for x in h.v_pop1_0_hhcell_v_SimExample3_pop1_v_dat.to_python() ]  # Convert to Python list for speed, variable has dim: voltage
        py_v_pop1_1_hhcell_v_SimExample3_pop1_v_dat = [ float(x  / 1000.0) for x in h.v_pop1_1_hhcell_v_SimExample3_pop1_v_dat.to_python() ]  # Convert to Python list for speed, variable has dim: voltage
        py_v_pop1_2_hhcell_v_SimExample3_pop1_v_dat = [ float(x  / 1000.0) for x in h.v_pop1_2_hhcell_v_SimExample3_pop1_v_dat.to_python() ]  # Convert to Python list for speed, variable has dim: voltage
        py_v_pop1_3_hhcell_v_SimExample3_pop1_v_dat = [ float(x  / 1000.0) for x in h.v_pop1_3_hhcell_v_SimExample3_pop1_v_dat.to_python() ]  # Convert to Python list for speed, variable has dim: voltage
        py_v_pop1_4_hhcell_v_SimExample3_pop1_v_dat = [ float(x  / 1000.0) for x in h.v_pop1_4_hhcell_v_SimExample3_pop1_v_dat.to_python() ]  # Convert to Python list for speed, variable has dim: voltage
        py_v_pop1_5_hhcell_v_SimExample3_pop1_v_dat = [ float(x  / 1000.0) for x in h.v_pop1_5_hhcell_v_SimExample3_pop1_v_dat.to_python() ]  # Convert to Python list for speed, variable has dim: voltage
        py_v_pop1_6_hhcell_v_SimExample3_pop1_v_dat = [ float(x  / 1000.0) for x in h.v_pop1_6_hhcell_v_SimExample3_pop1_v_dat.to_python() ]  # Convert to Python list for speed, variable has dim: voltage
        py_v_pop1_7_hhcell_v_SimExample3_pop1_v_dat = [ float(x  / 1000.0) for x in h.v_pop1_7_hhcell_v_SimExample3_pop1_v_dat.to_python() ]  # Convert to Python list for speed, variable has dim: voltage
        py_v_pop1_8_hhcell_v_SimExample3_pop1_v_dat = [ float(x  / 1000.0) for x in h.v_pop1_8_hhcell_v_SimExample3_pop1_v_dat.to_python() ]  # Convert to Python list for speed, variable has dim: voltage
        py_v_pop1_9_hhcell_v_SimExample3_pop1_v_dat = [ float(x  / 1000.0) for x in h.v_pop1_9_hhcell_v_SimExample3_pop1_v_dat.to_python() ]  # Convert to Python list for speed, variable has dim: voltage

        f_SimExample3_pop1_v_dat_f2 = open('SimExample3.pop1.v.dat', 'w')
        num_points = len(py_v_time)  # Simulation may have been stopped before tstop...

        for i in range(num_points):
            f_SimExample3_pop1_v_dat_f2.write('%e\t%e\t%e\t%e\t%e\t%e\t%e\t%e\t%e\t%e\t%e\t\n' % (py_v_time[i], py_v_pop1_0_hhcell_v_SimExample3_pop1_v_dat[i], py_v_pop1_1_hhcell_v_SimExample3_pop1_v_dat[i], py_v_pop1_2_hhcell_v_SimExample3_pop1_v_dat[i], py_v_pop1_3_hhcell_v_SimExample3_pop1_v_dat[i], py_v_pop1_4_hhcell_v_SimExample3_pop1_v_dat[i], py_v_pop1_5_hhcell_v_SimExample3_pop1_v_dat[i], py_v_pop1_6_hhcell_v_SimExample3_pop1_v_dat[i], py_v_pop1_7_hhcell_v_SimExample3_pop1_v_dat[i], py_v_pop1_8_hhcell_v_SimExample3_pop1_v_dat[i], py_v_pop1_9_hhcell_v_SimExample3_pop1_v_dat[i], ))
        f_SimExample3_pop1_v_dat_f2.close()
        print("Saved data to: SimExample3.pop1.v.dat")

        save_end = time.time()
        save_time = save_end - self.sim_end
        print("Finished saving results in %f seconds"%(save_time))

        self.report_file.write('StartTime=%s\n'%datetime.datetime.fromtimestamp(self.setup_start).strftime('%Y-%m-%d %H:%M:%S'))
        self.report_file.write('SetupTime=%s\n'%self.setup_time)
        self.report_file.write('RealSimulationTime=%s\n'%self.sim_time)
        self.report_file.write('SimulationSaveTime=%s\n'%save_time)
        self.report_file.close()

        print("Saving report of simulation to %s"%('report.SimExample3.txt'))

        print("Done")

        quit()


if __name__ == '__main__':

    ns = NeuronSimulation(tstop=1000.0, dt=0.025, seed=5678)

    ns.run()

