// implementation of EusoApplication
// $Id: EusoApplication.cc,v 1.59 2005/04/22 15:53:35 thea Exp $
// M. Pallavicini - created 28-12-2001
//
#include <iostream>
#include "EusoApplication.hh"
#include "EsafMsgDispatcher.hh"
#include "Config.hh"
#include "Detector.hh"
#include "EusoDetector.hh"
#include "LightToEuso.hh"
#include "EusoElectronics.hh"
#include "ElectronicsFactory.hh"
#include "LightFactory.hh"
#include "OpticsAnalysisModule.hh"
#include "Telemetry.hh"
#include "PhotonsOnPupil.hh"
#include "EsafRandom.hh"
#include "EEvent.hh"
#include "EAtmosphere.hh"
#include "EShower.hh"
#include <TBenchmark.h>
#include <TTree.h>
#include <TSysEvtHandler.h>
#include <TSystem.h>
#include <TObjectTable.h>
ClassImp(EusoApplication)
// static pointer to EusoApplication
EusoApplication *gEusoApplication = NULL;
//______________________________________________________________________________
EusoApplication::EusoApplication( Int_t argc, char **argv ) :
TRint("Euso Detector Simulation", &argc, argv, 0, 0, kTRUE ),
fLightToEuso(0), fDetector(0), fLock(0), fEvCount(0), fEvMax(1),
fManager(0) {
//
// Constructor.
// Parse inline parameters, build the detector and electronics
// reload random seed if required
//
fWriteTelemetry = kFALSE;
fWriteRoot = kTRUE;
fDoOpticsAnalysis = kFALSE;
string cmd;
for (Int_t i(0); i<argc; i++) {
cmd +=argv[i]; cmd += " ";
}
// initialize message dispatcher
EsafMsgDispatcher::Get()->LoadConfig();
// load standard configs
Config::Get()->LoadStandardConfigs();
Msg(EsafMsg::Debug) << "Simu command line:" << MsgDispatch;
Msg(EsafMsg::Debug) << cmd << MsgDispatch;
ParseCmdLine(argc,argv);
Init();
//FIXME handling of the special modes must be improved!
if ( fDoOpticsAnalysis ) {
EnableModule(kESAFLight, kFALSE);
fWriteRoot = kFALSE;
fWriteTelemetry = kFALSE;
gROOT->SetBatch(kTRUE);
} else {
// force all elements of the chain to be built (if required by Config)
SetChanged(kESAFLight);
SetChanged(kESAFDetector);
// right now just enable both light and euso
EnableModule(kESAFLight);
EnableModule(kESAFDetector);
try {
Build();
}
catch (exception &e) {
cerr << "ESAF ERROR: " << e.what() << endl;
exit(0);
}
}
gEusoApplication = this;
}
//______________________________________________________________________________
EusoApplication::~EusoApplication() {
// destructor
// close output file if open
// save random engine status
EndJob();
SafeDelete( fManager );
}
//______________________________________________________________________________
void EusoApplication::ParseCmdLine( Int_t argc, char** argv ) {
//
// Parse the commandline and set the corresponding variables
//
for(Int_t i=1; i<argc; i++) { //FIXME parser is too stupid....
if ( strlen(argv[i]) >= 2 &&
(argv[i][0] == '-') &&
(argv[i][0] != '-')) {
MsgForm(EsafMsg::Warning,"Simu usage:");
MsgForm(EsafMsg::Warning,"");
MsgForm(EsafMsg::Warning," Simu [-b --events=<n> --seed=<n> --ofile=<fname>
--no-telemetry --no-root --no-files--stdcfg=<cfg> --usrcfg=<cfg>
--ClassName.VarName=val] ");
} else if (strncmp(argv[i],"--events=",9)==0) {
// Number of events
sscanf(argv[i]+9,"%d",&fEvMax);
} else if (strncmp(argv[i],"--seed=",7)==0) {
// Set random seed
string key = "EsafRandom";
string value = key+".fSeed="+(argv[i]+7);
fUsrKeys.push_back(key);
fUsrValues.push_back(value);
} else if (strncmp(argv[i],"--ofile=",8)==0) {
// Superseed output file name
string key = "Run";
string value = key+".fFilesPrefix="+(argv[i]+8);
fUsrKeys.push_back(key);
fUsrValues.push_back(value);
Msg(EsafMsg::Info) << "Output file name set to: " << (argv[i]+8) << MsgDispatch;
} else if (strncmp(argv[i],"--odir=",7)==0) {
// Set Custom output directory
string key = "Run";
string value = key+".fOutputDir"+(argv[i]+7);
fUsrKeys.push_back(key);
fUsrValues.push_back(value);
Msg(EsafMsg::Info) << "Output directory set to: " << (argv[i]+7)<< MsgDispatch;
} else if (strncmp(argv[i],"--runname=",10)==0) {
// Add run name to the truth
fRunName = argv[i]+10;
} else if (strncmp(argv[i],"--no-telemetry",14)==0) {
// Don't write telemery
fWriteTelemetry=kFALSE;
} else if (strncmp(argv[i],"--no-root",8)==0) {
// Don't save rootfile
fWriteRoot=kFALSE;
} else if (strncmp(argv[i],"--no-files",8)==0) {
// Don't write root AND telemetry
fWriteTelemetry=kFALSE;
fWriteRoot=kFALSE;
} else if (strncmp(argv[i],"--stdcfg",8) == 0) {
//Standard Configuration
string s = argv[i]+8;
size_t pos = s.find('=');
if ( pos != string::npos )
Config::Get()->DefineConfig( s.substr(pos+1) );
else
FatalError("Invalid parameter "+string(argv[i]));
} else if (strncmp(argv[i],"--usrcfg",8) == 0 ) {
// User Configuration
string s = argv[i]+7;
size_t pos = s.find('=');
if ( pos != string::npos )
fUsrCfg += s.substr(pos+1);
else
FatalError("Invalid parameter "+string(argv[i]));
} else if (strncmp(argv[i],"--opticsanalysis",16)==0) { // Esaf Special Mode
// Enable OpticsAnalysis then exit loop
fDoOpticsAnalysis=true;
} else if (strncmp(argv[i],"--",2)==0) {
// Ok, it seems to be user-defined var
string s = argv[i]+2;
size_t pos = s.find('.');
if ( pos == string::npos )
FatalError("Invalid parameter "+string(argv[i]));
else
// user defined variable syntax
// ClassName::VarName
fUsrKeys.push_back(s.substr(0,pos));
fUsrValues.push_back(s);
}
}
// load user definition file first
if (!fUsrCfg.empty()) Config::Get()->LoadUserConfig(fUsrCfg.c_str());
// the apply custom parameters
for (size_t i(0); i< fUsrKeys.size(); i++) {
Config::Get()->AddUserDefinition(fUsrKeys[i],fUsrValues[i]);
}
}
//______________________________________________________________________________
void EusoApplication::Init() {
//
// Initialize Config and the message system
//
// initialize the file names.
fOutFileName = Config::Get()->GetCF("General","Run")->GetStr("Run.fFilesPrefix");
fOutDir = Config::Get()->GetCF("General","Run")->GetStr("Run.fOutputDir");
if ( fOutDir.rfind('/') != fOutDir.size()-1 )
fOutDir += '/';
fFileNames[kLog] = fOutDir+fOutFileName+".log";
fFileNames[kDump] = fOutDir+fOutFileName+".ConfigDump.cfg";
fFileNames[kRoot] = fOutDir+fOutFileName+".root";
fFileNames[kTelemetry] = fOutDir+fOutFileName+".Telemetry.dat.gz";
// open logfile
EsafMsgDispatcher::Get()->OpenLog(fFileNames[kLog]);
// set config dump
Config::Get()->SetDumpFileName( fFileNames[kDump] );
Msg(EsafMsg::Info) << "Logging to file "+fFileNames[kDump]+
" started" << MsgDispatch;
if (!fUsrCfg.empty())
Msg(EsafMsg::Debug) << "Using custom config: "+fUsrCfg<< MsgDispatch;
// add the user defined variables to the logfile
for (size_t i(0); i< fUsrKeys.size(); i++)
Msg(EsafMsg::Debug) << "Cmd line option: class "+
fUsrKeys[i]+", value "+fUsrValues[i] << MsgDispatch;
}
//______________________________________________________________________________
void EusoApplication::EndJob() {
// final clean up
// delete Euso detector if it exists
if ( Euso() ) {
delete fDetector;
fDetector = NULL;
}
// delete LightToEuso
if ( Light() ) {
delete fLightToEuso;
fLightToEuso = NULL;
}
// save trees and close file
Manager()->Close();
// save standard config if required
Config::Get()->SaveConfig();
}
//______________________________________________________________________________
void EusoApplication::Build() {
// build (or rebuild) application chain
//FIXME: When Config is resetted all ESAF modules must be rebuilt due to
// the ConfigFileParser pointers.
// Config::Reset must be modified to reset just one module at time.
Config::Get()->Reset();
SafeDelete( fManager );
fManager = new SimuRootFileManager();
if (fWriteRoot)
Manager()->Open( fFileNames[kRoot] );
// rebuild euso detector if required
// set gEusoDetector to right value (global pointer defined in EusoDetector.hh)
if ( HasChanged(kESAFDetector) ) {
if (fDetector)
delete fDetector;
fDetector = NULL;
if ( isModuleEnabled(kESAFDetector) ) {
// parameters are filled
Manager()->ResetRunPars();
fDetector = ElectronicsFactory::Get()->MakeDetector();
Manager()->FillRunTree();
}
SetChanged(kESAFDetector,kFALSE);
}
// rebuild shower generator if required
if ( HasChanged(kESAFLight) ) {
if ( fLightToEuso )
delete fLightToEuso;
fLightToEuso=NULL;
if ( isModuleEnabled(kESAFLight) )
fLightToEuso = LightFactory::Get()->GetLightToEuso();
else
cout << "Light not enabledn";
SetChanged(kESAFLight,kFALSE);
}
}
//______________________________________________________________________________
void EusoApplication::Help(const char* line) {
TApplication::Help(line);
}
//______________________________________________________________________________
Bool_t EusoApplication::DoEvent(Bool_t WriteRoot, Bool_t WriteTelemetry) {
// simulate and (if required) display a single event
// WriteRoot=true : writes event in Root file
// WriteTelemetry=true : writes in Telemetry (ASCII) file
// time info
TString s = Form("Event %d",fEvCount);
TBenchmark gB;
gB.Start(s);
if ( isLocked() ) {
MsgForm(EsafMsg::Warning, "Cannot run because application is lockedn");
MsgForm(EsafMsg::Warning, "Close configuration windows before runningn");
return kFALSE;
}
// clear root event
if ( Event() ) {
Event()->Clear();
Event()->Build(GetRunNumber(),fEvCount, fRunName);
// save the status of the random number generator before simulating the new event
Event()->GetHeader()->SetRandom(EsafRandom::Get());
}
// event generation and radiative transport through atmosphere
MCTruth* truth = 0;
PhotonsOnPupil* photons=0;
if ( Light() && Euso() ) {
Light()->Reset();
photons = Light()->Get(Euso()->GetGeometry());
if ( photons == NULL ) {
MsgForm(EsafMsg::Info,"PhotonsOnPupil objecti is null");
return kTRUE;
}
truth = Light()->GetTruth();
} else
MsgForm(EsafMsg::Info,"LightToEuso is null.");
// detector response simulation
Telemetry* data = 0;
if ( ( Euso() && photons && Light() ) || ( Euso() && (!Light()) )) {
Euso()->Reset();
data = Euso()->Get( photons );
}
// dump time info on screen
gB.Stop(s);
MsgForm(EsafMsg::Info,"Event %d REAL=%6.2f s CPU=%6.2f s",
fEvCount,gB.GetRealTime(s), gB.GetCpuTime(s) );
// write output data file (Telemetry format)
if ( data && WriteTelemetry ) {
data->SetTruth( truth );
if ( !data->IsOpen() ) data->Open( fFileNames[kTelemetry].c_str() );
data->Write();
}
// fill root file if enabled
if ( Event() && WriteRoot )
Manager()->FillEventsTree();
fEvCount++;
return kTRUE;
}
//______________________________________________________________________________
Bool_t EusoApplication::DoAll() {
//
// Simulate all events available from the data source
// DoEvent returns kFalse in case of error so the run will stop
// if fEvMax is -1 it never stops until error or end of file
//
if ( fDoOpticsAnalysis ) {
DoOpticsAnalysis();
return kTRUE;
}
Int_t ev = fEvMax;
ResetEvCounter();
TString jobname = Form("Job with %d events",fEvMax);
TBenchmark gB;
gB.Start(jobname);
SetRunNumber( (Int_t)Config::Get()->GetCF("General","Run")->GetNum("Run.fRunNumber"));
while( ev-- ) {
try {
if ( !DoEvent(fWriteRoot,fWriteTelemetry) )
return kFALSE;
}
catch (exception &e) {
Msg(EsafMsg::Panic) << e.what() << MsgDispatch;
}
}
gB.Stop(jobname);
MsgForm(EsafMsg::Info,"Average time per event: REAL=%6.2f s CPU=%6.2f s",
gB.GetRealTime(jobname)/fEvMax, (gB.GetCpuTime(jobname)/fEvMax) );
MsgForm(EsafMsg::Info,"Total time: REAL=%6.2f s CPU=%6.2f s",
gB.GetRealTime(jobname), gB.GetCpuTime(jobname));
return kTRUE;
}
//______________________________________________________________________________
void EusoApplication::SetLock( Bool_t lk) {
//
// Lock the application.
// If locked, events are not processed
//
if ( lk )
fLock++;
else
fLock--;
if (fLock<0) fLock=0;
}
//______________________________________________________________________________
Bool_t EusoApplication::DumpLastEvent(string* buffer ) {
//
// dump event on stdout or into a buffer
// buffer must be large enough
// if buffer is NULL, dump on cout
// return kFALSE if no data is available
//
// if ( ! E()->Data() )
// return kFALSE;
// if ( buffer )
// *buffer = E()->Data()->Dump();
// else {
// cout << endl << endl;
// cout << "EUSO DETECTOR SIMULATION DUMP. Event=" << EventCounter() << endl;
// cout << E()->Data()->Dump() << endl << endl;
// cout.flush();
// }
return kTRUE;
}
//______________________________________________________________________________
void EusoApplication::EnableModule(EsafElement e, Bool_t val) {
fEnModule[e]=val;
SetChanged(e);
//Build();
}
//______________________________________________________________________________
void EusoApplication::ResetCopies() {
// reset list of event copies
// used for re-rerunning the same event with different parameters
for ( Int_t i=0; i<fEventCopies.GetEntriesFast(); i++) {
EEvent *pEv = (EEvent*)(fEventCopies[i]);
if ( pEv )
delete pEv;
}
}
//______________________________________________________________________________
void EusoApplication::DoOpticsAnalysis() {
//
// Enable and run OpticsAnalysis module
//
OpticsAnalysisModule *oam;
oam = new OpticsAnalysisModule();
oam->Init();
oam->PreProcess();
oam->Process();
oam->PostProcess();
oam->Done();
}