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