docs: 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