Newer
Older
Markus Frank
committed
//==========================================================================
Markus Frank
committed
//--------------------------------------------------------------------------
// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
Markus Frank
committed
// All rights reserved.
Markus Frank
committed
// For the licensing terms see $DD4hepINSTALL/LICENSE.
// For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
Markus Frank
committed
// Author : M.Frank
//
//==========================================================================
Markus Frank
committed
#include "DD4hep/Printout.h"
#include "DD4hep/Primitives.h"
#include "DD4hep/InstanceCount.h"
#include "DDG4/Geant4HitCollection.h"
#include "DDG4/Geant4Output2ROOT.h"
#include "DDG4/Geant4Particle.h"
Markus Frank
committed
#include "DDG4/Geant4Data.h"
// Geant4 include files
#include "G4HCofThisEvent.hh"
// ROOT include files
#include "TFile.h"
#include "TTree.h"
#include "TBranch.h"
using namespace dd4hep::sim;
using namespace dd4hep;
using namespace std;
/// Standard constructor
Markus Frank
committed
Geant4Output2ROOT::Geant4Output2ROOT(Geant4Context* ctxt, const string& nam)
Markus Frank
committed
: Geant4OutputAction(ctxt, nam), m_file(0), m_tree(0) {
declareProperty("Section", m_section = "EVENT");
declareProperty("HandleMCTruth", m_handleMCTruth = true);
InstanceCount::increment(this);
}
/// Default destructor
Geant4Output2ROOT::~Geant4Output2ROOT() {
InstanceCount::decrement(this);
if (m_file) {
Markus Frank
committed
TDirectory::TContext ctxt(m_file);
m_tree->Write();
m_file->Close();
m_tree = 0;
}
}
/// Create/access tree by name
Markus Frank
committed
TTree* Geant4Output2ROOT::section(const string& nam) {
Sections::const_iterator i = m_sections.find(nam);
if (i == m_sections.end()) {
Markus Frank
committed
TDirectory::TContext ctxt(m_file);
TTree* t = new TTree(nam.c_str(), ("Geant4 " + nam + " information").c_str());
m_sections.insert(make_pair(nam, t));
return t;
}
return (*i).second;
}
/// Callback to store the Geant4 run information
void Geant4Output2ROOT::beginRun(const G4Run* run) {
if (!m_file && !m_output.empty()) {
Markus Frank
committed
TDirectory::TContext ctxt(TDirectory::CurrentDirectory());
m_file = TFile::Open(m_output.c_str(), "RECREATE", "dd4hep Simulation data");
throw runtime_error("Failed to open ROOT output file:'" + m_output + "'");
}
m_tree = section("EVENT");
}
Geant4OutputAction::beginRun(run);
}
/// Fill single EVENT branch entry (Geant4 collection data)
Markus Frank
committed
int Geant4Output2ROOT::fill(const string& nam, const ComponentCast& type, void* ptr) {
if (m_file) {
TBranch* b = 0;
Branches::const_iterator i = m_branches.find(nam);
if (i == m_branches.end()) {
TClass* cl = TBuffer::GetClass(type.type);
if (cl) {
b = m_tree->Branch(nam.c_str(), cl->GetName(), (void*) 0);
b->SetAutoDelete(false);
m_branches.insert(make_pair(nam, b));
}
else {
throw runtime_error("No ROOT TClass object availible for object type:" + typeName(type.type));
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
}
}
else {
b = (*i).second;
}
Long64_t evt = b->GetEntries(), nevt = b->GetTree()->GetEntries(), num = nevt - evt;
if (nevt > evt) {
b->SetAddress(0);
while (num > 0) {
b->Fill();
--num;
}
}
b->SetAddress(&ptr);
int nbytes = b->Fill();
if (nbytes < 0) {
throw runtime_error("Failed to write ROOT collection:" + nam + "!");
}
return nbytes;
}
return 0;
}
/// Commit data at end of filling procedure
void Geant4Output2ROOT::commit(OutputContext<G4Event>& ctxt) {
if (m_file) {
TObjArray* a = m_tree->GetListOfBranches();
Long64_t evt = m_tree->GetEntries() + 1;
Int_t nb = a->GetEntriesFast();
/// Fill NULL pointers to all branches, which have less entries than the Event branch
for (Int_t i = 0; i < nb; ++i) {
TBranch* br_ptr = (TBranch*) a->UncheckedAt(i);
Long64_t br_evt = br_ptr->GetEntries();
if (br_evt < evt) {
Long64_t num = evt - br_evt;
br_ptr->SetAddress(0);
while (num > 0) {
br_ptr->Fill();
--num;
}
}
}
m_tree->SetEntries(evt);
}
Geant4OutputAction::commit(ctxt);
}
Markus Frank
committed
/// Callback to store the Geant4 event
void Geant4Output2ROOT::saveEvent(OutputContext<G4Event>& /* ctxt */) {
Geant4ParticleMap* parts = context()->event().extension<Geant4ParticleMap>();
if ( parts ) {
Markus Frank
committed
typedef Geant4HitWrapper::HitManipulator Manip;
typedef Geant4ParticleMap::ParticleMap ParticleMap;
Manip* manipulator = Geant4HitWrapper::manipulator<Geant4Particle>();
const ParticleMap& pm = parts->particles();
Markus Frank
committed
vector<void*> particles;
for(ParticleMap::const_iterator i=pm.begin(); i!=pm.end(); ++i) {
particles.push_back((ParticleMap::mapped_type*)(*i).second);
}
fill("MCParticles",manipulator->vec_type,&particles);
}
}
/// Callback to store each Geant4 hit collection
void Geant4Output2ROOT::saveCollection(OutputContext<G4Event>& /* ctxt */, G4VHitsCollection* collection) {
Geant4HitCollection* coll = dynamic_cast<Geant4HitCollection*>(collection);
Markus Frank
committed
string hc_nam = collection->GetName();
vector<void*> hits;
if (coll) {
coll->getHitsUnchecked(hits);
Markus Frank
committed
size_t nhits = coll->GetSize();
Markus Frank
committed
if ( m_handleMCTruth && m_truth && nhits > 0 ) {
Markus Frank
committed
try {
Markus Frank
committed
for(size_t i=0; i<nhits; ++i) {
Geant4HitData* h = coll->hit(i);
Geant4Tracker::Hit* trk_hit = dynamic_cast<Geant4Tracker::Hit*>(h);
if ( 0 != trk_hit ) {
Geant4HitData::Contribution& t = trk_hit->truth;
int trackID = t.trackID;
t.trackID = m_truth->particleID(trackID);
}
Geant4Calorimeter::Hit* cal_hit = dynamic_cast<Geant4Calorimeter::Hit*>(h);
if ( 0 != cal_hit ) {
Geant4HitData::Contributions& c = cal_hit->truth;
for(Geant4HitData::Contributions::iterator j=c.begin(); j!=c.end(); ++j) {
Geant4HitData::Contribution& t = *j;
int trackID = t.trackID;
t.trackID = m_truth->particleID(trackID);
}
}
}
Markus Frank
committed
}
catch(...) {
Markus Frank
committed
printout(ERROR,name(),"+++ Exception while saving collection %s.",hc_nam.c_str());
Markus Frank
committed
}
}
fill(hc_nam, coll->vector_type(), &hits);
}
}