File indexing completed on 2023-03-17 11:00:59
0001 #ifndef FastSimulation_TrackingRecHitProducer_TrackerDetIdSelector_H
0002 #define FastSimulation_TrackingRecHitProducer_TrackerDetIdSelector_H
0003
0004 #include "DataFormats/DetId/interface/DetId.h"
0005 #include "DataFormats/TrackerCommon/interface/TrackerTopology.h"
0006 #include "FWCore/Utilities/interface/Exception.h"
0007
0008 #include <boost/variant/recursive_variant.hpp>
0009
0010 #include <iostream>
0011 #include <cstdlib>
0012 #include <typeinfo>
0013 #include <functional>
0014 #include <unordered_map>
0015
0016 struct BinaryOP;
0017 struct UnaryOP;
0018 struct ExpressionAST;
0019 struct Nil {};
0020
0021 namespace detail {
0022 ExpressionAST opLesser(ExpressionAST const& lhs, ExpressionAST const& rhs);
0023 ExpressionAST opLesserEq(ExpressionAST const& lhs, ExpressionAST const& rhs);
0024 ExpressionAST opEq(ExpressionAST const& lhs, ExpressionAST const& rhs);
0025 ExpressionAST opNotEq(ExpressionAST const& lhs, ExpressionAST const& rhs);
0026 ExpressionAST opGreater(ExpressionAST const& lhs, ExpressionAST const& rhs);
0027 ExpressionAST opGreaterEq(ExpressionAST const& lhs, ExpressionAST const& rhs);
0028 ExpressionAST opAnd(ExpressionAST const& lhs, ExpressionAST const& rhs);
0029 ExpressionAST opOr(ExpressionAST const& lhs, ExpressionAST const& rhs);
0030 }
0031
0032 struct ExpressionAST {
0033 typedef boost::variant<Nil,
0034 int,
0035 std::string,
0036 boost::recursive_wrapper<ExpressionAST>,
0037 boost::recursive_wrapper<BinaryOP>,
0038 boost::recursive_wrapper<UnaryOP> >
0039 Type;
0040
0041 ExpressionAST() : expr(Nil()) {}
0042
0043 template <typename Expr>
0044 ExpressionAST(Expr const& expr) : expr(expr) {}
0045
0046 int evaluate(const DetId& detId, const TrackerTopology& trackerTopology) const;
0047
0048 ExpressionAST& operator!();
0049
0050 Type expr;
0051
0052 friend ExpressionAST operator>(ExpressionAST const& lhs, ExpressionAST const& rhs) {
0053 return detail::opGreater(lhs, rhs);
0054 }
0055 friend ExpressionAST operator>=(ExpressionAST const& lhs, ExpressionAST const& rhs) {
0056 return detail::opGreaterEq(lhs, rhs);
0057 }
0058 friend ExpressionAST operator==(ExpressionAST const& lhs, ExpressionAST const& rhs) { return detail::opEq(lhs, rhs); }
0059 friend ExpressionAST operator!=(ExpressionAST const& lhs, ExpressionAST const& rhs) {
0060 return detail::opNotEq(lhs, rhs);
0061 }
0062 friend ExpressionAST operator<(ExpressionAST const& lhs, ExpressionAST const& rhs) {
0063 return detail::opLesser(lhs, rhs);
0064 }
0065 friend ExpressionAST operator<=(ExpressionAST const& lhs, ExpressionAST const& rhs) {
0066 return detail::opLesserEq(lhs, rhs);
0067 }
0068 friend ExpressionAST operator&&(ExpressionAST const& lhs, ExpressionAST const& rhs) {
0069 return detail::opAnd(lhs, rhs);
0070 }
0071 friend ExpressionAST operator||(ExpressionAST const& lhs, ExpressionAST const& rhs) { return detail::opOr(lhs, rhs); }
0072 };
0073
0074 struct BinaryOP {
0075 enum class OP { GREATER, GREATER_EQUAL, EQUAL, LESS_EQUAL, LESS, NOT_EQUAL, AND, OR } op;
0076 ExpressionAST left;
0077 ExpressionAST right;
0078
0079 BinaryOP(OP op, ExpressionAST const& left, ExpressionAST const& right) : op(op), left(left), right(right) {}
0080
0081 int evaluate(const DetId& detId, const TrackerTopology& trackerTopology) const {
0082 switch (op) {
0083 case OP::GREATER:
0084 return left.evaluate(detId, trackerTopology) > right.evaluate(detId, trackerTopology);
0085 case OP::GREATER_EQUAL:
0086 return left.evaluate(detId, trackerTopology) >= right.evaluate(detId, trackerTopology);
0087 case OP::EQUAL:
0088 return left.evaluate(detId, trackerTopology) == right.evaluate(detId, trackerTopology);
0089 case OP::LESS_EQUAL:
0090 return left.evaluate(detId, trackerTopology) <= right.evaluate(detId, trackerTopology);
0091 case OP::LESS:
0092 return left.evaluate(detId, trackerTopology) < right.evaluate(detId, trackerTopology);
0093 case OP::NOT_EQUAL:
0094 return left.evaluate(detId, trackerTopology) != right.evaluate(detId, trackerTopology);
0095 case OP::AND:
0096 return left.evaluate(detId, trackerTopology) && right.evaluate(detId, trackerTopology);
0097 case OP::OR:
0098 return left.evaluate(detId, trackerTopology) || right.evaluate(detId, trackerTopology);
0099 }
0100 return 0;
0101 }
0102 };
0103
0104 struct UnaryOP {
0105 enum class OP { NEG } op;
0106 ExpressionAST subject;
0107 UnaryOP(OP op, ExpressionAST const& subject) : op(op), subject(subject) {}
0108
0109 int evaluate(const DetId& detId, const TrackerTopology& trackerTopology) const {
0110 switch (op) {
0111 case OP::NEG:
0112 return !subject.evaluate(detId, trackerTopology);
0113 }
0114 return 0;
0115 }
0116 };
0117
0118 class TrackerDetIdSelector {
0119 private:
0120 const DetId& _detId;
0121 const TrackerTopology& _trackerTopology;
0122
0123 public:
0124 typedef std::function<int(const TrackerTopology& trackerTopology, const DetId&)> DetIdFunction;
0125 typedef std::unordered_map<std::string, DetIdFunction> StringFunctionMap;
0126 const static StringFunctionMap functionTable;
0127
0128 TrackerDetIdSelector(const DetId& detId, const TrackerTopology& trackerTopology)
0129 : _detId(detId), _trackerTopology(trackerTopology) {}
0130
0131 bool passSelection(const std::string& selectionStr) const;
0132 };
0133
0134 class Accessor : public boost::static_visitor<int> {
0135 private:
0136 const DetId& _detId;
0137 const TrackerTopology& _trackerTopology;
0138
0139 public:
0140 Accessor(const DetId& detId, const TrackerTopology& trackerTopology)
0141 : _detId(detId), _trackerTopology(trackerTopology) {}
0142
0143 int operator()(Nil i) const {
0144 throw cms::Exception("FastSimulation/TrackingRecHitProducer/TrackerDetIdSelector",
0145 "while evaluating a DetId selection a symbol was not set");
0146 }
0147 int operator()(const int& i) const { return i; }
0148 int operator()(const std::string& s) const {
0149 TrackerDetIdSelector::StringFunctionMap::const_iterator it = TrackerDetIdSelector::functionTable.find(s);
0150 int value = 0;
0151 if (it != TrackerDetIdSelector::functionTable.cend()) {
0152 value = (it->second)(_trackerTopology, _detId);
0153
0154 } else {
0155
0156 std::string msg =
0157 "error while parsing DetId selection: named identifier '" + s + "' not known. Possible values are: ";
0158 for (const TrackerDetIdSelector::StringFunctionMap::value_type& pair : TrackerDetIdSelector::functionTable) {
0159 msg += pair.first + ",";
0160 }
0161 throw cms::Exception("FastSimulation/TrackingRecHitProducer/TrackerDetIdSelector", msg);
0162 }
0163 return value;
0164 }
0165 int operator()(const ExpressionAST& ast) const { return ast.evaluate(_detId, _trackerTopology); }
0166 int operator()(const BinaryOP& binaryOP) const { return binaryOP.evaluate(_detId, _trackerTopology); }
0167 int operator()(const UnaryOP& unaryOP) const { return unaryOP.evaluate(_detId, _trackerTopology); }
0168 };
0169
0170 struct WalkAST {
0171 Accessor _acc;
0172
0173 WalkAST(const DetId& detId, const TrackerTopology& trackerTopology) : _acc(detId, trackerTopology) {}
0174
0175 typedef void result_type;
0176
0177 void operator()() const {}
0178 void operator()(int n) const {
0179 std::cout << n;
0180 std::cout << " [" << _acc(n) << "] ";
0181 }
0182 void operator()(std::string str) const {
0183 std::cout << str;
0184 std::cout << " [" << _acc(str) << "] ";
0185 }
0186 void operator()(ExpressionAST const& ast) const {
0187 boost::apply_visitor(*this, ast.expr);
0188 std::cout << " [=" << _acc(ast) << "] ";
0189 }
0190
0191 void operator()(BinaryOP const& expr) const {
0192 std::cout << "(";
0193 boost::apply_visitor(*this, expr.left.expr);
0194 switch (expr.op) {
0195 case BinaryOP::OP::GREATER:
0196 std::cout << " > ";
0197 break;
0198 case BinaryOP::OP::GREATER_EQUAL:
0199 std::cout << " >= ";
0200 break;
0201 case BinaryOP::OP::EQUAL:
0202 std::cout << " == ";
0203 break;
0204 case BinaryOP::OP::LESS_EQUAL:
0205 std::cout << " <= ";
0206 break;
0207 case BinaryOP::OP::LESS:
0208 std::cout << " < ";
0209 break;
0210 case BinaryOP::OP::NOT_EQUAL:
0211 std::cout << " != ";
0212 break;
0213 case BinaryOP::OP::AND:
0214 std::cout << " && ";
0215 break;
0216 case BinaryOP::OP::OR:
0217 std::cout << " || ";
0218 break;
0219 }
0220 boost::apply_visitor(*this, expr.right.expr);
0221 std::cout << ')';
0222 }
0223
0224 void operator()(UnaryOP const& expr) const {
0225 switch (expr.op) {
0226 case UnaryOP::OP::NEG:
0227 std::cout << " !(";
0228 break;
0229 }
0230 boost::apply_visitor(*this, expr.subject.expr);
0231 std::cout << ')';
0232 }
0233 };
0234
0235 inline int ExpressionAST::evaluate(const DetId& detId, const TrackerTopology& trackerTopology) const {
0236 return boost::apply_visitor(Accessor(detId, trackerTopology), this->expr);
0237 }
0238
0239 #endif