File indexing completed on 2025-01-18 09:14:28
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #include <DD4hep/Printout.h>
0016 #include <DD4hep/Primitives.h>
0017 #include <DD4hep/InstanceCount.h>
0018
0019 #include <DDG4/Geant4Kernel.h>
0020 #include <DDG4/Geant4Mapping.h>
0021 #include <DDG4/Geant4StepHandler.h>
0022 #include <DDG4/Geant4SensDetAction.h>
0023 #include <DDG4/Geant4VolumeManager.h>
0024 #include <DDG4/Geant4MonteCarloTruth.h>
0025
0026
0027 #include <G4Step.hh>
0028 #include <G4SDManager.hh>
0029 #include <G4VSensitiveDetector.hh>
0030
0031
0032 #include <stdexcept>
0033
0034 #ifdef DD4HEP_USE_GEANT4_UNITS
0035 #define MM_2_CM 1.0
0036 #else
0037 #define MM_2_CM 0.1
0038 #endif
0039
0040 using namespace dd4hep::sim;
0041
0042 #if 0
0043 namespace {
0044 Geant4ActionSD* _getSensitiveDetector(const std::string& name) {
0045 G4SDManager* mgr = G4SDManager::GetSDMpointer();
0046 G4VSensitiveDetector* sd = mgr->FindSensitiveDetector(name);
0047 if (0 == sd) {
0048 dd4hep::except("Geant4Sensitive", "DDG4: You requested to configure actions "
0049 "for the sensitive detector %s,\nDDG4: which is not known to Geant4. "
0050 "Are you sure you already converted the geometry?", name.c_str());
0051 }
0052 Geant4ActionSD* action_sd = dynamic_cast<Geant4ActionSD*>(sd);
0053 if (0 == action_sd) {
0054 throw dd4hep::except("Geant4Sensitive", "DDG4: You may only configure actions "
0055 "for sensitive detectors of type Geant4ActionSD.\n"
0056 "DDG4: The sensitive detector of %s is of type %s, which is incompatible.", name.c_str(),
0057 typeName(typeid(*sd)).c_str());
0058 }
0059 return action_sd;
0060 }
0061 }
0062 #endif
0063
0064
0065 Geant4ActionSD::Geant4ActionSD(const std::string& nam)
0066 : Geant4Action(0, nam) {
0067 InstanceCount::increment(this);
0068 }
0069
0070
0071 Geant4ActionSD::~Geant4ActionSD() {
0072 InstanceCount::decrement(this);
0073 }
0074
0075
0076 Geant4Filter::Geant4Filter(Geant4Context* ctxt, const std::string& nam)
0077 : Geant4Action(ctxt, nam) {
0078 InstanceCount::increment(this);
0079 }
0080
0081
0082 Geant4Filter::~Geant4Filter() {
0083 InstanceCount::decrement(this);
0084 }
0085
0086
0087 bool Geant4Filter::operator()(const G4Step*) const {
0088 return true;
0089 }
0090
0091
0092 bool Geant4Filter::operator()(const Geant4FastSimSpot*) const {
0093 except("The filter action %s does not support the GFLASH/FastSim interface for Geant4.", c_name());
0094 return false;
0095 }
0096
0097
0098 Geant4Sensitive::Geant4Sensitive(Geant4Context* ctxt, const std::string& nam, DetElement det, Detector& det_ref)
0099 : Geant4Action(ctxt, nam), m_detDesc(det_ref), m_detector(det)
0100 {
0101 InstanceCount::increment(this);
0102 if (!det.isValid()) {
0103 except("DDG4: Detector elemnt for %s is invalid.", nam.c_str());
0104 }
0105 declareProperty("HitCreationMode", m_hitCreationMode = SIMPLE_MODE);
0106 m_sequence = context()->kernel().sensitiveAction(m_detector.name());
0107 m_sensitive = m_detDesc.sensitiveDetector(det.name());
0108 m_readout = m_sensitive.readout();
0109 m_segmentation = m_readout.segmentation();
0110 }
0111
0112
0113 Geant4Sensitive::~Geant4Sensitive() {
0114 m_filters(&Geant4Filter::release);
0115 m_filters.clear();
0116 InstanceCount::decrement(this);
0117 }
0118
0119
0120 void Geant4Sensitive::adoptFilter(Geant4Action* action) {
0121 Geant4Filter* filter = dynamic_cast<Geant4Filter*>(action);
0122 adopt(filter);
0123 }
0124
0125
0126 void Geant4Sensitive::adopt(Geant4Filter* filter) {
0127 if (filter) {
0128 filter->addRef();
0129 m_filters.add(filter);
0130 return;
0131 }
0132 except("Attempt to add invalid sensitive filter!");
0133 }
0134
0135
0136 void Geant4Sensitive::adoptFilter_front(Geant4Action* action) {
0137 Geant4Filter* filter = dynamic_cast<Geant4Filter*>(action);
0138 adopt_front(filter);
0139 }
0140
0141
0142 void Geant4Sensitive::adopt_front(Geant4Filter* filter) {
0143 if (filter) {
0144 filter->addRef();
0145 m_filters.add_front(filter);
0146 return;
0147 }
0148 except("Attempt to add invalid sensitive filter!");
0149 }
0150
0151
0152 bool Geant4Sensitive::accept(const G4Step* step) const {
0153 bool (Geant4Filter::*filter)(const G4Step*) const = &Geant4Filter::operator();
0154 bool result = m_filters.filter(filter, step);
0155 return result;
0156 }
0157
0158
0159 bool Geant4Sensitive::accept(const Geant4FastSimSpot* spot) const {
0160 bool (Geant4Filter::*filter)(const Geant4FastSimSpot*) const = &Geant4Filter::operator();
0161 bool result = m_filters.filter(filter, spot);
0162 return result;
0163 }
0164
0165
0166 void Geant4Sensitive::setDetector(Geant4ActionSD* sens_det) {
0167 m_sensitiveDetector = sens_det;
0168 }
0169
0170
0171 Geant4ActionSD& Geant4Sensitive::detector() const {
0172 if (m_sensitiveDetector)
0173 return *m_sensitiveDetector;
0174
0175
0176 except("DDG4: The sensitive detector for action %s was not properly configured.", name().c_str());
0177 throw std::runtime_error("Geant4Sensitive::detector");
0178 }
0179
0180
0181 Geant4SensDetActionSequence& Geant4Sensitive::sequence() const {
0182 return *m_sequence;
0183 }
0184
0185
0186 dd4hep::Detector& Geant4Sensitive::detectorDescription() const {
0187 return m_detDesc;
0188 }
0189
0190
0191 const std::string& Geant4Sensitive::hitCollectionName(std::size_t which) const {
0192 return sequence().hitCollectionName(which);
0193 }
0194
0195
0196 Geant4HitCollection* Geant4Sensitive::collection(std::size_t which) {
0197 return sequence().collection(which);
0198 }
0199
0200
0201 Geant4HitCollection* Geant4Sensitive::collectionByID(std::size_t id) {
0202 return sequence().collectionByID(id);
0203 }
0204
0205
0206 void Geant4Sensitive::defineCollections() {
0207 }
0208
0209
0210 void Geant4Sensitive::begin(G4HCofThisEvent* ) {
0211 }
0212
0213
0214 void Geant4Sensitive::end(G4HCofThisEvent* ) {
0215 }
0216
0217
0218 bool Geant4Sensitive::process(const G4Step* , G4TouchableHistory* ) {
0219 return false;
0220 }
0221
0222
0223 bool Geant4Sensitive::processFastSim(const Geant4FastSimSpot* , G4TouchableHistory* ) {
0224 except("The sensitive action %s does not support the GFLASH/FastSim interface for Geant4.", c_name());
0225 return false;
0226 }
0227
0228
0229 void Geant4Sensitive::clear(G4HCofThisEvent* ) {
0230 }
0231
0232
0233 void Geant4Sensitive::mark(const G4Track* track) const {
0234 Geant4MonteCarloTruth* truth = context()->event().extension<Geant4MonteCarloTruth>(false);
0235 if ( truth ) truth->mark(track);
0236 }
0237
0238
0239 void Geant4Sensitive::mark(const G4Step* step) const {
0240 Geant4MonteCarloTruth* truth = context()->event().extension<Geant4MonteCarloTruth>(false);
0241 if ( truth ) truth->mark(step);
0242 }
0243
0244
0245 long long int Geant4Sensitive::volumeID(const G4Step* step) {
0246 Geant4StepHandler stepH(step);
0247 Geant4VolumeManager volMgr = Geant4Mapping::instance().volumeManager();
0248 VolumeID id = volMgr.volumeID(stepH.preTouchable());
0249 return id;
0250 }
0251
0252
0253 long long int Geant4Sensitive::volumeID(const G4VTouchable* touchable) {
0254 Geant4VolumeManager volMgr = Geant4Mapping::instance().volumeManager();
0255 VolumeID id = volMgr.volumeID(touchable);
0256 return id;
0257 }
0258
0259
0260 long long int Geant4Sensitive::cellID(const G4Step* step) {
0261 Geant4StepHandler h(step);
0262 Geant4VolumeManager volMgr = Geant4Mapping::instance().volumeManager();
0263 VolumeID volID = volMgr.volumeID(h.preTouchable());
0264 if ( m_segmentation.isValid() ) {
0265 std::exception_ptr eptr;
0266 G4ThreeVector global = 0.5 * (h.prePosG4()+h.postPosG4());
0267 G4ThreeVector local = h.preTouchable()->GetHistory()->GetTopTransform().TransformPoint(global);
0268 Position loc(local.x()*MM_2_CM, local.y()*MM_2_CM, local.z()*MM_2_CM);
0269 Position glob(global.x()*MM_2_CM, global.y()*MM_2_CM, global.z()*MM_2_CM);
0270 try {
0271 VolumeID cID = m_segmentation.cellID(loc, glob, volID);
0272 return cID;
0273 }
0274 catch(const std::exception& e) {
0275 eptr = std::current_exception();
0276 error("cellID: failed to access segmentation for VolumeID: %016lX [%ld] [%s]", volID, volID, e.what());
0277 error("....... G4-local: (%f, %f, %f) G4-global: (%f, %f, %f)",
0278 local.x(), local.y(), local.z(), global.x(), global.y(), global.z());
0279 error("....... TGeo-local: (%f, %f, %f) TGeo-global: (%f, %f, %f)",
0280 loc.x(), loc.y(), loc.z(), glob.x(), glob.y(), glob.z());
0281 error("....... Pre-step: %s SD: %s", h.volName(h.pre), h.sdName(h.pre).c_str());
0282 if ( h.post )
0283 error("....... Post-step: %s SD: %s", h.volName(h.post), h.sdName(h.post).c_str());
0284 std::rethrow_exception(std::move(eptr));
0285 }
0286 }
0287 return volID;
0288 }
0289
0290
0291 long long int Geant4Sensitive::cellID(const G4VTouchable* touchable, const G4ThreeVector& global) {
0292 Geant4VolumeManager volMgr = Geant4Mapping::instance().volumeManager();
0293 VolumeID volID = volMgr.volumeID(touchable);
0294 if ( m_segmentation.isValid() ) {
0295 std::exception_ptr eptr;
0296 G4ThreeVector local = touchable->GetHistory()->GetTopTransform().TransformPoint(global);
0297 Position loc (local.x()*MM_2_CM, local.y()*MM_2_CM, local.z()*MM_2_CM);
0298 Position glob(global.x()*MM_2_CM, global.y()*MM_2_CM, global.z()*MM_2_CM);
0299 try {
0300 VolumeID cID = m_segmentation.cellID(loc, glob, volID);
0301 return cID;
0302 }
0303 catch(const std::exception& e) {
0304 auto* pvol = touchable->GetVolume();
0305 auto* vol = pvol->GetLogicalVolume();
0306 auto* sd = vol->GetSensitiveDetector();
0307 eptr = std::current_exception();
0308 error("cellID: failed to access segmentation for VolumeID: %016lX [%ld] [%s]", volID, volID, e.what());
0309 error("....... G4-local: (%f, %f, %f) G4-global: (%f, %f, %f)",
0310 local.x(), local.y(), local.z(), global.x(), global.y(), global.z());
0311 error("....... TGeo-local: (%f, %f, %f) TGeo-global: (%f, %f, %f)",
0312 loc.x(), loc.y(), loc.z(), glob.x(), glob.y(), glob.z());
0313 error("....... Touchable: %s SD: %s", vol->GetName().c_str(), sd ? sd->GetName().c_str() : "???");
0314 std::rethrow_exception(std::move(eptr));
0315 }
0316 }
0317 return volID;
0318 }
0319
0320
0321 Geant4SensDetActionSequence::Geant4SensDetActionSequence(Geant4Context* ctxt, const std::string& nam)
0322 : Geant4Action(ctxt, nam), m_hce(0), m_detector(0)
0323 {
0324 m_needsControl = true;
0325 context()->sensitiveActions().insert(name(), this);
0326
0327 m_sensitive = context()->detectorDescription().sensitiveDetector(nam);
0328 m_sensitiveType = m_sensitive.type();
0329 InstanceCount::increment(this);
0330 }
0331
0332
0333 Geant4SensDetActionSequence::~Geant4SensDetActionSequence() {
0334 m_filters(&Geant4Filter::release);
0335 m_actors(&Geant4Sensitive::release);
0336 m_filters.clear();
0337 m_actors.clear();
0338 InstanceCount::decrement(this);
0339 }
0340
0341
0342 void Geant4SensDetActionSequence::updateContext(Geant4Context* ctxt) {
0343 m_context = ctxt;
0344 m_actors.updateContext(ctxt);
0345 m_filters.updateContext(ctxt);
0346 }
0347
0348
0349 void Geant4SensDetActionSequence::adoptFilter(Geant4Action* action) {
0350 Geant4Filter* filter = dynamic_cast<Geant4Filter*>(action);
0351 adopt(filter);
0352 }
0353
0354
0355 void Geant4SensDetActionSequence::adopt(Geant4Sensitive* sensitive) {
0356 if (sensitive) {
0357 sensitive->addRef();
0358 m_actors.add(sensitive);
0359 return;
0360 }
0361 except("Attempt to add invalid sensitive actor!");
0362 }
0363
0364
0365 void Geant4SensDetActionSequence::adopt(Geant4Filter* filter) {
0366 if (filter) {
0367 filter->addRef();
0368 m_filters.add(filter);
0369 return;
0370 }
0371 except("Attempt to add invalid sensitive filter!");
0372 }
0373
0374
0375 std::size_t Geant4SensDetActionSequence::defineCollection(Geant4Sensitive* owner, const std::string& collection_name, create_t func) {
0376 m_collections.emplace_back(collection_name, make_pair(owner,func));
0377 return m_collections.size() - 1;
0378 }
0379
0380
0381 std::size_t Geant4SensDetActionSequence::Geant4SensDetActionSequence::defineCollections(Geant4ActionSD* sens_det) {
0382 std::size_t count = 0;
0383 m_detector = sens_det;
0384 m_actors(&Geant4Sensitive::setDetector, sens_det);
0385 m_actors(&Geant4Sensitive::defineCollections);
0386 for (HitCollections::const_iterator i = m_collections.begin(); i != m_collections.end(); ++i) {
0387 sens_det->defineCollection((*i).first);
0388 ++count;
0389 }
0390 return count;
0391 }
0392
0393
0394 const std::string& Geant4SensDetActionSequence::hitCollectionName(std::size_t which) const {
0395 if (which < m_collections.size()) {
0396 return m_collections[which].first;
0397 }
0398 static std::string blank = "";
0399 except("The collection name index for subdetector %s is out of range!", c_name());
0400 return blank;
0401 }
0402
0403
0404 Geant4HitCollection* Geant4SensDetActionSequence::collection(std::size_t which) const {
0405 if (which < m_collections.size()) {
0406 int hc_id = m_detector->GetCollectionID(which);
0407 Geant4HitCollection* c = (Geant4HitCollection*) m_hce->GetHC(hc_id);
0408 if (c)
0409 return c;
0410 except("The collection index for subdetector %s is wrong!", c_name());
0411 }
0412 except("The collection name index for subdetector %s is out of range!", c_name());
0413 return 0;
0414 }
0415
0416
0417 Geant4HitCollection* Geant4SensDetActionSequence::collectionByID(std::size_t id) const {
0418 Geant4HitCollection* c = (Geant4HitCollection*) m_hce->GetHC(id);
0419 if (c)
0420 return c;
0421 except("The collection index for subdetector %s is wrong!", c_name());
0422 return 0;
0423 }
0424
0425
0426 bool Geant4SensDetActionSequence::accept(const G4Step* step) const {
0427 bool (Geant4Filter::*filter)(const G4Step*) const = &Geant4Filter::operator();
0428 bool result = m_filters.filter(filter, step);
0429 return result;
0430 }
0431
0432
0433 bool Geant4SensDetActionSequence::accept(const Geant4FastSimSpot* spot) const {
0434 bool (Geant4Filter::*filter)(const Geant4FastSimSpot*) const = &Geant4Filter::operator();
0435 bool result = m_filters.filter(filter, spot);
0436 return result;
0437 }
0438
0439
0440 bool Geant4SensDetActionSequence::process(const G4Step* step, G4TouchableHistory* history) {
0441 bool result = false;
0442 for (Geant4Sensitive* sensitive : m_actors) {
0443 if ( sensitive->accept(step) )
0444 result |= sensitive->process(step, history);
0445 }
0446 m_process(step, history);
0447 return result;
0448 }
0449
0450
0451 bool Geant4SensDetActionSequence::processFastSim(const Geant4FastSimSpot* spot, G4TouchableHistory* history) {
0452 bool result = false;
0453 for (Geant4Sensitive* sensitive : m_actors) {
0454 if ( sensitive->accept(spot) )
0455 result |= sensitive->processFastSim(spot, history);
0456 }
0457 m_process(spot, history);
0458 return result;
0459 }
0460
0461
0462
0463
0464
0465 void Geant4SensDetActionSequence::begin(G4HCofThisEvent* hce) {
0466 m_hce = hce;
0467 for (std::size_t count = 0; count < m_collections.size(); ++count) {
0468 const HitCollection& cr = m_collections[count];
0469 Geant4HitCollection* col = (*cr.second.second)(name(), cr.first, cr.second.first);
0470 int id = m_detector->GetCollectionID(count);
0471 m_hce->AddHitsCollection(id, col);
0472 }
0473 m_actors(&Geant4Sensitive::begin, m_hce);
0474 m_begin (m_hce);
0475 }
0476
0477
0478 void Geant4SensDetActionSequence::end(G4HCofThisEvent* hce) {
0479 m_end(hce);
0480 m_actors(&Geant4Sensitive::end, hce);
0481
0482 }
0483
0484
0485
0486
0487
0488
0489
0490 void Geant4SensDetActionSequence::clear() {
0491 m_clear (m_hce);
0492 m_actors(&Geant4Sensitive::clear, m_hce);
0493 }
0494
0495
0496 Geant4SensDetSequences::~Geant4SensDetSequences() {
0497 detail::releaseObjects(m_sequences);
0498 m_sequences.clear();
0499 }
0500
0501
0502 Geant4SensDetActionSequence* Geant4SensDetSequences::operator[](const std::string& nam) const {
0503 std::string n = "SD_Seq_" + nam;
0504 Members::const_iterator i = m_sequences.find(n);
0505 if (i != m_sequences.end())
0506 return (*i).second;
0507 except("Attempt to access undefined SensDetActionSequence: %s ", nam.c_str());
0508 return nullptr;
0509 }
0510
0511
0512 Geant4SensDetActionSequence* Geant4SensDetSequences::find(const std::string& name) const {
0513 std::string nam = "SD_Seq_" + name;
0514 Members::const_iterator i = m_sequences.find(nam);
0515 if (i != m_sequences.end())
0516 return (*i).second;
0517 return 0;
0518 }
0519
0520
0521 void Geant4SensDetSequences::insert(const std::string& name, Geant4SensDetActionSequence* seq) {
0522 if (seq) {
0523 std::string nam = "SD_Seq_" + name;
0524 seq->addRef();
0525 m_sequences[nam] = seq;
0526 return;
0527 }
0528 except("Attempt to add invalid sensitive sequence with name:%s", name.c_str());
0529 }
0530
0531
0532 void Geant4SensDetSequences::clear() {
0533 m_sequences.clear();
0534 }