HLTLevel1Pattern

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
/** \class HLTLevel1Pattern
 *
 *
 *  This class is an EDFilter
 *  that checks for a specific pattern of L1 accept/reject in 5 BX's for a given L1 bit
 *  It can be configured to use or ignore the L1 trigger mask
 *
 *
 *  \author Andrea Bocci
 *
 */

#include <vector>

#include "FWCore/Framework/interface/ESWatcher.h"
#include "FWCore/Framework/interface/Frameworkfwd.h"
#include "FWCore/Framework/interface/Event.h"
#include "FWCore/Framework/interface/stream/EDFilter.h"
#include "FWCore/Utilities/interface/InputTag.h"
#include "FWCore/Utilities/interface/Exception.h"
#include "FWCore/ParameterSet/interface/ParameterSet.h"
#include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
#include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
#include "CondFormats/DataRecord/interface/L1GtTriggerMenuRcd.h"
#include "CondFormats/DataRecord/interface/L1GtTriggerMaskTechTrigRcd.h"
#include "CondFormats/DataRecord/interface/L1GtTriggerMaskAlgoTrigRcd.h"
#include "CondFormats/L1TObjects/interface/L1GtTriggerMenu.h"
#include "CondFormats/L1TObjects/interface/L1GtTriggerMenuFwd.h"
#include "CondFormats/L1TObjects/interface/L1GtTriggerMask.h"
#include "DataFormats/L1GlobalTrigger/interface/L1GlobalTriggerReadoutRecord.h"

//
// class declaration
//

class HLTLevel1Pattern : public edm::stream::EDFilter<> {
public:
  explicit HLTLevel1Pattern(const edm::ParameterSet&);
  ~HLTLevel1Pattern() override;
  static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
  bool filter(edm::Event&, const edm::EventSetup&) override;

private:
  const edm::InputTag m_gtReadoutRecord;
  const edm::EDGetTokenT<L1GlobalTriggerReadoutRecord> m_gtReadoutRecordToken;
  const std::string m_triggerBit;
  const std::vector<int> m_bunchCrossings;
  std::vector<int> m_triggerPattern;
  const unsigned int m_daqPartitions;
  unsigned int m_triggerNumber;
  bool m_triggerAlgo;
  bool m_triggerMasked;
  const bool m_ignoreL1Mask;
  const bool m_invert;
  const bool m_throw;

  edm::ESGetToken<L1GtTriggerMenu, L1GtTriggerMenuRcd> const m_l1GtTriggerMenuToken;
  edm::ESGetToken<L1GtTriggerMask, L1GtTriggerMaskAlgoTrigRcd> const m_l1GtTriggerMaskAlgoTrigRcdToken;
  edm::ESGetToken<L1GtTriggerMask, L1GtTriggerMaskTechTrigRcd> const m_l1GtTriggerMaskTechTrigRcdToken;

  edm::ESWatcher<L1GtTriggerMenuRcd> m_watchL1Menu;
  edm::ESWatcher<L1GtTriggerMaskAlgoTrigRcd> m_watchPhysicsMask;
  edm::ESWatcher<L1GtTriggerMaskTechTrigRcd> m_watchTechnicalMask;
};

#include "FWCore/Framework/interface/EventSetup.h"
#include "FWCore/MessageLogger/interface/MessageLogger.h"
#include "CondFormats/L1TObjects/interface/L1GtTriggerMenu.h"
#include "CondFormats/L1TObjects/interface/L1GtTriggerMask.h"

//
// constructors and destructor
//
HLTLevel1Pattern::HLTLevel1Pattern(const edm::ParameterSet& config)
    : m_gtReadoutRecord(config.getParameter<edm::InputTag>("L1GtReadoutRecordTag")),
      m_gtReadoutRecordToken(consumes<L1GlobalTriggerReadoutRecord>(m_gtReadoutRecord)),
      m_triggerBit(config.getParameter<std::string>("triggerBit")),
      m_bunchCrossings(config.getParameter<std::vector<int> >("bunchCrossings")),
      m_triggerPattern(m_bunchCrossings.size(), false),
      m_daqPartitions(config.getParameter<unsigned int>("daqPartitions")),
      m_triggerNumber(0),
      m_triggerAlgo(true),
      m_triggerMasked(false),
      m_ignoreL1Mask(config.getParameter<bool>("ignoreL1Mask")),
      m_invert(config.getParameter<bool>("invert")),
      m_throw(config.getParameter<bool>("throw")),
      m_l1GtTriggerMenuToken(esConsumes()),
      m_l1GtTriggerMaskAlgoTrigRcdToken(esConsumes()),
      m_l1GtTriggerMaskTechTrigRcdToken(esConsumes()) {
  std::vector<int> pattern(config.getParameter<std::vector<int> >("triggerPattern"));
  if (pattern.size() != m_bunchCrossings.size())
    throw cms::Exception("Configuration") << "\"bunchCrossings\" and \"triggerPattern\" parameters do not match";

  for (unsigned int i = 0; i < pattern.size(); ++i)
    m_triggerPattern[i] = (bool)pattern[i];
}

