'''
NETPYNE simulator compliant 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 NETPYNE 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

'''
# Main NetPyNE script for: Example3_Network

# See https://github.com/Neurosim-lab/netpyne

from netpyne import specs  # import netpyne specs module
from netpyne import sim    # import netpyne sim module
from netpyne import __version__ as version

from neuron import h

import sys
import time
import datetime

class NetPyNESimulation():

    def __init__(self, tstop, dt, seed=123456789, save_json=False):

        self.setup_start = time.time()
        
        self.report_file = open('report.SimExample3.txt','w')
        self.report_file.write('# Report of running simulation with NetPyNE v%s\n'%version)
        self.report_file.write('Simulator=NetPyNE\n')
        self.report_file.write('SimulatorVersion=%s\n'%version)
        self.report_file.write('SimulationFile=%s\n'%__file__)
        self.report_file.write('PythonVersion=%s\n'%sys.version.replace('\n',' '))
        self.report_file.write('NeuronVersion=%s\n'%h.nrnversion())
        self.report_file.write('NeuroMLExportVersion=1.8.1\n')
        

        ###############################################################################
        # NETWORK PARAMETERS
        ###############################################################################

        self.nml2_file_name = 'Example3_Network.net.nml'

        ###############################################################################
        # SIMULATION PARAMETERS
        ###############################################################################

        self.simConfig = specs.SimConfig()   # object of class SimConfig to store the simulation configuration

        # Simulation parameters
        self.simConfig.duration = self.simConfig.tstop = tstop # Duration of the simulation, in ms
        self.simConfig.dt = dt # Internal integration timestep to use

        # Seeds for randomizers (connectivity, input stimulation and cell locations)
        # Note: locations and connections should be fully specified by the structure of the NeuroML,
        # so seeds for conn & loc shouldn't affect networks structure/behaviour
        self.simConfig.seeds = {'conn': 0, 'stim': 5678, 'loc': 0} 

        self.simConfig.createNEURONObj = 1  # create HOC objects when instantiating network
        self.simConfig.createPyStruct = 1  # create Python structure (simulator-independent) when instantiating network
        self.simConfig.verbose = False  # show detailed messages 
        
        # Recording 
        self.simConfig.recordCells = ['all']  
        self.simConfig.recordTraces = {}
        self.simConfig.saveCellSecs=False
        self.simConfig.saveCellConns=False
        self.simConfig.gatherOnlySimData=True 

                # For saving to file: SimExample3.pop0.v.dat (ref: SimExample3_pop0_v_dat)
                                
        # Column: pop0_0_hhcell_v: Pop: pop0; cell: 0; segment id: 0; segment name: soma; Neuron loc: soma(0.5); value: v (v)
        self.simConfig.recordTraces['SimExample3_pop0_v_dat_pop0_0_soma_v'] = {'sec':'soma','loc':0.5,'var':'v','conds':{'pop':'pop0','cellLabel':0}}
                                
        # Column: pop0_1_hhcell_v: Pop: pop0; cell: 1; segment id: 0; segment name: soma; Neuron loc: soma(0.5); value: v (v)
        self.simConfig.recordTraces['SimExample3_pop0_v_dat_pop0_1_soma_v'] = {'sec':'soma','loc':0.5,'var':'v','conds':{'pop':'pop0','cellLabel':1}}
                                
        # Column: pop0_2_hhcell_v: Pop: pop0; cell: 2; segment id: 0; segment name: soma; Neuron loc: soma(0.5); value: v (v)
        self.simConfig.recordTraces['SimExample3_pop0_v_dat_pop0_2_soma_v'] = {'sec':'soma','loc':0.5,'var':'v','conds':{'pop':'pop0','cellLabel':2}}
                                
        # Column: pop0_3_hhcell_v: Pop: pop0; cell: 3; segment id: 0; segment name: soma; Neuron loc: soma(0.5); value: v (v)
        self.simConfig.recordTraces['SimExample3_pop0_v_dat_pop0_3_soma_v'] = {'sec':'soma','loc':0.5,'var':'v','conds':{'pop':'pop0','cellLabel':3}}
                                
        # Column: pop0_4_hhcell_v: Pop: pop0; cell: 4; segment id: 0; segment name: soma; Neuron loc: soma(0.5); value: v (v)
        self.simConfig.recordTraces['SimExample3_pop0_v_dat_pop0_4_soma_v'] = {'sec':'soma','loc':0.5,'var':'v','conds':{'pop':'pop0','cellLabel':4}}
                        
                # For saving to file: SimExample3.pop1.v.dat (ref: SimExample3_pop1_v_dat)
                                
        # Column: pop1_0_hhcell_v: Pop: pop1; cell: 0; segment id: 0; segment name: soma; Neuron loc: soma(0.5); value: v (v)
        self.simConfig.recordTraces['SimExample3_pop1_v_dat_pop1_0_soma_v'] = {'sec':'soma','loc':0.5,'var':'v','conds':{'pop':'pop1','cellLabel':0}}
                                
        # Column: pop1_1_hhcell_v: Pop: pop1; cell: 1; segment id: 0; segment name: soma; Neuron loc: soma(0.5); value: v (v)
        self.simConfig.recordTraces['SimExample3_pop1_v_dat_pop1_1_soma_v'] = {'sec':'soma','loc':0.5,'var':'v','conds':{'pop':'pop1','cellLabel':1}}
                                
        # Column: pop1_2_hhcell_v: Pop: pop1; cell: 2; segment id: 0; segment name: soma; Neuron loc: soma(0.5); value: v (v)
        self.simConfig.recordTraces['SimExample3_pop1_v_dat_pop1_2_soma_v'] = {'sec':'soma','loc':0.5,'var':'v','conds':{'pop':'pop1','cellLabel':2}}
                                
        # Column: pop1_3_hhcell_v: Pop: pop1; cell: 3; segment id: 0; segment name: soma; Neuron loc: soma(0.5); value: v (v)
        self.simConfig.recordTraces['SimExample3_pop1_v_dat_pop1_3_soma_v'] = {'sec':'soma','loc':0.5,'var':'v','conds':{'pop':'pop1','cellLabel':3}}
                                
        # Column: pop1_4_hhcell_v: Pop: pop1; cell: 4; segment id: 0; segment name: soma; Neuron loc: soma(0.5); value: v (v)
        self.simConfig.recordTraces['SimExample3_pop1_v_dat_pop1_4_soma_v'] = {'sec':'soma','loc':0.5,'var':'v','conds':{'pop':'pop1','cellLabel':4}}
                                
        # Column: pop1_5_hhcell_v: Pop: pop1; cell: 5; segment id: 0; segment name: soma; Neuron loc: soma(0.5); value: v (v)
        self.simConfig.recordTraces['SimExample3_pop1_v_dat_pop1_5_soma_v'] = {'sec':'soma','loc':0.5,'var':'v','conds':{'pop':'pop1','cellLabel':5}}
                                
        # Column: pop1_6_hhcell_v: Pop: pop1; cell: 6; segment id: 0; segment name: soma; Neuron loc: soma(0.5); value: v (v)
        self.simConfig.recordTraces['SimExample3_pop1_v_dat_pop1_6_soma_v'] = {'sec':'soma','loc':0.5,'var':'v','conds':{'pop':'pop1','cellLabel':6}}
                                
        # Column: pop1_7_hhcell_v: Pop: pop1; cell: 7; segment id: 0; segment name: soma; Neuron loc: soma(0.5); value: v (v)
        self.simConfig.recordTraces['SimExample3_pop1_v_dat_pop1_7_soma_v'] = {'sec':'soma','loc':0.5,'var':'v','conds':{'pop':'pop1','cellLabel':7}}
                                
        # Column: pop1_8_hhcell_v: Pop: pop1; cell: 8; segment id: 0; segment name: soma; Neuron loc: soma(0.5); value: v (v)
        self.simConfig.recordTraces['SimExample3_pop1_v_dat_pop1_8_soma_v'] = {'sec':'soma','loc':0.5,'var':'v','conds':{'pop':'pop1','cellLabel':8}}
                                
        # Column: pop1_9_hhcell_v: Pop: pop1; cell: 9; segment id: 0; segment name: soma; Neuron loc: soma(0.5); value: v (v)
        self.simConfig.recordTraces['SimExample3_pop1_v_dat_pop1_9_soma_v'] = {'sec':'soma','loc':0.5,'var':'v','conds':{'pop':'pop1','cellLabel':9}}
                        
        
        self.simConfig.plotCells = ['all']

        self.simConfig.recordStim = True  # record spikes of cell stims
        self.simConfig.recordStep = self.simConfig.dt # Step size in ms to save data (eg. V traces, LFP, etc)

        # Analysis and plotting, see http://neurosimlab.org/netpyne/reference.html#analysis-related-functions
        self.simConfig.analysis['plotRaster'] = False  # Plot raster
        self.simConfig.analysis['plot2Dnet'] = False  # Plot 2D net cells and connections
        self.simConfig.analysis['plotSpikeHist'] = False # plot spike histogram
        self.simConfig.analysis['plotConn'] = False # plot network connectivity
        self.simConfig.analysis['plotSpikePSD'] = False # plot 3d architecture

        # Saving
        self.simConfig.filename = 'Example3_Network.txt'  # Set file output name
        self.simConfig.saveFileStep = self.simConfig.dt # step size in ms to save data to disk
        # self.simConfig.saveDat = True # save to dat file
        self.simConfig.saveJson = save_json # save to json file


    def run(self):

        ###############################################################################
        # IMPORT & RUN
        ###############################################################################

        print("Running a NetPyNE based simulation for %sms (dt: %sms) at %s degC"%(self.simConfig.duration, self.simConfig.dt, self.simConfig.hParams['celsius']))

        self.setup_sim_start = time.time()
        self.gids = sim.importNeuroML2SimulateAnalyze(self.nml2_file_name,self.simConfig)

        self.sim_end = time.time()
        self.setup_sim_time = self.sim_end - self.setup_sim_start
        print("Finished NetPyNE simulation in %f seconds (%f mins)..."%(self.setup_sim_time, self.setup_sim_time/60.0))

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


    def save_results(self):

        ###############################################################################
        #   Saving data (this ensures the data gets saved in the format/files 
        #   as specified in the LEMS <Simulation> element)
        ###############################################################################

        if sim.rank==0: 
        
            print("Saving traces to file: SimExample3.pop0.v.dat (ref: SimExample3_pop0_v_dat)")

                
            # Column: t
            col_SimExample3_pop0_v_dat_t = [i*self.simConfig.dt for i in range(int(self.simConfig.duration/self.simConfig.dt))]
                        
            # Column: pop0_0_hhcell_v: Pop: pop0; cell: 0; segment id: 0; segment name: soma; value: v
            col_SimExample3_pop0_v_dat_pop0_0_hhcell_v = sim.allSimData['SimExample3_pop0_v_dat_pop0_0_soma_v']['cell_%s'%self.gids['pop0'][0]]
                        
            # Column: pop0_1_hhcell_v: Pop: pop0; cell: 1; segment id: 0; segment name: soma; value: v
            col_SimExample3_pop0_v_dat_pop0_1_hhcell_v = sim.allSimData['SimExample3_pop0_v_dat_pop0_1_soma_v']['cell_%s'%self.gids['pop0'][1]]
                        
            # Column: pop0_2_hhcell_v: Pop: pop0; cell: 2; segment id: 0; segment name: soma; value: v
            col_SimExample3_pop0_v_dat_pop0_2_hhcell_v = sim.allSimData['SimExample3_pop0_v_dat_pop0_2_soma_v']['cell_%s'%self.gids['pop0'][2]]
                        
            # Column: pop0_3_hhcell_v: Pop: pop0; cell: 3; segment id: 0; segment name: soma; value: v
            col_SimExample3_pop0_v_dat_pop0_3_hhcell_v = sim.allSimData['SimExample3_pop0_v_dat_pop0_3_soma_v']['cell_%s'%self.gids['pop0'][3]]
                        
            # Column: pop0_4_hhcell_v: Pop: pop0; cell: 4; segment id: 0; segment name: soma; value: v
            col_SimExample3_pop0_v_dat_pop0_4_hhcell_v = sim.allSimData['SimExample3_pop0_v_dat_pop0_4_soma_v']['cell_%s'%self.gids['pop0'][4]]
                
            dat_file_SimExample3_pop0_v_dat = open('SimExample3.pop0.v.dat', 'w')
            for i in range(len(col_SimExample3_pop0_v_dat_t)):
                dat_file_SimExample3_pop0_v_dat.write( '%s\t'%(col_SimExample3_pop0_v_dat_t[i]/1000.0) +  '%s\t'%(col_SimExample3_pop0_v_dat_pop0_0_hhcell_v[i]/1000.0) +  '%s\t'%(col_SimExample3_pop0_v_dat_pop0_1_hhcell_v[i]/1000.0) +  '%s\t'%(col_SimExample3_pop0_v_dat_pop0_2_hhcell_v[i]/1000.0) +  '%s\t'%(col_SimExample3_pop0_v_dat_pop0_3_hhcell_v[i]/1000.0) +  '%s\t'%(col_SimExample3_pop0_v_dat_pop0_4_hhcell_v[i]/1000.0) +  '\n')
            dat_file_SimExample3_pop0_v_dat.close()

        
            print("Saving traces to file: SimExample3.pop1.v.dat (ref: SimExample3_pop1_v_dat)")

                
            # Column: t
            col_SimExample3_pop1_v_dat_t = [i*self.simConfig.dt for i in range(int(self.simConfig.duration/self.simConfig.dt))]
                        
            # Column: pop1_0_hhcell_v: Pop: pop1; cell: 0; segment id: 0; segment name: soma; value: v
            col_SimExample3_pop1_v_dat_pop1_0_hhcell_v = sim.allSimData['SimExample3_pop1_v_dat_pop1_0_soma_v']['cell_%s'%self.gids['pop1'][0]]
                        
            # Column: pop1_1_hhcell_v: Pop: pop1; cell: 1; segment id: 0; segment name: soma; value: v
            col_SimExample3_pop1_v_dat_pop1_1_hhcell_v = sim.allSimData['SimExample3_pop1_v_dat_pop1_1_soma_v']['cell_%s'%self.gids['pop1'][1]]
                        
            # Column: pop1_2_hhcell_v: Pop: pop1; cell: 2; segment id: 0; segment name: soma; value: v
            col_SimExample3_pop1_v_dat_pop1_2_hhcell_v = sim.allSimData['SimExample3_pop1_v_dat_pop1_2_soma_v']['cell_%s'%self.gids['pop1'][2]]
                        
            # Column: pop1_3_hhcell_v: Pop: pop1; cell: 3; segment id: 0; segment name: soma; value: v
            col_SimExample3_pop1_v_dat_pop1_3_hhcell_v = sim.allSimData['SimExample3_pop1_v_dat_pop1_3_soma_v']['cell_%s'%self.gids['pop1'][3]]
                        
            # Column: pop1_4_hhcell_v: Pop: pop1; cell: 4; segment id: 0; segment name: soma; value: v
            col_SimExample3_pop1_v_dat_pop1_4_hhcell_v = sim.allSimData['SimExample3_pop1_v_dat_pop1_4_soma_v']['cell_%s'%self.gids['pop1'][4]]
                        
            # Column: pop1_5_hhcell_v: Pop: pop1; cell: 5; segment id: 0; segment name: soma; value: v
            col_SimExample3_pop1_v_dat_pop1_5_hhcell_v = sim.allSimData['SimExample3_pop1_v_dat_pop1_5_soma_v']['cell_%s'%self.gids['pop1'][5]]
                        
            # Column: pop1_6_hhcell_v: Pop: pop1; cell: 6; segment id: 0; segment name: soma; value: v
            col_SimExample3_pop1_v_dat_pop1_6_hhcell_v = sim.allSimData['SimExample3_pop1_v_dat_pop1_6_soma_v']['cell_%s'%self.gids['pop1'][6]]
                        
            # Column: pop1_7_hhcell_v: Pop: pop1; cell: 7; segment id: 0; segment name: soma; value: v
            col_SimExample3_pop1_v_dat_pop1_7_hhcell_v = sim.allSimData['SimExample3_pop1_v_dat_pop1_7_soma_v']['cell_%s'%self.gids['pop1'][7]]
                        
            # Column: pop1_8_hhcell_v: Pop: pop1; cell: 8; segment id: 0; segment name: soma; value: v
            col_SimExample3_pop1_v_dat_pop1_8_hhcell_v = sim.allSimData['SimExample3_pop1_v_dat_pop1_8_soma_v']['cell_%s'%self.gids['pop1'][8]]
                        
            # Column: pop1_9_hhcell_v: Pop: pop1; cell: 9; segment id: 0; segment name: soma; value: v
            col_SimExample3_pop1_v_dat_pop1_9_hhcell_v = sim.allSimData['SimExample3_pop1_v_dat_pop1_9_soma_v']['cell_%s'%self.gids['pop1'][9]]
                
            dat_file_SimExample3_pop1_v_dat = open('SimExample3.pop1.v.dat', 'w')
            for i in range(len(col_SimExample3_pop1_v_dat_t)):
                dat_file_SimExample3_pop1_v_dat.write( '%s\t'%(col_SimExample3_pop1_v_dat_t[i]/1000.0) +  '%s\t'%(col_SimExample3_pop1_v_dat_pop1_0_hhcell_v[i]/1000.0) +  '%s\t'%(col_SimExample3_pop1_v_dat_pop1_1_hhcell_v[i]/1000.0) +  '%s\t'%(col_SimExample3_pop1_v_dat_pop1_2_hhcell_v[i]/1000.0) +  '%s\t'%(col_SimExample3_pop1_v_dat_pop1_3_hhcell_v[i]/1000.0) +  '%s\t'%(col_SimExample3_pop1_v_dat_pop1_4_hhcell_v[i]/1000.0) +  '%s\t'%(col_SimExample3_pop1_v_dat_pop1_5_hhcell_v[i]/1000.0) +  '%s\t'%(col_SimExample3_pop1_v_dat_pop1_6_hhcell_v[i]/1000.0) +  '%s\t'%(col_SimExample3_pop1_v_dat_pop1_7_hhcell_v[i]/1000.0) +  '%s\t'%(col_SimExample3_pop1_v_dat_pop1_8_hhcell_v[i]/1000.0) +  '%s\t'%(col_SimExample3_pop1_v_dat_pop1_9_hhcell_v[i]/1000.0) +  '\n')
            dat_file_SimExample3_pop1_v_dat.close()

        
        
            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('RealSetupAndSimulationTime=%s\n'%self.setup_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'))
        
if __name__ == '__main__':

    save_json = '-json' in sys.argv

    ns = NetPyNESimulation(tstop=1000.0, dt=0.025, seed=5678, save_json=save_json)

    ns.run()

    if '-nogui' in sys.argv:
        quit()
