19#ifndef UTILS_HISTOGRAM_HPP
20#define UTILS_HISTOGRAM_HPP
24#include <boost/multi_array.hpp>
46template <
typename T, std::
size_t N, std::
size_t M = 3,
typename U =
double>
48 using array_type = boost::multi_array<T, M + 1>;
49 using count_type = boost::multi_array<std::size_t, M + 1>;
50 using array_index =
typename array_type::index;
60 std::array<std::pair<U, U>, M> limits)
100 if (
pos.size() != M) {
101 throw std::invalid_argument(
"Wrong dimensions for the coordinates");
103 if (value.
size() !=
N) {
104 throw std::invalid_argument(
"Wrong dimensions for the value");
106 if (check_limits(
pos)) {
107 boost::array<array_index, M + 1> index;
108 for (std::size_t i = 0; i < M; ++i) {
111 for (array_index i = 0; i < static_cast<array_index>(
N); ++i) {
121 auto const bin_volume = std::accumulate(
125 [bin_volume](T v) { return static_cast<T>(v / bin_volume); });
135 array_index calc_bin_index(
double value,
double offset,
double size)
const {
136 return static_cast<array_index
>(std::floor((value - offset) / size));
142 std::array<U, M> calc_bin_sizes()
const {
143 std::array<U, M> bin_sizes;
144 for (std::size_t i = 0; i < M; ++i) {
155 bool check_limits(Span<const U>
pos)
const {
156 assert(
pos.size() == M);
157 bool within_range =
true;
158 for (std::size_t i = 0; i < M; ++i) {
160 within_range =
false;
165 std::array<std::size_t, M + 1> m_array_dim()
const {
166 std::array<std::size_t, M + 1> dimensions;
168 dimensions.back() =
N;
193template <
typename T, std::
size_t N, std::
size_t M = 3,
typename U =
double>
204 auto const min_r =
m_limits[0].first;
209 for (std::size_t i = 0; i < n_bins_r; i++) {
210 auto const r_left = min_r +
static_cast<U
>(i) * r_bin_size;
211 auto const r_right = r_left + r_bin_size;
212 auto const bin_volume =
213 (r_right * r_right - r_left * r_left) * z_bin_size * phi_bin_size / 2;
214 auto *begin =
m_array[i].origin();
216 begin, begin +
m_array[i].num_elements(), begin,
217 [bin_volume](T v) {
return static_cast<T
>(v / bin_volume); });
__shared__ int pos[MAXDEPTH *THREADS5/WARPSIZE]
Histogram in cylindrical coordinates.
void normalize() override
Histogram in Cartesian coordinates.
std::array< U, M > get_bin_sizes() const
Get the bin sizes.
std::array< std::size_t, M > m_n_bins
Number of bins for each dimension.
std::array< U, M > m_bin_sizes
Bin sizes for each dimension.
virtual void normalize()
Normalize histogram.
void update(Span< const U > pos, Span< const T > value)
Add data to the histogram.
std::array< std::pair< U, U >, M > m_limits
Min and max values for each dimension.
virtual ~Histogram()=default
count_type m_count
Track the number of total hits per bin entry.
std::array< T, N > m_ones
std::vector< std::size_t > get_tot_count() const
Get the histogram count data.
std::vector< T > get_histogram() const
Get the histogram data.
array_type m_array
Histogram data.
void update(Span< const U > pos)
Add data to the histogram.
std::array< std::pair< U, U >, M > get_limits() const
Get the ranges (min, max) for each dimension.
Histogram(std::array< std::size_t, M > n_bins, std::array< std::pair< U, U >, M > limits)
Histogram constructor.
std::array< std::size_t, M > get_n_bins() const
Get the number of bins for each dimension.
A stripped-down version of std::span from C++17.
DEVICE_QUALIFIER constexpr size_type size() const