// Macro for running Panda simulation  with Geant3  or Geant4 (M. Al-Turany)
// This macro is supposed to run the full simulation of the panda detector
// with visualization points to display track in the eventdisplay
// to run the macro:
// root  sim_complete.C  or in root session root>.x  sim_complete.C
// to run with different options:(e.g more events, different momentum, Geant4)
// root  sim_complete.C"(100, "TGeant4",2)"

sim_complete(Int_t nEvents = 20, Float_t mom = 15.0,UInt_t seed = 123456) // 15.0 for study of FTS //6.991)
{
  //-----User Settings:-----------------------------------------------
  TString  SimEngine ="TGeant3";
  TString  OutputFile     ="sim_complete.root";
  TString  ParOutputfile  ="simparams.root";
  Double_t BeamMomentum   = mom;
  TString  MediaFile      ="media_pnd.geo";
  gDebug                  = 0;
  TString digiFile        = "all.par"; //The emc run the hit producer directly 
  // choose your event generator 
  Bool_t UseEvtGen	      =kFALSE; 
  Bool_t UseEvtGenDirect      =kTRUE;     
  Bool_t UseDpm 	      =kFALSE;
  Bool_t UseBoxGenerator      =kFALSE;
  
  //------------------------------------------------------------------

/*
// Turn off TMI on screen, put output in file
// get handle
cout << "At this point I am going to shut off the TMI and direct it into a file" << endl;
FairLogger *logger = FairLogger::GetLogger();
// define log file name
logger->SetLogFileName("sim.log");
// log to screen and to file
logger->SetLogToScreen(kTRUE);
logger->SetLogToFile(kTRUE);
// Print very accurate output. Levels are LOW, MEDIUM and HIGH
logger->SetLogVerbosityLevel("HIGH");
// Set different levels of verbosity. In the example everything >=INFO goes to the
// file and everything >= ERROR is printed on the screen
// LogLevels are (FATAL, ERROR, WARNING, INFO, DEBUG, DEBUG1, DEBUG2, DEBUG3, DEBUG4)
logger->SetLogFileLevel("INFO"); // FATAL, ERROR, WARNING and INFO
logger->SetLogScreenLevel("ERROR"); //Only FATAL and ERROR to screen
*/

  TStopwatch timer;
  timer.Start();
 
  // Load basic libraries---------------------------------------------
  gROOT->LoadMacro("$VMCWORKDIR/gconfig/rootlogon.C");
  rootlogon();
  gRandom->SetSeed(seed);
  // Create the Simulation run manager--------------------------------
  FairRunSim *fRun = new FairRunSim();
  fRun->SetName(SimEngine.Data() );
  fRun->SetOutputFile(OutputFile.Data());
  fRun->SetBeamMom(BeamMomentum);
  fRun->SetMaterials(MediaFile.Data());
  FairRuntimeDb *rtdb=fRun->GetRuntimeDb();
  
  // Set the parameters 
  //-------------------------------
  TString allDigiFile = gSystem->Getenv("VMCWORKDIR");
  allDigiFile += "/macro/params/";
  allDigiFile += digiFile;
 
 
  //-------Set the parameter output --------------------
  FairParAsciiFileIo* parIo1 = new FairParAsciiFileIo();
  parIo1->open(allDigiFile.Data(),"in");
  rtdb->setFirstInput(parIo1);        

 //---------------------Set Parameter output      ---------- 
  Bool_t kParameterMerged=kTRUE;
  FairParRootFileIo* output=new FairParRootFileIo(kParameterMerged);
  output->open(ParOutputfile.Data());
  rtdb->setOutput(output);

   // Create and add detectors

 //-------------------------  CAVE      -----------------

  FairModule *Cave= new PndCave("CAVE");
  Cave->SetGeometryFileName("pndcave.geo");
  fRun->AddModule(Cave); 
  //-------------------------  Magnet   ----------------- 
  FairModule *Magnet= new PndMagnet("MAGNET");
  //Magnet->SetGeometryFileName("FullSolenoid_V842.root");
  Magnet->SetGeometryFileName("FullSuperconductingSolenoid_v831.root");
  fRun->AddModule(Magnet);
  FairModule *Dipole= new PndMagnet("MAGNET");
  Dipole->SetGeometryFileName("dipole.geo");
  fRun->AddModule(Dipole);
  //-------------------------  Pipe     -----------------
  FairModule *Pipe= new PndPipe("PIPE");
  Pipe->SetGeometryFileName("beampipe_201112.root");
  fRun->AddModule(Pipe);
  //-------------------------  STT       -----------------
  FairDetector *Stt= new PndStt("STT", kTRUE);
  Stt->SetGeometryFileName("straws_skewed_blocks_35cm_pipe.geo");
  fRun->AddModule(Stt);
  //-------------------------  MVD       -----------------
  FairDetector *Mvd = new PndMvdDetector("MVD", kTRUE);
  Mvd->SetGeometryFileName("Mvd-2.1_FullVersion.root");
  fRun->AddModule(Mvd);
  //-------------------------  GEM       -----------------
  FairDetector *Gem = new PndGemDetector("GEM", kTRUE);
  Gem->SetGeometryFileName("gem_3Stations.root");
  fRun->AddModule(Gem);
  //-------------------------  EMC       -----------------
  PndEmc *Emc = new PndEmc("EMC",kTRUE);
  Emc->SetGeometryVersion(1);
  Emc->SetStorageOfData(kFALSE);
  fRun->AddModule(Emc);
  //-------------------------  SCITIL    -----------------
  FairDetector *SciT = new PndSciT("SCIT",kTRUE);
  SciT->SetGeometryFileName("barrel-SciTil_07022013.root");
  fRun->AddModule(SciT);
  //-------------------------  DRC       -----------------
  PndDrc *Drc = new PndDrc("DIRC", kTRUE);
  Drc->SetGeometryFileName("dirc_l0_p0_updated.root"); 
  Drc->SetRunCherenkov(kFALSE);
  fRun->AddModule(Drc); 
  //-------------------------  DISC      -----------------
  PndDsk* Dsk = new PndDsk("DSK", kTRUE);
  Dsk->SetStoreCerenkovs(kFALSE);
  Dsk->SetStoreTrackPoints(kFALSE);
  fRun->AddModule(Dsk);
  //-------------------------  MDT       -----------------
  PndMdt *Muo = new PndMdt("MDT",kTRUE);
  Muo->SetBarrel("fast");
  Muo->SetEndcap("fast");
  Muo->SetMuonFilter("fast");
  Muo->SetForward("fast");
  Muo->SetMdtMagnet(kTRUE);
  Muo->SetMdtMFIron(kTRUE);
  fRun->AddModule(Muo);
  //-------------------------  FTS       -----------------
  FairDetector *Fts= new PndFts("FTS", kTRUE); // FTS is active
  //FairDetector *Fts= new PndFts("FTS", kFALSE); // FTS is inactive
  Fts->SetGeometryFileName("fts.geo");
  fRun->AddModule(Fts); 
  //-------------------------  FTOF      -----------------
  FairDetector *FTof = new PndFtof("FTOF",kTRUE);
  FTof->SetGeometryFileName("ftofwall.root");
  fRun->AddModule(FTof);
  //-------------------------  RICH       ----------------
  FairDetector *Rich= new PndRich("RICH",kFALSE);
  Rich->SetGeometryFileName("rich_v2.geo");
  fRun->AddModule(Rich);

  // Create and Set Event Generator
  //-------------------------------
  FairPrimaryGenerator* primGen = new FairPrimaryGenerator();
  primGen->SetEventMeanTime(10);
  fRun->SetGenerator(primGen);
	 
  if(UseBoxGenerator){	// Box Generator
     FairBoxGenerator* boxGen = new FairBoxGenerator(13, 1); // 13 = muon-; 1 = multipl.
     boxGen->SetPRange(0.5,5.); // GeV/c
     boxGen->SetPhiRange(0., 360.); // Azimuth angle range [degree]
     boxGen->SetThetaRange(0.1, 5.); // Polar angle in lab system range [degree]
     boxGen->SetXYZ(0., 0., 0.); // cm
     primGen->AddGenerator(boxGen);
  }
  if(UseDpm){
  	  PndDpmDirect *Dpm= new PndDpmDirect(mom,1);
	  primGen->AddGenerator(Dpm);
  }
  if(UseEvtGen){
      // Alternative
      // Read in from file
      /*  FairEvtGenGenerator* evtGen = new FairEvtGenGenerator("output.evt");
      primGen->AddGenerator(evtGen);*/

	  TString  EvtInput =gSystem->Getenv("VMCWORKDIR");
	  EvtInput+="/input/psi2s_jpsi2pi_1k.evt";	
	  FairEvtGenGenerator* evtGen = new FairEvtGenGenerator(EvtInput.Data());
	  primGen->AddGenerator(evtGen);
  }	
  if(UseEvtGenDirect){
      // default macro
      //  TString  EvtInput =gSystem->Getenv("VMCWORKDIR");
      //  EvtInput+="/macro/run/2pipi.dec";
      //  PndEvtGenDirect *EvtGen = new PndEvtGenDirect("pbarpSystem", EvtInput.Data(), mom);

      //PndEvtGenDirect *EvtGen = new PndEvtGenDirect("pbarpSystem","PSI2S.DEC",BeamMomentum,gRandom->GetSeed(),"","X.pdl");
      PndEvtGenDirect *EvtGen = new PndEvtGenDirect("pbarpSystem","psi2s_jpsi2pi.dec",BeamMomentum,gRandom->GetSeed(),"","evt.pdl");


	  EvtGen->SetStoreTree(kTRUE); // This should be kTRUE but is kFALSE in default macros
	  primGen->AddGenerator(EvtGen);
  }

 //---------------------Create and Set the Field(s)---------- 
  PndMultiField *fField= new PndMultiField("FULL");
  fRun->SetField(fField);

 // EMC Hit producer
  //-------------------------------
  PndEmcHitProducer* emcHitProd = new PndEmcHitProducer();
  fRun->AddTask(emcHitProd);

 //-------------------------- switch on the vis manager-----------//
	fRun->SetStoreTraj(kTRUE); // uncomment that if you want to have points for plotting

 //-------------------------  Initialize the RUN  -----------------
  fRun->Init();
 //----------------- Set some cuts for the visualization-----------
  FairTrajFilter* trajFilter = FairTrajFilter::Instance(); // uncomment that if you want to have points for plotting
  // Set cuts for storing the trajectpries
  trajFilter->SetStepSizeCut(0.1); // in cm // this shows some weird behavior... leave at 0 // uncomment that if you want to have points for plotting
//     trajFilter->SetVertexCut(-2000., -2000., 4., 2000., 2000., 100.);
//     trajFilter->SetMomentumCutP(10e-3); // p_lab > 10e-3 GeV
//     trajFilter->SetEnergyCut(0., 1.02); // 0 < Etot < 1.02 GeV
  trajFilter->SetStorePrimaries(kTRUE); // uncomment that if you want to have points for plotting
  trajFilter->SetStoreSecondaries(kTRUE); // uncomment that if you want to have points for plotting



  //-------------------------  Run the Simulation  -----------------
  fRun->Run(nEvents);
 //-------------------------  Save the parameters ----------------- 
  rtdb->saveOutput();
 //------------------------Print some info and exit----------------     
  timer.Stop();
  Double_t rtime = timer.RealTime();
  Double_t ctime = timer.CpuTime();
  printf("RealTime=%f seconds, CpuTime=%f seconds\n",rtime,ctime);
  
  cout << " Test passed" << endl;
  cout << " All ok " << endl;
  
  exit(0);

}  
  
