File indexing completed on 2024-05-10 02:21:15
0001
0002
0003
0004
0005 #include "SimG4CMS/Calo/interface/ECalSD.h"
0006 #include "SimG4CMS/Calo/interface/EcalDumpGeometry.h"
0007 #include "SimG4Core/Geometry/interface/DD4hep2DDDName.h"
0008 #include "SimG4Core/Notification/interface/TrackInformation.h"
0009 #include "Geometry/EcalCommonData/interface/EcalBarrelNumberingScheme.h"
0010 #include "Geometry/EcalCommonData/interface/EcalBaseNumber.h"
0011 #include "Geometry/EcalCommonData/interface/EcalEndcapNumberingScheme.h"
0012 #include "Geometry/EcalCommonData/interface/EcalPreshowerNumberingScheme.h"
0013 #include "Geometry/EcalCommonData/interface/ESTBNumberingScheme.h"
0014 #include "DataFormats/EcalDetId/interface/EBDetId.h"
0015 #include "DataFormats/Math/interface/GeantUnits.h"
0016 #include "SimDataFormats/CaloHit/interface/PCaloHit.h"
0017
0018 #include "FWCore/Framework/interface/ESTransientHandle.h"
0019 #include "FWCore/ServiceRegistry/interface/Service.h"
0020 #include "CommonTools/UtilAlgos/interface/TFileService.h"
0021
0022 #include "G4LogicalVolumeStore.hh"
0023 #include "G4LogicalVolume.hh"
0024 #include "G4Step.hh"
0025 #include "G4Track.hh"
0026 #include "G4VProcess.hh"
0027
0028 #include <CLHEP/Units/SystemOfUnits.h>
0029
0030 #include <algorithm>
0031
0032
0033
0034 using namespace geant_units::operators;
0035
0036 template <class T>
0037 bool any(const std::vector<T>& v, const T& what) {
0038 return std::find(v.begin(), v.end(), what) != v.end();
0039 }
0040
0041 ECalSD::ECalSD(const std::string& name,
0042 const EcalSimulationParameters* ecpar,
0043 const SensitiveDetectorCatalog& clg,
0044 edm::ParameterSet const& p,
0045 const SimTrackManager* manager)
0046 : CaloSD(name,
0047 clg,
0048 p,
0049 manager,
0050 (float)(p.getParameter<edm::ParameterSet>("ECalSD").getParameter<double>("TimeSliceUnit")),
0051 p.getParameter<edm::ParameterSet>("ECalSD").getParameter<bool>("IgnoreTrackID")),
0052 ecalSimParameters_(ecpar) {
0053 numberingScheme_.reset(nullptr);
0054
0055
0056
0057
0058
0059
0060
0061
0062 edm::ParameterSet m_EC = p.getParameter<edm::ParameterSet>("ECalSD");
0063 useBirk = m_EC.getParameter<bool>("UseBirkLaw");
0064 useBirkL3 = m_EC.getParameter<bool>("BirkL3Parametrization");
0065 double bunit = (CLHEP::g / (CLHEP::MeV * CLHEP::cm2));
0066 birk1 = m_EC.getParameter<double>("BirkC1") * bunit;
0067 birk2 = m_EC.getParameter<double>("BirkC2");
0068 birk3 = m_EC.getParameter<double>("BirkC3");
0069 birkSlope = m_EC.getParameter<double>("BirkSlope");
0070 birkCut = m_EC.getParameter<double>("BirkCut");
0071 slopeLY = m_EC.getParameter<double>("SlopeLightYield");
0072 storeTrack = m_EC.getParameter<bool>("StoreSecondary");
0073 crystalMat = m_EC.getUntrackedParameter<std::string>("XtalMat", "E_PbWO4");
0074 bool isItTB = m_EC.getUntrackedParameter<bool>("TestBeam", false);
0075 bool nullNS = m_EC.getUntrackedParameter<bool>("NullNumbering", false);
0076 storeRL = m_EC.getUntrackedParameter<bool>("StoreRadLength", false);
0077 scaleRL = m_EC.getUntrackedParameter<double>("ScaleRadLength", 1.0);
0078 int dumpGeom = m_EC.getUntrackedParameter<int>("DumpGeometry", 0);
0079
0080
0081 storeLayerTimeSim = m_EC.getUntrackedParameter<bool>("StoreLayerTimeSim", false);
0082
0083 ageingWithSlopeLY = m_EC.getUntrackedParameter<bool>("AgeingWithSlopeLY", false);
0084 if (ageingWithSlopeLY)
0085 ageing.setLumies(p.getParameter<edm::ParameterSet>("ECalSD").getParameter<double>("DelivLuminosity"),
0086 p.getParameter<edm::ParameterSet>("ECalSD").getParameter<double>("InstLuminosity"));
0087
0088 if (ecalSimParameters_ == nullptr) {
0089 edm::LogError("EcalSim") << "ECalSD : Cannot find EcalSimulationParameters for " << name;
0090 throw cms::Exception("Unknown", "ECalSD") << "Cannot find EcalSimulationParameters for " << name << "\n";
0091 }
0092
0093
0094 useWeight = ecalSimParameters_->useWeight_;
0095 #ifdef EDM_ML_DEBUG
0096 edm::LogVerbatim("EcalSim") << "ECalSD:: useWeight " << useWeight;
0097 #endif
0098 depth1Name = ecalSimParameters_->depth1Name_;
0099 depth2Name = ecalSimParameters_->depth2Name_;
0100 #ifdef EDM_ML_DEBUG
0101 edm::LogVerbatim("EcalSim") << "Names (Depth 1):" << depth1Name << " (Depth 2):" << depth2Name << std::endl;
0102 #endif
0103 int type(-1);
0104 bool dump(false);
0105 EcalNumberingScheme* scheme = nullptr;
0106 if (nullNS) {
0107 scheme = nullptr;
0108 } else if (name == "EcalHitsEB") {
0109 scheme = dynamic_cast<EcalNumberingScheme*>(new EcalBarrelNumberingScheme());
0110 type = 0;
0111 dump = ((dumpGeom % 10) > 0);
0112 } else if (name == "EcalHitsEE") {
0113 scheme = dynamic_cast<EcalNumberingScheme*>(new EcalEndcapNumberingScheme());
0114 type = 1;
0115 dump = (((dumpGeom / 10) % 10) > 0);
0116 } else if (name == "EcalHitsES") {
0117 if (isItTB)
0118 scheme = dynamic_cast<EcalNumberingScheme*>(new ESTBNumberingScheme());
0119 else
0120 scheme = dynamic_cast<EcalNumberingScheme*>(new EcalPreshowerNumberingScheme());
0121 useWeight = false;
0122 type = 2;
0123 dump = (((dumpGeom / 100) % 10) > 0);
0124 } else {
0125 edm::LogWarning("EcalSim") << "ECalSD: ReadoutName not supported";
0126 }
0127 int type0 = dumpGeom / 1000;
0128 type += (10 * type0);
0129
0130 if (nullptr != scheme) {
0131 setNumberingScheme(scheme);
0132 }
0133 #ifdef EDM_ML_DEBUG
0134 edm::LogVerbatim("EcalSim") << "Constructing a ECalSD with name " << GetName();
0135 #endif
0136 if (useWeight) {
0137 edm::LogVerbatim("EcalSim") << "ECalSD:: Use of Birks law is set to " << useBirk
0138 << " with three constants kB = " << birk1 / bunit << ", C1 = " << birk2
0139 << ", C2 = " << birk3 << "\n Use of L3 parametrization " << useBirkL3
0140 << " with slope " << birkSlope << " and cut off " << birkCut << "\n"
0141 << " Slope for Light yield is set to " << slopeLY;
0142 } else {
0143 edm::LogVerbatim("EcalSim") << "ECalSD:: energy deposit is not corrected "
0144 << " by Birk or light yield curve";
0145 }
0146
0147 edm::LogVerbatim("EcalSim") << "ECalSD:: Suppression Flag " << suppressHeavy << "\tprotons below "
0148 << kmaxProton / CLHEP::MeV << " MeV,\tneutrons below " << kmaxNeutron / CLHEP::MeV
0149 << " MeV,\tions below " << kmaxIon / CLHEP::MeV << " MeV \n\tDepth1 Name = " << depth1Name
0150 << "\tDepth2 Name = " << depth2Name << "\n\tstoreRL " << storeRL << ":" << scaleRL
0151 << "\tstoreLayerTimeSim " << storeLayerTimeSim << "\n\ttime Granularity "
0152 << p.getParameter<edm::ParameterSet>("ECalSD").getParameter<double>("TimeSliceUnit")
0153 << " ns";
0154 if (useWeight)
0155 initMap();
0156 #ifdef plotDebug
0157 edm::Service<TFileService> tfile;
0158 if (tfile.isAvailable()) {
0159 TFileDirectory ecDir = tfile->mkdir("ProfileFromECalSD");
0160 static const std::string ctype[4] = {"EB", "EBref", "EE", "EERef"};
0161 for (int k = 0; k < 4; ++k) {
0162 std::string name = "ECLL_" + ctype[k];
0163 std::string title = "Local vs Global for " + ctype[k];
0164 double xmin = (k > 1) ? 3000.0 : 1000.0;
0165 g2L_[k] = ecDir.make<TH2F>(name.c_str(), title.c_str(), 100, xmin, xmin + 1000., 100, 0.0, 3000.);
0166 }
0167 } else {
0168 for (int k = 0; k < 4; ++k)
0169 g2L_[k] = 0;
0170 }
0171 #endif
0172 if (dump) {
0173 const auto& lvNames = clg.logicalNames(name);
0174 EcalDumpGeometry geom(lvNames, depth1Name, depth2Name, type);
0175 geom.update();
0176 }
0177 }
0178
0179 ECalSD::~ECalSD() {}
0180
0181 double ECalSD::getEnergyDeposit(const G4Step* aStep) {
0182 const G4StepPoint* preStepPoint = aStep->GetPreStepPoint();
0183 const G4Track* theTrack = aStep->GetTrack();
0184 double edep = aStep->GetTotalEnergyDeposit();
0185
0186
0187 double weight = 1.;
0188 if (suppressHeavy) {
0189 TrackInformation* trkInfo = (TrackInformation*)(theTrack->GetUserInformation());
0190 if (trkInfo) {
0191 int pdg = theTrack->GetDefinition()->GetPDGEncoding();
0192 if (!(trkInfo->isPrimary())) {
0193 double ke = theTrack->GetKineticEnergy();
0194 if (((pdg / 1000000000 == 1 && ((pdg / 10000) % 100) > 0 && ((pdg / 10) % 100) > 0)) && (ke < kmaxIon))
0195 weight = 0;
0196 if ((pdg == 2212) && (ke < kmaxProton))
0197 weight = 0;
0198 if ((pdg == 2112) && (ke < kmaxNeutron))
0199 weight = 0;
0200 }
0201 }
0202 }
0203 const G4LogicalVolume* lv = preStepPoint->GetTouchable()->GetVolume(0)->GetLogicalVolume();
0204 double wt1 = 1.0;
0205 if (useWeight && !any(noWeight, lv)) {
0206 weight *= curve_LY(lv);
0207 if (useBirk) {
0208 if (useBirkL3)
0209 weight *= getBirkL3(aStep);
0210 else
0211 weight *= getAttenuation(aStep, birk1, birk2, birk3);
0212 }
0213 wt1 = getResponseWt(theTrack);
0214 }
0215 edep *= weight * wt1;
0216
0217 double wt2 = theTrack->GetWeight();
0218 if (wt2 > 0.0) {
0219 edep *= wt2;
0220 }
0221 #ifdef EDM_ML_DEBUG
0222 edm::LogVerbatim("EcalSim") << lv->GetName() << " "
0223 << DD4hep2DDDName::noNameSpace(static_cast<std::string>(lv->GetName()))
0224 << " Light Collection Efficiency " << weight << ":" << wt1 << " wt2= " << wt2
0225 << " Weighted Energy Deposit " << edep / CLHEP::MeV << " MeV at "
0226 << preStepPoint->GetPosition();
0227 #endif
0228 return edep;
0229 }
0230
0231 double ECalSD::EnergyCorrected(const G4Step& step, const G4Track* track) {
0232 const G4StepPoint* hitPoint = step.GetPreStepPoint();
0233 const G4LogicalVolume* lv = hitPoint->GetTouchable()->GetVolume(0)->GetLogicalVolume();
0234 if (lv->GetSensitiveDetector() != this)
0235 return 0.0;
0236
0237 double edep = step.GetTotalEnergyDeposit();
0238 if (useWeight && !any(noWeight, lv)) {
0239 currentLocalPoint = setToLocal(hitPoint->GetPosition(), hitPoint->GetTouchable());
0240 auto ite = xtalLMap.find(lv);
0241 crystalLength = (ite == xtalLMap.end()) ? 230._mm : std::abs(ite->second);
0242 crystalDepth = (ite == xtalLMap.end()) ? 0.0 : (std::abs(0.5 * (ite->second) + currentLocalPoint.z()));
0243 edep *= curve_LY(lv) * getResponseWt(track);
0244 }
0245 return edep;
0246 }
0247
0248 int ECalSD::getTrackID(const G4Track* aTrack) {
0249 int primaryID(0);
0250 if (storeTrack && depth > 0) {
0251 forceSave = true;
0252 primaryID = aTrack->GetTrackID();
0253 } else {
0254 primaryID = CaloSD::getTrackID(aTrack);
0255 }
0256 return primaryID;
0257 }
0258
0259 uint16_t ECalSD::getDepth(const G4Step* aStep) {
0260
0261 const G4StepPoint* hitPoint = aStep->GetPreStepPoint();
0262 currentLocalPoint = setToLocal(hitPoint->GetPosition(), hitPoint->GetTouchable());
0263 const G4LogicalVolume* lv = hitPoint->GetTouchable()->GetVolume(0)->GetLogicalVolume();
0264
0265 auto ite = xtalLMap.find(lv);
0266 crystalLength = (ite == xtalLMap.end()) ? 230._mm : std::abs(ite->second);
0267 crystalDepth = (ite == xtalLMap.end()) ? 0.0 : (std::abs(0.5 * (ite->second) + currentLocalPoint.z()));
0268 depth = any(useDepth1, lv) ? 1 : (any(useDepth2, lv) ? 2 : 0);
0269 uint16_t depth1(0), depth2(0);
0270 if (storeRL) {
0271 depth1 = (ite == xtalLMap.end()) ? 0 : (((ite->second) >= 0) ? 0 : PCaloHit::kEcalDepthRefz);
0272 depth2 = getRadiationLength(hitPoint, lv);
0273 depth |= (((depth2 & PCaloHit::kEcalDepthMask) << PCaloHit::kEcalDepthOffset) | depth1);
0274 } else if (storeLayerTimeSim) {
0275 depth2 = getLayerIDForTimeSim();
0276 depth |= ((depth2 & PCaloHit::kEcalDepthMask) << PCaloHit::kEcalDepthOffset);
0277 }
0278 #ifdef EDM_ML_DEBUG
0279 if (isXtal(lv))
0280 edm::LogVerbatim("EcalSimX") << "ECalSD::Volume " << lv->GetName() << " DetId " << std::hex << setDetUnitId(aStep)
0281 << std::dec << " Global " << (hitPoint->GetPosition()).rho() << ":"
0282 << (hitPoint->GetPosition()).z() << " Local Z " << currentLocalPoint.z() << " Depth "
0283 << crystalDepth;
0284 edm::LogVerbatim("EcalSim") << "ECalSD::Depth " << std::hex << depth1 << ":" << depth2 << ":" << depth << std::dec
0285 << " L " << (ite == xtalLMap.end()) << ":" << ite->second << " local "
0286 << currentLocalPoint << " Crystal length " << crystalLength << ":" << crystalDepth;
0287 #endif
0288 return depth;
0289 }
0290
0291 uint16_t ECalSD::getRadiationLength(const G4StepPoint* hitPoint, const G4LogicalVolume* lv) {
0292 uint16_t thisX0 = 0;
0293 if (useWeight) {
0294 double radl = hitPoint->GetMaterial()->GetRadlen();
0295 thisX0 = (uint16_t)floor(scaleRL * crystalDepth / radl);
0296 #ifdef plotDebug
0297 const std::string lvname = DD4hep2DDDName::noNameSpace(static_cast<std::string>(lv->GetName()));
0298 int k1 = (lvname.find("EFRY") != std::string::npos) ? 2 : 0;
0299 int k2 = (lvname.find("refl") != std::string::npos) ? 1 : 0;
0300 int kk = k1 + k2;
0301 double rz = (k1 == 0) ? (hitPoint->GetPosition()).rho() : std::abs((hitPoint->GetPosition()).z());
0302 edm::LogVerbatim("EcalSim") << lvname << " # " << k1 << ":" << k2 << ":" << kk << " rz " << rz << " D " << thisX0;
0303 g2L_[kk]->Fill(rz, thisX0);
0304 #endif
0305 #ifdef EDM_ML_DEBUG
0306 G4ThreeVector localPoint = setToLocal(hitPoint->GetPosition(), hitPoint->GetTouchable());
0307 edm::LogVerbatim("EcalSim") << lv->GetName() << " "
0308 << DD4hep2DDDName::noNameSpace(static_cast<std::string>(lv->GetName())) << " Global "
0309 << hitPoint->GetPosition() << ":" << (hitPoint->GetPosition()).rho() << " Local "
0310 << localPoint << " Crystal Length " << crystalLength << " Radl " << radl
0311 << " crystalDepth " << crystalDepth << " Index " << thisX0 << " : "
0312 << getLayerIDForTimeSim();
0313 #endif
0314 }
0315 return thisX0;
0316 }
0317
0318 uint16_t ECalSD::getLayerIDForTimeSim() {
0319 const double invLayerSize = 0.1;
0320 return (int)crystalDepth * invLayerSize;
0321 }
0322
0323 uint32_t ECalSD::setDetUnitId(const G4Step* aStep) {
0324 if (numberingScheme_.get() == nullptr) {
0325 return EBDetId(1, 1)();
0326 } else {
0327 getBaseNumber(aStep);
0328 return numberingScheme_->getUnitID(theBaseNumber);
0329 }
0330 }
0331
0332 void ECalSD::setNumberingScheme(EcalNumberingScheme* scheme) {
0333 if (scheme != nullptr) {
0334 edm::LogVerbatim("EcalSim") << "EcalSD: updates numbering scheme for " << GetName();
0335 numberingScheme_.reset(scheme);
0336 }
0337 }
0338
0339 void ECalSD::initMap() {
0340 std::vector<const G4LogicalVolume*> lvused;
0341 const G4LogicalVolumeStore* lvs = G4LogicalVolumeStore::GetInstance();
0342 std::map<const std::string, const G4LogicalVolume*> nameMap;
0343 for (auto lvi = lvs->begin(), lve = lvs->end(); lvi != lve; ++lvi)
0344 nameMap.emplace(DD4hep2DDDName::noNameSpace(static_cast<std::string>((*lvi)->GetName())), *lvi);
0345
0346 for (unsigned int it = 0; it < ecalSimParameters_->lvNames_.size(); ++it) {
0347 const std::string& matname = ecalSimParameters_->matNames_[it];
0348 const std::string& lvname = ecalSimParameters_->lvNames_[it];
0349 const G4LogicalVolume* lv = nameMap[lvname];
0350 int ibec = (lvname.find("EFRY") == std::string::npos) ? 0 : 1;
0351 int iref = (lvname.find("refl") == std::string::npos) ? 0 : 1;
0352 int type = (ibec + iref == 1) ? 1 : -1;
0353 if (depth1Name != " ") {
0354 if (strncmp(lvname.c_str(), depth1Name.c_str(), 4) == 0) {
0355 if (!any(useDepth1, lv)) {
0356 useDepth1.push_back(lv);
0357 #ifdef EDM_ML_DEBUG
0358 edm::LogVerbatim("EcalSim") << "ECalSD::initMap Logical Volume " << lvname << " in Depth 1 volume list";
0359 #endif
0360 }
0361 const G4LogicalVolume* lvr = nameMap[lvname + "_refl"];
0362 if (lvr != nullptr && !any(useDepth1, lvr)) {
0363 useDepth1.push_back(lvr);
0364 #ifdef EDM_ML_DEBUG
0365 edm::LogVerbatim("EcalSim") << "ECalSD::initMap Logical Volume " << lvname << "_refl"
0366 << " in Depth 1 volume list";
0367 #endif
0368 }
0369 }
0370 }
0371 if (depth2Name != " ") {
0372 if (strncmp(lvname.c_str(), depth2Name.c_str(), 4) == 0) {
0373 if (!any(useDepth2, lv)) {
0374 useDepth2.push_back(lv);
0375 #ifdef EDM_ML_DEBUG
0376 edm::LogVerbatim("EcalSim") << "ECalSD::initMap Logical Volume " << lvname << " in Depth 2 volume list";
0377 #endif
0378 }
0379 const G4LogicalVolume* lvr = nameMap[lvname + "_refl"];
0380 if (lvr != nullptr && !any(useDepth2, lvr)) {
0381 useDepth2.push_back(lvr);
0382 #ifdef EDM_ML_DEBUG
0383 edm::LogVerbatim("EcalSim") << "ECalSD::initMap Logical Volume " << lvname << "_refl"
0384 << " in Depth 2 volume list";
0385 #endif
0386 }
0387 }
0388 }
0389 if (lv != nullptr) {
0390 if (crystalMat.size() == matname.size() && !strcmp(crystalMat.c_str(), matname.c_str())) {
0391 if (!any(lvused, lv)) {
0392 lvused.push_back(lv);
0393 double dz = ecalSimParameters_->dzs_[it];
0394 xtalLMap.insert(std::pair<const G4LogicalVolume*, double>(lv, dz * type));
0395 lv = nameMap[lvname + "_refl"];
0396 if (lv != nullptr) {
0397 xtalLMap.insert(std::pair<const G4LogicalVolume*, double>(lv, -dz * type));
0398 }
0399 }
0400 } else {
0401 if (!any(noWeight, lv)) {
0402 noWeight.push_back(lv);
0403 #ifdef EDM_ML_DEBUG
0404 edm::LogVerbatim("EcalSim") << "ECalSD::initMap Logical Volume " << lvname << " Material " << matname
0405 << " in noWeight list";
0406 #endif
0407 }
0408 lv = nameMap[lvname];
0409 if (lv != nullptr && !any(noWeight, lv)) {
0410 noWeight.push_back(lv);
0411 #ifdef EDM_ML_DEBUG
0412 edm::LogVerbatim("EcalSim") << "ECalSD::initMap Logical Volume " << lvname << " Material " << matname
0413 << " in noWeight list";
0414 #endif
0415 }
0416 }
0417 }
0418 }
0419 #ifdef EDM_ML_DEBUG
0420 edm::LogVerbatim("EcalSim") << "ECalSD: Length Table:";
0421 int i = 0;
0422 for (auto ite : xtalLMap) {
0423 std::string name("Unknown");
0424 if (ite.first != nullptr)
0425 name = DD4hep2DDDName::noNameSpace(static_cast<std::string>((ite.first)->GetName()));
0426 edm::LogVerbatim("EcalSim") << " " << i << " " << ite.first << " " << name << " L = " << ite.second;
0427 ++i;
0428 }
0429 #endif
0430 }
0431
0432 double ECalSD::curve_LY(const G4LogicalVolume* lv) {
0433 double weight = 1.;
0434 if (ageingWithSlopeLY) {
0435
0436 if (crystalDepth >= -0.1 || crystalDepth <= crystalLength + 0.1)
0437 weight = ageing.calcLightCollectionEfficiencyWeighted(currentID[0].unitID(), crystalDepth / crystalLength);
0438 } else {
0439 double dapd = crystalLength - crystalDepth;
0440 if (dapd >= -0.1 || dapd <= crystalLength + 0.1) {
0441 if (dapd <= 100.)
0442 weight = 1.0 + slopeLY - dapd * 0.01 * slopeLY;
0443 } else {
0444 edm::LogWarning("EcalSim") << "ECalSD: light coll curve : wrong distance "
0445 << "to APD " << dapd << " crlength = " << crystalLength << ":" << crystalDepth
0446 << " crystal name = " << lv->GetName() << " "
0447 << DD4hep2DDDName::noNameSpace(static_cast<std::string>(lv->GetName()))
0448 << " z of localPoint = " << currentLocalPoint.z() << " take weight = " << weight;
0449 }
0450 }
0451 #ifdef EDM_ML_DEBUG
0452 edm::LogVerbatim("EcalSim") << "ECalSD: light coll curve : crlength = " << crystalLength << " Depth " << crystalDepth
0453 << " crystal name = " << lv->GetName() << " "
0454 << DD4hep2DDDName::noNameSpace(static_cast<std::string>(lv->GetName()))
0455 << " z of localPoint = " << currentLocalPoint.z() << " take weight = " << weight;
0456 #endif
0457 return weight;
0458 }
0459
0460 void ECalSD::getBaseNumber(const G4Step* aStep) {
0461 theBaseNumber.reset();
0462 const G4VTouchable* touch = aStep->GetPreStepPoint()->GetTouchable();
0463 int theSize = touch->GetHistoryDepth() + 1;
0464 if (theBaseNumber.getCapacity() < theSize)
0465 theBaseNumber.setSize(theSize);
0466
0467 if (theSize > 1) {
0468 for (int ii = 0; ii < theSize; ii++) {
0469 std::string name = DD4hep2DDDName::noNameSpace(static_cast<std::string>(touch->GetVolume(ii)->GetName()));
0470 theBaseNumber.addLevel(name, touch->GetReplicaNumber(ii));
0471 #ifdef EDM_ML_DEBUG
0472 edm::LogVerbatim("EcalSim") << "ECalSD::getBaseNumber(): Adding level " << ii << ": " << name << "["
0473 << touch->GetReplicaNumber(ii) << "]";
0474 #endif
0475 }
0476 }
0477 }
0478
0479 double ECalSD::getBirkL3(const G4Step* aStep) {
0480 double weight = 1.;
0481 const G4StepPoint* preStepPoint = aStep->GetPreStepPoint();
0482 double charge = preStepPoint->GetCharge();
0483
0484 if (charge != 0. && aStep->GetStepLength() > 0.) {
0485 const G4Material* mat = preStepPoint->GetMaterial();
0486 double density = mat->GetDensity();
0487 double dedx = aStep->GetTotalEnergyDeposit() / aStep->GetStepLength();
0488 double rkb = birk1 / density;
0489 if (dedx > 0) {
0490 weight = 1. - birkSlope * log(rkb * dedx);
0491 if (weight < birkCut)
0492 weight = birkCut;
0493 else if (weight > 1.)
0494 weight = 1.;
0495 }
0496 #ifdef EDM_ML_DEBUG
0497 edm::LogVerbatim("EcalSim") << "ECalSD::getBirkL3 in "
0498 << DD4hep2DDDName::noNameSpace(static_cast<std::string>(mat->GetName())) << " Charge "
0499 << charge << " dE/dx " << dedx << " Birk Const " << rkb << " Weight = " << weight
0500 << " dE " << aStep->GetTotalEnergyDeposit();
0501 #endif
0502 }
0503 return weight;
0504 }
0505
0506 bool ECalSD::isXtal(const G4LogicalVolume* lv) { return (xtalLMap.find(lv) != xtalLMap.end()); }