Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 13:34:08

0001 //These objects allow an arbitary parameristisation to be used
0002 //design:
0003 //    the function and parameterisation can be changing without having to change the interface
0004 //    or breaking backwards compatibiltiy with existing configs.
0005 //    This is vital for the HLT and the main driving force behind the design which otherwise
0006 //    could have been a lot simplier
0007 //
0008 //usage:
0009 //    The variables used are defined by an intermediate object which defines the
0010 //    variables x,y, and z. 1D objects only need to define x, 2D objects x,y, etc.
0011 //    Example is "AbsEtaNrClus" which defines x as |supercluster eta| and y as #subclusters of the supercluster.
0012 //    The object also defines a pass function where it determines if x (and y,z) is
0013 //    within the specificed xmin and xmax range. This is mainly done as individual
0014 //    objects can decide whether this means min<=x<max or min<=x<=max
0015 //
0016 //    These objects are used by the binning objects. The bins can currently be 1D, 2D,
0017 //    or 3D based on the intermediate object. Each bin has a function with it.
0018 //    The function takes a ParmaType as an argument and returns a float.
0019 //    The function is defined by a string of format FUNCID:=ExtraConfigInfo
0020 //    FUNCID = function type which allows different functions to be selected
0021 //    while ExtraConfigInfo is any extra information needed to configure that func
0022 //    currently implimented types are TF1, TF2, TF3
0023 //    so to get a TF1 which is a pol3 just do TF1:=pol3
0024 //
0025 //future plans:
0026 //    Seperate out intermediate wrapper objects such as AbsEtaNrClus
0027 //    and put them in their own file. However some mechanism is needed to register them
0028 //    so for now this isnt done. Note we might move to the standard CMSSW of dealing
0029 //    with this
0030 
0031 #include "DataFormats/EgammaReco/interface/ElectronSeed.h"
0032 #include "DataFormats/EgammaReco/interface/SuperClusterFwd.h"
0033 #include "DataFormats/EgammaReco/interface/SuperCluster.h"
0034 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0035 
0036 #include "TF1.h"
0037 #include "TF2.h"
0038 #include "TF3.h"
0039 
0040 namespace egPM {
0041 
0042   struct AbsEtaNrClus {
0043     float x;
0044     size_t y;
0045 
0046     AbsEtaNrClus(const reco::ElectronSeed& seed) {
0047       reco::SuperClusterRef scRef = seed.caloCluster().castTo<reco::SuperClusterRef>();
0048       x = std::abs(scRef->eta());
0049       y = scRef->clustersSize();
0050     }
0051     bool pass(float absEtaMin, float absEtaMax, size_t nrClusMin, size_t nrClusMax) const {
0052       return x >= absEtaMin && x < absEtaMax && y >= nrClusMin && y <= nrClusMax;
0053     }
0054   };
0055   struct AbsEtaNrClusPhi {
0056     float x;
0057     size_t y;
0058     float z;
0059 
0060     AbsEtaNrClusPhi(const reco::ElectronSeed& seed) {
0061       reco::SuperClusterRef scRef = seed.caloCluster().castTo<reco::SuperClusterRef>();
0062       x = std::abs(scRef->eta());
0063       y = scRef->clustersSize();
0064       z = scRef->phi();
0065     }
0066     bool pass(float absEtaMin, float absEtaMax, size_t nrClusMin, size_t nrClusMax, float phiMin, float phiMax) const {
0067       return x >= absEtaMin && x < absEtaMax && y >= nrClusMin && y <= nrClusMax && z >= phiMin && z < phiMax;
0068     }
0069   };
0070 
0071   struct AbsEtaNrClusEt {
0072     float x;
0073     size_t y;
0074     float z;
0075 
0076     AbsEtaNrClusEt(const reco::ElectronSeed& seed) {
0077       reco::SuperClusterRef scRef = seed.caloCluster().castTo<reco::SuperClusterRef>();
0078       x = std::abs(scRef->eta());
0079       y = scRef->clustersSize();
0080       z = scRef->energy() * sin(scRef->position().Theta());
0081     }
0082     bool pass(float absEtaMin, float absEtaMax, size_t nrClusMin, size_t nrClusMax, float etMin, float etMax) const {
0083       return x >= absEtaMin && x < absEtaMax && y >= nrClusMin && y <= nrClusMax && z >= etMin && z < etMax;
0084     }
0085   };
0086 
0087   //these structs wrap the TF1 object
0088   //also if the ParamType doesnt have a high enough dimension
0089   //(ie using only one with x,y for a TF3), then the second
0090   //template parameter disables the function
0091   template <typename ParamType, bool = true>
0092   struct TF1Wrap {
0093   private:
0094     TF1 func_;
0095 
0096   public:
0097     TF1Wrap(const std::string& funcExpr, const std::vector<double>& params) : func_("func", funcExpr.c_str()) {
0098       for (size_t paraNr = 0; paraNr < params.size(); paraNr++) {
0099         func_.SetParameter(paraNr, params[paraNr]);
0100       }
0101     }
0102     float operator()(const ParamType& obj) { return func_.Eval(obj.x); };
0103   };
0104   template <typename ParamType>
0105   class TF1Wrap<ParamType, false> {
0106   public:
0107     TF1Wrap(const std::string& funcExpr, const std::vector<double>& params) {}
0108     float operator()(const ParamType& obj) { return 1.; };
0109   };
0110 
0111   template <typename ParamType, bool = true>
0112   struct TF2Wrap {
0113   private:
0114     TF2 func_;
0115 
0116   public:
0117     TF2Wrap(const std::string& funcExpr, const std::vector<double>& params) : func_("func", funcExpr.c_str()) {
0118       for (size_t paraNr = 0; paraNr < params.size(); paraNr++) {
0119         func_.SetParameter(paraNr, params[paraNr]);
0120       }
0121     }
0122     float operator()(const ParamType& obj) { return func_.Eval(obj.x, obj.y); };
0123   };
0124   template <typename ParamType>
0125   class TF2Wrap<ParamType, false> {
0126   public:
0127     TF2Wrap(const std::string& funcExpr, const std::vector<double>& params) {}
0128     float operator()(const ParamType& obj) { return 1.; };
0129   };
0130 
0131   template <typename ParamType, bool = true>
0132   struct TF3Wrap {
0133   private:
0134     TF3 func_;
0135 
0136   public:
0137     TF3Wrap(const std::string& funcExpr, const std::vector<double>& params) : func_("func", funcExpr.c_str()) {
0138       for (size_t paraNr = 0; paraNr < params.size(); paraNr++) {
0139         func_.SetParameter(paraNr, params[paraNr]);
0140       }
0141     }
0142     float operator()(const ParamType& obj) { return func_.Eval(obj.x, obj.y, obj.z); };
0143   };
0144   template <typename ParamType>
0145   class TF3Wrap<ParamType, false> {
0146   public:
0147     TF3Wrap(const std::string& funcExpr, const std::vector<double>& params) {}
0148     float operator()(const ParamType& obj) { return 1.; };
0149   };
0150 
0151   //the following functions allow for the fact that the type in the CMSSW PSet does not
0152   //have floats do when it sees a float parameter, it retrieves a double
0153   template <typename T>
0154   struct ConfigType {
0155     typedef T type;
0156   };
0157   template <>
0158   struct ConfigType<float> {
0159     typedef double type;
0160   };
0161   template <>
0162   struct ConfigType<size_t> {
0163     typedef int type;
0164   };
0165 
0166   //helper functions to figure out what dimension the ParamType is
0167   //and not generate functions which require a higher dimension
0168   template <typename T>
0169   constexpr auto has1D(int) -> decltype(T::x, bool()) {
0170     return true;
0171   }
0172   template <typename T>
0173   constexpr bool has1D(...) {
0174     return false;
0175   }
0176   template <typename T>
0177   constexpr auto has2D(int) -> decltype(T::y, bool()) {
0178     return true;
0179   }
0180   template <typename T>
0181   constexpr bool has2D(...) {
0182     return false;
0183   }
0184   template <typename T>
0185   constexpr auto has3D(int) -> decltype(T::z, bool()) {
0186     return true;
0187   }
0188   template <typename T>
0189   constexpr bool has3D(...) {
0190     return false;
0191   }
0192 
0193   template <typename InputType>
0194   class ParamBin {
0195   public:
0196     ParamBin() {}
0197     virtual ~ParamBin() {}
0198     virtual bool pass(const InputType&) const = 0;
0199     virtual float operator()(const InputType&) const = 0;
0200 
0201   protected:
0202     //the FUNCTYPE:=funcExpr is designed for future extensions
0203     static std::pair<std::string, std::string> readFuncStr(const std::string& inStr) {
0204       size_t pos = inStr.find(":=");
0205       if (pos != std::string::npos)
0206         return std::make_pair(inStr.substr(0, pos), inStr.substr(pos + 2));
0207       else
0208         return std::make_pair(inStr, std::string(""));
0209     }
0210     template <typename ParamType>
0211     static std::function<float(const ParamType&)> makeFunc(const edm::ParameterSet& config) {
0212       auto funcType = readFuncStr(config.getParameter<std::string>("funcType"));
0213       auto funcParams = config.getParameter<std::vector<double>>("funcParams");
0214       if (funcType.first == "TF1" && has1D<ParamType>(0))
0215         return TF1Wrap<ParamType, has1D<ParamType>(0)>(funcType.second, funcParams);
0216       else if (funcType.first == "TF2" && has2D<ParamType>(0))
0217         return TF2Wrap<ParamType, has2D<ParamType>(0)>(funcType.second, funcParams);
0218       else if (funcType.first == "TF3" && has3D<ParamType>(0))
0219         return TF3Wrap<ParamType, has3D<ParamType>(0)>(funcType.second, funcParams);
0220       else
0221         throw cms::Exception("InvalidConfig") << " type " << funcType.first
0222                                               << " is not recognised or is imcompatable with the ParamType, "
0223                                                  "configuration is invalid and needs to be fixed"
0224                                               << std::endl;
0225     }
0226   };
0227 
0228   template <typename InputType, typename ParamType>
0229   class ParamBin1D : public ParamBin<InputType> {
0230   private:
0231     using XType = decltype(ParamType::x);
0232     XType xMin_, xMax_;
0233     std::function<float(const ParamType&)> func_;
0234 
0235   public:
0236     ParamBin1D(const edm::ParameterSet& config)
0237         : xMin_(config.getParameter<typename ConfigType<XType>::type>("xMin")),
0238           xMax_(config.getParameter<typename ConfigType<XType>::type>("xMax")),
0239           func_(ParamBin<InputType>::template makeFunc<ParamType>(config)) {}
0240     bool pass(const InputType& input) const override { return ParamType(input).pass(xMin_, xMax_); }
0241     float operator()(const InputType& input) const override {
0242       if (!pass(input))
0243         return 0;
0244       else
0245         return func_(ParamType(input));
0246     }
0247   };
0248 
0249   template <typename InputType, typename ParamType>
0250   class ParamBin2D : public ParamBin<InputType> {
0251   private:
0252     using XType = decltype(ParamType::x);
0253     using YType = decltype(ParamType::y);
0254     XType xMin_, xMax_;
0255     YType yMin_, yMax_;
0256     std::function<float(const ParamType&)> func_;
0257 
0258   public:
0259     ParamBin2D(const edm::ParameterSet& config)
0260         : xMin_(config.getParameter<typename ConfigType<XType>::type>("xMin")),
0261           xMax_(config.getParameter<typename ConfigType<XType>::type>("xMax")),
0262           yMin_(config.getParameter<typename ConfigType<YType>::type>("yMin")),
0263           yMax_(config.getParameter<typename ConfigType<YType>::type>("yMax")),
0264           func_(ParamBin<InputType>::template makeFunc<ParamType>(config)) {}
0265 
0266     bool pass(const InputType& input) const override { return ParamType(input).pass(xMin_, xMax_, yMin_, yMax_); }
0267     float operator()(const InputType& input) const override {
0268       if (!pass(input))
0269         return 0;
0270       else
0271         return func_(ParamType(input));
0272     }
0273   };
0274 
0275   template <typename InputType, typename ParamType>
0276   class ParamBin3D : public ParamBin<InputType> {
0277     using XType = decltype(ParamType::x);
0278     using YType = decltype(ParamType::y);
0279     using ZType = decltype(ParamType::z);
0280 
0281     XType xMin_, xMax_;
0282     YType yMin_, yMax_;
0283     ZType zMin_, zMax_;
0284     std::function<float(const ParamType&)> func_;
0285 
0286   public:
0287     ParamBin3D(const edm::ParameterSet& config)
0288         : xMin_(config.getParameter<typename ConfigType<XType>::type>("xMin")),
0289           xMax_(config.getParameter<typename ConfigType<XType>::type>("xMax")),
0290           yMin_(config.getParameter<typename ConfigType<YType>::type>("yMin")),
0291           yMax_(config.getParameter<typename ConfigType<YType>::type>("yMax")),
0292           zMin_(config.getParameter<typename ConfigType<ZType>::type>("zMin")),
0293           zMax_(config.getParameter<typename ConfigType<ZType>::type>("zMax")),
0294           func_(ParamBin<InputType>::template makeFunc<ParamType>(config)) {}
0295 
0296     bool pass(const InputType& input) const override {
0297       return ParamType(input).pass(xMin_, xMax_, yMin_, yMax_, zMin_, zMax_);
0298     }
0299     float operator()(const InputType& input) const override {
0300       if (!pass(input))
0301         return 0;
0302       else
0303         return func_(ParamType(input));
0304     }
0305   };
0306 
0307   template <typename InputType>
0308   class Param {
0309     std::vector<std::unique_ptr<ParamBin<InputType>>> bins_;
0310 
0311   public:
0312     Param(const edm::ParameterSet& config) {
0313       std::vector<edm::ParameterSet> binConfigs = config.getParameter<std::vector<edm::ParameterSet>>("bins");
0314       for (auto& binConfig : binConfigs)
0315         bins_.emplace_back(createParamBin_(binConfig));
0316     }
0317     float operator()(const InputType& input) const {
0318       for (auto& bin : bins_) {
0319         if (bin->pass(input))
0320           return (*bin)(input);
0321       }
0322       return -1;  //didnt find a suitable bin, just return -1 for now
0323     }
0324 
0325   private:
0326     std::unique_ptr<ParamBin<InputType>> createParamBin_(const edm::ParameterSet& config) {
0327       std::string type = config.getParameter<std::string>("binType");
0328       if (type == "AbsEtaClus")
0329         return std::make_unique<ParamBin2D<InputType, AbsEtaNrClus>>(config);
0330       else if (type == "AbsEtaClusPhi")
0331         return std::make_unique<ParamBin3D<InputType, AbsEtaNrClusPhi>>(config);
0332       else if (type == "AbsEtaClusEt")
0333         return std::make_unique<ParamBin3D<InputType, AbsEtaNrClusEt>>(config);
0334       else
0335         throw cms::Exception("InvalidConfig")
0336             << " type " << type << " is not recognised, configuration is invalid and needs to be fixed" << std::endl;
0337     }
0338   };
0339 }  // namespace egPM