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
//
//==========================================================================
// Framework include files
#define DDG4_MAKE_INSTANTIATIONS
#include <DD4hep/Detector.h>
#include <DD4hep/Printout.h>
#include <DDG4/Geant4HitCollection.h>
#include <DDG4/Geant4DataConversion.h>
#include <DDG4/Geant4SensDetAction.h>
#include <DDG4/Geant4Context.h>
#include <DDG4/Geant4Primary.h>
#include <DDG4/Geant4Data.h>
#include <lcio.h>
#include <IMPL/LCCollectionVec.h>
#include <IMPL/LCEventImpl.h>
#include <IMPL/ClusterImpl.h>
#include <IMPL/SimTrackerHitImpl.h>
#include <IMPL/SimCalorimeterHitImpl.h>
#include <IMPL/MCParticleImpl.h>
#include <UTIL/Operators.h>
#include <UTIL/ILDConf.h>
#include <CLHEP/Units/SystemOfUnits.h>
using namespace lcio ;
//==================================================================================
//
// SimCalorimeterHit:
// ------------------
// LCIO::CHBIT_STEP If detailed mode set | YES if detailed
// LCIO::CHBIT_LONG: Position is stored | YES
// LCIO::CHBIT_ID1: CellID1 is stored | YES
//
//
// SimTrackerHit:
// --------------
// LCIO::THBIT_ID1: CellID1 is stored (TrackerHit) | YES
// LCIO::THBIT_MOMENTUM: Momentum is stored | YES if detailed
//
//==================================================================================
/*
* Simulation namespace declaration
*/
typedef VolumeManager VolMgr;
typedef IDDescriptor IDDescriptor;
/// Data conversion interface calling lower level explicit convetrers
/**
* @author M.Frank
* @version 1.0
*/
template <> lcio::LCCollectionVec*
Markus Frank
committed
pair<const Geant4Context*,G4VHitsCollection*>,
Geant4HitCollection>::operator()(const arg_t& args) const {
G4VHitsCollection* c = args.second;
Geant4HitCollection* coll = dynamic_cast<Geant4HitCollection*>(c);
if ( coll ) {
Markus Frank
committed
typedef pair<arg_t::first_type,Geant4HitCollection*> _A;
typedef Geant4Conversion<output_t,_A> _C;
const _C& cnv= _C::converter(coll->type().type());
Markus Frank
committed
return cnv(_A(args.first,coll));
}
throw unrelated_type_error(typeid(Geant4HitCollection),typeid(*c),
Markus Frank
committed
"Cannot save the collection entries of:"+c->GetName());
/// Data conversion interface creating lcio::SimTrackerHitImpl from Geant4Tracker::Hit structures
/**
* This converter is to be used, when the sensitive detectors create fill collections
* of type Geant4HitCollection with objects of type **Geant4Tracker::Hit**.
* The original objects are untouched and are automatically when the hosting
* Geant4HitCollection object is released.
*
* @author M.Frank
* @version 1.0
*/
Markus Frank
committed
template <> lcio::LCCollectionVec*
Markus Frank
committed
pair<const Geant4Context*,Geant4HitCollection*>,
Geant4Tracker::Hit>::operator()(const arg_t& args) const {
Geant4HitCollection* coll = args.second;
string hc_nam = coll->GetName();
Geant4Sensitive* sd = coll->sensitive();
size_t nhits = coll->GetSize();
string dsc = encoding(sd->sensitiveDetector());
Geant4ParticleMap* pm = args.first->event().extension<Geant4ParticleMap>();
lcio::LCEventImpl* lc_evt = args.first->event().extension<lcio::LCEventImpl>();
EVENT::LCCollection* lc_part = lc_evt->getCollection(lcio::LCIO::MCPARTICLE);
lcio::LCCollectionVec* lc_coll = nullptr;
bool isNewCollection = false;
try {
lc_coll = static_cast<lcio::LCCollectionVec*>(lc_evt->getCollection(hc_nam));
} catch (lcio::DataNotAvailableException &e) {
lc_coll = new lcio::LCCollectionVec(lcio::LCIO::SIMTRACKERHIT);
isNewCollection = true;
}
UTIL::CellIDEncoder<SimTrackerHit> decoder(dsc,lc_coll);
int hit_creation_mode = sd->hitCreationMode();
if ( hit_creation_mode == Geant4Sensitive::DETAILED_MODE )
Markus Frank
committed
lc_coll->setFlag(UTIL::make_bitset32(LCIO::THBIT_MOMENTUM,LCIO::THBIT_ID1));
Markus Frank
committed
lc_coll->setFlag(LCIO::THBIT_ID1);
lc_coll->reserve(nhits + lc_coll->getNumberOfElements());
for(size_t i=0; i<nhits; ++i) {
Markus Frank
committed
const Geant4Tracker::Hit* hit = coll->hit(i);
const Geant4Tracker::Hit::Contribution& t = hit->truth;
int trackID = pm->particleID(t.trackID);
EVENT::MCParticle* lc_mcp = (EVENT::MCParticle*)lc_part->getElementAt(trackID);
double pos[3] = {hit->position.x()/CLHEP::mm, hit->position.y()/CLHEP::mm, hit->position.z()/CLHEP::mm};
Markus Frank
committed
lcio::SimTrackerHitImpl* lc_hit = new lcio::SimTrackerHitImpl;
lc_hit->setCellID0((hit->cellID >> 0 ) & 0xFFFFFFFF);
lc_hit->setCellID1((hit->cellID >> sizeof(int)*8) & 0xFFFFFFFF);
lc_hit->setEDep(hit->energyDeposit/CLHEP::GeV);
lc_hit->setPathLength(hit->length/CLHEP::mm);
lc_hit->setTime(hit->truth.time/CLHEP::ns);
Markus Frank
committed
lc_hit->setMCParticle(lc_mcp);
lc_hit->setPosition(pos);
lc_hit->setMomentum(hit->momentum.x()/CLHEP::GeV,hit->momentum.y()/CLHEP::GeV,hit->momentum.z()/CLHEP::GeV);
#if LCIO_VERSION_GE( 2, 8 )
auto particleIt = pm->particles().find(trackID);
if( ( particleIt != pm->particles().end()) ){
// if the original track ID of the particle is not the same as the
// original track ID of the hit it was produced by an MCParticle that
// is no longer stored
lc_hit->setProducedBySecondary( (particleIt->second->originalG4ID != t.trackID) );
}
#endif
Markus Frank
committed
lc_coll->addElement(lc_hit);
if(isNewCollection) {
lc_evt->addCollection(lc_coll, hc_nam);
}
/// Data conversion interface creating lcio::SimCalorimeterHitImpl from Geant4Calorimeter::Hit structures
/**
* This converter is to be used, when the sensitive detectors create fill collections
* of type Geant4HitCollection with objects of type **Geant4Calorimeter::Hit**.
* The original objects are untouched and are automatically when the hosting
* Geant4HitCollection object is released.
*
* @author M.Frank
* @version 1.0
*/
Markus Frank
committed
template <> lcio::LCCollectionVec*
Markus Frank
committed
pair<const Geant4Context*,Geant4HitCollection*>,
Geant4Calorimeter::Hit>::operator()(const arg_t& args) const {
typedef Geant4HitData::Contributions Contributions;
Geant4HitCollection* coll = args.second;
string hc_nam = coll->GetName();
Geant4Sensitive* sd = coll->sensitive();
size_t nhits = coll->GetSize();
string dsc = encoding(sd->sensitiveDetector());
Geant4ParticleMap* pm = args.first->event().extension<Geant4ParticleMap>();
lcio::LCEventImpl* lc_evt = args.first->event().extension<lcio::LCEventImpl>();
EVENT::LCCollection* lc_parts = lc_evt->getCollection(lcio::LCIO::MCPARTICLE);
lcio::LCCollectionVec* lc_coll = nullptr;
bool isNewCollection = false;
try {
lc_coll = static_cast<lcio::LCCollectionVec*>(lc_evt->getCollection(hc_nam));
} catch (lcio::DataNotAvailableException &e) {
lc_coll = new lcio::LCCollectionVec(lcio::LCIO::SIMCALORIMETERHIT);
isNewCollection = true;
}
UTIL::CellIDEncoder<SimCalorimeterHit> decoder(dsc,lc_coll);
int hit_creation_mode = sd->hitCreationMode();
if ( hit_creation_mode == Geant4Sensitive::DETAILED_MODE )
Markus Frank
committed
lc_coll->setFlag(UTIL::make_bitset32(LCIO::CHBIT_LONG,LCIO::CHBIT_STEP,LCIO::CHBIT_ID1));
Markus Frank
committed
lc_coll->setFlag(UTIL::make_bitset32(LCIO::CHBIT_LONG,LCIO::CHBIT_ID1));
lc_coll->reserve(nhits + lc_coll->getNumberOfElements());
if ( sd->hasProperty("HitCreationMode") ) {
Markus Frank
committed
hit_creation_mode = sd->property("HitCreationMode").value<int>();
for(size_t i=0; i<nhits; ++i) {
Markus Frank
committed
const Geant4Calorimeter::Hit* hit = coll->hit(i);
float pos[3] = {float(hit->position.x()/CLHEP::mm), float(hit->position.y()/CLHEP::mm), float(hit->position.z()/CLHEP::mm)};
Markus Frank
committed
lcio::SimCalorimeterHitImpl* lc_hit = new lcio::SimCalorimeterHitImpl;
lc_hit->setCellID0((hit->cellID >> 0 ) & 0xFFFFFFFF);
lc_hit->setCellID1((hit->cellID >> sizeof(int)*8) & 0xFFFFFFFF); // ????
Markus Frank
committed
lc_hit->setPosition(pos);
///No! Done when adding particle contributions: lc_hit->setEnergy( hit->energyDeposit );
Markus Frank
committed
lc_coll->addElement(lc_hit);
/// Now add the individual track contributions to the LCIO hit structure
for(Contributions::const_iterator j=hit->truth.begin(); j!=hit->truth.end(); ++j) {
const Geant4HitData::Contribution& c = *j;
int trackID = pm->particleID(c.trackID);
EVENT::MCParticle* lc_mcp = (EVENT::MCParticle*)lc_parts->getElementAt(trackID);
if ( hit_creation_mode == Geant4Sensitive::DETAILED_MODE ) {
float contrib_pos[] = {float(c.x/CLHEP::mm), float(c.y/CLHEP::mm), float(c.z/CLHEP::mm)};
#if LCIO_VERSION_GE( 2, 11 )
lc_hit->addMCParticleContribution(lc_mcp, c.deposit/CLHEP::GeV, c.time/CLHEP::ns, c.length/CLHEP::mm, c.pdgID, contrib_pos);
lc_hit->addMCParticleContribution(lc_mcp, c.deposit/CLHEP::GeV, c.time/CLHEP::ns, c.pdgID, contrib_pos);
lc_hit->addMCParticleContribution(lc_mcp, c.deposit/CLHEP::GeV, c.time/CLHEP::ns);
Markus Frank
committed
}
if(isNewCollection) {
lc_evt->addCollection(lc_coll, hc_nam);
}
Markus Frank
committed
template <typename T>
lcio::LCCollectionVec* moveEntries(Geant4HitCollection* coll,
Markus Frank
committed
lcio::LCCollectionVec* lc_coll)
size_t nhits = coll->GetSize();
lc_coll->reserve(nhits);
for(size_t i=0; i<nhits; ++i) {
Markus Frank
committed
Geant4HitWrapper& wrap = coll->hit(i);
Markus Frank
committed
wrap.release(); // Now we have ownership!
lc_coll->addElement(lc_hit);
}
coll->clear(); // Since the collection now only contains NULL pointers, better clear it!
return lc_coll;
}
/// Data conversion interface moving lcio::SimTrackerHitImpl objects from a Geant4HitCollection to a LCCollectionVec
/**
* This converter is to be used, when the sensitive detectors create fill collections
* of type Geant4HitCollection with objects of type **lcio::SimTrackerHitImpl**.
* The ownership of the original Geant4HitCollection is released and moved to
* the newly created lcio::LCCollectionVec container.
* Finally the original hits collection is cleared.
*
* Note: This conversion is INTRUSIVE and CLEARS the original collection!
*
* @author M.Frank
* @version 1.0
*/
Markus Frank
committed
template <> lcio::LCCollectionVec*
Markus Frank
committed
pair<const Geant4Context*,Geant4HitCollection*>,
lcio::SimTrackerHitImpl>::operator()(const arg_t& args) const
Geant4Sensitive* sd = args.second->sensitive();
string dsc = encoding(sd->sensitiveDetector());
output_t* lc = new lcio::LCCollectionVec(lcio::LCIO::SIMTRACKERHIT);
int hit_creation_mode = sd->hitCreationMode();
if ( hit_creation_mode == Geant4Sensitive::DETAILED_MODE )
Markus Frank
committed
lc->setFlag(UTIL::make_bitset32(LCIO::CHBIT_LONG,LCIO::CHBIT_STEP,LCIO::CHBIT_ID1));
Markus Frank
committed
lc->setFlag(UTIL::make_bitset32(LCIO::CHBIT_LONG,LCIO::CHBIT_ID1));
UTIL::CellIDEncoder<SimTrackerHit> decoder(dsc,lc);
return moveEntries<lcio::SimTrackerHitImpl>(args.second,lc);
}
/// Data conversion interface moving lcio::SimCalorimeterHitImpl objects from a Geant4HitCollection to a LCCollectionVec
/**
* This converter is to be used, when the sensitive detectors create fill collections
* of type Geant4HitCollection with objects of type **lcio::SimCalorimeterHitImpl**.
* The ownership of the original Geant4HitCollection is released and moved to
* the newly created lcio::LCCollectionVec container.
* Finally the original hits collection is cleared.
*
* Note: This conversion is INTRUSIVE and CLEARS the original collection!
*
* @author M.Frank
* @version 1.0
*/
Markus Frank
committed
template <> lcio::LCCollectionVec*
Markus Frank
committed
pair<const Geant4Context*,Geant4HitCollection*>,
lcio::SimCalorimeterHitImpl>::operator()(const arg_t& args) const
Geant4Sensitive* sd = args.second->sensitive();
//string dsc = encoding(args.second->sensitive()->sensitiveDetector());
output_t* lc = new lcio::LCCollectionVec(lcio::LCIO::SIMCALORIMETERHIT);
int hit_creation_mode = sd->hitCreationMode();
if ( hit_creation_mode == Geant4Sensitive::DETAILED_MODE )
Markus Frank
committed
lc->setFlag(UTIL::make_bitset32(LCIO::CHBIT_LONG,LCIO::CHBIT_STEP,LCIO::CHBIT_ID1));
Markus Frank
committed
lc->setFlag(UTIL::make_bitset32(LCIO::CHBIT_LONG,LCIO::CHBIT_ID1));
return moveEntries<tag_t>(args.second,lc);
}
/// Data conversion interface moving lcio::ClusterImpl objects from a Geant4HitCollection to a LCCollectionVec
/** Same comments apply as for the data mover for lcio::SimCalorimeterHitImpl and lcio::SimTrackerHitImpl
*
* @author M.Frank
* @version 1.0
*/
Markus Frank
committed
template <> lcio::LCCollectionVec*
Geant4DataConversion<lcio::LCCollectionVec,
Markus Frank
committed
pair<const Geant4Context*,Geant4HitCollection*>,
lcio::ClusterImpl>::operator()(const arg_t& args) const
{
output_t* lc = new lcio::LCCollectionVec(lcio::LCIO::CLUSTER);
return moveEntries<tag_t>(args.second,lc);
}
typedef pair<const Geant4Context*,G4VHitsCollection*> RAW_CONVERSION_ARGS;
typedef pair<const Geant4Context*,Geant4HitCollection*> CONVERSION_ARGS;
template class Geant4Conversion<lcio::LCCollectionVec,RAW_CONVERSION_ARGS>;
DECLARE_GEANT4_HITCONVERTER(lcio::LCCollectionVec,RAW_CONVERSION_ARGS,Geant4HitCollection)
template class Geant4Conversion<lcio::LCCollectionVec,CONVERSION_ARGS>;
DECLARE_GEANT4_HITCONVERTER(lcio::LCCollectionVec,CONVERSION_ARGS,Geant4Tracker::Hit)
DECLARE_GEANT4_HITCONVERTER(lcio::LCCollectionVec,CONVERSION_ARGS,Geant4Calorimeter::Hit)
DECLARE_GEANT4_HITCONVERTER(lcio::LCCollectionVec,CONVERSION_ARGS,lcio::SimTrackerHitImpl)
DECLARE_GEANT4_HITCONVERTER(lcio::LCCollectionVec,CONVERSION_ARGS,lcio::SimCalorimeterHitImpl)
DECLARE_GEANT4_HITCONVERTER(lcio::LCCollectionVec,CONVERSION_ARGS,lcio::ClusterImpl)
} // End namespace sim
} // End namespace dd4hep