25constexpr HistogramRegistry::HistName::HistName(
char const*
const name)
32HistogramRegistry::HistogramRegistry(
char const*
const name, std::vector<HistogramSpec> histSpecs,
OutputObjHandlingPolicy policy,
bool sortHistos,
bool createRegistryDir)
33 : mName(
name), mPolicy(policy), mCreateRegistryDir(createRegistryDir), mSortHistos(sortHistos), mRegistryKey(), mRegistryValue()
35 mRegistryKey.fill(0u);
36 for (
auto& histSpec : histSpecs) {
46 std::memset(desc.str,
'_', 16);
48 s << std::hex << lhash;
49 s << std::hex << mTaskHash;
50 s << std::hex << reinterpret_cast<uint64_t>(
this);
51 std::memcpy(desc.str, s.str().data(), 12);
60 header.createContainer = mCreateRegistryDir ? 1 : 0;
72 validateHistName(histSpec.
name, histSpec.
hash);
73 const uint32_t idx = imask(histSpec.
hash);
74 for (
auto i = 0u;
i < MAX_REGISTRY_SIZE; ++
i) {
76 std::visit([&](
const auto& sharedPtr) { rawPtr = sharedPtr.get(); }, mRegistryValue[imask(idx +
i)]);
78 registerName(histSpec.
name);
79 mRegistryKey[imask(idx +
i)] = histSpec.
hash;
82 return mRegistryValue[imask(idx +
i)];
85 LOGF(fatal, R
"(Internal array of HistogramRegistry "%s" is full.)", mName);
90void HistogramRegistry::validateHistName(
const std::string&
name,
const uint32_t
hash)
93 if (mRegisteredNames.size() == MAX_REGISTRY_SIZE) {
94 LOGF(fatal, R
"(HistogramRegistry "%s" is full! It can hold only %d histograms.)", mName, MAX_REGISTRY_SIZE);
98 auto it = std::find(mRegistryKey.begin(), mRegistryKey.end(),
hash);
99 if (it != mRegistryKey.end()) {
100 auto idx = it - mRegistryKey.begin();
101 std::string collidingName{};
102 std::visit([&](
const auto& hist) { collidingName = hist->GetName(); }, mRegistryValue[
idx]);
103 LOGF(fatal, R
"(Hash collision in HistogramRegistry "%s"! Please rename histogram "%s" or "%s".)", mName, name, collidingName);
107 if (!std::regex_match(
name, std::regex(
"([a-zA-Z0-9])(([\\/_-])?[a-zA-Z0-9])*"))) {
108 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);
114 return insert(histSpec);
119 return insert({
name, title, histConfigSpec, callSumw2});
124 return insert({
name, title, {histType, axes}, callSumw2});
129 return add(
name.c_str(), title, histType, axes, callSumw2);
135 auto doInsertClone = [&](
const auto& sharedPtr) {
136 if (!sharedPtr.get()) {
139 std::string sourceName{((TNamed*)sharedPtr.get())->GetName()};
141 if (sourceName.rfind(
source, 0) == 0) {
143 if (sourceName.size() !=
source.size() && (
source.back() !=
'/' ||
target.back() !=
'/')) {
147 if (sourceName.size() ==
source.size() &&
target.back() ==
'/') {
148 LOGF(fatal,
"Cannot turn histogram into folder!");
150 std::string targetName{
target};
151 targetName += sourceName.substr(sourceName.find(
source) +
source.size());
152 insertClone(targetName.data(), sharedPtr);
156 for (
auto& histVariant : mRegistryValue) {
157 std::visit(doInsertClone, histVariant);
165 auto iter = mRegistryKey.begin();
166 while ((iter = std::find(iter, mRegistryKey.end(), histName.hash)) != mRegistryKey.end()) {
167 const char* curName =
nullptr;
168 std::visit([&](
auto&& hist) {
if(hist) { curName = hist->GetName(); } }, mRegistryValue[iter - mRegistryKey.begin()]);
170 if (strcmp(curName, histName.str) == 0) {
181 std::visit([&fillFraction, &
size](
auto&& hist) {
size =
HistFiller::getSize(hist, fillFraction); }, mRegistryValue[getHistIndex(histName)]);
189 for (
auto j = 0u;
j < MAX_REGISTRY_SIZE; ++
j) {
197 for (
auto&
value : mRegistryValue) {
198 std::visit([](
auto&& hist) { hist.reset(); },
value);
205 std::vector<double> fillFractions{0.1, 0.25, 0.5};
206 std::vector<double> totalSizes(fillFractions.size());
209 bool containsSparseHist{};
210 auto printHistInfo = [&](
auto&& hist) {
212 using T = std::decay_t<
decltype(*hist)>;
214 if (hist->InheritsFrom(THnSparse::Class())) {
216 containsSparseHist =
true;
219 std::vector<double>
sizes;
220 std::string sizeInfo{};
222 std::transform(std::begin(fillFractions), std::end(fillFractions), std::back_inserter(
sizes), [&hist](
auto& fraction) {
return HistFiller::getSize(hist, fraction); });
223 for (
int i = 0;
i < fillFractions.size(); ++
i) {
224 sizeInfo += fmt::format(
"{:.2f} kB ({:.0f} %)",
sizes[
i] * 1024, fillFractions[
i] * 100);
225 if (
i != fillFractions.size() - 1) {
231 sizes.resize(fillFractions.size(),
size);
232 sizeInfo = fmt::format(
"{:.2f} kB",
sizes[0] * 1024);
234 std::transform(totalSizes.begin(), totalSizes.end(),
sizes.begin(), totalSizes.begin(), std::plus<double>());
235 LOGF(info,
"Hist %03d: %-35s %-19s [%s]", nHistos, hist->GetName(), hist->IsA()->GetName(), sizeInfo);
237 if (showAxisDetails) {
239 if constexpr (std::is_base_of_v<THnBase, T>) {
240 nDim = hist->GetNdimensions();
241 }
else if constexpr (std::is_base_of_v<TH1, T>) {
242 nDim = hist->GetDimension();
244 TAxis* axis{
nullptr};
245 for (
int d = 0; d < nDim; ++d) {
246 if constexpr (std::is_base_of_v<THnBase, T> || std::is_base_of_v<StepTHn, T>) {
247 axis = hist->GetAxis(d);
250 axis = hist->GetXaxis();
252 axis = hist->GetYaxis();
254 axis = hist->GetZaxis();
257 LOGF(info,
"- Axis %d: %-20s (%d bins)", d, axis->GetTitle(), axis->GetNbins());
263 std::string titleString{
"======================== HistogramRegistry ========================"};
265 LOGF(info,
"%s", titleString);
266 LOGF(info,
"%s\"%s\"", std::string((
int)(0.5 * titleString.size() - (1 + 0.5 * mName.size())),
' '), mName);
267 for (
auto& curHistName : mRegisteredNames) {
268 std::visit(printHistInfo, mRegistryValue[getHistIndex(HistName{curHistName.data()})]);
270 std::string totalSizeInfo{};
271 if (containsSparseHist) {
272 for (
int i = 0;
i < totalSizes.size(); ++
i) {
273 totalSizeInfo += fmt::format(
"{:.2f} MB ({:.0f} %)", totalSizes[
i], fillFractions[
i] * 100);
274 if (
i != totalSizes.size() - 1) {
275 totalSizeInfo +=
", ";
279 totalSizeInfo = fmt::format(
"{:.2f} MB", totalSizes[0]);
281 LOGF(info,
"%s", std::string(titleString.size(),
'='), titleString);
282 LOGF(info,
"Total: %d histograms, ca. %s", nHistos, totalSizeInfo);
284 LOGF(info,
"Due to index collisions, histograms were shifted by %d registry slots in total.",
lookup);
286 LOGF(info,
"%s", std::string(titleString.size(),
'='), titleString);
293 auto finalList = mRegisteredNames;
294 auto caseInsensitiveCompare = [](
const std::string&
s1,
const std::string& s2) {
295 return std::lexicographical_compare(
s1.begin(),
s1.end(), s2.begin(), s2.end(),
296 [](
char c1,
char c2) { return std::tolower(static_cast<unsigned char>(c1)) < std::tolower(static_cast<unsigned char>(c2)); });
299 std::sort(finalList.begin(), finalList.end(), caseInsensitiveCompare);
301 for (
auto& curHistName : finalList) {
302 TNamed* rawPtr =
nullptr;
303 std::visit([&](
const auto& sharedPtr) { rawPtr = (TNamed*)sharedPtr.get(); }, mRegistryValue[getHistIndex(HistName{curHistName.data()})]);
308 callback(*
this, rawPtr);
313std::deque<std::string> HistogramRegistry::splitPath(
const std::string& pathAndNameUser)
315 std::istringstream pathAndNameStream(pathAndNameUser);
316 std::deque<std::string> pathAndName;
318 while (std::getline(pathAndNameStream, curDir,
'/')) {
319 pathAndName.push_back(curDir);
325void HistogramRegistry::registerName(
const std::string&
name)
327 if (
name.empty() ||
name.back() ==
'/') {
328 LOGF(fatal,
"Invalid name for a histogram.");
330 std::deque<std::string>
path = splitPath(
name);
331 std::string cumulativeName{};
333 for (
auto& step :
path) {
335 LOGF(fatal, R
"(Found empty group name in path for histogram "%s".)", name);
337 cumulativeName += step;
338 for (
auto& curName : mRegisteredNames) {
340 if (cumulativeName == curName) {
341 LOGF(fatal, R
"(Histogram name "%s" is not compatible with existing names.)", name);
345 if (curName.rfind(cumulativeName, 0) == 0 && curName.size() > cumulativeName.size() && curName.at(cumulativeName.size()) ==
'/') {
346 LOGF(fatal, R
"(Histogram name "%s" is not compatible with existing names.)", name);
351 cumulativeName += "/";
353 mRegisteredNames.push_back(
name);
356void HistFiller::badHistogramFill(
char const*
name)
358 LOGF(fatal,
"The number of arguments in fill function called for histogram %s is incompatible with histogram dimensions.",
name);
362HistPtr HistogramRegistry::insertClone(
const HistName& histName,
const std::shared_ptr<T> originalHist)
364 validateHistName(histName.str, histName.hash);
365 for (
auto i = 0u;
i < MAX_REGISTRY_SIZE; ++
i) {
367 std::visit([&](
const auto& sharedPtr) { rawPtr = sharedPtr.get(); }, mRegistryValue[imask(histName.idx +
i)]);
369 registerName(histName.str);
370 mRegistryKey[imask(histName.idx +
i)] = histName.hash;
371 mRegistryValue[imask(histName.idx +
i)] = std::shared_ptr<T>(
static_cast<T*
>(originalHist->Clone(histName.str)));
373 return mRegistryValue[imask(histName.idx +
i)];
376 LOGF(fatal, R
"(Internal array of HistogramRegistry "%s" is full.)", mName);
380template HistPtr HistogramRegistry::insertClone(
const HistName&,
const std::shared_ptr<TH1>);
381template HistPtr HistogramRegistry::insertClone(
const HistName&,
const std::shared_ptr<TH2>);
382template HistPtr HistogramRegistry::insertClone(
const HistName&,
const std::shared_ptr<TH3>);
383template HistPtr HistogramRegistry::insertClone(
const HistName&,
const std::shared_ptr<TProfile>);
384template HistPtr HistogramRegistry::insertClone(
const HistName&,
const std::shared_ptr<TProfile2D>);
385template HistPtr HistogramRegistry::insertClone(
const HistName&,
const std::shared_ptr<TProfile3D>);
386template HistPtr HistogramRegistry::insertClone(
const HistName&,
const std::shared_ptr<THnSparse>);
387template HistPtr HistogramRegistry::insertClone(
const HistName&,
const std::shared_ptr<THn>);
388template HistPtr HistogramRegistry::insertClone(
const HistName&,
const std::shared_ptr<StepTHn>);
393 auto histVariant =
add(
name, title, histConfigSpec, callSumw2);
394 if (
auto histPtr = std::get_if<std::shared_ptr<T>>(&histVariant)) {
397 throw runtime_error_f(R
"(Histogram type specified in add<>("%s") does not match the actual type of the histogram!)", name);
404 auto histVariant =
add(
name, title, histType, axes, callSumw2);
405 if (
auto histPtr = std::get_if<std::shared_ptr<T>>(&histVariant)) {
408 throw runtime_error_f(R
"(Histogram type specified in add<>("%s") does not match the actual type of the histogram!)", name);
412template std::shared_ptr<TH1> HistogramRegistry::add<TH1>(
char const*
const name,
char const*
const title,
const HistogramConfigSpec& histConfigSpec,
bool callSumw2);
413template std::shared_ptr<TH1> HistogramRegistry::add<TH1>(
char const*
const name,
char const*
const title,
HistType histType,
const std::vector<AxisSpec>& axes,
bool callSumw2);
414template std::shared_ptr<TH2> HistogramRegistry::add<TH2>(
char const*
const name,
char const*
const title,
const HistogramConfigSpec& histConfigSpec,
bool callSumw2);
415template std::shared_ptr<TH2> HistogramRegistry::add<TH2>(
char const*
const name,
char const*
const title,
HistType histType,
const std::vector<AxisSpec>& axes,
bool callSumw2);
416template std::shared_ptr<TH3> HistogramRegistry::add<TH3>(
char const*
const name,
char const*
const title,
const HistogramConfigSpec& histConfigSpec,
bool callSumw2);
417template std::shared_ptr<TH3> HistogramRegistry::add<TH3>(
char const*
const name,
char const*
const title,
HistType histType,
const std::vector<AxisSpec>& axes,
bool callSumw2);
418template std::shared_ptr<TProfile> HistogramRegistry::add<TProfile>(
char const*
const name,
char const*
const title,
const HistogramConfigSpec& histConfigSpec,
bool callSumw2);
419template std::shared_ptr<TProfile> HistogramRegistry::add<TProfile>(
char const*
const name,
char const*
const title,
HistType histType,
const std::vector<AxisSpec>& axes,
bool callSumw2);
420template std::shared_ptr<TProfile2D> HistogramRegistry::add<TProfile2D>(
char const*
const name,
char const*
const title,
const HistogramConfigSpec& histConfigSpec,
bool callSumw2);
421template std::shared_ptr<TProfile2D> HistogramRegistry::add<TProfile2D>(
char const*
const name,
char const*
const title,
HistType histType,
const std::vector<AxisSpec>& axes,
bool callSumw2);
422template std::shared_ptr<TProfile3D> HistogramRegistry::add<TProfile3D>(
char const*
const name,
char const*
const title,
const HistogramConfigSpec& histConfigSpec,
bool callSumw2);
423template std::shared_ptr<TProfile3D> HistogramRegistry::add<TProfile3D>(
char const*
const name,
char const*
const title,
HistType histType,
const std::vector<AxisSpec>& axes,
bool callSumw2);
424template std::shared_ptr<THn> HistogramRegistry::add<THn>(
char const*
const name,
char const*
const title,
const HistogramConfigSpec& histConfigSpec,
bool callSumw2);
425template std::shared_ptr<THn> HistogramRegistry::add<THn>(
char const*
const name,
char const*
const title,
HistType histType,
const std::vector<AxisSpec>& axes,
bool callSumw2);
426template std::shared_ptr<THnSparse> HistogramRegistry::add<THnSparse>(
char const*
const name,
char const*
const title,
const HistogramConfigSpec& histConfigSpec,
bool callSumw2);
427template std::shared_ptr<THnSparse> HistogramRegistry::add<THnSparse>(
char const*
const name,
char const*
const title,
HistType histType,
const std::vector<AxisSpec>& axes,
bool callSumw2);
428template std::shared_ptr<StepTHn> HistogramRegistry::add<StepTHn>(
char const*
const name,
char const*
const title,
const HistogramConfigSpec& histConfigSpec,
bool callSumw2);
429template 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 ITS Vertex 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.)