The Gaudi Framework  master (b9786168)
Loading...
Searching...
No Matches
HistogramWrapper.h
Go to the documentation of this file.
1/***********************************************************************************\
2* (c) Copyright 1998-2025 CERN for the benefit of the LHCb and ATLAS collaborations *
3* *
4* This software is distributed under the terms of the Apache version 2 licence, *
5* copied verbatim in the file "LICENSE". *
6* *
7* In applying this licence, CERN does not waive the privileges and immunities *
8* granted to it by virtue of its status as an Intergovernmental Organization *
9* or submit itself to any jurisdiction. *
10\***********************************************************************************/
11#pragma once
12
14
15namespace Gaudi::Accumulators {
16
38 template <typename HistogramType,
39 typename Seq =
40 std::make_integer_sequence<unsigned int, std::tuple_size_v<typename HistogramType::AxisTupleType>>>
42 template <typename HistogramType, unsigned int... ND>
43 class HistogramWrapperInternal<HistogramType, std::integer_sequence<unsigned int, ND...>> {
44 public:
45 using AxisTupleType = typename HistogramType::AxisTupleType;
46 using AxisArithmeticType = typename HistogramType::AxisArithmeticType;
47 using BufferType = typename HistogramType::BufferType;
48 template <unsigned int I>
49 using AxisType = std::tuple_element_t<I, AxisTupleType>;
50
52 template <typename OWNER>
53 HistogramWrapperInternal( OWNER* owner, std::string const& name, std::string const& title = "",
54 typename HistogramType::AxisTupleType axis = {}, bool doNotInitialize = false )
55 : m_name{ name }, m_title{ title }, m_axis{ axis } {
56 // Create associated properties
57 owner->declareProperty( titlePropertyName(), m_title, std::format( "Title of histogram {}", name ) )
58 ->template setOwnerType<OWNER>();
59 ( owner
60 ->declareProperty( axisPropertyName<ND>(), std::get<ND>( m_axis ),
61 std::format( "Axis {} of histogram {}", ND, name ) )
62 ->template setOwnerType<OWNER>(),
63 ... );
64 // register creation of the Histogram at initialization time
65 if ( !doNotInitialize ) {
66 if ( owner->FSMState() >= Gaudi::StateMachine::INITIALIZED ) {
67 // if the owner is already initialized (e.g. the histogram is being created during `start()`)
68 // it is too late to register the callback
69 createHistogram( *owner );
70 } else {
71 owner->registerCallBack( StateMachine::INITIALIZE, [this, owner]() { createHistogram( *owner ); } );
72 }
73 }
74 }
75
77 template <typename OWNER>
78 HistogramWrapperInternal( OWNER const* owner, std::string const& name, std::string const& title = "",
79 typename HistogramType::AxisTupleType axis = {} )
80 : m_name{ name }, m_title{ title }, m_axis{ axis } {
81 createHistogram( *owner );
82 }
83
84 template <typename OWNER>
85 HistogramWrapperInternal( OWNER* owner, std::string const& name, std::string const& title, AxisType<ND>... allAxis )
86 : HistogramWrapperInternal( owner, name, title, std::make_tuple( allAxis... ) ) {}
87
89 [[nodiscard]] auto operator[]( typename HistogramType::AxisTupleArithmeticType v ) {
90 if ( !m_histo ) {
91 throw std::logic_error( std::format( "Histogram {} is used before being initialized", m_name ) );
92 }
93 return m_histo.value()[v];
94 }
95
97 template <typename OWNER>
98 void createHistogram( OWNER& owner ) {
99 m_histo.emplace( &owner, m_name, m_title, m_axis );
100 }
101
102 friend void to_json( nlohmann::json& j, HistogramWrapperInternal const& h ) {
103 if ( !h.m_histo ) {
104 throw std::logic_error( std::format( "Histogram {} is converted to json before being initialized", h.m_name ) );
105 }
106 j = h.m_histo.value();
107 }
108
109 // set directly some properties, only if histogram was not yet created
110 void setTitle( std::string const& title ) {
111 if ( m_histo )
112 throw std::logic_error(
113 std::format( "Cannot modify title of histogram {} after it has been initialized", m_name ) );
114 m_title = title;
115 }
116 template <unsigned int N>
117 void setAxis( std::tuple_element_t<N, typename HistogramType::AxisTupleType> const& axis ) {
118 if ( m_histo )
119 throw std::logic_error(
120 std::format( "Cannot modify axis {} of histogram {} after it has been initialized", N, m_name ) );
121 std::get<N>( m_axis ) = axis;
122 }
123
124 template <unsigned int N>
125 auto& axis() const {
126 if ( !m_histo )
127 throw std::logic_error(
128 std::format( "Cannot get axis {} of histogram {} before it has been initialized", N, m_name ) );
129 return m_histo->template axis<N>();
130 }
131
132 auto& axis() const {
133 if ( !m_histo )
134 throw std::logic_error(
135 std::format( "Cannot get axis of histogram {} before it has been initialized", m_name ) );
136 return m_histo->axis();
137 }
138
139 void reset() { m_histo.reset(); }
140
141 // wrapping some methods of the underlyoing histogram
142 auto buffer() {
143 if ( !m_histo )
144 throw std::logic_error( std::format( "`buffer()` called on histogram {} before being initialized", m_name ) );
145 return m_histo->buffer();
146 }
147
148 private:
149 std::string basePropertyName() const {
150 // properties are used as identifiers in python and thus cannot anything alse than _, letters and numbers
151 // we thus replace anything else with '_' in the property names
152 std::string name = m_name;
153 std::replace_if(
154 begin( name ), end( name ), []( auto& c ) { return !std::isalnum( c ); }, '_' );
155 return name;
156 }
157 std::string titlePropertyName() const { return std::format( "{}_Title", basePropertyName() ); }
158 template <unsigned int N>
159 std::string axisPropertyName() const {
160 return std::format( "{}_Axis{}", basePropertyName(), N );
161 }
162
163 // Members of the custom histogrem
164 std::string m_name{};
165 std::string m_title{};
166 typename HistogramType::AxisTupleType m_axis{};
167 std::optional<HistogramType> m_histo{};
168 };
169
170 template <typename HistogramType>
172
173} // namespace Gaudi::Accumulators
A Wrapper of a static Histogram base class using Properties to define title and axis.
void setAxis(std::tuple_element_t< N, typename HistogramType::AxisTupleType > const &axis)
HistogramWrapperInternal(OWNER *owner, std::string const &name, std::string const &title, AxisType< ND >... allAxis)
constructor with more natural syntax for axis
void createHistogram(OWNER &owner)
creation of the internal histogram, from the properties
auto operator[](typename HistogramType::AxisTupleArithmeticType v)
override of operator[] with extra checking that initialization happened
HistogramWrapperInternal(OWNER *owner, std::string const &name, std::string const &title="", typename HistogramType::AxisTupleType axis={}, bool doNotInitialize=false)
constructor, only creates a set of Properties
HistogramWrapperInternal(OWNER const *owner, std::string const &name, std::string const &title="", typename HistogramType::AxisTupleType axis={})
constructor with const owner (i.e.
Efficient counter implementations for Gaudi.
HistogramWrapperInternal< HistogramType > HistogramWrapper
STL namespace.