def generate_and_run(simulation, 
                     simulator, 
                     network=None, 
                     return_results=False, 
                     base_dir=None,
                     target_dir=None,
                     num_processors=1):
    """
    Generates the network in the specified simulator and runs, if appropriate
    """

    if network == None:
        network = load_network_json(simulation.network)
    
    print_v("Generating network %s and running in simulator: %s..." % (network.id, simulator))
    
    if simulator == 'NEURON':
        
        _generate_neuron_files_from_neuroml(network, dir_for_mod_files=target_dir)
        
        from neuromllite.NeuronHandler import NeuronHandler
        
        nrn_handler = NeuronHandler()

        for c in network.cells:
            if c.neuroml2_source_file:
                src_dir = os.path.dirname(os.path.abspath(c.neuroml2_source_file))
                nrn_handler.executeHoc('load_file("%s/%s.hoc")' % (src_dir, c.id))
                
        generate_network(network, nrn_handler, generate_network, base_dir)
        if return_results:
            raise NotImplementedError("Reloading results not supported in Neuron yet...")


    elif simulator.lower() == 'sonata': # Will not "run" obviously...
        
        from neuromllite.SonataHandler import SonataHandler
        
        sonata_handler = SonataHandler()
        
        generate_network(network, sonata_handler, always_include_props=True, base_dir=base_dir)
    
        print_v("Done with Sonata...")


    elif simulator.lower().startswith('graph'): # Will not "run" obviously...
                           
        from neuromllite.GraphVizHandler import GraphVizHandler, engines
        

        try:
            if simulator[-1].isalpha():
                print simulator
                print simulator[5:]
                print simulator[5:-1]
                engine = engines[simulator[-1]]
                level = int(simulator[5:-1])
            else:
                engine = 'dot'
                level = int(simulator[5:])
        
        except Exception as e:
            print e
            print_v("Error parsing: %s"%simulator)
            print_v("Graphs of the network structure can be generated at many levels of detail (1-6, required) and laid out using GraphViz engines (d - dot (default); c - circo; n - neato; f - fdp), so use: -graph3c, -graph2, -graph4f etc.")
            return
        
        handler = GraphVizHandler(level, engine=engine, nl_network=network)
        
        generate_network(network, handler, always_include_props=True, base_dir=base_dir)
    
        print_v("Done with GraphViz...")
        
        
    elif simulator.lower().startswith('matrix'): # Will not "run" obviously...
                           
        from neuromllite.MatrixHandler import MatrixHandler
        
        try:
            level = int(simulator[6:])
        except:
            print_v("Error parsing: %s"%simulator)
            print_v("Matrices of the network structure can be generated at many levels of detail (1-n, required), so use: -matrix1, -matrix2, etc.")
            return
        
        handler = MatrixHandler(level, nl_network=network)
        
        generate_network(network, handler, always_include_props=True, base_dir=base_dir)
    
        print_v("Done with MatrixHandler...")
        

    elif simulator.startswith('PyNN'):
        
        #_generate_neuron_files_from_neuroml(network)
        simulator_name = simulator.split('_')[1].lower()
        
        
        from neuromllite.PyNNHandler import PyNNHandler
        
        pynn_handler = PyNNHandler(simulator_name, simulation.dt, network.id)
        
        syn_cell_params = {}
        for proj in network.projections:
            
            synapse = network.get_child(proj.synapse, 'synapses')
            post_pop = network.get_child(proj.postsynaptic, 'populations')
          
            if not post_pop.component in syn_cell_params:
                syn_cell_params[post_pop.component] = {}
            for p in synapse.parameters:
                post = ''
                if synapse.pynn_receptor_type == "excitatory":
                    post = '_E'
                elif synapse.pynn_receptor_type == "inhibitory":
                    post = '_I'
                syn_cell_params[post_pop.component]['%s%s' % (p, post)] = synapse.parameters[p]
                    
        
        cells = {}
        for c in network.cells:
            if c.pynn_cell:
                cell_params = {}
                if c.parameters: 
                    for p in c.parameters:
                        cell_params[p] = evaluate(c.parameters[p], network.parameters)
                
                dont_set_here = ['tau_syn_E', 'e_rev_E', 'tau_syn_I', 'e_rev_I']
                for d in dont_set_here:
                    if d in c.parameters:
                        raise Exception('Synaptic parameters like %s should be set '+
                          'in individual synapses, not in the list of parameters associated with the cell' % d)
                if c.id in syn_cell_params:
                    cell_params.update(syn_cell_params[c.id])
                print_v("Creating cell with params: %s" % cell_params)
                exec('cells["%s"] = pynn_handler.sim.%s(**cell_params)' % (c.id, c.pynn_cell))
                
                if c.pynn_cell != 'SpikeSourcePoisson':
                    exec("cells['%s'].default_initial_values['v'] = cells['%s'].parameter_space['v_rest'].base_value" % (c.id, c.id))
                
        pynn_handler.set_cells(cells)
        
        receptor_types = {}
        for s in network.synapses:
            if s.pynn_receptor_type:
                receptor_types[s.id] = s.pynn_receptor_type
                
        pynn_handler.set_receptor_types(receptor_types)
        
        for input_source in network.input_sources:
            if input_source.pynn_input:
                pynn_handler.add_input_source(input_source)
        
        generate_network(network, pynn_handler, always_include_props=True, base_dir=base_dir)
        
        for pid in pynn_handler.populations:
            pop = pynn_handler.populations[pid]
            if 'all' in simulation.recordTraces or pop.label in simulation.recordTraces:
                if pop.can_record('v'):
                    pop.record('v')
        
        
        pynn_handler.sim.run(simulation.duration)
        pynn_handler.sim.end()
        
        traces = {}
        events = {}
        
        if not 'NeuroML' in simulator:
            from neo.io import PyNNTextIO

            for pid in pynn_handler.populations:
                pop = pynn_handler.populations[pid]

                if 'all' in simulation.recordTraces or pop.label in simulation.recordTraces:
                    
                    filename = "%s.%s.v.dat" % (simulation.id, pop.label)
                    all_columns = []
                    print_v("Writing data for %s to %s" % (pop.label, filename))
                    for i in range(len(pop)):
                        if pop.can_record('v'):
                            ref = '%s[%i]'%(pop.label,i)
                            traces[ref] = []
                            data = pop.get_data('v', gather=False)
                            for segment in data.segments:
                                vm = segment.analogsignals[0].transpose()[i]
                                
                                if len(all_columns) == 0:
                                    tt = np.array([t * simulation.dt / 1000. for t in range(len(vm))])
                                    all_columns.append(tt)
                                vm_si = [float(v / 1000.) for v in vm]
                                traces[ref] = vm_si
                                all_columns.append(vm_si)
                                
                            times_vm = np.array(all_columns).transpose()
                                
                    np.savetxt(filename, times_vm, delimiter='\t', fmt='%s')
          
        
        if return_results:
            _print_result_info(traces, events)
            return traces, events

    elif simulator == 'NetPyNE':
        
        if target_dir==None:
            target_dir='./'
            
        _generate_neuron_files_from_neuroml(network, dir_for_mod_files=target_dir)
        
        from netpyne import specs
        from netpyne import sim
        # Note NetPyNE from this branch is required: https://github.com/Neurosim-lab/netpyne/tree/neuroml_updates
        from netpyne.conversion.neuromlFormat import NetPyNEBuilder
        
        import pprint; pp = pprint.PrettyPrinter(depth=6)
        
        netParams = specs.NetParams()
        simConfig = specs.SimConfig()
        netpyne_handler = NetPyNEBuilder(netParams, simConfig=simConfig, verbose=True)
        
        generate_network(network, netpyne_handler, base_dir=base_dir)
        
        netpyne_handler.finalise()
        
        simConfig = specs.SimConfig() 
        simConfig.tstop = simulation.duration
        simConfig.duration = simulation.duration
        simConfig.dt = simulation.dt
        simConfig.seed = simulation.seed
        simConfig.recordStep = simulation.dt
        
        simConfig.recordCells = ['all'] 
        simConfig.recordTraces = {}
        

        for pop in netpyne_handler.popParams.values():
            if 'all' in simulation.recordTraces or pop.id in simulation.recordTraces:
                for i in pop['cellsList']:
                    id = pop['pop']
                    index = i['cellLabel']
                    simConfig.recordTraces['v_%s_%s' % (id, index)] = {'sec':'soma', 'loc':0.5, 'var':'v', 'conds':{'pop':id, 'cellLabel':index}}

        simConfig.saveDat = True
        
        print_v("NetPyNE netParams: ")
        pp.pprint(netParams.todict())
        #print_v("NetPyNE simConfig: ")
        #pp.pprint(simConfig.todict())
        
        sim.initialize(netParams, simConfig)  # create network object and set cfg and net params

        sim.net.createPops()  
        cells = sim.net.createCells()                 # instantiate network cells based on defined populations  
        
        
        for proj_id in netpyne_handler.projection_infos.keys():
            projName, prePop, postPop, synapse, ptype = netpyne_handler.projection_infos[proj_id]
            print_v("Creating connections for %s (%s): %s->%s via %s" % (projName, ptype, prePop, postPop, synapse))
            
            preComp = netpyne_handler.pop_ids_vs_components[prePop]
            
            for conn in netpyne_handler.connections[projName]:
                
                pre_id, pre_seg, pre_fract, post_id, post_seg, post_fract, delay, weight = conn
                
                #connParam = {'delay':delay,'weight':weight,'synsPerConn':1, 'sec':post_seg, 'loc':post_fract, 'threshold':threshold}
                connParam = {'delay':delay, 'weight':weight, 'synsPerConn':1, 'sec':post_seg, 'loc':post_fract}
                
                if ptype == 'electricalProjection':

                    if weight != 1:
                        raise Exception('Cannot yet support inputs where weight !=1!')
                    connParam = {'synsPerConn': 1, 
                        'sec': post_seg, 
                        'loc': post_fract, 
                        'gapJunction': True, 
                        'weight': weight}
                else:
                    connParam = {'delay': delay,
                        'weight': weight,
                        'synsPerConn': 1, 
                        'sec': post_seg, 
                        'loc': post_fract} 
                        #'threshold': threshold}

                connParam['synMech'] = synapse

                if post_id in sim.net.gid2lid:  # check if postsyn is in this node's list of gids
                    sim.net._addCellConn(connParam, pre_id, post_id)
                    
                    
        stims = sim.net.addStims()                    # add external stimulation to cells (IClamps etc)
        simData = sim.setupRecording()              # setup variables to record for each cell (spikes, V traces, etc)
        sim.runSim()                      # run parallel Neuron simulation  
        sim.gatherData()                  # gather spiking data and cell info from each node
        sim.saveData()                    # save params, cell info and sim output to file (pickle,mat,txt,etc)
        
        if return_results:
            raise NotImplementedError("Reloading results not supported in NetPyNE yet...")
        
    elif simulator == 'jNeuroML' or  simulator == 'jNeuroML_NEURON' or simulator == 'jNeuroML_NetPyNE':

        from pyneuroml.lems import generate_lems_file_for_neuroml
        from pyneuroml import pynml

        lems_file_name = 'LEMS_%s.xml' % simulation.id

        nml_file_name, nml_doc = generate_neuroml2_from_network(network, base_dir=base_dir, target_dir=target_dir)
        included_files = ['PyNN.xml']

        for c in network.cells:        
            if c.lems_source_file:
                included_files.append(c.lems_source_file)
        '''
        if network.cells:
            for c in network.cells:
                included_files.append(c.neuroml2_source_file)
        '''
        if network.synapses:
            for s in network.synapses:  
                if s.lems_source_file:
                    included_files.append(s.lems_source_file)
                
        print_v("Generating LEMS file prior to running in %s" % simulator)
        
        pops_plot_save = []
        pops_spike_save = []
        gen_plots_for_quantities = {}
        gen_saves_for_quantities = {}
        
        for p in network.populations:
            
            if simulation.recordTraces and ('all' in simulation.recordTraces or p.id in simulation.recordTraces):
                pops_plot_save.append(p.id)
                
            if simulation.recordSpikes and ('all' in simulation.recordSpikes or p.id in simulation.recordSpikes):
                pops_spike_save.append(p.id)
                
            if simulation.recordRates and ('all' in simulation.recordRates or p.id in simulation.recordRates):
                size = evaluate(p.size, network.parameters)
                for i in range(size):
                    quantity = '%s/%i/%s/r' % (p.id, i, p.component)
                    gen_plots_for_quantities['%s_%i_r' % (p.id, i)] = [quantity]
                    gen_saves_for_quantities['%s_%i.r.dat' % (p.id, i)] = [quantity]
                
            if simulation.recordVariables:
                for var in simulation.recordVariables:
                    to_rec = simulation.recordVariables[var]
                    if ('all' in to_rec or p.id in to_rec):
                        size = evaluate(p.size, network.parameters)
                        for i in range(size):
                            quantity = '%s/%i/%s/%s' % (p.id, i, p.component,var)
                            gen_plots_for_quantities['%s_%i_%s' % (p.id, i, var)] = [quantity]
                            gen_saves_for_quantities['%s_%i.%s.dat' % (p.id, i, var)] = [quantity]
                
        
        generate_lems_file_for_neuroml(simulation.id, 
                                       nml_file_name, 
                                       network.id, 
                                       simulation.duration, 
                                       simulation.dt, 
                                       lems_file_name,
                                       target_dir=target_dir if target_dir else '.',
                                       nml_doc=nml_doc, # Use this if the nml doc has already been loaded (to avoid delay in reload)
                                       include_extra_files=included_files,
                                       
                                       gen_plots_for_all_v=False,
                                       plot_all_segments=False,
                                       gen_plots_for_quantities=gen_plots_for_quantities, # Dict with displays vs lists of quantity paths
                                       gen_plots_for_only_populations=pops_plot_save, # List of populations, all pops if = []
                                       
                                       gen_saves_for_all_v=False,
                                       save_all_segments=False,
                                       gen_saves_for_only_populations=pops_plot_save, # List of populations, all pops if = []
                                       gen_saves_for_quantities=gen_saves_for_quantities, # Dict with file names vs lists of quantity paths
                                       
                                       gen_spike_saves_for_all_somas=False,
                                       gen_spike_saves_for_only_populations=pops_spike_save, # List of populations, all pops if = []
                                       gen_spike_saves_for_cells={}, # Dict with file names vs lists of quantity paths
                                       spike_time_format='ID_TIME',
                                       
                                       copy_neuroml=True,
                                       lems_file_generate_seed=12345,
                                       report_file_name='report.%s.txt' % simulation.id,
                                       simulation_seed=simulation.seed if simulation.seed else 12345,
                                       verbose=True)
              
        lems_file_name = _locate_file(lems_file_name, target_dir)
        
        if simulator == 'jNeuroML':
            results = pynml.run_lems_with_jneuroml(lems_file_name, 
                                                   nogui=True, 
                                                   load_saved_data=return_results, 
                                                   reload_events=return_results)
        elif simulator == 'jNeuroML_NEURON':
            results = pynml.run_lems_with_jneuroml_neuron(lems_file_name, 
                                                          nogui=True, 
                                                          load_saved_data=return_results, 
                                                          reload_events=return_results)
        elif simulator == 'jNeuroML_NetPyNE':
            results = pynml.run_lems_with_jneuroml_netpyne(lems_file_name, 
                                                           nogui=True, 
                                                           verbose=True, 
                                                           load_saved_data=return_results, 
                                                           reload_events=return_results,
                                                           num_processors=num_processors)

        print_v("Finished running LEMS file %s in %s (returning results: %s)" % (lems_file_name, simulator, return_results))

        if return_results:
            traces, events = results
            _print_result_info(traces, events)
            return results
Generates the network in the specified simulator and runs, if appropriate