Universita' di GenovaINFN Sezione di Genova  
AIRWATCH / EUSO Genova

SimuApplication - source file

// implementation of SimuApplication
// $Id: SimuApplication.cc,v 1.6 2005/11/14 22:44:15 thea Exp $
// M. Pallavicini - created 28-12-2001
// 

#include <iostream>

#include "SimuApplication.hh"
#include "EsafMsgDispatcher.hh"
#include "Config.hh"

#include "Detector.hh"
#include "DetectorGeometry.hh"
#include "EEventGeoFiller.hh"
#include "LightToEuso.hh"
#include "EusoElectronics.hh"
#include "ElectronicsFactory.hh"
#include "LightFactory.hh"
#include "Telemetry.hh"
#include "PhotonsOnPupil.hh"
#include "EsafRandom.hh"

#include "EEvent.hh" 
#include "EHeader.hh"
#include "EAtmosphere.hh"
#include "EShower.hh"

#include <TBenchmark.h>
#include <TTree.h>
#include <TSysEvtHandler.h>
#include <TSystem.h>

#include <TObjectTable.h>

ClassImp(SimuApplication)

// static pointer to SimuApplication
SimuApplication *gSimuApplication = NULL;

//----- Interrupt signal handler -----------------------------------------------
//______________________________________________________________________________
class SimuInterruptHandler : public TSignalHandler, EsafMsgSource {
public:
    SimuInterruptHandler() : TSignalHandler(kSigInterrupt, kFALSE) { }
    Bool_t  Notify();
};

//______________________________________________________________________________
Bool_t SimuInterruptHandler::Notify()
{
    // TRint interrupt handler.

    Msg(EsafMsg::Panic) << "Esaf execution aborted" << MsgDispatch;

    return kTRUE;;
}

//______________________________________________________________________________
 SimuApplication::SimuApplication( 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
    //

    // Install interrupt handler
    SimuInterruptHandler *ih = new SimuInterruptHandler;
    ih->Add();
    SetSignalHandler(ih);

    fWriteTelemetry     = kFALSE;
    fWriteRoot          = kTRUE;

    string cmd; 
    for (Int_t i(0); i<argc; i++) {
        cmd +=argv[i]; cmd += " ";
    }

    {
        MsgForm(EsafMsg::Warning,"Current Directory: %s",gSystem->Getenv("PWD"));
        MsgForm(EsafMsg::Warning,"Simu command     : %s",argv[0]);
        
        const char esafsys[]="ESAFSYS";
        string esafCfgPath;

        if ( gSystem->Getenv(esafsys) )
            fEsafSys = gSystem->Getenv("ESAFSYS");
        else
            fEsafSys = gSystem->Getenv("PWD");
            
        
        esafCfgPath = fEsafSys+"/config";
        ConfigFileParser::ChangeConfigDir(esafCfgPath);
        MsgForm(EsafMsg::Warning,"Simu Config Path : %s",esafCfgPath.c_str());

        // 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();
    
        
    // force all elements of the chain to be built (if required by Config)
    SetChanged(kESAFLight);
    SetChanged(kESAFDetector);

    try {	
        Build();
    }
    catch (exception &e) {
        cerr << "ESAF ERROR: " << e.what() << endl;
        exit(0);
    }

    gSimuApplication = this;
}

//______________________________________________________________________________
 SimuApplication::~SimuApplication() {
    // destructor
    // close output file if open
    // save random engine status
    
    EndJob();
    SafeDelete( fManager );

    Msg(EsafMsg::Debug) << "Manager deleted" << MsgDispatch;

}

//______________________________________________________________________________
 void SimuApplication::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()->UseConfig( 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 ) 
                fUsrCfgs.push_back(s.substr(pos+1));
            else
                FatalError("Invalid parameter "+string(argv[i]));

        } 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
    vector<string>::const_iterator itCfg;
    for( itCfg=fUsrCfgs.begin(); itCfg!=fUsrCfgs.end(); itCfg++)
        Config::Get()->LoadUserConfig(itCfg->c_str());

    // the apply custom parameters
    for (size_t i(0); i< fUsrKeys.size(); i++) {
        Config::Get()->AddUserDefinition(fUsrKeys[i],fUsrValues[i]);
    }
}

//______________________________________________________________________________
 void SimuApplication::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 += '/';

    if ( fOutDir.find('/') != 0 )
        fOutDir = fEsafSys+'/'+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()->SetCfgDump( fFileNames[kDump].c_str() );

    Msg(EsafMsg::Info) << "Logging to file "+fFileNames[kDump]+
        " started" << MsgDispatch;

    vector<string>::const_iterator itCfg;
    for( itCfg=fUsrCfgs.begin(); itCfg!=fUsrCfgs.end(); itCfg++)
        Msg(EsafMsg::Debug) << "Using custom config: "+(*itCfg)<< 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 SimuApplication::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 SimuApplication::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(kFALSE);

    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;

        // parameters are filled 
        Manager()->ResetRunPars();
        fDetector = ElectronicsFactory::Get()->MakeDetector();


        DetectorGeometry* detGeo = fDetector->GetGeometry();
        ConfigFileParser* p = Config::Get()->GetCF("General","Euso");
        Double_t alt = p->GetNum("Euso.fAltitude")*sou::km;
        TVector3 pos(0,0,alt);
        detGeo->SetPos(pos);

        /*             // Detector's orientation
         *             // diabled until further tests.
         *
         *             Double_t phi, theta, psi;
         *             phi = p->GetNum("Euso.fXPhi");
         *             theta = p->GetNum("Euso.fXTheta");
         *             psi = p->GetNum("Euso.fXPsi");
         *             geo->SetXEulerRotation(phi, theta, psi);
         */
        
        SetChanged(kESAFDetector,kFALSE);
    }

    // rebuild shower generator if required
    if ( HasChanged(kESAFLight) ) {
        if ( fLightToEuso )  
            delete fLightToEuso;
        fLightToEuso=NULL;
        fLightToEuso = LightFactory::Get()->GetLightToEuso();

        SetChanged(kESAFLight,kFALSE);
    } 
}


//______________________________________________________________________________
 void SimuApplication::Help(const char* line) {
    TApplication::Help(line);
}

//______________________________________________________________________________
 Bool_t SimuApplication::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());
        

        if ( Euso() ) {
            EEventGeoFiller a( Euso()->GetGeometry() );
            Event()->Fill(a);
        }
    }  

    // 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 object 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()->FillEvent();

    fEvCount++;
    return kTRUE;


}

//______________________________________________________________________________
 Bool_t SimuApplication::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
    //

    Int_t ev = fEvMax;
    ResetEvCounter();

    // OpenFile
    if (fWriteRoot) Manager()->Open( fFileNames[kRoot] );
    Event()->GetHeader()->SetRandom(EsafRandom::Get());
    
    // Lock the Event
    Manager()->LockEvent();

    ////////////////////////////////////////////////////////
    
    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));

    // Unlock Event
    Manager()->UnlockEvent();
    // Close File
    if (fWriteRoot) Manager()->Close();
    //
    return kTRUE;
}

//______________________________________________________________________________
 void SimuApplication::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 SimuApplication::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 SimuApplication::EnableModule(EsafElement e, Bool_t val) {
//    fEnModule[e]=val; 
//    SetChanged(e);
//    //Build();
//}

//______________________________________________________________________________
 void SimuApplication::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;
    }
}

About Us | EUSO Official Website | Web pages created by Roberto Pesce and Alessandro Thea - Last Update Wed Nov 16 16:57:39 2005 Wed Nov 16 16:29:22 2005