// OutROOTProc.cc
// Contact person: P G Jones
// See OutROOTProc.hh for more details.
//—————————————————————---------------------------------------------——//
#include
#include
#include
#include
#include
#include
using namespace RAT;
#include
#include
#include
using namespace std;
OutROOTProc::OutROOTProc() : Processor("OutROOTProc")
{
fOverrideFileName = "";
fFileNameSuffix = "";
fFile = NULL;
fDSTree = NULL;
fRunTree = NULL;
fDSBranch = new DS::Entry();
fRunBranch = new DS::Run();
fUpdate = false;
fAutoFlush = 1000000;
fAutoSave = 10000000;
}
OutROOTProc::~OutROOTProc()
{
if( fFile != NULL )
{
// Store the current ROOT global directory (to switch back too) and switch to the file's directory
TDirectory* const oldDirectory = gDirectory;
fFile->cd();
// Write both trees to the file
if(!fDSTree->Write())
Log::Die("Could not write DS tree to file!");
if(!fRunTree->Write())
Log::Die("Could not write run tree to file!");
// Write the log and macro to a string in the file
TObjString* log = new TObjString( Log::GetLogBuffer().c_str() );
if(!log->Write( "log" ))
Log::Die("Could not write log to ROOT file");
TObjString* macro = new TObjString( Log::GetMacro().c_str() );
if(!macro->Write( "macro" ))
Log::Die("Could not write macro to ROOT file");
// Write the database trace (of access)
TMap *dbtrace = Log::GetDBTraceMap();
if(!dbtrace->Write("db", TObject::kSingleKey))
Log::Die("Could not write db trace to ROOT file");
// complete the meta information with the event counts etc.
fMetaHelper.SetStoredEvents(fDSTree->GetEntries());
MetaInformation::Get()->Finalise(fMetaHelper);
// Write the MetaInformation (RAT and DB state)
if(!MetaInformation::Get()->GetDSMeta().Write( "meta" ))
Log::Die("Could not write meta to ROOT file");
// Switch back to the previous ROOT global directory
oldDirectory->cd();
// Cleanup
fFile->Close(); // also deletes TTree and TObjString?
delete fFile;
delete fDSBranch;
delete fRunBranch;
}
// Don't delete branchDS because it looks like the TTree took ownership of it
}
void
OutROOTProc::SetS( const std::string& param,
const std::string& value )
{
if( param == "file" )
fOverrideFileName = value;
else if( param == "updatefile" )
{
fOverrideFileName = value;
fUpdate = true;
}
else if ( param == "suffix" ) {
fFileNameSuffix = value;
}
else
throw Processor::ParamUnknown( param );
}
void
OutROOTProc::SetI( const std::string& param,
const int value )
{
if( param == "autosave" )
{
if( value < 0 )
throw ParamInvalid( param, "autosave value must be >= 0" );
fAutoSave = value;
// SetAutoSave might be called after the file is already opened
if( fFile != NULL )
{
fDSTree->SetAutoSave( fAutoSave );
fRunTree->SetAutoSave( fAutoSave );
}
}
else if( param == "autoflush" )
{
fAutoFlush = value;
// SetAutoFlush might be called after the file is already opened
if( fFile != NULL )
{
fDSTree->SetAutoFlush( fAutoFlush );
fRunTree->SetAutoFlush( fAutoFlush );
}
}
}
void
OutROOTProc::BeginOfRun( DS::Run& )
{
// Get the database file name, this is the default unless the user overrides it
try
{
fDBFileName = DB::Get()->GetLink("IO")->GetS("default_output_filename");
if( fDBFileName.find( "." ) == string::npos )
fDBFileName += ".root";
}
catch( DBNotFoundError& e ) { Log::Die( "OutROOTProc::BeginOfRun: File name not found in IO[] ratdb." ); }
if( fFile == NULL )
OpenFile();
}
Processor::Result
OutROOTProc::DSEvent( DS::Run&,
DS::Entry& ds )
{
if( fFile == NULL )
OpenFile();
// Don't let a crazy track with hundreds of thousands of steps flood
// the output file
if( ds.MCExists() )
{
RAT::DS::MC& mc = ds.GetMC();
std::vector trackIDs = mc.GetMCTrackIDs();
for( size_t i = 0; i < trackIDs.size(); i++ )
{
RAT::DS::MCTrack& mctrack = mc.GetMCTrack(trackIDs.at(i));
size_t nsteps = mctrack.GetMCTrackStepCount();
if (nsteps > 10000) {
warn << "outroot: trimming intermediate steps from event #"
<< mc.GetMCID() << ", track #" << mctrack.GetTrackID()
<< " which has " << nsteps << " steps" << newline;
mctrack.PruneIntermediateMCTrackSteps();
}
}
}
TDirectory* const oldDirectory = gDirectory;
fFile->cd();
*fDSBranch = ds;
if(-1 == fDSTree->Fill()) Log::Die("Could not fill DS tree!");
oldDirectory->cd();
return Processor::OK;
}
void
OutROOTProc::EndOfRun( DS::Run& run )
{
if( fFile == NULL )
OpenFile();
TDirectory* const oldDirectory = gDirectory;
fFile->cd();
*fRunBranch = run;
if(-1 == fRunTree->Fill()) Log::Die("Could not fill run tree!");
oldDirectory->cd();
fMetaHelper.AddRun(run);
}
void
OutROOTProc::OpenFile()
{
string fileName = fDBFileName;
if( !fOverrideFileName.empty() )
fileName = fOverrideFileName;
if (!fFileNameSuffix.empty()) {
info << "OutROOTProc: Appending [" << fFileNameSuffix << "] to the output ROOT file name." << newline;
string tmp_file = "";
if( fileName.find( ".root" ) == string::npos ) {
// -- there is no .root extension
tmp_file = fileName;
} else {
tmp_file = fileName.substr(0,fileName.rfind(".root"));
}
fileName = tmp_file;
fileName += "_";
fileName += fFileNameSuffix;
fileName += ".root";
} else {
debug << "OutROOTProc: There is **NO** appendix to be added [" << fFileNameSuffix << "] to the file name. " << newline;
}
if( fUpdate )
{
info << "OutROOTProc: Appending to " << fileName << newline;
fFile = TFile::Open( fileName.c_str(), "UPDATE" );
}
else
{
info << "OutROOTProc: Writing to " << fileName << newline;
fFile = TFile::Open( fileName.c_str(), "RECREATE" );
}
if( fFile == NULL )
Log::Die( "OutROOTProc::OpenFile: Cannot open the file." );
if( fUpdate )
{
fDSTree = reinterpret_cast( fFile->Get( "T" ) );
fRunTree = reinterpret_cast( fFile->Get( "runT" ) );
fDSTree->SetBranchAddress( "ds", &fDSBranch, 0 );
fRunTree->SetBranchAddress( "run", &fRunBranch, 0 );
// load up the meta information and start a new pass
DS::Meta *meta = NULL;
fFile -> GetObject("meta", meta);
if(meta){
MetaInformation::Get()->Initialise(meta);
fMetaHelper.LoadLastPass(*meta);
}
}
else
{
// Setup tree
fDSTree = new TTree( "T", "RAT Tree" );
fDSTree->Branch( "ds", fDSBranch->ClassName(), &fDSBranch, 32000, 99 );
fRunTree = new TTree( "runT", "RAT Run Tree" );
fRunTree->Branch( "run", fRunBranch->ClassName(), &fRunBranch, 32000, 99 );
}
fDSTree->SetAutoFlush( fAutoFlush );
fDSTree->SetAutoSave( fAutoSave );
fRunTree->SetAutoFlush( fAutoFlush );
fRunTree->SetAutoSave( fAutoSave );
}