HepMC3 event record library
Feature.h
Go to the documentation of this file.
1// -*- C++ -*-
2//
3// This file is part of HepMC
4// Copyright (C) 2014-2023 The HepMC collaboration (see AUTHORS for details)
5//
6///
7/// @file Feature.h
8/// @brief Defines Feature interface for selecting Particles according to extracted Features.
9///
10
11#ifndef HEPMC3_FEATURE_H
12#define HEPMC3_FEATURE_H
13
14#include <functional>
15#include <memory>
16#include <limits>
17#include "HepMC3/GenParticle.h"
18#include "HepMC3/Filter.h"
19
20
21namespace HepMC3 {
22
23//////////////////////////////////////////////////////////////////////
24
25/**
26 * @brief GenericFeature defines the Feature interface
27 * GenericFeature is not intended to be used directly. The
28 * derived Feature class and its specialisations should be used.
29 *
30 * A Feature wraps a function object that can extract a
31 * generic Feature_type from a ConstGenParticlePtr. Usually the
32 * Feature_type would be something like int (e.g. status) or
33 * double (e.g. pT), but it could in principle be any attribute of a
34 * particle so long as there are well defined <, <=, >, >=, == and
35 * != operators for that attribute, as well as an abs function.
36 *
37 * Once a Feature is defined, you can obtain Filters that select
38 * Particles according to that Feature by e.g.
39 * Feature<int> status([](ConstGenParticlePtr p)->int{return p->status();});
40 * bool is_stable = (status == 1)(p);
41 * Filter is_beam = (status == 4);
42 * bool beam = is_beam(p);
43 *
44 * An abs function is also defined, so abs(Feature) works as you'd
45 * expect, e.g.
46 * Feature<double> rapidity([](ConstGenParticlePtr p)->double{return p->momentum().rap();});
47 * Filter rapCut = abs(rapidity) < 2.5;
48 *
49 * Please also see the Selector interface, which defines an
50 * abstract interface to Feature that is free of the template params
51 * and also includes some standard Features such as
52 *
53 * Selector::STATUS;
54 * Selector::PDG_ID;
55 * Selector::PT;
56 * Selector::RAPIDITY;
57 */
58template<typename Feature_type>
60public:
61 /// @brief evaluator type
62 using Evaluator_type = std::function<Feature_type(ConstGenParticlePtr)>;
63 /// @brief shared pointer for evaluator type
64 using EvaluatorPtr = std::shared_ptr<Evaluator_type>;
65
66 /// @brief access the underlying feature value
67 Feature_type operator()(ConstGenParticlePtr input)const {
68 return (*m_internal)(input);
69 }
70
71 /// @brief greater than operator
72 /// @return Filter function
73 Filter operator > (Feature_type value) const {
74 EvaluatorPtr functor = m_internal;
75 return [value, functor](ConstGenParticlePtr input)->bool{return (*functor)(input) > value;};
76 }
77 /// @brief less than operator
78 /// @return Filter function
79 Filter operator < (Feature_type value) const {
80 EvaluatorPtr functor = m_internal;
81 return [value, functor](ConstGenParticlePtr input)->bool{return (*functor)(input) < value;};
82 }
83
84 /// @brief greater than or equals operator
85 /// @return Filter function
86 Filter operator >= (Feature_type value) const {
87 EvaluatorPtr functor = m_internal;
88 return [value, functor](ConstGenParticlePtr input)->bool{return (*functor)(input) >= value;};
89 }
90
91 /// @brief less than or equals operator
92 /// @return Filter function
93 Filter operator <= (Feature_type value) const {
94 EvaluatorPtr functor = m_internal;
95 return [value, functor](ConstGenParticlePtr input)->bool{return (*functor)(input) <= value;};
96 }
97
98 /// @brief equality operator
99 /// @return Filter function
100 virtual Filter operator == (Feature_type value) const {
101 EvaluatorPtr functor = m_internal;
102 return [value, functor](ConstGenParticlePtr input)->bool{return (*functor)(input) == value;};
103 }
104
105 /// @brief inequality operator
106 /// @return Filter function
107 virtual Filter operator != (Feature_type value) const {
108 EvaluatorPtr functor = m_internal;
109 return [value, functor](ConstGenParticlePtr input)->bool{return (*functor)(input) != value;};
110 }
111
112protected:
113 /// Hide the constructor so no one can use GenericFeature directly
114 GenericFeature(Evaluator_type functor):m_internal(std::make_shared<Evaluator_type>(functor)) {}
115
116 /// Hide the copy constructor
118
119 /** @brief Move constructor */
121 /** @brief = */
123 /** @brief = */
125
126
127 /// @brief internal copy of func for evaluation
128 /// on the heap so will persist in resulting Filters even if
129 /// parent Feature object was destroyed
131};
132
133//////////////////////////////////////////////////////////////////////
134
135/** @brief Expose GenericFeature interface to derived Feature class
136 *
137 * This will get used for generic class types that aren't integral or
138 * floating point types.
139 *
140 * A Feature wraps a function object that can extract a
141 * generic Feature_type from a ConstGenParticlePtr. Usually the
142 * Feature_type would be something like int (e.g. status) or
143 * double (e.g. pT), but it could in principle be any attribute of a
144 * particle so long as there are well defined <, <=, >, >=, == and
145 * != operators for that attribute, as well as an abs function.
146 *
147 * Once a Feature is defined, you can obtain Filters that select
148 * Particles according to that Feature by e.g.
149 * Feature<int> status([](ConstGenParticlePtr p)->int{return p->status();});
150 * bool is_stable = (status == 1)(p);
151 * Filter is_beam = (status == 4);
152 * bool beam = is_beam(p);
153 *
154 * An abs function is also defined, so abs(Feature) works as you'd
155 * expect, e.g.
156 * Feature<double> rapidity([](ConstGenParticlePtr p)->double{return p->momentum().rap();});
157 * Filter rapCut = abs(rapidity) < 2.5;
158 *
159 * Please also see the Selector interface, which defines an
160 * abstract interface to Feature that is free of the template params
161 * and also includes some standard Features such as
162 *
163 * Selector::STATUS;
164 * Selector::PDG_ID;
165 * Selector::PT;
166 * Selector::RAPIDITY;
167
168 */
169template<typename Feature_type, typename Dummy = void>
170class Feature : public GenericFeature<Feature_type> {
171public:
174 using GenericFeature<Feature_type>::m_internal;
175
176 using GenericFeature<Feature_type>::operator ();
177 using GenericFeature<Feature_type>::operator >;
178 using GenericFeature<Feature_type>::operator >=;
179 using GenericFeature<Feature_type>::operator <;
180 using GenericFeature<Feature_type>::operator <=;
181 using GenericFeature<Feature_type>::operator ==;
182 using GenericFeature<Feature_type>::operator !=;
183
184 /// @brief Feature
185 Feature(Evaluator_type functor) : GenericFeature<Feature_type>(functor) {}
186 /// @brief Copy
187 Feature(const Feature &copy) : GenericFeature<Feature_type>(copy) {}
188 /** @brief Move constructor */
189 Feature(Feature && ) = default;
190 /** @brief = */
191 Feature& operator=(const Feature&) = default;
192 /** @brief = */
193 Feature& operator=(Feature&&) = default;
194
195 /// @brief Abs function
197 EvaluatorPtr functor = m_internal;
198 Evaluator_type absfunctor = [functor](ConstGenParticlePtr p)->Feature_type{return ::abs((*functor)(p));};
199 return Feature<Feature_type>(absfunctor);
200 }
201};
202
203//////////////////////////////////////////////////////////////////////
204
205/** @brief Specialisation of Feature for integral types
206 *
207 * It is a valid operator to compare an int to a float, but the
208 * generic version of these operators in the base class will
209 * first cast input float to an int, then compare that. In some cases
210 * the comparison will be incorrect because of rounding the float.
211 * e.g. int x=5; float y=5.5; bool result = x<y; would be wrong
212 * because y first gets converted to int 5.
213 *
214 * To solve this, we provide specialised comparison operators for
215 * integral type and double. Note that the opposite specialisation
216 * in which the Feature_type is floating_point is not necessary
217 */
218template<typename Feature_type>
219class Feature<Feature_type, typename std::enable_if<std::is_integral<Feature_type>::value, void>::type> : public GenericFeature<Feature_type> {
220public:
221 using GenericFeature<Feature_type>::operator ();
222 using GenericFeature<Feature_type>::operator >;
223 using GenericFeature<Feature_type>::operator >=;
224 using GenericFeature<Feature_type>::operator <;
225 using GenericFeature<Feature_type>::operator <=;
226 using GenericFeature<Feature_type>::operator ==;
227 using GenericFeature<Feature_type>::operator !=;
228
231
232 using GenericFeature<Feature_type>::m_internal;
233
234 /// @brief Feature
235 Feature(Evaluator_type functor) : GenericFeature<Feature_type>(functor) {}
236 /// @brief Feature
237 Feature(const Feature &copy) : GenericFeature<Feature_type>(copy) {}
238 /** @brief Move constructor */
239 Feature(Feature && ) = default;
240 /** @brief = */
241 Feature& operator=(const Feature&) = default;
242 /** @brief = */
243 Feature& operator=(Feature&&) = default;
244
245
246 /// @brief abs function
248 EvaluatorPtr functor = m_internal;
249 Evaluator_type absfunctor = [functor](ConstGenParticlePtr p)->Feature_type{return ::abs((*functor)(p));};
250 return Feature<Feature_type>(absfunctor);
251 }
252
253 /// @brief greater operator
254 Filter operator > (double value) const {
255 EvaluatorPtr functor = m_internal;
256 return [value, functor](ConstGenParticlePtr input)->bool{return (*functor)(input) > value;};
257 }
258
259 /// @brief less operator
260 Filter operator < (double value) const {
261 EvaluatorPtr functor = m_internal;
262 return [value, functor](ConstGenParticlePtr input)->bool{return (*functor)(input) < value;};
263 }
264
265 /// @brief equal operator
266 Filter operator == (double value) const {
267 EvaluatorPtr functor = m_internal;
268 return [value, functor](ConstGenParticlePtr input)->bool{
269 Feature_type local = (*functor)(input);
270 return std::abs(local - value) < std::numeric_limits<double>::epsilon();
271 };
272 }
273
274 /// @brief greater or equal operator
275 Filter operator >= (double value) const { return !( (*this) < value );}
276
277 /// @brief less or equal operator
278 Filter operator <= (double value) const { return !( (*this) > value );}
279
280 /// @brief not equal operator
281 Filter operator != (double value) const {
282 return !( (*this) == value );
283 }
284};
285
286//////////////////////////////////////////////////////////////////////
287
288/** @brief specialisation of Feature for floating point type
289 *
290 * Test of equality of floating point types is not safe. Here we
291 * provide a "reasonable" definition of equality based on the
292 * floating point precision.
293 */
294
295template<typename Feature_type>
296class Feature<Feature_type, typename std::enable_if<std::is_floating_point<Feature_type>::value, void>::type> : public GenericFeature<Feature_type> {
297public:
300
301 using GenericFeature<Feature_type>::operator ();
302 using GenericFeature<Feature_type>::operator >;
303 using GenericFeature<Feature_type>::operator >=;
304 using GenericFeature<Feature_type>::operator <;
305 using GenericFeature<Feature_type>::operator <=;
306
307 using GenericFeature<Feature_type>::m_internal;
308
309 /// @brief Feature
310 Feature(Evaluator_type functor) : GenericFeature<Feature_type>(functor) {}
311 /// @brief Copy
312 Feature(const Feature &copy) : GenericFeature<Feature_type>(copy) {}
313
314 /** @brief Move constructor */
315 Feature(Feature && ) = default;
316 /** @brief = */
317 Feature& operator=(const Feature&) = default;
318 /** @brief = */
319 Feature& operator=(Feature&&) = default;
320
321
322 /// @brief abs function
324 EvaluatorPtr functor = m_internal;
325 Evaluator_type absfunctor = [functor](ConstGenParticlePtr p)->Feature_type{return std::abs((*functor)(p));};
326 return Feature<Feature_type>(absfunctor);
327 }
328
329 Filter operator == (Feature_type value) const override {
330 EvaluatorPtr functor = m_internal;
331 return [value, functor](ConstGenParticlePtr input)->bool{
332 Feature_type local = (*functor)(input);
333 return std::less_equal<Feature_type>{}(fabs(local - value) , std::numeric_limits<Feature_type>::epsilon());
334 };
335 }
336
337 Filter operator != (Feature_type value) const override {
338 return !( (*this) == value );
339 }
340};
341
342//////////////////////////////////////////////////////////////////////
343
344/**
345 * @brief Obtain the absolute value of a Feature.
346 * This works as you'd expect. If foo is a valid Feature, then
347 * abs(foo) returns a new Feature that corresponds to the absolute
348 * value of the foo feature. You can construct a Filter from that in
349 * the usual way with e.g. Filter f = abs(foo) > 10.;
350 */
351template<typename Feature_type>
353 return input.abs();
354}
355
356}
357
358#endif
Defines Filter operations for combingin Filters.
Definition of class GenParticle.
Expose GenericFeature interface to derived Feature class.
Definition Feature.h:170
Feature & operator=(const Feature &)=default
=
Feature< Feature_type > abs() const
Abs function.
Definition Feature.h:196
Feature(Evaluator_type functor)
Feature.
Definition Feature.h:185
Feature & operator=(Feature &&)=default
=
Feature(Feature &&)=default
Move constructor.
Feature(const Feature &copy)
Copy.
Definition Feature.h:187
Filter operator>(Feature_type value) const
greater than operator
Definition Feature.h:73
Filter operator<(Feature_type value) const
less than operator
Definition Feature.h:79
EvaluatorPtr m_internal
internal copy of func for evaluation on the heap so will persist in resulting Filters even if parent ...
Definition Feature.h:130
Filter operator>=(Feature_type value) const
greater than or equals operator
Definition Feature.h:86
GenericFeature & operator=(const GenericFeature &)=default
=
std::function< Feature_type(ConstGenParticlePtr)> Evaluator_type
evaluator type
Definition Feature.h:62
virtual Filter operator!=(Feature_type value) const
inequality operator
Definition Feature.h:107
GenericFeature(GenericFeature &&)=default
Move constructor.
GenericFeature(const GenericFeature &copy)
Hide the copy constructor.
Definition Feature.h:117
GenericFeature & operator=(GenericFeature &&)=default
=
std::shared_ptr< Evaluator_type > EvaluatorPtr
shared pointer for evaluator type
Definition Feature.h:64
Feature_type operator()(ConstGenParticlePtr input) const
access the underlying feature value
Definition Feature.h:67
virtual Filter operator==(Feature_type value) const
equality operator
Definition Feature.h:100
Filter operator<=(Feature_type value) const
less than or equals operator
Definition Feature.h:93
GenericFeature(Evaluator_type functor)
Hide the constructor so no one can use GenericFeature directly.
Definition Feature.h:114
HepMC3 main namespace.
std::function< bool(ConstGenParticlePtr)> Filter
type of Filter
Definition Filter.h:19
Feature< Feature_type > abs(const Feature< Feature_type > &input)
Obtain the absolute value of a Feature. This works as you'd expect. If foo is a valid Feature,...
Definition Feature.h:352