24constexpr HistogramRegistry::HistName::HistName(
char const*
const name)
27 idx(hash & REGISTRY_BITMASK)
31HistogramRegistry::HistogramRegistry(
char const*
const name, std::vector<HistogramSpec> histSpecs,
OutputObjHandlingPolicy policy,
bool sortHistos,
bool createRegistryDir)
32 : mName(
name), mPolicy(policy), mCreateRegistryDir(createRegistryDir), mSortHistos(sortHistos), mRegistryKey(), mRegistryValue()
34 mRegistryKey.fill(0u);
35 for (
auto& histSpec : histSpecs) {
45 std::memset(desc.str,
'_', 16);
47 s << std::hex << lhash;
48 s << std::hex << mTaskHash;
49 s << std::hex << reinterpret_cast<uint64_t>(
this);
50 std::memcpy(desc.str, s.str().data(), 12);
59 header.createContainer = mCreateRegistryDir ? 1 : 0;
71 validateHistName(histSpec.
name, histSpec.
hash);
72 const uint32_t idx = imask(histSpec.
hash);
73 for (
auto i = 0u;
i < MAX_REGISTRY_SIZE; ++
i) {
75 std::visit([&](
const auto& sharedPtr) { rawPtr = sharedPtr.get(); }, mRegistryValue[imask(idx +
i)]);
77 registerName(histSpec.
name);
78 mRegistryKey[imask(idx +
i)] = histSpec.
hash;
81 return mRegistryValue[imask(idx +
i)];
84 LOGF(fatal, R
"(Internal array of HistogramRegistry "%s" is full.)", mName);
89void HistogramRegistry::validateHistName(
const std::string&
name,
const uint32_t hash)
92 if (mRegisteredNames.size() == MAX_REGISTRY_SIZE) {
93 LOGF(fatal, R
"(HistogramRegistry "%s" is full! It can hold only %d histograms.)", mName, MAX_REGISTRY_SIZE);
97 auto it = std::find(mRegistryKey.begin(), mRegistryKey.end(), hash);
98 if (it != mRegistryKey.end()) {
99 auto idx = it - mRegistryKey.begin();
100 std::string collidingName{};
101 std::visit([&](
const auto& hist) { collidingName = hist->GetName(); }, mRegistryValue[
idx]);
102 LOGF(fatal, R
"(Hash collision in HistogramRegistry "%s"! Please rename histogram "%s" or "%s".)", mName, name, collidingName);
106 if (!std::regex_match(
name, std::regex(
"([a-zA-Z0-9])(([\\/_-])?[a-zA-Z0-9])*"))) {
107 LOGF(fatal, R
"(Histogram name "%s" contains invalid characters. Only letters, numbers, and (except for the beginning or end of the word) the special characters '/', '_', '-' are allowed.)", name);
113 return insert(histSpec);
118 return insert({
name, title, histConfigSpec, callSumw2});
123 return insert({
name, title, {histType, axes}, callSumw2});
128 return add(
name.c_str(), title, histType, axes, callSumw2);
134 auto doInsertClone = [&](
const auto& sharedPtr) {
135 if (!sharedPtr.get()) {
138 std::string sourceName{((TNamed*)sharedPtr.get())->GetName()};
140 if (sourceName.rfind(
source, 0) == 0) {
142 if (sourceName.size() !=
source.size() && (
source.back() !=
'/' ||
target.back() !=
'/')) {
146 if (sourceName.size() ==
source.size() &&
target.back() ==
'/') {
147 LOGF(fatal,
"Cannot turn histogram into folder!");
149 std::string targetName{
target};
150 targetName += sourceName.substr(sourceName.find(
source) +
source.size());
151 insertClone(targetName.data(), sharedPtr);
155 for (
auto& histVariant : mRegistryValue) {
156 std::visit(doInsertClone, histVariant);
164 auto iter = mRegistryKey.begin();
165 while ((iter = std::find(iter, mRegistryKey.end(), histName.hash)) != mRegistryKey.end()) {
166 const char* curName =
nullptr;
167 std::visit([&](
auto&& hist) {
if(hist) { curName = hist->GetName(); } }, mRegistryValue[iter - mRegistryKey.begin()]);
169 if (strcmp(curName, histName.str) == 0) {
180 std::visit([&fillFraction, &
size](
auto&& hist) {
size =
HistFiller::getSize(hist, fillFraction); }, mRegistryValue[getHistIndex(histName)]);
188 for (
auto j = 0u;
j < MAX_REGISTRY_SIZE; ++
j) {
196 for (
auto&
value : mRegistryValue) {
197 std::visit([](
auto&& hist) { hist.reset(); },
value);
204 std::vector<double> fillFractions{0.1, 0.25, 0.5};
205 std::vector<double> totalSizes(fillFractions.size());
208 bool containsSparseHist{};
209 auto printHistInfo = [&](
auto&& hist) {
211 using T = std::decay_t<
decltype(*hist)>;
213 if (hist->InheritsFrom(THnSparse::Class())) {
215 containsSparseHist =
true;
218 std::vector<double>
sizes;
219 std::string sizeInfo{};
221 std::transform(std::begin(fillFractions), std::end(fillFractions), std::back_inserter(
sizes), [&hist](
auto& fraction) {
return HistFiller::getSize(hist, fraction); });
222 for (
int i = 0;
i < fillFractions.size(); ++
i) {
223 sizeInfo += fmt::format(
"{:.2f} kB ({:.0f} %)",
sizes[
i] * 1024, fillFractions[
i] * 100);
224 if (
i != fillFractions.size() - 1) {
230 sizes.resize(fillFractions.size(),
size);
231 sizeInfo = fmt::format(
"{:.2f} kB",
sizes[0] * 1024);
233 std::transform(totalSizes.begin(), totalSizes.end(),
sizes.begin(), totalSizes.begin(), std::plus<double>());
234 LOGF(info,
"Hist %03d: %-35s %-19s [%s]", nHistos, hist->GetName(), hist->IsA()->GetName(), sizeInfo);
236 if (showAxisDetails) {
238 if constexpr (std::is_base_of_v<THnBase, T>) {
239 nDim = hist->GetNdimensions();
240 }
else if constexpr (std::is_base_of_v<TH1, T>) {
241 nDim = hist->GetDimension();
243 TAxis* axis{
nullptr};
244 for (
int d = 0; d < nDim; ++d) {
245 if constexpr (std::is_base_of_v<THnBase, T> || std::is_base_of_v<StepTHn, T>) {
246 axis = hist->GetAxis(d);
249 axis = hist->GetXaxis();
251 axis = hist->GetYaxis();
253 axis = hist->GetZaxis();
256 LOGF(info,
"- Axis %d: %-20s (%d bins)", d, axis->GetTitle(), axis->GetNbins());
262 std::string titleString{
"======================== HistogramRegistry ========================"};
264 LOGF(info,
"%s", titleString);
265 LOGF(info,
"%s\"%s\"", std::string((
int)(0.5 * titleString.size() - (1 + 0.5 * mName.size())),
' '), mName);
266 for (
auto& curHistName : mRegisteredNames) {
267 std::visit(printHistInfo, mRegistryValue[getHistIndex(HistName{curHistName.data()})]);
269 std::string totalSizeInfo{};
270 if (containsSparseHist) {
271 for (
int i = 0;
i < totalSizes.size(); ++
i) {
272 totalSizeInfo += fmt::format(
"{:.2f} MB ({:.0f} %)", totalSizes[
i], fillFractions[
i] * 100);
273 if (
i != totalSizes.size() - 1) {
274 totalSizeInfo +=
", ";
278 totalSizeInfo = fmt::format(
"{:.2f} MB", totalSizes[0]);
280 LOGF(info,
"%s", std::string(titleString.size(),
'='), titleString);
281 LOGF(info,
"Total: %d histograms, ca. %s", nHistos, totalSizeInfo);
283 LOGF(info,
"Due to index collisions, histograms were shifted by %d registry slots in total.",
lookup);
285 LOGF(info,
"%s", std::string(titleString.size(),
'='), titleString);
292 auto finalList = mRegisteredNames;
293 auto caseInsensitiveCompare = [](
const std::string&
s1,
const std::string& s2) {
294 return std::lexicographical_compare(
s1.begin(),
s1.end(), s2.begin(), s2.end(),
295 [](
char c1,
char c2) { return std::tolower(static_cast<unsigned char>(c1)) < std::tolower(static_cast<unsigned char>(c2)); });
298 std::sort(finalList.begin(), finalList.end(), caseInsensitiveCompare);
300 for (
auto& curHistName : finalList) {
301 TNamed* rawPtr =
nullptr;
302 std::visit([&](
const auto& sharedPtr) { rawPtr = (TNamed*)sharedPtr.get(); }, mRegistryValue[getHistIndex(HistName{curHistName.data()})]);
307 callback(*
this, rawPtr);
312std::deque<std::string> HistogramRegistry::splitPath(
const std::string& pathAndNameUser)
314 std::istringstream pathAndNameStream(pathAndNameUser);
315 std::deque<std::string> pathAndName;
317 while (std::getline(pathAndNameStream, curDir,
'/')) {
318 pathAndName.push_back(curDir);
324void HistogramRegistry::registerName(
const std::string&
name)
326 if (
name.empty() ||
name.back() ==
'/') {
327 LOGF(fatal,
"Invalid name for a histogram.");
329 std::deque<std::string>
path = splitPath(
name);
330 std::string cumulativeName{};
332 for (
auto& step :
path) {
334 LOGF(fatal, R
"(Found empty group name in path for histogram "%s".)", name);
336 cumulativeName += step;
337 for (
auto& curName : mRegisteredNames) {
339 if (cumulativeName == curName) {
340 LOGF(fatal, R
"(Histogram name "%s" is not compatible with existing names.)", name);
344 if (curName.rfind(cumulativeName, 0) == 0 && curName.size() > cumulativeName.size() && curName.at(cumulativeName.size()) ==
'/') {
345 LOGF(fatal, R
"(Histogram name "%s" is not compatible with existing names.)", name);
350 cumulativeName += "/";
352 mRegisteredNames.push_back(
name);
355void HistFiller::badHistogramFill(
char const*
name)
357 LOGF(fatal,
"The number of arguments in fill function called for histogram %s is incompatible with histogram dimensions.",
name);
361HistPtr HistogramRegistry::insertClone(
const HistName& histName,
const std::shared_ptr<T> originalHist)
363 validateHistName(histName.str, histName.hash);
364 for (
auto i = 0u;
i < MAX_REGISTRY_SIZE; ++
i) {
366 std::visit([&](
const auto& sharedPtr) { rawPtr = sharedPtr.get(); }, mRegistryValue[imask(histName.idx +
i)]);
368 registerName(histName.str);
369 mRegistryKey[imask(histName.idx +
i)] = histName.hash;
370 mRegistryValue[imask(histName.idx +
i)] = std::shared_ptr<T>(
static_cast<T*
>(originalHist->Clone(histName.str)));
372 return mRegistryValue[imask(histName.idx +
i)];
375 LOGF(fatal, R
"(Internal array of HistogramRegistry "%s" is full.)", mName);
379template HistPtr HistogramRegistry::insertClone(
const HistName&,
const std::shared_ptr<TH1>);
380template HistPtr HistogramRegistry::insertClone(
const HistName&,
const std::shared_ptr<TH2>);
381template HistPtr HistogramRegistry::insertClone(
const HistName&,
const std::shared_ptr<TH3>);
382template HistPtr HistogramRegistry::insertClone(
const HistName&,
const std::shared_ptr<TProfile>);
383template HistPtr HistogramRegistry::insertClone(
const HistName&,
const std::shared_ptr<TProfile2D>);
384template HistPtr HistogramRegistry::insertClone(
const HistName&,
const std::shared_ptr<TProfile3D>);
385template HistPtr HistogramRegistry::insertClone(
const HistName&,
const std::shared_ptr<THnSparse>);
386template HistPtr HistogramRegistry::insertClone(
const HistName&,
const std::shared_ptr<THn>);
387template HistPtr HistogramRegistry::insertClone(
const HistName&,
const std::shared_ptr<StepTHn>);
392 auto histVariant =
add(
name, title, histConfigSpec, callSumw2);
393 if (
auto histPtr = std::get_if<std::shared_ptr<T>>(&histVariant)) {
396 throw runtime_error_f(R
"(Histogram type specified in add<>("%s") does not match the actual type of the histogram!)", name);
403 auto histVariant =
add(
name, title, histType, axes, callSumw2);
404 if (
auto histPtr = std::get_if<std::shared_ptr<T>>(&histVariant)) {
407 throw runtime_error_f(R
"(Histogram type specified in add<>("%s") does not match the actual type of the histogram!)", name);
411template std::shared_ptr<TH1> HistogramRegistry::add<TH1>(
char const*
const name,
char const*
const title,
const HistogramConfigSpec& histConfigSpec,
bool callSumw2);
412template std::shared_ptr<TH1> HistogramRegistry::add<TH1>(
char const*
const name,
char const*
const title,
HistType histType,
const std::vector<AxisSpec>& axes,
bool callSumw2);
413template std::shared_ptr<TH2> HistogramRegistry::add<TH2>(
char const*
const name,
char const*
const title,
const HistogramConfigSpec& histConfigSpec,
bool callSumw2);
414template std::shared_ptr<TH2> HistogramRegistry::add<TH2>(
char const*
const name,
char const*
const title,
HistType histType,
const std::vector<AxisSpec>& axes,
bool callSumw2);
415template std::shared_ptr<TH3> HistogramRegistry::add<TH3>(
char const*
const name,
char const*
const title,
const HistogramConfigSpec& histConfigSpec,
bool callSumw2);
416template std::shared_ptr<TH3> HistogramRegistry::add<TH3>(
char const*
const name,
char const*
const title,
HistType histType,
const std::vector<AxisSpec>& axes,
bool callSumw2);
417template std::shared_ptr<TProfile> HistogramRegistry::add<TProfile>(
char const*
const name,
char const*
const title,
const HistogramConfigSpec& histConfigSpec,
bool callSumw2);
418template std::shared_ptr<TProfile> HistogramRegistry::add<TProfile>(
char const*
const name,
char const*
const title,
HistType histType,
const std::vector<AxisSpec>& axes,
bool callSumw2);
419template std::shared_ptr<TProfile2D> HistogramRegistry::add<TProfile2D>(
char const*
const name,
char const*
const title,
const HistogramConfigSpec& histConfigSpec,
bool callSumw2);
420template std::shared_ptr<TProfile2D> HistogramRegistry::add<TProfile2D>(
char const*
const name,
char const*
const title,
HistType histType,
const std::vector<AxisSpec>& axes,
bool callSumw2);
421template std::shared_ptr<TProfile3D> HistogramRegistry::add<TProfile3D>(
char const*
const name,
char const*
const title,
const HistogramConfigSpec& histConfigSpec,
bool callSumw2);
422template std::shared_ptr<TProfile3D> HistogramRegistry::add<TProfile3D>(
char const*
const name,
char const*
const title,
HistType histType,
const std::vector<AxisSpec>& axes,
bool callSumw2);
423template std::shared_ptr<THn> HistogramRegistry::add<THn>(
char const*
const name,
char const*
const title,
const HistogramConfigSpec& histConfigSpec,
bool callSumw2);
424template std::shared_ptr<THn> HistogramRegistry::add<THn>(
char const*
const name,
char const*
const title,
HistType histType,
const std::vector<AxisSpec>& axes,
bool callSumw2);
425template std::shared_ptr<THnSparse> HistogramRegistry::add<THnSparse>(
char const*
const name,
char const*
const title,
const HistogramConfigSpec& histConfigSpec,
bool callSumw2);
426template std::shared_ptr<THnSparse> HistogramRegistry::add<THnSparse>(
char const*
const name,
char const*
const title,
HistType histType,
const std::vector<AxisSpec>& axes,
bool callSumw2);
427template std::shared_ptr<StepTHn> HistogramRegistry::add<StepTHn>(
char const*
const name,
char const*
const title,
const HistogramConfigSpec& histConfigSpec,
bool callSumw2);
428template std::shared_ptr<StepTHn> HistogramRegistry::add<StepTHn>(
char const*
const name,
char const*
const title,
HistType histType,
const std::vector<AxisSpec>& axes,
bool callSumw2);
constexpr uint32_t runtime_hash(char const *str)
bool contains(const HistName &histName)
double getSize(const HistName &histName, double fillFraction=1.)
void fill(const HistName &histName, Ts... positionAndWeight)
void addClone(const std::string &source, const std::string &target)
void print(bool showAxisDetails=false)
void setHash(uint32_t hash)
HistPtr add(const HistogramSpec &histSpec)
void apply(std::function< void(HistogramRegistry const &, TNamed *named)> callback) const
OutputRef ref(uint16_t idx, uint16_t pipelineSize) const
void clean()
deletes all the histograms from the registry
GLuint GLsizei const GLuint const GLintptr const GLsizeiptr * sizes
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat s1
GLuint const GLchar * name
GLsizei GLsizei GLchar * source
GLsizei const GLfloat * value
GLint GLint GLsizei GLsizei GLsizei depth
GLsizei const GLchar *const * path
Defining PrimaryVertex explicitly as messageable.
@ HistogramRegistrySource
std::variant< std::shared_ptr< THn >, std::shared_ptr< THnSparse >, std::shared_ptr< TH3 >, std::shared_ptr< TH2 >, std::shared_ptr< TH1 >, std::shared_ptr< TProfile3D >, std::shared_ptr< TProfile2D >, std::shared_ptr< TProfile >, std::shared_ptr< StepTHn > > HistPtr
RuntimeErrorRef runtime_error_f(const char *,...)
OutputObjHandlingPolicy
Policy enum to determine OutputObj handling when writing.
static HistPtr createHistVariant(const HistogramSpec &histSpec)
static double getSize(std::shared_ptr< T > hist, double fillFraction=1.)