diff --git a/DPGAnalysis/MuonTools/BuildFile.xml b/DPGAnalysis/MuonTools/BuildFile.xml new file mode 100644 index 0000000000000..6977478d3e4af --- /dev/null +++ b/DPGAnalysis/MuonTools/BuildFile.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/DPGAnalysis/MuonTools/interface/MuBaseFlatTableProducer.h b/DPGAnalysis/MuonTools/interface/MuBaseFlatTableProducer.h new file mode 100644 index 0000000000000..4f9bf88862b7c --- /dev/null +++ b/DPGAnalysis/MuonTools/interface/MuBaseFlatTableProducer.h @@ -0,0 +1,73 @@ +#ifndef Mu_MuBaseFlatTableProducer_h +#define Mu_MuBaseFlatTableProducer_h + +/** \class MuBaseFlatTableProducer MuBaseFlatTableProducer.h DPGAnalysis/MuonTools/src/MuBaseFlatTableProducer.h + * + * Helper class defining the generic interface of a FlatTableProducer + * + * \author C. Battilana (INFN BO) + * + * + */ + +#include "DPGAnalysis/MuonTools/interface/MuNtupleUtils.h" + +#include "FWCore/Framework/interface/stream/EDProducer.h" +#include "FWCore/Framework/interface/ConsumesCollector.h" + +#include "DataFormats/NanoAOD/interface/FlatTable.h" + +#include + +class MuBaseFlatTableProducer : public edm::stream::EDProducer<> { +public: + /// Constructor + explicit MuBaseFlatTableProducer(const edm::ParameterSet &); + + /// Configure event setup for each run + void beginRun(const edm::Run &run, const edm::EventSetup &config) final; + + /// Fill ntuples event by event + void produce(edm::Event &, const edm::EventSetup &) final; + + /// Empty, needed by interface + void endRun(const edm::Run &, const edm::EventSetup &) final {} + +protected: + /// The label name of the FlatTableProducer + std::string m_name; + + /// Get info from the ES by run + virtual void getFromES(const edm::Run &run, const edm::EventSetup &environment) {} + + /// Get info from the ES for a given event + virtual void getFromES(const edm::EventSetup &environment) {} + + /// Fill ntuple + virtual void fillTable(edm::Event &ev) = 0; + + /// Definition of default values for int variables + static constexpr int DEFAULT_INT_VAL{-999}; + + /// Definition of default values for int8 variables + static constexpr int8_t DEFAULT_INT8_VAL{-99}; + + /// Definition of default values for positive int variables + static constexpr int DEFAULT_INT_VAL_POS{-1}; + + /// Definition of default values for float variables + static constexpr double DEFAULT_DOUBLE_VAL{-999.0}; + + /// Definition of default values for positive float variables + static constexpr double DEFAULT_DOUBLE_VAL_POS{-1.0}; + + template + void addColumn(std::unique_ptr &table, + const std::string name, + const std::vector &vec, + const std::string descr) { + table->template addColumn>(name, vec, descr); + } +}; + +#endif diff --git a/DPGAnalysis/MuonTools/interface/MuDigiBaseProducer.h b/DPGAnalysis/MuonTools/interface/MuDigiBaseProducer.h new file mode 100644 index 0000000000000..27d161fa233c5 --- /dev/null +++ b/DPGAnalysis/MuonTools/interface/MuDigiBaseProducer.h @@ -0,0 +1,118 @@ +#ifndef MuonTools_MuDigiBaseProducer_h +#define MuonTools_MuDigiBaseProducer_h + +/** \class MuDigiBaseProducer MuDigiBaseProducer.h DPGAnalysis/MuonTools/src/MuDigiBaseProducer.h + * + * Helper class defining the generic interface of a muon digi Producer + * + * \author C. Battilana (INFN BO) + * + * + */ + +#include "DataFormats/MuonData/interface/MuonDigiCollection.h" +#include "PhysicsTools/NanoAOD/interface/SimpleFlatTableProducer.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" + +#include +#include +#include + +template +class MuDigiBaseProducer : public SimpleFlatTableProducerBase> { + using COLLECTION = MuonDigiCollection; + + using IntDetVar = FuncVariable, int>; + using UIntDetVar = FuncVariable, unsigned int>; + using Int8DetVar = FuncVariable, int8_t>; + using UInt8DetVar = FuncVariable, uint8_t>; + + std::vector>> detIdVars_; + +public: + MuDigiBaseProducer(edm::ParameterSet const ¶ms) : SimpleFlatTableProducerBase(params) { + const auto &varCfgs = params.getParameter("detIdVariables"); + const auto &varNames = varCfgs.getParameterNamesForType(); + + std::transform(varNames.begin(), varNames.end(), std::back_inserter(detIdVars_), [&](const auto &name) { + const edm::ParameterSet &varCfg = varCfgs.getParameter(name); + const std::string &type = varCfg.getParameter("type"); + + std::unique_ptr> detVarPtr; + + if (type == "int") { + detVarPtr = std::move(std::make_unique(name, varCfg)); + } else if (type == "uint") { + detVarPtr = std::move(std::make_unique(name, varCfg)); + } else if (type == "int8") { + detVarPtr = std::move(std::make_unique(name, varCfg)); + } else if (type == "uint8") { + detVarPtr = std::move(std::make_unique(name, varCfg)); + } else { + throw cms::Exception("Configuration", "unsupported type " + type + " for variable " + name); + } + + return detVarPtr; + }); + } + + ~MuDigiBaseProducer() override {} + + static void fillDescriptions(edm::ConfigurationDescriptions &descriptions) { + edm::ParameterSetDescription desc = SimpleFlatTableProducerBase::baseDescriptions(); + + edm::ParameterSetDescription variable; + edm::Comment comType{"the c++ type of the branch in the flat table"}; + edm::Comment comPrecision{"the precision with which to store the value in the flat table"}; + + variable.add("expr")->setComment("a function to define the content of the branch in the flat table"); + variable.add("doc")->setComment("few words description of the branch content"); + + variable.ifValue(edm::ParameterDescription("type", "int", true, comType), + edm::allowedValues("int", "uint", "int8", "uint8")); + + edm::ParameterSetDescription variables; + + variables.setComment("a parameters set to define all variable taken form detId to fill the flat table"); + + edm::ParameterWildcard variableWildCard{"*", edm::RequireZeroOrMore, true, variable}; + variables.addNode(variableWildCard); + + desc.add("detIdVariables", variables); + + descriptions.addWithDefaultLabel(desc); + } + + std::unique_ptr fillTable(const edm::Event &iEvent, + const edm::Handle &prod) const override { + std::vector digis; + std::vector detIds; + std::list detIdObjs; // CB needed to store DetIds (they are transient) + + if (prod.isValid()) { + auto detIdIt = prod->begin(); + auto detIdEnd = prod->end(); + + for (; detIdIt != detIdEnd; ++detIdIt) { + const auto &[detId, range] = (*detIdIt); + detIdObjs.push_back(detId); + std::fill_n(std::back_inserter(detIds), range.second - range.first, &detIdObjs.back()); + std::transform(range.first, range.second, std::back_inserter(digis), [](const auto &digi) { return &digi; }); + } + } + + auto table = std::make_unique(digis.size(), this->name_, false, this->extension_); + + for (const auto &var : this->vars_) { + var->fill(digis, *table); + } + + for (const auto &var : detIdVars_) { + var->fill(detIds, *table); + } + + return table; + } +}; + +#endif diff --git a/DPGAnalysis/MuonTools/interface/MuLocalRecoBaseProducer.h b/DPGAnalysis/MuonTools/interface/MuLocalRecoBaseProducer.h new file mode 100644 index 0000000000000..318ba3c60477e --- /dev/null +++ b/DPGAnalysis/MuonTools/interface/MuLocalRecoBaseProducer.h @@ -0,0 +1,212 @@ +#ifndef MuonTools_MuRecObjBaseProducer_h +#define MuonTools_MuRecObjBaseProducer_h + +/** \class MuRecObjBaseProducer MuRecObjBaseProducer.h DPGAnalysis/MuonTools/src/MuRecObjBaseProducer.h + * + * Helper class defining the generic interface of a muon digi Producer + * + * \author C. Battilana (INFN BO) + * + * + */ + +#include "DataFormats/Common/interface/RangeMap.h" +#include "DataFormats/Common/interface/ClonePolicy.h" +#include "DataFormats/Common/interface/OwnVector.h" + +#include "PhysicsTools/NanoAOD/interface/SimpleFlatTableProducer.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "DataFormats/TrackingRecHit/interface/RecSegment.h" + +#include "FWCore/Framework/interface/ESHandle.h" + +#include "FWCore/Utilities/interface/ESGetToken.h" +#include "FWCore/Framework/interface/ConsumesCollector.h" +#include "Geometry/CommonDetUnit/interface/GlobalTrackingGeometry.h" +#include "Geometry/Records/interface/GlobalTrackingGeometryRecord.h" + +#include +#include +#include +#include + +template +class MuRecObjBaseProducer + : public SimpleFlatTableProducerBase>> { + using COLLECTION = edm::RangeMap>; + + edm::ESGetToken m_token; + edm::ESHandle m_geometry; + + using IntDetVar = FuncVariable, int>; + using UIntDetVar = FuncVariable, unsigned int>; + using Int8DetVar = FuncVariable, int8_t>; + using UInt8DetVar = FuncVariable, uint8_t>; + + std::vector>> detIdVars_; + + using GlobalPosVar = FuncVariable, float>; + using GlobalDirVar = FuncVariable, float>; + + std::vector>> globalPosVars_; + std::vector>> globalDirVars_; + +public: + MuRecObjBaseProducer(edm::ParameterSet const ¶ms) + : SimpleFlatTableProducerBase(params), m_token{this->template esConsumes()} { + auto varCfgs = params.getParameter("detIdVariables"); + auto varNames = varCfgs.getParameterNamesForType(); + + std::transform(varNames.begin(), varNames.end(), std::back_inserter(detIdVars_), [&](const auto &name) { + const edm::ParameterSet &varCfg = varCfgs.getParameter(name); + const std::string &type = varCfg.getParameter("type"); + + std::unique_ptr> detVarPtr; + + if (type == "int") { + detVarPtr = std::move(std::make_unique(name, varCfg)); // CB can improve? + } else if (type == "uint") { + detVarPtr = std::move(std::make_unique(name, varCfg)); + } else if (type == "int8") { + detVarPtr = std::move(std::make_unique(name, varCfg)); + } else if (type == "uint8") { + detVarPtr = std::move(std::make_unique(name, varCfg)); + } else { + throw cms::Exception("Configuration", "unsupported type " + type + " for variable " + name); + } + + return detVarPtr; + }); + + varCfgs = params.getParameter("globalPosVariables"); + varNames = varCfgs.getParameterNamesForType(); + + std::transform(varNames.begin(), varNames.end(), std::back_inserter(globalPosVars_), [&](const auto &name) { + return std::make_unique(name, varCfgs.getParameter(name)); + }); + + if constexpr (std::is_base_of_v) { + varCfgs = params.getParameter("globalDirVariables"); + varNames = varCfgs.getParameterNamesForType(); + + std::transform(varNames.begin(), varNames.end(), std::back_inserter(globalDirVars_), [&](const auto &name) { + return std::make_unique(name, varCfgs.getParameter(name)); + }); + } + } + + ~MuRecObjBaseProducer() override {} + + static void fillDescriptions(edm::ConfigurationDescriptions &descriptions) { + edm::ParameterSetDescription desc = SimpleFlatTableProducerBase::baseDescriptions(); + + auto baseDescription = []() { + edm::ParameterSetDescription varBase; + + varBase.add("expr")->setComment("a function to define the content of the branch in the flat table"); + varBase.add("doc")->setComment("few words description of the branch content"); + + return varBase; + }; + + auto fullDescription = [](auto const &var, std::string const label) { + edm::ParameterSetDescription fullDesc; + + edm::ParameterWildcard detIdVarWildCard{"*", edm::RequireZeroOrMore, true, var}; + fullDesc.setComment("a parameters set to define all " + label + " variables to the flat table"); + fullDesc.addNode(detIdVarWildCard); + + return fullDesc; + }; + + auto detIdVar{baseDescription()}; + auto globalGeomVar{baseDescription()}; + + edm::Comment comType{"the c++ type of the branch in the flat table"}; + detIdVar.ifValue(edm::ParameterDescription{"type", "int", true, comType}, + edm::allowedValues("int", "uint", "int8", "uint8")); + + edm::Comment comPrecision{"the precision with which to store the value in the flat table"}; + globalGeomVar.addOptionalNode(edm::ParameterDescription{"precision", true, comPrecision}, false); + + desc.add("detIdVariables", fullDescription(detIdVar, "DetId")); + desc.add("globalPosVariables", fullDescription(globalGeomVar, "Global Position")); + + if constexpr (std::is_base_of_v) { + desc.add("globalDirVariables", fullDescription(globalGeomVar, "Global Direction")); + } + + descriptions.addWithDefaultLabel(desc); + } + + std::unique_ptr fillTable(const edm::Event &iEvent, + const edm::Handle &product) const override { + std::vector objs; + std::vector detIds; + std::vector globalPositions; + std::vector globalDirections; + + // CB needed to store DetIds, global points and vectors (they are transient) + std::list detIdObjs; + std::list globalPointObjs; + std::list globalVectorObjs; + + if (product.isValid()) { + auto detIdIt = product->id_begin(); + const auto detIdEnd = product->id_end(); + + for (; detIdIt != detIdEnd; ++detIdIt) { + const auto &range = product->get(*detIdIt); + const GeomDet *geomDet = m_geometry->idToDet(*detIdIt); + + detIdObjs.push_back(*detIdIt); + std::fill_n(std::back_inserter(detIds), range.second - range.first, &detIdObjs.back()); + + for (auto objIt{range.first}; objIt != range.second; ++objIt) { + objs.push_back(&(*objIt)); + globalPointObjs.push_back(geomDet->toGlobal(objIt->localPosition())); + globalPositions.push_back(&globalPointObjs.back()); + if constexpr (std::is_base_of_v) { + globalVectorObjs.push_back(geomDet->toGlobal(objIt->localDirection())); + globalDirections.push_back(&globalVectorObjs.back()); + } + } + } + } + + auto table = std::make_unique(objs.size(), this->name_, false, this->extension_); + + for (const auto &var : this->vars_) { + var->fill(objs, *table); + } + + for (const auto &var : detIdVars_) { + var->fill(detIds, *table); + } + + for (const auto &var : globalPosVars_) { + var->fill(globalPositions, *table); + } + + if constexpr (std::is_base_of_v) { + for (const auto &var : globalDirVars_) { + var->fill(globalDirections, *table); + } + } + + return table; + } + + void produce(edm::Event &event, const edm::EventSetup &environment) override { + edm::Handle src; + event.getByToken(this->src_, src); + + m_geometry = environment.getHandle(m_token); + std::unique_ptr out = fillTable(event, src); + out->setDoc(this->doc_); + + event.put(std::move(out)); + } +}; + +#endif diff --git a/DPGAnalysis/MuonTools/interface/MuNtupleUtils.h b/DPGAnalysis/MuonTools/interface/MuNtupleUtils.h new file mode 100644 index 0000000000000..71116cf55956d --- /dev/null +++ b/DPGAnalysis/MuonTools/interface/MuNtupleUtils.h @@ -0,0 +1,135 @@ +#ifndef MuNtuple_MuNtupleUtils_h +#define MuNtuple_MuNtupleUtils_h + +/** \class MuNtupleUtils MuNtupleUtils.h MuDPGAnalysis/MuNtuples/src/MuNtupleUtils.h + * + * A set of helper classes class to handle : + * - Handing of InputTags and tokens + * - DB information from edm::EventSetup + * - Conversion between L1T trigger primitive coordinates and CMS global ones + * + * \author C. Battilana - INFN (BO) + * \author L. Giuducci - INFN (BO) + * + * + */ + +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Utilities/interface/InputTag.h" +#include "FWCore/Framework/interface/ESHandle.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/Framework/interface/ConsumesCollector.h" +#include "FWCore/MessageLogger/interface/MessageLogger.h" + +#include "Geometry/DTGeometry/interface/DTGeometry.h" +#include "Geometry/Records/interface/MuonGeometryRecord.h" + +#include +#include + +class L1MuDTChambPhDigi; +class L1Phase2MuDTPhDigi; + +namespace nano_mu { + + template + class EDTokenHandle { + public: + /// Constructor + EDTokenHandle(const edm::ParameterSet& config, edm::ConsumesCollector&& collector, std::string name) + : m_name{name}, m_inputTag{config.getParameter(name)} { + if (m_inputTag.label() != "none") { + m_token = collector.template consumes(m_inputTag); + } + } + + /// Conditional getter + /// checks whether a token is valid and if + /// retireving the data collection succeded + auto conditionalGet(const edm::Event& ev) const { + edm::Handle collection; + + if (!m_token.isUninitialized() && !ev.getByToken(m_token, collection)) + edm::LogError("") << "[EDTokenHandle]::conditionalGet: " << m_inputTag.label() + << " collection does not exist !!!"; + + return collection; + } + + private: + std::string m_name; + edm::InputTag m_inputTag; + edm::EDGetTokenT m_token; + }; + + template + class ESTokenHandle { + public: + /// Constructor + ESTokenHandle(edm::ConsumesCollector&& collector, const std::string& label = "") + : m_token{collector.template esConsumes(edm::ESInputTag{"", label})} {} + + ///Get Handle from ES + void getFromES(const edm::EventSetup& environment) { m_handle = environment.getHandle(m_token); } + + /// Check validity + bool isValid() { return m_handle.isValid(); } + + /// Return handle + T const* operator->() { return m_handle.product(); } + + private: + edm::ESGetToken m_token; + edm::ESHandle m_handle; + }; + + class DTTrigGeomUtils { + public: + struct chambCoord { + double pos{}; + double dir{}; + }; + + /// Constructor + DTTrigGeomUtils(edm::ConsumesCollector&& collector, bool dirInDeg = true); + + /// Return local position and direction in chamber RF - legacy + chambCoord trigToReco(const L1MuDTChambPhDigi* trig); + + /// Return local position and direction in chamber RF - analytical method + chambCoord trigToReco(const L1Phase2MuDTPhDigi* trig); + + /// Checks id the chamber has positive RF; + bool hasPosRF(int wh, int sec) { return wh > 0 || (wh == 0 && sec % 4 > 1); }; + + /// Update EventSetup information + void getFromES(const edm::Run& run, const edm::EventSetup& environment) { + m_dtGeom.getFromES(environment); + for (int i_st = 0; i_st != 4; ++i_st) { + const DTChamberId chId(-2, i_st + 1, 4); + const DTChamber* chamb = m_dtGeom->chamber(chId); + const DTSuperLayer* sl1 = chamb->superLayer(DTSuperLayerId(chId, 1)); + const DTSuperLayer* sl3 = chamb->superLayer(DTSuperLayerId(chId, 3)); + m_zsl1[i_st] = chamb->surface().toLocal(sl1->position()).z(); + m_zsl3[i_st] = chamb->surface().toLocal(sl3->position()).z(); + m_zcn[i_st] = 0.5 * (m_zsl1[i_st] + m_zsl3[i_st]); + } + }; + + private: + ESTokenHandle m_dtGeom; + + std::array m_zcn; + std::array m_zsl1; + std::array m_zsl3; + + static constexpr double PH1_PHI_R = 4096.; + static constexpr double PH1_PHIB_R = 512.; + + static constexpr double PH2_PHI_R = 65536. / 0.8; + static constexpr double PH2_PHIB_R = 2048. / 1.4; + }; + +} // namespace nano_mu + +#endif diff --git a/DPGAnalysis/MuonTools/plugins/BuildFile.xml b/DPGAnalysis/MuonTools/plugins/BuildFile.xml new file mode 100644 index 0000000000000..ccd1c6c40c741 --- /dev/null +++ b/DPGAnalysis/MuonTools/plugins/BuildFile.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/DPGAnalysis/MuonTools/plugins/MuCSCTnPFlatTableProducer.cc b/DPGAnalysis/MuonTools/plugins/MuCSCTnPFlatTableProducer.cc new file mode 100644 index 0000000000000..368e2474733c8 --- /dev/null +++ b/DPGAnalysis/MuonTools/plugins/MuCSCTnPFlatTableProducer.cc @@ -0,0 +1,1031 @@ +/** \class MuCSCTnPFlatTableProducer MuCSCTnPFlatTableProducer.cc DPGAnalysis/MuonTools/plugins/MuCSCTnPFlatTableProducer.cc + * + * Helper class : the CSC Tag and probe segment efficiency filler + * + * \author M. Herndon (UW Madison) + * + * + */ + +#include "DataFormats/DetId/interface/DetId.h" +#include "DataFormats/CSCRecHit/interface/CSCSegment.h" +#include "DataFormats/CSCRecHit/interface/CSCSegmentCollection.h" +#include "DataFormats/MuonDetId/interface/CSCDetId.h" + +#include "DataFormats/MuonReco/interface/MuonSelectors.h" +#include "DataFormats/TrackingRecHit/interface/TrackingRecHitFwd.h" + +#include "DataFormats/Math/interface/deltaR.h" + +#include "TString.h" +#include "TRegexp.h" + +#include + +#include +#include + +#include "DPGAnalysis/MuonTools/interface/MuBaseFlatTableProducer.h" + +#include "FWCore/Framework/interface/ESHandle.h" + +#include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h" +#include "FWCore/ParameterSet/interface/ParameterSetDescription.h" + +#include "Geometry/CSCGeometry/interface/CSCGeometry.h" +#include "Geometry/Records/interface/MuonGeometryRecord.h" + +#include "DataFormats/MuonReco/interface/Muon.h" +#include "DataFormats/MuonReco/interface/MuonFwd.h" +#include "DataFormats/MuonReco/interface/MuonIsolation.h" +#include "DataFormats/MuonReco/interface/MuonPFIsolation.h" + +#include "DataFormats/TrackReco/interface/Track.h" +#include "DataFormats/TrackReco/interface/TrackFwd.h" + +#include "DataFormats/VertexReco/interface/Vertex.h" +#include "DataFormats/VertexReco/interface/VertexFwd.h" + +#include "DataFormats/Common/interface/TriggerResults.h" +#include "DataFormats/HLTReco/interface/TriggerEvent.h" +#include "DataFormats/HLTReco/interface/TriggerObject.h" +#include "HLTrigger/HLTcore/interface/HLTConfigProvider.h" + +#include "RecoMuon/TrackingTools/interface/MuonServiceProxy.h" +#include "TrackingTools/TransientTrack/interface/TransientTrackBuilder.h" +#include "TrackingTools/Records/interface/TransientTrackRecord.h" +#include "TrackingTools/TrajectoryState/interface/TrajectoryStateOnSurface.h" +#include "TrackingTools/GeomPropagators/interface/Propagator.h" + +class MuonServiceProxy; + +class MuCSCTnPFlatTableProducer : public MuBaseFlatTableProducer { +public: + /// Constructor + MuCSCTnPFlatTableProducer(const edm::ParameterSet&); + + /// Fill descriptors + static void fillDescriptions(edm::ConfigurationDescriptions&); + +protected: + /// Fill tree branches for a given events + void fillTable(edm::Event&) final; + + /// Get info from the ES by run + void getFromES(const edm::Run&, const edm::EventSetup&) final; + + /// Get info from the ES for a given event + void getFromES(const edm::EventSetup&) final; + +private: + static constexpr Float_t MEZ[6] = {601.3, 696.11, 696.11, 827.56, 936.44, 1025.9}; + + /// Tokens + nano_mu::EDTokenHandle m_muToken; + nano_mu::EDTokenHandle m_trackToken; + + nano_mu::EDTokenHandle m_cscSegmentToken; + + nano_mu::EDTokenHandle> m_primaryVerticesToken; + + nano_mu::EDTokenHandle m_trigResultsToken; + nano_mu::EDTokenHandle m_trigEventToken; + + /// Name of the triggers used by muon filler for trigger matching + std::string m_trigName; + std::string m_isoTrigName; + + /// Handles to geometry, detector and specialized objects + /// CSC Geometry + nano_mu::ESTokenHandle m_cscGeometry; + + /// Muon service proxy + std::unique_ptr m_muonSP; + + /// Transient Track Builder + nano_mu::ESTokenHandle m_transientTrackBuilder; + + // Extrapolator to cylinder + edm::ESHandle propagatorAlong; + edm::ESHandle propagatorOpposite; + edm::ESHandle theBField; + + /// HLT config provider + HLTConfigProvider m_hltConfig; + + /// Indices of the triggers used by muon filler for trigger matching + std::vector m_trigIndices; + std::vector m_isoTrigIndices; + + /// Selection functions + //bool muonTagSelection(const reco::Muon & muon,edm::Handle> tracks); + bool trackProbeSelection(const reco::Track& track, edm::Handle>); + bool muonTagSelection(const reco::Muon&); + //bool trackProbeSelection(const reco::Track & track); + bool zSelection(const reco::Muon&, const reco::Track&); + + // Calculation functions + double zMass(const reco::Track&, const reco::Muon&); + double calcDeltaR(double, double, double, double); + double iso(const reco::Track&, edm::Handle>); + + // Track extrapolation and segment match functions + TrajectoryStateOnSurface surfExtrapTrkSam(const reco::Track&, double); + FreeTrajectoryState freeTrajStateMuon(const reco::Track&); + + UChar_t ringCandidate(Int_t iiStation, Int_t station, Float_t feta, Float_t phi); + UChar_t thisChamberCandidate(UChar_t station, UChar_t ring, Float_t phi); + + TrajectoryStateOnSurface* matchTTwithCSCSeg(const reco::Track&, + edm::Handle, + CSCSegmentCollection::const_iterator&, + CSCDetId&); + Float_t TrajectoryDistToSeg(TrajectoryStateOnSurface, CSCSegmentCollection::const_iterator); + std::vector GetEdgeAndDistToGap(const reco::Track&, CSCDetId&); + Float_t YDistToHVDeadZone(Float_t, Int_t); + + /// The variables holding + /// the T&P related information + + unsigned int m_nZCands; // the # of digis (size of all following vectors) + + double _trackIso; + double _muonIso; + double _zMass; + + bool hasTrigger(std::vector&, + const trigger::TriggerObjectCollection&, + edm::Handle&, + const reco::Muon&); + + float computeTrkIso(const reco::MuonIsolation&, float); + float computePFIso(const reco::MuonPFIsolation&, float); +}; + +MuCSCTnPFlatTableProducer::MuCSCTnPFlatTableProducer(const edm::ParameterSet& config) + : MuBaseFlatTableProducer(config), + m_muToken{config, consumesCollector(), "muonSrc"}, + m_trackToken{config, consumesCollector(), "trackSrc"}, + m_cscSegmentToken{config, consumesCollector(), "cscSegmentSrc"}, + m_primaryVerticesToken{config, consumesCollector(), "primaryVerticesSrc"}, + m_trigResultsToken{config, consumesCollector(), "trigResultsSrc"}, + m_trigEventToken{config, consumesCollector(), "trigEventSrc"}, + m_trigName{config.getParameter("trigName")}, + m_isoTrigName{config.getParameter("isoTrigName")}, + m_cscGeometry{consumesCollector()}, + m_muonSP{std::make_unique(config.getParameter("ServiceParameters"), + consumesCollector())}, + m_transientTrackBuilder{consumesCollector(), "TransientTrackBuilder"} { + produces(); +} + +void MuCSCTnPFlatTableProducer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { + edm::ParameterSetDescription desc; + + desc.add("name", "cscTnP"); + desc.add("muonSrc", edm::InputTag{"muons"}); + desc.add("trackSrc", edm::InputTag{"generalTracks"}); + desc.add("cscSegmentSrc", edm::InputTag{"cscSegments"}); + desc.add("primaryVerticesSrc", edm::InputTag{"offlinePrimaryVertices"}); + + desc.add("trigEventSrc", edm::InputTag{"hltTriggerSummaryAOD::HLT"}); + desc.add("trigResultsSrc", edm::InputTag{"TriggerResults::HLT"}); + + desc.add("trigName", "none"); + desc.add("isoTrigName", "HLT_IsoMu2*"); + + desc.setAllowAnything(); + + descriptions.addWithDefaultLabel(desc); +} + +void MuCSCTnPFlatTableProducer::getFromES(const edm::Run& run, const edm::EventSetup& environment) { + m_cscGeometry.getFromES(environment); + + bool changed{true}; + m_hltConfig.init(run, environment, "HLT", changed); + + const bool enableWildcard{true}; + + TString tName = TString(m_trigName); + TRegexp tNamePattern = TRegexp(tName, enableWildcard); + + for (unsigned iPath = 0; iPath < m_hltConfig.size(); ++iPath) { + TString pathName = TString(m_hltConfig.triggerName(iPath)); + if (pathName.Contains(tNamePattern)) + m_trigIndices.push_back(static_cast(iPath)); + } + + tName = TString(m_isoTrigName); + tNamePattern = TRegexp(tName, enableWildcard); + + for (unsigned iPath = 0; iPath < m_hltConfig.size(); ++iPath) { + TString pathName = TString(m_hltConfig.triggerName(iPath)); + if (pathName.Contains(tNamePattern)) + m_isoTrigIndices.push_back(static_cast(iPath)); + } +} + +void MuCSCTnPFlatTableProducer::getFromES(const edm::EventSetup& environment) { + m_transientTrackBuilder.getFromES(environment); + m_muonSP->update(environment); +} + +void MuCSCTnPFlatTableProducer::fillTable(edm::Event& ev) { + unsigned int m_nZCands = 0; // the # of digis (size of all following vectors) + + // Muon track tag variables + std::vector m_muonPt; // muon pT [GeV/c] + std::vector m_muonPhi; // muon phi [rad] + std::vector m_muonEta; // muon eta + std::vector m_muonPtError; // muon pT [GeV/c] error + std::vector m_muonPhiError; // muon phi [rad] error + std::vector m_muonEtaError; // muon eta error + std::vector m_muonCharge; // muon charge + std::vector m_muonDXY; // muon dXY + std::vector m_muonDZ; // muon dZ + std::vector m_muonTrkHits; // muon track Hits + std::vector m_muonChi2; // muon Chi2 + std::vector m_muonTrigger; // muon trigger + std::vector m_muonIso; // track Iso + + // Track probe variabes + std::vector m_trackPt; // track pT [GeV/c] + std::vector m_trackP; // track P [GeV/c] + std::vector m_trackPhi; // track phi [rad] + std::vector m_trackEta; // track eta + std::vector m_trackPtError; // track pT [GeV/c] error + std::vector m_trackPhiError; // track phi [rad] error + std::vector m_trackEtaError; // track eta error + std::vector m_trackCharge; // track charge + std::vector m_trackDXY; // track dXY + std::vector m_trackDZ; // track dZ + std::vector m_trackTrkHits; // track Hits + std::vector m_trackChi2; // track Chi2 + std::vector m_trackIso; // track Iso + + // Z and global variables + std::vector m_zMass; // z mass + std::vector m_dRTrackMuon; // dR between the track and muon + std::vector m_numberOfPrimaryVertices; // Number of primary Vertices + + // CSC chamber information, station encoded in vector + std::vector m_chamberEndcap; // chamber endcap + // station encoded in array index + std::array, 4> m_chamberRing; // chamber Ring + std::array, 4> m_chamberChamber; // chamber Chamber + std::array, 4> m_chamberLayer; // Segment layer information + + // Track intersection variables + std::array, 4> m_ttIntLocalX; // track trajector intersection local X on stations 1-4 + std::array, 4> m_ttIntLocalY; // track trajector intersection local Y on stations 1-4 + std::array, 4> m_ttIntLocalErrorX; // track trajector intersection local X on stations 1-4 + std::array, 4> m_ttIntLocalErrorY; // track trajector intersection local Y on stations 1-4 + std::array, 4> m_ttIntLocalW; // track trajector intersection local Wire on stations 1-4 + std::array, 4> m_ttIntLocalS; // track trajector intersection local Strip on stations 1-4 + std::array, 4> m_ttIntEta; // track trajector intersection Eta stations 1-4 + + // Track intersection fiducial information + + std::array, 4> + m_ttDistToEdge; // track trajector intersection distance to edge, neg is with chamber, on stations 1-4 + std::array, 4> m_ttDistToHVGap; // track trajector intersection distance to HV GAP on stations 1-4 + + // Segment location variables + std::array, 4> m_segLocalX; // segment local X on stations 1-4 + std::array, 4> m_segLocalY; // segment local Y on stations 1-4 + std::array, 4> m_segLocalErrorX; // segment local X error on stations 1-4 + std::array, 4> m_segLocalErrorY; // segment local Y error on stations 1-4 + + // track intersection segment residuals variables + std::array, 4> + m_ttIntSegResidualLocalX; // track trajector intersection Segment residual local X on stations 1-4 + std::array, 4> + m_ttIntSegResidualLocalY; // track trajector intersection Segment residuallocal Y on stations 1-4 + + auto&& propagator_along = m_muonSP->propagator("SteppingHelixPropagatorAlong"); + auto&& propagator_opposite = m_muonSP->propagator("SteppingHelixPropagatorOpposite"); + + propagatorAlong = propagator_along; + propagatorOpposite = propagator_opposite; + + theBField = m_muonSP->magneticField(); + + auto muons = m_muToken.conditionalGet(ev); + auto tracks = m_trackToken.conditionalGet(ev); + auto segments = m_cscSegmentToken.conditionalGet(ev); + auto primaryVertices = m_primaryVerticesToken.conditionalGet(ev); + + auto triggerResults = m_trigResultsToken.conditionalGet(ev); + auto triggerEvent = m_trigEventToken.conditionalGet(ev); + + if (muons.isValid() && tracks.isValid() && segments.isValid() && primaryVertices.isValid() && + m_transientTrackBuilder.isValid()) { + for (const auto& muon : (*muons)) { + if (!muonTagSelection(muon)) + continue; + + bool muonTrigger = false; + if (triggerResults.isValid() && triggerEvent.isValid()) { + const auto& triggerObjects = triggerEvent->getObjects(); + muonTrigger = (hasTrigger(m_isoTrigIndices, triggerObjects, triggerEvent, muon) || + hasTrigger(m_trigIndices, triggerObjects, triggerEvent, muon)); + } + + for (const auto& track : (*tracks)) { + if (!trackProbeSelection(track, tracks)) + continue; + if (!zSelection(muon, track)) + continue; + //std::cout << "Z candidate found: " << _zMass << " track eta: " << track.eta() << std::endl; + //std::cout.flush(); + m_nZCands++; + + m_trackPt.push_back(track.pt()); + m_trackP.push_back(track.p()); + m_trackEta.push_back(track.eta()); + m_trackPhi.push_back(track.phi()); + m_trackPtError.push_back(track.pt()); + m_trackEtaError.push_back(track.eta()); + m_trackPhiError.push_back(track.phi()); + m_trackCharge.push_back(track.charge()); + m_trackDXY.push_back(track.dxy()); + m_trackDZ.push_back(track.dz()); + m_trackTrkHits.push_back(track.hitPattern().numberOfValidTrackerHits()); + m_trackChi2.push_back(track.normalizedChi2()); + m_trackIso.push_back(_trackIso); + + m_muonPt.push_back(muon.track()->pt()); + m_muonPhi.push_back(muon.track()->phi()); + m_muonEta.push_back(muon.track()->eta()); + m_muonPtError.push_back(muon.track()->ptError()); + m_muonPhiError.push_back(muon.track()->phiError()); + m_muonEtaError.push_back(muon.track()->etaError()); + m_muonCharge.push_back(muon.charge()); + m_muonDXY.push_back(muon.track()->dxy()); + m_muonDZ.push_back(muon.track()->dz()); + m_muonTrkHits.push_back(muon.track()->hitPattern().numberOfValidTrackerHits()); + m_muonChi2.push_back(muon.track()->normalizedChi2()); + m_muonIso.push_back(computeTrkIso(muon.isolationR03(), muon.pt())); + m_muonTrigger.push_back(muonTrigger); + + m_zMass.push_back(_zMass); + double_t dR = calcDeltaR(track.eta(), muon.eta(), track.phi(), muon.phi()); + //double_t dR = 1.0; + m_dRTrackMuon.push_back(dR); + const reco::VertexCollection& vertices = *primaryVertices.product(); + m_numberOfPrimaryVertices.push_back(vertices.size()); + + bool ec = (track.eta() > 0); + UChar_t endcapCSC = ec ? 0 : 1; + m_chamberEndcap.push_back(endcapCSC * 1); + + Int_t iiStationFail = 0; + for (int iiStationZ = 0; iiStationZ < 6; iiStationZ++) { + UChar_t stationCSC = iiStationZ > 2 ? iiStationZ - 2 : 0; + UChar_t ringCSC = 0; + TrajectoryStateOnSurface tsos = surfExtrapTrkSam(track, ec ? MEZ[iiStationZ] : -MEZ[iiStationZ]); + + if (tsos.isValid()) { + Float_t trkEta = tsos.globalPosition().eta(), trkPhi = tsos.globalPosition().phi(); + ringCSC = ringCandidate(iiStationZ, stationCSC + 1, trkEta, trkPhi); + + if (ringCSC) { + UChar_t chamberCSC = thisChamberCandidate(stationCSC + 1, ringCSC, track.phi()) - 1; + CSCDetId Layer3id = CSCDetId(endcapCSC + 1, stationCSC + 1, ringCSC, chamberCSC + 1, 3); + CSCDetId Layer0Id = CSCDetId(endcapCSC + 1, + stationCSC + 1, + ringCSC, + chamberCSC + 1, + 0); //layer 0 is the mid point of the chamber. It is not a real layer. + // !!!!! need to fix Layer0Id problem with ME1/1 here + + const BoundPlane& Layer3Surface = m_cscGeometry->idToDet(Layer3id)->surface(); + + tsos = surfExtrapTrkSam(track, Layer3Surface.position().z()); + + if (tsos.isValid()) { + // Fill track intersection denominator information + LocalPoint localTTIntPoint = Layer3Surface.toLocal(tsos.freeState()->position()); + const CSCLayerGeometry* layerGeoma = m_cscGeometry->chamber(Layer0Id)->layer(3)->geometry(); + const CSCLayerGeometry* layerGeomb = m_cscGeometry->chamber(Layer0Id)->layer(4)->geometry(); + + m_chamberRing[stationCSC].push_back(ringCSC); + m_chamberChamber[stationCSC].push_back(chamberCSC); + m_ttIntLocalX[stationCSC].push_back(localTTIntPoint.x()); + m_ttIntLocalY[stationCSC].push_back(localTTIntPoint.y()); + m_ttIntLocalW[stationCSC].push_back( + (layerGeoma->nearestWire(localTTIntPoint) + layerGeomb->nearestWire(localTTIntPoint)) / 2.0); + m_ttIntLocalS[stationCSC].push_back( + (layerGeoma->strip(localTTIntPoint) + layerGeomb->strip(localTTIntPoint)) / 2.0); + m_ttIntEta[stationCSC].push_back(trkEta); + + // Errors are those of the track intersection, chosing the plane and exact geomentry is performed in the function + Float_t CSCProjEdgeDist = -9999.0; + Float_t ttIntLocalErrorX = -9999.0; + Float_t CSCDyProjHVGap = 9999.0; + Float_t ttIntLocalErrorY = -9999.0; + for (Int_t ly = 1; ly < 7; ly++) { + CSCDetId Layerid = CSCDetId(endcapCSC + 1, stationCSC + 1, ringCSC, chamberCSC + 1, ly); + std::vector EdgeAndDistToGap(GetEdgeAndDistToGap( + track, Layerid)); //values: 1-edge;2-err of edge;3-disttogap;4-err of dist to gap + if (EdgeAndDistToGap[0] > CSCProjEdgeDist) { + CSCProjEdgeDist = EdgeAndDistToGap[0]; + ttIntLocalErrorX = EdgeAndDistToGap[1]; + } + if (EdgeAndDistToGap[2] < CSCDyProjHVGap) { + CSCDyProjHVGap = EdgeAndDistToGap[2]; + ttIntLocalErrorY = EdgeAndDistToGap[3]; + } + } + m_ttDistToEdge[stationCSC].push_back(CSCProjEdgeDist); + m_ttDistToHVGap[stationCSC].push_back(CSCDyProjHVGap); + m_ttIntLocalErrorX[stationCSC].push_back(ttIntLocalErrorX); + m_ttIntLocalErrorY[stationCSC].push_back(ttIntLocalErrorY); + + // now we have a local point for comparison to segments + CSCSegmentCollection::const_iterator cscSegOut; + TrajectoryStateOnSurface* TrajToSeg = matchTTwithCSCSeg(track, segments, cscSegOut, Layer3id); + + if (TrajToSeg == nullptr) { + // fill Null Num + m_segLocalX[stationCSC].push_back(-9999.0); + m_segLocalY[stationCSC].push_back(-9999.0); + m_segLocalErrorX[stationCSC].push_back(0.0); + m_segLocalErrorY[stationCSC].push_back(0.0); + + m_ttIntSegResidualLocalX[stationCSC].push_back(-9990.0); + m_ttIntSegResidualLocalY[stationCSC].push_back(-9990.0); + + m_chamberLayer[stationCSC].push_back(-9); + + continue; + } + + LocalPoint localSegmentPoint = (*cscSegOut).localPosition(); + LocalError localSegErr = (*cscSegOut).localPositionError(); + + m_segLocalX[stationCSC].push_back(localSegmentPoint.x()); + m_segLocalY[stationCSC].push_back(localSegmentPoint.y()); + m_segLocalErrorX[stationCSC].push_back(sqrt(localSegErr.xx())); + m_segLocalErrorY[stationCSC].push_back(sqrt(localSegErr.yy())); + + m_ttIntSegResidualLocalX[stationCSC].push_back(localTTIntPoint.x() - localSegmentPoint.x()); + m_ttIntSegResidualLocalY[stationCSC].push_back(localTTIntPoint.y() - localSegmentPoint.y()); + /* Extract layers for hits */ + int layers = 0; + for (std::vector::const_iterator itRH = cscSegOut->specificRecHits().begin(); + itRH != cscSegOut->specificRecHits().end(); + ++itRH) { + const CSCRecHit2D* recHit = &(*itRH); + int layer = recHit->cscDetId().layer(); + layers |= 1 << (layer - 1); + } + m_chamberLayer[stationCSC].push_back(layers); + + } // end preliminary tsos is valid + + } // end found ring CSC + + } // end refined tsos is valid + + if ((!tsos.isValid()) || (ringCSC == 0)) { + // only fill Null denominator once for station 1, iiStation Z = 0,1,2 + if (iiStationZ <= 2) + iiStationFail++; + if (iiStationZ > 2 || iiStationFail == 3) { + // fill Null Den Num + m_chamberRing[stationCSC].push_back(-9); + m_chamberChamber[stationCSC].push_back(-9); + m_ttIntLocalX[stationCSC].push_back(-9999.0); + m_ttIntLocalY[stationCSC].push_back(-9999.0); + m_ttIntLocalErrorX[stationCSC].push_back(0.0); + m_ttIntLocalErrorY[stationCSC].push_back(0.0); + m_ttIntLocalW[stationCSC].push_back(-9999.0); + m_ttIntLocalS[stationCSC].push_back(-9999.0); + m_ttIntEta[stationCSC].push_back(-9999.0); + + m_ttDistToEdge[stationCSC].push_back(-9999.0); + m_ttDistToHVGap[stationCSC].push_back(-9999.9); + + m_segLocalX[stationCSC].push_back(-9999.0); + m_segLocalY[stationCSC].push_back(-9999.0); + m_segLocalErrorX[stationCSC].push_back(0.0); + m_segLocalErrorY[stationCSC].push_back(0.0); + + m_ttIntSegResidualLocalX[stationCSC].push_back(-9990.0); + m_ttIntSegResidualLocalY[stationCSC].push_back(-9990.0); + + m_chamberLayer[stationCSC].push_back(-9); + } + } + + } // end loop over CSC Z planes + } // endl loop over tracks + } // end loop over muons + + } // End if good physics objects + + // if (m_nZCands>0) { + auto table = std::make_unique(m_nZCands, m_name, false, false); + + table->setDoc("CSC Tag & Probe segment efficiency information"); + + addColumn(table, "muonPt", m_muonPt, "muon pt [GeV/c]"); + addColumn(table, "muonPhi", m_muonPhi, "muon phi [rad]"); + addColumn(table, "muonEta", m_muonEta, "muon eta"); + addColumn(table, "muonPtError", m_muonPtError, "muon pt error [GeV/c]"); + addColumn(table, "muonPhiError", m_muonPhiError, "muon phi error [rad]"); + addColumn(table, "muonEtaError", m_muonEtaError, "muon eta error"); + addColumn(table, "muonCharge", m_muonCharge, "muon charge"); + addColumn(table, "muonDXY", m_muonDXY, "muon dXY [cm]"); + addColumn(table, "muonDZ", m_muonDZ, "muon dZ [cm]"); + addColumn(table, "muonTrkHits", m_muonTrkHits, "muon track hits"); + addColumn(table, "muonChi2", m_muonChi2, "muon chi2"); + addColumn(table, "muonIso", m_trackIso, "muon relative iso"); + addColumn(table, "muonTrigger", m_muonTrigger, "muon has trigger bool"); + + addColumn(table, "trackPt", m_trackPt, "track pt [GeV/c]"); + addColumn(table, "trackP", m_trackPt, "track p [GeV/c]"); + addColumn(table, "trackPhi", m_trackPhi, "track phi [rad]"); + addColumn(table, "trackEta", m_trackEta, "track eta"); + addColumn(table, "trackPtError", m_trackPtError, "track pt error [GeV/c]"); + addColumn(table, "trackPhiError", m_trackPhiError, "track phi error [rad]"); + addColumn(table, "trackEtaError", m_trackEtaError, "track eta error"); + addColumn(table, "trackCharge", m_trackCharge, "track charge"); + addColumn(table, "trackDXY", m_trackDXY, "track dXY [cm]"); + addColumn(table, "trackDZ", m_trackDZ, "track dZ [cm]"); + addColumn(table, "trackTrkHits", m_trackTrkHits, "track track hits"); + addColumn(table, "trackChi2", m_trackChi2, "track chi2"); + addColumn(table, "trackIso", m_trackIso, "track relative iso"); + + addColumn(table, "zMass", m_zMass, "Z mass [GeV/c^2]"); + addColumn(table, "dRTrackMuon", m_dRTrackMuon, "dR between track and muon"); + addColumn(table, "numberOfPrimaryVertidies", m_numberOfPrimaryVertices, "Number of PVs"); + + addColumn(table, "chamberEndcap", m_chamberEndcap, ""); + addColumn(table, "chamberRing1", m_chamberRing[0], ""); + addColumn(table, "chamberRing2", m_chamberRing[1], ""); + addColumn(table, "chamberRing3", m_chamberRing[2], ""); + addColumn(table, "chamberRing4", m_chamberRing[3], ""); + addColumn(table, "chamberChamber1", m_chamberChamber[0], ""); + addColumn(table, "chamberChamber2", m_chamberChamber[1], ""); + addColumn(table, "chamberChamber3", m_chamberChamber[2], ""); + addColumn(table, "chamberChamber4", m_chamberChamber[3], ""); + addColumn(table, "chamberLayer1", m_chamberLayer[0], ""); + addColumn(table, "chamberLayer2", m_chamberLayer[1], ""); + addColumn(table, "chamberLayer3", m_chamberLayer[2], ""); + addColumn(table, "chamberLayer4", m_chamberLayer[3], ""); + + addColumn(table, "ttIntLocalX1", m_ttIntLocalX[0], ""); + addColumn(table, "ttIntLocalX2", m_ttIntLocalX[1], ""); + addColumn(table, "ttIntLocalX3", m_ttIntLocalX[2], ""); + addColumn(table, "ttIntLocalX4", m_ttIntLocalX[3], ""); + addColumn(table, "ttIntLocalY1", m_ttIntLocalY[0], ""); + addColumn(table, "ttIntLocalY2", m_ttIntLocalY[1], ""); + addColumn(table, "ttIntLocalY3", m_ttIntLocalY[2], ""); + addColumn(table, "ttIntLocalY4", m_ttIntLocalY[3], ""); + addColumn(table, "ttIntLocalErrorX1", m_ttIntLocalErrorX[0], ""); + addColumn(table, "ttIntLocalErrorX2", m_ttIntLocalErrorX[1], ""); + addColumn(table, "ttIntLocalErrorX3", m_ttIntLocalErrorX[2], ""); + addColumn(table, "ttIntLocalErrorX4", m_ttIntLocalErrorX[3], ""); + addColumn(table, "ttIntLocalErrorY1", m_ttIntLocalErrorY[0], ""); + addColumn(table, "ttIntLocalErrorY2", m_ttIntLocalErrorY[1], ""); + addColumn(table, "ttIntLocalErrorY3", m_ttIntLocalErrorY[2], ""); + addColumn(table, "ttIntLocalErrorY4", m_ttIntLocalErrorY[3], ""); + addColumn(table, "ttIntLocalW1", m_ttIntLocalW[0], ""); + addColumn(table, "ttIntLocalW2", m_ttIntLocalW[1], ""); + addColumn(table, "ttIntLocalW3", m_ttIntLocalW[2], ""); + addColumn(table, "ttIntLocalW4", m_ttIntLocalW[3], ""); + addColumn(table, "ttIntLocalS1", m_ttIntLocalS[0], ""); + addColumn(table, "ttIntLocalS2", m_ttIntLocalS[1], ""); + addColumn(table, "ttIntLocalS3", m_ttIntLocalS[2], ""); + addColumn(table, "ttIntLocalS4", m_ttIntLocalS[3], ""); + addColumn(table, "ttIntEta1", m_ttIntEta[0], ""); + addColumn(table, "ttIntEta2", m_ttIntEta[1], ""); + addColumn(table, "ttIntEta3", m_ttIntEta[2], ""); + addColumn(table, "ttIntEta4", m_ttIntEta[3], ""); + + addColumn(table, "ttDistToEdge1", m_ttDistToEdge[0], ""); + addColumn(table, "ttDistToEdge2", m_ttDistToEdge[1], ""); + addColumn(table, "ttDistToEdge3", m_ttDistToEdge[2], ""); + addColumn(table, "ttDistToEdge4", m_ttDistToEdge[3], ""); + addColumn(table, "ttDistToHVGap1", m_ttDistToHVGap[0], ""); + addColumn(table, "ttDistToHVGap2", m_ttDistToHVGap[1], ""); + addColumn(table, "ttDistToHVGap3", m_ttDistToHVGap[2], ""); + addColumn(table, "ttDistToHVGap4", m_ttDistToHVGap[3], ""); + + addColumn(table, "segLocalX1", m_segLocalX[0], ""); + addColumn(table, "segLocalX2", m_segLocalX[1], ""); + addColumn(table, "segLocalX3", m_segLocalX[2], ""); + addColumn(table, "segLocalX4", m_segLocalX[3], ""); + addColumn(table, "segLocalY1", m_segLocalY[0], ""); + addColumn(table, "segLocalY2", m_segLocalY[1], ""); + addColumn(table, "segLocalY3", m_segLocalY[2], ""); + addColumn(table, "segLocalY4", m_segLocalY[3], ""); + addColumn(table, "segLocalErrorX1", m_segLocalErrorX[0], ""); + addColumn(table, "segLocalErrorX2", m_segLocalErrorX[1], ""); + addColumn(table, "segLocalErrorX3", m_segLocalErrorX[2], ""); + addColumn(table, "segLocalErrorX4", m_segLocalErrorX[3], ""); + addColumn(table, "segLocalErrorY1", m_segLocalErrorY[0], ""); + addColumn(table, "segLocalErrorY2", m_segLocalErrorY[1], ""); + addColumn(table, "segLocalErrorY3", m_segLocalErrorY[2], ""); + addColumn(table, "segLocalErrorY4", m_segLocalErrorY[3], ""); + + addColumn(table, "ttIntSegResidualLocalX1", m_ttIntSegResidualLocalX[0], ""); + addColumn(table, "ttIntSegResidualLocalX2", m_ttIntSegResidualLocalX[1], ""); + addColumn(table, "ttIntSegResidualLocalX3", m_ttIntSegResidualLocalX[2], ""); + addColumn(table, "ttIntSegResidualLocalX4", m_ttIntSegResidualLocalX[3], ""); + addColumn(table, "ttIntSegResidualLocalY1", m_ttIntSegResidualLocalY[0], ""); + addColumn(table, "ttIntSegResidualLocalY2", m_ttIntSegResidualLocalY[1], ""); + addColumn(table, "ttIntSegResidualLocalY3", m_ttIntSegResidualLocalY[2], ""); + addColumn(table, "ttIntSegResidualLocalY4", m_ttIntSegResidualLocalY[3], ""); + + ev.put(std::move(table)); +} + +float MuCSCTnPFlatTableProducer::computeTrkIso(const reco::MuonIsolation& isolation, float muonPt) { + return isolation.sumPt / muonPt; +} + +float MuCSCTnPFlatTableProducer::computePFIso(const reco::MuonPFIsolation& pfIsolation, float muonPt) { + return (pfIsolation.sumChargedHadronPt + + std::max(0., pfIsolation.sumNeutralHadronEt + pfIsolation.sumPhotonEt - 0.5 * pfIsolation.sumPUPt)) / + muonPt; +} + +bool MuCSCTnPFlatTableProducer::hasTrigger(std::vector& trigIndices, + const trigger::TriggerObjectCollection& trigObjs, + edm::Handle& trigEvent, + const reco::Muon& muon) { + float dRMatch = 999.; + for (int trigIdx : trigIndices) { + const std::vector trigModuleLabels = m_hltConfig.moduleLabels(trigIdx); + + const unsigned trigModuleIndex = + std::find(trigModuleLabels.begin(), trigModuleLabels.end(), "hltBoolEnd") - trigModuleLabels.begin() - 1; + const unsigned hltFilterIndex = trigEvent->filterIndex(edm::InputTag(trigModuleLabels[trigModuleIndex], "", "HLT")); + if (hltFilterIndex < trigEvent->sizeFilters()) { + const trigger::Keys keys = trigEvent->filterKeys(hltFilterIndex); + const trigger::Vids vids = trigEvent->filterIds(hltFilterIndex); + const unsigned nTriggers = vids.size(); + + for (unsigned iTrig = 0; iTrig < nTriggers; ++iTrig) { + trigger::TriggerObject trigObj = trigObjs[keys[iTrig]]; + float dR = deltaR(muon, trigObj); + if (dR < dRMatch) + dRMatch = dR; + } + } + } + + return dRMatch < 0.1; //CB should get it programmable +} + +//bool MuCSCTnPFlatTableProducer::muonTagSelection(const reco::Muon & muon,edm::Handle> tracks) +bool MuCSCTnPFlatTableProducer::muonTagSelection(const reco::Muon& muon) { + float ptCut = 10.0; + int trackerHitsCut = 8; + float dxyCut = 2.0; + float dzCut = 24.0; + float chi2Cut = 4.0; + + bool selected = false; + //_muonIso = iso(*muon.track(),tracks); + _muonIso = computePFIso(muon.pfIsolationR04(), muon.pt()); + + if (!muon.isTrackerMuon()) + return false; + if (!muon.track().isNonnull()) + return false; + selected = + ((muon.track()->pt() > ptCut) && (muon.track()->hitPattern().numberOfValidTrackerHits() >= trackerHitsCut) && + (muon.track()->dxy() < dxyCut) && (std::abs(muon.track()->dz()) < dzCut) && + (muon.track()->normalizedChi2() < chi2Cut) && _muonIso < 0.1); + + return selected; +} + +bool MuCSCTnPFlatTableProducer::trackProbeSelection(const reco::Track& track, + edm::Handle> tracks) { + float ptCut = 10.0; + int trackerHitsCut = 8; + float dxyCut = 2.0; + float dzCut = 24.0; + float chi2Cut = 4.0; + + bool selected = false; + _trackIso = iso(track, tracks); + + selected = + ((track.pt() > ptCut) && (std::abs(track.eta()) > 0.75) && (std::abs(track.eta()) < 2.55) && + (track.numberOfValidHits() >= trackerHitsCut) && (track.dxy() < dxyCut) && (std::abs(track.dz()) < dzCut) && + (track.normalizedChi2() > 0.0) && (track.normalizedChi2() < chi2Cut) && _trackIso < 0.1); + + return selected; +} + +bool MuCSCTnPFlatTableProducer::zSelection(const reco::Muon& muon, const reco::Track& track) { + bool selected = false; + + _zMass = zMass(track, muon); + selected = (track.charge() * muon.charge() == -1 && (_zMass > 75.0) && (_zMass < 120.0)); + + return selected; +} + +// get track position at a particular (xy) plane given its z +TrajectoryStateOnSurface MuCSCTnPFlatTableProducer::surfExtrapTrkSam(const reco::Track& track, double z) { + Plane::PositionType pos(0, 0, z); + Plane::RotationType rot; + Plane::PlanePointer myPlane = Plane::build(pos, rot); + + FreeTrajectoryState recoStart = freeTrajStateMuon(track); + TrajectoryStateOnSurface recoProp = propagatorAlong->propagate(recoStart, *myPlane); + + if (!recoProp.isValid()) + recoProp = propagatorOpposite->propagate(recoStart, *myPlane); + + return recoProp; +} + +FreeTrajectoryState MuCSCTnPFlatTableProducer::freeTrajStateMuon(const reco::Track& track) { + //no track extras in nanoaod so directly use vx and p + GlobalPoint innerPoint(track.vx(), track.vy(), track.vz()); + GlobalVector innerVec(track.px(), track.py(), track.pz()); + + GlobalTrajectoryParameters gtPars(innerPoint, innerVec, track.charge(), &*theBField); + + AlgebraicSymMatrix66 cov; + cov *= 1e-20; + + CartesianTrajectoryError tCov(cov); + + return (cov.kRows == 6 ? FreeTrajectoryState(gtPars, tCov) : FreeTrajectoryState(gtPars)); +} + +UChar_t MuCSCTnPFlatTableProducer::ringCandidate(Int_t iiStation, Int_t station, Float_t feta, Float_t phi) { + UChar_t ring = 0; + + switch (station) { + case 1: + if (std::abs(feta) >= 0.85 && std::abs(feta) < 1.18) { //ME13 + if (iiStation == 2) + ring = 3; + return ring; + } + if (std::abs(feta) >= 1.18 && + std::abs(feta) <= 1.5) { //ME12 if(std::abs(feta)>1.18 && std::abs(feta)<1.7){//ME12 + if (iiStation == 1) + ring = 2; + return ring; + } + if (std::abs(feta) > 1.5 && std::abs(feta) < 2.1) { //ME11 + if (iiStation == 0) + ring = 1; + return ring; + } + if (std::abs(feta) >= 2.1 && std::abs(feta) < 2.45) { //ME11 + if (iiStation == 0) + ring = 4; + return ring; + } + break; + case 2: + if (std::abs(feta) > 0.95 && std::abs(feta) < 1.6) { //ME22 + ring = 2; + return ring; + } + if (std::abs(feta) > 1.55 && std::abs(feta) < 2.45) { //ME21 + ring = 1; + return ring; + } + break; + case 3: + if (std::abs(feta) > 1.08 && std::abs(feta) < 1.72) { //ME32 + ring = 2; + return ring; + } + if (std::abs(feta) > 1.69 && std::abs(feta) < 2.45) { //ME31 + ring = 1; + return ring; + } + break; + case 4: + if (std::abs(feta) > 1.78 && std::abs(feta) < 2.45) { //ME41 + ring = 1; + return ring; + } + if (std::abs(feta) > 1.15 && std::abs(feta) <= 1.78) { //ME42 + ring = 2; + return ring; + } + break; + default: + edm::LogError("") << "Invalid station: " << station << std::endl; + break; + } + return 0; +} + +UChar_t MuCSCTnPFlatTableProducer::thisChamberCandidate(UChar_t station, UChar_t ring, Float_t phi) { + // cout <<"\t\t TPTrackMuonSys::thisChamberCandidate..."< 1 && ring == 1) ? 18 : 36; + const Float_t ChamberSpan = 2 * M_PI / nVal; + Float_t dphi = phi + M_PI / 36; + while (dphi >= 2 * M_PI) + dphi -= 2 * M_PI; + while (dphi < 0) + dphi += 2 * M_PI; + UChar_t ChCand = floor(dphi / ChamberSpan) + 1; + return ChCand > nVal ? nVal : ChCand; +} + +Float_t MuCSCTnPFlatTableProducer::TrajectoryDistToSeg(TrajectoryStateOnSurface TrajSuf, + CSCSegmentCollection::const_iterator segIt) { + if (!TrajSuf.isValid()) + return 9999.; + const GeomDet* gdet = m_cscGeometry->idToDet((CSCDetId)(*segIt).cscDetId()); + LocalPoint localTTPos = gdet->surface().toLocal(TrajSuf.freeState()->position()); + LocalPoint localSegPos = (*segIt).localPosition(); + Float_t CSCdeltaX = localSegPos.x() - localTTPos.x(); + Float_t CSCdeltaY = localSegPos.y() - localTTPos.y(); + return sqrt(pow(CSCdeltaX, 2) + pow(CSCdeltaY, 2)); +} + +TrajectoryStateOnSurface* MuCSCTnPFlatTableProducer::matchTTwithCSCSeg(const reco::Track& track, + edm::Handle cscSegments, + CSCSegmentCollection::const_iterator& cscSegOut, + CSCDetId& idCSC) { + TrajectoryStateOnSurface* TrajSuf = nullptr; + Float_t deltaCSCR = 9999.; + for (CSCSegmentCollection::const_iterator segIt = cscSegments->begin(); segIt != cscSegments->end(); segIt++) { + CSCDetId id = (CSCDetId)(*segIt).cscDetId(); + + if (idCSC.endcap() != id.endcap()) + continue; + if (idCSC.station() != id.station()) + continue; + if (idCSC.chamber() != id.chamber()) + continue; + + Bool_t ed1 = + (idCSC.station() == 1) && ((idCSC.ring() == 1 || idCSC.ring() == 4) && (id.ring() == 1 || id.ring() == 4)); + Bool_t ed2 = + (idCSC.station() == 1) && ((idCSC.ring() == 2 && id.ring() == 2) || (idCSC.ring() == 3 && id.ring() == 3)); + Bool_t ed3 = (idCSC.station() != 1) && (idCSC.ring() == id.ring()); + Bool_t TMCSCMatch = (ed1 || ed2 || ed3); + + if (!TMCSCMatch) + continue; + + const CSCChamber* cscchamber = m_cscGeometry->chamber(id); + + if (!cscchamber) + continue; + + TrajectoryStateOnSurface TrajSuf_ = surfExtrapTrkSam(track, cscchamber->toGlobal((*segIt).localPosition()).z()); + Float_t dR_ = std::abs(TrajectoryDistToSeg(TrajSuf_, segIt)); + if (dR_ < deltaCSCR) { + delete TrajSuf; + TrajSuf = new TrajectoryStateOnSurface(TrajSuf_); + deltaCSCR = dR_; + cscSegOut = segIt; + } + } //loop over segments + + return TrajSuf; +} + +std::vector MuCSCTnPFlatTableProducer::GetEdgeAndDistToGap(const reco::Track& track, CSCDetId& detid) { + std::vector result(4, 9999.); + result[3] = -9999; + const GeomDet* gdet = m_cscGeometry->idToDet(detid); + TrajectoryStateOnSurface tsos = surfExtrapTrkSam(track, gdet->surface().position().z()); + if (!tsos.isValid()) + return result; + LocalPoint localTTPos = gdet->surface().toLocal(tsos.freeState()->position()); + const CSCWireTopology* wireTopology = m_cscGeometry->layer(detid)->geometry()->wireTopology(); + Float_t wideWidth = wireTopology->wideWidthOfPlane(); + Float_t narrowWidth = wireTopology->narrowWidthOfPlane(); + Float_t length = wireTopology->lengthOfPlane(); + // If slanted, there is no y offset between local origin and symmetry center of wire plane + Float_t yOfFirstWire = std::abs(wireTopology->wireAngle()) > 1.E-06 ? -0.5 * length : wireTopology->yOfWire(1); + // y offset between local origin and symmetry center of wire plane + Float_t yCOWPOffset = yOfFirstWire + 0.5 * length; + // tangent of the incline angle from inside the trapezoid + Float_t tangent = (wideWidth - narrowWidth) / (2. * length); + // y position wrt bottom of trapezoid + Float_t yPrime = localTTPos.y() + std::abs(yOfFirstWire); + // half trapezoid width at y' is 0.5 * narrowWidth + x side of triangle with the above tangent and side y' + Float_t halfWidthAtYPrime = 0.5 * narrowWidth + yPrime * tangent; + // x offset between local origin and symmetry center of wire plane is zero + // x offset of ME11s is also zero. x center of wire groups is not at zero, because it is not parallel to x. The wire groups of ME11s have a complex geometry, see the code in m_debug. + Float_t edgex = std::abs(localTTPos.x()) - halfWidthAtYPrime; + Float_t edgey = std::abs(localTTPos.y() - yCOWPOffset) - 0.5 * length; + LocalError localTTErr = tsos.localError().positionError(); + if (edgex > edgey) { + result[0] = edgex; + result[1] = sqrt(localTTErr.xx()); + //result[1] = sqrt(tsos.cartesianError().position().cxx()); + } else { + result[0] = edgey; + result[1] = sqrt(localTTErr.yy()); + //result[1] = sqrt(tsos.cartesianError().position().cyy()); + } + result[2] = YDistToHVDeadZone(localTTPos.y(), detid.station() * 10 + detid.ring()); + result[3] = sqrt(localTTErr.yy()); + return result; //return values: 1-edge;2-err of edge;3-disttogap;4-err of dist to gap +} + +//deadzone center is according to http://cmssdt.cern.ch/SDT/lxr/source/RecoLocalMuon/CSCEfficiency/src/CSCEfficiency.cc#605 +//wire spacing is according to CSCTDR +Float_t MuCSCTnPFlatTableProducer::YDistToHVDeadZone(Float_t yLocal, Int_t StationAndRing) { + //the ME11 wires are not parallel to x, but no gap + //chamber edges are not included. + const Float_t deadZoneCenterME1_2[2] = {-32.88305, 32.867423}; + const Float_t deadZoneCenterME1_3[2] = {-22.7401, 27.86665}; + const Float_t deadZoneCenterME2_1[2] = {-27.47, 33.67}; + const Float_t deadZoneCenterME3_1[2] = {-36.21, 23.68}; + const Float_t deadZoneCenterME4_1[2] = {-26.14, 23.85}; + const Float_t deadZoneCenterME234_2[4] = {-81.8744, -21.18165, 39.51105, 100.2939}; + const Float_t* deadZoneCenter; + Float_t deadZoneHeightHalf = 0.32 * 7 / 2; // wire spacing * (wires missing + 1)/2 + Float_t minY = 999999.; + UChar_t nGaps = 2; + switch (std::abs(StationAndRing)) { + case 11: + case 14: + return 162; //the height of ME11 + break; + case 12: + deadZoneCenter = deadZoneCenterME1_2; + break; + case 13: + deadZoneCenter = deadZoneCenterME1_3; + break; + case 21: + deadZoneCenter = deadZoneCenterME2_1; + break; + case 31: + deadZoneCenter = deadZoneCenterME3_1; + break; + case 41: + deadZoneCenter = deadZoneCenterME4_1; + break; + default: + deadZoneCenter = deadZoneCenterME234_2; + nGaps = 4; + } + for (UChar_t iGap = 0; iGap < nGaps; iGap++) { + Float_t newMinY = yLocal < deadZoneCenter[iGap] ? deadZoneCenter[iGap] - deadZoneHeightHalf - yLocal + : yLocal - (deadZoneCenter[iGap] + deadZoneHeightHalf); + if (newMinY < minY) + minY = newMinY; + } + return minY; +} + +double MuCSCTnPFlatTableProducer::iso(const reco::Track& track, edm::Handle> tracks) { + double isoSum = 0.0; + for (const auto& track2 : (*tracks)) { + double dR = calcDeltaR(track.eta(), track2.eta(), track.phi(), track2.phi()); + if (track2.pt() > 1.0 && dR > 0.001 && dR < 0.3) + isoSum += track2.pt(); + } + return isoSum / track.pt(); +} + +double MuCSCTnPFlatTableProducer::calcDeltaR(double eta1, double eta2, double phi1, double phi2) { + double deta = eta1 - eta2; + if (phi1 < 0) + phi1 += 2.0 * M_PI; + if (phi2 < 0) + phi2 += 2.0 * M_PI; + double dphi = phi1 - phi2; + if (dphi > M_PI) + dphi -= 2. * M_PI; + else if (dphi < -M_PI) + dphi += 2. * M_PI; + return std::sqrt(deta * deta + dphi * dphi); +} + +double MuCSCTnPFlatTableProducer::zMass(const reco::Track& track, const reco::Muon& muon) { + double zMass = -99.0; + double mMu = 0.1134289256; + + zMass = std::pow((std::sqrt(std::pow(muon.p(), 2) + mMu * mMu) + std::sqrt(std::pow(track.p(), 2) + mMu * mMu)), 2) - + (std::pow((muon.px() + track.px()), 2) + std::pow((muon.py() + track.py()), 2) + + std::pow((muon.pz() + track.pz()), 2)); + + return std::sqrt(zMass); +} + +#include "FWCore/PluginManager/interface/ModuleDef.h" +#include "FWCore/Framework/interface/MakerMacros.h" + +DEFINE_FWK_MODULE(MuCSCTnPFlatTableProducer); diff --git a/DPGAnalysis/MuonTools/plugins/MuDTMuonExtTableProducer.cc b/DPGAnalysis/MuonTools/plugins/MuDTMuonExtTableProducer.cc new file mode 100644 index 0000000000000..a1653d692407c --- /dev/null +++ b/DPGAnalysis/MuonTools/plugins/MuDTMuonExtTableProducer.cc @@ -0,0 +1,396 @@ +/** \class MuDTMuonExtTableProducer MuDTMuonExtTableProducer.cc DPGAnalysis/MuonTools/plugins/MuDTMuonExtTableProducer.cc + * + * Helper class : the muon filler + * + * \author L. Lunerti (INFN BO) + * + * + */ + +#include "DataFormats/DetId/interface/DetId.h" +#include "DataFormats/MuonDetId/interface/DTChamberId.h" +#include "DataFormats/MuonReco/interface/MuonChamberMatch.h" +#include "DataFormats/MuonReco/interface/MuonSegmentMatch.h" +#include "DataFormats/MuonReco/interface/MuonSelectors.h" + +#include "DataFormats/DTRecHit/interface/DTRecSegment4D.h" +#include "DataFormats/DTRecHit/interface/DTRecSegment4DCollection.h" +#include "DataFormats/TrackingRecHit/interface/TrackingRecHitFwd.h" +#include "DataFormats/MuonDetId/interface/DTChamberId.h" + +#include "DataFormats/Math/interface/deltaR.h" + +#include "TString.h" +#include "TRegexp.h" + +#include +#include + +#include "DPGAnalysis/MuonTools/interface/MuBaseFlatTableProducer.h" + +#include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h" +#include "FWCore/ParameterSet/interface/ParameterSetDescription.h" + +#include "DataFormats/Common/interface/View.h" +#include "DataFormats/MuonReco/interface/Muon.h" +#include "DataFormats/VertexReco/interface/Vertex.h" +#include "DataFormats/MuonReco/interface/MuonFwd.h" +#include "DataFormats/MuonReco/interface/MuonIsolation.h" +#include "DataFormats/MuonReco/interface/MuonPFIsolation.h" +#include "DataFormats/DTRecHit/interface/DTRecSegment4D.h" + +#include "DataFormats/Common/interface/TriggerResults.h" +#include "DataFormats/HLTReco/interface/TriggerEvent.h" +#include "DataFormats/HLTReco/interface/TriggerObject.h" +#include "HLTrigger/HLTcore/interface/HLTConfigProvider.h" + +class MuDTMuonExtTableProducer : public MuBaseFlatTableProducer { +public: + /// Constructor + MuDTMuonExtTableProducer(const edm::ParameterSet&); + + /// Fill descriptors + static void fillDescriptions(edm::ConfigurationDescriptions&); + +protected: + /// Fill tree branches for a given events + void fillTable(edm::Event&) final; + + /// Get info from the ES by run + void getFromES(const edm::Run&, const edm::EventSetup&) final; + +private: + /// Tokens + nano_mu::EDTokenHandle> m_muToken; + nano_mu::EDTokenHandle m_dtSegmentToken; + + nano_mu::EDTokenHandle m_trigResultsToken; + nano_mu::EDTokenHandle m_trigEventToken; + + /// Fill matches table + bool m_fillMatches; + + /// Name of the triggers used by muon filler for trigger matching + std::string m_trigName; + std::string m_isoTrigName; + + /// DT Geometry + nano_mu::ESTokenHandle m_dtGeometry; + + /// HLT config provider + HLTConfigProvider m_hltConfig; + + /// Indices of the triggers used by muon filler for trigger matching + std::vector m_trigIndices; + std::vector m_isoTrigIndices; + + bool hasTrigger(std::vector&, + const trigger::TriggerObjectCollection&, + edm::Handle&, + const reco::Muon&); +}; + +MuDTMuonExtTableProducer::MuDTMuonExtTableProducer(const edm::ParameterSet& config) + : MuBaseFlatTableProducer(config), + m_muToken{config, consumesCollector(), "src"}, + m_dtSegmentToken{config, consumesCollector(), "dtSegmentSrc"}, + m_trigResultsToken{config, consumesCollector(), "trigResultsSrc"}, + m_trigEventToken{config, consumesCollector(), "trigEventSrc"}, + m_fillMatches{config.getParameter("fillMatches")}, + m_trigName{config.getParameter("trigName")}, + m_isoTrigName{config.getParameter("isoTrigName")}, + m_dtGeometry{consumesCollector()} { + produces(); + if (m_fillMatches) { + produces("matches"); + produces("staMatches"); + } +} + +void MuDTMuonExtTableProducer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { + edm::ParameterSetDescription desc; + + desc.add("name", "muon"); + desc.add("src", edm::InputTag{"patMuons"}); + desc.add("dtSegmentSrc", edm::InputTag{"dt4DSegments"}); + desc.add("trigEventSrc", edm::InputTag{"hltTriggerSummaryAOD::HLT"}); + desc.add("trigResultsSrc", edm::InputTag{"TriggerResults::HLT"}); + + desc.add("fillMatches", true); + + desc.add("trigName", "HLT_Mu55*"); + desc.add("isoTrigName", "HLT_IsoMu2*"); + + descriptions.addWithDefaultLabel(desc); +} + +void MuDTMuonExtTableProducer::getFromES(const edm::Run& run, const edm::EventSetup& environment) { + m_dtGeometry.getFromES(environment); + + bool changed{true}; + m_hltConfig.init(run, environment, "HLT", changed); + + const bool enableWildcard{true}; + + TString tName = TString(m_trigName); + TRegexp tNamePattern = TRegexp(tName, enableWildcard); + + for (unsigned iPath = 0; iPath < m_hltConfig.size(); ++iPath) { + TString pathName = TString(m_hltConfig.triggerName(iPath)); + if (pathName.Contains(tNamePattern)) + m_trigIndices.push_back(static_cast(iPath)); + } + + tName = TString(m_isoTrigName); + tNamePattern = TRegexp(tName, enableWildcard); + + for (unsigned iPath = 0; iPath < m_hltConfig.size(); ++iPath) { + TString pathName = TString(m_hltConfig.triggerName(iPath)); + if (pathName.Contains(tNamePattern)) + m_isoTrigIndices.push_back(static_cast(iPath)); + } +} + +void MuDTMuonExtTableProducer::fillTable(edm::Event& ev) { + unsigned int nMuons{0}; + + std::vector firesIsoTrig; + std::vector firesTrig; + + std::vector nMatches; + std::vector staMu_nMatchSeg; + + std::vector matches_begin; + std::vector matches_end; + + std::vector staMatches_begin; + std::vector staMatches_end; + + std::vector matches_wheel; + std::vector matches_sector; + std::vector matches_station; + + std::vector matches_x; + std::vector matches_y; + + std::vector matches_phi; + std::vector matches_eta; + std::vector matches_edgeX; + std::vector matches_edgeY; + + std::vector matches_dXdZ; + std::vector matches_dYdZ; + + std::vector staMatches_MuSegIdx; + + auto muons = m_muToken.conditionalGet(ev); + auto segments = m_dtSegmentToken.conditionalGet(ev); + + auto triggerResults = m_trigResultsToken.conditionalGet(ev); + auto triggerEvent = m_trigEventToken.conditionalGet(ev); + + if (muons.isValid() && segments.isValid()) { + for (const auto& muon : (*muons)) { + if (triggerResults.isValid() && triggerEvent.isValid()) { + const auto& triggerObjects = triggerEvent->getObjects(); + + bool hasIsoTrig = hasTrigger(m_isoTrigIndices, triggerObjects, triggerEvent, muon); + bool hasTrig = hasTrigger(m_trigIndices, triggerObjects, triggerEvent, muon); + + firesIsoTrig.push_back(hasIsoTrig); + firesTrig.push_back(hasTrig); + + } else { + firesIsoTrig.push_back(false); + firesTrig.push_back(false); + } + + size_t iMatches = 0; + size_t iSegMatches = 0; + + if (m_fillMatches) { + matches_begin.push_back(matches_wheel.size()); + + if (muon.isMatchesValid()) { + for (const auto& match : muon.matches()) { + if (match.id.det() == DetId::Muon && match.id.subdetId() == MuonSubdetId::DT) { + DTChamberId dtId(match.id.rawId()); + const auto chamb = m_dtGeometry->chamber(static_cast(match.id)); + + matches_wheel.push_back(dtId.wheel()); + matches_sector.push_back(dtId.sector()); + matches_station.push_back(dtId.station()); + + matches_x.push_back(match.x); + matches_y.push_back(match.y); + + matches_phi.push_back(chamb->toGlobal(LocalPoint(match.x, match.y, 0.)).phi()); + matches_eta.push_back(chamb->toGlobal(LocalPoint(match.x, match.y, 0.)).eta()); + + matches_edgeX.push_back(match.edgeX); + matches_edgeY.push_back(match.edgeY); + + matches_dXdZ.push_back(match.dXdZ); + matches_dYdZ.push_back(match.dYdZ); + + ++iMatches; + } + } + } + + matches_end.push_back(matches_wheel.size()); + + //SEGMENT MATCHING VARIABLES + + staMatches_begin.push_back(staMatches_MuSegIdx.size()); + + if (!muon.outerTrack().isNull()) { + reco::TrackRef outerTrackRef = muon.outerTrack(); + + auto recHitIt = outerTrackRef->recHitsBegin(); + auto recHitEnd = outerTrackRef->recHitsEnd(); + + for (; recHitIt != recHitEnd; ++recHitIt) { + DetId detId = (*recHitIt)->geographicalId(); + + if (detId.det() == DetId::Muon && detId.subdetId() == MuonSubdetId::DT) { + const auto dtSegmentSta = dynamic_cast((*recHitIt)); + int iSeg = 0; + + for (const auto& segment : (*segments)) { + if (dtSegmentSta && dtSegmentSta->chamberId().station() == segment.chamberId().station() && + dtSegmentSta->chamberId().wheel() == segment.chamberId().wheel() && + dtSegmentSta->chamberId().sector() == segment.chamberId().sector() && + std::abs(dtSegmentSta->localPosition().x() - segment.localPosition().x()) < 0.001 && + std::abs(dtSegmentSta->localPosition().y() - segment.localPosition().y()) < 0.001 && + std::abs(dtSegmentSta->localDirection().x() - segment.localDirection().x()) < 0.001 && + std::abs(dtSegmentSta->localDirection().y() - segment.localDirection().y()) < 0.001) { + staMatches_MuSegIdx.push_back(iSeg); + ++iSegMatches; + } + + ++iSeg; + } //loop over segments + } + + } //loop over recHits + } + + staMatches_end.push_back(staMatches_MuSegIdx.size()); + } + + nMatches.push_back(iMatches); + staMu_nMatchSeg.push_back(iSegMatches); + + ++nMuons; + } + } + + auto table = std::make_unique(nMuons, m_name, false, true); + + addColumn(table, + "firesIsoTrig", + firesIsoTrig, + "True if the muon is matched to an isolated trigger" + "
specified in the ntuple config file"); + + addColumn(table, + "firesTrig", + firesTrig, + "True if the muon is matched to a (non isolated)trigger" + "
specified in the ntuple config file"); + + addColumn(table, "nMatches", nMatches, "Number of muon chamber matches (DT only)"); + addColumn(table, "staMu_nMatchSeg", staMu_nMatchSeg, "Number of segments used in the standalone track (DT only)"); + + addColumn(table, + "matches_begin", + matches_begin, + "begin() of range of quantities for a given muon in the *_matches_* vectors"); + addColumn( + table, "matches_end", matches_end, "end() of range of quantities for a given muon in the *_matches_* vectors"); + + addColumn(table, + "staMatches_begin", + staMatches_begin, + "begin() of range of quantities for a given muon in the matches_staMuSegIdx vector"); + addColumn(table, + "staMatches_end", + staMatches_end, + "end() of range of quantities for a given muon in the matches_staMuSegIdx vector"); + + ev.put(std::move(table)); + + if (m_fillMatches) { + auto sum = [](std::vector v) { return std::accumulate(v.begin(), v.end(), 0); }; + + auto tabMatches = std::make_unique(sum(nMatches), m_name + "_matches", false, false); + + tabMatches->setDoc("RECO muon matches_* vectors"); + + addColumn(tabMatches, "x", matches_x, "x position of the extrapolated track on the matched DT chamber"); + addColumn(tabMatches, "y", matches_y, "x position of the extrapolated track on the matched DT chamber"); + + addColumn(tabMatches, "wheel", matches_wheel, "matched DT chamber wheel"); + addColumn(tabMatches, "sector", matches_sector, "matched DT chamber sector"); + addColumn(tabMatches, "station", matches_station, "matched DT chamber station"); + + addColumn( + tabMatches, "phi", matches_phi, "phi of the (x,y) position on the matched DT chamber (global reference frame)"); + addColumn(tabMatches, + "eta", + matches_eta, + " eta of the (x,y) position on the matched cDT hamber (global reference frame)"); + + addColumn(tabMatches, "dXdZ", matches_dXdZ, "dXdZ of the extrapolated track on the matched DT chamber"); + addColumn(tabMatches, "dYdZ", matches_dYdZ, "dYdZ of the extrapolated track on the matched DT chamber"); + + ev.put(std::move(tabMatches), "matches"); + + auto tabStaMatches = + std::make_unique(sum(staMu_nMatchSeg), m_name + "_staMatches", false, false); + + tabStaMatches->setDoc("RECO muon staMatches_* vector"); + + addColumn(tabStaMatches, + "MuSegIdx", + staMatches_MuSegIdx, + "Index of DT segments used in the standalone track it corresponds" + "
to the index of a given segment in the ntuple seg_* collection"); + + ev.put(std::move(tabStaMatches), "staMatches"); + } +} + +bool MuDTMuonExtTableProducer::hasTrigger(std::vector& trigIndices, + const trigger::TriggerObjectCollection& trigObjs, + edm::Handle& trigEvent, + const reco::Muon& muon) { + float dRMatch = 999.; + for (int trigIdx : trigIndices) { + const std::vector trigModuleLabels = m_hltConfig.moduleLabels(trigIdx); + + const unsigned trigModuleIndex = + std::find(trigModuleLabels.begin(), trigModuleLabels.end(), "hltBoolEnd") - trigModuleLabels.begin() - 1; + const unsigned hltFilterIndex = trigEvent->filterIndex(edm::InputTag(trigModuleLabels[trigModuleIndex], "", "HLT")); + if (hltFilterIndex < trigEvent->sizeFilters()) { + const trigger::Keys keys = trigEvent->filterKeys(hltFilterIndex); + const trigger::Vids vids = trigEvent->filterIds(hltFilterIndex); + const unsigned nTriggers = vids.size(); + + for (unsigned iTrig = 0; iTrig < nTriggers; ++iTrig) { + trigger::TriggerObject trigObj = trigObjs[keys[iTrig]]; + float dR = deltaR(muon, trigObj); + if (dR < dRMatch) + dRMatch = dR; + } + } + } + + return dRMatch < 0.1; //CB should become programmable +} + +#include "FWCore/PluginManager/interface/ModuleDef.h" +#include "FWCore/Framework/interface/MakerMacros.h" + +DEFINE_FWK_MODULE(MuDTMuonExtTableProducer); \ No newline at end of file diff --git a/DPGAnalysis/MuonTools/plugins/MuDTSegmentExtTableProducer.cc b/DPGAnalysis/MuonTools/plugins/MuDTSegmentExtTableProducer.cc new file mode 100644 index 0000000000000..b37ed891f7e93 --- /dev/null +++ b/DPGAnalysis/MuonTools/plugins/MuDTSegmentExtTableProducer.cc @@ -0,0 +1,379 @@ +/** \class MuDTSegmentExtTableProducer MuDTSegmentExtTableProducer.ccDPGAnalysis/MuonTools/src/MuDTSegmentExtTableProducer.cc + * + * Helper class : the segment TableProducer for Phase-1 / Phase2 segments (the DataFormat is the same) + * + * \author C. Battilana (INFN BO) + * +* +*/ + +#include "DPGAnalysis/MuonTools/interface/MuBaseFlatTableProducer.h" + +#include "TrackingTools/GeomPropagators/interface/StraightLinePlaneCrossing.h" +#include "TrackingTools/GeomPropagators/interface/Propagator.h" + +#include "CalibMuon/DTDigiSync/interface/DTTTrigSyncFactory.h" + +#include +#include + +#include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h" +#include "FWCore/ParameterSet/interface/ParameterSetDescription.h" + +#include "CalibMuon/DTDigiSync/interface/DTTTrigBaseSync.h" +#include "DataFormats/DTRecHit/interface/DTRecSegment4DCollection.h" + +#include "Geometry/DTGeometry/interface/DTGeometry.h" +#include "Geometry/Records/interface/MuonGeometryRecord.h" + +#include "Geometry/CommonDetUnit/interface/GlobalTrackingGeometry.h" +#include "Geometry/Records/interface/GlobalTrackingGeometryRecord.h" + +class MuDTSegmentExtTableProducer : public MuBaseFlatTableProducer { +public: + /// Constructor + MuDTSegmentExtTableProducer(const edm::ParameterSet&); + + /// Fill descriptors + static void fillDescriptions(edm::ConfigurationDescriptions&); + +protected: + /// Fill tree branches for a given event + void fillTable(edm::Event&) final; + + /// Get info from the ES by run + void getFromES(const edm::Run&, const edm::EventSetup&) final; + + /// Get info from the ES for a given event + void getFromES(const edm::EventSetup&) final; + +private: + static const int FIRST_LAYER{1}; + static const int LAST_LAYER{4}; + static const int THETA_SL{2}; + /// The segment token + nano_mu::EDTokenHandle m_token; + + /// Fill rec-hit table + bool m_fillHits; + + /// Fill segment extrapolation table + bool m_fillExtr; + + /// DT Geometry + nano_mu::ESTokenHandle m_dtGeometry; + + /// Tracking Geometry + nano_mu::ESTokenHandle m_trackingGeometry; + + /// Handle DT trigger time pedestals + std::unique_ptr m_dtSync; +}; + +MuDTSegmentExtTableProducer::MuDTSegmentExtTableProducer(const edm::ParameterSet& config) + : MuBaseFlatTableProducer{config}, + m_token{config, consumesCollector(), "src"}, + m_fillHits{config.getParameter("fillHits")}, + m_fillExtr{config.getParameter("fillExtrapolation")}, + m_dtGeometry{consumesCollector()}, + m_trackingGeometry{consumesCollector()} { + produces(); + if (m_fillHits) { + produces("hits"); + } + if (m_fillExtr) { + produces("extr"); + } + + m_dtSync = DTTTrigSyncFactory::get()->create(config.getParameter("tTrigMode"), + config.getParameter("tTrigModeConfig"), + consumesCollector()); +} + +void MuDTSegmentExtTableProducer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { + edm::ParameterSetDescription desc; + + desc.add("name", "dtSegment"); + desc.add("src", edm::InputTag{"dt4DSegments"}); + desc.add("fillExtrapolation", true); + desc.add("fillHits", true); + + desc.add("tTrigMode", "DTTTrigSyncFromDB"); + + edm::ParameterSetDescription tTrigModeParams; + tTrigModeParams.add("doTOFCorrection", true); + tTrigModeParams.add("tofCorrType", 2); + + tTrigModeParams.add("vPropWire", 24.4); + tTrigModeParams.add("doWirePropCorrection", true); + tTrigModeParams.add("wirePropCorrType", 0); + + tTrigModeParams.add("tTrigLabel", ""); + tTrigModeParams.add("doT0Correction", true); + tTrigModeParams.add("t0Label", ""); + tTrigModeParams.addUntracked("debug", false); + + desc.add("tTrigModeConfig", tTrigModeParams); + + descriptions.addWithDefaultLabel(desc); +} + +void MuDTSegmentExtTableProducer::getFromES(const edm::Run& run, const edm::EventSetup& environment) { + m_dtGeometry.getFromES(environment); +} + +void MuDTSegmentExtTableProducer::getFromES(const edm::EventSetup& environment) { + m_trackingGeometry.getFromES(environment); + m_dtSync->setES(environment); +} + +void MuDTSegmentExtTableProducer::fillTable(edm::Event& ev) { + unsigned int nSegments{0}; + + std::vector seg4D_posLoc_x_SL1; + std::vector seg4D_posLoc_x_SL3; + std::vector seg4D_posLoc_x_midPlane; + + std::vector seg4D_extr_begin; + std::vector seg4D_extr_end; + + std::vector seg2D_hits_begin; + std::vector seg2D_hits_end; + + // segment extrapolation to DT layers filled, if m_fillExtr == true + unsigned int nExtr{0}; + + std::vector seg4D_hitsExpPos; + std::vector seg4D_hitsExpPosCh; + std::vector seg4D_hitsExpWire; + + // rec-hits vectors, filled if m_fillHits == true + unsigned int nHits{0}; + + std::vector seg2D_hits_pos; + std::vector seg2D_hits_posCh; + std::vector seg2D_hits_posErr; + std::vector seg2D_hits_side; + std::vector seg2D_hits_wire; + std::vector seg2D_hits_wirePos; + std::vector seg2D_hits_layer; + std::vector seg2D_hits_superLayer; + std::vector seg2D_hits_time; + std::vector seg2D_hits_timeCali; + + auto fillHits = [&](const DTRecSegment2D* seg, const GeomDet* chamb) { + const auto& recHits = seg->specificRecHits(); + + for (const auto& recHit : recHits) { + ++nHits; + + const auto wireId = recHit.wireId(); + const auto layerId = wireId.layerId(); + const auto* layer = m_dtGeometry->layer(layerId); + + seg2D_hits_pos.push_back(recHit.localPosition().x()); + seg2D_hits_posCh.push_back(chamb->toLocal(layer->toGlobal(recHit.localPosition())).x()); + seg2D_hits_posErr.push_back(recHit.localPositionError().xx()); + + seg2D_hits_side.push_back(recHit.lrSide()); + seg2D_hits_wire.push_back(wireId.wire()); + seg2D_hits_wirePos.push_back(layer->specificTopology().wirePosition(wireId.wire())); + seg2D_hits_layer.push_back(layerId.layer()); + seg2D_hits_superLayer.push_back(layerId.superlayer()); + + auto digiTime = recHit.digiTime(); + + auto tTrig = m_dtSync->offset(wireId); + + seg2D_hits_time.push_back(digiTime); + seg2D_hits_timeCali.push_back(digiTime - tTrig); + } + }; + + auto segments4D = m_token.conditionalGet(ev); + + if (segments4D.isValid()) { + auto chambIt = segments4D->id_begin(); + const auto chambEnd = segments4D->id_end(); + + for (; chambIt != chambEnd; ++chambIt) { + const auto& range = segments4D->get(*chambIt); + + for (auto segment4D = range.first; segment4D != range.second; ++segment4D) { + auto station = (*chambIt).station(); + auto wheel = (*chambIt).wheel(); + auto sector = (*chambIt).sector(); + + bool hasPhi = segment4D->hasPhi(); + bool hasZed = segment4D->hasZed(); + + auto pos = segment4D->localPosition(); + auto dir = segment4D->localDirection(); + + std::array xPosLocSL{{DEFAULT_DOUBLE_VAL, DEFAULT_DOUBLE_VAL}}; + std::array hasPptSL{{false, false}}; + auto xPosLocMidPlane = DEFAULT_DOUBLE_VAL; + + const auto* chamb = m_dtGeometry->chamber(*chambIt); + + StraightLinePlaneCrossing segmentPlaneCrossing{ + chamb->toGlobal(pos).basicVector(), chamb->toGlobal(dir).basicVector(), anyDirection}; + + if (hasPhi) { + for (int iSL = 0; iSL < 2; ++iSL) { + const auto* sl = chamb->superLayer(1 + iSL * 2); + + auto pptSL = segmentPlaneCrossing.position(sl->surface()); + hasPptSL[iSL] = pptSL.first; + + if (hasPptSL[iSL]) { + GlobalPoint segExrapolationToSL(pptSL.second); + xPosLocSL[iSL] = chamb->toLocal(segExrapolationToSL).x(); + } + } + } + + seg4D_posLoc_x_SL1.push_back(xPosLocSL[0]); + seg4D_posLoc_x_SL3.push_back(xPosLocSL[1]); + + if (hasPptSL[0] && hasPptSL[1]) + xPosLocMidPlane = (xPosLocSL[0] + xPosLocSL[1]) * 0.5; + + seg4D_posLoc_x_midPlane.push_back(xPosLocMidPlane); + + const auto begin = seg4D_hitsExpPos.size(); + + const auto size{station == 4 ? 8 : 12}; + + nExtr += size; + seg4D_extr_begin.push_back(begin); + seg4D_extr_end.push_back(begin + size); + + const auto iSLs = station < 4 ? std::vector{1, 2, 3} : std::vector{1, 3}; + + for (int iL = FIRST_LAYER; iL <= LAST_LAYER; ++iL) { + for (const auto iSL : iSLs) { + auto* layer = m_dtGeometry->layer(DTWireId{wheel, station, sector, iSL, iL, 2}); + auto ppt = segmentPlaneCrossing.position(layer->surface()); + + bool success{ppt.first}; // check for failure + + auto expPos{DEFAULT_DOUBLE_VAL}; + auto expPosCh{DEFAULT_DOUBLE_VAL}; + auto expWire{DEFAULT_INT_VAL_POS}; + + if (success) { + GlobalPoint segExrapolationToLayer(ppt.second); + LocalPoint segPosAtZWireLayer = layer->toLocal(segExrapolationToLayer); + LocalPoint segPosAtZWireChamber = chamb->toLocal(segExrapolationToLayer); + + if (hasPhi && iSL != THETA_SL) { + expPos = segPosAtZWireLayer.x(); + expPosCh = segPosAtZWireChamber.x(); + expWire = layer->specificTopology().channel(segPosAtZWireLayer); + } else if (hasZed && iSL == THETA_SL) { + expPos = segPosAtZWireLayer.x(); + expPosCh = segPosAtZWireChamber.y(); + expWire = layer->specificTopology().channel(segPosAtZWireLayer); + } + } + + seg4D_hitsExpPos.push_back(expPos); + seg4D_hitsExpPosCh.push_back(expPosCh); + seg4D_hitsExpWire.push_back(expWire); + } + } + + seg2D_hits_begin.push_back(seg2D_hits_pos.size()); + + const GeomDet* geomDet = m_trackingGeometry->idToDet(segment4D->geographicalId()); + if (hasPhi) { + fillHits(segment4D->phiSegment(), geomDet); + } + + if (hasZed) { + fillHits(segment4D->zSegment(), geomDet); + } + + seg2D_hits_end.push_back(seg2D_hits_pos.size()); + ++nSegments; + } + } + } + + auto table = std::make_unique(nSegments, m_name, false, true); + + table->setDoc("DT segment information"); + + addColumn(table, "seg4D_posLoc_x_SL1", seg4D_posLoc_x_SL1, "position x at SL1 in local coordinates - cm"); + addColumn(table, "seg4D_posLoc_x_SL3", seg4D_posLoc_x_SL3, "position x at SL3 in local coordinates - cm"); + addColumn(table, + "seg4D_posLoc_x_midPlane", + seg4D_posLoc_x_midPlane, + "position x at SL1 - SL3 mid plane in local coordinates - cm"); + + addColumn(table, "seg2D_hits_begin", seg2D_hits_begin, "begin() of range of quantities in the *_hits_* vectors"); + addColumn(table, "seg2D_hits_end", seg2D_hits_end, "end() of range of quantities in the *_hits_* vectors"); + + addColumn(table, "seg4D_extr_begin", seg4D_extr_begin, "begin() of range of quantities in the *_extr_* vectors"); + addColumn(table, "seg4D_extr_end", seg4D_extr_end, "end() of range of quantities in the *_extr_* vectors"); + + ev.put(std::move(table)); + + if (m_fillHits) { + auto tabHits = std::make_unique(nHits, m_name + "_hits", false, false); + + tabHits->setDoc("Size of DT segment *_hits_* vectors"); + + addColumn(tabHits, "pos", seg2D_hits_pos, "local x position of a hit in layer local coordinates"); + addColumn(tabHits, "posCh", seg2D_hits_posCh, "local x position of a hit in chamber local coordinates"); + addColumn(tabHits, + "posErr", + seg2D_hits_posErr, + "local position error of a hit in layer local coordinates - xx component of error matrix"); + addColumn(tabHits, "side", seg2D_hits_side, "is hit on L/R side of a cell wire - 1/2 is R/L"); + addColumn(tabHits, "wire", seg2D_hits_wire, "hit wire number - range depends on chamber size"); + addColumn(tabHits, "wirePos", seg2D_hits_wirePos, "hit wire x position in layer local coordinates"); + addColumn(tabHits, "layer", seg2D_hits_layer, "hit layer number - range [1:4]"); + addColumn(tabHits, + "superLayer", + seg2D_hits_superLayer, + "hit superlayer - [1:3] range" + "
SL 1 and 3 are phi SLs" + "
SL 2 is theta SL"); + addColumn(tabHits, "time", seg2D_hits_time, "digi time - ns, pedestal not subtracted"); + addColumn(tabHits, "timeCali", seg2D_hits_timeCali, "digi time - ns, pedestal subtracted"); + + ev.put(std::move(tabHits), "hits"); + } + + if (m_fillExtr) { + auto tabExtr = std::make_unique(nExtr, m_name + "_extr", false, false); + + tabExtr->setDoc("Size of DT segment *_extr_* vectors"); + addColumn(tabExtr, + "ExpPos", + seg4D_hitsExpPos, + "expected position of segment extrapolated" + "
to a given layer in layer local coordinates - cm"); + + addColumn(tabExtr, + "ExpPosCh", + seg4D_hitsExpPosCh, + "expected position of segment extrapolated" + "
to a given layer in chhamber local coordinates - cm"); + + addColumn(tabExtr, + "ExpWire", + seg4D_hitsExpWire, + "expected wire crossed by segment extrapolated" + "
to a given layer - range depends on chamber size"); + + ev.put(std::move(tabExtr), "extr"); + } +} + +#include "FWCore/PluginManager/interface/ModuleDef.h" +#include "FWCore/Framework/interface/MakerMacros.h" + +DEFINE_FWK_MODULE(MuDTSegmentExtTableProducer); diff --git a/DPGAnalysis/MuonTools/plugins/MuDTTPGPhiFlatTableProducer.cc b/DPGAnalysis/MuonTools/plugins/MuDTTPGPhiFlatTableProducer.cc new file mode 100644 index 0000000000000..781cddeea2ea0 --- /dev/null +++ b/DPGAnalysis/MuonTools/plugins/MuDTTPGPhiFlatTableProducer.cc @@ -0,0 +1,207 @@ +/** \class MuDTTPGPhiFlatTableProducer MuDTTPGPhiFlatTableProducer.cc DPGAnalysis/MuonTools/src/MuDTTPGPhiFlatTableProducer.cc + * + * Helper class : the Phase-1 local trigger FlatTableProducer for TwinMux in/out and BMTF in (the DataFormat is the same) + * + * \author C. Battilana (INFN BO) + * + * + */ + +#include "FWCore/ParameterSet/interface/allowedValues.h" + +#include +#include + +#include "DPGAnalysis/MuonTools/interface/MuBaseFlatTableProducer.h" + +#include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h" +#include "FWCore/ParameterSet/interface/ParameterSetDescription.h" + +#include "DataFormats/L1DTTrackFinder/interface/L1MuDTChambPhContainer.h" + +class MuDTTPGPhiFlatTableProducer : public MuBaseFlatTableProducer { +public: + enum class TriggerTag { TM_IN = 0, TM_OUT, BMTF_IN }; + + /// Constructor + MuDTTPGPhiFlatTableProducer(const edm::ParameterSet&); + + /// Fill descriptors + static void fillDescriptions(edm::ConfigurationDescriptions&); + +protected: + /// Fill tree branches for a given event + void fillTable(edm::Event&) final; + + /// Get info from the ES by run + void getFromES(const edm::Run&, const edm::EventSetup&) final; + +private: + /// Enum to activate "flavour-by-flavour" + /// changes in the filling logic + TriggerTag m_tag; + + /// The trigger-primitive token + nano_mu::EDTokenHandle m_token; + + /// The class to perform DT local trigger coordinate conversions + nano_mu::DTTrigGeomUtils m_trigGeomUtils; + + /// Helper function translating config parameter into TriggerTag + TriggerTag getTag(const edm::ParameterSet&); +}; + +MuDTTPGPhiFlatTableProducer::MuDTTPGPhiFlatTableProducer(const edm::ParameterSet& config) + : MuBaseFlatTableProducer{config}, + m_tag{getTag(config)}, + m_token{config, consumesCollector(), "src"}, + m_trigGeomUtils{consumesCollector()} { + produces(); +} + +void MuDTTPGPhiFlatTableProducer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { + edm::ParameterSetDescription desc; + + desc.add("name", "ltBmtfIn"); + desc.ifValue(edm::ParameterDescription("tag", "BMTF_IN", true), + edm::allowedValues("BMTF_IN", "TM_IN", "TM_OUT")); + desc.add("src", edm::InputTag{"bmtfDigis"}); + + descriptions.addWithDefaultLabel(desc); +} + +void MuDTTPGPhiFlatTableProducer::getFromES(const edm::Run& run, const edm::EventSetup& environment) { + m_trigGeomUtils.getFromES(run, environment); +} + +void MuDTTPGPhiFlatTableProducer::fillTable(edm::Event& ev) { + unsigned int nTrigs{0}; + + std::vector wheel; + std::vector sector; + std::vector station; + + std::vector quality; + std::vector rpcBit; + + std::vector phi; + std::vector phiB; + + std::vector posLoc_x; + std::vector dirLoc_phi; + + std::vector bx; + std::vector is2nd; + + auto trigColl = m_token.conditionalGet(ev); + + if (trigColl.isValid()) { + const auto trigs = trigColl->getContainer(); + for (const auto& trig : (*trigs)) { + if (trig.code() != 7) { + wheel.push_back(trig.whNum()); + sector.push_back(trig.scNum() + (m_tag != TriggerTag::BMTF_IN ? 1 : 0)); + station.push_back(trig.stNum()); + + quality.push_back(trig.code()); + + if (m_tag == TriggerTag::TM_OUT) + rpcBit.push_back(trig.RpcBit()); + + phi.push_back(trig.phi()); + phiB.push_back(trig.phiB()); + + auto [x, dir] = m_trigGeomUtils.trigToReco(&trig); + + posLoc_x.push_back(x); + dirLoc_phi.push_back(dir); + + bx.push_back(trig.bxNum() - (m_tag == TriggerTag::TM_IN && trig.Ts2Tag() ? 1 : 0)); + is2nd.push_back(trig.Ts2Tag()); + + ++nTrigs; + } + } + } + + auto table = std::make_unique(nTrigs, m_name, false, false); + + table->setDoc("Barrel trigger primitive information (phi view)"); + + addColumn(table, "wheel", wheel, "wheel - [-2:2] range"); + addColumn(table, + "sector", + sector, + "sector" + "
- [1:12] range for TwinMux" + "
- [0:11] range for BMTF input" + "
- double MB4 stations are part of S4 and S10 in TwinMux" + "
- double MB4 stations are part of S3 and S9 in BMTF input"); + addColumn(table, "station", station, "station - [1:4] range"); + addColumn(table, + "quality", + quality, + "quality - [0:6] range" + "
- [0:1] : uncorrelated L triggers" + "
- [2:3] : uncorrelated H triggers" + "
- 4 : correlated LL triggers" + "
- 5 : correlated HL triggers" + "
- 6 : correlated HH triggers"); + if (m_tag == TriggerTag::TM_OUT) { + addColumn(table, + "rpcBit", + rpcBit, + "use of RPC - [0:2] range" + "
- 0 : RPC not used" + "
- 1 : RPC+DT combined trigger" + "
- 2 : RPC-only trigger"); + } + + addColumn(table, + "phi", + phi, + "phi - scale and range:" + "
- 4096 correstpond to 1 rad" + "
- 0 is @ (DT sector - 1) * 30 deg in global CMS phi"); + addColumn(table, + "phiB", + phiB, + "phiB - scale and range:" + "
- 512 correstpond to 1 rad" + "
- 0 is a muon with infinite pT (straight line)"); + addColumn(table, "posLoc_x", posLoc_x, "position x in chamber local coordinates - cm"); + addColumn(table, "dirLoc_phi", dirLoc_phi, "direction phi angle in chamber local coordinates - deg"); + addColumn(table, + "bx", + bx, + "bx:" + "
- BX = 0 is the one where the event is collected" + "
- TwinMux range [X:Y]" + "
- BMT input range [X:Y]"); + addColumn(table, "is2nd", is2nd, "1st/2nd track flag - [0:1]"); + + ev.put(std::move(table)); +} + +MuDTTPGPhiFlatTableProducer::TriggerTag MuDTTPGPhiFlatTableProducer::getTag(const edm::ParameterSet& config) { + auto tag{TriggerTag::TM_IN}; + + auto tagName = config.getParameter("tag"); + + if (tagName != "TM_IN" && tagName != "TM_OUT" && tagName != "BMTF_IN") + edm::LogError("") << "[MuDTTPGPhiFlatTableProducer]::getTag: " << tagName + << " is not a valid tag, defaulting to TM_IN"; + + if (tagName == "TM_OUT") { + tag = TriggerTag::TM_OUT; + } else if (tagName == "BMTF_IN") { + tag = TriggerTag::BMTF_IN; + } + + return tag; +} + +#include "FWCore/PluginManager/interface/ModuleDef.h" +#include "FWCore/Framework/interface/MakerMacros.h" + +DEFINE_FWK_MODULE(MuDTTPGPhiFlatTableProducer); diff --git a/DPGAnalysis/MuonTools/plugins/MuDTTPGThetaFlatTableProducer.cc b/DPGAnalysis/MuonTools/plugins/MuDTTPGThetaFlatTableProducer.cc new file mode 100644 index 0000000000000..95c0e9ce6fe83 --- /dev/null +++ b/DPGAnalysis/MuonTools/plugins/MuDTTPGThetaFlatTableProducer.cc @@ -0,0 +1,155 @@ +/** \class MuDTTPGThetaFlatTableProducer MuDTTPGThetaFlatTableProducer.cc DPGAnalysis/MuonTools/plugins/MuDTTPGThetaFlatTableProducer.cc + * + * Helper class : the Phase-1 local trigger FlatTableProducer for TwinMux in/out and BMTF in (the DataFormat is the same) + * + * \author C. Battilana (INFN BO) + * + * + */ + +#include "DPGAnalysis/MuonTools/interface/MuBaseFlatTableProducer.h" +#include "FWCore/ParameterSet/interface/allowedValues.h" + +#include +#include + +#include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h" +#include "FWCore/ParameterSet/interface/ParameterSetDescription.h" + +#include "DataFormats/L1DTTrackFinder/interface/L1MuDTChambThContainer.h" + +class MuDTTPGThetaFlatTableProducer : public MuBaseFlatTableProducer { +public: + enum class TriggerTag { TM_IN = 0, BMTF_IN }; + + /// Constructor + MuDTTPGThetaFlatTableProducer(const edm::ParameterSet&); + + /// Fill descriptors + static void fillDescriptions(edm::ConfigurationDescriptions&); + +protected: + /// Fill tree branches for a given events + void fillTable(edm::Event&) final; + +private: + /// Enum to activate "flavour-by-flavour" + /// changes in the filling logic + TriggerTag m_tag; + + /// The trigger-primitive token + nano_mu::EDTokenHandle m_token; + + /// Helper function translating config parameter into TriggerTag + TriggerTag getTag(const edm::ParameterSet&); +}; + +MuDTTPGThetaFlatTableProducer::MuDTTPGThetaFlatTableProducer(const edm::ParameterSet& config) + : MuBaseFlatTableProducer{config}, m_tag{getTag(config)}, m_token{config, consumesCollector(), "src"} { + produces(); +} + +void MuDTTPGThetaFlatTableProducer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { + edm::ParameterSetDescription desc; + + desc.add("name", "ltBmtfInTh"); + desc.ifValue(edm::ParameterDescription("tag", "BMTF_IN", true), + edm::allowedValues("BMTF_IN", "TM_IN")); + desc.add("src", edm::InputTag{"bmtfDigis"}); + + descriptions.addWithDefaultLabel(desc); +} + +void MuDTTPGThetaFlatTableProducer::fillTable(edm::Event& ev) { + unsigned int nTrigs{0}; + + std::vector wheel; + std::vector sector; + std::vector station; + + std::vector bx; + std::vector hitMap; + + auto trigColl = m_token.conditionalGet(ev); + + if (trigColl.isValid()) { + const auto trigs = trigColl->getContainer(); + for (const auto& trig : (*trigs)) { + bool hasData = false; + for (int pos = 0; pos < 7; ++pos) { + if (trig.code(pos)) { + hasData = true; + break; + } + } + + if (!hasData) + continue; + + wheel.push_back(trig.whNum()); + sector.push_back(trig.scNum() + (m_tag != TriggerTag::BMTF_IN ? 1 : 0)); + station.push_back(trig.stNum()); + + bx.push_back(trig.bxNum()); + + uint32_t hitMapCh = 0; + for (int pos = 0; pos < 7; ++pos) + if (trig.code(pos)) + hitMapCh = hitMapCh | (0x1 << pos); + + hitMap.push_back(hitMapCh); + + ++nTrigs; + } + } + + auto table = std::make_unique(nTrigs, m_name, false, false); + + table->setDoc("Barrel trigger primitive information (theta view)"); + + addColumn(table, "wheel", wheel, "wheel - [-2:2] range"); + addColumn(table, + "sector", + sector, + "sector" + "
- [1:12] range for TwinMux" + "
- [0:11] range for BMTF input" + "
- double MB4 stations are part of S4 and S10 in TwinMux" + "
- double MB4 stations are part of S3 and S9 in BMTF input"); + addColumn(table, "station", station, "station - [1:3] range"); + addColumn(table, + "bx", + bx, + "bx:" + "
- BX = 0 is the one where the event is collected" + "
- TwinMux range [X:Y]" + "
- BMTF input range [X:Y]"); + addColumn(table, + "hitMap", + hitMap, + "Map groups of BTIs that fired (unsigned int):" + "
there are 7 groups of BTI per chamber, the first one" + "
being the less significant bit of the map [CHECK]"); + + ev.put(std::move(table)); +} + +MuDTTPGThetaFlatTableProducer::TriggerTag MuDTTPGThetaFlatTableProducer::getTag(const edm::ParameterSet& config) { + auto tag{TriggerTag::TM_IN}; + + auto tagName = config.getParameter("tag"); + + if (tagName != "TM_IN" && tagName != "BMTF_IN") + edm::LogError("") << "[MuDTTPGThetaFlatTableProducer]::getTag: " << tagName + << " is not a valid tag, defaulting to TM_IN"; + + if (tagName == "BMTF_IN") + tag = TriggerTag::BMTF_IN; + + return tag; +} + +#include "FWCore/PluginManager/interface/ModuleDef.h" +#include "FWCore/Framework/interface/MakerMacros.h" + +DEFINE_FWK_MODULE(MuDTTPGThetaFlatTableProducer); \ No newline at end of file diff --git a/DPGAnalysis/MuonTools/plugins/MuDigiFlatTableProducers.cc b/DPGAnalysis/MuonTools/plugins/MuDigiFlatTableProducers.cc new file mode 100644 index 0000000000000..cca1a4ae72eab --- /dev/null +++ b/DPGAnalysis/MuonTools/plugins/MuDigiFlatTableProducers.cc @@ -0,0 +1,38 @@ +/** \class MuDigiFlatTableProducers.cc MuDigiFlatTableProducers.cc DPGAnalysis/MuonTools/src/MuDigiFlatTableProducers.cc + * + * EDProducers : the flat table producers for CSC, DT, GEM and RPC digis + * + * \author C. Battilana (INFN BO) + * + * + */ + +#include "DPGAnalysis/MuonTools/interface/MuDigiBaseProducer.h" + +#include "DataFormats/CSCDigi/interface/CSCWireDigiCollection.h" +using CSCWireDigiFlatTableProducer = MuDigiBaseProducer; + +#include "DataFormats/CSCDigi/interface/CSCALCTDigiCollection.h" +using CSCAlctDigiFlatTableProducer = MuDigiBaseProducer; + +#include "DataFormats/DTDigi/interface/DTDigiCollection.h" +using DTDigiFlatTableProducer = MuDigiBaseProducer; + +#include "DataFormats/RPCDigi/interface/RPCDigiCollection.h" +using RPCDigiFlatTableProducer = MuDigiBaseProducer; + +#include "DataFormats/GEMDigi/interface/GEMDigiCollection.h" +using GEMDigiFlatTableProducer = MuDigiBaseProducer; + +#include "DataFormats/GEMDigi/interface/GEMOHStatusCollection.h" +using GEMOHStatusFlatTableProducer = MuDigiBaseProducer; + +#include "FWCore/PluginManager/interface/ModuleDef.h" +#include "FWCore/Framework/interface/MakerMacros.h" + +DEFINE_FWK_MODULE(CSCWireDigiFlatTableProducer); +DEFINE_FWK_MODULE(CSCAlctDigiFlatTableProducer); +DEFINE_FWK_MODULE(DTDigiFlatTableProducer); +DEFINE_FWK_MODULE(RPCDigiFlatTableProducer); +DEFINE_FWK_MODULE(GEMDigiFlatTableProducer); +DEFINE_FWK_MODULE(GEMOHStatusFlatTableProducer); diff --git a/DPGAnalysis/MuonTools/plugins/MuGEMMuonExtTableProducer.cc b/DPGAnalysis/MuonTools/plugins/MuGEMMuonExtTableProducer.cc new file mode 100644 index 0000000000000..a8ba0a8d92d02 --- /dev/null +++ b/DPGAnalysis/MuonTools/plugins/MuGEMMuonExtTableProducer.cc @@ -0,0 +1,588 @@ +#include "DataFormats/MuonDetId/interface/MuonSubdetId.h" +#include "DataFormats/MuonDetId/interface/GEMDetId.h" +#include "DataFormats/MuonDetId/interface/CSCDetId.h" + +#include "DataFormats/GeometryCommonDetAlgo/interface/ErrorFrameTransformer.h" +#include "TrackPropagation/SteppingHelixPropagator/interface/SteppingHelixStateInfo.h" + +#include + +#include "DPGAnalysis/MuonTools/interface/MuBaseFlatTableProducer.h" + +#include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h" +#include "FWCore/ParameterSet/interface/ParameterSetDescription.h" + +#include "DataFormats/Common/interface/View.h" +#include "DataFormats/MuonReco/interface/Muon.h" +#include "DataFormats/MuonReco/interface/MuonFwd.h" + +#include "Geometry/GEMGeometry/interface/GEMGeometry.h" +#include "Geometry/Records/interface/MuonGeometryRecord.h" + +#include "RecoMuon/TrackingTools/interface/MuonServiceProxy.h" + +#include "TrackingTools/TransientTrack/interface/TransientTrackBuilder.h" +#include "TrackingTools/Records/interface/TransientTrackRecord.h" + +class MuGEMMuonExtTableProducer : public MuBaseFlatTableProducer { +public: + /// Constructor + MuGEMMuonExtTableProducer(const edm::ParameterSet&); + + /// Fill descriptors + static void fillDescriptions(edm::ConfigurationDescriptions&); + +protected: + /// Fill tree branches for a given event + void fillTable(edm::Event&) final; + + /// Get info from the ES by run + void getFromES(const edm::Run&, const edm::EventSetup&) final; + + /// Get info from the ES for a given event + void getFromES(const edm::EventSetup&) final; + +private: + /// The RECO mu token + nano_mu::EDTokenHandle> m_token; + + /// Fill matches table + bool m_fillPropagated; + + /// GEM Geometry + nano_mu::ESTokenHandle m_gemGeometry; + + /// Transient Track Builder + nano_mu::ESTokenHandle m_transientTrackBuilder; + + /// Muon service proxy + std::unique_ptr m_muonSP; +}; + +MuGEMMuonExtTableProducer::MuGEMMuonExtTableProducer(const edm::ParameterSet& config) + : MuBaseFlatTableProducer{config}, + m_token{config, consumesCollector(), "src"}, + m_fillPropagated{config.getParameter("fillPropagated")}, + m_gemGeometry{consumesCollector()}, + m_transientTrackBuilder{consumesCollector(), "TransientTrackBuilder"}, + m_muonSP{std::make_unique(config.getParameter("ServiceParameters"), + consumesCollector())} { + produces(); + + if (m_fillPropagated) { + produces("propagated"); + } +} + +void MuGEMMuonExtTableProducer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { + edm::ParameterSetDescription desc; + + desc.add("name", "muon"); + desc.add("src", edm::InputTag{"patMuons"}); + + desc.add("fillPropagated", true); + desc.setAllowAnything(); + + descriptions.addWithDefaultLabel(desc); +} + +void MuGEMMuonExtTableProducer::getFromES(const edm::Run& run, const edm::EventSetup& environment) { + m_gemGeometry.getFromES(environment); +} + +void MuGEMMuonExtTableProducer::getFromES(const edm::EventSetup& environment) { + m_transientTrackBuilder.getFromES(environment); + m_muonSP->update(environment); +} + +void MuGEMMuonExtTableProducer::fillTable(edm::Event& ev) { + unsigned int nMuons{0}; + + std::vector isCSC; + std::vector isME11; + + std::vector innermost_x; + std::vector innermost_y; + std::vector innermost_z; + + std::vector outermost_x; + std::vector outermost_y; + std::vector outermost_z; + + unsigned int nProp{0}; + + std::vector propagated_muIdx; + + std::vector propagated_isincoming; + std::vector propagated_isinsideout; + std::vector propagated_region; + std::vector propagated_layer; + std::vector propagated_chamber; + std::vector propagated_etaP; + + std::vector propagatedLoc_x; + std::vector propagatedLoc_y; + std::vector propagatedLoc_z; + std::vector propagatedLoc_r; + std::vector propagatedLoc_phi; + std::vector propagatedLoc_dirX; + std::vector propagatedLoc_dirY; + std::vector propagatedLoc_dirZ; + std::vector propagatedLoc_errX; + std::vector propagatedLoc_errY; + + std::vector propagatedGlb_x; + std::vector propagatedGlb_y; + std::vector propagatedGlb_z; + std::vector propagatedGlb_r; + std::vector propagatedGlb_phi; + std::vector propagatedGlb_errX; + std::vector propagatedGlb_errY; + std::vector propagatedGlb_phierr; + std::vector propagatedGlb_rerr; + + std::vector propagated_EtaPartition_centerX; + std::vector propagated_EtaPartition_centerY; + std::vector propagated_EtaPartition_phiMax; + std::vector propagated_EtaPartition_phiMin; + std::vector propagated_EtaPartition_rMax; + std::vector propagated_EtaPartition_rMin; + + std::vector propagated_nME1hits; + std::vector propagated_nME2hits; + std::vector propagated_nME3hits; + std::vector propagated_nME4hits; + + auto muons = m_token.conditionalGet(ev); + + // edm::ESHandle + auto&& propagator_any = m_muonSP->propagator("SteppingHelixPropagatorAny"); + auto&& propagator_along = m_muonSP->propagator("SteppingHelixPropagatorAlong"); + auto&& propagator_opposite = m_muonSP->propagator("SteppingHelixPropagatorOpposite"); + + if (!propagator_any.isValid() || !propagator_along.isValid() || !propagator_opposite.isValid()) { + return; + } + + if (muons.isValid() && m_transientTrackBuilder.isValid()) { + //loop on recoMuons + for (const auto& muon : (*muons)) { + ++nMuons; + + bool is_csc = false; + bool is_me11 = false; + + if (!muon.outerTrack().isNull()) { + const auto track = muon.outerTrack().get(); + const auto outerTrackRef = muon.outerTrack(); + + float p2_in = track->innerMomentum().mag2(); + float p2_out = track->outerMomentum().mag2(); + float pos_out = track->outerPosition().mag2(); + float pos_in = track->innerPosition().mag2(); + + bool is_insideout = pos_in > pos_out; + + if (is_insideout) { + std::swap(pos_in, pos_out); + std::swap(p2_in, p2_out); + } + + bool is_incoming = p2_out > p2_in; + + const auto&& transient_track = m_transientTrackBuilder->build(track); + const auto& htp = transient_track.hitPattern(); + + if (transient_track.isValid()) { + const auto innerPosGlb{transient_track.innermostMeasurementState().globalPosition()}; + const auto outerPosGlb{transient_track.outermostMeasurementState().globalPosition()}; + + innermost_x.push_back(innerPosGlb.x()); + innermost_y.push_back(innerPosGlb.y()); + innermost_z.push_back(innerPosGlb.z()); + outermost_x.push_back(outerPosGlb.x()); + outermost_y.push_back(outerPosGlb.y()); + outermost_z.push_back(outerPosGlb.z()); + } else { + innermost_x.push_back(DEFAULT_DOUBLE_VAL); + innermost_y.push_back(DEFAULT_DOUBLE_VAL); + innermost_z.push_back(DEFAULT_DOUBLE_VAL); + outermost_x.push_back(DEFAULT_DOUBLE_VAL); + outermost_y.push_back(DEFAULT_DOUBLE_VAL); + outermost_z.push_back(DEFAULT_DOUBLE_VAL); + continue; + } + + const auto&& start_state = + is_insideout ? transient_track.outermostMeasurementState() : transient_track.innermostMeasurementState(); + auto& propagator = is_incoming ? propagator_along : propagator_opposite; + + auto recHitMu = outerTrackRef->recHitsBegin(); + auto recHitMuEnd = outerTrackRef->recHitsEnd(); + + //loop on recHits which form the outerTrack + for (; recHitMu != recHitMuEnd; ++recHitMu) { + DetId detId{(*recHitMu)->geographicalId()}; + + if (detId.det() == DetId::Muon && detId.subdetId() == MuonSubdetId::CSC) { + is_csc = true; + + const CSCDetId csc_id{detId}; + // ME11 chambers consist of 2 subchambers: ME11a, ME11b. + // In CMSSW they are referred as Stat. 1 Ring 1, Stat. 1 Ring. 4 respectively + if (csc_id.station() == 1 && ((csc_id.ring() == 1) || (csc_id.ring() == 4))) + is_me11 = true; + } + } //loop on recHits + + //if at least one CSC hit is found, perform propagation + if (is_csc) { + // CSC Hits + int8_t nME1_hits = 0; + int8_t nME2_hits = 0; + int8_t nME3_hits = 0; + int8_t nME4_hits = 0; + + int nHits{htp.numberOfAllHits(htp.TRACK_HITS)}; + + for (int i = 0; i != nHits; ++i) { + uint32_t hit = htp.getHitPattern(htp.TRACK_HITS, i); + int substructure = htp.getSubStructure(hit); + int hittype = htp.getHitType(hit); + + if (substructure == 2 && hittype == 0) { // CSC Hits + int CSC_station = htp.getMuonStation(hit); + + switch (CSC_station) { + case 1: + ++nME1_hits; + break; + case 2: + ++nME2_hits; + break; + case 3: + ++nME3_hits; + break; + case 4: + ++nME4_hits; + break; + default: + // do nothing + break; + } + } + } + //loop on GEM etaPartitions + for (const auto& eta_partition : m_gemGeometry->etaPartitions()) { + if (eta_partition->id().station() != 1) { + continue; //Only takes GE1/1 + } + const GEMDetId&& gem_id = eta_partition->id(); + + bool is_opposite_region = muon.eta() * gem_id.region() < 0; + if (is_incoming xor is_opposite_region) { + continue; //Check on muon direction + } + const BoundPlane& bound_plane = eta_partition->surface(); + + const auto& dest_state = propagator->propagate(start_state, bound_plane); + if (!dest_state.isValid()) { + // std::cout << "failed to propagate" << std::endl; + continue; + } + const GlobalPoint&& dest_global_pos = dest_state.globalPosition(); + const LocalPoint&& local_point = eta_partition->toLocal(dest_global_pos); + const LocalPoint local_point_2d{local_point.x(), local_point.y(), 0.0f}; + + if (eta_partition->surface().bounds().inside(local_point_2d)) { + //// PROPAGATED HIT ERROR EVALUATION + // X,Y + double xx = dest_state.curvilinearError().matrix()(3, 3); + double yy = dest_state.curvilinearError().matrix()(4, 4); + double xy = dest_state.curvilinearError().matrix()(4, 3); + double dest_glob_error_x = sqrt(0.5 * (xx + yy - sqrt((xx - yy) * (xx - yy) + 4 * xy * xy))); + double dest_glob_error_y = sqrt(0.5 * (xx + yy + sqrt((xx - yy) * (xx - yy) + 4 * xy * xy))); + + // R,Phi + const LocalPoint&& dest_local_pos = eta_partition->toLocal(dest_global_pos); + const LocalError&& dest_local_err = dest_state.localError().positionError(); + const GlobalError& dest_global_err = + ErrorFrameTransformer().transform(dest_local_err, eta_partition->surface()); + const double dest_global_r_err = std::sqrt(dest_global_err.rerr(dest_global_pos)); + const double dest_global_phi_err = std::sqrt(dest_global_err.phierr(dest_global_pos)); + + ++nProp; + + propagated_muIdx.push_back(nMuons - 1); + + propagated_nME1hits.push_back(nME1_hits); + propagated_nME2hits.push_back(nME2_hits); + propagated_nME3hits.push_back(nME3_hits); + propagated_nME4hits.push_back(nME4_hits); + + const auto& eta_partition_pos{eta_partition->position()}; + const auto& eta_partition_surf{eta_partition->surface()}; + propagated_EtaPartition_centerX.push_back(eta_partition_pos.x()); + propagated_EtaPartition_centerY.push_back(eta_partition_pos.y()); + propagated_EtaPartition_rMin.push_back(eta_partition_surf.rSpan().first); + propagated_EtaPartition_rMax.push_back(eta_partition_surf.rSpan().second); + propagated_EtaPartition_phiMin.push_back(eta_partition_surf.phiSpan().first); + propagated_EtaPartition_phiMax.push_back(eta_partition_surf.phiSpan().second); + + propagatedGlb_x.push_back(dest_global_pos.x()); + propagatedGlb_y.push_back(dest_global_pos.y()); + propagatedGlb_z.push_back(dest_global_pos.z()); + propagatedGlb_r.push_back(dest_global_pos.perp()); + propagatedGlb_phi.push_back(dest_global_pos.phi()); + + const auto dest_local_dir{dest_state.localDirection()}; + propagatedLoc_x.push_back(dest_local_pos.x()); + propagatedLoc_y.push_back(dest_local_pos.y()); + propagatedLoc_z.push_back(dest_local_pos.z()); + propagatedLoc_r.push_back(dest_local_pos.perp()); + propagatedLoc_phi.push_back(dest_local_pos.phi()); + propagatedLoc_dirX.push_back(dest_local_dir.x()); + propagatedLoc_dirY.push_back(dest_local_dir.y()); + propagatedLoc_dirZ.push_back(dest_local_dir.z()); + + propagatedLoc_errX.push_back(dest_local_err.xx()); + propagatedLoc_errY.push_back(dest_local_err.yy()); + + propagatedGlb_errX.push_back(dest_glob_error_x); + propagatedGlb_errY.push_back(dest_glob_error_y); + propagatedGlb_rerr.push_back(dest_global_r_err); + propagatedGlb_phierr.push_back(dest_global_phi_err); + + propagated_region.push_back(gem_id.region()); + propagated_layer.push_back(gem_id.layer()); + propagated_chamber.push_back(gem_id.chamber()); + propagated_etaP.push_back(gem_id.roll()); + + propagated_isinsideout.push_back(is_insideout); + propagated_isincoming.push_back(is_incoming); + + } //propagation is inside boundaries + } //loop on EtaPartitions + } //is_csc therefore perform propagation + } else { //!muon.outerTrack().isNull() + innermost_x.push_back(DEFAULT_DOUBLE_VAL); + innermost_y.push_back(DEFAULT_DOUBLE_VAL); + innermost_z.push_back(DEFAULT_DOUBLE_VAL); + outermost_x.push_back(DEFAULT_DOUBLE_VAL); + outermost_y.push_back(DEFAULT_DOUBLE_VAL); + outermost_z.push_back(DEFAULT_DOUBLE_VAL); + } + isCSC.push_back(is_csc); + isME11.push_back(is_me11); + + } //loop on reco muons + } + + auto table = std::make_unique(nMuons, m_name, false, true); + + //table->setDoc("RECO muon information"); + + addColumn(table, "innermost_x", innermost_x, ""); + addColumn(table, "innermost_y", innermost_y, ""); + addColumn(table, "innermost_z", innermost_z, ""); + + addColumn(table, "outermost_x", outermost_x, ""); + addColumn(table, "outermost_y", outermost_y, ""); + addColumn(table, "outermost_z", outermost_z, ""); + ev.put(std::move(table)); + + if (m_fillPropagated) { + auto tabProp = std::make_unique(nProp, m_name + "_propagated", false, false); + + addColumn(tabProp, "propagated_muIdx", propagated_muIdx, ""); + + addColumn(tabProp, + "propagated_nME1hits", + propagated_nME1hits, + "number of hits in the CSC ME1 station" + "in the STA muon track extrapolated to GE11"); + addColumn(tabProp, + "propagated_nME2hits", + propagated_nME2hits, + "number of hits in the CSC ME2 station" + "in the STA muon track extrapolated to GE11"); + addColumn(tabProp, + "propagated_nME3hits", + propagated_nME3hits, + "number of hits in the CSC ME3 station" + "in the STA muon track extrapolated to GE11"); + addColumn(tabProp, + "propagated_nME4hits", + propagated_nME4hits, + "number of hits in the CSC ME4 station" + "in the STA muon track extrapolated to GE11"); + + addColumn( + tabProp, "propagated_isincoming", propagated_isincoming, "bool, condition on the muon STA track direction"); + addColumn( + tabProp, "propagated_isinsideout", propagated_isinsideout, "bool, condition on the muon STA track direction"); + addColumn(tabProp, + "propagated_region", + propagated_region, + "GE11 region where the extrapolated muon track falls" + "
(int, positive endcap: +1, negative endcap: -1"); + addColumn(tabProp, + "propagated_layer", + propagated_layer, + "GE11 layer where the extrapolated muon track falls" + "
(int, layer1: 1, layer2: 2"); + addColumn(tabProp, + "propagated_chamber", + propagated_chamber, + "GE11 superchamber where the extrapolated muon track falls" + "
(int, chambers numbered from 0 to 35"); + addColumn(tabProp, + "propagated_etaP", + propagated_etaP, + "GE11 eta partition where the extrapolated muon track falls" + "
(int, partitions numbered from 1 to 8"); + + addColumn(tabProp, + "propagatedLoc_x", + propagatedLoc_x, + "expected position of muon track extrapolated to GE11 surface" + "
(float, local layer x coordinates, cm)"); + addColumn(tabProp, + "propagatedLoc_y", + propagatedLoc_y, + "expected position of muon track extrapolated to GE11 surface" + "
(float, local layer y coordinates, cm)"); + addColumn(tabProp, + "propagatedLoc_z", + propagatedLoc_z, + "expected position of muon track extrapolated to GE11 surface" + "
(float, local layer z coordinates, cm)"); + addColumn(tabProp, + "propagatedLoc_r", + propagatedLoc_r, + "expected position of muon track extrapolated to GE11 surface" + "
(float, local layer radial coordinate, cm)"); + addColumn(tabProp, + "propagatedLoc_phi", + propagatedLoc_phi, + "expected position of muon track extrapolated to GE11 surface" + "
(float, local layer phi coordinates, rad)"); + + addColumn(tabProp, + "propagatedLoc_dirX", + propagatedLoc_dirX, + "direction cosine of angle between local x axis and GE11 plane" + "
(float, dir. cosine)"); + addColumn(tabProp, + "propagatedLoc_dirY", + propagatedLoc_dirY, + "direction cosine of angle between local y axis and GE11 plane" + "
(float, dir. cosine)"); + addColumn(tabProp, + "propagatedLoc_dirZ", + propagatedLoc_dirZ, + "direction cosine of angle between local z axis and GE11 plane" + "
(float, dir. cosine)"); + + addColumn(tabProp, + "propagatedLoc_errX", + propagatedLoc_errX, + "uncertainty on expected position of muon track extrapolated to GE11 surface" + "
(float, local layer x coordinates, cm)"); + addColumn(tabProp, + "propagatedLoc_errY", + propagatedLoc_errY, + "uncertainty on expected position of muon track extrapolated to GE11 surface" + "
(float, local layer y coordinates, cm)"); + + addColumn(tabProp, + "propagatedGlb_x", + propagatedGlb_x, + "expected position of muon track extrapolated to GE11 surface" + "
(float, global x coordinates, cm)"); + addColumn(tabProp, + "propagatedGlb_y", + propagatedGlb_y, + "expected position of muon track extrapolated to GE11 surface" + "
(float, global y coordinates, cm)"); + addColumn(tabProp, + "propagatedGlb_z", + propagatedGlb_z, + "expected position of muon track extrapolated to GE11 surface" + "
(float, global z coordinates, cm)"); + addColumn(tabProp, + "propagatedGlb_r", + propagatedGlb_r, + "expected position of muon track extrapolated to GE11 surface" + "
(float, global radial (r) coordinates, cm)"); + addColumn(tabProp, + "propagatedGlb_phi", + propagatedGlb_phi, + "expected position of muon track extrapolated to GE11 surface" + "
(float, global phi coordinates, rad)"); + addColumn(tabProp, + "propagatedGlb_errX", + propagatedGlb_errX, + "uncertainty on position of muon track extrapolated to GE11 surface" + "
(float, global x coordinates, cm)"); + addColumn(tabProp, + "propagatedGlb_errY", + propagatedGlb_errY, + "uncertainty on position of muon track extrapolated to GE11 surface" + "
(float, global y coordinates, cm)"); + addColumn(tabProp, + "propagatedGlb_rerr", + propagatedGlb_rerr, + "uncertainty on position of muon track extrapolated to GE11 surface" + "
(float, global radial (r) coordinates, cm)"); + addColumn(tabProp, + "propagatedGlb_phierr", + propagatedGlb_phierr, + "uncertainty on position of muon track extrapolated to GE11 surface" + "
(float, global phi coordinates, rad)"); + + addColumn(tabProp, + "propagated_EtaPartition_centerX", + propagated_EtaPartition_centerX, + "global X coordinate of the center of the etaPartition" + "
where the extrapolated muon track position falls" + "
(float, global x coordinates, cm)"); + addColumn(tabProp, + "propagated_EtaPartition_centerY", + propagated_EtaPartition_centerY, + "global Y coordinate of the center of the etaPartition" + "
where the extrapolated muon track position falls" + "
(float, global x coordinates, cm)"); + addColumn(tabProp, + "propagated_EtaPartition_phiMax", + propagated_EtaPartition_phiMax, + "upper edge in phi global coordinates of the etaPartition" + "
where the extrapolated muon track position falls" + "
(float, global phi coordinates, rad)"); + addColumn(tabProp, + "propagated_EtaPartition_phiMin", + propagated_EtaPartition_phiMin, + "lower edge in phi global coordinates of the etaPartition" + "
where the extrapolated muon track position falls" + "
(float, global phi coordinates, rad)"); + addColumn(tabProp, + "propagated_EtaPartition_rMax", + propagated_EtaPartition_rMax, + "upper edge in r global coordinates of the etaPartition" + "
where the extrapolated muon track position falls" + "
(float, global radial (r) coordinates, cm)"); + addColumn(tabProp, + "propagated_EtaPartition_rMin", + propagated_EtaPartition_rMin, + "lower edge in r global coordinates of the etaPartition" + "
where the extrapolated muon track position falls" + "
(float, global radial (r) coordinates, cm)"); + + ev.put(std::move(tabProp), "propagated"); + } +} + +#include "FWCore/PluginManager/interface/ModuleDef.h" +#include "FWCore/Framework/interface/MakerMacros.h" + +DEFINE_FWK_MODULE(MuGEMMuonExtTableProducer); diff --git a/DPGAnalysis/MuonTools/plugins/MuLocalRecoFlatTableProducers.cc b/DPGAnalysis/MuonTools/plugins/MuLocalRecoFlatTableProducers.cc new file mode 100644 index 0000000000000..454c84bdf1ddd --- /dev/null +++ b/DPGAnalysis/MuonTools/plugins/MuLocalRecoFlatTableProducers.cc @@ -0,0 +1,42 @@ +/** \class MuRecoFlatTableProducers.ccMuRecoFlatTableProducers DPGAnalysis/MuonTools/src/MuRecoFlatTableProducers.cc + * + * EDProducers : the flat table producers for DT, GEM and RPC RecHits and Segments + * + * \author C. Battilana (INFN BO) + * + * + */ + +#include "DPGAnalysis/MuonTools/interface/MuLocalRecoBaseProducer.h" + +#include "Geometry/DTGeometry/interface/DTGeometry.h" +#include "Geometry/Records/interface/MuonGeometryRecord.h" +#include "DataFormats/DTRecHit/interface/DTRecSegment4DCollection.h" + +using DTSegmentFlatTableProducer = MuRecObjBaseProducer; + +#include "Geometry/RPCGeometry/interface/RPCGeometry.h" +#include "Geometry/Records/interface/MuonGeometryRecord.h" +#include "DataFormats/RPCRecHit/interface/RPCRecHitCollection.h" + +using RPCRecHitFlatTableProducer = MuRecObjBaseProducer; + +#include "Geometry/GEMGeometry/interface/GEMGeometry.h" +#include "Geometry/Records/interface/MuonGeometryRecord.h" +#include "DataFormats/GEMRecHit/interface/GEMRecHitCollection.h" + +using GEMRecHitFlatTableProducer = MuRecObjBaseProducer; + +#include "Geometry/GEMGeometry/interface/GEMGeometry.h" +#include "Geometry/Records/interface/MuonGeometryRecord.h" +#include "DataFormats/GEMRecHit/interface/GEMSegmentCollection.h" + +using GEMSegmentFlatTableProducer = MuRecObjBaseProducer; + +#include "FWCore/PluginManager/interface/ModuleDef.h" +#include "FWCore/Framework/interface/MakerMacros.h" + +DEFINE_FWK_MODULE(DTSegmentFlatTableProducer); +DEFINE_FWK_MODULE(RPCRecHitFlatTableProducer); +DEFINE_FWK_MODULE(GEMRecHitFlatTableProducer); +DEFINE_FWK_MODULE(GEMSegmentFlatTableProducer); diff --git a/DPGAnalysis/MuonTools/python/common_cff.py b/DPGAnalysis/MuonTools/python/common_cff.py new file mode 100644 index 0000000000000..b217515add89c --- /dev/null +++ b/DPGAnalysis/MuonTools/python/common_cff.py @@ -0,0 +1,42 @@ +from PhysicsTools.NanoAOD.common_cff import * +from typing import NamedTuple + +class DEFAULT_VAL(NamedTuple): + INT: int = -999 + INT8: int = -99 + INT_POS: int = -1 + FLOAT: int = -999.0 + FLOAT_POS: int = -1.0 + +defaults = DEFAULT_VAL() + +def DetIdVar(expr, type, doc=None): + """ Create a PSet for a DetId variable in the tree: + - expr is the expression to evaluate to compute the variable, + - type of the value (int, bool, or a string that the table producer understands), + - doc is a docstring, that will be passed to the table producer + """ + if type == float: type = "float" + elif type == bool: type = "bool" + elif type == int: type = "int" + return cms.PSet( + type = cms.string(type), + expr = cms.string(expr), + doc = cms.string(doc if doc else expr) + ) + +def GlobGeomVar(expr, doc=None, precision=-1): + """ Create a PSet for a Global position/direction variable in the tree , + - expr is the expression to evaluate to compute the variable, + - doc is a docstring, that will be passed to the table producer, + - precision is an int handling mantissa reduction. + """ + return cms.PSet( + expr = cms.string(expr), + doc = cms.string(doc if doc else expr), + precision=cms.string(precision) if type(precision)==str else cms.int32(precision) + ) + + + + diff --git a/DPGAnalysis/MuonTools/python/customiseMuNtuples_cff.py b/DPGAnalysis/MuonTools/python/customiseMuNtuples_cff.py new file mode 100644 index 0000000000000..6630cafce20d2 --- /dev/null +++ b/DPGAnalysis/MuonTools/python/customiseMuNtuples_cff.py @@ -0,0 +1,37 @@ +import FWCore.ParameterSet.Config as cms + +def customiseForRunningOnMC(process, pathName) : + + if hasattr(process,"muNtupleProducer") : + print("[customiseForRunningOnMC]: updating ntuple input tags") + + process.muNtupleTwinMuxInFiller.dtTpTag = "none" + process.muNtupleTwinMuxOutFiller.dtTpTag = "none" + process.muNtupleTwinMuxInThFiller.dtTpTag = "none" + + return process + +def customiseForMuonWorkflow(process) : + print("[customiseForMuonWorkflow]: adding VarParsing") + + import FWCore.ParameterSet.VarParsing as VarParsing + options = VarParsing.VarParsing() + + options.register('globalTag', + '130X_dataRun3_Express_v1', #default value + VarParsing.VarParsing.multiplicity.singleton, + VarParsing.VarParsing.varType.string, + "Global Tag") + + options.register('nEvents', + 100, #default value + VarParsing.VarParsing.multiplicity.singleton, + VarParsing.VarParsing.varType.int, + "Maximum number of processed events") + + options.parseArguments() + + process.GlobalTag.globaltag = cms.string(options.globalTag) + process.maxEvents = cms.untracked.PSet(input = cms.untracked.int32(options.nEvents)) + + return process \ No newline at end of file diff --git a/DPGAnalysis/MuonTools/python/muNtupleProducerBkg_cff.py b/DPGAnalysis/MuonTools/python/muNtupleProducerBkg_cff.py new file mode 100644 index 0000000000000..b928bf610b491 --- /dev/null +++ b/DPGAnalysis/MuonTools/python/muNtupleProducerBkg_cff.py @@ -0,0 +1,15 @@ +import FWCore.ParameterSet.Config as cms + +from PhysicsTools.NanoAOD.common_cff import * + +from DPGAnalysis.MuonTools.nano_mu_digi_cff import * + +muNtupleProducerBkg = cms.Sequence(muDigiProducersBkg) + +def nanoAOD_customizeCommon(process) : + + if hasattr(process, "NANOAODoutput"): + process.NANOAODoutput.outputCommands.append("keep nanoaodFlatTable_*Table*_*_*") + process.NANOAODoutput.outputCommands.append("drop edmTriggerResults_*_*_*") + + return process \ No newline at end of file diff --git a/DPGAnalysis/MuonTools/python/muNtupleProducerRaw_cff.py b/DPGAnalysis/MuonTools/python/muNtupleProducerRaw_cff.py new file mode 100644 index 0000000000000..0a186e4f431e7 --- /dev/null +++ b/DPGAnalysis/MuonTools/python/muNtupleProducerRaw_cff.py @@ -0,0 +1,19 @@ +import FWCore.ParameterSet.Config as cms + +from DPGAnalysis.MuonTools.muNtupleDTDigiFiller_cfi import muNtupleDTDigiFiller +from DPGAnalysis.MuonTools.muNtupleCSCALCTDigiFiller_cfi import muNtupleCSCALCTDigiFiller +from DPGAnalysis.MuonTools.muNtupleCSCWireDigiFiller_cfi import muNtupleCSCWireDigiFiller +from DPGAnalysis.MuonTools.muNtupleRPCDigiFiller_cfi import muNtupleRPCDigiFiller +from DPGAnalysis.MuonTools.muNtupleGEMDigiFiller_cfi import muNtupleGEMDigiFiller + +from DPGAnalysis.MuonTools.muNtupleRPCRecHitFiller_cfi import muNtupleRPCRecHitFiller +from DPGAnalysis.MuonTools.muNtupleGEMRecHitFiller_cfi import muNtupleGEMRecHitFiller + +muNtupleProducerRaw = cms.Sequence(muNtupleDTDigiFiller + + muNtupleRPCDigiFiller + + muNtupleGEMDigiFiller + + muNtupleRPCRecHitFiller + + muNtupleGEMRecHitFiller + + muNtupleCSCALCTDigiFiller + + muNtupleCSCWireDigiFiller + ) \ No newline at end of file diff --git a/DPGAnalysis/MuonTools/python/muNtupleProducer_cff.py b/DPGAnalysis/MuonTools/python/muNtupleProducer_cff.py new file mode 100644 index 0000000000000..993e2e1098e90 --- /dev/null +++ b/DPGAnalysis/MuonTools/python/muNtupleProducer_cff.py @@ -0,0 +1,28 @@ +import FWCore.ParameterSet.Config as cms + +from PhysicsTools.NanoAOD.common_cff import * + +from DPGAnalysis.MuonTools.nano_mu_digi_cff import * +from DPGAnalysis.MuonTools.nano_mu_local_reco_cff import * +from DPGAnalysis.MuonTools.nano_mu_reco_cff import * +from DPGAnalysis.MuonTools.nano_mu_l1t_cff import * + +muNtupleProducer = cms.Sequence(muDigiProducers + + muLocalRecoProducers + + muRecoProducers + + muL1TriggerProducers + ) + +def nanoAOD_customizeCommon(process) : + + if hasattr(process, "muGEMMuonExtTableProducer") or hasattr(process, "muCSCTnPFlatTableProducer"): + process.load("TrackingTools/TransientTrack/TransientTrackBuilder_cfi") + process.load("TrackPropagation.SteppingHelixPropagator.SteppingHelixPropagatorAny_cfi") + process.load("TrackPropagation.SteppingHelixPropagator.SteppingHelixPropagatorAlong_cfi") + process.load("TrackPropagation.SteppingHelixPropagator.SteppingHelixPropagatorOpposite_cfi") + + if hasattr(process, "NANOAODoutput"): + process.NANOAODoutput.outputCommands.append("keep nanoaodFlatTable_*Table*_*_*") + process.NANOAODoutput.outputCommands.append("drop edmTriggerResults_*_*_*") + + return process diff --git a/DPGAnalysis/MuonTools/python/nano_mu_digi_cff.py b/DPGAnalysis/MuonTools/python/nano_mu_digi_cff.py new file mode 100644 index 0000000000000..1be4ef59d022e --- /dev/null +++ b/DPGAnalysis/MuonTools/python/nano_mu_digi_cff.py @@ -0,0 +1,160 @@ +import FWCore.ParameterSet.Config as cms + +from PhysicsTools.NanoAOD.common_cff import * +from DPGAnalysis.MuonTools.common_cff import * + +from DPGAnalysis.MuonTools.dtDigiFlatTableProducer_cfi import dtDigiFlatTableProducer + +dtDigiFlatTableProducer.name = "dtDigi" +dtDigiFlatTableProducer.src = "muonDTDigis" +dtDigiFlatTableProducer.doc = "DT digi information" + +dtDigiFlatTableProducer.variables = cms.PSet( + time = Var("time()", float, doc = "digi time"), + wire = Var("wire()", "int8", doc="wire - [1:X] range" + "
(X varies for different chambers SLs and layers)") +) + +dtDigiFlatTableProducer.detIdVariables = cms.PSet( + wheel = DetIdVar("wheel()", "int8", doc = "wheel - [-2:2] range"), + sector = DetIdVar("sector()", "int8", doc = "sector - [1:14] range" + "
sector 13 used for the second MB4 of sector 4" + "
sector 14 used for the second MB4 of sector 10"), + station = DetIdVar("station()", "int8", doc = "station - [1:4] range"), + superLayer = DetIdVar("superLayer()", "int8", doc = "superlayer - [1:3] range" + "
SL 1 and 3 are phi SLs" + "
SL 2 is theta SL"), + layer = DetIdVar("layer()", "int8", doc = "layer - [1:4] range") +) + + +from DPGAnalysis.MuonTools.rpcDigiFlatTableProducer_cfi import rpcDigiFlatTableProducer + +rpcDigiFlatTableProducer.name = "rpcDigi" +rpcDigiFlatTableProducer.src = "muonRPCDigis" +rpcDigiFlatTableProducer.doc = "RPC digi information" + +rpcDigiFlatTableProducer.variables = cms.PSet( + strip = Var("strip()", "uint8", doc = "index of the readout strip associated to the digi"), + bx = Var("bx()", int, doc="bunch crossing associated to the digi") +) + +rpcDigiFlatTableProducer.detIdVariables = cms.PSet( + region = DetIdVar("region()", "int8", doc = "0: barrel, +/-1: endcap"), + ring = DetIdVar("ring()", "int8", doc = "ring id:" + "
wheel number in barrel - [-2:+2] range" + "
ring number in endcap - [1:3] range"), + station = DetIdVar("station()", "int8", doc = "chambers at same R in barrel, chambers at same Z ion endcap"), + layer = DetIdVar("layer()", "int8", doc = "layer id:" + "
barrel stations 1 and 2, have two layers of chambers " + "(layer 1 is the inner chamber and layer 2 is the outer chamber)"), + sector = DetIdVar("sector()", "int8", doc = "group of chambers at same phi"), + subsector = DetIdVar("subsector()", "int8", doc = "Some sectors are divided along the phi direction in subsectors " + "(from 1 to 4 in Barrel, from 1 to 6 in Endcap)"), + roll = DetIdVar("roll()", "int8", doc = "roll id (also known as eta partition):" + "
each chamber is divided along the strip direction"), + rawId = DetIdVar("rawId()", "uint", doc = "unique detector unit ID") +) + +from DPGAnalysis.MuonTools.gemDigiFlatTableProducer_cfi import gemDigiFlatTableProducer + +gemDigiFlatTableProducer.name = "gemDigi" +gemDigiFlatTableProducer.src = "muonGEMDigis" +gemDigiFlatTableProducer.doc = "GEM digi information" + +gemDigiFlatTableProducer.variables = cms.PSet( + strip = Var("strip()", "int8", doc = "index of the readout strip associated to the digi"), + bx = Var("bx()", "int8", doc="bunch crossing associated to the digi") +) + +gemDigiFlatTableProducer.detIdVariables = cms.PSet( + station = DetIdVar("station()", "int8", doc = "GEM station
(always 1 for GE1/1)"), + region = DetIdVar("region()", "int8", doc = "GE11 region where the digi is detected" + "
(int, positive endcap: +1, negative endcap: -1)"), + roll = DetIdVar("roll()", "int8", doc = "roll id (also known as eta partition)" + "
(partitions numbered from 1 to 8)"), + chamber = DetIdVar("chamber()", "int8", doc = "GE11 superchamber where the hit is reconstructed" + "
(chambers numbered from 0 to 35)"), + layer = DetIdVar("layer()", "int8", doc = "GE11 layer where the hit is reconstructed" + "
(layer1: 1, layer2: 2)") +) + + + +from DPGAnalysis.MuonTools.gemohStatusFlatTableProducer_cfi import gemohStatusFlatTableProducer + +gemohStatusFlatTableProducer.name = "gemOHStatus" +gemohStatusFlatTableProducer.src = "muonGEMDigis:OHStatus:" +gemohStatusFlatTableProducer.doc = "GEM OH status information" + + +gemohStatusFlatTableProducer.variables = cms.PSet( +chamberType = Var("chamberType()", "int", doc = "two digits number that specifies the module within a chamber
11,12 for GE1/1 chambers layer 1,2
21,22,23,24 for GE2/1 chambers module 1,2,3,4"), +vfatMask = Var("vfatMask()", "uint", doc = "24 bit word that specifies the VFAT Mask
nth bit == 0 means that the VFAT_n was masked from the DAQ in the event"), +zsMask = Var("zsMask()", "uint", doc = "24 bit word that specifies the Zero Suppression
nth bit == 1 means that the VFAT_n was zero suppressed"), +missingVFATs = Var("missingVFATs()", "uint", doc = "24 bit word that specifies the missing VFAT mask
nth bit == 1 means that the VFAT_n was expected in the payload but not found"), +errors = Var("errors()", "uint16", doc = "code for GEM OH errors
non-zero values indicate errors"), +warnings = Var("warnings()", "uint16", doc = "code for GEM OH warnings
non-zero values indicate warnings") +) + +gemohStatusFlatTableProducer.detIdVariables = cms.PSet( + station = DetIdVar("station()", "int8", doc = "GEM station
always 1 for GE1/1)"), + region = DetIdVar("region()", "int8", doc = "region with which the GEMOHStatus is associated" + "
int, positive endcap: +1, negative endcap: -1"), + chamber = DetIdVar("chamber()", "int8", doc = "chamber with which the GEMOHStatus is associated"), + layer = DetIdVar("layer()", "int8", doc = "layer with which the GEMOHStatus is associated
either 1 or 2 for GE1/1 and GE2/1") +) + + +from DPGAnalysis.MuonTools.cscWireDigiFlatTableProducer_cfi import cscWireDigiFlatTableProducer + +cscWireDigiFlatTableProducer.name = "cscWireDigi" +cscWireDigiFlatTableProducer.src = "muonCSCDigis:MuonCSCWireDigi" +cscWireDigiFlatTableProducer.doc = "CSC wire digi information" + +cscWireDigiFlatTableProducer.variables = cms.PSet( + timeBin = Var("getTimeBin()", "int8", doc = ""), + wireGroup = Var("getWireGroup()", "int8", doc=""), + wireGroupBX = Var("getWireGroupBX()", "int8", doc="") +) + +cscWireDigiFlatTableProducer.detIdVariables = cms.PSet( + endcap = DetIdVar("endcap()", "int8", doc = ""), + station = DetIdVar("station()", "int8", doc = ""), + ring = DetIdVar("ring()", "int8", doc = ""), + chamber = DetIdVar("chamber()", "int8", doc = ""), + layer = DetIdVar("layer()", "int8", doc = "") +) + +from DPGAnalysis.MuonTools.cscAlctDigiFlatTableProducer_cfi import cscAlctDigiFlatTableProducer + +cscAlctDigiFlatTableProducer.name = "cscALCTDigi" +cscAlctDigiFlatTableProducer.src = "muonCSCDigis:MuonCSCALCTDigi:" +cscAlctDigiFlatTableProducer.doc = "CSC ALCT digi information" + +cscAlctDigiFlatTableProducer.variables = cms.PSet( + keyWireGroup = Var("getKeyWG()", "int8", doc = ""), + bx = Var("getBX()", "int8", doc="") +) + +cscAlctDigiFlatTableProducer.detIdVariables = cms.PSet( + endcap = DetIdVar("endcap()", "int8", doc = ""), + station = DetIdVar("station()", "int8", doc = ""), + ring = DetIdVar("ring()", "int8", doc = ""), + chamber = DetIdVar("chamber()", "int8", doc = ""), + layer = DetIdVar("layer()", "int8", doc = "") +) + +muDigiProducers = cms.Sequence(dtDigiFlatTableProducer + + rpcDigiFlatTableProducer + + gemDigiFlatTableProducer + + gemohStatusFlatTableProducer + ) + +muDigiProducersBkg = cms.Sequence(dtDigiFlatTableProducer + + rpcDigiFlatTableProducer + + cscAlctDigiFlatTableProducer + + cscWireDigiFlatTableProducer + + gemDigiFlatTableProducer + + gemohStatusFlatTableProducer + ) diff --git a/DPGAnalysis/MuonTools/python/nano_mu_l1t_cff.py b/DPGAnalysis/MuonTools/python/nano_mu_l1t_cff.py new file mode 100644 index 0000000000000..b36d88a283583 --- /dev/null +++ b/DPGAnalysis/MuonTools/python/nano_mu_l1t_cff.py @@ -0,0 +1,19 @@ +import FWCore.ParameterSet.Config as cms + +from DPGAnalysis.MuonTools.muDTTPGPhiFlatTableProducer_cfi import muDTTPGPhiFlatTableProducer + +muBmtfInFlatTableProducer = muDTTPGPhiFlatTableProducer.clone() +muTwinMuxInFlatTableProducer = muDTTPGPhiFlatTableProducer.clone(tag = 'TM_IN', name = 'ltTwinMuxIn', src = cms.InputTag('twinMuxStage2Digis','PhIn')) +muTwinMuxOutFlatTableProducer = muDTTPGPhiFlatTableProducer.clone(tag = 'TM_OUT', name = 'ltTwinMuxOut', src = cms.InputTag('twinMuxStage2Digis','PhOut')) + +from DPGAnalysis.MuonTools.muDTTPGThetaFlatTableProducer_cfi import muDTTPGThetaFlatTableProducer + +muBmtfInThFlatTableProducer = muDTTPGThetaFlatTableProducer.clone() +muTwinMuxInThFlatTableProducer = muDTTPGThetaFlatTableProducer.clone(tag = 'TM_IN', name = 'ltTwinMuxInTh', src = cms.InputTag('twinMuxStage2Digis','ThIn')) + +muL1TriggerProducers = cms.Sequence(muTwinMuxInFlatTableProducer + + muTwinMuxOutFlatTableProducer + + muBmtfInFlatTableProducer + + muTwinMuxInThFlatTableProducer + + muBmtfInThFlatTableProducer + ) diff --git a/DPGAnalysis/MuonTools/python/nano_mu_local_reco_cff.py b/DPGAnalysis/MuonTools/python/nano_mu_local_reco_cff.py new file mode 100644 index 0000000000000..307c3c90cc1e7 --- /dev/null +++ b/DPGAnalysis/MuonTools/python/nano_mu_local_reco_cff.py @@ -0,0 +1,163 @@ +import FWCore.ParameterSet.Config as cms + +from DPGAnalysis.MuonTools.dtSegmentFlatTableProducer_cfi import dtSegmentFlatTableProducer + +from PhysicsTools.NanoAOD.common_cff import * +from DPGAnalysis.MuonTools.common_cff import * + +dtSegmentFlatTableProducer.name = "dtSegment" +dtSegmentFlatTableProducer.src = "dt4DSegments" +dtSegmentFlatTableProducer.doc = "DT segment information" + +dtSegmentFlatTableProducer.variables = cms.PSet( + seg4D_hasPhi = Var("hasPhi()", bool, doc = "has segment phi view - bool"), + seg4D_hasZed = Var("hasZed()", bool, doc = "has segment zed view - bool"), + seg4D_posLoc_x = Var("localPosition().x()", float, doc = "position x in local coordinates - cm"), + seg4D_posLoc_y = Var("localPosition().y()", float, doc = "position y in local coordinates - cm"), + seg4D_posLoc_z = Var("localPosition().z()", float, doc = "position z in local coordinates - cm"), + seg4D_dirLoc_x = Var("localDirection().x()", float, doc = "direction x in local coordinates"), + seg4D_dirLoc_y = Var("localDirection().y()", float, doc = "direction y in local coordinates"), + seg4D_dirLoc_z = Var("localDirection().z()", float, doc = "direction z in local coordinates"), + + seg2D_phi_t0 = Var(f"? hasPhi() ? phiSegment().t0() : {defaults.FLOAT}", float, doc = "t0 from segments with phi view - ns"), + seg2D_phi_nHits = Var(f"? hasPhi() ? phiSegment().specificRecHits().size() : 0", "int8", doc = "# hits in phi view - [0:8] range"), + seg2D_phi_vDrift = Var(f"? hasPhi() ? phiSegment().vDrift() : {defaults.FLOAT_POS}", float, doc = "v_drift from segments with phi view"), + seg2D_phi_normChi2 = Var(f"? hasPhi() ? (phiSegment().chi2() / phiSegment().degreesOfFreedom()) : {defaults.FLOAT_POS}", float, doc = "chi2/n.d.o.f. from segments with phi view"), + + seg2D_z_t0 = Var(f"? hasZed() ? zSegment().t0() : {defaults.FLOAT}", float, doc = "t0 from segments with z view - ns"), + seg2D_z_nHits = Var(f"? hasZed() ? zSegment().specificRecHits().size() : 0", "int8", doc = "# hits in z view - [0:4] range"), + seg2D_z_normChi2 = Var(f"? hasZed() ? (zSegment().chi2() / zSegment().degreesOfFreedom()) : {defaults.FLOAT_POS}", float, doc = "chi2/n.d.o.f. from segments with z view"), +) + +dtSegmentFlatTableProducer.detIdVariables = cms.PSet( + wheel = DetIdVar("wheel()", "int8", doc = "wheel - [-2:2] range"), + sector = DetIdVar("sector()", "int8", doc = "sector - [1:14] range" + "
sector 13 used for the second MB4 of sector 4" + "
sector 14 used for the second MB4 of sector 10"), + station = DetIdVar("station()", "int8", doc = "station - [1:4] range") +) + +dtSegmentFlatTableProducer.globalPosVariables = cms.PSet( + seg4D_posGlb_phi = GlobGeomVar("phi().value()", doc = "position phi in global coordinates - radians [-pi:pi]"), + seg4D_posGlb_eta = GlobGeomVar("eta()", doc = "position eta in global coordinates"), +) + +dtSegmentFlatTableProducer.globalDirVariables = cms.PSet( + seg4D_dirGlb_phi = GlobGeomVar("phi().value()", doc = "direction phi in global coordinates - radians [-pi:pi]"), + seg4D_dirGlb_eta = GlobGeomVar("eta()", doc = "direction eta in global coordinates"), +) + +from DPGAnalysis.MuonTools.muDTSegmentExtTableProducer_cfi import muDTSegmentExtTableProducer + +from DPGAnalysis.MuonTools.rpcRecHitFlatTableProducer_cfi import rpcRecHitFlatTableProducer + +rpcRecHitFlatTableProducer.name = "rpcRecHit" +rpcRecHitFlatTableProducer.src = "rpcRecHits" +rpcRecHitFlatTableProducer.doc = "RPC rec-hit information" + +rpcRecHitFlatTableProducer.variables = cms.PSet( + bx = Var("BunchX()", int, doc="bunch crossing number"), + time = Var("time()", float, doc = "time information in ns"), + firstClusterStrip = Var("firstClusterStrip()", "int8", doc = "lowest-numbered strip in the cluster"), + clusterSize = Var("clusterSize()", "int8", doc = "number of strips in the cluster"), + coordX = Var("localPosition().x()", float, doc = "position x in local coordinates - cm"), + coordY = Var("localPosition().y()", float, doc = "position y in local coordinates - cm"), + coordZ = Var("localPosition().z()", float, doc = "position z in local coordinates - cm"), +) + +rpcRecHitFlatTableProducer.detIdVariables = cms.PSet( + region = DetIdVar("region()", "int8", doc = "0: barrel, +-1: endcap"), + ring = DetIdVar("ring()", "int8", doc = "ring id:" + "
wheel number in barrel (from -2 to +2)" + "
ring number in endcap (from 1 to 3)"), + station = DetIdVar("station()", "int8", doc = "chambers at same R in barrel, chambers at same Z ion endcap"), + layer = DetIdVar("layer()", "int8", doc = "layer id:" + "
in station 1 and 2 for barrel, we have two layers of chambers:" + "
layer 1 is the inner chamber and layer 2 is the outer chamber"), + sector = DetIdVar("sector()", "int8", doc = "group of chambers at same phi"), + subsector = DetIdVar("subsector()", "int8", doc = "Some sectors are divided along the phi direction in subsectors " + "(from 1 to 4 in Barrel, from 1 to 6 in Endcap)"), + roll = DetIdVar("roll()", "int8", doc = "roll id (also known as eta partition):" + "
each chamber is divided along the strip direction"), + rawId = DetIdVar("rawId()", "uint", doc = "unique detector unit ID") +) + +from DPGAnalysis.MuonTools.gemRecHitFlatTableProducer_cfi import gemRecHitFlatTableProducer + +gemRecHitFlatTableProducer.name = "gemRecHit" +gemRecHitFlatTableProducer.src = "gemRecHits" +gemRecHitFlatTableProducer.doc = "GEM rec-hit information" + +gemRecHitFlatTableProducer.variables = cms.PSet( + bx = Var("BunchX()", int, doc="bunch crossing number"), + clusterSize = Var("clusterSize()", "int8", doc = "number of strips in the cluster"), loc_x = Var("localPosition().x()", float, doc = "hit position x in local coordinates - cm"), + firstClusterStrip = Var("firstClusterStrip()", "int8", doc = "lowest-numbered strip in the cluster"), + loc_phi = Var("localPosition().phi().value()", float, doc = "hit position phi in local coordinates - rad"), + loc_y = Var("localPosition().y()", float, doc = "hit position y in local coordinates - cm"), + loc_z = Var("localPosition().z()", float, doc = "hit position z in local coordinates - cm"), +) + +gemRecHitFlatTableProducer.detIdVariables = cms.PSet( + roll = DetIdVar("roll()", "int8", doc = "roll id, also known as eta partition:" + "
(partitions numbered from 1 to 8)"), + region = DetIdVar("region()", "int8", doc = "GE11 region where the hit is reconstructed" + "
(int, positive endcap: +1, negative endcap: -1)"), + chamber = DetIdVar("chamber()", "int8", doc = "GE11 superchamber where the hit is reconstructed" + "
(chambers numbered from 0 to 35)"), + layer = DetIdVar("layer()", "int8", doc = "GE11 layer where the hit is reconstructed" + "
(layer1: 1, layer2: 2)") +) + +gemRecHitFlatTableProducer.globalPosVariables = cms.PSet( + g_r = GlobGeomVar("perp()", doc = "hit position r in global coordinates - cm"), + g_phi = GlobGeomVar("phi().value()", doc = "hit position phi in global coordinates - radians [-pi:pi]"), + g_x = GlobGeomVar("x()", doc = "hit position x in global coordinates - cm"), + g_y = GlobGeomVar("y()", doc = "hit position y in global coordinates - cm"), + g_z = GlobGeomVar("z()", doc = "hit position z in global coordinates - cm") +) + +from DPGAnalysis.MuonTools.gemSegmentFlatTableProducer_cfi import gemSegmentFlatTableProducer + +gemSegmentFlatTableProducer.name = "gemSegment" +gemSegmentFlatTableProducer.src = "gemSegments" +gemSegmentFlatTableProducer.doc = "GEM segment information" + +gemSegmentFlatTableProducer.variables = cms.PSet( + chi2 = Var("chi2()", int, doc = "chi2 from segment fit"), + bx = Var("bunchX()", int, doc="bunch crossing number"), + posLoc_x = Var("localPosition().x()", float, doc = "position x in local coordinates - cm"), + posLoc_y = Var("localPosition().y()", float, doc = "position y in local coordinates - cm"), + posLoc_z = Var("localPosition().z()", float, doc = "position z in local coordinates - cm"), + dirLoc_x = Var("localDirection().x()", float, doc = "direction x in local coordinates"), + dirLoc_y = Var("localDirection().y()", float, doc = "direction y in local coordinates"), + dirLoc_z = Var("localDirection().z()", float, doc = "direction z in local coordinates"), +) + +gemSegmentFlatTableProducer.detIdVariables = cms.PSet( + region = DetIdVar("region()", "int8", doc = "GE11 region where the hit is reconstructed" + "
(int, positive endcap: +1, negative endcap: -1)"), + ring = DetIdVar("ring()", "int8", doc = ""), + station = DetIdVar("station()", "int8", doc = "GEM station
(always 1 for GE1/1)"), + chamber = DetIdVar("chamber()", "int8", doc = "GE11 superchamber where the hit is reconstructed" + "
(chambers numbered from 0 to 35)") +) + +gemSegmentFlatTableProducer.globalPosVariables = cms.PSet( + posGlb_x = GlobGeomVar("x()", doc = "position x in global coordinates - cm"), + posGlb_y = GlobGeomVar("y()", doc = "position y in global coordinates - cm"), + posGlb_z = GlobGeomVar("z()", doc = "position z in global coordinates - cm"), + posGlb_phi = GlobGeomVar("phi().value()", doc = "position phi in global coordinates - radians [-pi:pi]"), + posGlb_eta = GlobGeomVar("eta()", doc = "position eta in global coordinates"), +) + +gemSegmentFlatTableProducer.globalDirVariables = cms.PSet( + dirGlb_phi = GlobGeomVar("phi().value()", doc = "direction phi in global coordinates - radians [-pi:pi]"), + dirGlb_eta = GlobGeomVar("eta()", doc = "direction eta in global coordinates"), +) + +muLocalRecoProducers = cms.Sequence(rpcRecHitFlatTableProducer + + gemRecHitFlatTableProducer + + dtSegmentFlatTableProducer + + muDTSegmentExtTableProducer + + gemSegmentFlatTableProducer + ) diff --git a/DPGAnalysis/MuonTools/python/nano_mu_reco_cff.py b/DPGAnalysis/MuonTools/python/nano_mu_reco_cff.py new file mode 100644 index 0000000000000..1d4716f5099bf --- /dev/null +++ b/DPGAnalysis/MuonTools/python/nano_mu_reco_cff.py @@ -0,0 +1,66 @@ +import FWCore.ParameterSet.Config as cms + +from PhysicsTools.NanoAOD.common_cff import * +from DPGAnalysis.MuonTools.common_cff import * + +from PhysicsTools.NanoAOD.simpleCandidateFlatTableProducer_cfi import simpleCandidateFlatTableProducer + +from PhysicsTools.PatAlgos.producersLayer1.muonProducer_cfi import * + +muonFlatTableProducer = simpleCandidateFlatTableProducer.clone( + src = cms.InputTag("patMuons"), + name = cms.string("muon"), + doc = cms.string("RECO muon information"), + + variables = cms.PSet(CandVars, # CB is this including eta + isGlobal = Var("isGlobalMuon", bool, doc="muon is a global muon"), + isTracker = Var("isTrackerMuon", bool, doc="muon is a tracker muon"), + # isTrackerArb = Var("muon::isGoodMuon(muon, muon::TrackerMuonArbitrated)", bool, doc="muon is tracker muon arbitrated"), + isStandalone = Var("isStandAloneMuon", bool, doc="muon is a standalone muon"), + isRPC = Var("isRPCMuon", bool, doc="muon is an RPC muon"), + isGEM = Var("isGEMMuon", bool, doc="muon is a GEM muon"), + + isLoose = Var("passed('CutBasedIdLoose')", bool, doc="Loose muon ID"), + isMedium = Var("passed('CutBasedIdMedium')", bool, doc="Medium muon ID"), + isTight = Var("passed('CutBasedIdTight')", bool, doc="Tight muon ID"), + + pfIso04 = Var("(pfIsolationR04().sumChargedHadronPt + max(pfIsolationR04().sumNeutralHadronEt + pfIsolationR04().sumPhotonEt - pfIsolationR04().sumPUPt/2,0.0))/pt", float, doc="relative PF-isolation (delta beta corrected, 0.4 cone)", precision=6), + trkIso03 = Var("isolationR03().sumPt/tunePMuonBestTrack().pt", float, doc="relative tracker isolation (0.3 cone)", precision=6), + + trk_dz = Var(f"?!innerTrack().isNull()? dB('PVDZ') : {defaults.FLOAT}", float, doc="dz (with sign) wrt first PV - cm", precision=10), + trk_dxy = Var(f"?!innerTrack().isNull()? dB('PV2D') : {defaults.FLOAT}", float, doc="dxy (with sign) wrt first PV - cm", precision=10), + + trk_algo = Var(f"?!innerTrack().isNull()? innerTrack().algo() : {defaults.INT_POS}", "int8", doc="iterative tracking algorithm used to build the inner track"), + trk_origAlgo = Var(f"?!innerTrack().isNull()? innerTrack().originalAlgo() : {defaults.INT_POS}", "int8", doc="original (pre muon iterations) iterative tracking algorithm used to build the inner track"), + + trk_numberOfValidPixelHits = Var(f"?!innerTrack().isNull()? innerTrack().hitPattern().numberOfValidPixelHits() : {defaults.INT_POS}", "int8", doc="number of valid pixel hits"), + trk_numberOfValidTrackerLayers = Var(f"?!innerTrack().isNull()? innerTrack().hitPattern().trackerLayersWithMeasurement() : {defaults.INT_POS}", "int8", doc="number of valid tracker layers"), + trk_validFraction = Var(f"?!innerTrack().isNull()? innerTrack().validFraction() : {defaults.FLOAT_POS}", "int8", doc="fraction of tracker layer with muon hits"), + + trkMu_stationMask = Var("stationMask()", "uint8", doc="bit map of stations with tracks within given distance (in cm) of chamber edges"), + trkMu_numberOfMatchedStations = Var("numberOfMatchedStations()", "int8", doc="number of matched DT/CSC stations"), + rpcMu_numberOfMatchedRPCLayers = Var("numberOfMatchedRPCLayers()", "int8", doc="number of matched RPC layers"), + + staMu_numberOfValidMuonHits = Var(f"?isStandAloneMuon()? outerTrack().hitPattern().numberOfValidMuonHits() : {defaults.INT_POS}", "int8", doc="Number of valid muon hits"), + + staMu_normChi2 = Var(f"?isStandAloneMuon()? outerTrack().chi2()/outerTrack().ndof() : {defaults.FLOAT_POS}", float, doc="chi2/ndof (standalone track)", precision=10), + glbMu_normChi2 = Var(f"?isGlobalMuon()? globalTrack().chi2()/globalTrack().ndof() : {defaults.FLOAT_POS}", float, doc="chi2/ndof (global track)", precision=10) + ) +) + +from DPGAnalysis.MuonTools.muDTMuonExtTableProducer_cfi import muDTMuonExtTableProducer + +from RecoMuon.TrackingTools.MuonServiceProxy_cff import MuonServiceProxy + +from DPGAnalysis.MuonTools.muGEMMuonExtTableProducer_cfi import muGEMMuonExtTableProducer +muGEMMuonExtTableProducer.ServiceParameters = MuonServiceProxy.ServiceParameters + +from DPGAnalysis.MuonTools.muCSCTnPFlatTableProducer_cfi import muCSCTnPFlatTableProducer +muCSCTnPFlatTableProducer.ServiceParameters = MuonServiceProxy.ServiceParameters + +muRecoProducers = cms.Sequence(patMuons + + muonFlatTableProducer + + muDTMuonExtTableProducer + + muGEMMuonExtTableProducer + + muCSCTnPFlatTableProducer + ) diff --git a/DPGAnalysis/MuonTools/src/MuBaseFlatTableProducer.cc b/DPGAnalysis/MuonTools/src/MuBaseFlatTableProducer.cc new file mode 100644 index 0000000000000..3d5f183e71d8a --- /dev/null +++ b/DPGAnalysis/MuonTools/src/MuBaseFlatTableProducer.cc @@ -0,0 +1,22 @@ +/** \class MuBaseFlatTableProducer MuBaseFlatTableProducer.cc DPGAnalysis/MuonTools/src/MuBaseFlatTableProducer.cc + * + * Helper class defining the generic interface of a FlatTableProducer + * + * \author C. Battilana (INFN BO) + * + * + */ + +#include "DPGAnalysis/MuonTools/interface/MuBaseFlatTableProducer.h" + +MuBaseFlatTableProducer::MuBaseFlatTableProducer(const edm::ParameterSet &config) + : m_name{config.getParameter("name")} {} + +void MuBaseFlatTableProducer::beginRun(const edm::Run &run, const edm::EventSetup &environment) { + getFromES(run, environment); +} + +void MuBaseFlatTableProducer::produce(edm::Event &ev, const edm::EventSetup &environment) { + getFromES(environment); + fillTable(ev); +} diff --git a/DPGAnalysis/MuonTools/src/MuNtupleUtils.cc b/DPGAnalysis/MuonTools/src/MuNtupleUtils.cc new file mode 100644 index 0000000000000..96d5a98ab0e5c --- /dev/null +++ b/DPGAnalysis/MuonTools/src/MuNtupleUtils.cc @@ -0,0 +1,101 @@ +/* + * \file MuNtupleUtils.cc + * + * \author C. Battilana - INFN (BO) + * \author L. Giuducci - INFN (BO) +*/ + +#include "DPGAnalysis/MuonTools/interface/MuNtupleUtils.h" + +#include "DataFormats/L1DTTrackFinder/interface/L1MuDTChambPhDigi.h" +#include "DataFormats/L1DTTrackFinder/interface/L1Phase2MuDTPhDigi.h" + +#include "DataFormats/DTRecHit/interface/DTRecSegment4DCollection.h" + +// CB +// formulas to be re-checked +// can use template is_same, static_assert, enable_if ... + +nano_mu::DTTrigGeomUtils::DTTrigGeomUtils(edm::ConsumesCollector&& collector, bool dirInDeg) + : m_dtGeom{std::move(collector), "idealForDigi"} {} + +nano_mu::DTTrigGeomUtils::chambCoord nano_mu::DTTrigGeomUtils::trigToReco(const L1MuDTChambPhDigi* trig) { + auto wh{trig->whNum()}; + auto sec{trig->scNum() + 1}; + auto st{trig->stNum()}; + auto phi{trig->phi()}; + auto phib{trig->phiB()}; + + auto recoChamb = [&]() { + if (st != 4) { + return DTChamberId(wh, st, sec); + } + int reco_sec{(sec == 4 && phi > 0) ? 13 : (sec == 10 && phi > 0) ? 14 : sec}; + return DTChamberId(wh, st, reco_sec); + }; + + auto gpos{m_dtGeom->chamber(recoChamb())->position()}; + auto r{gpos.perp()}; + + auto delta_phi{gpos.phi() - (sec - 1) * Geom::pi() / 6}; + + // zcn is in local coordinates -> z invreases approching to vertex + // LG: zcn offset was removed <- CB do we need to fix this? + float x = r * tan((phi - (phi < 0 ? 1 : 0)) / PH1_PHI_R) * cos(delta_phi) - r * sin(delta_phi); + float dir = (phib / PH1_PHIB_R + phi / PH1_PHI_R); + + // change sign in case of positive wheels + if (hasPosRF(wh, sec)) { + x = -x; + } else { + dir = -dir; + } + + return {x, dir}; +} + +nano_mu::DTTrigGeomUtils::chambCoord nano_mu::DTTrigGeomUtils::trigToReco(const L1Phase2MuDTPhDigi* trig) { + auto wh{trig->whNum()}; + auto sec{trig->scNum() + 1}; + auto st{trig->stNum()}; + auto phi{trig->phi()}; + auto phib{trig->phiBend()}; + auto quality{trig->quality()}; + auto sl{trig->slNum()}; + + auto recoChamb = [&]() { + if (st != 4) { + return DTChamberId(wh, st, sec); + } + int reco_sec{(sec == 4 && phi > 0) ? 13 : (sec == 10 && phi > 0) ? 14 : sec}; + return DTChamberId(wh, st, reco_sec); + }; + + auto gpos{m_dtGeom->chamber(recoChamb())->position()}; + auto r{gpos.perp()}; + + auto delta_phi{gpos.phi() - (sec - 1) * Geom::pi() / 6}; + + // CB to be potentially updated based on Silvia's results + double zRF = 0; + if (quality >= 6 && quality != 7) + zRF = m_zcn[st - 1]; + if ((quality < 6 || quality == 7) && sl == 1) + zRF = m_zsl1[st - 1]; + if ((quality < 6 || quality == 7) && sl == 3) + zRF = m_zsl3[st - 1]; + + // zcn is in local coordinates -> z invreases approching to vertex + // LG: zcn offset was removed <- CB Mist confirm it is tryly accurate? + float x = r * tan((phi - (phi < 0 ? 1 : 0)) / PH1_PHI_R) * (cos(delta_phi) - zRF) - r * sin(delta_phi); + float dir = (phib / PH2_PHIB_R + phi / PH2_PHI_R); + + // change sign in case of positive wheels + if (hasPosRF(wh, sec)) { + x = -x; + } else { + dir = -dir; + } + + return {x, dir}; +} diff --git a/DPGAnalysis/MuonTools/test/muDpgNtuplesRaw_cfg.py b/DPGAnalysis/MuonTools/test/muDpgNtuplesRaw_cfg.py new file mode 100644 index 0000000000000..10b5d3e3e9d94 --- /dev/null +++ b/DPGAnalysis/MuonTools/test/muDpgNtuplesRaw_cfg.py @@ -0,0 +1,87 @@ +import FWCore.ParameterSet.Config as cms +import FWCore.ParameterSet.VarParsing as VarParsing +from Configuration.StandardSequences.Eras import eras +from Configuration.AlCa.GlobalTag import GlobalTag + +import subprocess +import sys + +options = VarParsing.VarParsing() + +options.register('globalTag', + '124X_dataRun3_Prompt_v4', #default value + VarParsing.VarParsing.multiplicity.singleton, + VarParsing.VarParsing.varType.string, + "Global Tag") + +options.register('nEvents', + 1000, #default value + VarParsing.VarParsing.multiplicity.singleton, + VarParsing.VarParsing.varType.int, + "Maximum number of processed events") + +options.register('inputFile', + '/store/data/Run2022E/ZeroBias/RAW/v1/000/359/751/00000/6ee95dd0-8fb4-4693-90b9-f7a3fbd2fdeb.root', #default value + VarParsing.VarParsing.multiplicity.singleton, + VarParsing.VarParsing.varType.string, + "EOS folder with input files") + +options.register('ntupleName', + './MuDPGNtuple_nanoAOD_ZeroBias.root', #default value + VarParsing.VarParsing.multiplicity.singleton, + VarParsing.VarParsing.varType.string, + "Folder and name ame for output ntuple") + +options.parseArguments() + +process = cms.Process("MUNTUPLES",eras.Run3) + +process.load('FWCore.MessageService.MessageLogger_cfi') + +process.options = cms.untracked.PSet( wantSummary = cms.untracked.bool(True), + numberOfThreads = cms.untracked.uint32(4)) +process.MessageLogger.cerr.FwkReport.reportEvery = 100 +process.maxEvents = cms.untracked.PSet(input = cms.untracked.int32(options.nEvents)) + +process.load('Configuration.StandardSequences.FrontierConditions_GlobalTag_cff') +process.GlobalTag.globaltag = cms.string(options.globalTag) + +process.source = cms.Source("PoolSource", + fileNames = cms.untracked.vstring(options.inputFile), + secondaryFileNames = cms.untracked.vstring() +) + +process.load('Configuration/StandardSequences/GeometryRecoDB_cff') +process.load("Configuration.StandardSequences.MagneticField_cff") + +process.load('Configuration.StandardSequences.RawToDigi_Data_cff') +process.load('RecoLocalMuon.Configuration.RecoLocalMuon_cff') + +process.load('DPGAnalysis.MuonTools.muNtupleProducerRaw_cff') + +import EventFilter.RPCRawToDigi.rpcUnpacker_cfi +process.muonRPCDigis = EventFilter.RPCRawToDigi.rpcUnpacker_cfi.rpcunpacker.clone() + +process.nanoMuDPGPath = cms.Path(process.muonDTDigis + + process.muonCSCDigis + + process.muonRPCDigis + + process.muonGEMDigis + + process.rpcRecHits + + process.gemRecHits + + process.muNtupleProducerRaw) + +process.load("PhysicsTools.NanoAOD.NanoAODEDMEventContent_cff") + +process.out = cms.OutputModule("NanoAODOutputModule", + fileName = cms.untracked.string(options.ntupleName), + outputCommands = process.NANOAODEventContent.outputCommands \ + + ["keep nanoaodFlatTable_*_*_*", + "drop edmTriggerResults_*_*_*"], + SelectEvents = cms.untracked.PSet( + SelectEvents=cms.vstring("nanoMuDPGPath") + ) +) + +process.end = cms.EndPath(process.out) + +process.schedule = cms.Schedule(process.nanoMuDPGPath, process.end) diff --git a/DPGAnalysis/MuonTools/test/muDpgNtuplesZMu_cfg.py b/DPGAnalysis/MuonTools/test/muDpgNtuplesZMu_cfg.py new file mode 100644 index 0000000000000..089cfeca4783a --- /dev/null +++ b/DPGAnalysis/MuonTools/test/muDpgNtuplesZMu_cfg.py @@ -0,0 +1,99 @@ +import FWCore.ParameterSet.Config as cms +import FWCore.ParameterSet.VarParsing as VarParsing +from Configuration.StandardSequences.Eras import eras +from Configuration.AlCa.GlobalTag import GlobalTag + +import subprocess +import sys + +options = VarParsing.VarParsing() + +options.register('globalTag', + '125X_dataRun3_relval_v4', #default value + VarParsing.VarParsing.multiplicity.singleton, + VarParsing.VarParsing.varType.string, + "Global Tag") + +options.register('nEvents', + 1000, #default value + VarParsing.VarParsing.multiplicity.singleton, + VarParsing.VarParsing.varType.int, + "Maximum number of processed events") + +options.register('inputFile', + '/store/relval/CMSSW_12_6_0_pre5/SingleMuon/FEVTDEBUGHLT/125X_dataRun3_HLT_relval_v3_RelVal_2022C-v2/2590000//053845fa-aa05-48a3-8bc0-c833cfdd3e53.root', #default value + VarParsing.VarParsing.multiplicity.singleton, + VarParsing.VarParsing.varType.string, + "EOS folder with input files") + +options.register('ntupleName', + './MuDPGNtuple_nanoAOD_ZMuSkim.root', #default value + VarParsing.VarParsing.multiplicity.singleton, + VarParsing.VarParsing.varType.string, + "Folder and name ame for output ntuple") + +options.register('runOnMC', + False, #default value + VarParsing.VarParsing.multiplicity.singleton, + VarParsing.VarParsing.varType.bool, + "Apply customizations to run on MC") + +options.parseArguments() + +process = cms.Process("MUNTUPLES",eras.Run3) + +process.load('FWCore.MessageService.MessageLogger_cfi') + +process.options = cms.untracked.PSet( wantSummary = cms.untracked.bool(True), + numberOfThreads = cms.untracked.uint32(4)) +process.MessageLogger.cerr.FwkReport.reportEvery = 100 +process.maxEvents = cms.untracked.PSet(input = cms.untracked.int32(options.nEvents)) + +process.load('Configuration.StandardSequences.FrontierConditions_GlobalTag_cff') +process.GlobalTag.globaltag = cms.string(options.globalTag) + +process.source = cms.Source("PoolSource", + fileNames = cms.untracked.vstring(options.inputFile), + secondaryFileNames = cms.untracked.vstring() +) + +process.load('Configuration/StandardSequences/GeometryRecoDB_cff') +process.load("Configuration.StandardSequences.MagneticField_cff") + +process.load("TrackingTools/TransientTrack/TransientTrackBuilder_cfi") +process.load('TrackPropagation.SteppingHelixPropagator.SteppingHelixPropagatorAny_cfi') +process.load('TrackPropagation.SteppingHelixPropagator.SteppingHelixPropagatorAlong_cfi') +process.load('TrackPropagation.SteppingHelixPropagator.SteppingHelixPropagatorOpposite_cfi') + +process.load('Configuration.StandardSequences.RawToDigi_Data_cff') +process.load('DPGAnalysis.MuonTools.muNtupleProducer_cff') + +import EventFilter.RPCRawToDigi.rpcUnpacker_cfi +process.muonRPCDigis = EventFilter.RPCRawToDigi.rpcUnpacker_cfi.rpcunpacker.clone() + +process.nanoMuDPGPath = cms.Path(process.muonDTDigis + + process.muonRPCDigis + + process.muonGEMDigis + + process.twinMuxStage2Digis + + process.bmtfDigis + + process.muNtupleProducer) + +process.load("PhysicsTools.NanoAOD.NanoAODEDMEventContent_cff") + +process.out = cms.OutputModule("NanoAODOutputModule", + fileName = cms.untracked.string(options.ntupleName), + outputCommands = process.NANOAODEventContent.outputCommands \ + + ["keep nanoaodFlatTable_*_*_*", + "drop edmTriggerResults_*_*_*"], + SelectEvents = cms.untracked.PSet( + SelectEvents=cms.vstring("nanoMuDPGPath") + ) +) + +process.end = cms.EndPath(process.out) + +process.schedule = cms.Schedule(process.nanoMuDPGPath, process.end) + +if options.runOnMC : + from DPGAnalysis.MuonTools.customiseMuNtuples_cff import customiseForRunningOnMC + customiseForRunningOnMC(process,"p")