/
githubmirror
/
cmssw
Обзор
Документация
Войти
/
githubmirror
/
cmssw
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
SimTracker/TrackerMaterialAnalysis/plugins/TrackingMaterialProducer.cc
376 строк
18 KB
Sunanda
Code check
11 дек 2023, 04:00
11 дек 2023, 04:00
626bec7
Код
Авторство
О чём код?
#include <iostream> // FIXME: switch to MessagLogger & friends #include <vector> #include <string> #include <cassert> #include <exception> #include <tuple> #include "FWCore/Framework/interface/Event.h" #include "FWCore/Framework/interface/EventSetup.h" #include "FWCore/Framework/interface/ESHandle.h" #include "FWCore/ParameterSet/interface/ParameterSet.h" #include "FWCore/MessageLogger/interface/MessageLogger.h" #include "SimG4Core/Notification/interface/BeginOfJob.h" #include "SimG4Core/Notification/interface/BeginOfEvent.h" #include "SimG4Core/Notification/interface/BeginOfTrack.h" #include "SimG4Core/Notification/interface/EndOfTrack.h" #include "DataFormats/GeometryVector/interface/GlobalPoint.h" // GEANT4 #include "G4Step.hh" #include "G4Track.hh" #include "G4VSolid.hh" #include "G4LogicalVolumeStore.hh" #include "G4TouchableHistory.hh" #include "G4VPhysicalVolume.hh" #include "G4AffineTransform.hh" #include <DD4hep/Filter.h> #include "TrackingMaterialProducer.h" // Uncomment the following #define directive to have the full list of // volumes known to G4 printed to LogInfo("TrackingMaterialProducer") #define DEBUG_G4_VOLUMES using namespace CLHEP; using edm::LogInfo; // missing from GEANT4 < 9.0 : G4LogicalVolumeStore::GetVolume( name ) static const G4LogicalVolume* GetVolume(const std::string& name) { const G4LogicalVolumeStore* lvs = G4LogicalVolumeStore::GetInstance(); #ifdef DEBUG_G4_VOLUMES for (G4LogicalVolumeStore::const_iterator volume = lvs->begin(); volume != lvs->end(); ++volume) LogInfo("TrackingMaterialProducer") << "TrackingMaterialProducer: G4 registered volumes " << (*volume)->GetName() << std::endl; #endif for (G4LogicalVolumeStore::const_iterator volume = lvs->begin(); volume != lvs->end(); ++volume) { if ((const std::string)(dd4hep::dd::noNamespace((*volume)->GetName())) == name) return (*volume); } return nullptr; } // missing from GEANT4 : G4TouchableHistory::GetTransform( depth ) static inline const G4AffineTransform& GetTransform(const G4TouchableHistory* touchable, int depth) { return touchable->GetHistory()->GetTransform(touchable->GetHistory()->GetDepth() - depth); } // navigate up the hierarchy of volumes until one with an attached sensitive detector is found // return a tuple holding // - pointer to the first (deepest) sensitive G4VPhysicalVolume // - how may steps up in the hierarchy it is (0 is the starting volume) // if no sensitive detector is found, return a NULL pointer and 0 std::tuple<const G4VPhysicalVolume*, int> GetSensitiveVolume(const G4VTouchable* touchable) { int depth = touchable->GetHistoryDepth(); for (int level = 0; level < depth; ++level) { // 0 is self const G4VPhysicalVolume* volume = touchable->GetVolume(level); if (volume->GetLogicalVolume()->GetSensitiveDetector() != nullptr) { return std::make_tuple(volume, level); } } return std::tuple<const G4VPhysicalVolume*, int>(nullptr, 0); } //------------------------------------------------------------------------- TrackingMaterialProducer::TrackingMaterialProducer(const edm::ParameterSet& iPSet) { edm::ParameterSet config = iPSet.getParameter<edm::ParameterSet>("TrackingMaterialProducer"); m_selectedNames = config.getParameter<std::vector<std::string> >("SelectedVolumes"); m_primaryTracks = config.getParameter<bool>("PrimaryTracksOnly"); m_txtOutFile = config.getUntrackedParameter<std::string>("txtOutFile"); m_hgcalzfront = config.getParameter<double>("hgcalzfront"); m_tracks = nullptr; m_track_volume = nullptr; produces<std::vector<MaterialAccountingTrack> >(); output_file_ = new TFile("radLen_vs_eta_fromProducer.root", "RECREATE"); output_file_->cd(); radLen_vs_eta_ = new TProfile("radLen", "radLen", 250., -5., 5., 0, 10.); //Check if HGCal volumes are selected isHGCal = false; //if (std::find(m_selectedNames.begin(), m_selectedNames.end(), "CALOECTSRear") != m_selectedNames.end()) { if (std::find(m_selectedNames.begin(), m_selectedNames.end(), "HGCal") != m_selectedNames.end()) { isHGCal = true; } //Check if HFNose volumes are selected isHFNose = false; if (std::find(m_selectedNames.begin(), m_selectedNames.end(), "HFNose") != m_selectedNames.end()) { isHFNose = true; } if (isHGCal or isHFNose) { outVolumeZpositionTxt.open(m_txtOutFile.c_str(), std::ios::out); } } //------------------------------------------------------------------------- TrackingMaterialProducer::~TrackingMaterialProducer(void) {} //------------------------------------------------------------------------- void TrackingMaterialProducer::update(const EndOfJob* event) { radLen_vs_eta_->Write(); output_file_->Close(); } //------------------------------------------------------------------------- void TrackingMaterialProducer::update(const BeginOfJob* event) { // INFO LogInfo("TrackingMaterialProducer") << "TrackingMaterialProducer: List of the selected volumes: " << std::endl; for (std::vector<std::string>::const_iterator volume_name = m_selectedNames.begin(); volume_name != m_selectedNames.end(); ++volume_name) { const G4LogicalVolume* volume = GetVolume(*volume_name); if (volume) { LogInfo("TrackingMaterialProducer") << "TrackingMaterialProducer: " << *volume_name << std::endl; m_selectedVolumes.push_back(volume); } else { // FIXME: throw an exception ? std::cerr << "TrackingMaterialProducer::update(const BeginOfJob*): WARNING: selected volume \"" << *volume_name << "\" not found in geometry " << std::endl; } } } //------------------------------------------------------------------------- void TrackingMaterialProducer::update(const BeginOfEvent* event) { m_tracks = new std::vector<MaterialAccountingTrack>(); } //------------------------------------------------------------------------- void TrackingMaterialProducer::update(const BeginOfTrack* event) { m_track.reset(); m_track_volume = nullptr; // prevent secondary tracks from propagating G4Track* track = const_cast<G4Track*>((*event)()); if (m_primaryTracks and track->GetParentID() != 0) { track->SetTrackStatus(fStopAndKill); } //For the HGCal case: //In the beginning of each track, the track will first hit an HGCAL volume and it will //save the upper z volume boundary. So, the low boundary of the first //volume is never saved. Here we give the low boundary of the first volume. //This can be found by asking first to run not on 'HGCal' volume below but //on 'CALOECTSRear', which at the moment of this writing it contains //HGCalService, HGCal and thermal screen. You should run Fireworks to //check if these naming conventions and volumes are valid in the future. //Then, check the VolumesZPosition.txt file to see where CEService ends and //put that number in hgcalzfront. Keep in mind to run on the desired volume above here: //https://github.com/cms-sw/cmssw/blob/master/SimTracker/TrackerMaterialAnalysis/plugins/TrackingMaterialProducer.cc#L95 //and to replace the volume name of the material first hit at the file creation line below if (isHGCal && track->GetTrackStatus() != fStopAndKill && fabs(track->GetMomentum().eta()) > outerHGCalEta && fabs(track->GetMomentum().eta()) < innerHGCalEta) { if (track->GetMomentum().eta() > 0.) { outVolumeZpositionTxt << "Air " << m_hgcalzfront << " " << 0 << " " << 0 << " " << 0 << " " << 0 << std::endl; } else if (track->GetMomentum().eta() <= 0.) { outVolumeZpositionTxt << "Air " << -m_hgcalzfront << " " << 0 << " " << 0 << " " << 0 << " " << 0 << std::endl; } } //For the HFnose case: //restrict the outher radius to eta 3.3 since there is HGCAL shadowing //restrict the innner radius to eta 4 since it's non projective if (isHFNose && track->GetTrackStatus() != fStopAndKill && fabs(track->GetMomentum().eta()) > outerHFnoseEta && fabs(track->GetMomentum().eta()) < innerHFnoseEta) { if (track->GetMomentum().eta() > 0.) { outVolumeZpositionTxt << "Polyethylene " << m_hgcalzfront << " " << 0 << " " << 0 << " " << 0 << " " << 0 << std::endl; } else if (track->GetMomentum().eta() <= 0.) { outVolumeZpositionTxt << "Polyethylene " << -m_hgcalzfront << " " << 0 << " " << 0 << " " << 0 << " " << 0 << std::endl; } } } bool TrackingMaterialProducer::isSelectedFast(const G4TouchableHistory* touchable) { for (int d = touchable->GetHistoryDepth() - 1; d >= 0; --d) { if (std::find(m_selectedNames.begin(), m_selectedNames.end(), (std::string)(dd4hep::dd::noNamespace(touchable->GetVolume(d)->GetName()))) != m_selectedNames.end()) return true; } return false; } //------------------------------------------------------------------------- void TrackingMaterialProducer::update(const G4Step* step) { const G4TouchableHistory* touchable = static_cast<const G4TouchableHistory*>(step->GetTrack()->GetTouchable()); if (not isSelectedFast(touchable)) { LogInfo("TrackingMaterialProducer") << "TrackingMaterialProducer:\t[...] skipping " << touchable->GetVolume()->GetName() << std::endl; return; } // material and step proterties const G4Material* material = touchable->GetVolume()->GetLogicalVolume()->GetMaterial(); double length = step->GetStepLength() / cm; // mm -> cm double X0 = material->GetRadlen() / cm; // mm -> cm double Ne = material->GetElectronDensity() * cm3; // 1/mm3 -> 1/cm3 double Xi = Ne / 6.0221415e23 * 0.307075 / 2; // MeV / cm double radiationLengths = length / X0; // double energyLoss = length * Xi / 1000.; // GeV //double energyLoss = step->GetDeltaEnergy()/MeV; should we use this?? G4ThreeVector globalPosPre = step->GetPreStepPoint()->GetPosition(); G4ThreeVector globalPosPost = step->GetPostStepPoint()->GetPosition(); GlobalPoint globalPositionIn(globalPosPre.x() / cm, globalPosPre.y() / cm, globalPosPre.z() / cm); // mm -> cm GlobalPoint globalPositionOut(globalPosPost.x() / cm, globalPosPost.y() / cm, globalPosPost.z() / cm); // mm -> cm G4StepPoint* prePoint = step->GetPreStepPoint(); G4StepPoint* postPoint = step->GetPostStepPoint(); const CLHEP::Hep3Vector& postPos = postPoint->GetPosition(); //Go below only in HGCal case if (isHGCal or isHFNose) { //A step never spans across boundaries: geometry or physics define the end points //If the step is limited by a boundary, the post-step point stands on the //boundary and it logically belongs to the next volume. if (postPoint->GetStepStatus() == fGeomBoundary && fabs(postPoint->GetMomentum().eta()) > outerHGCalEta && fabs(postPoint->GetMomentum().eta()) < innerHGCalEta) { //Post point position is the low z edge of the new volume, or the upper for the prepoint volume. //So, premat - postz - posteta - postR - premattotalenergylossEtable - premattotalenergylossEfull //Observe the two zeros at the end which in the past where set to emCalculator.GetDEDX and //emCalculator.ComputeTotalDEDX but decided not to be used. Will save the structure though for the script. outVolumeZpositionTxt << prePoint->GetMaterial()->GetName() << " " << postPos.z() << " " << postPoint->GetMomentum().eta() << " " << sqrt(postPos.x() * postPos.x() + postPos.y() * postPos.y()) << " " << 0 << " " << 0 << std::endl; } if (postPoint->GetStepStatus() == fGeomBoundary && fabs(postPoint->GetMomentum().eta()) > outerHFnoseEta && fabs(postPoint->GetMomentum().eta()) < innerHFnoseEta) { outVolumeZpositionTxt << prePoint->GetMaterial()->GetName() << " " << postPos.z() << " " << postPoint->GetMomentum().eta() << " " << sqrt(postPos.x() * postPos.x() + postPos.y() * postPos.y()) << " " << 0 << " " << 0 << std::endl; } } //end of isHGCal or HFnose if // check for a sensitive detector bool enter_sensitive = false; bool leave_sensitive = false; double cosThetaPre = 0.0; double cosThetaPost = 0.0; int level = 0; const G4VPhysicalVolume* sensitive = nullptr; GlobalPoint position; std::tie(sensitive, level) = GetSensitiveVolume(touchable); if (sensitive) { const G4VSolid& solid = *touchable->GetSolid(level); const G4AffineTransform& transform = GetTransform(touchable, level); G4ThreeVector pos = transform.Inverse().TransformPoint(G4ThreeVector(0., 0., 0.)); position = GlobalPoint(pos.x() / cm, pos.y() / cm, pos.z() / cm); // mm -> cm G4ThreeVector localPosPre = transform.TransformPoint(globalPosPre); EInside statusPre = solid.Inside(localPosPre); if (statusPre == kSurface) { enter_sensitive = true; G4ThreeVector globalDirPre = step->GetPreStepPoint()->GetMomentumDirection(); G4ThreeVector localDirPre = transform.TransformAxis(globalDirPre); G4ThreeVector normalPre = solid.SurfaceNormal(localPosPre); cosThetaPre = normalPre.cosTheta(-localDirPre); } G4ThreeVector localPosPost = transform.TransformPoint(globalPosPost); EInside statusPost = solid.Inside(localPosPost); if (statusPost == kSurface) { leave_sensitive = true; G4ThreeVector globalDirPost = step->GetPostStepPoint()->GetMomentumDirection(); G4ThreeVector localDirPost = transform.TransformAxis(globalDirPost); G4ThreeVector normalPost = solid.SurfaceNormal(localPosPost); cosThetaPost = normalPost.cosTheta(localDirPost); } } // update track accounting if (enter_sensitive) { if (m_track_volume != nullptr) { edm::LogWarning("TrackingMaterialProducer") << "Entering volume " << sensitive << " while inside volume " << m_track_volume << ". Something is inconsistent"; m_track.reset(); } m_track_volume = sensitive; m_track.enterDetector(position, cosThetaPre); } m_track.step(MaterialAccountingStep(length, radiationLengths, energyLoss, globalPositionIn, globalPositionOut)); if (leave_sensitive) { if (m_track_volume != sensitive) { edm::LogWarning("TrackingMaterialProducer") << "Leaving volume " << sensitive << " while inside volume " << m_track_volume << ". Something is inconsistent"; m_track.reset(); } else m_track.leaveDetector(cosThetaPost); m_track_volume = nullptr; } if (sensitive) LogInfo("TrackingMaterialProducer") << "Track was near sensitive volume " << sensitive->GetName() << std::endl; else LogInfo("TrackingMaterialProducer") << "Track was near non-sensitive volume " << touchable->GetVolume()->GetName() << std::endl; LogInfo("TrackingMaterialProducer") << "Step length: " << length << " cm\n" << "globalPreStep(r,z): (" << globalPositionIn.perp() << ", " << globalPositionIn.z() << ") cm\n" << "globalPostStep(r,z): (" << globalPositionOut.perp() << ", " << globalPositionOut.z() << ") cm\n" << "position(r,z): (" << position.perp() << ", " << position.z() << ") cm\n" << "Radiation lengths: " << radiationLengths << " \t\t(X0: " << X0 << " cm)\n" << "Energy loss: " << energyLoss << " MeV \t(Xi: " << Xi << " MeV/cm)\n" << "Track was " << (enter_sensitive ? "entering " : "in none ") << "sensitive volume\n" << "Track was " << (leave_sensitive ? "leaving " : "in none ") << "sensitive volume\n"; } //------------------------------------------------------------------------- void TrackingMaterialProducer::update(const EndOfTrack* event) { const G4Track* track = (*event)(); if (m_primaryTracks and track->GetParentID() != 0) return; radLen_vs_eta_->Fill(track->GetMomentum().eta(), m_track.summary().radiationLengths()); m_tracks->push_back(m_track); // LogInfo LogInfo("TrackingMaterialProducer") << "TrackingMaterialProducer: this track took " << m_track.steps().size() << " steps, and passed through " << m_track.detectors().size() << " sensitive detectors" << std::endl; LogInfo("TrackingMaterialProducer") << "TrackingMaterialProducer: track length: " << m_track.summary().length() << " cm" << std::endl; LogInfo("TrackingMaterialProducer") << "TrackingMaterialProducer: radiation lengths: " << m_track.summary().radiationLengths() << std::endl; LogInfo("TrackingMaterialProducer") << "TrackingMaterialProducer: energy loss: " << m_track.summary().energyLoss() << " MeV" << std::endl; } //------------------------------------------------------------------------- void TrackingMaterialProducer::produce(edm::Event& iEvent, const edm::EventSetup& iSetup) { // transfer ownership to the Event std::unique_ptr<std::vector<MaterialAccountingTrack> > tracks(m_tracks); iEvent.put(std::move(tracks)); m_tracks = nullptr; } //------------------------------------------------------------------------- bool TrackingMaterialProducer::isSelected(const G4VTouchable* touchable) { for (size_t i = 0; i < m_selectedVolumes.size(); ++i) if (m_selectedVolumes[i]->IsAncestor(touchable->GetVolume()) or m_selectedVolumes[i] == touchable->GetVolume()->GetLogicalVolume()) return true; return false; } //------------------------------------------------------------------------- // define as a plugin #include "SimG4Core/Watcher/interface/SimWatcherFactory.h" #include "FWCore/Framework/interface/MakerMacros.h" DEFINE_SIMWATCHER(TrackingMaterialProducer);