Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 14:23:19

0001 #include <iostream>
0002 #include <memory>
0003 
0004 #include "FWCore/Framework/interface/ModuleFactory.h"
0005 #include "FWCore/Framework/interface/ESProducer.h"
0006 #include "FWCore/Framework/interface/ESHandle.h"
0007 #include "FWCore/Framework/interface/ESProducts.h"
0008 
0009 #include "CondFormats/L1TObjects/interface/L1TMuonEndCapForest.h"
0010 #include "CondFormats/DataRecord/interface/L1TMuonEndCapForestRcd.h"
0011 
0012 #include "L1Trigger/L1TMuonEndCap/interface/PtAssignmentEngine.h"
0013 #include "L1Trigger/L1TMuonEndCap/interface/PtAssignmentEngine2016.h"
0014 #include "L1Trigger/L1TMuonEndCap/interface/PtAssignmentEngine2017.h"
0015 #include "L1Trigger/L1TMuonEndCap/interface/bdt/Node.h"
0016 #include "L1Trigger/L1TMuonEndCap/interface/bdt/Tree.h"
0017 #include "L1Trigger/L1TMuonEndCap/interface/bdt/Forest.h"
0018 
0019 using namespace std;
0020 
0021 // class declaration
0022 
0023 class L1TMuonEndCapForestESProducer : public edm::ESProducer {
0024 public:
0025   L1TMuonEndCapForestESProducer(const edm::ParameterSet&);
0026   ~L1TMuonEndCapForestESProducer() override {}
0027 
0028   using ReturnType = std::unique_ptr<L1TMuonEndCapForest>;
0029 
0030   ReturnType produce(const L1TMuonEndCapForestRcd&);
0031 
0032 private:
0033   int ptLUTVersion;
0034   string bdtXMLDir;
0035 
0036   L1TMuonEndCapForest::DTree traverse(emtf::Node* tree);
0037 };
0038 
0039 // constructor
0040 
0041 L1TMuonEndCapForestESProducer::L1TMuonEndCapForestESProducer(const edm::ParameterSet& iConfig) {
0042   setWhatProduced(this);
0043 
0044   ptLUTVersion = iConfig.getParameter<int>("PtAssignVersion");
0045   bdtXMLDir = iConfig.getParameter<string>("bdtXMLDir");
0046 }
0047 
0048 // member functions
0049 
0050 L1TMuonEndCapForest::DTree L1TMuonEndCapForestESProducer::traverse(emtf::Node* node) {
0051   // original implementation use 0 ptr for non-existing children nodes, return empty cond tree (vector of nodes)
0052   if (!node)
0053     return L1TMuonEndCapForest::DTree();
0054   // recur on left and then right child
0055   L1TMuonEndCapForest::DTree left_subtree = traverse(node->getLeftDaughter());
0056   L1TMuonEndCapForest::DTree right_subtree = traverse(node->getRightDaughter());
0057   // allocate tree
0058   L1TMuonEndCapForest::DTree cond_tree(1 + left_subtree.size() + right_subtree.size());
0059   // copy the local root node
0060   L1TMuonEndCapForest::DTreeNode& local_root = cond_tree[0];
0061   local_root.splitVar = node->getSplitVariable();
0062   local_root.splitVal = node->getSplitValue();
0063   local_root.fitVal = node->getFitValue();
0064   // shift children indicies and place the subtrees into the newly allocated tree
0065   local_root.ileft =
0066       (!left_subtree.empty() ? 1 : 0);  // left subtree (if exists) is placed right after the root -> index=1
0067   transform(left_subtree.cbegin(),      // source from
0068             left_subtree.cend(),        // source till
0069             cond_tree.begin() + 1,      // destination
0070             [](L1TMuonEndCapForest::DTreeNode cond_node) {
0071               // increment indecies only for existing children, left 0 for non-existing
0072               if (cond_node.ileft)
0073                 cond_node.ileft += 1;
0074               if (cond_node.iright)
0075                 cond_node.iright += 1;
0076               return cond_node;
0077             });
0078   unsigned int offset = left_subtree.size();
0079   local_root.iright = (offset + right_subtree.size() ? 1 + offset : 0);  // right subtree is placed after the left one
0080   transform(right_subtree.cbegin(),                                      // source from
0081             right_subtree.cend(),                                        // source till
0082             cond_tree.begin() + 1 + offset,                              // destination
0083             [offset](L1TMuonEndCapForest::DTreeNode cond_node) {
0084               // increment indecies only for existing children, left 0 for non-existing
0085               if (cond_node.ileft)
0086                 cond_node.ileft += 1 + offset;
0087               if (cond_node.iright)
0088                 cond_node.iright += 1 + offset;
0089               return cond_node;
0090             });
0091   return cond_tree;
0092 }
0093 
0094 L1TMuonEndCapForestESProducer::ReturnType L1TMuonEndCapForestESProducer::produce(const L1TMuonEndCapForestRcd& iRecord) {
0095   // piggyback on the PtAssignmentEngine class to read the XMLs in
0096   PtAssignmentEngine* pt_assign_engine_;
0097   std::unique_ptr<PtAssignmentEngine> pt_assign_engine_2016_;
0098   std::unique_ptr<PtAssignmentEngine> pt_assign_engine_2017_;
0099 
0100   pt_assign_engine_2016_ = std::make_unique<PtAssignmentEngine2016>();
0101   pt_assign_engine_2017_ = std::make_unique<PtAssignmentEngine2017>();
0102 
0103   if (ptLUTVersion <= 5)
0104     pt_assign_engine_ = pt_assign_engine_2016_.get();
0105   else
0106     pt_assign_engine_ = pt_assign_engine_2017_.get();
0107 
0108   pt_assign_engine_->read(ptLUTVersion, bdtXMLDir);
0109 
0110   // get a hold on the forests; copy to non-const locals
0111   std::array<emtf::Forest, 16> forests = pt_assign_engine_->getForests();
0112   std::vector<int> allowedModes = pt_assign_engine_->getAllowedModes();
0113   // construct empty cond payload
0114   auto pEMTFForest = std::make_unique<L1TMuonEndCapForest>();
0115   // pack the forests into the cond payload for each mode
0116   pEMTFForest->forest_coll_.resize(0);
0117   for (unsigned int i = 0; i < allowedModes.size(); i++) {
0118     int mode = allowedModes[i];
0119     pEMTFForest->forest_map_[mode] = i;
0120     // convert emtf::Forest into the L1TMuonEndCapForest::DForest
0121     emtf::Forest& forest = forests.at(mode);
0122     // Store boostWeight (initial pT value of tree 0) as an integer: boostWeight x 1 million
0123     pEMTFForest->forest_map_[mode + 16] = forest.getTree(0)->getBoostWeight() * 1000000;
0124     L1TMuonEndCapForest::DForest cond_forest;
0125     for (unsigned int j = 0; j < forest.size(); j++)
0126       cond_forest.push_back(traverse(forest.getTree(j)->getRootNode()));
0127     // of course, move has no effect here, but I'll keep it in case move constructor will be provided some day
0128     pEMTFForest->forest_coll_.push_back(std::move(cond_forest));
0129   }
0130 
0131   return pEMTFForest;
0132 }
0133 
0134 // Define this as a plug-in
0135 DEFINE_FWK_EVENTSETUP_MODULE(L1TMuonEndCapForestESProducer);