Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:23:59

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/stream/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::stream::EDProducer<> {
0067 public:
0068   explicit PATUserDataTestModule(const edm::ParameterSet&);
0069   ~PATUserDataTestModule() override = default;
0070 
0071 private:
0072   virtual void produce(edm::Event&, const edm::EventSetup&) override;
0073 
0074   // ----------member data ---------------------------
0075   const edm::EDGetTokenT<edm::View<pat::Muon>> muonsToken_;
0076   const std::string label_;
0077   enum TestMode { TestRead, TestWrite, TestExternal };
0078   const 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 // ------------ method called to for each event  ------------
0103 void PATUserDataTestModule::produce(edm::Event& iEvent, const edm::EventSetup& iSetup) {
0104   using namespace edm;
0105 
0106   // I need to define a type for which we don't have a dictionary in CMSSW. I hope this is crazy enough.
0107   typedef std::pair<std::map<std::string, pat::Muon>, std::vector<math::XYZVector>> CrazyDataType;
0108 
0109   if (mode_ != TestExternal) {
0110     edm::Handle<View<pat::Muon>> muons;
0111     iEvent.getByToken(muonsToken_, muons);
0112 
0113     auto output = std::make_unique<std::vector<pat::Muon>>();
0114 
0115     for (View<pat::Muon>::const_iterator muon = muons->begin(), end = muons->end(); muon != end; ++muon) {
0116       if (mode_ == TestWrite) {
0117         pat::Muon myMuon = *muon;  // copy
0118         myMuon.addUserInt("answer", 42);
0119         myMuon.addUserFloat("pi", 3.14);
0120         myMuon.addUserData("half p4", 0.5 * muon->p4());
0121 
0122         //// This shoud throw an exception because we don't have the wrapper type
0123         //myMuon.addUserData("self", *muon);
0124         //// This should throw an exception because we don't have the dictionary (I hope)
0125         // myMuon.addUserData("crazy", CrazyDataType());
0126         //// These instead should not throw an exception as long as they don't get saved on disk
0127         // myMuon.addUserData("tmp self", *muon, true);
0128         // myMuon.addUserData("tmp crazy", CrazyDataType(), true);
0129 
0130         output->push_back(std::move(myMuon));
0131       } else {
0132         std::cout << "Muon #" << (muon - muons->begin()) << ":" << std::endl;
0133         std::cout << "\tanswer   = " << muon->userInt("answer") << std::endl;
0134         std::cout << "\tanswer:il= " << muon->userInt("answer:il") << std::endl;
0135         std::cout << "\tpi       = " << muon->userFloat("pi") << std::endl;
0136         std::cout << "\tmiss int = " << muon->userInt("missing int") << std::endl;
0137         std::cout << "\tmiss flt = " << muon->userFloat("missing flt") << std::endl;
0138         std::cout << "\t# u d    = " << muon->userDataNames().size() << std::endl;
0139         std::cout << "\tud nam[0]= " << muon->userDataNames()[0] << std::endl;
0140         std::cout << "\thas p4/2 = " << muon->hasUserData("half p4") << std::endl;
0141         if (muon->hasUserData("half p4")) {
0142           std::cout << "\ttyp p4/2 = " << muon->userDataObjectType("half p4") << std::endl;
0143           std::cout << "\tval p4/2 = " << (*muon->userData<reco::Particle::LorentzVector>("half p4"))
0144                     << "  == " << (0.5 * muon->p4()) << std::endl;
0145         }
0146         if (muon->hasUserData("tmp self")) {
0147           std::cout << "\tself.pt  = " << muon->userData<pat::Muon>("tmp self")->pt() << "  == " << muon->pt()
0148                     << std::endl;
0149         }
0150         if (muon->hasUserData("tmp crazy")) {
0151           std::cout << "\tcrazy.siz= " << muon->userData<CrazyDataType>("tmp crazy")->second.size() << "  == 0 "
0152                     << std::endl;
0153         }
0154         if (muon->hasUserData("halfP4")) {
0155           std::cout << "\ttyp P4/2 = " << muon->userDataObjectType("halfP4") << std::endl;
0156           std::cout << "\tval P4/2 = " << (*muon->userData<reco::Particle::LorentzVector>("halfP4"))
0157                     << "  == " << (0.5 * muon->p4()) << std::endl;
0158         }
0159       }
0160     }
0161     iEvent.put(std::move(output));
0162   } else {
0163     using namespace std;
0164     Handle<View<reco::Muon>> recoMuons;
0165     iEvent.getByToken(muonsToken_, recoMuons);
0166     std::cout << "Got " << recoMuons->size() << " muons" << std::endl;
0167 
0168     vector<int> ints(recoMuons->size(), 42);
0169     auto answers = std::make_unique<ValueMap<int>>();
0170     ValueMap<int>::Filler intfiller(*answers);
0171     intfiller.insert(recoMuons, ints.begin(), ints.end());
0172     intfiller.fill();
0173     iEvent.put(std::move(answers), label_);
0174     std::cout << "Filled in the answer" << std::endl;
0175 
0176     vector<float> floats(recoMuons->size(), 3.14);
0177     auto pis = std::make_unique<ValueMap<float>>();
0178     ValueMap<float>::Filler floatfiller(*pis);
0179     floatfiller.insert(recoMuons, floats.begin(), floats.end());
0180     floatfiller.fill();
0181     iEvent.put(std::move(pis));
0182     std::cout << "Wrote useless floats into the event" << std::endl;
0183 
0184     auto halfp4s = std::make_unique<OwnVector<pat::UserData>>();
0185     for (size_t i = 0; i < recoMuons->size(); ++i) {
0186       halfp4s->push_back(pat::UserData::make(0.5 * (*recoMuons)[i].p4()));
0187     }
0188     OrphanHandle<OwnVector<pat::UserData>> handle = iEvent.put(std::move(halfp4s));
0189     std::cout << "Wrote OwnVector of useless objects into the event" << std::endl;
0190     vector<Ptr<pat::UserData>> halfp4sPtr;
0191     for (size_t i = 0; i < recoMuons->size(); ++i) {
0192       // It is crucial to use the OrphanHandle here and not a RefProd from GetRefBeforePut
0193       halfp4sPtr.push_back(Ptr<pat::UserData>(handle, i));
0194     }
0195     std::cout << "   Made edm::Ptr<> to those useless objects" << std::endl;
0196     auto vmhalfp4s = std::make_unique<ValueMap<Ptr<pat::UserData>>>();
0197     ValueMap<Ptr<pat::UserData>>::Filler filler(*vmhalfp4s);
0198     filler.insert(recoMuons, halfp4sPtr.begin(), halfp4sPtr.end());
0199     filler.fill();
0200     std::cout << "   Filled the ValueMap of edm::Ptr<> to those useless objects" << std::endl;
0201     iEvent.put(std::move(vmhalfp4s));
0202     std::cout << "   Wrote the ValueMap of edm::Ptr<> to those useless objects" << std::endl;
0203 
0204     std::cout << "So long, and thanks for all the muons.\n" << std::endl;
0205   }
0206 }
0207 
0208 //define this as a plug-in
0209 DEFINE_FWK_MODULE(PATUserDataTestModule);