1 // -*- C++ -*- 2 // 3 // This file is part of HepMC 4 // Copyright (C) 2014-2020 The HepMC collaboration (see AUTHORS for details) 5 // 6 /// 7 /// @file Relatives.h 8 /// @brief Defines helper classes to extract relatives of an input GenParticle or GenVertex 9 /// 10 #ifndef HEPMC3_RELATIVES_H 11 #define HEPMC3_RELATIVES_H 12 13 #include <vector> 14 #include "HepMC3/GenParticle.h" 15 #include "HepMC3/GenVertex.h" 16 17 18 namespace HepMC3 { 19 20 /// forward declare the Relatives interface in which _parents and _children are wrapped 21 template<typename T> 22 class RelativesInterface; 23 /// forward declare the recursion wrapper 24 template<typename T> 25 class Recursive; 26 27 // forward declare _parents class 28 class _parents; 29 // forward declare _children class 30 class _children; 31 32 /// alias of _parents wrapped in the Relatives interface 33 using Parents = RelativesInterface<_parents>; 34 /// alias of _children wrapped in the Relatives interface 35 using Children = RelativesInterface<_children>; 36 /// Ancestors is an alias to Recursion applied to the _parents and wrapped in the Relatives interface 37 using Ancestors = RelativesInterface<Recursive<_parents> >; 38 /// Descendants is an alias to Recursion applied to the _children and wrapped in the Relatives interface 39 using Descendants = RelativesInterface<Recursive<_children> >; 40 41 /** @brief Define a common interface that all Relatives objects will satisfy 42 * Relatives provides an operator to get the relatives of a range of different 43 * GenObject types. The following are examples 44 * 45 * Relatives::ANCESTORS(GenParticlePtr);// returns ancestors of the particle 46 * Descendants descendants; 47 * descendants(GenVertexPtr);// descendants of the vertex 48 * vector<Relatives*> relations = {&Relatives::CHILDREN, &Relatives::DESCENDANTS, &Relatives::PARENTS, new Ancestors()}; // make a vector of Relatives 49 * 50 * You can also define your own relation and wrap it in the Relatives interface using 51 * Relatives * relo = new RelativesInterface<MyRelationClass>(); 52 */ 53 class Relatives { 54 public: 55 /// @brief Operator 56 virtual std::vector<GenParticlePtr> operator()(GenParticlePtr input) const = 0; 57 /// @brief Operator 58 virtual std::vector<ConstGenParticlePtr> operator()(ConstGenParticlePtr input) const = 0; 59 /// @brief Operator 60 virtual std::vector<GenParticlePtr> operator()(GenVertexPtr input) const = 0; 61 /// @brief Operator 62 virtual std::vector<ConstGenParticlePtr> operator()(ConstGenVertexPtr input) const = 0; 63 64 static const Parents PARENTS; ///< Parents 65 static const Children CHILDREN; ///< Children 66 static thread_local const Ancestors ANCESTORS; ///< Ancestors 67 static thread_local const Descendants DESCENDANTS; ///< Descendants 68 }; 69 70 /** @brief wrap a templated class that implements Relatives 71 * Since we need to template the functionality on the input 72 * type (GenParticlePtr, ConstGenVertexPtr etc.) we must wrap a 73 * class that has a templated operator in this that provides the 74 * Relatives interface and calls through to the underlying template 75 * method. 76 */ 77 template<typename Relative_type> 78 class RelativesInterface : public Relatives { 79 public: 80 //RelativesInterface(Relative_type relatives): _internal(relatives){} RelativesInterface()81 constexpr RelativesInterface() {} 82 83 /// @brief Operator operator()84 GenParticles_type<GenParticlePtr> operator()(GenParticlePtr input) const override {return _internal(input);} 85 /// @brief Operator operator()86 GenParticles_type<ConstGenParticlePtr> operator()(ConstGenParticlePtr input) const override {return _internal(input);} 87 /// @brief Operator operator()88 GenParticles_type<GenVertexPtr> operator()(GenVertexPtr input) const override {return _internal(input);} 89 /// @brief Operator operator()90 GenParticles_type<ConstGenVertexPtr> operator()(ConstGenVertexPtr input) const override {return _internal(input);} 91 92 private: 93 Relative_type _internal; 94 }; 95 /** @brief Recursive */ 96 template<typename Relation_type> 97 class Recursive { 98 public: 99 /// @brief Operator 100 template<typename GenObject_type> operator()101 GenParticles_type<GenObject_type> operator()(GenObject_type input) const { 102 for (auto obj: m_checkedObjects) { 103 delete obj; 104 } 105 m_checkedObjects.clear(); 106 return _recursive(input); 107 } 108 109 private: 110 /// @brief recursive 111 template<typename GenObject_type, typename dummy> 112 GenParticles_type<GenObject_type> _recursive(GenObject_type input) const; 113 114 /// @brief recursive _recursive(GenVertexPtr input)115 GenParticles_type<GenVertexPtr> _recursive(GenVertexPtr input) const { 116 GenParticles_type <GenVertexPtr> results; 117 if ( !input ) return results; 118 for (auto v: m_checkedObjects) { 119 if (v->id() == input->id()) return results; 120 } 121 122 m_checkedObjects.emplace_back(new idInterface<GenVertexPtr>(input)); 123 124 for (auto p: m_applyRelation(input)) { 125 results.emplace_back(p); 126 GenParticles_type <GenVertexPtr> tmp = _recursive(p); 127 results.insert(results.end(), 128 std::make_move_iterator(tmp.begin()), 129 std::make_move_iterator(tmp.end())); 130 } 131 132 return results; 133 } 134 135 /// @brief recursive _recursive(ConstGenVertexPtr input)136 GenParticles_type<ConstGenVertexPtr> _recursive(ConstGenVertexPtr input) const { 137 GenParticles_type <ConstGenVertexPtr> results; 138 if ( !input ) return results; 139 for (auto v: m_checkedObjects) { 140 if (v->id() == input->id()) return results; 141 } 142 143 m_checkedObjects.emplace_back(new idInterface<ConstGenVertexPtr>(input)); 144 145 for (auto p: m_applyRelation(input)) { 146 results.emplace_back(p); 147 GenParticles_type <ConstGenVertexPtr> tmp = _recursive(p); 148 results.insert(results.end(), 149 std::make_move_iterator(tmp.begin()), 150 std::make_move_iterator(tmp.end())); 151 } 152 153 return results; 154 } 155 156 /** @brief recursive */ _recursive(GenParticlePtr input)157 GenParticles_type<GenParticlePtr> _recursive(GenParticlePtr input) const { 158 return _recursive(m_applyRelation.vertex(input)); 159 } 160 /** @brief recursive */ _recursive(ConstGenParticlePtr input)161 GenParticles_type<ConstGenParticlePtr> _recursive(ConstGenParticlePtr input) const { 162 return _recursive(m_applyRelation.vertex(input)); 163 } 164 165 166 /** @brief hasID */ 167 class hasId { 168 public: 169 /// @brief destructor ~hasId()170 virtual ~hasId() {} 171 /// @brief id 172 virtual int id() const = 0; 173 }; 174 /** @brief iDinterface */ 175 template<typename ID_type> 176 class idInterface : public hasId { 177 public: 178 /** @brief idInterface */ idInterface(ID_type genObject)179 constexpr idInterface(ID_type genObject): m_object(genObject) {} 180 /** @brief id */ id()181 int id() const override {return m_object->id();} 182 183 private: 184 ID_type m_object; ///< id of object 185 }; 186 187 Relation_type m_applyRelation; ///< applyRelation 188 mutable std::vector<hasId*> m_checkedObjects; ///< Checked objects 189 }; 190 191 /** @brief Provides operator to find the parent particles of a Vertex or Particle 192 * 193 * Note you would usually not instantiate this directly, but wrap it in a RelativesInterface 194 */ 195 class _parents { 196 public: 197 /** @brief operator */ 198 template<typename GenObject_type, typename dummy> 199 GenParticles_type<GenObject_type> operator()(GenObject_type input) const; 200 201 /** @brief operator */ 202 template<typename GenObject_type, typename std::enable_if<std::is_same<GenVertex, typename std::remove_const<typename GenObject_type::element_type>::type>::value, int*>::type = nullptr> operator()203 GenParticles_type<GenObject_type> operator()(GenObject_type input) const {return input->particles_in();} 204 205 /** @brief operator */ 206 template<typename GenObject_type, typename std::enable_if<std::is_same<GenParticle, typename std::remove_const<typename GenObject_type::element_type>::type>::value, int*>::type = nullptr> operator()207 GenParticles_type<GenObject_type> operator()(GenObject_type input) const {return (*this)(vertex(input));} 208 209 /** @brief vertex */ 210 template<typename GenObject_type> vertex(GenObject_type input)211 GenVertex_type<GenObject_type> vertex(GenObject_type input) const {return input->production_vertex();} 212 }; 213 214 /** @brief Provides operator to find the child particles of a Vertex or Particle 215 * 216 * Note you would usually not instantiate this directly, but wrap it in a RelativesInterface 217 */ 218 class _children { 219 public: 220 /// @brief operator 221 template<typename GenObject_type, typename dummy> 222 GenParticles_type<GenObject_type> operator()(GenObject_type input) const; 223 224 /// @brief operator 225 template<typename GenObject_type, typename std::enable_if<std::is_same<GenVertex, typename std::remove_const<typename GenObject_type::element_type>::type>::value, int*>::type = nullptr> operator()226 GenParticles_type<GenObject_type> operator()(GenObject_type input) const {return input->particles_out();} 227 228 /// @brief operator 229 template<typename GenObject_type, typename std::enable_if<std::is_same<GenParticle, typename std::remove_const<typename GenObject_type::element_type>::type>::value, int*>::type = nullptr> operator()230 GenParticles_type<GenObject_type> operator()(GenObject_type input) const {return (*this)(vertex(input));} 231 232 /// @brief operator 233 template<typename GenObject_type> vertex(GenObject_type input)234 GenVertex_type<GenObject_type> vertex(GenObject_type input) const {return input->end_vertex();} 235 }; 236 237 } 238 239 240 namespace HepMC3 { 241 242 std::vector<HepMC3::GenParticlePtr> children_particles(HepMC3::GenVertexPtr O); ///< Return children particles 243 std::vector<HepMC3::ConstGenParticlePtr> children_particles(HepMC3::ConstGenVertexPtr O); ///< Return children particles 244 std::vector<HepMC3::GenVertexPtr> children_vertices(HepMC3::GenParticlePtr O); ///< Return children vertices 245 std::vector<HepMC3::ConstGenVertexPtr> children_vertices(HepMC3::ConstGenParticlePtr O); ///< Return children vertices 246 std::vector<HepMC3::GenParticlePtr> grandchildren_particles(HepMC3::GenParticlePtr O); ///< Return grandchildren particles 247 std::vector<HepMC3::ConstGenParticlePtr> grandchildren_particles(HepMC3::ConstGenParticlePtr O); ///< Return grandchildren particles 248 std::vector<HepMC3::GenVertexPtr> grandchildren_vertices(HepMC3::GenVertexPtr O); ///< Return grandchildren vertices 249 std::vector<HepMC3::ConstGenVertexPtr> grandchildren_vertices(HepMC3::ConstGenVertexPtr O); ///< Return grandchildren vertices 250 std::vector<HepMC3::GenParticlePtr> parent_particles(HepMC3::GenVertexPtr O); ///< Return parent particles 251 std::vector<HepMC3::ConstGenParticlePtr> parent_particles(HepMC3::ConstGenVertexPtr O); ///< Return parent particles 252 std::vector<HepMC3::GenVertexPtr> parent_vertices(HepMC3::GenParticlePtr O); ///< Return parent vertices 253 std::vector<HepMC3::ConstGenVertexPtr> parent_vertices(HepMC3::ConstGenParticlePtr O); ///< Return parent vertices 254 std::vector<HepMC3::GenParticlePtr> grandparent_particles(HepMC3::GenParticlePtr O); ///< Return grandparent particles 255 std::vector<HepMC3::ConstGenParticlePtr> grandparent_particles(HepMC3::ConstGenParticlePtr O); ///< Return grandparent particles 256 std::vector<HepMC3::GenVertexPtr> grandparent_vertices(HepMC3::GenVertexPtr O); ///< Return grandparent vertices 257 std::vector<HepMC3::ConstGenVertexPtr> grandparent_vertices(HepMC3::ConstGenVertexPtr O); ///< Return grandparent vertices 258 std::vector<HepMC3::ConstGenParticlePtr> descendant_particles(HepMC3::ConstGenVertexPtr obj); ///< Return descendant particles 259 std::vector<HepMC3::GenParticlePtr> descendant_particles(HepMC3::GenVertexPtr obj); ///< Return descendant particles 260 std::vector<HepMC3::ConstGenParticlePtr> descendant_particles(HepMC3::ConstGenParticlePtr obj); ///< Return descendant particles 261 std::vector<HepMC3::GenParticlePtr> descendant_particles(HepMC3::GenParticlePtr obj); ///< Return descendant particles 262 std::vector<HepMC3::ConstGenVertexPtr> descendant_vertices(HepMC3::ConstGenParticlePtr obj); ///< Return descendant vertices 263 std::vector<HepMC3::GenVertexPtr> descendant_vertices(HepMC3::GenParticlePtr obj); ///< Return descendant vertices 264 std::vector<HepMC3::ConstGenVertexPtr> descendant_vertices(HepMC3::ConstGenVertexPtr obj); ///< Return descendant vertices 265 std::vector<HepMC3::GenVertexPtr> descendant_vertices(HepMC3::GenVertexPtr obj); ///< Return descendant vertices 266 std::vector<HepMC3::ConstGenParticlePtr> ancestor_particles(HepMC3::ConstGenVertexPtr obj); ///< Return ancestor particles 267 std::vector<HepMC3::GenParticlePtr> ancestor_particles(HepMC3::GenVertexPtr obj); ///< Return ancestor particles 268 std::vector<HepMC3::ConstGenParticlePtr> ancestor_particles(HepMC3::ConstGenParticlePtr obj); ///< Return ancestor particles 269 std::vector<HepMC3::GenParticlePtr> ancestor_particles(HepMC3::GenParticlePtr obj); ///< Return ancestor particles 270 std::vector<HepMC3::ConstGenVertexPtr> ancestor_vertices(HepMC3::ConstGenParticlePtr obj); ///< Return ancestor vertices 271 std::vector<HepMC3::GenVertexPtr> ancestor_vertices(HepMC3::GenParticlePtr obj); ///< Return ancestor vertices 272 std::vector<HepMC3::ConstGenVertexPtr> ancestor_vertices(HepMC3::ConstGenVertexPtr obj); ///< Return ancestor vertices 273 std::vector<HepMC3::GenVertexPtr> ancestor_vertices(HepMC3::GenVertexPtr obj); ///< Return ancestor vertices 274 } 275 276 #endif 277 278