DDFilter

DDFilteredView

DDSolid

Macros

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282
#ifndef DetectorDescription_DDCMS_DDFilteredView_h
#define DetectorDescription_DDCMS_DDFilteredView_h

// -*- C++ -*-
//
// Package:    DetectorDescription/Core
// Class:      DDFilteredView
//
/**\class DDFilteredView

 Description: Filtered View of a Tree

 Implementation:
     Filter criteria is defined in XML
*/
//
// Original Author:  Ianna Osborne
//         Created:  Wed, 30 Jan 2019 09:24:30 GMT
//
//
#include "DetectorDescription/DDCMS/interface/DDSolidShapes.h"
#include "DetectorDescription/DDCMS/interface/ExpandedNodes.h"
#include "DetectorDescription/DDCMS/interface/DDVectorRegistry.h"
#include <DD4hep/Filter.h>
#include <DD4hep/SpecParRegistry.h>
#include <DD4hep/Volumes.h>
#include <memory>
#include <tuple>
#include <vector>

namespace cms {

  struct DDSolid {
    explicit DDSolid(dd4hep::Solid s) : solid_(s) {}
    dd4hep::Solid solid() const { return solid_; }
    dd4hep::Solid solidA() const;
    dd4hep::Solid solidB() const;
    const std::vector<double> parameters() const;

  private:
    dd4hep::Solid solid_;
  };

  class DDDetector;
  class DDCompactView;

  using Volume = dd4hep::Volume;
  using PlacedVolume = dd4hep::PlacedVolume;
  using ExpandedNodes = cms::ExpandedNodes;
  using Filter = dd4hep::Filter;
  using DDSpecPar = dd4hep::SpecPar;
  using DDSpecParRefs = dd4hep::SpecParRefs;
  using DDSpecParRegistry = dd4hep::SpecParRegistry;
  using Iterator = TGeoIterator;
  using Node = TGeoNode;
  using Translation = ROOT::Math::DisplacementVector3D<ROOT::Math::Cartesian3D<double>>;
  using RotationMatrix = ROOT::Math::Rotation3D;

  struct DDFilter {
    DDFilter(const std::string& attribute = "", const std::string& value = "")
        : m_attribute(attribute), m_value(value) {}
    const std::string& attribute() const { return m_attribute; }
    const std::string& value() const { return m_value; }

  private:
    const std::string m_attribute;
    const std::string m_value;
  };

  class DDFilteredView {
  public:
    using nav_type = std::vector<int>;

    DDFilteredView(const DDDetector*, const Volume);
    DDFilteredView(const DDCompactView&, const cms::DDFilter&);
    DDFilteredView() = delete;

    //! The numbering history of the current node
    const ExpandedNodes& history();

    //! The physical volume of the current node
    const PlacedVolume volume() const;

    //! The full path to the current node
    const std::string path() const;

    const std::vector<const Node*> geoHistory() const;

    //! The list of the volume copy numbers
    //  along the full path to the current node
    const std::vector<int> copyNos() const;

    template <typename... Ts>
    auto copyNumbers(Ts&&... ts) const -> decltype(copyNos(std::forward<Ts>(ts)...)) {
      return copyNos(std::forward<Ts>(ts)...);
    }

    //! The absolute translation of the current node
    // Return value is Double_t translation[3] with x, y, z elements.
    const Double_t* trans() const;
    const Translation translation() const;
    const Translation translation(const std::vector<Node*>&) const;

    //! The absolute rotation of the current node
    const Double_t* rot() const;
    const RotationMatrix rotation() const;
    void rot(dd4hep::Rotation3D& matrixOut) const;

    //! User specific data
    void mergedSpecifics(DDSpecParRefs const&);
    const cms::DDSpecParRefs specpars() const { return refs_; }

    //! set the current node to the first child
    bool firstChild();
    bool nextChild();

    //! set the current node to the child in path
    std::vector<std::vector<Node*>> children(const std::string& path);

    //! set the current node to the next sibling
    bool nextSibling();

    //! set the current node to the next sub sibling
    bool sibling();

    //! count the number of children matching selection
    bool checkChild();

    //! set the current node to the parent node ...
    bool parent();

    //! set current node to the next node in the filtered tree
    bool next(int);

    //! set current node to the child node in the filtered tree
    void down();

