File indexing completed on 2024-04-06 12:24:10
0001 #ifndef PhysicsTools_SelectorUtils_VersionedSelector_h
0002 #define PhysicsTools_SelectorUtils_VersionedSelector_h
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #if (!defined(__CINT__) && !defined(__MAKECINT__) && !defined(__REFLEX__) && !defined(__CLING__))
0015
0016 #define REGULAR_CPLUSPLUS 1
0017 #define CINT_GUARD(CODE) CODE
0018 #include "FWCore/Framework/interface/ConsumesCollector.h"
0019 #include <memory>
0020 #define SHARED_PTR(T) std::shared_ptr<T>
0021
0022 #else
0023
0024 #define CINT_GUARD(CODE)
0025
0026 #define SHARED_PTR(T) std::shared_ptr<T>
0027
0028 #endif
0029
0030 #include "PhysicsTools/SelectorUtils/interface/Selector.h"
0031 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0032 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0033 #include "PhysicsTools/SelectorUtils/interface/CandidateCut.h"
0034 #include "PhysicsTools/SelectorUtils/interface/CutApplicatorBase.h"
0035 #include "PhysicsTools/SelectorUtils/interface/CutApplicatorWithEventContentBase.h"
0036
0037 #include "Utilities/OpenSSL/interface/openssl_init.h"
0038
0039 namespace candf = candidate_functions;
0040
0041 namespace vid {
0042 class CutFlowResult;
0043 }
0044
0045 template <class T>
0046 class VersionedSelector : public Selector<T> {
0047 public:
0048 VersionedSelector() : Selector<T>(), initialized_(false) {}
0049
0050 VersionedSelector(const edm::ParameterSet& conf) : Selector<T>(), initialized_(false) {
0051 validateParamsAreTracked(conf);
0052
0053 name_ = conf.getParameter<std::string>("idName");
0054
0055
0056 cms::openssl_init();
0057 EVP_MD_CTX* mdctx = EVP_MD_CTX_new();
0058 const EVP_MD* md = EVP_get_digestbyname("MD5");
0059 unsigned int md_len = 0;
0060 std::string tracked(conf.trackedPart().dump());
0061
0062 EVP_DigestInit_ex(mdctx, md, nullptr);
0063 EVP_DigestUpdate(mdctx, tracked.c_str(), tracked.size());
0064 EVP_DigestFinal_ex(mdctx, id_md5_, &md_len);
0065 EVP_MD_CTX_free(mdctx);
0066 id_md5_[md_len] = 0;
0067 char tmp[EVP_MAX_MD_SIZE * 2 + 1];
0068 for (unsigned int i = 0; i < md_len; i++) {
0069 ::sprintf(&tmp[i * 2], "%02x", id_md5_[i]);
0070 }
0071 tmp[md_len * 2] = 0;
0072 md5_string_ = tmp;
0073 initialize(conf);
0074 this->retInternal_ = this->getBitTemplate();
0075 }
0076
0077 bool operator()(const T& ref, pat::strbitset& ret) CINT_GUARD(final) {
0078 howfar_ = 0;
0079 bitmap_ = 0;
0080 values_.clear();
0081 bool failed = false;
0082 if (!initialized_) {
0083 throw cms::Exception("CutNotInitialized") << "VersionedGsfElectronSelector not initialized!" << std::endl;
0084 }
0085 for (unsigned i = 0; i < cuts_.size(); ++i) {
0086 reco::CandidatePtr temp(ref);
0087 const bool result = (*cuts_[i])(temp);
0088 values_.push_back(cuts_[i]->value(temp));
0089 if (result || this->ignoreCut(cut_indices_[i])) {
0090 this->passCut(ret, cut_indices_[i]);
0091 bitmap_ |= 1 << i;
0092 if (!failed)
0093 ++howfar_;
0094 } else {
0095 failed = true;
0096 }
0097 }
0098 this->setIgnored(ret);
0099 return (bool)ret;
0100 }
0101
0102 bool operator()(const T& ref, edm::EventBase const& e, pat::strbitset& ret) CINT_GUARD(final) {
0103
0104 for (size_t i = 0, cutssize = cuts_.size(); i < cutssize; ++i) {
0105 if (needs_event_content_[i]) {
0106 CutApplicatorWithEventContentBase* needsEvent = static_cast<CutApplicatorWithEventContentBase*>(cuts_[i].get());
0107 needsEvent->getEventContent(e);
0108 }
0109 }
0110 return this->operator()(ref, ret);
0111 }
0112
0113
0114
0115
0116
0117 bool operator()(typename T::value_type const& t) {
0118 const T temp(&t, 0);
0119 return this->operator()(temp);
0120 }
0121
0122 bool operator()(typename T::value_type const& t, edm::EventBase const& e) {
0123 const T temp(&t, 0);
0124 return this->operator()(temp, e);
0125 }
0126
0127 bool operator()(T const& t) CINT_GUARD(final) {
0128 this->retInternal_.set(false);
0129 this->operator()(t, this->retInternal_);
0130 this->setIgnored(this->retInternal_);
0131 return (bool)this->retInternal_;
0132 }
0133
0134 bool operator()(T const& t, edm::EventBase const& e) CINT_GUARD(final) {
0135 this->retInternal_.set(false);
0136 this->operator()(t, e, this->retInternal_);
0137 this->setIgnored(this->retInternal_);
0138 return (bool)this->retInternal_;
0139 }
0140
0141 const unsigned char* md55Raw() const { return id_md5_; }
0142 bool operator==(const VersionedSelector& other) const {
0143 constexpr unsigned length = EVP_MAX_MD_SIZE;
0144 return (0 == memcmp(id_md5_, other.id_md5_, length * sizeof(unsigned char)));
0145 }
0146 const std::string& md5String() const { return md5_string_; }
0147
0148 const std::string& name() const { return name_; }
0149
0150 const unsigned howFarInCutFlow() const { return howfar_; }
0151
0152 const unsigned bitMap() const { return bitmap_; }
0153
0154 const size_t cutFlowSize() const { return cuts_.size(); }
0155
0156 vid::CutFlowResult cutFlowResult() const;
0157
0158 void initialize(const edm::ParameterSet&);
0159
0160 CINT_GUARD(void setConsumes(edm::ConsumesCollector));
0161
0162 private:
0163
0164
0165
0166
0167
0168
0169
0170 static void validateParamsAreTracked(const edm::ParameterSet& conf) {
0171 edm::ParameterSet trackedPart = conf.trackedPart();
0172 edm::ParameterSet confWithoutIsPOGApproved;
0173 for (auto& paraName : conf.getParameterNames()) {
0174 if (paraName != "isPOGApproved")
0175 confWithoutIsPOGApproved.copyFrom(conf, paraName);
0176 else if (conf.existsAs<bool>(paraName, true))
0177 confWithoutIsPOGApproved.copyFrom(conf, paraName);
0178 }
0179 std::string tracked(conf.trackedPart().dump()), untracked(confWithoutIsPOGApproved.dump());
0180 if (tracked != untracked) {
0181 throw cms::Exception("InvalidConfiguration") << "VersionedSelector does not allow untracked parameters"
0182 << " in the cutflow ParameterSet!";
0183 }
0184 }
0185
0186 protected:
0187 bool initialized_;
0188 std::vector<SHARED_PTR(candf::CandidateCut)> cuts_;
0189 std::vector<bool> needs_event_content_;
0190 std::vector<typename Selector<T>::index_type> cut_indices_;
0191 unsigned howfar_, bitmap_;
0192 std::vector<double> values_;
0193
0194 private:
0195 unsigned char id_md5_[EVP_MAX_MD_SIZE];
0196 std::string md5_string_, name_;
0197 };
0198
0199 template <class T>
0200 void VersionedSelector<T>::initialize(const edm::ParameterSet& conf) {
0201 if (initialized_) {
0202 edm::LogWarning("VersionedPatElectronSelector") << "ID was already initialized!";
0203 return;
0204 }
0205 const std::vector<edm::ParameterSet>& cutflow = conf.getParameterSetVector("cutFlow");
0206 if (cutflow.empty()) {
0207 throw cms::Exception("InvalidCutFlow") << "You have supplied a null/empty cutflow to VersionedIDSelector,"
0208 << " please add content to the cuflow and try again.";
0209 }
0210
0211
0212 std::vector<edm::ParameterSet>::const_iterator cbegin(cutflow.begin()), cend(cutflow.end());
0213 std::vector<edm::ParameterSet>::const_iterator icut = cbegin;
0214 std::map<std::string, unsigned> cut_counter;
0215 std::vector<std::string> ignored_cuts;
0216 for (; icut != cend; ++icut) {
0217 std::stringstream realname;
0218 const std::string& name = icut->getParameter<std::string>("cutName");
0219 if (!cut_counter.count(name))
0220 cut_counter[name] = 0;
0221 realname << name << "_" << cut_counter[name];
0222 const bool needsContent = icut->getParameter<bool>("needsAdditionalProducts");
0223 const bool ignored = icut->getParameter<bool>("isIgnored");
0224 CINT_GUARD(cuts_.emplace_back(CutApplicatorFactory::get()->create(name, *icut)));
0225 needs_event_content_.push_back(needsContent);
0226 const std::string therealname = realname.str();
0227 this->push_back(therealname);
0228 this->set(therealname);
0229 if (ignored)
0230 ignored_cuts.push_back(therealname);
0231 cut_counter[name]++;
0232 }
0233 this->setIgnoredCuts(ignored_cuts);
0234
0235
0236 icut = cbegin;
0237 cut_counter.clear();
0238 for (; icut != cend; ++icut) {
0239 std::stringstream realname;
0240 const std::string& name = cuts_[std::distance(cbegin, icut)]->name();
0241 if (!cut_counter.count(name))
0242 cut_counter[name] = 0;
0243 realname << name << "_" << cut_counter[name];
0244 cut_indices_.push_back(typename Selector<T>::index_type(&(this->bits_), realname.str()));
0245 cut_counter[name]++;
0246 }
0247
0248 initialized_ = true;
0249 }
0250
0251 #ifdef REGULAR_CPLUSPLUS
0252 #include "DataFormats/PatCandidates/interface/VIDCutFlowResult.h"
0253 template <class T>
0254 vid::CutFlowResult VersionedSelector<T>::cutFlowResult() const {
0255 std::map<std::string, unsigned> names_to_index;
0256 std::map<std::string, unsigned> cut_counter;
0257 for (unsigned idx = 0; idx < cuts_.size(); ++idx) {
0258 const std::string& name = cuts_[idx]->name();
0259 if (!cut_counter.count(name))
0260 cut_counter[name] = 0;
0261 std::stringstream realname;
0262 realname << name << "_" << cut_counter[name];
0263 names_to_index.emplace(realname.str(), idx);
0264 cut_counter[name]++;
0265 }
0266 return vid::CutFlowResult(name_, md5_string_, names_to_index, values_, bitmap_);
0267 }
0268
0269 #include "PhysicsTools/SelectorUtils/interface/CutApplicatorWithEventContentBase.h"
0270 template <class T>
0271 void VersionedSelector<T>::setConsumes(edm::ConsumesCollector cc) {
0272 for (size_t i = 0, cutssize = cuts_.size(); i < cutssize; ++i) {
0273 if (needs_event_content_[i]) {
0274 CutApplicatorWithEventContentBase* needsEvent = dynamic_cast<CutApplicatorWithEventContentBase*>(cuts_[i].get());
0275 if (nullptr != needsEvent) {
0276 needsEvent->setConsumes(cc);
0277 } else {
0278 throw cms::Exception("InvalidCutConfiguration") << "Cut: " << ((CutApplicatorBase*)cuts_[i].get())->name()
0279 << " configured to consume event products but does not "
0280 << " inherit from CutApplicatorWithEventContenBase "
0281 << " please correct either your python or C++!";
0282 }
0283 }
0284 }
0285 }
0286 #endif
0287
0288 #endif