File indexing completed on 2024-05-10 02:21:14
0001
0002
0003
0004
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
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
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
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
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
0333 void CaloSteppingAction::update(const G4Step* aStep) {
0334
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
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
0429 void CaloSteppingAction::update(const EndOfEvent* evt) {
0430 ++count_;
0431
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);