    //! set current node to the parent node in the filtered tree
    void up();

    // Shape of current node
    dd4hep::Solid solid() const;

    // Name of current node
    std::string_view name() const;

    // Name of current node with namespace
    std::string_view fullName() const;

    // Copy number of current node
    unsigned short copyNum() const;

    // Material name of current node
    std::string_view materialName() const;

    //! extract shape parameters
    const std::vector<double> parameters() const;

    const cms::DDSolidShape shape() const;

    // Convert new DD4hep shape id to an old DD one
    LegacySolidShape legacyShape(const cms::DDSolidShape shape) const;

    //! extract attribute value
    template <typename T>
    T get(const std::string&);

    //! extract attribute value for current Node
    //  keep the namespace for comparison
    //  assume there are no regular expressions
    template <typename T>
    std::vector<T> getValuesNS(const std::string& key) {
      DDSpecParRefs refs;
      registry_->filter(refs, key);

      std::string path = this->path();
      for (const auto& specPar : refs) {
        for (const auto& part : specPar.second->paths) {
          bool flag(true);
          std::size_t from = 0;
          for (auto name : dd4hep::dd::split(part, "/")) {
            auto const& to = path.find(name, from);
            if (to == std::string::npos) {
              flag = false;
              break;
            } else {
              from = to;
            }
          }
          if (flag) {
            return specPar.second->value<std::vector<T>>(key);
          }
        }
      }
      return std::vector<T>();
    }

    //! extract another value from the same SpecPar
    //  call get<double> first to find a relevant one
    double getNextValue(const std::string&) const;

    //! extract attribute value in SpecPar
    template <typename T>
    T get(const std::string&, const std::string&) const;

    //! convert an attribute value from SpecPar
    //  without passing it through an evaluator,
    //  e.g. the original values have no units
    std::vector<double> get(const std::string&, const std::string&) const;

    std::string_view getString(const std::string&) const;

    //! return the stack of sibling numbers which indicates
    //  the current position in the DDFilteredView
    nav_type navPos() const;

    //! get Iterator level
    const int level() const;

    //! transversed the DDFilteredView according
    //  to the given stack of sibling numbers
    bool goTo(const nav_type&);

    //! print Filter paths and selections
    void printFilter() const;

    //! find a current Node SpecPar that has at least
    //  one of the attributes
    template <class T, class... Ts>
    void findSpecPar(T const& first, Ts const&... rest) {
      currentSpecPar_ = find(first);
      if constexpr (sizeof...(rest) > 0) {
        // this line will only be instantiated if there are further
        // arguments. if rest... is empty, there will be no call to
        // findSpecPar(next).
        if (currentSpecPar_ == nullptr)
          findSpecPar(rest...);
      }
    }

  private:
    bool accept(std::string_view);
    int nodeCopyNo(const std::string_view) const;
    std::vector<std::pair<std::string, int>> toNodeNames(const std::string&);
    bool match(const std::string&, const std::vector<std::pair<std::string, int>>&) const;

    //! set the current node to the first sibling
    bool firstSibling();

    //! find a SpecPar in the registry by key
    //  doesn't really belong here, but allows
    //  speeding up avoiding the same search over
    //  the registry
    const DDSpecPar* find(const std::string&) const;
    void filter(DDSpecParRefs&, const std::string&) const;
    std::string_view front(const std::string_view) const;
    std::string_view back(const std::string_view) const;

    //! helper functions
    std::string_view nodeNameAt(int) const;
    const int nodeCopyNoAt(int) const;
    bool compareEqualName(const std::string_view, const std::string_view) const;
    std::tuple<std::string_view, std::string_view> alignNamespaces(std::string_view, std::string_view) const;
    bool compareEqualCopyNumber(const std::string_view, int) const;
    bool matchPath(const std::string_view) const;

    ExpandedNodes nodes_;
    std::vector<Iterator> it_;
    std::vector<std::unique_ptr<Filter>> filters_;
    Filter* currentFilter_ = nullptr;
    Node* node_ = nullptr;
    const DDSpecParRegistry* registry_;
    DDSpecParRefs refs_;
    const DDSpecPar* currentSpecPar_ = nullptr;
    int startLevel_;
  };
}  // namespace cms

//stream geoHistory
std::ostream& operator<<(std::ostream& os, const std::vector<const cms::Node*>& hst);

#endif