/
githubmirror
/
cmssw
Обзор
Документация
Войти
/
githubmirror
/
cmssw
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
SimTracker/TrackerMaterialAnalysis/plugins/TrackingMaterialAnalyser.cc
381 строка
16 KB
Matti Kortelainen
Use esConsumes in ListIds and TrackingMaterialAnalyser
04 ноя 2021, 22:29
04 ноя 2021, 22:29
6264e27
Код
Авторство
О чём код?
#include <iostream> // FIXME: switch to MessagLogger & friends #include <fstream> #include <sstream> #include <vector> #include <string> #include <stdexcept> #include <cstring> #include <cstdlib> #include <fmt/printf.h> #include "FWCore/Framework/interface/Event.h" #include "FWCore/Framework/interface/EventSetup.h" #include "FWCore/Framework/interface/ESTransientHandle.h" #include "FWCore/ParameterSet/interface/ParameterSet.h" #include "FWCore/Utilities/interface/EDMException.h" #include "DetectorDescription/Core/interface/DDFilteredView.h" #include "DetectorDescription/Core/interface/DDCompactView.h" #include "DetectorDescription/Core/interface/DDMaterial.h" #include "Geometry/Records/interface/IdealGeometryRecord.h" #include "SimDataFormats/ValidationFormats/interface/MaterialAccountingStep.h" #include "SimDataFormats/ValidationFormats/interface/MaterialAccountingTrack.h" #include "MaterialAccountingGroup.h" #include "TrackingMaterialAnalyser.h" #include "TrackingMaterialPlotter.h" //------------------------------------------------------------------------- TrackingMaterialAnalyser::TrackingMaterialAnalyser(const edm::ParameterSet& iPSet) { m_materialToken = consumes<std::vector<MaterialAccountingTrack> >(iPSet.getParameter<edm::InputTag>("MaterialAccounting")); m_dddToken = esConsumes(); m_groupNames = iPSet.getParameter<std::vector<std::string> >("Groups"); const std::string& splitmode = iPSet.getParameter<std::string>("SplitMode"); if (strcasecmp(splitmode.c_str(), "NearestLayer") == 0) { m_splitMode = NEAREST_LAYER; } else if (strcasecmp(splitmode.c_str(), "InnerLayer") == 0) { m_splitMode = INNER_LAYER; } else if (strcasecmp(splitmode.c_str(), "OuterLayer") == 0) { m_splitMode = OUTER_LAYER; } else { m_splitMode = UNDEFINED; throw edm::Exception(edm::errors::LogicError) << "Invalid SplitMode \"" << splitmode << "\". Acceptable values are \"NearestLayer\", \"InnerLayer\", \"OuterLayer\"."; } m_skipAfterLastDetector = iPSet.getParameter<bool>("SkipAfterLastDetector"); m_skipBeforeFirstDetector = iPSet.getParameter<bool>("SkipBeforeFirstDetector"); m_saveSummaryPlot = iPSet.getParameter<bool>("SaveSummaryPlot"); m_saveDetailedPlots = iPSet.getParameter<bool>("SaveDetailedPlots"); m_saveParameters = iPSet.getParameter<bool>("SaveParameters"); m_saveXml = iPSet.getParameter<bool>("SaveXML"); m_isHGCal = iPSet.getParameter<bool>("isHGCal"); m_isHFNose = iPSet.getParameter<bool>("isHFNose"); if (m_saveSummaryPlot) { if (m_isHGCal) { m_plotter = new TrackingMaterialPlotter(550., 300., 10); } else if (m_isHFNose) { m_plotter = new TrackingMaterialPlotter(1200., 350., 10); } else { m_plotter = new TrackingMaterialPlotter(300., 120., 10); } // 10x10 points per cm2 } else { m_plotter = nullptr; } } //------------------------------------------------------------------------- TrackingMaterialAnalyser::~TrackingMaterialAnalyser(void) { if (m_plotter) delete m_plotter; } //------------------------------------------------------------------------- void TrackingMaterialAnalyser::saveParameters(const char* name) { std::ofstream parameters(name); std::cout << std::endl; for (unsigned int i = 0; i < m_groups.size(); ++i) { MaterialAccountingGroup& layer = *(m_groups[i]); std::cout << layer.name() << std::endl; std::cout << fmt::sprintf("\tnumber of hits: %9d", layer.tracks()) << std::endl; std::cout << fmt::sprintf( "\tnormalized segment length: %9.1f ± %9.1f cm", layer.averageLength(), layer.sigmaLength()) << std::endl; std::cout << fmt::sprintf("\tnormalized radiation lengths: %9.3f ± %9.3f", layer.averageRadiationLengths(), layer.sigmaRadiationLengths()) << std::endl; std::cout << fmt::sprintf("\tnormalized energy loss: %6.5fe-03 ± %6.5fe-03 GeV", layer.averageEnergyLoss(), layer.sigmaEnergyLoss()) << std::endl; parameters << fmt::sprintf("%-20s\t%7d\t%5.1f ± %5.1f cm\t%6.4f ± %6.4f \t%6.4fe-03 ± %6.4fe-03 GeV", layer.name(), layer.tracks(), layer.averageLength(), layer.sigmaLength(), layer.averageRadiationLengths(), layer.sigmaRadiationLengths(), layer.averageEnergyLoss(), layer.sigmaEnergyLoss()) << std::endl; } std::cout << std::endl; parameters.close(); } //------------------------------------------------------------------------- void TrackingMaterialAnalyser::saveXml(const char* name) { std::ofstream xml(name); xml << "<?xml version=\"1.0\" encoding=\"utf-8\"?>" << std::endl; xml << "<Groups>" << std::endl; for (unsigned int i = 0; i < m_groups.size(); ++i) { MaterialAccountingGroup& layer = *(m_groups[i]); xml << " <Group name=\"" << layer.name() << "\">\n" << " <Parameter name=\"TrackerRadLength\" value=\"" << layer.averageRadiationLengths() << "\"/>\n" << " <Parameter name=\"TrackerXi\" value=\"" << layer.averageEnergyLoss() << "\"/>\n" << " </Group>\n" << std::endl; } xml << "</Groups>" << std::endl; } //------------------------------------------------------------------------- void TrackingMaterialAnalyser::saveLayerPlots() { for (unsigned int i = 0; i < m_groups.size(); ++i) { MaterialAccountingGroup& layer = *(m_groups[i]); layer.savePlots(); } } //------------------------------------------------------------------------- void TrackingMaterialAnalyser::endJob(void) { if (m_saveParameters) saveParameters("parameters"); if (m_saveXml) saveXml("parameters.xml"); if (m_saveDetailedPlots) saveLayerPlots(); if (m_saveSummaryPlot and m_plotter) { m_plotter->normalize(); m_plotter->draw(); } } //------------------------------------------------------------------------- //------------------------------------------------------------------------- void TrackingMaterialAnalyser::analyze(const edm::Event& event, const edm::EventSetup& setup) { using namespace edm; auto hDDD = setup.getHandle(m_dddToken); m_groups.reserve(m_groupNames.size()); // Initialize m_groups iff it has size equal to zero, so that we are // sure it will never be repopulated with the same entries over and // over again in the eventloop, at each call of the analyze method. if (m_groups.empty()) { for (unsigned int i = 0; i < m_groupNames.size(); ++i) m_groups.push_back(new MaterialAccountingGroup(m_groupNames[i], *hDDD)); LogInfo("TrackingMaterialAnalyser") << "TrackingMaterialAnalyser: List of the tracker groups: " << std::endl; for (unsigned int i = 0; i < m_groups.size(); ++i) LogInfo("TrackingMaterialAnalyser") << i << " TrackingMaterialAnalyser:\t" << m_groups[i]->info() << std::endl; } Handle<std::vector<MaterialAccountingTrack> > h_tracks; event.getByToken(m_materialToken, h_tracks); for (std::vector<MaterialAccountingTrack>::const_iterator t = h_tracks->begin(), end = h_tracks->end(); t != end; ++t) { MaterialAccountingTrack track(*t); split(track); } } //------------------------------------------------------------------- // split a track in segments, each associated to a sensitive detector // in a DetLayer; then, associate each step to one segment, splitting // the steps across the segment boundaries // // Nota Bene: this implementation assumes that the steps stored along // each track are consecutive and adjacent, and that no step can span // across 3 layers, since all steps should split at layer boundaries void TrackingMaterialAnalyser::split(MaterialAccountingTrack& track) { using namespace edm; // group sensitive detectors by their DetLayer std::vector<int> group(track.detectors().size()); for (unsigned int i = 0; i < track.detectors().size(); ++i) group[i] = findLayer(track.detectors()[i]); for (unsigned int i = 0; i < group.size(); ++i) if (group[i] > 0) LogInfo("TrackingMaterialAnalyser") << "For detector i: " << i << " index: " << group[i] << " R-ranges: " << m_groups[group[i] - 1]->getBoundingR().first << ", " << m_groups[group[i] - 1]->getBoundingR().second << group[i] << " Z-ranges: " << m_groups[group[i] - 1]->getBoundingZ().first << ", " << m_groups[group[i] - 1]->getBoundingZ().second << std::endl; unsigned int detectors = track.detectors().size(); if (detectors == 0) { // the track doesn't cross any active detector: // keep al material as unassigned if (m_plotter) for (unsigned int i = 1; i < track.steps().size(); ++i) m_plotter->plotSegmentUnassigned(track.steps()[i]); } else { const double TOLERANCE = 0.0001; // 1 um tolerance std::vector<double> limits(detectors + 2); // define the trivial limits if (m_skipBeforeFirstDetector) limits[0] = track.detectors()[0].m_curvilinearIn - TOLERANCE; else limits[0] = -TOLERANCE; if (m_skipAfterLastDetector) limits[detectors] = track.detectors()[detectors - 1].m_curvilinearOut + TOLERANCE; else limits[detectors] = track.summary().length() + TOLERANCE; limits[detectors + 1] = INFINITY; // this is probably no more needed, but doesn't harm... // pick the algorithm to define the non-trivial limits switch (m_splitMode) { // assign each segment to the the nearest layer // e.g. the material between pixel barrel 3 and TIB 1 will be split among the two case NEAREST_LAYER: for (unsigned int i = 1; i < detectors; ++i) { limits[i] = (track.detectors()[i - 1].m_curvilinearOut + track.detectors()[i].m_curvilinearIn) / 2.; } break; // assign each segment to the the inner layer // e.g. all material between pixel barrel 3 and TIB 1 will go into the pixel barrel case INNER_LAYER: for (unsigned int i = 1; i < detectors; ++i) limits[i] = track.detectors()[i].m_curvilinearIn - TOLERANCE; break; // assign each segment to the the outer layer // e.g. all material between pixel barrel 3 and TIB 1 will go into the TIB case OUTER_LAYER: for (unsigned int i = 1; i < detectors; ++i) limits[i] = track.detectors()[i - 1].m_curvilinearOut + TOLERANCE; break; case UNDEFINED: [[fallthrough]]; default: // throw something throw edm::Exception(edm::errors::LogicError) << "Invalid SplitMode"; } double begin = 0.; // beginning of step, along the track double end = 0.; // end of step, along the track unsigned int i = 1; // step conter // skip the material before the first layer while (end < limits[0]) { const MaterialAccountingStep& step = track.steps()[i++]; end = begin + step.length(); // do not account material before the first layer if (m_plotter) m_plotter->plotSegmentUnassigned(step); begin = end; } unsigned int index = 0; // which detector while (i < track.steps().size()) { const MaterialAccountingStep& step = track.steps()[i++]; end = begin + step.length(); if (begin > limits[detectors]) { // segment after last layer and skipping requested in configuation if (m_plotter) m_plotter->plotSegmentUnassigned(step); begin = end; continue; } // from here onwards we should be in the accountable region, either completely in a single layer: // limits[index] <= begin < end <= limits[index+1] // or possibly split between 2 layers // limits[index] < begin < limits[index+1] < end < limits[index+2] if (begin < limits[index] or end > limits[index + 2]) { // sanity check std::cerr << "MaterialAccountingTrack::split(): ERROR: internal logic error, expected " << limits[index] << " < " << begin << " < " << limits[index + 1] << std::endl; break; } if (limits[index] <= begin and end <= limits[index + 1]) { // step completely inside current detector range track.detectors()[index].account(step, begin, end); if (m_plotter) m_plotter->plotSegmentInLayer(step, group[index]); } else { // step shared beteewn two detectors, transition at limits[index+1] double fraction = (limits[index + 1] - begin) / (end - begin); assert(fraction < 1.); std::pair<MaterialAccountingStep, MaterialAccountingStep> parts = step.split(fraction); if (m_plotter) { if (index > 0) m_plotter->plotSegmentInLayer(parts.first, group[index]); else // track outside acceptance, keep as unassocated m_plotter->plotSegmentUnassigned(parts.first); if (index + 1 < detectors) m_plotter->plotSegmentInLayer(parts.second, group[index + 1]); else // track outside acceptance, keep as unassocated m_plotter->plotSegmentUnassigned(parts.second); } track.detectors()[index].account(parts.first, begin, limits[index + 1]); ++index; // next layer if (index < detectors) track.detectors()[index].account(parts.second, limits[index + 1], end); } begin = end; } } // add the material from each detector to its layer (if there is one and only one) for (unsigned int i = 0; i < track.detectors().size(); ++i) if (group[i] != 0) m_groups[group[i] - 1]->addDetector(track.detectors()[i]); // end of track: commit internal buffers and reset the m_groups internal state for a new track for (unsigned int i = 0; i < m_groups.size(); ++i) m_groups[i]->endOfTrack(); } //------------------------------------------------------------------------- // find the layer index (0: none, 1-3: PixelBarrel, // 4-7: TID, 8-13: TOB, 14-15,28-29: PixelEndcap, // 16-18,30-32: TID, 19-27,33-41: TEC) int TrackingMaterialAnalyser::findLayer(const MaterialAccountingDetector& detector) { int index = 0; size_t inside = 0; for (size_t i = 0; i < m_groups.size(); ++i) if (m_groups[i]->inside(detector)) { ++inside; index = i + 1; } if (inside == 0) { index = 0; std::cerr << "TrackingMaterialAnalyser::findLayer(...): ERROR: detector does not belong to any DetLayer" << std::endl; std::cerr << "TrackingMaterialAnalyser::findLayer(...): detector position: " << std::fixed << " (r: " << std::setprecision(1) << std::setw(5) << detector.position().perp() << ", z: " << std::setprecision(1) << std::setw(6) << detector.position().z() << ", phi: " << std::setprecision(3) << std::setw(6) << detector.position().phi() << ")" << std::endl; } if (inside > 1) { index = 0; std::cerr << "TrackingMaterialAnalyser::findLayer(...): ERROR: detector belongs to " << inside << " DetLayers" << std::endl; std::cerr << "TrackingMaterialAnalyser::findLayer(...): detector position: " << std::fixed << " (r: " << std::setprecision(1) << std::setw(5) << detector.position().perp() << ", z: " << std::setprecision(1) << std::setw(6) << detector.position().z() << ", phi: " << std::setprecision(3) << std::setw(6) << detector.position().phi() << ")" << std::endl; } return index; } //------------------------------------------------------------------------- // define as a plugin #include "FWCore/PluginManager/interface/ModuleDef.h" #include "FWCore/Framework/interface/MakerMacros.h" DEFINE_FWK_MODULE(TrackingMaterialAnalyser);