Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-05-10 02:21:14

0001 //#define EDM_ML_DEBUG
0002 //#define HcalNumberingTest
0003 
0004 // to make hits in EB/EE/HC
0005 
0006 #include "DataFormats/Common/interface/Handle.h"
0007 #include "DataFormats/HcalDetId/interface/HcalDetId.h"
0008 #include "DataFormats/Math/interface/Point3D.h"
0009 
0010 #include "FWCore/Framework/interface/Event.h"
0011 #include "FWCore/Framework/interface/EventSetup.h"
0012 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0013 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0014 #include "FWCore/Utilities/interface/isFinite.h"
0015 #include "FWCore/Utilities/interface/Exception.h"
0016 
0017 #include "Geometry/EcalCommonData/interface/EcalBarrelNumberingScheme.h"
0018 #include "Geometry/EcalCommonData/interface/EcalBaseNumber.h"
0019 #include "Geometry/EcalCommonData/interface/EcalEndcapNumberingScheme.h"
0020 #ifdef HcalNumberingTest
0021 #include "Geometry/HcalCommonData/interface/HcalNumberingFromDDD.h"
0022 #include "Geometry/HcalCommonData/interface/HcalDDDSimConstants.h"
0023 #include "Geometry/Records/interface/HcalSimNumberingRecord.h"
0024 #endif
0025 
0026 #include "SimDataFormats/CaloHit/interface/PCaloHit.h"
0027 #include "SimDataFormats/CaloHit/interface/PCaloHitContainer.h"
0028 #include "SimDataFormats/CaloHit/interface/PassiveHit.h"
0029 #include "SimDataFormats/SimHitMaker/interface/CaloSlaveSD.h"
0030 
0031 #include "SimG4CMS/Calo/interface/CaloGVHit.h"
0032 #include "SimG4CMS/Calo/interface/HcalNumberingScheme.h"
0033 #include "SimG4CMS/Calo/interface/HcalNumberingFromPS.h"
0034 
0035 #include "SimG4Core/Notification/interface/G4TrackToParticleID.h"
0036 #include "SimG4Core/Notification/interface/Observer.h"
0037 #include "SimG4Core/Notification/interface/BeginOfRun.h"
0038 #include "SimG4Core/Notification/interface/BeginOfEvent.h"
0039 #include "SimG4Core/Notification/interface/EndOfEvent.h"
0040 #include "SimG4Core/Watcher/interface/SimProducer.h"
0041 #include "SimG4Core/Watcher/interface/SimWatcherFactory.h"
0042 
0043 #include "G4LogicalVolume.hh"
0044 #include "G4LogicalVolumeStore.hh"
0045 #include "G4NavigationHistory.hh"
0046 #include "G4ParticleTable.hh"
0047 #include "G4PhysicalVolumeStore.hh"
0048 #include "G4Region.hh"
0049 #include "G4RegionStore.hh"
0050 #include "G4Step.hh"
0051 #include "G4Track.hh"
0052 #include "G4Trap.hh"
0053 #include "G4UnitsTable.hh"
0054 #include "G4UserSteppingAction.hh"
0055 #include "G4VPhysicalVolume.hh"
0056 #include "G4VTouchable.hh"
0057 
0058 #include <CLHEP/Units/SystemOfUnits.h>
0059 
0060 #include <algorithm>
0061 #include <cmath>
0062 #include <iostream>
0063 #include <iomanip>
0064 #include <string>
0065 #include <utility>
0066 #include <vector>
0067 
0068 class CaloSteppingAction : public SimProducer,
0069                            public Observer<const BeginOfRun*>,
0070                            public Observer<const BeginOfEvent*>,
0071                            public Observer<const EndOfEvent*>,
0072                            public Observer<const G4Step*> {
0073 public:
0074   CaloSteppingAction(const edm::ParameterSet& p);
0075   ~CaloSteppingAction() override;
0076 
0077   void registerConsumes(edm::ConsumesCollector) override;
0078   void produce(edm::Event&, const edm::EventSetup&) override;
0079   void beginRun(edm::EventSetup const&) override;
0080 
0081 private:
0082   void fillHits(edm::PCaloHitContainer& cc, int type);
0083   void fillPassiveHits(edm::PassiveHitContainer& cc);
0084   // observer classes
0085   void update(const BeginOfRun* run) override;
0086   void update(const BeginOfEvent* evt) override;
0087   void update(const G4Step* step) override;
0088   void update(const EndOfEvent* evt) override;
0089 
0090   void NaNTrap(const G4Step*) const;
0091   uint32_t getDetIDHC(int det, int lay, int depth, const math::XYZVectorD& pos) const;
0092   void fillHit(uint32_t id, double dE, double time, int primID, uint16_t depth, double em, int flag);
0093   uint16_t getDepth(bool flag, double crystalDepth, double radl) const;
0094   double curve_LY(double crystalLength, double crystalDepth) const;
0095   double getBirkL3(double dE, double step, double chg, double dens) const;
0096   double getBirkHC(double dE, double step, double chg, double dens) const;
0097   void saveHits(int flag);
0098 
0099   static const int nSD_ = 3;
0100   std::unique_ptr<EcalBarrelNumberingScheme> ebNumberingScheme_;
0101   std::unique_ptr<EcalEndcapNumberingScheme> eeNumberingScheme_;
0102   std::unique_ptr<HcalNumberingFromPS> hcNumberingPS_;
0103 #ifdef HcalNumberingTest
0104   edm::ESGetToken<HcalDDDSimConstants, HcalSimNumberingRecord> ddconsToken_;
0105   std::unique_ptr<HcalNumberingFromDDD> hcNumbering_;
0106 #endif
0107   std::unique_ptr<HcalNumberingScheme> hcNumberingScheme_;
0108   std::unique_ptr<CaloSlaveSD> slave_[nSD_];
0109 
0110   const edm::ParameterSet iC_;
0111   const std::vector<std::string> nameEBSD_, nameEESD_, nameHCSD_;
0112   const std::vector<std::string> nameHitC_;
0113   std::vector<const G4LogicalVolume*> volEBSD_, volEESD_, volHCSD_;
0114   std::map<const G4LogicalVolume*, double> xtalMap_;
0115   std::map<const G4LogicalVolume*, std::string> mapLV_;
0116   const int allSteps_;
0117   const double slopeLY_, birkC1EC_, birkSlopeEC_;
0118   const double birkCutEC_, birkC1HC_, birkC2HC_;
0119   const double birkC3HC_, timeSliceUnit_;
0120   int count_, eventID_;
0121   std::map<std::pair<int, CaloHitID>, CaloGVHit> hitMap_[nSD_];
0122   typedef std::tuple<const G4LogicalVolume*, uint32_t, int, int, double, double, double, double, double, double, double>
0123       PassiveData;
0124   std::vector<PassiveData> store_;
0125 };
0126 
0127 CaloSteppingAction::CaloSteppingAction(const edm::ParameterSet& p)
0128     : iC_(p.getParameter<edm::ParameterSet>("CaloSteppingAction")),
0129       nameEBSD_(iC_.getParameter<std::vector<std::string> >("EBSDNames")),
0130       nameEESD_(iC_.getParameter<std::vector<std::string> >("EESDNames")),
0131       nameHCSD_(iC_.getParameter<std::vector<std::string> >("HCSDNames")),
0132       nameHitC_(iC_.getParameter<std::vector<std::string> >("HitCollNames")),
0133       allSteps_(iC_.getParameter<int>("AllSteps")),
0134       slopeLY_(iC_.getParameter<double>("SlopeLightYield")),
0135       birkC1EC_(iC_.getParameter<double>("BirkC1EC")),
0136       birkSlopeEC_(iC_.getParameter<double>("BirkSlopeEC")),
0137       birkCutEC_(iC_.getParameter<double>("BirkCutEC")),
0138       birkC1HC_(iC_.getParameter<double>("BirkC1HC")),
0139       birkC2HC_(iC_.getParameter<double>("BirkC2HC")),
0140       birkC3HC_(iC_.getParameter<double>("BirkC3HC")),
0141       timeSliceUnit_(iC_.getUntrackedParameter<double>("TimeSliceUnit", 1.0)),
0142       count_(0) {
0143   edm::ParameterSet iC = p.getParameter<edm::ParameterSet>("CaloSteppingAction");
0144 
0145   edm::LogVerbatim("Step") << "CaloSteppingAction:: " << nameEBSD_.size() << " names for EB SD's";
0146   for (unsigned int k = 0; k < nameEBSD_.size(); ++k)
0147     edm::LogVerbatim("Step") << "[" << k << "] " << nameEBSD_[k];
0148   edm::LogVerbatim("Step") << "CaloSteppingAction:: " << nameEESD_.size() << " names for EE SD's";
0149   for (unsigned int k = 0; k < nameEESD_.size(); ++k)
0150     edm::LogVerbatim("Step") << "[" << k << "] " << nameEESD_[k];
0151   edm::LogVerbatim("Step") << "CaloSteppingAction:: " << nameHCSD_.size() << " names for HC SD's";
0152   for (unsigned int k = 0; k < nameHCSD_.size(); ++k)
0153     edm::LogVerbatim("Step") << "[" << k << "] " << nameHCSD_[k];
0154   edm::LogVerbatim("Step") << "CaloSteppingAction::Constants for ECAL: slope " << slopeLY_ << " Birk constants "
0155                            << birkC1EC_ << ":" << birkSlopeEC_ << ":" << birkCutEC_;
0156   edm::LogVerbatim("Step") << "CaloSteppingAction::Constants for HCAL: Birk "
0157                            << "constants " << birkC1HC_ << ":" << birkC2HC_ << ":" << birkC3HC_;
0158   edm::LogVerbatim("Step") << "CaloSteppingAction::Constant for time slice " << timeSliceUnit_;
0159   edm::LogVerbatim("Step") << "CaloSteppingAction:: " << nameHitC_.size() << " hit collections";
0160   for (unsigned int k = 0; k < nameHitC_.size(); ++k)
0161     edm::LogVerbatim("Step") << "[" << k << "] " << nameHitC_[k];
0162 
0163   ebNumberingScheme_ = std::make_unique<EcalBarrelNumberingScheme>();
0164   eeNumberingScheme_ = std::make_unique<EcalEndcapNumberingScheme>();
0165   hcNumberingPS_ = std::make_unique<HcalNumberingFromPS>(iC);
0166   hcNumberingScheme_ = std::make_unique<HcalNumberingScheme>();
0167 #ifdef HcalNumberingTest
0168   hcNumbering_.reset(nullptr);
0169 #endif
0170   for (int k = 0; k < CaloSteppingAction::nSD_; ++k) {
0171     slave_[k] = std::make_unique<CaloSlaveSD>(nameHitC_[k]);
0172     produces<edm::PCaloHitContainer>(nameHitC_[k]);
0173   }
0174   if (allSteps_ != 0)
0175     produces<edm::PassiveHitContainer>("AllPassiveHits");
0176   edm::LogVerbatim("Step") << "CaloSteppingAction:: All Steps Flag " << allSteps_ << " for passive hits";
0177 }
0178 
0179 CaloSteppingAction::~CaloSteppingAction() {
0180   edm::LogVerbatim("Step") << "CaloSteppingAction: -------->  Total number of "
0181                            << "selected entries : " << count_;
0182 }
0183 
0184 void CaloSteppingAction::registerConsumes(edm::ConsumesCollector cc) {
0185 #ifdef HcalNumberingTest
0186   ddconsToken_ = cc.esConsumes<HcalDDDSimConstants, HcalSimNumberingRecord, edm::Transition::BeginRun>();
0187   edm::LogVerbatim("Step") << "CaloSteppingAction::Initialize ESGetToken for HcalDDDSimConstants";
0188 #endif
0189 }
0190 
0191 void CaloSteppingAction::produce(edm::Event& e, const edm::EventSetup&) {
0192   for (int k = 0; k < CaloSteppingAction::nSD_; ++k) {
0193     saveHits(k);
0194     auto product = std::make_unique<edm::PCaloHitContainer>();
0195     fillHits(*product, k);
0196     e.put(std::move(product), nameHitC_[k]);
0197   }
0198   if (allSteps_ != 0) {
0199     std::unique_ptr<edm::PassiveHitContainer> hgcPH(new edm::PassiveHitContainer);
0200     fillPassiveHits(*hgcPH);
0201     e.put(std::move(hgcPH), "AllPassiveHits");
0202   }
0203 }
0204 
0205 void CaloSteppingAction::fillHits(edm::PCaloHitContainer& cc, int type) {
0206   edm::LogVerbatim("Step") << "CaloSteppingAction::fillHits for type " << type << " with "
0207                            << slave_[type].get()->hits().size() << " hits";
0208   cc = slave_[type].get()->hits();
0209   slave_[type].get()->Clean();
0210 }
0211 
0212 void CaloSteppingAction::fillPassiveHits(edm::PassiveHitContainer& cc) {
0213   edm::LogVerbatim("Step") << "CaloSteppingAction::fillPassiveHits with " << store_.size() << " hits";
0214   for (const auto& element : store_) {
0215     auto lv = std::get<0>(element);
0216     auto it = mapLV_.find(lv);
0217     if (it != mapLV_.end()) {
0218       PassiveHit hit(it->second,
0219                      std::get<1>(element),
0220                      std::get<5>(element),
0221                      std::get<6>(element),
0222                      std::get<4>(element),
0223                      std::get<2>(element),
0224                      std::get<3>(element),
0225                      std::get<7>(element),
0226                      std::get<8>(element),
0227                      std::get<9>(element),
0228                      std::get<10>(element));
0229       cc.emplace_back(hit);
0230     }
0231   }
0232 }
0233 
0234 void CaloSteppingAction::beginRun(edm::EventSetup const& es) {
0235   edm::LogVerbatim("Step") << "CaloSteppingAction:: Enter BeginOfRun";
0236 
0237 #ifdef HcalNumberingTest
0238   // Numbering From DDD
0239   const HcalDDDSimConstants* hcons_ = &es.getData(ddconsToken_);
0240   edm::LogVerbatim("Step") << "CaloSteppingAction:: Initialise "
0241                            << "HcalNumberingFromDDD";
0242   hcNumbering_ = std::make_unique<HcalNumberingFromDDD>(hcons_);
0243 #endif
0244 }
0245 
0246 //==================================================================== per RUN
0247 void CaloSteppingAction::update(const BeginOfRun* run) {
0248   int irun = (*run)()->GetRunID();
0249   edm::LogVerbatim("Step") << "CaloSteppingAction:: Begin of Run = " << irun;
0250 
0251   const G4LogicalVolumeStore* lvs = G4LogicalVolumeStore::GetInstance();
0252   if (lvs) {
0253     std::map<const std::string, const G4LogicalVolume*> nameMap;
0254     std::map<const std::string, const G4LogicalVolume*>::const_iterator itr;
0255     for (auto lvi = lvs->begin(), lve = lvs->end(); lvi != lve; ++lvi) {
0256       nameMap.emplace((*lvi)->GetName(), *lvi);
0257       if (allSteps_ < 0)
0258         mapLV_[*lvi] = (*lvi)->GetName();
0259     }
0260 
0261     for (auto const& name : nameEBSD_) {
0262       for (itr = nameMap.begin(); itr != nameMap.end(); ++itr) {
0263         const std::string& lvname = itr->first;
0264         if (lvname.find(name) != std::string::npos) {
0265           volEBSD_.emplace_back(itr->second);
0266           int type = (lvname.find("refl") == std::string::npos) ? -1 : 1;
0267           G4Trap* solid = static_cast<G4Trap*>(itr->second->GetSolid());
0268           double dz = 2 * solid->GetZHalfLength() / CLHEP::mm;
0269           xtalMap_.insert(std::pair<const G4LogicalVolume*, double>(itr->second, dz * type));
0270           if ((allSteps_ > 0) && ((allSteps_ % 10) > 0))
0271             mapLV_[itr->second] = itr->first;
0272         }
0273       }
0274     }
0275     for (auto const& name : nameEESD_) {
0276       for (itr = nameMap.begin(); itr != nameMap.end(); ++itr) {
0277         const std::string& lvname = itr->first;
0278         if (lvname.find(name) != std::string::npos) {
0279           volEESD_.emplace_back(itr->second);
0280           int type = (lvname.find("refl") == std::string::npos) ? 1 : -1;
0281           G4Trap* solid = static_cast<G4Trap*>(itr->second->GetSolid());
0282           double dz = 2 * solid->GetZHalfLength() / CLHEP::mm;
0283           xtalMap_.insert(std::pair<const G4LogicalVolume*, double>(itr->second, dz * type));
0284           if ((allSteps_ > 0) && (((allSteps_ / 10) % 10) > 0))
0285             mapLV_[itr->second] = itr->first;
0286         }
0287       }
0288     }
0289 
0290     for (auto const& name : nameHCSD_) {
0291       for (itr = nameMap.begin(); itr != nameMap.end(); ++itr) {
0292         const std::string& lvname = itr->first;
0293         if (lvname.find(name) != std::string::npos) {
0294           volHCSD_.emplace_back(itr->second);
0295           if ((allSteps_ > 0) && (((allSteps_ / 100) % 10) > 0))
0296             mapLV_[itr->second] = itr->first;
0297         }
0298       }
0299     }
0300   }
0301 #ifdef EDM_ML_DEBUG
0302   edm::LogVerbatim("Step") << volEBSD_.size() << " logical volumes for EB SD";
0303   for (unsigned int k = 0; k < volEBSD_.size(); ++k)
0304     edm::LogVerbatim("Step") << "[" << k << "] " << volEBSD_[k];
0305   edm::LogVerbatim("Step") << volEESD_.size() << " logical volumes for EE SD";
0306   for (unsigned int k = 0; k < volEESD_.size(); ++k)
0307     edm::LogVerbatim("Step") << "[" << k << "] " << volEESD_[k];
0308   edm::LogVerbatim("Step") << volHCSD_.size() << " logical volumes for HC SD";
0309   for (unsigned int k = 0; k < volHCSD_.size(); ++k)
0310     edm::LogVerbatim("Step") << "[" << k << "] " << volHCSD_[k];
0311   edm::LogVerbatim("Step") << mapLV_.size() << " logical volumes for Passive hits";
0312   unsigned int k(0);
0313   for (auto itr = mapLV_.begin(); itr != mapLV_.end(); ++itr) {
0314     edm::LogVerbatim("Step") << "[" << k << "] " << itr->second << ":" << itr->first;
0315     ++k;
0316   }
0317 #endif
0318 }
0319 
0320 //=================================================================== per EVENT
0321 void CaloSteppingAction::update(const BeginOfEvent* evt) {
0322   eventID_ = (*evt)()->GetEventID();
0323   edm::LogVerbatim("Step") << "CaloSteppingAction: Begin of event = " << eventID_;
0324   for (int k = 0; k < CaloSteppingAction::nSD_; ++k) {
0325     hitMap_[k].erase(hitMap_[k].begin(), hitMap_[k].end());
0326     slave_[k].get()->Initialize();
0327   }
0328   if (allSteps_ != 0)
0329     store_.clear();
0330 }
0331 
0332 //=================================================================== each STEP
0333 void CaloSteppingAction::update(const G4Step* aStep) {
0334   //  edm::LogVerbatim("Step") <<"CaloSteppingAction: At each Step";
0335   NaNTrap(aStep);
0336   auto lv = aStep->GetPreStepPoint()->GetPhysicalVolume()->GetLogicalVolume();
0337   bool hc = (std::find(volHCSD_.begin(), volHCSD_.end(), lv) != volHCSD_.end());
0338   bool eb = (std::find(volEBSD_.begin(), volEBSD_.end(), lv) != volEBSD_.end());
0339   bool ee = (std::find(volEESD_.begin(), volEESD_.end(), lv) != volEESD_.end());
0340   uint32_t unitID(0);
0341   if (hc || eb || ee) {
0342     double dEStep = aStep->GetTotalEnergyDeposit() / CLHEP::MeV;
0343     auto const theTrack = aStep->GetTrack();
0344     double time = theTrack->GetGlobalTime() / CLHEP::nanosecond;
0345     int primID = theTrack->GetTrackID();
0346     bool em = G4TrackToParticleID::isGammaElectronPositron(theTrack);
0347     auto const touch = aStep->GetPreStepPoint()->GetTouchable();
0348     auto const& hitPoint = aStep->GetPreStepPoint()->GetPosition();
0349     if (hc) {
0350       int depth = (touch->GetReplicaNumber(0)) % 10 + 1;
0351       int lay = (touch->GetReplicaNumber(0) / 10) % 100 + 1;
0352       int det = (touch->GetReplicaNumber(1)) / 1000;
0353       unitID = getDetIDHC(det, lay, depth, math::XYZVectorD(hitPoint.x(), hitPoint.y(), hitPoint.z()));
0354       if (unitID > 0 && dEStep > 0.0) {
0355         dEStep *= getBirkHC(dEStep,
0356                             (aStep->GetStepLength() / CLHEP::cm),
0357                             aStep->GetPreStepPoint()->GetCharge(),
0358                             (aStep->GetPreStepPoint()->GetMaterial()->GetDensity() / (CLHEP::g / CLHEP::cm3)));
0359         fillHit(unitID, dEStep, time, primID, 0, em, 2);
0360       }
0361     } else {
0362       EcalBaseNumber theBaseNumber;
0363       int size = touch->GetHistoryDepth() + 1;
0364       if (theBaseNumber.getCapacity() < size)
0365         theBaseNumber.setSize(size);
0366       //Get name and copy numbers
0367       if (size > 1) {
0368         for (int ii = 0; ii < size; ii++) {
0369           theBaseNumber.addLevel(touch->GetVolume(ii)->GetName(), touch->GetReplicaNumber(ii));
0370         }
0371       }
0372       unitID = (eb ? (ebNumberingScheme_->getUnitID(theBaseNumber)) : (eeNumberingScheme_->getUnitID(theBaseNumber)));
0373       if (unitID > 0 && dEStep > 0.0) {
0374         auto local = touch->GetHistory()->GetTopTransform().TransformPoint(hitPoint);
0375         auto ite = xtalMap_.find(lv);
0376         double crystalLength = ((ite == xtalMap_.end()) ? 230.0 : std::abs(ite->second));
0377         double crystalDepth =
0378             ((ite == xtalMap_.end()) ? 0.0 : (std::abs(0.5 * (ite->second) + (local.z() / CLHEP::mm))));
0379         double radl = aStep->GetPreStepPoint()->GetMaterial()->GetRadlen() / CLHEP::mm;
0380         bool flag = ((ite == xtalMap_.end()) ? true : (((ite->second) >= 0) ? true : false));
0381         auto depth = getDepth(flag, crystalDepth, radl);
0382         dEStep *= (getBirkL3(dEStep,
0383                              (aStep->GetStepLength() / CLHEP::cm),
0384                              aStep->GetPreStepPoint()->GetCharge(),
0385                              (aStep->GetPreStepPoint()->GetMaterial()->GetDensity() / (CLHEP::g / CLHEP::cm3))) *
0386                    curve_LY(crystalLength, crystalDepth));
0387         fillHit(unitID, dEStep, time, primID, depth, em, (eb ? 0 : 1));
0388       }
0389     }
0390   }
0391 
0392   if (allSteps_ != 0) {
0393     auto it = mapLV_.find(lv);
0394     if (it != mapLV_.end()) {
0395       double energy = aStep->GetTotalEnergyDeposit() / CLHEP::MeV;
0396       auto const touch = aStep->GetPreStepPoint()->GetTouchable();
0397       double time = aStep->GetTrack()->GetGlobalTime() / CLHEP::nanosecond;
0398       int trackId = aStep->GetTrack()->GetTrackID();
0399       int pdg = aStep->GetTrack()->GetDefinition()->GetPDGEncoding();
0400       double stepl = (aStep->GetStepLength() / CLHEP::cm);
0401       double xp = aStep->GetPreStepPoint()->GetPosition().x() / CLHEP::cm;
0402       double yp = aStep->GetPreStepPoint()->GetPosition().y() / CLHEP::cm;
0403       double zp = aStep->GetPreStepPoint()->GetPosition().z() / CLHEP::cm;
0404 #ifdef EDM_ML_DEBUG
0405       edm::LogVerbatim("Step") << "CaloSteppingAction: Volume " << lv->GetName() << " History "
0406                                << touch->GetHistoryDepth() << " Pointers " << aStep->GetPostStepPoint() << ":"
0407                                << aStep->GetTrack()->GetNextVolume() << ":" << aStep->IsLastStepInVolume() << " E "
0408                                << energy << " T " << time << " PDG " << pdg << " step " << stepl << " Position (" << xp
0409                                << ", " << yp << ", " << zp << ")";
0410 #endif
0411       uint32_t copy = (allSteps_ < 0) ? 0 : unitID;
0412       if (((aStep->GetPostStepPoint() == nullptr) || (aStep->GetTrack()->GetNextVolume() == nullptr)) &&
0413           (aStep->IsLastStepInVolume())) {
0414         energy += (aStep->GetPreStepPoint()->GetKineticEnergy() / CLHEP::MeV);
0415       } else {
0416         time = aStep->GetPostStepPoint()->GetGlobalTime() / CLHEP::nanosecond;
0417         if (copy == 0)
0418           copy = (touch->GetHistoryDepth() < 1)
0419                      ? static_cast<uint32_t>(touch->GetReplicaNumber(0))
0420                      : static_cast<uint32_t>(touch->GetReplicaNumber(0) + 1000 * touch->GetReplicaNumber(1));
0421       }
0422       PassiveData key(std::make_tuple(lv, copy, trackId, pdg, time, energy, energy, stepl, xp, yp, zp));
0423       store_.push_back(key);
0424     }
0425   }
0426 }
0427 
0428 //================================================================ End of EVENT
0429 void CaloSteppingAction::update(const EndOfEvent* evt) {
0430   ++count_;
0431   // Fill event input
0432   edm::LogVerbatim("Step") << "CaloSteppingAction: EndOfEvent " << (*evt)()->GetEventID();
0433 }
0434 
0435 void CaloSteppingAction::NaNTrap(const G4Step* aStep) const {
0436   auto currentPos = aStep->GetTrack()->GetPosition();
0437   double xyz = currentPos.x() + currentPos.y() + currentPos.z();
0438   auto currentMom = aStep->GetTrack()->GetMomentum();
0439   xyz += currentMom.x() + currentMom.y() + currentMom.z();
0440 
0441   if (edm::isNotFinite(xyz)) {
0442     auto pCurrentVol = aStep->GetPreStepPoint()->GetPhysicalVolume();
0443     auto& nameOfVol = pCurrentVol->GetName();
0444     throw cms::Exception("Unknown", "CaloSteppingAction")
0445         << " Corrupted Event - NaN detected in volume " << nameOfVol << "\n";
0446   }
0447 }
0448 
0449 uint32_t CaloSteppingAction::getDetIDHC(int det, int lay, int depth, const math::XYZVectorD& pos) const {
0450   HcalNumberingFromDDD::HcalID tmp = hcNumberingPS_.get()->unitID(det, lay, depth, pos);
0451 #ifdef HcalNumberingTest
0452   auto id0 = hcNumberingScheme_.get()->getUnitID(tmp);
0453   HcalNumberingFromDDD::HcalID tmpO = hcNumbering_.get()->unitID(det, pos, depth, lay);
0454   auto idO = hcNumberingScheme_.get()->getUnitID(tmpO);
0455   std::string error = (id0 == idO) ? " ** OK **" : " ** ERROR **";
0456   edm::LogVerbatim("Step") << "Det ID " << HcalDetId(id0) << " Original " << HcalDetId(idO) << error;
0457 #endif
0458   return (hcNumberingScheme_.get()->getUnitID(tmp));
0459 }
0460 
0461 void CaloSteppingAction::fillHit(uint32_t id, double dE, double time, int primID, uint16_t depth, double em, int flag) {
0462   CaloHitID currentID(id, time, primID, depth, timeSliceUnit_);
0463   double edepEM = (em ? dE : 0);
0464   double edepHAD = (em ? 0 : dE);
0465   std::pair<int, CaloHitID> evID = std::make_pair(eventID_, currentID);
0466   auto it = hitMap_[flag].find(evID);
0467   if (it != hitMap_[flag].end()) {
0468     (it->second).addEnergyDeposit(edepEM, edepHAD);
0469   } else {
0470     CaloGVHit aHit;
0471     aHit.setEventID(eventID_);
0472     aHit.setID(currentID);
0473     aHit.addEnergyDeposit(edepEM, edepHAD);
0474     hitMap_[flag][evID] = aHit;
0475   }
0476 }
0477 
0478 uint16_t CaloSteppingAction::getDepth(bool flag, double crystalDepth, double radl) const {
0479   uint16_t depth1 = (flag ? 0 : PCaloHit::kEcalDepthRefz);
0480   uint16_t depth2 = (uint16_t)floor(crystalDepth / radl);
0481   uint16_t depth = (((depth2 & PCaloHit::kEcalDepthMask) << PCaloHit::kEcalDepthOffset) | depth1);
0482 #ifdef EDM_ML_DEBUG
0483   edm::LogVerbatim("Step") << "CaloSteppingAction::getDepth radl " << radl << ":" << crystalDepth << " depth " << depth;
0484 #endif
0485   return depth;
0486 }
0487 
0488 double CaloSteppingAction::curve_LY(double crystalLength, double crystalDepth) const {
0489   double weight = 1.;
0490   double dapd = crystalLength - crystalDepth;
0491   if (dapd >= -0.1 || dapd <= crystalLength + 0.1) {
0492     if (dapd <= 100.)
0493       weight = 1.0 + slopeLY_ - dapd * 0.01 * slopeLY_;
0494 #ifdef EDM_ML_DEBUG
0495     edm::LogVerbatim("Step") << "CaloSteppingAction::curve_LY " << crystalDepth << ":" << crystalLength << ":" << dapd
0496                              << ":" << weight;
0497 #endif
0498   } else {
0499     edm::LogWarning("Step") << "CaloSteppingAction: light coll curve : wrong "
0500                             << "distance to APD " << dapd << " crlength = " << crystalLength
0501                             << " crystal Depth = " << crystalDepth << " weight = " << weight;
0502   }
0503   return weight;
0504 }
0505 
0506 double CaloSteppingAction::getBirkL3(double dEStep, double step, double charge, double density) const {
0507   double weight = 1.;
0508   if (charge != 0. && step > 0.) {
0509     double dedx = dEStep / step;
0510     double rkb = birkC1EC_ / density;
0511     if (dedx > 0) {
0512       weight = 1. - birkSlopeEC_ * log(rkb * dedx);
0513       if (weight < birkCutEC_)
0514         weight = birkCutEC_;
0515       else if (weight > 1.)
0516         weight = 1.;
0517     }
0518 #ifdef EDM_ML_DEBUG
0519     edm::LogVerbatim("Step") << "CaloSteppingAction::getBirkL3 Charge " << charge << " dE/dx " << dedx << " Birk Const "
0520                              << rkb << " Weight = " << weight << " dE " << dEStep << " step " << step;
0521 #endif
0522   }
0523   return weight;
0524 }
0525 
0526 double CaloSteppingAction::getBirkHC(double dEStep, double step, double charge, double density) const {
0527   double weight = 1.;
0528   if (charge != 0. && step > 0.) {
0529     double dedx = dEStep / step;
0530     double rkb = birkC1HC_ / density;
0531     double c = birkC2HC_ * rkb * rkb;
0532     if (std::abs(charge) >= 2.)
0533       rkb /= birkC3HC_;
0534     weight = 1. / (1. + rkb * dedx + c * dedx * dedx);
0535 #ifdef EDM_ML_DEBUG
0536     edm::LogVerbatim("Step") << "CaloSteppingAction::getBirkHC Charge " << charge << " dE/dx " << dedx << " Birk Const "
0537                              << rkb << ", " << c << " Weight = " << weight << " dE " << dEStep;
0538 #endif
0539   }
0540   return weight;
0541 }
0542 
0543 void CaloSteppingAction::saveHits(int type) {
0544   edm::LogVerbatim("Step") << "CaloSteppingAction:: saveHits for type " << type << " with " << hitMap_[type].size()
0545                            << " hits";
0546   slave_[type].get()->ReserveMemory(hitMap_[type].size());
0547   for (auto const& hit : hitMap_[type]) {
0548     slave_[type].get()->processHits(hit.second.getUnitID(),
0549                                     0.001 * hit.second.getEM(),
0550                                     0.001 * hit.second.getHadr(),
0551                                     hit.second.getTimeSlice(),
0552                                     hit.second.getTrackID(),
0553                                     hit.second.getDepth());
0554   }
0555 }
0556 
0557 #include "SimG4Core/Watcher/interface/SimWatcherFactory.h"
0558 #include "FWCore/PluginManager/interface/ModuleDef.h"
0559 
0560 DEFINE_SIMWATCHER(CaloSteppingAction);