Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 13:33:04

0001 // -*- C++ -*-
0002 //
0003 // Package:    PatAlgos
0004 // Class:      PATUserDataTestModule
0005 //
0006 /**\class PATUserDataTestModule PATUserDataTestModule.cc PhysicsTools/PatAlgos/test/PATUserDataTestModule.cc
0007 
0008  Description: Test module for UserData in PAT
0009 
0010  Implementation:
0011 
0012  this analyzer shows how to loop over PAT output.
0013 */
0014 //
0015 // Original Author:  Freya Blekman
0016 //         Created:  Mon Apr 21 10:03:50 CEST 2008
0017 //
0018 //
0019 
0020 // system include files
0021 #include <memory>
0022 
0023 // user include files
0024 #include "FWCore/Framework/interface/Frameworkfwd.h"
0025 #include "FWCore/Framework/interface/EDProducer.h"
0026 
0027 #include "FWCore/Framework/interface/Event.h"
0028 #include "FWCore/Framework/interface/MakerMacros.h"
0029 
0030 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0031 #include "FWCore/Utilities/interface/InputTag.h"
0032 
0033 #include "DataFormats/PatCandidates/interface/Muon.h"
0034 
0035 #include "DataFormats/Common/interface/View.h"
0036 #include "DataFormats/Common/interface/ValueMap.h"
0037 #include "DataFormats/Common/interface/OwnVector.h"
0038 
0039 #include <string>
0040 
0041 // BEGIN CRAZY WORKAROUND
0042 namespace edm {
0043   using ::std::advance;
0044 }
0045 // END CRAZY WORKAROUND
0046 /*  Exmplanation of  the above crazy workaround:
0047     1) edm::Ptr uses 'advance' free function to locate a given item within a collection
0048     2) 'advance' is defined in  the std::namespace for std containers (e.g. vector)
0049        http://www.sgi.com/tech/stl/advance.html
0050     3) In edm::Ptr sources, we use 'advance'  without namespace prefix
0051        http://cmslxr.fnal.gov/lxr/source/DataFormats/Common/interface/Ptr.h?v=CMSSW_2_1_10#214
0052     4) This normally work because the container is std:: so the free function is resolved in the
0053        correct namespace (don't ask me why or how it works; Ask Marc, Bill or read C++ standards)
0054     5) The hack 'namespace edm { using ::std::advance; }' imports std::advance into edm namespace,
0055        so that it works. Apparently the default implementation of std::advance is ok also for the
0056        iterator of the OwnVector
0057     6) Anyway, this should be solved upstream in OwnVector.h
0058 
0059             gpetruc
0060 */
0061 
0062 //
0063 // class decleration
0064 //
0065 
0066 class PATUserDataTestModule : public edm::EDProducer {
0067 public:
0068   explicit PATUserDataTestModule(const edm::ParameterSet&);
0069   ~PATUserDataTestModule();
0070 
0071 private:
0072   virtual void produce(edm::Event&, const edm::EventSetup&) override;
0073 
0074   // ----------member data ---------------------------
0075   edm::EDGetTokenT<edm::View<pat::Muon>> muonsToken_;
0076   std::string label_;
0077   enum TestMode { TestRead, TestWrite, TestExternal };
0078   TestMode mode_;
0079 };
0080 
0081 //
0082 // constructors and destructor
0083 //
0084 PATUserDataTestModule::PATUserDataTestModule(const edm::ParameterSet& iConfig)
0085     : muonsToken_(consumes<edm::View<pat::Muon>>(iConfig.getParameter<edm::InputTag>("muons"))),
0086       label_(iConfig.existsAs<std::string>("label") ? iConfig.getParameter<std::string>("label") : ""),
0087       mode_(iConfig.getParameter<std::string>("mode") == "write"
0088                 ? TestWrite
0089                 : (iConfig.getParameter<std::string>("mode") == "read" ? TestRead : TestExternal))
0090 
0091 {
0092   if (mode_ != TestExternal) {
0093     produces<std::vector<pat::Muon>>();
0094   } else {
0095     produces<edm::ValueMap<int>>(label_);
0096     produces<edm::ValueMap<float>>();
0097     produces<edm::OwnVector<pat::UserData>>();
0098     produces<edm::ValueMap<edm::Ptr<pat::UserData>>>();
0099   }
0100 }
0101 
0102 PATUserDataTestModule::~PATUserDataTestModule() {}
0103 
0104 // ------------ method called to for each event  ------------
0105 void PATUserDataTestModule::produce(edm::Event& iEvent, const edm::EventSetup& iSetup) {
0106   using namespace edm;
0107 
0108   // I need to define a type for which we don't have a dictionary in CMSSW. I hope this is crazy enough.
0109   typedef std::pair<std::map<std::string, pat::Muon>, std::vector<math::XYZVector>> CrazyDataType;
0110 
0111   if (mode_ != TestExternal) {
0112     edm::Handle<View<pat::Muon>> muons;
0113     iEvent.getByToken(muonsToken_, muons);
0114 
0115     auto output = std::make_unique<std::vector<pat::Muon>>();
0116 
0117     for (View<pat::Muon>::const_iterator muon = muons->begin(), end = muons->end(); muon != end; ++muon) {
0118       if (mode_ == TestWrite) {
0119         pat::Muon myMuon = *muon;  // copy
0120         myMuon.addUserInt("answer", 42);
0121         myMuon.addUserFloat("pi", 3.14);
0122         myMuon.addUserData("half p4", 0.5 * muon->p4());
0123 
0124         //// This shoud throw an exception because we don't have the wrapper type
0125         //myMuon.addUserData("self", *muon);
0126         //// This should throw an exception because we don't have the dictionary (I hope)
0127         // myMuon.addUserData("crazy", CrazyDataType());
0128         //// These instead should not throw an exception as long as they don't get saved on disk
0129         // myMuon.addUserData("tmp self", *muon, true);
0130         // myMuon.addUserData("tmp crazy", CrazyDataType(), true);
0131 
0132         output->push_back(std::move(myMuon));
0133       } else {
0134         std::cout << "Muon #" << (muon - muons->begin()) << ":" << std::endl;
0135         std::cout << "\tanswer   = " << muon->userInt("answer") << std::endl;
0136         std::cout << "\tanswer:il= " << muon->userInt("answer:il") << std::endl;
0137         std::cout << "\tpi       = " << muon->userFloat("pi") << std::endl;
0138         std::cout << "\tmiss int = " << muon->userInt("missing int") << std::endl;
0139         std::cout << "\tmiss flt = " << muon->userFloat("missing flt") << std::endl;
0140         std::cout << "\t# u d    = " << muon->userDataNames().size() << std::endl;
0141         std::cout << "\tud nam[0]= " << muon->userDataNames()[0] << std::endl;
0142         std::cout << "\thas p4/2 = " << muon->hasUserData("half p4") << std::endl;
0143         if (muon->hasUserData("half p4")) {
0144           std::cout << "\ttyp p4/2 = " << muon->userDataObjectType("half p4") << std::endl;
0145           std::cout << "\tval p4/2 = " << (*muon->userData<reco::Particle::LorentzVector>("half p4"))
0146                     << "  == " << (0.5 * muon->p4()) << std::endl;
0147         }
0148         if (muon->hasUserData("tmp self")) {
0149           std::cout << "\tself.pt  = " << muon->userData<pat::Muon>("tmp self")->pt() << "  == " << muon->pt()
0150                     << std::endl;
0151         }
0152         if (muon->hasUserData("tmp crazy")) {
0153           std::cout << "\tcrazy.siz= " << muon->userData<CrazyDataType>("tmp crazy")->second.size() << "  == 0 "
0154                     << std::endl;
0155         }
0156         if (muon->hasUserData("halfP4")) {
0157           std::cout << "\ttyp P4/2 = " << muon->userDataObjectType("halfP4") << std::endl;
0158           std::cout << "\tval P4/2 = " << (*muon->userData<reco::Particle::LorentzVector>("halfP4"))
0159                     << "  == " << (0.5 * muon->p4()) << std::endl;
0160         }
0161       }
0162     }
0163     iEvent.put(std::move(output));
0164   } else {
0165     using namespace std;
0166     Handle<View<reco::Muon>> recoMuons;
0167     iEvent.getByToken(muonsToken_, recoMuons);
0168     std::cout << "Got " << recoMuons->size() << " muons" << std::endl;
0169 
0170     vector<int> ints(recoMuons->size(), 42);
0171     auto answers = std::make_unique<ValueMap<int>>();
0172     ValueMap<int>::Filler intfiller(*answers);
0173     intfiller.insert(recoMuons, ints.begin(), ints.end());
0174     intfiller.fill();
0175     iEvent.put(std::move(answers), label_);
0176     std::cout << "Filled in the answer" << std::endl;
0177 
0178     vector<float> floats(recoMuons->size(), 3.14);
0179     auto pis = std::make_unique<ValueMap<float>>();
0180     ValueMap<float>::Filler floatfiller(*pis);
0181     floatfiller.insert(recoMuons, floats.begin(), floats.end());
0182     floatfiller.fill();
0183     iEvent.put(std::move(pis));
0184     std::cout << "Wrote useless floats into the event" << std::endl;
0185 
0186     auto halfp4s = std::make_unique<OwnVector<pat::UserData>>();
0187     for (size_t i = 0; i < recoMuons->size(); ++i) {
0188       halfp4s->push_back(pat::UserData::make(0.5 * (*recoMuons)[i].p4()));
0189     }
0190     OrphanHandle<OwnVector<pat::UserData>> handle = iEvent.put(std::move(halfp4s));
0191     std::cout << "Wrote OwnVector of useless objects into the event" << std::endl;
0192     vector<Ptr<pat::UserData>> halfp4sPtr;
0193     for (size_t i = 0; i < recoMuons->size(); ++i) {
0194       // It is crucial to use the OrphanHandle here and not a RefProd from GetRefBeforePut
0195       halfp4sPtr.push_back(Ptr<pat::UserData>(handle, i));
0196     }
0197     std::cout << "   Made edm::Ptr<> to those useless objects" << std::endl;
0198     auto vmhalfp4s = std::make_unique<ValueMap<Ptr<pat::UserData>>>();
0199     ValueMap<Ptr<pat::UserData>>::Filler filler(*vmhalfp4s);
0200     filler.insert(recoMuons, halfp4sPtr.begin(), halfp4sPtr.end());
0201     filler.fill();
0202     std::cout << "   Filled the ValueMap of edm::Ptr<> to those useless objects" << std::endl;
0203     iEvent.put(std::move(vmhalfp4s));
0204     std::cout << "   Wrote the ValueMap of edm::Ptr<> to those useless objects" << std::endl;
0205 
0206     std::cout << "So long, and thanks for all the muons.\n" << std::endl;
0207   }
0208 }
0209 
0210 //define this as a plug-in
0211 DEFINE_FWK_MODULE(PATUserDataTestModule);