tttrlib
A library for time-tagged time resolved data
Loading...
Searching...
No Matches
Histogram.h
Go to the documentation of this file.
1#ifndef TTTRLIB_HISTOGRAM_H
2#define TTTRLIB_HISTOGRAM_H
3
4#include <algorithm>
5#include <vector>
6#include <cstdio>
7#include <string.h>
8#include <string>
9
10#include <map>
11#include <cmath>
12
13#include "HistogramAxis.h"
14
15
16
17template<class T>
18class Histogram {
19
20private:
21
22 std::map<size_t , HistogramAxis<T>> axes;
23
24 T* histogram; // A 1D array of that contains the histogram
25 int number_of_axis;
26 int n_total_bins;
27 size_t getAxisDimensions(){
28 return axes.size();
29 }
30
31public:
32
33 void update(T *data, int n_rows_data, int n_cols_data){
34 int axis_index;
35 int global_bin_idx;
36 int global_bin_offset;
37 int n_axis;
38 int current_bin_idx, current_n_bins;
39 HistogramAxis<T> *current_axis;
40 T data_value;
41
42 // update the axes
43 for(const auto& p : axes){
44 axes[p.first].update();
45 }
46
47 // initialize a new empty histogram
48 // clear the memory of the old histogram
49 free(histogram);
50 // 1. count the total number of bins
51 n_total_bins = 1;
52 n_axis = 0;
53 for(const auto& p : axes){
54 axis_index = p.first;
55 n_axis += 1;
56 n_total_bins *= axes[axis_index].getNumberOfBins();
57 }
58 // 2. fill the histogram with zeros
59 histogram = (T*) malloc(sizeof(T) * (n_total_bins));
60 for(global_bin_idx=0; global_bin_idx < n_total_bins; global_bin_idx++){
61 histogram[global_bin_idx] = 0.0;
62 }
63
64 // Fill the histogram
65 // Very instructive for multi-dimensional array indexing
66 // https://eli.thegreenplace.net/2015/memory-layout-of-multi-dimensional-arrays/
67 bool is_inside;
68 for(int i_row=0; i_row<n_rows_data; i_row++){
69 // in this loop the position within the 1D array is calculated
70 global_bin_offset = 0;
71 is_inside = true;
72 for(const auto& p : axes){
73 axis_index = p.first;
74 current_axis = &axes[axis_index];
75
76 data_value = data[i_row*n_axis + axis_index];
77 current_bin_idx = current_axis->getBinIdx(data_value);
78 current_n_bins = current_axis->getNumberOfBins();
79
80 if( (current_bin_idx < 0) || (current_bin_idx >= current_n_bins) ){
81 is_inside = false;
82 break;
83 }
84 global_bin_offset = current_bin_idx + current_n_bins * global_bin_offset;
85 }
86 if(is_inside){
87 histogram[global_bin_offset] += 1.0;
88 }
89 }
90 }
91
92 void get_histogram(T** hist, int* dim){
93 *hist = histogram;
94 *dim = n_total_bins;
95 }
96
97 void set_axis(size_t data_column, HistogramAxis<T> &new_axis){
98 axes[data_column] = new_axis;
99 }
100
102 size_t data_column,
103 std::string name,
104 T begin, T end, int n_bins,
105 std::string axis_type
106 ){
107 HistogramAxis<T> new_axis(name, begin, end, n_bins, axis_type);
108 set_axis(data_column, new_axis);
109 }
110
111 HistogramAxis<T> get_axis(size_t axis_index){
112 return axes[axis_index];
113 }
114
115 Histogram() = default;
116
117 ~Histogram() = default;
118
119};
120
121
122void bincount1D(int *data, int n_data, int *bins, int n_bins);
123
124
140template<typename T>
142 T *data, int n_data,
143 double *weights, int n_weights,
144 T *bin_edges, int n_bins,
145 double *hist, int n_hist,
146 const char *axis_type,
147 bool use_weights
148) {
149 T v; // stores the data value in iterations
150 int i, bin_idx;
151 T lower, upper, bin_width;
152 bool is_log10 = !strcmp(axis_type, "log10");
153 bool is_lin = !strcmp(axis_type, "lin");
154
155 if (is_lin || is_log10) {
156 if (is_log10) {
157 lower = std::log10(bin_edges[0]);
158 upper = std::log10(bin_edges[n_bins - 1]);
159 } else {
160 lower = bin_edges[0];
161 upper = bin_edges[n_bins - 1];
162 }
163 bin_width = (upper - lower) / (n_bins - 1);
164
165 for (i = 0; i < n_data; i++) {
166 v = data[i];
167 if(is_log10){
168 if(v == 0){
169 continue;
170 } else {
171 v = std::log10(v);
172 }
173 }
174 bin_idx = calc_bin_idx(lower, bin_width, v);
175 // ignore values outside of the bounds
176 if ((bin_idx <= n_bins) && (bin_idx >= 0)){
177 hist[bin_idx] += (use_weights) ? weights[i] : 1;
178 }
179 }
180 } else {
181 for (i = 0; i < n_data; i++) {
182 v = data[i];
183 bin_idx = search_bin_idx(v, bin_edges, n_bins);
184 if(bin_idx > 0)
185 hist[bin_idx] += (use_weights) ? weights[i] : 1;
186 }
187 }
188
189}
190
191
192#endif //TTTRLIB_HISTOGRAM_H
void histogram1D(T *data, int n_data, double *weights, int n_weights, T *bin_edges, int n_bins, double *hist, int n_hist, const char *axis_type, bool use_weights)
Definition Histogram.h:141
void bincount1D(int *data, int n_data, int *bins, int n_bins)
int search_bin_idx(T value, T *bin_edges, int n_bins)
Definition HistogramAxis.h:43
int calc_bin_idx(T begin, T bin_width, T value)
Definition HistogramAxis.h:75
Definition HistogramAxis.h:80
int getNumberOfBins()
Definition HistogramAxis.h:119
void update()
Definition HistogramAxis.h:96
int getBinIdx(T value)
Definition HistogramAxis.h:123
Definition Histogram.h:18
Histogram()=default
HistogramAxis< T > get_axis(size_t axis_index)
Definition Histogram.h:111
void get_histogram(T **hist, int *dim)
Definition Histogram.h:92
void set_axis(size_t data_column, std::string name, T begin, T end, int n_bins, std::string axis_type)
Definition Histogram.h:101
~Histogram()=default
void set_axis(size_t data_column, HistogramAxis< T > &new_axis)
Definition Histogram.h:97
void update(T *data, int n_rows_data, int n_cols_data)
Definition Histogram.h:33