Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-09-22 22:37:09

0001 #include "FWCore/Framework/interface/global/EDAnalyzer.h"
0002 
0003 #include "FWCore/Framework/interface/Event.h"
0004 #include "FWCore/Framework/interface/EventSetup.h"
0005 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0006 #include "FWCore/Utilities/interface/EDGetToken.h"
0007 #include "FWCore/Utilities/interface/Exception.h"
0008 #include "FWCore/Utilities/interface/InputTag.h"
0009 #include "FWCore/Utilities/interface/transform.h"
0010 #include "FWCore/Framework/interface/MakerMacros.h"
0011 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
0012 #include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
0013 #include "DataFormats/Common/interface/DetSetVectorNew.h"
0014 #include "DataFormats/Common/interface/ThinnedAssociation.h"
0015 #include "DataFormats/TestObjects/interface/Thing.h"
0016 #include "DataFormats/TestObjects/interface/TrackOfDSVThings.h"
0017 #include "DataFormats/Provenance/interface/ProductID.h"
0018 
0019 #include <vector>
0020 
0021 namespace edmtest {
0022 
0023   class ThinningDSVTestAnalyzer : public edm::global::EDAnalyzer<> {
0024   public:
0025     explicit ThinningDSVTestAnalyzer(edm::ParameterSet const& pset);
0026 
0027     static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
0028 
0029     void analyze(edm::StreamID, edm::Event const& e, edm::EventSetup const& c) const override;
0030 
0031   private:
0032     void incrementExpectedValue(std::vector<int>::const_iterator& iter) const;
0033 
0034     edm::EDGetTokenT<edmNew::DetSetVector<Thing>> parentToken_;
0035     edm::EDGetTokenT<edmNew::DetSetVector<Thing>> thinnedToken_;
0036     edm::EDGetTokenT<edm::ThinnedAssociation> associationToken_;
0037     edm::EDGetTokenT<TrackOfDSVThingsCollection> trackToken_;
0038 
0039     struct DSContent {
0040       unsigned int id;
0041       std::vector<int> values;
0042     };
0043 
0044     bool parentWasDropped_;
0045     std::vector<DSContent> expectedParentContent_;
0046     bool thinnedWasDropped_;
0047     bool thinnedIsAlias_;
0048     bool refToParentIsAvailable_;
0049     std::vector<DSContent> expectedThinnedContent_;
0050     std::vector<unsigned int> expectedIndexesIntoParent_;
0051     bool associationShouldBeDropped_;
0052     unsigned int expectedNumberOfTracks_;
0053     std::vector<int> expectedValues_;
0054     int parentSlimmedValueFactor_;
0055     int thinnedSlimmedValueFactor_;
0056     int refSlimmedValueFactor_;
0057   };
0058 
0059   ThinningDSVTestAnalyzer::ThinningDSVTestAnalyzer(edm::ParameterSet const& pset)
0060       : parentToken_(consumes<edmNew::DetSetVector<Thing>>(pset.getParameter<edm::InputTag>("parentTag"))),
0061         thinnedToken_(consumes<edmNew::DetSetVector<Thing>>(pset.getParameter<edm::InputTag>("thinnedTag"))),
0062         associationToken_(consumes<edm::ThinnedAssociation>(pset.getParameter<edm::InputTag>("associationTag"))),
0063         trackToken_(consumes<TrackOfDSVThingsCollection>(pset.getParameter<edm::InputTag>("trackTag"))),
0064         parentWasDropped_(pset.getParameter<bool>("parentWasDropped")),
0065         thinnedWasDropped_(pset.getParameter<bool>("thinnedWasDropped")),
0066         thinnedIsAlias_(pset.getParameter<bool>("thinnedIsAlias")),
0067         refToParentIsAvailable_(pset.getParameter<bool>("refToParentIsAvailable")),
0068         associationShouldBeDropped_(pset.getParameter<bool>("associationShouldBeDropped")),
0069         expectedNumberOfTracks_(pset.getParameter<unsigned int>("expectedNumberOfTracks")),
0070         expectedValues_(pset.getParameter<std::vector<int>>("expectedValues")) {
0071     auto makeDSContent = [](edm::ParameterSet const& p) {
0072       return DSContent{p.getParameter<unsigned int>("id"), p.getParameter<std::vector<int>>("values")};
0073     };
0074     if (!parentWasDropped_) {
0075       expectedParentContent_ = edm::vector_transform(
0076           pset.getParameter<std::vector<edm::ParameterSet>>("expectedParentContent"), makeDSContent);
0077     }
0078     if (!thinnedWasDropped_) {
0079       expectedThinnedContent_ = edm::vector_transform(
0080           pset.getParameter<std::vector<edm::ParameterSet>>("expectedThinnedContent"), makeDSContent);
0081     }
0082     if (!associationShouldBeDropped_) {
0083       expectedIndexesIntoParent_ = pset.getParameter<std::vector<unsigned int>>("expectedIndexesIntoParent");
0084     }
0085 
0086     auto slimmedFactor = [](int count, int factor) {
0087       int ret = 1;
0088       for (int i = 0; i < count; ++i) {
0089         ret *= factor;
0090       }
0091       return ret;
0092     };
0093     int const slimmedValueFactor = pset.getParameter<int>("slimmedValueFactor");
0094     parentSlimmedValueFactor_ = slimmedFactor(pset.getParameter<int>("parentSlimmedCount"), slimmedValueFactor);
0095     thinnedSlimmedValueFactor_ = slimmedFactor(pset.getParameter<int>("thinnedSlimmedCount"), slimmedValueFactor);
0096     refSlimmedValueFactor_ = slimmedFactor(pset.getParameter<int>("refSlimmedCount"), slimmedValueFactor);
0097   }
0098 
0099   void ThinningDSVTestAnalyzer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
0100     edm::ParameterSetDescription desc;
0101     desc.add<edm::InputTag>("parentTag");
0102     desc.add<edm::InputTag>("thinnedTag");
0103     desc.add<edm::InputTag>("associationTag");
0104     desc.add<edm::InputTag>("trackTag");
0105     desc.add<bool>("parentWasDropped", false);
0106     desc.add<bool>("thinnedWasDropped", false);
0107     desc.add<bool>("thinnedIsAlias", false);
0108     desc.add<bool>("refToParentIsAvailable", true)
0109         ->setComment(
0110             "If Ref-to-parent is generally available. With thinnedRefFrom it may happen that the Ref-to-parent is not "
0111             "available, but the Ref-to-thinned is. In such case this parameter should be set to 'False', and the "
0112             "'expectedValues' should be set to correspond the values via Ref-to-thinned.");
0113     std::vector<int> defaultV;
0114     std::vector<unsigned int> defaultVU;
0115     std::vector<edm::ParameterSet> defaultVPSet;
0116     edm::ParameterSetDescription dsValidator;
0117     dsValidator.add<unsigned int>("id");
0118     dsValidator.add<std::vector<int>>("values", defaultV);
0119     desc.addVPSet("expectedParentContent", dsValidator, defaultVPSet);
0120     desc.addVPSet("expectedThinnedContent", dsValidator, defaultVPSet);
0121     desc.add<std::vector<unsigned int>>("expectedIndexesIntoParent", defaultVU);
0122     desc.add<bool>("associationShouldBeDropped", false);
0123     desc.add<unsigned int>("expectedNumberOfTracks", 5);
0124     desc.add<std::vector<int>>("expectedValues");
0125     desc.add<int>("parentSlimmedCount", 0);
0126     desc.add<int>("thinnedSlimmedCount", 0);
0127     desc.add<int>("refSlimmedCount", 0);
0128     desc.add<int>("slimmedValueFactor", 10);
0129     descriptions.addDefault(desc);
0130   }
0131 
0132   void ThinningDSVTestAnalyzer::analyze(edm::StreamID, edm::Event const& event, edm::EventSetup const&) const {
0133     auto parentCollection = event.getHandle(parentToken_);
0134     auto thinnedCollection = event.getHandle(thinnedToken_);
0135     auto associationCollection = event.getHandle(associationToken_);
0136     auto trackCollection = event.getHandle(trackToken_);
0137 
0138     if (parentWasDropped_) {
0139       if (parentCollection.isValid()) {
0140         throw cms::Exception("TestFailure") << "parent collection present, should have been dropped";
0141       }
0142     } else if (!expectedParentContent_.empty()) {
0143       if (parentCollection->size() != expectedParentContent_.size()) {
0144         throw cms::Exception("TestFailure") << "parent collection has unexpected size, got " << parentCollection->size()
0145                                             << " expected " << expectedParentContent_.size();
0146       }
0147 
0148       auto iExpected = expectedParentContent_.begin();
0149       for (auto const& detset : *parentCollection) {
0150         auto const& expectedContent = *iExpected;
0151         ++iExpected;
0152 
0153         if (detset.id() != expectedContent.id) {
0154           throw cms::Exception("TestFailure")
0155               << "parent collection detset has unexpected id " << detset.id() << " expected " << expectedContent.id;
0156         }
0157         if (detset.size() != expectedContent.values.size()) {
0158           throw cms::Exception("TestFailure")
0159               << "parent collection detset with id " << detset.id() << " has unexpected size, got " << detset.size()
0160               << " expected " << expectedContent.values.size();
0161         }
0162         auto iValue = expectedContent.values.begin();
0163         for (auto const& thing : detset) {
0164           // Just some numbers that match the somewhat arbitrary values put in
0165           // by the ThingProducer.
0166           int expected =
0167               static_cast<int>(*iValue + (event.eventAuxiliary().event() - 1) * 100) * parentSlimmedValueFactor_;
0168           if (thing.a != expected) {
0169             throw cms::Exception("TestFailure")
0170                 << "parent collection has unexpected content for detset with id " << detset.id() << ", got " << thing.a
0171                 << " expected " << expected << " (element " << std::distance(expectedContent.values.begin(), iValue)
0172                 << ")";
0173           }
0174           ++iValue;
0175         }
0176       }
0177     }
0178 
0179     // Check to see the content is what we expect based on what was written
0180     // by ThingProducer and TrackOfThingsProducer. The values are somewhat
0181     // arbitrary and meaningless.
0182     edm::RefProd<edmNew::DetSetVector<Thing>> thinnedRefProd;
0183     if (thinnedWasDropped_) {
0184       if (thinnedCollection.isValid()) {
0185         throw cms::Exception("TestFailure") << "thinned collection present, should have been dropped";
0186       }
0187     } else {
0188       thinnedRefProd = edm::RefProd<edmNew::DetSetVector<Thing>>{thinnedCollection};
0189       if (thinnedCollection->size() != expectedThinnedContent_.size()) {
0190         throw cms::Exception("TestFailure")
0191             << "thinned collection has unexpected size, got " << thinnedCollection->size() << " expected "
0192             << expectedThinnedContent_.size();
0193       }
0194 
0195       auto iExpected = expectedThinnedContent_.begin();
0196       for (auto const& detset : *thinnedCollection) {
0197         auto const& expectedContent = *iExpected;
0198         ++iExpected;
0199 
0200         if (detset.id() != expectedContent.id) {
0201           throw cms::Exception("TestFailure")
0202               << "thinned collection detset has unexpected id " << detset.id() << " expected " << expectedContent.id;
0203         }
0204         if (detset.size() != expectedContent.values.size()) {
0205           throw cms::Exception("TestFailure")
0206               << "thinned collection detset with id " << detset.id() << " has unexpected size, got " << detset.size()
0207               << " expected " << expectedContent.values.size();
0208         }
0209         auto iValue = expectedContent.values.begin();
0210         for (auto const& thing : detset) {
0211           int expected =
0212               static_cast<int>(*iValue + (event.eventAuxiliary().event() - 1) * 100) * thinnedSlimmedValueFactor_;
0213           if (thing.a != expected) {
0214             throw cms::Exception("TestFailure")
0215                 << "thinned collection has unexpected content for detset with id " << detset.id() << ", got " << thing.a
0216                 << " expected " << expected << " (element " << std::distance(expectedContent.values.begin(), iValue)
0217                 << ")";
0218           }
0219           ++iValue;
0220         }
0221       }
0222     }
0223 
0224     if (associationShouldBeDropped_ && associationCollection.isValid()) {
0225       throw cms::Exception("TestFailure") << "association collection should have been dropped but was not";
0226     }
0227     if (!associationShouldBeDropped_) {
0228       unsigned int expectedIndex = 0;
0229       if (associationCollection->indexesIntoParent().size() != expectedIndexesIntoParent_.size()) {
0230         throw cms::Exception("TestFailure")
0231             << "association collection has unexpected size " << associationCollection->indexesIntoParent().size()
0232             << " expected " << expectedIndexesIntoParent_.size();
0233       }
0234       for (auto const& association : associationCollection->indexesIntoParent()) {
0235         if (association != expectedIndexesIntoParent_.at(expectedIndex)) {
0236           throw cms::Exception("TestFailure")
0237               << "association collection has unexpected content, for index " << expectedIndex << " got " << association
0238               << " expected " << expectedIndexesIntoParent_.at(expectedIndex);
0239         }
0240         ++expectedIndex;
0241       }
0242     }
0243 
0244     if (!parentWasDropped_ && !associationShouldBeDropped_) {
0245       if (associationCollection->parentCollectionID() != parentCollection.id()) {
0246         throw cms::Exception("TestFailure") << "analyze parent ProductID is not correct";
0247       }
0248     }
0249 
0250     if (!thinnedWasDropped_ && !associationShouldBeDropped_) {
0251       if (associationCollection->thinnedCollectionID() != thinnedCollection.id()) {
0252         throw cms::Exception("TestFailure") << "analyze thinned ProductID is not correct";
0253       }
0254     }
0255 
0256     if (trackCollection->size() != expectedNumberOfTracks_) {
0257       throw cms::Exception("TestFailure")
0258           << "unexpected Track size " << trackCollection->size() << " expected " << expectedNumberOfTracks_;
0259     }
0260 
0261     if (expectedValues_.empty()) {
0262       return;
0263     }
0264 
0265     int eventOffset = (static_cast<int>(event.eventAuxiliary().event()) - 1) * 100;
0266 
0267     std::vector<int>::const_iterator expectedValue = expectedValues_.begin();
0268     for (auto const& track : *trackCollection) {
0269       if (not refToParentIsAvailable_ or *expectedValue == -1) {
0270         if (track.ref1.isAvailable()) {
0271           throw cms::Exception("TestFailure") << "ref1 is available when it should not be, refers to "
0272                                               << track.ref1.id() << " key " << track.ref1.key();
0273         }
0274       } else {
0275         if (!track.ref1.isAvailable()) {
0276           throw cms::Exception("TestFailure") << "ref1 is not available when it should be";
0277         }
0278         // Check twice to test some possible caching problems.
0279         const int expected = (*expectedValue + eventOffset) * refSlimmedValueFactor_;
0280         if (track.ref1->a != expected) {
0281           throw cms::Exception("TestFailure")
0282               << "Unexpected values from ref1, got " << track.ref1->a << " expected " << expected;
0283         }
0284         if (track.ref1->a != expected) {
0285           throw cms::Exception("TestFailure")
0286               << "Unexpected values from ref1 (2nd try), got " << track.ref1->a << " expected " << expected;
0287           ;
0288         }
0289       }
0290 
0291       if (not thinnedWasDropped_) {
0292         auto refToThinned = edm::thinnedRefFrom(track.ref1, thinnedRefProd, event.productGetter());
0293         if (*expectedValue == -1) {
0294           if (refToThinned.isNonnull()) {
0295             throw cms::Exception("TestFailure") << "thinnedRefFrom(ref1) is non-null when it should be null";
0296           }
0297           if (refToThinned.isAvailable()) {
0298             throw cms::Exception("TestFailure") << "thinnedRefFrom(ref1) is available when it should not be";
0299           }
0300         } else {
0301           if (refToThinned.isNull()) {
0302             throw cms::Exception("TestFailure") << "thinnedRefFrom(ref1) is null when it should not be";
0303           }
0304           if (refToThinned.id() != thinnedCollection.id()) {
0305             throw cms::Exception("TestFailure") << "thinnedRefFrom(ref).id() " << refToThinned.id()
0306                                                 << " differs from expectation " << thinnedCollection.id();
0307           }
0308           if (not refToThinned.isAvailable()) {
0309             throw cms::Exception("TestFailure") << "thinnedRefFrom(ref1) is not available when it should be";
0310           }
0311           // Check twice to test some possible caching problems.
0312           // need to account for slimming because going through an explicit ref-to-slimmed
0313           const int expected = (*expectedValue + eventOffset) * thinnedSlimmedValueFactor_;
0314           if (refToThinned->a != expected) {
0315             throw cms::Exception("TestFailure")
0316                 << "Unexpected values from thinnedRefFrom(ref1), got " << refToThinned->a << " expected " << expected;
0317           }
0318           if (refToThinned->a != expected) {
0319             throw cms::Exception("TestFailure") << "Unexpected values from thinnedRefFrom(ref1) (2nd try) "
0320                                                 << refToThinned->a << " expected " << expected;
0321           }
0322         }
0323       }
0324       incrementExpectedValue(expectedValue);
0325 
0326       if (not refToParentIsAvailable_ or *expectedValue == -1) {
0327         if (track.ref2.isAvailable()) {
0328           throw cms::Exception("TestFailure") << "ref2 is available when it should not be";
0329         }
0330       } else {
0331         if (!track.ref2.isAvailable()) {
0332           throw cms::Exception("TestFailure") << "ref2 is not available when it should be";
0333         }
0334 
0335         const int expected = (*expectedValue + eventOffset) * refSlimmedValueFactor_;
0336         if (track.ref2->a != expected) {
0337           throw cms::Exception("TestFailure")
0338               << "unexpected values from ref2, got " << track.ref2->a << " expected " << expected;
0339         }
0340         if (track.ref2->a != expected) {
0341           throw cms::Exception("TestFailure")
0342               << "unexpected values from ref2 (2nd try), got " << track.ref2->a << " expected " << expected;
0343         }
0344       }
0345 
0346       if (not thinnedWasDropped_) {
0347         auto refToThinned = edm::thinnedRefFrom(track.ref2, thinnedRefProd, event.productGetter());
0348         if (*expectedValue == -1) {
0349           if (refToThinned.isNonnull()) {
0350             throw cms::Exception("TestFailure") << "thinnedRefFrom(ref2) is non-null when it should be null";
0351           }
0352           if (refToThinned.isAvailable()) {
0353             throw cms::Exception("TestFailure") << "thinnedRefFrom(ref2) is available when it should not be";
0354           }
0355         } else {
0356           if (refToThinned.isNull()) {
0357             throw cms::Exception("TestFailure") << "thinnedRefFrom(ref2) is null when it should not be";
0358           }
0359           if (refToThinned.id() != thinnedCollection.id()) {
0360             throw cms::Exception("TestFailure") << "thinnedRefFrom(ref2).id() " << refToThinned.id()
0361                                                 << " differs from expectation " << thinnedCollection.id();
0362           }
0363           if (not refToThinned.isAvailable()) {
0364             throw cms::Exception("TestFailure") << "thinnedRefFrom(ref2) is not available when it should be";
0365           }
0366           // Check twice to test some possible caching problems.
0367           // need to account for slimming because going through an explicit ref-to-slimmed
0368           const int expected = (*expectedValue + eventOffset) * thinnedSlimmedValueFactor_;
0369           if (refToThinned->a != expected) {
0370             throw cms::Exception("TestFailure")
0371                 << "Unexpected values from thinnedRefFrom(ref2), got " << refToThinned->a << " expected " << expected;
0372           }
0373           if (refToThinned->a != expected) {
0374             throw cms::Exception("TestFailure") << "Unexpected values from thinnedRefFrom(ref2) (2nd try), got "
0375                                                 << refToThinned->a << " expected " << expected;
0376           }
0377         }
0378       }
0379 
0380       incrementExpectedValue(expectedValue);
0381 
0382       // Test RefVector
0383       unsigned int k = 0;
0384       bool allPresent = true;
0385       for (auto iExpectedValue : expectedValues_) {
0386         if (iExpectedValue != -1) {
0387           if (not thinnedWasDropped_) {
0388             auto refToThinned = edm::thinnedRefFrom(track.refVector1[k], thinnedRefProd, event.productGetter());
0389             // need to account for slimming because going through an explicit ref-to-slimmed
0390             const int expected = (iExpectedValue + eventOffset) * thinnedSlimmedValueFactor_;
0391             if (refToThinned->a != expected) {
0392               throw cms::Exception("TestFailure") << "unexpected values from thinnedRefFrom(refVector1), got "
0393                                                   << refToThinned->a << " expected " << expected;
0394             }
0395           }
0396           if (refToParentIsAvailable_) {
0397             const int expected = (iExpectedValue + eventOffset) * refSlimmedValueFactor_;
0398             if (track.refVector1[k]->a != expected) {
0399               throw cms::Exception("TestFailure")
0400                   << "unexpected values from refVector1, got " << track.refVector1[k]->a << " expected " << expected;
0401             }
0402           }
0403         } else {
0404           allPresent = false;
0405         }
0406         ++k;
0407       }
0408 
0409       if (refToParentIsAvailable_ and allPresent) {
0410         if (!track.refVector1.isAvailable()) {
0411           throw cms::Exception("TestFailure") << "unexpected value (false) from refVector::isAvailable";
0412         }
0413       } else {
0414         if (track.refVector1.isAvailable()) {
0415           throw cms::Exception("TestFailure") << "unexpected value (true) from refVector::isAvailable";
0416         }
0417       }
0418     }
0419   }
0420 
0421   void ThinningDSVTestAnalyzer::incrementExpectedValue(std::vector<int>::const_iterator& iter) const {
0422     ++iter;
0423     if (iter == expectedValues_.end())
0424       iter = expectedValues_.begin();
0425   }
0426 }  // namespace edmtest
0427 using edmtest::ThinningDSVTestAnalyzer;
0428 DEFINE_FWK_MODULE(ThinningDSVTestAnalyzer);