HLTLevel1Pattern::~HLTLevel1Pattern() = default;

void HLTLevel1Pattern::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
  edm::ParameterSetDescription desc;
  desc.add<edm::InputTag>("L1GtReadoutRecordTag", edm::InputTag("hltGtDigis"));
  desc.add<std::string>("triggerBit", "L1Tech_RPC_TTU_pointing_Cosmics.v0");
  {
    std::vector<int> temp1;
    temp1.reserve(5);
    temp1.push_back(-2);
    temp1.push_back(-1);
    temp1.push_back(0);
    temp1.push_back(1);
    temp1.push_back(2);
    desc.add<std::vector<int> >("bunchCrossings", temp1);
  }
  desc.add<unsigned int>("daqPartitions", 1);
  desc.add<bool>("ignoreL1Mask", false);
  desc.add<bool>("invert", false);
  desc.add<bool>("throw", true);
  {
    std::vector<int> temp1;
    temp1.reserve(5);
    temp1.push_back(1);
    temp1.push_back(1);
    temp1.push_back(1);
    temp1.push_back(0);
    temp1.push_back(0);
    desc.add<std::vector<int> >("triggerPattern", temp1);
  }
  descriptions.add("hltLevel1Pattern", desc);
}

//
// member functions
//

// ------------ method called to produce the data  ------------
bool HLTLevel1Pattern::filter(edm::Event& event, const edm::EventSetup& setup) {
  // determine the L1 algo or tech bit to use
  if (m_watchL1Menu.check(setup)) {
    auto const& h_menu = setup.getHandle(m_l1GtTriggerMenuToken);
    // look for an Algo L1 bit
    const AlgorithmMap& algoMap = h_menu->gtAlgorithmAliasMap();
    const AlgorithmMap& techMap = h_menu->gtTechnicalTriggerMap();
    AlgorithmMap::const_iterator entry;
    if ((entry = algoMap.find(m_triggerBit)) != algoMap.end()) {
      m_triggerAlgo = true;
      m_triggerNumber = entry->second.algoBitNumber();
    } else if ((entry = techMap.find(m_triggerBit)) != techMap.end()) {
      m_triggerAlgo = false;
      m_triggerNumber = entry->second.algoBitNumber();
    } else {
      if (m_throw) {
        throw cms::Exception("Configuration")
            << "requested L1 trigger \"" << m_triggerBit << "\" does not exist in the current L1 menu";
      } else {
        return m_invert;
      }
    }
  }

  if (m_triggerAlgo) {
    // check the L1 algorithms mask
    //  - mask & partition == part. --> fully masked
    //  - mask & partition == 0x00  --> fully unmasked
    //  - mask & partition != part. --> unmasked in some partitions, consider as unmasked
    if (m_watchPhysicsMask.check(setup)) {
      auto const& h_mask = setup.getHandle(m_l1GtTriggerMaskAlgoTrigRcdToken);
      m_triggerMasked = ((h_mask->gtTriggerMask()[m_triggerNumber] & m_daqPartitions) == m_daqPartitions);
    }
  } else {
    // check the L1 technical triggers mask
    //  - mask & partition == part. --> fully masked
    //  - mask & partition == 0x00  --> fully unmasked
    //  - mask & partition != part. --> unmasked in some partitions, consider as unmasked
    if (m_watchTechnicalMask.check(setup)) {
      auto const& h_mask = setup.getHandle(m_l1GtTriggerMaskTechTrigRcdToken);
      m_triggerMasked = ((h_mask->gtTriggerMask()[m_triggerNumber] & m_daqPartitions) == m_daqPartitions);
    }
  }

  // is the L1 trigger masked ?
  if (not m_ignoreL1Mask and m_triggerMasked)
    return m_invert;

  // access the L1 decisions
  edm::Handle<L1GlobalTriggerReadoutRecord> h_gtReadoutRecord;
  event.getByToken(m_gtReadoutRecordToken, h_gtReadoutRecord);

  // check the L1 algorithms results
  for (unsigned int i = 0; i < m_bunchCrossings.size(); ++i) {
    int bx = m_bunchCrossings[i];
    const std::vector<bool>& word =
        (m_triggerAlgo) ? h_gtReadoutRecord->decisionWord(bx) : h_gtReadoutRecord->technicalTriggerWord(bx);
    if (word.empty() or m_triggerNumber >= word.size())
      // L1 results not available, bail out
      return m_invert;
    bool result = word[m_triggerNumber];
    if (result != m_triggerPattern[i])
      // comparison failed, bail out
      return m_invert;
  }

  // comparison successful
  return not m_invert;
}

// define as a framework plugin
#include "FWCore/Framework/interface/MakerMacros.h"
DEFINE_FWK_MODULE(HLTLevel1Pattern);