File indexing completed on 2026-10-06 08:15:40
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #include <DDG4/Geant4SensDetAction.inl>
0016 #include <DDG4/Geant4FastSimHandler.h>
0017 #include <DDG4/Geant4EventAction.h>
0018 #include <G4OpticalPhoton.hh>
0019 #include <G4VProcess.hh>
0020
0021
0022
0023 namespace dd4hep {
0024
0025
0026 namespace sim {
0027
0028 namespace {
0029 struct Geant4VoidSensitive {};
0030
0031
0032 template <class HANDLER>
0033 void handleCalorimeterHit (VolumeID cell,
0034 const HitContribution& contrib,
0035 Geant4HitCollection& coll,
0036 const HANDLER& h,
0037 const Geant4Sensitive& sd,
0038 const Segmentation& segmentation)
0039 {
0040 typedef Geant4Calorimeter::Hit Hit;
0041 Hit* hit = coll.findByKey<Hit>(cell);
0042 if( !hit ) {
0043 DDSegmentation::Vector3D pos;
0044 Position global;
0045
0046 if( !sd.useVolumeManager() || !segmentation.isValid() ) {
0047 pos = h.avgPosition();
0048 global = h.localToGlobal(pos);
0049 }
0050 else if( !segmentation.cellsSpanVolumes() ) {
0051
0052
0053 pos = segmentation.position(cell);
0054 global = h.localToGlobal(pos);
0055 }
0056 else {
0057
0058
0059
0060
0061
0062
0063
0064 VolumeID volID = segmentation.volumeID(cell);
0065 VolumeManager vman_glob = VolumeManager::getVolumeManager(sd.detectorDescription());
0066 VolumeManager vman = vman_glob.subdetector(sd.id());
0067 VolumeManagerContext* vc = vman.lookupContext(volID);
0068
0069 pos = segmentation.position(cell);
0070 global = vc->localToWorld(Position(pos)) / dd4hep::mm;
0071 }
0072 hit = new Hit(global);
0073 hit->cellID = cell;
0074 coll.add(cell, hit);
0075 Geant4TouchableHandler handler(h.touchable());
0076 sd.printM2("%s> CREATE hit with deposit:%e MeV Pos:%8.2f %8.2f %8.2f %s [%s]",
0077 sd.c_name(),contrib.deposit,pos.X,pos.Y,pos.Z,handler.path().c_str(),
0078 coll.GetName().c_str());
0079 if ( 0 == hit->cellID ) {
0080 hit->cellID = cell;
0081 sd.except("+++ Invalid CELL ID for hit!");
0082 }
0083 }
0084 hit->truth.emplace_back(contrib);
0085 hit->energyDeposit += contrib.deposit;
0086 }
0087 }
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103 template <> void Geant4SensitiveAction<Geant4VoidSensitive>::defineCollections() {
0104 m_collectionID = -1;
0105 }
0106
0107
0108 template <> bool
0109 Geant4SensitiveAction<Geant4VoidSensitive>::process(const G4Step* ,
0110 G4TouchableHistory* ) {
0111 return true;
0112 }
0113
0114
0115 template <> bool
0116 Geant4SensitiveAction<Geant4VoidSensitive>::processFastSim(const Geant4FastSimSpot* ,
0117 G4TouchableHistory* ) {
0118 return true;
0119 }
0120 typedef Geant4SensitiveAction<Geant4VoidSensitive> Geant4VoidSensitiveAction;
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135 template <> void Geant4SensitiveAction<Geant4Tracker>::defineCollections() {
0136 m_collectionID = declareReadoutFilteredCollection<Geant4Tracker::Hit>();
0137 }
0138
0139
0140 template <> bool
0141 Geant4SensitiveAction<Geant4Tracker>::process(const G4Step* step,G4TouchableHistory* ) {
0142 typedef Geant4Tracker::Hit Hit;
0143
0144
0145 Geant4StepHandler h(step);
0146 auto contrib = Hit::extractContribution(step);
0147 Direction hit_momentum = 0.5 * (h.preMom() + h.postMom());
0148 double hit_deposit = h.deposit();
0149 Hit* hit = new Hit(contrib, hit_momentum, hit_deposit);
0150
0151 hit->cellID = cellID(step);
0152 if ( 0 == hit->cellID ) {
0153 hit->cellID = volumeID(step);
0154 except("+++ Invalid CELL ID for hit!");
0155 }
0156 collection(m_collectionID)->add(hit);
0157 mark(h.track);
0158 print("Hit with deposit:%f Pos:%f %f %f ID=%016X",
0159 hit->energyDeposit,hit->position.X(),hit->position.Y(),hit->position.Z(),(void*)hit->cellID);
0160 Geant4TouchableHandler handler(step);
0161 print(" Geant4 path:%s",handler.path().c_str());
0162 return true;
0163 }
0164
0165
0166 template <> bool
0167 Geant4SensitiveAction<Geant4Tracker>::processFastSim(const Geant4FastSimSpot* spot,
0168 G4TouchableHistory* )
0169 {
0170 typedef Geant4Tracker::Hit Hit;
0171 Geant4FastSimHandler h(spot);
0172 auto contrib = Hit::extractContribution(spot);
0173 Hit* hit = new Hit(contrib, h.momentum(), h.deposit());
0174
0175 hit->cellID = cellID(h.touchable(), h.avgPositionG4());
0176 if ( 0 == hit->cellID ) {
0177 hit->cellID = volumeID(h.touchable());
0178 except("+++ Invalid CELL ID for hit!");
0179 }
0180 collection(m_collectionID)->add(hit);
0181 mark(h.track);
0182 print("Hit with deposit:%f Pos:%f %f %f ID=%016X",
0183 hit->energyDeposit,hit->position.X(),hit->position.Y(),hit->position.Z(),(void*)hit->cellID);
0184 Geant4TouchableHandler handler(h.touchable());
0185 print(" Geant4 path:%s",handler.path().c_str());
0186 return true;
0187 }
0188
0189 typedef Geant4SensitiveAction<Geant4Tracker> Geant4TrackerAction;
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205 struct Geant4OpticalTracker {};
0206
0207
0208 template <> void Geant4SensitiveAction<Geant4OpticalTracker>::defineCollections() {
0209 m_collectionID = declareReadoutFilteredCollection<Geant4Tracker::Hit>();
0210 }
0211
0212
0213 template <> bool
0214 Geant4SensitiveAction<Geant4OpticalTracker>::process(const G4Step* step,G4TouchableHistory* ) {
0215
0216
0217 typedef Geant4Tracker::Hit Hit;
0218 Geant4StepHandler h(step);
0219 auto contrib = Hit::extractContribution(step);
0220 Direction hit_momentum = 0.5 * (h.preMom() + h.postMom());
0221 double hit_deposit = contrib.deposit;
0222 Hit* hit = new Hit(contrib, hit_momentum, hit_deposit);
0223
0224 if (h.trackDef() == G4OpticalPhoton::OpticalPhotonDefinition()) {
0225 step->GetTrack()->SetTrackStatus(fStopAndKill);
0226 }
0227 hit->cellID = cellID(step);
0228 if ( 0 == hit->cellID ) {
0229 hit->cellID = volumeID( step ) ;
0230 except("+++ Invalid CELL ID for hit!");
0231 }
0232 collection(m_collectionID)->add(hit);
0233 mark(h.track);
0234 print("Hit with deposit:%f Pos:%f %f %f ID=%016X",
0235 hit->energyDeposit,hit->position.X(),hit->position.Y(),hit->position.Z(),(void*)hit->cellID);
0236 Geant4TouchableHandler handler(step);
0237 print(" Geant4 path:%s",handler.path().c_str());
0238 return true;
0239 }
0240
0241
0242 template <> bool
0243 Geant4SensitiveAction<Geant4OpticalTracker>::processFastSim(const Geant4FastSimSpot* spot,
0244 G4TouchableHistory* )
0245 {
0246 typedef Geant4Tracker::Hit Hit;
0247 Geant4FastSimHandler h(spot);
0248 auto contrib = Hit::extractContribution(spot);
0249 Hit* hit = new Hit(contrib, h.momentum(), contrib.deposit);
0250
0251 hit->cellID = cellID(h.touchable(), h.avgPositionG4());
0252 if ( 0 == hit->cellID ) {
0253 hit->cellID = volumeID(h.touchable());
0254 except("+++ Invalid CELL ID for hit!");
0255 }
0256 collection(m_collectionID)->add(hit);
0257 mark(h.track);
0258 print("Hit with deposit:%f Pos:%f %f %f ID=%016X",
0259 hit->energyDeposit,hit->position.X(),hit->position.Y(),hit->position.Z(),(void*)hit->cellID);
0260 Geant4TouchableHandler handler(h.touchable());
0261 print(" Geant4 path:%s",handler.path().c_str());
0262 return true;
0263 }
0264 typedef Geant4SensitiveAction<Geant4OpticalTracker> Geant4OpticalTrackerAction;
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277
0278
0279
0280 template <> void Geant4SensitiveAction<Geant4Calorimeter>::defineCollections() {
0281 m_collectionID = declareReadoutFilteredCollection<Geant4Calorimeter::Hit>();
0282 }
0283
0284
0285 template <> bool
0286 Geant4SensitiveAction<Geant4Calorimeter>::process(const G4Step* step,G4TouchableHistory*) {
0287 typedef Geant4Calorimeter::Hit Hit;
0288 Geant4StepHandler h(step);
0289 HitContribution contrib = Hit::extractContribution(step);
0290 Geant4HitCollection* coll = collection(m_collectionID);
0291 VolumeID cell = 0;
0292
0293 try {
0294 cell = cellID(step);
0295 } catch(std::runtime_error &e) {
0296 std::stringstream out;
0297 out << std::setprecision(20) << std::scientific;
0298 out << "ERROR: " << e.what() << std::endl;
0299 out << "Position: "
0300 << "Pre (" << std::setw(24) << step->GetPreStepPoint()->GetPosition() << ") "
0301 << "Post (" << std::setw(24) << step->GetPostStepPoint()->GetPosition() << ") "
0302 << std::endl;
0303 out << "Momentum: "
0304 << " Pre (" <<std::setw(24) << step->GetPreStepPoint() ->GetMomentum() << ") "
0305 << " Post (" <<std::setw(24) << step->GetPostStepPoint()->GetMomentum() << ") "
0306 << std::endl;
0307 std::cout << out.str();
0308 return true;
0309 }
0310
0311 handleCalorimeterHit(cell, contrib, *coll, h, *this, m_segmentation);
0312 mark(h.track);
0313 return true;
0314 }
0315
0316 template <> bool
0317 Geant4SensitiveAction<Geant4Calorimeter>::processFastSim(const Geant4FastSimSpot* spot,
0318 G4TouchableHistory* )
0319 {
0320 typedef Geant4Calorimeter::Hit Hit;
0321 Geant4FastSimHandler h(spot);
0322 HitContribution contrib = Hit::extractContribution(spot);
0323 Geant4HitCollection* coll = collection(m_collectionID);
0324 VolumeID cell = 0;
0325
0326 try {
0327 cell = cellID(h.touchable(), h.avgPositionG4());
0328 } catch(std::runtime_error &e) {
0329 std::stringstream out;
0330 out << std::setprecision(20) << std::scientific;
0331 out << "ERROR: " << e.what() << std::endl;
0332 out << "Position: (" << std::setw(24) << h.avgPositionG4() << ") " << std::endl;
0333 out << "Momentum: (" << std::setw(24) << h.momentumG4() << ") " << std::endl;
0334 std::cout << out.str();
0335 return true;
0336 }
0337 handleCalorimeterHit(cell, contrib, *coll, h, *this, m_segmentation);
0338 mark(h.track);
0339 return true;
0340 }
0341
0342 typedef Geant4SensitiveAction<Geant4Calorimeter> Geant4CalorimeterAction;
0343
0344
0345
0346
0347
0348
0349
0350
0351
0352
0353
0354
0355
0356
0357
0358
0359
0360
0361 struct Geant4OpticalCalorimeter {};
0362
0363
0364 template <> void Geant4SensitiveAction<Geant4OpticalCalorimeter>::defineCollections() {
0365 m_collectionID = declareReadoutFilteredCollection<Geant4Calorimeter::Hit>();
0366 }
0367
0368 template <> bool
0369 Geant4SensitiveAction<Geant4OpticalCalorimeter>::process(const G4Step* step,G4TouchableHistory*) {
0370 G4Track * track = step->GetTrack();
0371
0372 if( track->GetDefinition() != G4OpticalPhoton::OpticalPhotonDefinition() ) {
0373 return false;
0374 }
0375 else if ( track->GetCreatorProcess()->G4VProcess::GetProcessName() != "Cerenkov") {
0376 track->SetTrackStatus(fStopAndKill);
0377 return false;
0378 }
0379 else {
0380 typedef Geant4Calorimeter::Hit Hit;
0381 Geant4StepHandler h(step);
0382 Geant4HitCollection* coll = collection(m_collectionID);
0383 HitContribution contrib = Hit::extractContribution(step);
0384 Position pos = h.prePos();
0385 Hit* hit = coll->find<Hit>(PositionCompare<Hit,Position>(pos));
0386 if ( !hit ) {
0387 hit = new Hit(pos);
0388 hit->cellID = volumeID(step);
0389 coll->add(hit);
0390 if ( 0 == hit->cellID ) {
0391 hit->cellID = volumeID(step);
0392 except("+++ Invalid CELL ID for hit!");
0393 }
0394 }
0395 hit->energyDeposit += contrib.deposit;
0396 hit->truth.emplace_back(contrib);
0397 track->SetTrackStatus(fStopAndKill);
0398 mark(h.track);
0399 return true;
0400 }
0401 }
0402
0403
0404 template <> bool
0405 Geant4SensitiveAction<Geant4OpticalCalorimeter>::processFastSim(const Geant4FastSimSpot* spot,
0406 G4TouchableHistory* )
0407 {
0408 typedef Geant4Calorimeter::Hit Hit;
0409 Geant4FastSimHandler h(spot);
0410 const G4Track* track = h.track;
0411 if( track->GetDefinition() != G4OpticalPhoton::OpticalPhotonDefinition() ) {
0412 return false;
0413 }
0414 else if ( track->GetCreatorProcess()->G4VProcess::GetProcessName() != "Cerenkov") {
0415 return false;
0416 }
0417 else {
0418 Geant4HitCollection* coll = collection(m_collectionID);
0419 HitContribution contrib = Hit::extractContribution(spot);
0420 Position pos = h.avgPosition();
0421 Hit* hit = coll->find<Hit>(PositionCompare<Hit,Position>(pos));
0422 if ( !hit ) {
0423 hit = new Hit(pos);
0424 hit->cellID = volumeID(h.touchable());
0425 coll->add(hit);
0426 if ( 0 == hit->cellID ) {
0427 hit->cellID = volumeID(h.touchable());
0428 except("+++ Invalid CELL ID for hit!");
0429 }
0430 }
0431 hit->energyDeposit += contrib.deposit;
0432 hit->truth.emplace_back(contrib);
0433 mark(h.track);
0434 return true;
0435 }
0436 }
0437 typedef Geant4SensitiveAction<Geant4OpticalCalorimeter> Geant4OpticalCalorimeterAction;
0438
0439
0440
0441
0442
0443
0444
0445
0446
0447
0448
0449
0450
0451
0452
0453
0454
0455
0456
0457 struct Geant4ScintillatorCalorimeter {};
0458
0459
0460 template <> void Geant4SensitiveAction<Geant4ScintillatorCalorimeter>::defineCollections() {
0461 m_collectionID = declareReadoutFilteredCollection<Geant4Calorimeter::Hit>();
0462 }
0463
0464 template <> bool
0465 Geant4SensitiveAction<Geant4ScintillatorCalorimeter>::process(const G4Step* step,G4TouchableHistory*) {
0466 typedef Geant4Calorimeter::Hit Hit;
0467 Geant4StepHandler h(step);
0468 HitContribution contrib = Hit::extractContribution(step,true);
0469 Geant4HitCollection* coll = collection(m_collectionID);
0470 VolumeID cell = 0;
0471 try {
0472 cell = cellID(step);
0473 } catch(std::runtime_error &e) {
0474 std::stringstream out;
0475 out << std::setprecision(20) << std::scientific;
0476 out << "ERROR: " << e.what() << std::endl;
0477 out << "Position: "
0478 << "Pre (" << std::setw(24) << step->GetPreStepPoint()->GetPosition() << ") "
0479 << "Post (" << std::setw(24) << step->GetPostStepPoint()->GetPosition() << ") "
0480 << std::endl;
0481 out << "Momentum: "
0482 << " Pre (" <<std::setw(24) << step->GetPreStepPoint() ->GetMomentum() << ") "
0483 << " Post (" <<std::setw(24) << step->GetPostStepPoint()->GetMomentum() << ") "
0484 << std::endl;
0485 std::cout << out.str();
0486 return true;
0487 }
0488 handleCalorimeterHit(cell, contrib, *coll, h, *this, m_segmentation);
0489 mark(h.track);
0490 return true;
0491 }
0492
0493
0494 template <> bool
0495 Geant4SensitiveAction<Geant4ScintillatorCalorimeter>::processFastSim(const Geant4FastSimSpot* spot,
0496 G4TouchableHistory* )
0497 {
0498 typedef Geant4Calorimeter::Hit Hit;
0499 Geant4FastSimHandler h(spot);
0500 HitContribution contrib = Hit::extractContribution(spot);
0501 Geant4HitCollection* coll = collection(m_collectionID);
0502 VolumeID cell = 0;
0503
0504 try {
0505 cell = cellID(h.touchable(), h.avgPositionG4());
0506 } catch(std::runtime_error &e) {
0507 std::stringstream out;
0508 out << std::setprecision(20) << std::scientific;
0509 out << "ERROR: " << e.what() << std::endl;
0510 out << "Position: (" << std::setw(24) << h.avgPositionG4() << ") " << std::endl;
0511 out << "Momentum: (" << std::setw(24) << h.momentumG4() << ") " << std::endl;
0512 std::cout << out.str();
0513 return true;
0514 }
0515 handleCalorimeterHit(cell, contrib, *coll, h, *this, m_segmentation);
0516 mark(h.track);
0517 return true;
0518 }
0519
0520 typedef Geant4SensitiveAction<Geant4ScintillatorCalorimeter> Geant4ScintillatorCalorimeterAction;
0521
0522
0523
0524
0525
0526
0527
0528
0529
0530
0531
0532
0533
0534
0535
0536
0537
0538
0539
0540
0541
0542
0543
0544 struct TrackerCombine {
0545 Geant4Tracker::Hit pre, post;
0546 Position mean_pos;
0547 Geant4Sensitive* sensitive { nullptr };
0548 G4VPhysicalVolume* firstSpotVolume { nullptr };
0549 double mean_time { 0e0 };
0550 double e_cut { 0e0 };
0551 int current { -1 };
0552 int combined { 0 };
0553 long long int cell { 0 };
0554
0555 TrackerCombine() : pre(), post() {
0556 }
0557
0558
0559 void start_collecting(const G4Track* track) {
0560 pre.truth.deposit = 0.0;
0561 current = pre.truth.trackID;
0562 sensitive->mark(track);
0563 mean_pos.SetXYZ(0,0,0);
0564 mean_time = 0;
0565 post.copyFrom(pre);
0566 combined = 0;
0567 cell = 0;
0568 }
0569 void start(const G4Step* step, const G4StepPoint* point) {
0570 pre.storePoint(step,point);
0571 start_collecting(step->GetTrack());
0572 firstSpotVolume = step->GetPreStepPoint()->GetTouchableHandle()->GetVolume();
0573 }
0574 void start(const Geant4FastSimSpot* spot) {
0575 pre.storePoint(spot);
0576 start_collecting(spot->primary);
0577 firstSpotVolume = spot->volume();
0578 }
0579
0580
0581 void update_collected_hit(const G4VTouchable* h, G4ThreeVector&& global) {
0582 pre.truth.deposit += post.truth.deposit;
0583 mean_pos.SetX(mean_pos.x()+post.position.x()*post.truth.deposit);
0584 mean_pos.SetY(mean_pos.y()+post.position.y()*post.truth.deposit);
0585 mean_pos.SetZ(mean_pos.z()+post.position.z()*post.truth.deposit);
0586 mean_time += post.truth.time*post.truth.deposit;
0587 if ( 0 == cell ) {
0588 cell = sensitive->cellID(h, global);
0589 if ( 0 == cell ) {
0590 cell = sensitive->volumeID(h) ;
0591 sensitive->except("+++ Invalid CELL ID for hit!");
0592 }
0593 }
0594 ++combined;
0595 }
0596 void update(const Geant4StepHandler& h) {
0597 post.storePoint(h.step, h.post);
0598 update_collected_hit(h.preTouchable(), h.avgPositionG4());
0599 }
0600 void update(const Geant4FastSimHandler& h) {
0601 post.storePoint(h.spot);
0602 update_collected_hit(h.touchable(), h.avgPositionG4());
0603 }
0604
0605
0606 void clear() {
0607 mean_pos.SetXYZ(0,0,0);
0608 mean_time = 0;
0609 post.clear();
0610 pre.clear();
0611 current = -1;
0612 combined = 0;
0613 cell = 0;
0614 firstSpotVolume = nullptr;
0615 }
0616
0617
0618 bool mustSaveTrack(const G4Track* tr) const {
0619 return current > 0 && current != tr->GetTrackID();
0620 }
0621
0622
0623 void extractHit(Geant4HitCollection* collection) {
0624 if ( current == -1 ) {
0625 return;
0626 }
0627 double depo = pre.truth.deposit;
0628 double time = depo != 0 ? mean_time / depo : mean_time;
0629 Position pos = depo != 0 ? mean_pos / depo : mean_pos;
0630 Momentum mom = 0.5 * (pre.momentum + post.momentum);
0631 double path_len = (post.position - pre.position).R();
0632 Geant4Tracker::Hit* hit = new Geant4Tracker::Hit(pre.truth.trackID, pre.truth.pdgID,
0633 depo, time, path_len, pos, mom);
0634 hit->cellID = cell;
0635 collection->add(hit);
0636 sensitive->printM2("+++ TrackID:%6d [%s] CREATE hit combination with %2d deposit(s):"
0637 " %e MeV Pos:%8.2f %8.2f %8.2f",
0638 pre.truth.trackID,sensitive->c_name(),combined,pre.truth.deposit/CLHEP::MeV,
0639 pos.X()/CLHEP::mm,pos.Y()/CLHEP::mm,pos.Z()/CLHEP::mm);
0640 clear();
0641 }
0642
0643
0644
0645 G4bool process(const G4Step* step, G4TouchableHistory* ) {
0646 Geant4StepHandler h(step);
0647
0648
0649 void *prePV = h.volume(h.pre), *postPV = h.volume(h.post);
0650
0651 Geant4HitCollection* coll = sensitive->collection(0);
0652
0653 if ( mustSaveTrack(h.track) ) {
0654 extractHit(coll);
0655 }
0656
0657 if ( current < 0 ) {
0658 start(step, h.pre);
0659 }
0660
0661 update(h);
0662
0663 if ( prePV != postPV ) {
0664 void* postSD = h.sd(h.post);
0665 extractHit(coll);
0666 if ( 0 != postSD ) {
0667 void* preSD = h.sd(h.pre);
0668 if ( preSD == postSD ) {
0669 start(step,h.post);
0670 }
0671 }
0672 }
0673 else if ( h.track->GetTrackStatus() == fStopAndKill ) {
0674 extractHit(coll);
0675 }
0676 return true;
0677 }
0678
0679
0680 G4bool process(const Geant4FastSimSpot* spot, G4TouchableHistory* ) {
0681 Geant4FastSimHandler h(spot);
0682 G4VPhysicalVolume* prePV = firstSpotVolume, *postPV = h.volume();
0683 Geant4HitCollection* coll = sensitive->collection(0);
0684
0685 if ( mustSaveTrack(h.track) ) {
0686 extractHit(coll);
0687 }
0688
0689 if ( current < 0 ) {
0690 start(spot);
0691 }
0692
0693 update(h);
0694
0695 if ( firstSpotVolume && prePV != postPV ) {
0696 void* postSD = h.sd();
0697 extractHit(coll);
0698 if ( 0 != postSD ) {
0699 void* preSD = prePV ? prePV->GetLogicalVolume()->GetSensitiveDetector() : nullptr;
0700 if ( preSD == postSD ) {
0701 start(spot);
0702 }
0703 }
0704 }
0705 else if ( h.track->GetTrackStatus() == fStopAndKill ) {
0706 extractHit(coll);
0707 }
0708 return true;
0709 }
0710
0711
0712 void endEvent(const G4Event* ) {
0713
0714
0715
0716
0717
0718
0719 if ( current > 0 ) {
0720 Geant4HitCollection* coll = sensitive->collection(0);
0721 extractHit(coll);
0722 }
0723 }
0724 };
0725
0726
0727 template <> void Geant4SensitiveAction<TrackerCombine>::initialize() {
0728 eventAction().callAtEnd(&m_userData,&TrackerCombine::endEvent);
0729 m_userData.e_cut = m_sensitive.energyCutoff();
0730 m_userData.sensitive = this;
0731 }
0732
0733
0734 template <> void Geant4SensitiveAction<TrackerCombine>::defineCollections() {
0735 m_collectionID = declareReadoutFilteredCollection<Geant4Tracker::Hit>();
0736 }
0737
0738
0739 template <> void Geant4SensitiveAction<TrackerCombine>::clear(G4HCofThisEvent*) {
0740 m_userData.clear();
0741 }
0742
0743
0744 template <> G4bool
0745 Geant4SensitiveAction<TrackerCombine>::process(const G4Step* step, G4TouchableHistory* history) {
0746 return m_userData.process(step, history);
0747 }
0748
0749
0750 template <> bool
0751 Geant4SensitiveAction<TrackerCombine>::processFastSim(const Geant4FastSimSpot* spot,
0752 G4TouchableHistory* history) {
0753 return m_userData.process(spot, history);
0754 }
0755
0756 typedef Geant4SensitiveAction<TrackerCombine> Geant4TrackerCombineAction;
0757 typedef Geant4TrackerAction Geant4SimpleTrackerAction;
0758 typedef Geant4CalorimeterAction Geant4SimpleCalorimeterAction;
0759 typedef Geant4OpticalCalorimeterAction Geant4SimpleOpticalCalorimeterAction;
0760 }
0761 }
0762
0763 using namespace dd4hep::sim;
0764
0765 #include <DDG4/Factories.h>
0766
0767 DECLARE_GEANT4SENSITIVE(Geant4VoidSensitiveAction)
0768
0769 DECLARE_GEANT4SENSITIVE(Geant4TrackerAction)
0770 DECLARE_GEANT4SENSITIVE(Geant4OpticalTrackerAction)
0771 DECLARE_GEANT4SENSITIVE(Geant4TrackerCombineAction)
0772 DECLARE_GEANT4SENSITIVE(Geant4CalorimeterAction)
0773 DECLARE_GEANT4SENSITIVE(Geant4OpticalCalorimeterAction)
0774 DECLARE_GEANT4SENSITIVE(Geant4ScintillatorCalorimeterAction)
0775
0776
0777 DECLARE_GEANT4SENSITIVE(Geant4SimpleTrackerAction)
0778 DECLARE_GEANT4SENSITIVE(Geant4SimpleCalorimeterAction)
0779 DECLARE_GEANT4SENSITIVE(Geant4SimpleOpticalCalorimeterAction)