Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:08:25

0001 #ifndef SiPixel_GeometryInterface_h
0002 #define SiPixel_GeometryInterface_h
0003 // -*- C++ -*-
0004 //
0005 // Package:    SiPixelPhase1Common
0006 // Class:      GeometryInterface
0007 //
0008 // The histogram manager uses this class to gather information about a sample.
0009 // All geometry dependence goes here.
0010 //
0011 // Original Author: Marcel Schneider
0012 //
0013 
0014 #include "DataFormats/DetId/interface/DetId.h"
0015 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0016 #include "FWCore/Framework/interface/ConsumesCollector.h"
0017 #include "FWCore/Framework/interface/Event.h"
0018 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0019 
0020 #include "FWCore/Utilities/interface/ESGetToken.h"
0021 #include "FWCore/Utilities/interface/Transition.h"
0022 #include "CondFormats/SiPixelObjects/interface/SiPixelFedCablingMap.h"
0023 #include "CondFormats/DataRecord/interface/SiPixelFedCablingMapRcd.h"
0024 #include "Geometry/TrackerGeometryBuilder/interface/TrackerGeometry.h"
0025 #include "Geometry/Records/interface/TrackerDigiGeometryRecord.h"
0026 #include "DataFormats/TrackerCommon/interface/TrackerTopology.h"
0027 #include "Geometry/Records/interface/TrackerTopologyRcd.h"
0028 
0029 #include <functional>
0030 #include <map>
0031 #include <string>
0032 #include <array>
0033 
0034 class GeometryInterface {
0035 public:
0036   // an ID is produced by interning a string name.
0037   typedef int ID;
0038   // A column could have multiple IDs if it is a or-form.
0039   // Not used atm, makes many things much easier.
0040   typedef ID Column;
0041   typedef double Value;
0042   static const Value UNDEFINED;
0043 
0044   // Essentially a map backed by a vector (for the small counts here
0045   // this should always be faster). Most ops turned out to be not needed.
0046   typedef std::vector<std::pair<Column, Value>> Values;
0047 
0048   GeometryInterface(const edm::ParameterSet&,
0049                     edm::ConsumesCollector&&,
0050                     edm::Transition transition = edm::Transition::BeginRun);
0051 
0052   bool loaded() { return is_loaded; };
0053 
0054   // The hard work happens here.
0055   void load(edm::EventSetup const& iSetup);
0056 
0057   struct InterestingQuantities {
0058     // in this order the struct should fit 2 64bit words and is cheap to copy.
0059     const edm::Event* sourceEvent = nullptr;
0060     DetId sourceModule;
0061     int16_t col = 0;
0062     int16_t row = 0;
0063   };
0064 
0065   // This has to be fast, _should_ not malloc.
0066   void extractColumns(std::vector<Column> const& names, InterestingQuantities const& iq, Values& out) {
0067     out.clear();
0068     for (Column const& col : names) {
0069       auto val = extract(col, iq);
0070       out.push_back(val);
0071     }
0072   }
0073 
0074   // the pair return value is historical; it is only really needed with or-columns.
0075   // But it is cleaner to carry it around.
0076   std::pair<Column, Value> extract(Column const& col, InterestingQuantities const& iq) {
0077     assert(col != 0 || !"Extracting invalid column.");
0078     ID id = col;
0079     assert(ID(extractors.size()) > id || !"extractors vector too small!");
0080     auto& ex = extractors[id];
0081     if (!ex) {  // we have never heard about this. This is a typo for sure.
0082       edm::LogError("GeometryInterface") << "Undefined column used: " << unintern(id) << ". Check your spelling.\n";
0083     } else {
0084       auto val = ex(iq);
0085       if (val != UNDEFINED) {
0086         return std::make_pair(Column{id}, val);
0087       }
0088     }
0089     return std::make_pair(col, UNDEFINED);
0090   }
0091 
0092   Value extract(ID id, DetId did, edm::Event* ev = nullptr, int16_t col = 0, int16_t row = 0) {
0093     InterestingQuantities iq = {ev, did, col, row};
0094     return extractors[id](iq);
0095   }
0096 
0097   // TODO: for Phase0 (and maybe also Phase2) this should include the 4 corners
0098   // of each ROC (or the *correct* corners of the respective modules).
0099   std::vector<InterestingQuantities> const& allModules() { return all_modules; }
0100 
0101   Value maxValue(ID id) { return max_value[id]; };
0102   Value minValue(ID id) { return min_value[id]; };
0103   Value binWidth(ID id) { return bin_width[id]; };
0104 
0105   // turn string into an ID, adding it if needed.
0106   ID intern(std::string const& id) {
0107     auto it = ids.find(id);
0108     if (it == ids.end()) {
0109       ids[id] = ++max_id;
0110       extractors.resize(max_id + 1);
0111     }
0112     return ids[id];
0113   };
0114 
0115   // turn an ID back into a string. Only for pretty output (including histo
0116   // labels), so it can be slow (though intern() does not have to be fast
0117   // either).
0118   std::string unintern(ID id) {
0119     for (auto& e : ids)
0120       if (e.second == id)
0121         return e.first;
0122     return "INVALID";
0123   }
0124 
0125   std::string pretty(Column col) { return unintern(col); }
0126 
0127   std::string formatValue(Column, Value);
0128 
0129 private:
0130   void loadFromTopology(const TrackerGeometry&, const TrackerTopology&, const edm::ParameterSet&);
0131   void loadFromSiPixelCoordinates(const TrackerGeometry&,
0132                                   const TrackerTopology&,
0133                                   const SiPixelFedCablingMap&,
0134                                   const edm::ParameterSet&);
0135   void loadTimebased(const edm::ParameterSet& iConfig);
0136   void loadModuleLevel(const edm::ParameterSet& iConfig);
0137   void loadFEDCabling(const SiPixelFedCablingMap*);
0138 
0139   const edm::ParameterSet iConfig;
0140 
0141   edm::ESGetToken<TrackerGeometry, TrackerDigiGeometryRecord> trackerGeometryToken_;
0142   edm::ESGetToken<TrackerTopology, TrackerTopologyRcd> trackerTopologyToken_;
0143   // When converting this module to use esConsumes I preserved the previous behavior.
0144   // In one place a configurable label is allowed when getting SiPixelFedCablingMap
0145   // and in another place it always assumes an empty label. I am not sure if this is
0146   // actually correct (seems strange). Maybe it does not matter as in all the configurations
0147   // I could find in the repository the parameter was an empty string... An expert who
0148   // understands this might want to fix this or eliminate this comment if the behavior is
0149   // correct.
0150   edm::ESGetToken<SiPixelFedCablingMap, SiPixelFedCablingMapRcd> siPixelFedCablingMapToken_;
0151   edm::ESGetToken<SiPixelFedCablingMap, SiPixelFedCablingMapRcd> labeledSiPixelFedCablingMapToken_;
0152   std::string cablingMapLabel_;
0153 
0154   bool is_loaded = false;
0155 
0156   // This holds closures that compute the column values in step1.
0157   // can be a Vector since ids are dense.
0158   std::vector<std::function<Value(InterestingQuantities const& iq)>> extractors;
0159   // quantity range if it is known. Can be UNDEFINED, in this case booking will
0160   // determine the range. Map for ease of use.
0161   std::map<ID, Value> max_value;
0162   std::map<ID, Value> min_value;
0163   std::map<ID, Value> bin_width;
0164 
0165   // cache of pre-formatted values. Can be pre-populated while loading
0166   // (used for Pixel*Name)
0167   std::map<std::pair<Column, Value>, std::string> format_value;
0168 
0169   void addExtractor(ID id,
0170                     std::function<Value(InterestingQuantities const& iq)> func,
0171                     Value min = UNDEFINED,
0172                     Value max = UNDEFINED,
0173                     Value binwidth = 1) {
0174     max_value[id] = max;
0175     min_value[id] = min;
0176     bin_width[id] = binwidth;
0177     extractors[id] = func;
0178   }
0179 
0180   std::vector<InterestingQuantities> all_modules;
0181 
0182   // interning table. Maps string IDs to a dense set of integer IDs
0183   std::map<std::string, ID> ids{std::make_pair(std::string("INVALID"), ID(0))};
0184   ID max_id = 0;
0185 };
0186 
0187 #endif