int Fun4All_G4_sPHENIX(
		       const int nEvents = 10000,
		       const char * inputFile = "/sphenix/sim//sim01/production/2016-07-21/single_particle/spacal2d/fieldmap/G4Hits_sPHENIX_e-_eta0_8GeV-0002.root",
		       const char * outputFile = "G4sPHENIXCells.root",
           const char * embed_input_file = "/sphenix/sim/sim01/production/2016-07-12/sHijing/spacal2d/G4Hits_sPHENIX_sHijing-0-4.4fm.list"
		       )
{

  //===============
  // Input options
  //===============

  // Either:
  // read previously generated g4-hits files, in this case it opens a DST and skips
  // the simulations step completely. The G4Setup macro is only loaded to get information
  // about the number of layers used for the cell reco code
  //
  // In case reading production output, please double check your G4Setup_sPHENIX.C and G4_*.C consistent with those in the production macro folder
  // E.g. /sphenix/sim//sim01/production/2016-07-21/single_particle/spacal2d/
  const bool readhits = false;
  // Or:
  // read files in HepMC format (typically output from event generators like hijing or pythia)
  const bool readhepmc = false; // read HepMC files
  // Or:
  // Use particle generator
  const bool runpythia8 = true;
  const bool runpythia6 = false;
  // And
  // Further choose to embed newly simulated events to a previous simulation. Not compatible with `readhits = true`
  // In case embedding into a production output, please double check your G4Setup_sPHENIX.C and G4_*.C consistent with those in the production macro folder
  // E.g. /sphenix/sim//sim01/production/2016-07-21/single_particle/spacal2d/
  const bool do_embedding = false;

  //======================
  // What to run
  //======================

  bool do_bbc = false;

  bool do_pipe = false;

  bool do_svtx = false;
  bool do_svtx_cell = false;
  bool do_svtx_track = false;
  bool do_svtx_eval = false;

  bool do_preshower = false;

  bool do_cemc = false;
  bool do_cemc_cell = false;
  bool do_cemc_twr = false;
  bool do_cemc_cluster = false;
  bool do_cemc_eval = false;

  bool do_hcalin = false;
  bool do_hcalin_cell = false;
  bool do_hcalin_twr = false;
  bool do_hcalin_cluster = false;
  bool do_hcalin_eval = false;

  bool do_magnet = false;

  bool do_hcalout = false;
  bool do_hcalout_cell = false;
  bool do_hcalout_twr = false;
  bool do_hcalout_cluster = false;
  bool do_hcalout_eval = false;

  bool do_global = false;
  bool do_global_fastsim = false;

  bool do_jet_reco = true;
  bool do_jet_eval = false;

  bool do_dst_compress = false;

  //Option to convert DST to human command readable TTree for quick poke around the outputs
  bool do_DSTReader = true;
  //---------------
  // Load libraries
  //---------------

  gSystem->Load("libfun4all.so");
  gSystem->Load("libg4detectors.so");
  gSystem->Load("libphhepmc.so");
  gSystem->Load("libg4testbench.so");
  gSystem->Load("libg4hough.so");
  gSystem->Load("libg4calo.so");
  gSystem->Load("libg4eval.so");

  // establish the geometry and reconstruction setup
  gROOT->LoadMacro("G4Setup_sPHENIX.C");
  G4Init(do_svtx,do_preshower,do_cemc,do_hcalin,do_magnet,do_hcalout,do_pipe);

  int absorberactive = 1; // set to 1 to make all absorbers active volumes
    const string magfield = "0"; // if like float -> solenoidal field in T, if string use as fieldmap name (including path)
//  const string magfield = "/phenix/upgrades/decadal/fieldmaps/sPHENIX.2d.root"; // if like float -> solenoidal field in T, if string use as fieldmap name (including path)
  const float magfield_rescale = 1.4/1.5; // scale the map to a 1.4 T field

  //---------------
  // Fun4All server
  //---------------

  Fun4AllServer *se = Fun4AllServer::instance();
  se->Verbosity(1);
  // just if we set some flags somewhere in this macro
  recoConsts *rc = recoConsts::instance();
  // By default every random number generator uses
  // PHRandomSeed() which reads /dev/urandom to get its seed
  // if the RANDOMSEED flag is set its value is taken as seed
  // You ca neither set this to a random value using PHRandomSeed()
  // which will make all seeds identical (not sure what the point of
  // this would be:
  //  rc->set_IntFlag("RANDOMSEED",PHRandomSeed());
  // or set it to a fixed value so you can debug your code
  // rc->set_IntFlag("RANDOMSEED", 12345);

  //-----------------
  // Event generation
  //-----------------

  if (readhits)
    {
      // Get the hits from a file
      // The input manager is declared later

      if (do_embedding)
       {
         cout <<"Do not support read hits and embed background at the same time."<<endl;
         exit(1);
       }

    }
  else if (readhepmc)
    {
      // this module is needed to read the HepMC records into our G4 sims
      // but only if you read HepMC input files
      HepMCNodeReader *hr = new HepMCNodeReader();
      se->registerSubsystem(hr);
    }
  else if (runpythia8)
    {
      gSystem->Load("libPHPythia8.so");


      PHPy8JetTrigger *theTrigger = new PHPy8JetTrigger();
//      theTrigger->Verbosity(10);
      theTrigger->SetEtaHighLow(-1, 1);
      theTrigger->SetJetR(.4);
      theTrigger->SetMinJetPt(25);

      PHPythia8* pythia8 = new PHPythia8();
      // see coresoftware/generators/PHPythia8 for example config
      pythia8->set_config_file("phpythia8.cfg");

      pythia8->beam_vertex_parameters(0,0,0,0,0,5);
      pythia8->register_trigger(theTrigger);
//      pythia8->set_trigger_AND();

      se->registerSubsystem(pythia8);
      pythia8->print_config();
//      pythia8->Verbosity(10);

      HepMCNodeReader *hr = new HepMCNodeReader();
      se->registerSubsystem(hr);
    }
  else if (runpythia6)
    {
      gSystem->Load("libPHPythia6.so");

      PHPythia6 *pythia6 = new PHPythia6();
      pythia6->set_config_file("phpythia6.cfg");
      se->registerSubsystem(pythia6);

      HepMCNodeReader *hr = new HepMCNodeReader();
      se->registerSubsystem(hr);
    }
  else
    {
      // toss low multiplicity dummy events
      PHG4SimpleEventGenerator *gen = new PHG4SimpleEventGenerator();
      gen->add_particles("e-",1); // mu+,e+,proton,pi+,Upsilon
      // gen->add_particles("e+",5); // mu-,e-,anti_proton,pi-
      if (readhepmc || do_embedding) {
	gen->set_reuse_existing_vertex(true);
	gen->set_existing_vertex_offset_vector(0.0,0.0,0.0);
      } else {
	gen->set_vertex_distribution_function(PHG4SimpleEventGenerator::Uniform,
					       PHG4SimpleEventGenerator::Uniform,
					       PHG4SimpleEventGenerator::Uniform);
	gen->set_vertex_distribution_mean(0.0,0.0,0.0);
	gen->set_vertex_distribution_width(0.0,0.0,5.0);
      }
      gen->set_vertex_size_function(PHG4SimpleEventGenerator::Uniform);
      gen->set_vertex_size_parameters(10.0,0.0);
      gen->set_eta_range(-0.1, 0.1);
      gen->set_phi_range(-1.0*TMath::Pi(), 1.0*TMath::Pi());
      gen->set_pt_range(24, 24);
      gen->Embed(1);
      gen->Verbosity(0);
      se->registerSubsystem(gen);
    }

  if (!readhits)
    {
      //---------------------
      // Detector description
      //---------------------

      G4Setup(absorberactive, magfield, TPythia6Decayer::kAll,
	      do_svtx, do_preshower, do_cemc, do_hcalin, do_magnet, do_hcalout, do_pipe, magfield_rescale);
    }

  //---------
  // BBC Reco
  //---------

  if (do_bbc)
    {
      gROOT->LoadMacro("G4_Bbc.C");
      BbcInit();
      Bbc_Reco();
    }
  //------------------
  // Detector Division
  //------------------

  if (do_svtx_cell) Svtx_Cells();

  if (do_cemc_cell) CEMC_Cells();

  if (do_hcalin_cell) HCALInner_Cells();

  if (do_hcalout_cell) HCALOuter_Cells();

  //-----------------------------
  // CEMC towering and clustering
  //-----------------------------

  if (do_cemc_twr) CEMC_Towers();
  if (do_cemc_cluster) CEMC_Clusters();

  //-----------------------------
  // HCAL towering and clustering
  //-----------------------------

  if (do_hcalin_twr) HCALInner_Towers();
  if (do_hcalin_cluster) HCALInner_Clusters();

  if (do_hcalout_twr) HCALOuter_Towers();
  if (do_hcalout_cluster) HCALOuter_Clusters();

  if (do_dst_compress) ShowerCompress();

  //--------------
  // SVTX tracking
  //--------------

  if (do_svtx_track) Svtx_Reco();

  //-----------------
  // Global Vertexing
  //-----------------

  if (do_global)
    {
      gROOT->LoadMacro("G4_Global.C");
      Global_Reco();
    }

  else if (do_global_fastsim)
    {
      gROOT->LoadMacro("G4_Global.C");
      Global_FastSim();
    }

  //---------
  // Jet reco
  //---------

  if (do_jet_reco)
    {
      gROOT->LoadMacro("G4_Jets.C");
      Jet_Reco();
    }
  //----------------------
  // Simulation evaluation
  //----------------------

  if (do_svtx_eval) Svtx_Eval("g4svtx_eval.root");

  if (do_cemc_eval) CEMC_Eval("g4cemc_eval.root");

  if (do_hcalin_eval) HCALInner_Eval("g4hcalin_eval.root");

  if (do_hcalout_eval) HCALOuter_Eval("g4hcalout_eval.root");

  if (do_jet_eval) Jet_Eval("g4jet_eval.root");



  //-------------- 
  // IO management
  //--------------

  if (readhits)
    {
      // Hits file
      Fun4AllInputManager *hitsin = new Fun4AllDstInputManager("DSTin");
      hitsin->fileopen(inputFile);
      se->registerInputManager(hitsin);
    }
  if (do_embedding)
    {
      if (embed_input_file == NULL)
        {
          cout << "Missing embed_input_file! Exit";
          exit(3);
        }

      Fun4AllDstInputManager *in1 = new Fun4AllNoSyncDstInputManager("DSTinEmbed");
      //      in1->AddFile(embed_input_file); // if one use a single input file
      in1->AddListFile(embed_input_file); // RecommendedL: if one use a text list of many input files
      se->registerInputManager(in1);
    }
  if (readhepmc)
    {
      Fun4AllInputManager *in = new Fun4AllHepMCInputManager( "DSTIN");
      se->registerInputManager( in );
      se->fileopen( in->Name().c_str(), inputFile );
    }
  else
    {
      // for single particle generators we just need something which drives
      // the event loop, the Dummy Input Mgr does just that
      Fun4AllInputManager *in = new Fun4AllDummyInputManager( "JADE");
      se->registerInputManager( in );
    }

  //temp lines for QA modules
    {

      gSystem->Load("libqa_modules");

        if (do_jet_reco)
          {
            QAG4SimulationJet * calo_jet7 = new QAG4SimulationJet(
                "AntiKt_Truth_r07",QAG4SimulationJet:: kProcessTruthSpectrum);
            se->registerSubsystem(calo_jet7);

            QAG4SimulationJet * calo_jet7 = new QAG4SimulationJet(
                "AntiKt_Truth_r04", QAG4SimulationJet::kProcessTruthSpectrum);
            se->registerSubsystem(calo_jet7);

            QAG4SimulationJet * calo_jet7 = new QAG4SimulationJet(
                "AntiKt_Truth_r02",QAG4SimulationJet:: kProcessTruthSpectrum);
            se->registerSubsystem(calo_jet7);
          }
      }

    // HF jet trigger moudle
      assert (gSystem->Load("libHFJetTruthGeneration") == 0);
      {
        if (do_jet_reco)
          {
            HFJetTruthTrigger * jt = new HFJetTruthTrigger(
                "HFJetTruthTrigger.root",5 , "AntiKt_Truth_r07");
//            jt->Verbosity(HFJetTruthTrigger::VERBOSITY_MORE);
            se->registerSubsystem(jt);

            HFJetTruthTrigger * jt = new HFJetTruthTrigger(
                "HFJetTruthTrigger.root",5 , "AntiKt_Truth_r04");
//            jt->Verbosity(HFJetTruthTrigger::VERBOSITY_MORE);
            se->registerSubsystem(jt);

            HFJetTruthTrigger * jt = new HFJetTruthTrigger(
                "HFJetTruthTrigger.root",5 , "AntiKt_Truth_r02");
//            jt->Verbosity(HFJetTruthTrigger::VERBOSITY_MORE);
            se->registerSubsystem(jt);
          }
      }

  // HF jet analysis moudle
    if (gSystem->Load("libslt") == 0)
    {


      if (do_jet_reco)
        {
          SoftLeptonTaggingTruth * slt = new SoftLeptonTaggingTruth(
              "AntiKt_Truth_r07");
          se->registerSubsystem(slt);

          SoftLeptonTaggingTruth * slt = new SoftLeptonTaggingTruth(
              "AntiKt_Truth_r04");
//          slt->Verbosity(1);
          se->registerSubsystem(slt);

          SoftLeptonTaggingTruth * slt = new SoftLeptonTaggingTruth(
              "AntiKt_Truth_r02");
          se->registerSubsystem(slt);
        }
    }


  if (do_DSTReader)
    {
      //Convert DST to human command readable TTree for quick poke around the outputs
      gROOT->LoadMacro("G4_DSTReader.C");

      G4DSTreader( outputFile, //
          /*int*/ absorberactive ,
          /*bool*/ do_svtx ,
          /*bool*/ do_preshower ,
          /*bool*/ do_cemc ,
          /*bool*/ do_hcalin ,
          /*bool*/ do_magnet ,
          /*bool*/ do_hcalout ,
          /*bool*/ do_cemc_twr ,
          /*bool*/ do_hcalin_twr ,
          /*bool*/ do_magnet  ,
          /*bool*/ do_hcalout_twr
          );
    }


   Fun4AllDstOutputManager *out = new Fun4AllDstOutputManager("DSTOUT", outputFile);
   if (do_dst_compress) DstCompress(out);
   se->registerOutputManager(out);

  //-----------------
  // Event processing
  //-----------------
  if (nEvents < 0)
    {
      return;
    }
  // if we run the particle generator and use 0 it'll run forever
  if (nEvents == 0 && !readhits && !readhepmc)
    {
      cout << "using 0 for number of events is a bad idea when using particle generators" << endl;
      cout << "it will run forever, so I just return without running anything" << endl;
      return;
    }

  se->run(nEvents);

  {

    gSystem->Load("libqa_modules");
    QAHistManagerDef::saveQARootFile(string(outputFile) + "_qa.root");

      if (gSystem->Load("libslt") == 0)
        {
          SoftLeptonTaggingTruth::getHistoManager()->dumpHistos(
              string(outputFile) + "_slt.root");
        }
  }

  //-----
  // Exit
  //-----
  gSystem->Exec("ps -o sid,ppid,pid,user,comm,vsize,rssize,time");
  se->End();
  std::cout << "All done" << std::endl;
  delete se;
  gSystem->Exit(0);
}
int Fun4All_EICAnalysis_DIS(
			    const int nEvents = 100000,
			    const char * inputFile = "../data/phpythia6_e10p250_dis_100k_hepmc.root",
			    const char * outputFile = "eicana_pythia6_e10p250_dis_100k.root"
			    )
{

  bool readdst = true;
  bool readhepmc = false;

  //---------------
  // Load libraries
  //---------------

  gSystem->Load("libfun4all.so");
  gSystem->Load("libphhepmc.so");
  gSystem->Load("libeicana.so");

  //---------------
  // Fun4All server
  //---------------

  Fun4AllServer *se = Fun4AllServer::instance();
  se->Verbosity(0);
  // just if we set some flags somewhere in this macro
  recoConsts *rc = recoConsts::instance();

  //  rc->set_FloatFlag("WorldSizex",1000);
  //  rc->set_FloatFlag("WorldSizey",1000);
  //  rc->set_FloatFlag("WorldSizez",1000);
  //  rc->set_CharFlag("WorldShape","G4Tubs");


  //--------------
  // Analysis modules
  //--------------

  //  DISKinematics *disana = new DISKinematics("testdis.root");
  //  se->registerSubsystem( disana );

  DISKinematics *mcana = new DISKinematics(outputFile);
  se->registerSubsystem( mcana );

  //--------------
  // IO management
  //--------------

  /* Read DST Files */
  if ( readdst )
    {
      Fun4AllInputManager *hitsin = new Fun4AllDstInputManager("DSTin");
      hitsin->fileopen(inputFile);
      se->registerInputManager(hitsin);
    }
  /* Read HepMC ASCII files */
  else if ( readhepmc )
    {
      Fun4AllInputManager *in = new Fun4AllHepMCInputManager( "DSTIN");
      se->registerInputManager( in );
      se->fileopen( in->Name().c_str(), inputFile );
    }


  //-----------------
  // Event processing
  //-----------------
  if (nEvents < 0)
    {
      return;
    }
  // if we run the particle generator and use 0 it'll run forever
  if (nEvents == 0 && !readhits && !readhepmc)
    {
      cout << "using 0 for number of events is a bad idea when using particle generators" << endl;
      cout << "it will run forever, so I just return without running anything" << endl;
      return;
    }

  se->run(nEvents);

  //-----
  // Exit
  //-----

  se->End();
  std::cout << "All done" << std::endl;
  delete se;
  gSystem->Exit(0);
}
int Fun4All_G4_sPHENIX_AnaGenFit(
  const int nEvents = 10000,
  const char * inputFile = "/gpfs02/phenix/prod/sPHENIX/preCDR/pro.1-beta.5/single_particle/spacal1d/fieldmap/G4Hits_sPHENIX_e-_eta0_16GeV.root",
  const char * outputFile = "AnaSvtxTracksForGenFit.root"
)
{
  //===============
  // Input options
  //===============

  // Either:
  // read previously generated g4-hits files, in this case it opens a DST and skips
  // the simulations step completely. The G4Setup macro is only loaded to get information
  // about the number of layers used for the cell reco code
  const bool readhits = false;
  // Or:
  // read files in HepMC format (typically output from event generators like hijing or pythia)
  const bool readhepmc = false; // read HepMC files
  // Or:
  // Use particle generator
  const bool runpythia8 = false;
  const bool runpythia6 = false;

  //======================
  // What to run
  //======================

  bool do_bbc = true;

  bool do_pipe = true;

  bool do_svtx = true;
  bool do_svtx_cell = true;
  bool do_svtx_track = true;
  bool do_svtx_eval = true;

  bool do_preshower = false;

  bool do_cemc = false;
  bool do_cemc_cell = false;
  bool do_cemc_twr = false;
  bool do_cemc_cluster = false;
  bool do_cemc_eval = false;

  bool do_hcalin = false;
  bool do_hcalin_cell = false;
  bool do_hcalin_twr = false;
  bool do_hcalin_cluster = false;
  bool do_hcalin_eval = false;

  bool do_magnet = false;

  bool do_hcalout = false;
  bool do_hcalout_cell = false;
  bool do_hcalout_twr = false;
  bool do_hcalout_cluster = false;
  bool do_hcalout_eval = false;

  bool do_global = false;
  bool do_global_fastsim = false;

  bool do_jet_reco = false;
  bool do_jet_eval = false;

  bool do_dst_compress = false;

  //Option to convert DST to human command readable TTree for quick poke around the outputs
  bool do_DSTReader = false;
  //---------------
  // Load libraries
  //---------------

  gSystem->Load("libfun4all.so");
  gSystem->Load("libg4detectors.so");
  gSystem->Load("libphhepmc.so");
  gSystem->Load("libg4testbench.so");
  gSystem->Load("libg4hough.so");
  gSystem->Load("libcemc.so");
  gSystem->Load("libg4eval.so");
  gSystem->Load("libAnaSvtxTracksForGenFit.so");

  // establish the geometry and reconstruction setup
  gROOT->LoadMacro("G4Setup_sPHENIX.C");
  G4Init(do_svtx, do_preshower, do_cemc, do_hcalin, do_magnet, do_hcalout, do_pipe);

  int absorberactive = 1; // set to 1 to make all absorbers active volumes
  //  const string magfield = "1.5"; // if like float -> solenoidal field in T, if string use as fieldmap name (including path)
  const string magfield = "/phenix/upgrades/decadal/fieldmaps/sPHENIX.2d.root"; // if like float -> solenoidal field in T, if string use as fieldmap name (including path)
  const float magfield_rescale = 1.4 / 1.5; // scale the map to a 1.4 T field

  //---------------
  // Fun4All server
  //---------------

  Fun4AllServer *se = Fun4AllServer::instance();
  se->Verbosity(0);
  // just if we set some flags somewhere in this macro
  recoConsts *rc = recoConsts::instance();
  // By default every random number generator uses
  // PHRandomSeed() which reads /dev/urandom to get its seed
  // if the RANDOMSEED flag is set its value is taken as seed
  // You ca neither set this to a random value using PHRandomSeed()
  // which will make all seeds identical (not sure what the point of
  // this would be:
  //  rc->set_IntFlag("RANDOMSEED",PHRandomSeed());
  // or set it to a fixed value so you can debug your code
  // rc->set_IntFlag("RANDOMSEED", 12345);

  //-----------------
  // Event generation
  //-----------------

  if (readhits)
  {
    // Get the hits from a file
    // The input manager is declared later
  }
  else if (readhepmc)
  {
    // this module is needed to read the HepMC records into our G4 sims
    // but only if you read HepMC input files
    HepMCNodeReader *hr = new HepMCNodeReader();
    se->registerSubsystem(hr);
  }
  else if (runpythia8)
  {
    gSystem->Load("libPHPythia8.so");

    PHPythia8* pythia8 = new PHPythia8();
    // see coresoftware/generators/PHPythia8 for example config
    pythia8->set_config_file("phpythia8.cfg");
    se->registerSubsystem(pythia8);

    HepMCNodeReader *hr = new HepMCNodeReader();
    se->registerSubsystem(hr);
  }
  else if (runpythia6)
  {
    gSystem->Load("libPHPythia6.so");

    PHPythia6 *pythia6 = new PHPythia6();
    pythia6->set_config_file("phpythia6.cfg");
    se->registerSubsystem(pythia6);

    HepMCNodeReader *hr = new HepMCNodeReader();
    se->registerSubsystem(hr);
  }
  else
  {
    // toss low multiplicity dummy events
    PHG4SimpleEventGenerator *gen = new PHG4SimpleEventGenerator();
    gen->add_particles("mu+", 1); // mu+,e+,proton,pi+,Upsilon
    // gen->add_particles("e+",5); // mu-,e-,anti_proton,pi-
    if (readhepmc) {
      gen->set_reuse_existing_vertex(true);
      gen->set_existing_vertex_offset_vector(0.0, 0.0, 0.0);
    } else {
      gen->set_vertex_distribution_function(PHG4SimpleEventGenerator::Uniform,
                                            PHG4SimpleEventGenerator::Uniform,
                                            PHG4SimpleEventGenerator::Uniform);
      gen->set_vertex_distribution_mean(0.0, 0.0, 0.0);
      gen->set_vertex_distribution_width(0.0, 0.0, 5.0);
    }
    gen->set_vertex_size_function(PHG4SimpleEventGenerator::Uniform);
    gen->set_vertex_size_parameters(0.0, 0.0);
    gen->set_eta_range(-0.5, 0.5);
    gen->set_phi_range(-1.0 * TMath::Pi(), 1.0 * TMath::Pi());
    gen->set_pt_range(0.1, 10.0);
    gen->Embed(1);
    gen->Verbosity(0);
    se->registerSubsystem(gen);
  }

  if (!readhits)
  {
    //---------------------
    // Detector description
    //---------------------

    G4Setup(absorberactive, magfield, TPythia6Decayer::kAll,
            do_svtx, do_preshower, do_cemc, do_hcalin, do_magnet, do_hcalout, do_pipe, magfield_rescale);
  }

  //---------
  // BBC Reco
  //---------

  if (do_bbc)
  {
    gROOT->LoadMacro("G4_Bbc.C");
    BbcInit();
    Bbc_Reco();
  }
  //------------------
  // Detector Division
  //------------------

  if (do_svtx_cell) Svtx_Cells();

  if (do_cemc_cell) CEMC_Cells();

  if (do_hcalin_cell) HCALInner_Cells();

  if (do_hcalout_cell) HCALOuter_Cells();

  //-----------------------------
  // CEMC towering and clustering
  //-----------------------------

  if (do_cemc_twr) CEMC_Towers();
  if (do_cemc_cluster) CEMC_Clusters();

  //-----------------------------
  // HCAL towering and clustering
  //-----------------------------

  if (do_hcalin_twr) HCALInner_Towers();
  if (do_hcalin_cluster) HCALInner_Clusters();

  if (do_hcalout_twr) HCALOuter_Towers();
  if (do_hcalout_cluster) HCALOuter_Clusters();

  if (do_dst_compress) ShowerCompress();

  //--------------
  // SVTX tracking
  //--------------

  if (do_svtx_track) Svtx_Reco();

  //-----------------
  // Global Vertexing
  //-----------------

  if (do_global)
  {
    gROOT->LoadMacro("G4_Global.C");
    Global_Reco();
  }

  else if (do_global_fastsim)
  {
    gROOT->LoadMacro("G4_Global.C");
    Global_FastSim();
  }

  //---------
  // Jet reco
  //---------

  if (do_jet_reco)
  {
    gROOT->LoadMacro("G4_Jets.C");
    Jet_Reco();
  }
  //----------------------
  // Simulation evaluation
  //----------------------

  if (do_svtx_eval) Svtx_Eval("g4svtx_eval.root");

  if (do_cemc_eval) CEMC_Eval("g4cemc_eval.root");

  if (do_hcalin_eval) HCALInner_Eval("g4hcalin_eval.root");

  if (do_hcalout_eval) HCALOuter_Eval("g4hcalout_eval.root");

  if (do_jet_eval) Jet_Eval("g4jet_eval.root");

  //--------------
  // IO management
  //--------------

  if (readhits)
  {
    // Hits file
    Fun4AllInputManager *hitsin = new Fun4AllDstInputManager("DSTin");
    hitsin->fileopen(inputFile);
    se->registerInputManager(hitsin);
  }
  if (readhepmc)
  {
    Fun4AllInputManager *in = new Fun4AllHepMCInputManager( "DSTIN");
    se->registerInputManager( in );
    se->fileopen( in->Name().c_str(), inputFile );
  }
  else
  {
    // for single particle generators we just need something which drives
    // the event loop, the Dummy Input Mgr does just that
    Fun4AllInputManager *in = new Fun4AllDummyInputManager( "JADE");
    se->registerInputManager( in );
  }

  if (do_DSTReader)
  {
    //Convert DST to human command readable TTree for quick poke around the outputs
    gROOT->LoadMacro("G4_DSTReader.C");

    G4DSTreader( outputFile, //
                 /*int*/ absorberactive ,
                 /*bool*/ do_svtx ,
                 /*bool*/ do_preshower ,
                 /*bool*/ do_cemc ,
                 /*bool*/ do_hcalin ,
                 /*bool*/ do_magnet ,
                 /*bool*/ do_hcalout ,
                 /*bool*/ do_cemc_twr ,
                 /*bool*/ do_hcalin_twr ,
                 /*bool*/ do_magnet  ,
                 /*bool*/ do_hcalout_twr
               );
  }

  // Fun4AllDstOutputManager *out = new Fun4AllDstOutputManager("DSTOUT", outputFile);
  // if (do_dst_compress) DstCompress(out);
  // se->registerOutputManager(out);

  //-----------------
  // Analysis Module
  //-----------------

  AnaSvtxTracksForGenFit *ana = new AnaSvtxTracksForGenFit();
  ana->set_filename( outputFile );
  se->registerSubsystem( ana );

  //-----------------
  // Event processing
  //-----------------
  if (nEvents < 0)
  {
    return;
  }
  // if we run the particle generator and use 0 it'll run forever
  if (nEvents == 0 && !readhits && !readhepmc)
  {
    cout << "using 0 for number of events is a bad idea when using particle generators" << endl;
    cout << "it will run forever, so I just return without running anything" << endl;
    return;
  }

  se->run(nEvents);

  //-----
  // Exit
  //-----

  se->End();
  std::cout << "All done" << std::endl;
  delete se;
  gSystem->Exit(0);
}
int Fun4All_G4_sPHENIX(
		       int nEvents = 100,
		       const char * inputFile = "/phenix/sim02/phnxreco/sPHENIX/hijing_sims/output/G4sPHENIX-4fm-050-0199.root",
		       const char * outputFile = "G4sPHENIXCells.root"
		       )
{
  //===============
  // Input options
  //===============

  // Either:
  // read previously generated g4-hits files, in this case it opens a DST and skips
  // the simulations step completely. The G4Setup macro is only loaded to get information
  // about the number of layers used for the cell reco code
  const bool readhits = false;
  // Or:
  // read files in HepMC format (typically output from event generators like hijing or pythia)
  const bool readhepmc = false; // read HepMC files
  // Or:
  // Use particle generator

  //======================
  // What to run
  //======================

  bool do_svtx = true;
  bool do_svtx_cell = true;
  bool do_svtx_track = true;
  bool do_svtx_eval = true;

  bool do_preshower = false;
  
  bool do_cemc = true;
  bool do_cemc_cell = true;
  bool do_cemc_twr = true;
  bool do_cemc_cluster = true;
  bool do_cemc_eval = true;

  bool do_hcalin = true;
  bool do_hcalin_cell = true;
  bool do_hcalin_twr = true;
  bool do_hcalin_cluster = true;
  bool do_hcalin_eval = true;

  bool do_magnet = true;
  
  bool do_hcalout = true;
  bool do_hcalout_cell = true;
  bool do_hcalout_twr = true;
  bool do_hcalout_cluster = true;
  bool do_hcalout_eval = true;

  //Option to convert DST to human command readable TTree for quick poke around the outputs
  bool do_DSTReader = false;
  //---------------
  // Load libraries
  //---------------

  gSystem->Load("libfun4all.so");
  gSystem->Load("libg4detectors.so");
  gSystem->Load("libphhepmc.so");
  gSystem->Load("libg4testbench.so");
  gSystem->Load("libg4hough.so");
  gSystem->Load("libcemc.so");
  gSystem->Load("libg4eval.so");

  // establish the geometry and reconstruction setup
  gROOT->LoadMacro("G4Setup_sPHENIX.C");
  G4Init(do_svtx,do_preshower,do_cemc,do_hcalin,do_magnet,do_hcalout);
  
  int absorberactive = 1; // set to 1 to make all absorbers active volumes
  //  const string magfield = "1.5"; // if like float -> solenoidal field in T, if string use as fieldmap name (including path)
  const string magfield = "/phenix/upgrades/decadal/fieldmaps/bPHENIX.dp.root"; // if like float -> solenoidal field in T, if string use as fieldmap name (including path)

  //---------------
  // Fun4All server
  //---------------

  Fun4AllServer *se = Fun4AllServer::instance();
  se->Verbosity(0);

  // unique seed
  int uniqueseed = TRandom3(0).GetSeed();
  recoConsts *rc = recoConsts::instance();
  rc->set_IntFlag("RANDOMSEED", uniqueseed);

  //-----------------
  // Event generation
  //-----------------

  if (readhits)
    {
      // Get the hits from a file
      // The input manager is declared later
    }
  else if (readhepmc)
    {
      // this module is needed to read the HepMC records into our G4 sims
      // but only if you read HepMC input files
      HepMCNodeReader *hr = new HepMCNodeReader();
      se->registerSubsystem(hr);
    }
  else
    {
      // toss low multiplicity dummy events
      PHG4SimpleEventGenerator *gen = new PHG4SimpleEventGenerator();
      gen->add_particles("e-",5); // mu+,e+,proton,pi+,Upsilon
      gen->add_particles("e+",5); // mu-,e-,anti_proton,pi-
      if (readhepmc) {
	gen->set_reuse_existing_vertex(true);
	gen->set_existing_vertex_offset_vector(0.0,0.0,0.0);
      } else {
	gen->set_vertex_distribution_function(PHG4SimpleEventGenerator::Uniform,
					       PHG4SimpleEventGenerator::Uniform,
					       PHG4SimpleEventGenerator::Uniform);
	gen->set_vertex_distribution_mean(0.0,0.0,0.0);
	gen->set_vertex_distribution_width(0.0,0.0,5.0);
      }
      gen->set_vertex_size_function(PHG4SimpleEventGenerator::Uniform);
      gen->set_vertex_size_parameters(0.0,0.0);
      gen->set_eta_range(-0.5, 0.5);
      gen->set_phi_range(-1.0*TMath::Pi(), 1.0*TMath::Pi());
      gen->set_pt_range(0.1, 10.0);
      gen->set_embedflag(1);
      gen->set_seed(uniqueseed);
      gen->set_verbosity(0);
      se->registerSubsystem(gen);
    }

  if (!readhits)
    {
      //---------------------
      // Detector description
      //---------------------

      G4Setup(absorberactive, magfield, TPythia6Decayer::kAll,
	      do_svtx, do_preshower, do_cemc, do_hcalin, do_magnet, do_hcalout);
    }

  //------------------
  // Detector Division
  //------------------

  if (do_svtx_cell) Svtx_Cells();

  if (do_cemc_cell) CEMC_Cells();

  if (do_hcalin_cell) HCALInner_Cells();

  if (do_hcalout_cell) HCALOuter_Cells();

  //-----------------------------
  // CEMC towering and clustering
  //-----------------------------

  if (do_cemc_twr) CEMC_Towers();
  if (do_cemc_cluster) CEMC_Clusters();

  //-----------------------------
  // HCAL towering and clustering
  //-----------------------------
  
  if (do_hcalin_cell) HCALInner_Towers();
  if (do_hcalin_cell) HCALInner_Clusters();

  if (do_hcalout_cell) HCALOuter_Towers();
  if (do_hcalout_cell) HCALOuter_Clusters();

  //--------------
  // SVTX tracking
  //--------------

  if (do_svtx_track) Svtx_Reco();

  //----------------------
  // Simulation evaluation
  //----------------------

  if (do_svtx_eval) Svtx_Eval("g4svtx_eval.root");

  if (do_cemc_eval) CEMC_Eval("g4cemc_eval.root");

  if (do_hcalin_cell) HCALInner_Eval("g4hcalin_eval.root");

  if (do_hcalout_cell) HCALOuter_Eval("g4hcalout_eval.root");

  //-------------- 
  // IO management
  //--------------

  if (readhits)
    {
      // Hits file
      Fun4AllInputManager *hitsin = new Fun4AllDstInputManager("DSTin");
      hitsin->fileopen(inputFile);
      se->registerInputManager(hitsin);
    }
  if (readhepmc)
    {
      Fun4AllInputManager *in = new Fun4AllHepMCInputManager( "DSTIN");
      se->registerInputManager( in );
      se->fileopen( in->Name(), inputFile );
    }
  else
    {
      // for single particle generators we just need something which drives
      // the event loop, the Dummy Input Mgr does just that
      Fun4AllInputManager *in = new Fun4AllDummyInputManager( "JADE");
      se->registerInputManager( in );
    }

  if (do_DSTReader)
    {
      //Convert DST to human command readable TTree for quick poke around the outputs
      gROOT->LoadMacro("G4DSTreader.C");

      G4DSTreader( outputFile, //
          /*int*/ absorberactive ,
          /*bool*/ do_svtx ,
          /*bool*/ do_preshower ,
          /*bool*/ do_cemc ,
          /*bool*/ do_hcalin ,
          /*bool*/ do_magnet ,
          /*bool*/ do_hcalout ,
          /*bool*/ do_cemc_twr ,
          /*bool*/ do_hcalin_twr ,
          /*bool*/ do_magnet  ,
          /*bool*/ do_hcalout_twr
          );
    }

  // Fun4AllDstOutputManager *out = new Fun4AllDstOutputManager("DSTOUT", outputFile);
  // se->registerOutputManager(out);

  //-----------------
  // Event processing
  //-----------------
  se->run(nEvents);

  //-----
  // Exit
  //-----

  se->End();
  std::cout << "All done" << std::endl;
  delete se;
  gSystem->Exit(0);
}
//! ePHENIX simulation loading script
//! \param[in] nEvents Number of events to run. If nEvents=1, then a event display will be shown
//! \param[in] outputFile output for G4DSTReader
//! \param[in] inputFile HepMC input files, not activated by default
int
Fun4All_G4_ePHENIX( //
//        int nEvents = 0, //
    //    int nEvents = 1, //
    int nEvents = 2, //
//    int nEvents = 100000, //
    const char * outputFile = "G4ePHENIX.root", //
    const char * inputFile = "MyPythia.dat" //
    )
{
  //---------------
  // Load libraries
  //---------------

  const bool readhepmc = false; // read HepMC files
  const int absorberactive = 1; // set to 1 to make all absorbers active volumes
  const bool verbosity = false; // very slow but very detailed logs
//  const bool verbosity = true; // very slow but very detailed logs

  gSystem->Load("libg4testbench.so");
  gSystem->Load("libfun4all.so");
  gSystem->Load("libcemc.so");
  gSystem->Load("libg4eval.so");

  gROOT->LoadMacro("G4Setup_ePHENIX.C");

  G4Init(); // initialize layer numbers for barrel

  //---------------
  // Fun4All server
  //---------------

  Fun4AllServer *se = Fun4AllServer::instance();
  se->Verbosity(0);

  //-----------------
  // Event generation
  //-----------------
  if (readhepmc)
    {
      // this module is needed to read the HepMC records into our G4 sims
      // but only if you read HepMC input files
      HepMCNodeReader *hr = new HepMCNodeReader();
      se->registerSubsystem(hr);
    }
  else
    {
      // The PHG4ParticleGun runs the same particle(s) in
      // every event

      PHG4ParticleGun *gun = new PHG4ParticleGun();
//          gun->set_name("geantino+");
//      gun->set_name("chargedgeantino");
      gun->set_name("mu-");
//      gun->set_name("pi-"); // e,pi,mu,p,gamma
      //    gun->set_vtx(0,12.09,200);
      gun->set_vtx(0, 0, 0);
//        gun->set_mom(0, 0, 10);
      gun->set_mom(1.12641e-16, 1.83962, 13.6021);
//      se->registerSubsystem(gun);

      PHG4ParticleGenerator *gen = new PHG4ParticleGenerator();

      //      gen->set_seed(TRandom3(0).GetSeed());
      gen->set_seed(1234);
//      gen->set_name("geantino");
      gen->set_name("mu-");
//      gun->set_name("pi-"); // e,pi,mu,p,gamma
      gen->set_vtx(0, 0, 0);
      gen->set_z_range(0, 0);
//      gen->set_eta_range(3.5, 3.5);
      gen->set_eta_range(-4, 4);
      gen->set_phi_range(TMath::Pi() / 2, TMath::Pi() / 2);
      gen->set_mom_range(1.0, 50.0);
      gen->Verbosity(1);
//      se->registerSubsystem(gen);
//
      //! high Q2 250x10 GeV pythia file from Kieran
      ReadEICFiles *eic = new ReadEICFiles();
      const char *infile =
          "/direct/phenix+sim02/phnxreco/ePHENIX/jinhuang/display/pythia.ep.250x010.10000000events.seed679586890.root";
      eic->OpenInputFile(infile);
      eic->SetFirstEntry(565);
      se->registerSubsystem(eic);

    }
  //---------------------
  // Detector description from loaded macro
  //---------------------

  G4Setup(absorberactive, -1);
//  G4Setup_Sandbox(absorberactive, -1);

//  MaterialScan();
  //----------------------
  // Simulation evaluation
  //----------------------

//  SubsysReco* eval = new PHG4Evaluator("PHG4EVALUATOR","g4eval.root");
  //eval->Verbosity(0);
  //se->registerSubsystem( eval );

  //SubsysReco* eval = new PHG4CEMCEvaluator("PHG4CEMCEVALUATOR","out/g4eval.root");
  //eval->Verbosity(1);
  //se->registerSubsystem( eval );

  //     HitNtuples *hits = new HitNtuples();
  //        hits->AddNode("FEMCABS",0);
  //        hits->AddNode("FEMC",3);
  //        hits->AddNode("FPRESHOWER",1);
  //        hits->AddNode("GEM",2);
  //        hits->AddNode("GEMLIDFRONT",4);
  //        hits->AddNode("GEMLIDBACK",5);
  //    se->registerSubsystem(hits);

  //----------------------
  // Save selected nodes to root file
  //----------------------
    {
      // require offline/analysis/g4analysis_fsphenix

    PHG4DSTReader* ana = new PHG4DSTReader(outputFile);
      if (nEvents > 0 && nEvents < 3)
        ana->Verbosity(2);
      ana->AddNode("GEMSTATION0");
      ana->AddNode("GEMSTATION1");
      ana->AddNode("GEMSTATION2");
      ana->AddNode("GEMSTATION3");
      ana->AddNode("GEMSTATION4");
//      ana->AddNode("TestDetector_0");
      se->registerSubsystem(ana);

    }

  //--------------
  // IO management
  //--------------

  if (readhepmc)
    {
      Fun4AllInputManager *in = new Fun4AllHepMCInputManager("DSTIN");
      se->registerInputManager(in);
      se->fileopen(in->Name(), inputFile);
    }
  else
    {
      // for single particle generators we just need something which drives
      // the event loop, the Dummy Input Mgr does just that
      Fun4AllInputManager *in = new Fun4AllDummyInputManager("JADE");
      se->registerInputManager(in);
    }

  // File Managers
  bool save_dst = false;
  if (save_dst)
    {
      Fun4AllDstOutputManager *dstManager = new Fun4AllDstOutputManager(
          "DSTOUT", "DST.root");
      //FVTX nodes
      dstManager->AddNode("PHG4INEVENT");
      dstManager->AddNode("G4TruthInfo");

      se->registerOutputManager(dstManager);
    }

  //-----------------
  // Event processing
  //-----------------

  if (nEvents == 1)
    {
      PHG4Reco *g4 = (PHG4Reco *) se->getSubsysReco("PHG4RECO");
      g4->ApplyCommand("/control/execute eic.mac");
//      g4->StartGui();
      se->run(1);

      se->End();
      std::cout << "All done" << std::endl;
    }
  else
    {
      if (verbosity)
        {
          se->Verbosity(3);
          PHG4Reco *g4 = (PHG4Reco *) se->getSubsysReco("PHG4RECO");
          g4->Verbosity(3);
          g4->ApplyCommand("/control/verbose 5");
          g4->ApplyCommand("/run/verbose  5");
          g4->ApplyCommand("/tracking/verbose 5");
        }

      se->run(nEvents);

      se->End();
      std::cout << "All done" << std::endl;
      delete se;
      gSystem->Exit(0);
    }

  //   //-----
  //   // Exit
  //   //-----

  return 0;
}
int Fun4All_G4_EICDetector_LQ_reference(
			      string n="1093",
			      string ebeam="20",
			      string pbeam="250",
			      //string inputFile,
			      string inputFile="/direct/phenix+u/spjeffas/LQGENEP/TestOut.1093event.root",
			      string output="",
			      const char * outputFile = "G4EICDetector.root"
			   )
{
  // Set the number of TPC layer
  const int n_TPC_layers = 40;  // use 60 for backward compatibility only
  
  //Get parameter variables from parameter file
  
  int nEvents;
  stringstream geek(n);
  geek>>nEvents;



  string directory = "/direct/phenix+u/spjeffas/leptoquark/output/"+output+"/";


  //===============
  // Input options
  //===============
  // Either:
  // read previously generated g4-hits files, in this case it opens a DST and skips
  // the simulations step completely. The G4Setup macro is only loaded to get information
  // about the number of layers used for the cell reco code
  //
  // In case reading production output, please double check your G4Setup_sPHENIX.C and G4_*.C consistent with those in the production macro folder
  // E.g. /sphenix/sim//sim01/production/2016-07-21/single_particle/spacal2d/
  const bool readhits = false;
  // Or:
  // read files in HepMC format (typically output from event generators like hijing or pythia)
  const bool readhepmc = false; // read HepMC files
  // Or:
  // read files in EICTree format generated by eicsmear package
  const bool readeictree = true;
  // Or:
  // Use Pythia 8
  const bool runpythia8 = false;
  // Or:
  // Use Pythia 6
  const bool runpythia6 = false;
  // Or:
  // Use HEPGen
  const bool runhepgen = false;
  // Or:
  // Use Sartre
  const bool runsartre = false;



  // Besides the above flags. One can further choose to further put in following particles in Geant4 simulation
  // Use multi-particle generator (PHG4SimpleEventGenerator), see the code block below to choose particle species and kinematics
  const bool particles = false && !readhits;
  // or gun/ very simple single particle gun generator
  const bool usegun = false && !readhits;
  // Throw single Upsilons, may be embedded in Hijing by setting readhepmc flag also  (note, careful to set Z vertex equal to Hijing events)
  const bool upsilons = false && !readhits;

  //======================
  // What to run
  //======================

  // sPHENIX barrel
  bool do_bbc = true;

  bool do_pipe = true;

  bool do_svtx = true;
  bool do_svtx_cell = do_svtx && true;
  bool do_svtx_track = do_svtx_cell && true;
  bool do_svtx_eval = do_svtx_track && true;

  bool do_pstof = false;

  bool do_cemc = true;

  bool do_cemc_cell = true;
  bool do_cemc_twr = true;
  bool do_cemc_cluster = true;
  bool do_cemc_eval = true;

  bool do_hcalin = true;
  bool do_hcalin_cell = true;
  bool do_hcalin_twr = true;
  bool do_hcalin_cluster = true;
  bool do_hcalin_eval = true;

  bool do_cemc_cell = do_cemc && true;
  bool do_cemc_twr = do_cemc_cell && true;
  bool do_cemc_cluster = do_cemc_twr && true;
  bool do_cemc_eval = do_cemc_cluster && true;

  bool do_hcalin = true;
  bool do_hcalin_cell = do_hcalin && true;
  bool do_hcalin_twr = do_hcalin_cell && true;
  bool do_hcalin_cluster = do_hcalin_twr && true;
  bool do_hcalin_eval = do_hcalin_cluster && true;


  bool do_magnet = true;

  bool do_hcalout = true;

  bool do_hcalout_cell = true;
  bool do_hcalout_twr = true;
  bool do_hcalout_cluster = true;
  bool do_hcalout_eval = true;

  bool do_global = true;
  bool do_global_fastsim = false;

  bool do_jet_reco = true;
  bool do_jet_eval = true;

  bool do_fwd_jet_reco = true;
  bool do_fwd_jet_eval = false;

  bool do_hcalout_cell = do_hcalout && true;
  bool do_hcalout_twr = do_hcalout_cell && true;
  bool do_hcalout_cluster = do_hcalout_twr && true;
  bool do_hcalout_eval = do_hcalout_cluster && true;


  // EICDetector geometry - barrel
  bool do_DIRC = true;

  // EICDetector geometry - 'hadron' direction
  bool do_FGEM = true;
  bool do_FGEM_track = do_FGEM &&  false;

  bool do_RICH = true;
  bool do_Aerogel = true;

  bool do_FEMC = true;
  bool do_FEMC_cell = do_FEMC && true;
  bool do_FEMC_twr = do_FEMC_cell && true;
  bool do_FEMC_cluster = do_FEMC_twr && true;
  bool do_FEMC_eval = do_FEMC_cluster && true;

  bool do_FHCAL = true;
  bool do_FHCAL_cell = do_FHCAL && true;
  bool do_FHCAL_twr = do_FHCAL_cell && true;
  bool do_FHCAL_cluster = do_FHCAL_twr && true;
  bool do_FHCAL_eval = do_FHCAL_cluster && true;

  // EICDetector geometry - 'electron' direction
  bool do_EGEM = true;
  bool do_EGEM_track = do_EGEM &&  false;

  bool do_EEMC = true;
  bool do_EEMC_cell = do_EEMC && true;
  bool do_EEMC_twr = do_EEMC_cell && true;
  bool do_EEMC_cluster = do_EEMC_twr && true;
  bool do_EEMC_eval = do_EEMC_cluster && true;

  //do leptoquark analysis modules
  bool do_lepto_analysis = true;

  // Other options
  bool do_global = true;
  bool do_global_fastsim = false;

  bool do_calotrigger = false && do_cemc_twr && do_hcalin_twr && do_hcalout_twr;

  bool do_jet_reco = true;
  bool do_jet_eval = do_jet_reco && true;

  bool do_fwd_jet_reco = true;
  bool do_fwd_jet_eval = do_fwd_jet_reco && true;

  // HI Jet Reco for jet simulations in Au+Au (default is false for
  // single particle / p+p simulations, or for Au+Au simulations which
  // don't care about jets)
  bool do_HIjetreco = false && do_jet_reco && do_cemc_twr && do_hcalin_twr && do_hcalout_twr;

  // Compress DST files
  bool do_dst_compress = false;

  //Option to convert DST to human command readable TTree for quick poke around the outputs
  bool do_DSTReader = false;

  //---------------
  // Load libraries
  //---------------

  gSystem->Load("libfun4all.so");
  gSystem->Load("libg4detectors.so");
  gSystem->Load("libphhepmc.so");
  gSystem->Load("libg4testbench.so");
  gSystem->Load("libg4hough.so");
  gSystem->Load("libg4calo.so");
  gSystem->Load("libg4eval.so");
  gSystem->Load("libeicana.so");

  // establish the geometry and reconstruction setup
  gROOT->LoadMacro("G4Setup_EICDetector.C");
  G4Init(do_svtx,do_cemc,do_hcalin,do_magnet,do_hcalout,do_pipe,do_FGEM,do_EGEM,do_FEMC,do_FHCAL,do_EEMC,do_DIRC,do_RICH,do_Aerogel,n_TPC_layers);

  int absorberactive = 0; // set to 1 to make all absorbers active volumes
  //  const string magfield = "1.5"; // if like float -> solenoidal field in T, if string use as fieldmap name (including path)
  const string magfield = "/phenix/upgrades/decadal/fieldmaps/sPHENIX.2d.root"; // if like float -> solenoidal field in T, if string use as fieldmap name (including path)
  const float magfield_rescale = 1.4/1.5; // scale the map to a 1.4 T field

  //---------------
  // Fun4All server
  //---------------

  Fun4AllServer *se = Fun4AllServer::instance();
  se->Verbosity(0); // uncomment for batch production running with minimal output messages
  // se->Verbosity(Fun4AllServer::VERBOSITY_SOME); // uncomment for some info for interactive running

  // just if we set some flags somewhere in this macro
  recoConsts *rc = recoConsts::instance();
  // By default every random number generator uses
  // PHRandomSeed() which reads /dev/urandom to get its seed
  // if the RANDOMSEED flag is set its value is taken as seed
  // You can either set this to a random value using PHRandomSeed()
  // which will make all seeds identical (not sure what the point of
  // this would be:
  //  rc->set_IntFlag("RANDOMSEED",PHRandomSeed());
  // or set it to a fixed value so you can debug your code
  // rc->set_IntFlag("RANDOMSEED", 12345);

  //-----------------
  // Event generation
  //-----------------

  if (readhits)
    {
      // Get the hits from a file
      // The input manager is declared later
    }
  else if (readhepmc)
    {
      // this module is needed to read the HepMC records into our G4 sims
      // but only if you read HepMC input files
      HepMCNodeReader *hr = new HepMCNodeReader();
      se->registerSubsystem(hr);
    }
  else if (readeictree)
    {
      // this module is needed to read the EICTree style records into our G4 sims
      ReadEICFiles *eicr = new ReadEICFiles();
      eicr->OpenInputFile(inputFile);

      se->registerSubsystem(eicr);
    }
  else if (runpythia8)
    {
      gSystem->Load("libPHPythia8.so");

      PHPythia8* pythia8 = new PHPythia8();
      // see coresoftware/generators/PHPythia8 for example config
      pythia8->set_config_file("/direct/phenix+u/spjeffas/coresoftware/generators/PHPythia8/phpythia8.cfg");
      se->registerSubsystem(pythia8);

      HepMCNodeReader *hr = new HepMCNodeReader();
      se->registerSubsystem(hr);
    }
  else if (runpythia6)
    {
      gSystem->Load("libPHPythia6.so");

      PHPythia6 *pythia6 = new PHPythia6();
      // see coresoftware/generators/PHPythia6 for example config
      pythia6->set_config_file("/direct/phenix+u/spjeffas/coresoftware/generators/PHPythia6/phpythia6_ep.cfg");
      se->registerSubsystem(pythia6);

      HepMCNodeReader *hr = new HepMCNodeReader();
      se->registerSubsystem(hr);
    }
  else if (runhepgen)
    {
      gSystem->Load("libsHEPGen.so");

      sHEPGen *hepgen = new sHEPGen();
      // see HEPGen source directory/share/vggdata for required .dat files
      // see HEPGen source directory/share/datacards for required datacard files
      hepgen->set_datacard_file("hepgen_dvcs.data");
      hepgen->set_momentum_electron(-20);
      hepgen->set_momentum_hadron(250);
      se->registerSubsystem(hepgen);

      HepMCNodeReader *hr = new HepMCNodeReader();
      se->registerSubsystem(hr);
    }
  else if (runsartre)
    {
      // see coresoftware/generators/PHSartre/README for setup instructions
      // before running:
      // setenv SARTRE_DIR /opt/sphenix/core/sartre-1.20_root-5.34.36
      gSystem->Load("libPHSartre.so");

      PHSartre* mysartre = new PHSartre();
      // see coresoftware/generators/PHSartre for example config
      mysartre->set_config_file("sartre.cfg");

      // particle trigger to enhance forward J/Psi -> ee
      PHSartreParticleTrigger* pTrig = new PHSartreParticleTrigger("MySartreTrigger");
      pTrig->AddParticles(-11);
      //pTrig->SetEtaHighLow(4.0,1.4);
      pTrig->SetEtaHighLow(1.0,-1.1);  // central arm
      pTrig->PrintConfig();
      mysartre->register_trigger((PHSartreGenTrigger *)pTrig);
      se->registerSubsystem(mysartre);

      HepMCNodeReader *hr = new HepMCNodeReader();
      se->registerSubsystem(hr);
    }

  // If "readhepMC" is also set, the particles will be embedded in Hijing events
  if(particles)
    {
      // toss low multiplicity dummy events
      PHG4SimpleEventGenerator *gen = new PHG4SimpleEventGenerator();

      //gen->add_particles("e-",5); // mu+,e+,proton,pi+,Upsilon
      //gen->add_particles("e+",5); // mu-,e-,anti_proton,pi-
      gen->add_particles("tau-",1); // mu-,e-,anti_proton,pi-
      if (readhepmc) {
        gen->set_reuse_existing_vertex(true);
        gen->set_existing_vertex_offset_vector(0.0,0.0,0.0);
      } else {
        gen->set_vertex_distribution_function(PHG4SimpleEventGenerator::Uniform,
                                              PHG4SimpleEventGenerator::Uniform,
                                              PHG4SimpleEventGenerator::Uniform);
        gen->set_vertex_distribution_mean(0.0,0.0,0.0);
        gen->set_vertex_distribution_width(0.0,0.0,5.0);
      }
      gen->set_vertex_size_function(PHG4SimpleEventGenerator::Uniform);
      gen->set_vertex_size_parameters(0.0,0.0);
      gen->set_eta_range(0.1, 0.1);
      //gen->set_eta_range(3.0, 3.0); //EICDetector FWD
      gen->set_phi_range(TMath::Pi()/2-0.1, TMath::Pi()/2-0.1);
      //gen->set_phi_range(TMath::Pi()/2-0.1, TMath::Pi()/2-0.1);
      gen->set_p_range(30.0, 30.0);

      //gen->add_particles("pi-",1); // mu+,e+,proton,pi+,Upsilon
      //gen->add_particles("pi+",100); // 100 pion option
      if (readhepmc)
        {
          gen->set_reuse_existing_vertex(true);
          gen->set_existing_vertex_offset_vector(0.0, 0.0, 0.0);
        }
      else
        {
          gen->set_vertex_distribution_function(PHG4SimpleEventGenerator::Uniform,
                                                PHG4SimpleEventGenerator::Uniform,
                                                PHG4SimpleEventGenerator::Uniform);
          gen->set_vertex_distribution_mean(0.0, 0.0, 0.0);
          gen->set_vertex_distribution_width(0.0, 0.0, 0.0);
        }
      gen->set_vertex_size_function(PHG4SimpleEventGenerator::Uniform);
      gen->set_vertex_size_parameters(0.0, 0.0);
      gen->set_eta_range(-1.0, 1.0);
      gen->set_phi_range(-1.0 * TMath::Pi(), 1.0 * TMath::Pi());
      //gen->set_pt_range(0.1, 50.0);
      gen->set_pt_range(0.1, 20.0);

      gen->Embed(1);
      gen->Verbosity(0);

      se->registerSubsystem(gen);
    }
  if (usegun)
    {
      // PHG4ParticleGun *gun = new PHG4ParticleGun();
      // gun->set_name("anti_proton");
      // gun->set_name("geantino");
      // gun->set_vtx(0, 0, 0);
      // gun->set_mom(10, 0, 0.01);
      // gun->AddParticle("geantino",1.7776,-0.4335,0.);
      // gun->AddParticle("geantino",1.7709,-0.4598,0.);
      // gun->AddParticle("geantino",2.5621,0.60964,0.);
      // gun->AddParticle("geantino",1.8121,0.253,0.);
      // se->registerSubsystem(gun);
      PHG4ParticleGenerator *pgen = new PHG4ParticleGenerator();
      pgen->set_name("e-");
      pgen->set_z_range(0,0);
      pgen->set_eta_range(0.01,0.01);
      pgen->set_mom_range(10,10);
      pgen->set_phi_range(-1.0 * TMath::Pi(), 1.0 * TMath::Pi());
      se->registerSubsystem(pgen);
    }

  // If "readhepMC" is also set, the Upsilons will be embedded in Hijing events, if 'particles" is set, the Upsilons will be embedded in whatever particles are thrown
  if(upsilons)
    {
      // run upsilons for momentum, dca performance, alone or embedded in Hijing

      PHG4ParticleGeneratorVectorMeson *vgen = new PHG4ParticleGeneratorVectorMeson();
      vgen->add_decay_particles("e+","e-",0); // i = decay id
      // event vertex
      if (readhepmc || particles)
        {
          vgen->set_reuse_existing_vertex(true);
        }
      else
        {
          vgen->set_vtx_zrange(-10.0, +10.0);
        }

      // Note: this rapidity range completely fills the acceptance of eta = +/- 1 unit
      vgen->set_rapidity_range(-1.0, +1.0);
      vgen->set_pt_range(0.0, 10.0);

      int istate = 1;

      if(istate == 1)
        {
          // Upsilon(1S)
          vgen->set_mass(9.46);
          vgen->set_width(54.02e-6);
        }
      else if (istate == 2)
        {
          // Upsilon(2S)
          vgen->set_mass(10.0233);
          vgen->set_width(31.98e-6);
        }
      else
        {
          // Upsilon(3S)
          vgen->set_mass(10.3552);
          vgen->set_width(20.32e-6);
        }

      vgen->Verbosity(0);
      vgen->Embed(2);
      se->registerSubsystem(vgen);

      cout << "Upsilon generator for istate = " << istate << " created and registered "  << endl;
    }

  if (!readhits)
    {
      //---------------------
      // Detector description
      //---------------------

      G4Setup(absorberactive, magfield, TPythia6Decayer::kAll,
              do_svtx,do_cemc,do_hcalin,do_magnet,do_hcalout,do_pipe,
              do_FGEM,do_EGEM,do_FEMC,do_FHCAL,do_EEMC,do_DIRC,do_RICH,do_Aerogel,
              magfield_rescale);
   
    }

  //---------
  // BBC Reco
  //---------

  if (do_bbc)
    {
      gROOT->LoadMacro("G4_Bbc.C");
      BbcInit();
      Bbc_Reco();
    }

  //------------------
  // Detector Division
  //------------------

  if (do_svtx_cell) Svtx_Cells();

  if (do_cemc_cell) CEMC_Cells();

  if (do_hcalin_cell) HCALInner_Cells();

  if (do_hcalout_cell) HCALOuter_Cells();

  if (do_FEMC_cell) FEMC_Cells();

  if (do_FHCAL_cell) FHCAL_Cells();

  if (do_EEMC_cell) EEMC_Cells();

  //-----------------------------
  // CEMC towering and clustering
  //-----------------------------

  if (do_cemc_twr) CEMC_Towers();
  if (do_cemc_cluster) CEMC_Clusters();

  //-----------------------------
  // HCAL towering and clustering
  //-----------------------------

  if (do_hcalin_twr) HCALInner_Towers();
  if (do_hcalin_cluster) HCALInner_Clusters();

  if (do_hcalout_twr) HCALOuter_Towers();
  if (do_hcalout_cluster) HCALOuter_Clusters();

  //-----------------------------
  // e, h direction Calorimeter  towering and clustering
  //-----------------------------

  if (do_FEMC_twr) FEMC_Towers();
  if (do_FEMC_cluster) FEMC_Clusters();

  if (do_FHCAL_twr) FHCAL_Towers();
  if (do_FHCAL_cluster) FHCAL_Clusters();

  if (do_EEMC_twr) EEMC_Towers();
  if (do_EEMC_cluster) EEMC_Clusters();

  if (do_dst_compress) ShowerCompress();

  //--------------
  // SVTX tracking
  //--------------

  if (do_svtx_track) Svtx_Reco();

  //--------------
  // FGEM tracking
  //--------------

  if(do_FGEM_track) FGEM_FastSim_Reco();

  //--------------
  // EGEM tracking
  //--------------

  if(do_EGEM_track) EGEM_FastSim_Reco();

  //-----------------
  // Global Vertexing
  //-----------------

  if (do_global)
    {
      gROOT->LoadMacro("G4_Global.C");
      Global_Reco();
    }

  else if (do_global_fastsim)
    {
      gROOT->LoadMacro("G4_Global.C");
      Global_FastSim();
    }

  //-----------------
  // Calo Trigger Simulation
  //-----------------

  if (do_calotrigger)
    {
      gROOT->LoadMacro("G4_CaloTrigger.C");
      CaloTrigger_Sim();
    }

  //---------
  // Jet reco
  //---------

  if (do_jet_reco)
    {
      gROOT->LoadMacro("G4_Jets.C");
      Jet_Reco();
    }

  if (do_HIjetreco) {
    gROOT->LoadMacro("G4_HIJetReco.C");
    HIJetReco();
  }

  if (do_fwd_jet_reco)
    {
      gROOT->LoadMacro("G4_FwdJets.C");
      Jet_FwdReco();
    }

  //----------------------
  // Simulation evaluation
  //----------------------
  
  
  if (do_svtx_eval) Svtx_Eval(directory+"g4svtx_p"+pbeam+"_e"+ebeam+"_"+n+"events_eval.root");
  
  if (do_cemc_eval) CEMC_Eval(directory+"g4cemc_p"+pbeam+"_e"+ebeam+"_"+n+"events_eval.root");

  if (do_hcalin_eval) HCALInner_Eval(directory+"g4hcalin_p"+pbeam+"_e"+ebeam+"_"+n+"events_eval.root");

  if (do_hcalout_eval) HCALOuter_Eval(directory+"g4hcalout_p"+pbeam+"_e"+ebeam+"_"+n+"events_eval.root");

  if (do_jet_eval) Jet_Eval(directory+"g4jet_p"+pbeam+"_e"+ebeam+"_"+n+"events_eval.root");

  if (do_fwd_jet_eval) Jet_FwdEval(directory+"g4fwdjet_p"+pbeam+"_e"+ebeam+"_"+n+"events_eval.root");
  
  if(do_lepto_analysis){
    gROOT->LoadMacro("G4_Lepto.C");
    G4_Lepto(directory+"LeptoAna_p"+pbeam+"_e"+ebeam+"_"+n+"events");
  }
  

  
 
  
  //--------------
  // IO management
  //--------------

  if (readhits)
    {
      // Hits file
      Fun4AllInputManager *hitsin = new Fun4AllDstInputManager("DSTin");
      hitsin->fileopen(inputFile);
      se->registerInputManager(hitsin);
    }
  if (readhepmc)
    {
      Fun4AllInputManager *in = new Fun4AllHepMCInputManager( "DSTIN");
      se->registerInputManager( in );
      se->fileopen( in->Name().c_str(), inputFile );
    }
  else
    {
      // for single particle generators we just need something which drives
      // the event loop, the Dummy Input Mgr does just that
      Fun4AllInputManager *in = new Fun4AllDummyInputManager( "JADE");
      se->registerInputManager( in );
    }

  if (do_DSTReader)
    {
      //Convert DST to human command readable TTree for quick poke around the outputs
      gROOT->LoadMacro("G4_DSTReader_EICDetector.C");

      G4DSTreader_EICDetector( outputFile, //
                               /*int*/ absorberactive ,
                               /*bool*/ do_svtx ,
                               /*bool*/ do_cemc ,
                               /*bool*/ do_hcalin ,
                               /*bool*/ do_magnet ,
                               /*bool*/ do_hcalout ,
                               /*bool*/ do_cemc_twr ,
                               /*bool*/ do_hcalin_twr ,
                               /*bool*/ do_magnet  ,
                               /*bool*/ do_hcalout_twr,
                               /*bool*/ do_FGEM,
                               /*bool*/ do_EGEM,
                               /*bool*/ do_FHCAL,
                               /*bool*/ do_FHCAL_twr,
                               /*bool*/ do_FEMC,
                               /*bool*/ do_FEMC_twr,
                               /*bool*/ do_EEMC,
                               /*bool*/ do_EEMC_twr
                               );
    }

  Fun4AllDstOutputManager *out = new Fun4AllDstOutputManager("DSTOUT", outputFile);
  if (do_dst_compress) DstCompress(out);
  se->registerOutputManager(out);

  //-----------------
  // Event processing
  //-----------------
  if (nEvents < 0)
    {
      return;
    }
  // if we run the particle generator and use 0 it'll run forever
  if (nEvents == 0 && !readhits && !readhepmc)
    {
      cout << "using 0 for number of events is a bad idea when using particle generators" << endl;
      cout << "it will run forever, so I just return without running anything" << endl;
      return;
    }

  se->run(nEvents);

  //-----
  // Exit
  //-----

  se->End();
  std::cout << "All done" << std::endl;
  delete se;
  gSystem->Exit(0);
}