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);
67 validateHistName(histSpec.
name, histSpec.
hash);
68 const uint32_t idx = imask(histSpec.
hash);
69 for (
auto i = 0u;
i < MAX_REGISTRY_SIZE; ++
i) {
71 std::visit([&](
const auto& sharedPtr) { rawPtr = sharedPtr.get(); }, mRegistryValue[imask(idx +
i)]);
73 registerName(histSpec.
name);
74 mRegistryKey[imask(idx +
i)] = histSpec.
hash;
77 return mRegistryValue[imask(idx +
i)];
80 LOGF(fatal, R
"(Internal array of HistogramRegistry "%s" is full.)", mName);
85void HistogramRegistry::validateHistName(
const std::string&
name,
const uint32_t hash)
88 if (mRegisteredNames.size() == MAX_REGISTRY_SIZE) {
89 LOGF(fatal, R
"(HistogramRegistry "%s" is full! It can hold only %d histograms.)", mName, MAX_REGISTRY_SIZE);
93 auto it = std::find(mRegistryKey.begin(), mRegistryKey.end(), hash);
94 if (it != mRegistryKey.end()) {
95 auto idx = it - mRegistryKey.begin();
96 std::string collidingName{};
97 std::visit([&](
const auto& hist) { collidingName = hist->GetName(); }, mRegistryValue[
idx]);
98 LOGF(fatal, R
"(Hash collision in HistogramRegistry "%s"! Please rename histogram "%s" or "%s".)", mName, name, collidingName);
102 if (!std::regex_match(
name, std::regex(
"([a-zA-Z0-9])(([\\/_-])?[a-zA-Z0-9])*"))) {
103 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);
109 return insert(histSpec);
114 return insert({
name, title, histConfigSpec, callSumw2});
119 return insert({
name, title, {histType, axes}, callSumw2});
124 return add(
name.c_str(), title, histType, axes, callSumw2);
130 auto doInsertClone = [&](
const auto& sharedPtr) {
131 if (!sharedPtr.get()) {
134 std::string sourceName{((TNamed*)sharedPtr.get())->GetName()};
136 if (sourceName.rfind(
source, 0) == 0) {
138 if (sourceName.size() !=
source.size() && (
source.back() !=
'/' ||
target.back() !=
'/')) {
142 if (sourceName.size() ==
source.size() &&
target.back() ==
'/') {
143 LOGF(fatal,
"Cannot turn histogram into folder!");
145 std::string targetName{
target};
146 targetName += sourceName.substr(sourceName.find(
source) +
source.size());
147 insertClone(targetName.data(), sharedPtr);
151 for (
auto& histVariant : mRegistryValue) {
152 std::visit(doInsertClone, histVariant);
160 auto iter = mRegistryKey.begin();
161 while ((iter = std::find(iter, mRegistryKey.end(), histName.hash)) != mRegistryKey.end()) {
162 const char* curName =
nullptr;
163 std::visit([&](
auto&& hist) {
if(hist) { curName = hist->GetName(); } }, mRegistryValue[iter - mRegistryKey.begin()]);
165 if (strcmp(curName, histName.str) == 0) {
176 std::visit([&fillFraction, &
size](
auto&& hist) {
size =
HistFiller::getSize(hist, fillFraction); }, mRegistryValue[getHistIndex(histName)]);
184 for (
auto j = 0u;
j < MAX_REGISTRY_SIZE; ++
j) {
192 for (
auto&
value : mRegistryValue) {
193 std::visit([](
auto&& hist) { hist.reset(); },
value);
200 std::vector<double> fillFractions{0.1, 0.25, 0.5};
201 std::vector<double> totalSizes(fillFractions.size());
204 bool containsSparseHist{};
205 auto printHistInfo = [&](
auto&& hist) {
207 using T = std::decay_t<
decltype(*hist)>;
209 if (hist->InheritsFrom(THnSparse::Class())) {
211 containsSparseHist =
true;
214 std::vector<double>
sizes;
215 std::string sizeInfo{};
217 std::transform(std::begin(fillFractions), std::end(fillFractions), std::back_inserter(
sizes), [&hist](
auto& fraction) {
return HistFiller::getSize(hist, fraction); });
218 for (
int i = 0;
i < fillFractions.size(); ++
i) {
219 sizeInfo += fmt::format(
"{:.2f} kB ({:.0f} %)",
sizes[
i] * 1024, fillFractions[
i] * 100);
220 if (
i != fillFractions.size() - 1) {
226 sizes.resize(fillFractions.size(),
size);
227 sizeInfo = fmt::format(
"{:.2f} kB",
sizes[0] * 1024);
229 std::transform(totalSizes.begin(), totalSizes.end(),
sizes.begin(), totalSizes.begin(), std::plus<double>());
230 LOGF(info,
"Hist %03d: %-35s %-19s [%s]", nHistos, hist->GetName(), hist->IsA()->GetName(), sizeInfo);
232 if (showAxisDetails) {
234 if constexpr (std::is_base_of_v<THnBase, T>) {
235 nDim = hist->GetNdimensions();
236 }
else if constexpr (std::is_base_of_v<TH1, T>) {
237 nDim = hist->GetDimension();
239 TAxis* axis{
nullptr};
240 for (
int d = 0; d < nDim; ++d) {
241 if constexpr (std::is_base_of_v<THnBase, T> || std::is_base_of_v<StepTHn, T>) {
242 axis = hist->GetAxis(d);
245 axis = hist->GetXaxis();
247 axis = hist->GetYaxis();
249 axis = hist->GetZaxis();
252 LOGF(info,
"- Axis %d: %-20s (%d bins)", d, axis->GetTitle(), axis->GetNbins());
258 std::string titleString{
"======================== HistogramRegistry ========================"};
260 LOGF(info,
"%s", titleString);
261 LOGF(info,
"%s\"%s\"", std::string((
int)(0.5 * titleString.size() - (1 + 0.5 * mName.size())),
' '), mName);
262 for (
auto& curHistName : mRegisteredNames) {
263 std::visit(printHistInfo, mRegistryValue[getHistIndex(HistName{curHistName.data()})]);
265 std::string totalSizeInfo{};
266 if (containsSparseHist) {
267 for (
int i = 0;
i < totalSizes.size(); ++
i) {
268 totalSizeInfo += fmt::format(
"{:.2f} MB ({:.0f} %)", totalSizes[
i], fillFractions[
i] * 100);
269 if (
i != totalSizes.size() - 1) {
270 totalSizeInfo +=
", ";
274 totalSizeInfo = fmt::format(
"{:.2f} MB", totalSizes[0]);
276 LOGF(info,
"%s", std::string(titleString.size(),
'='), titleString);
277 LOGF(info,
"Total: %d histograms, ca. %s", nHistos, totalSizeInfo);
279 LOGF(info,
"Due to index collisions, histograms were shifted by %d registry slots in total.",
lookup);
281 LOGF(info,
"%s", std::string(titleString.size(),
'='), titleString);
288 TList*
list =
new TList();
289 list->SetName(mName.data());
292 auto caseInsensitiveCompare = [](
const std::string&
s1,
const std::string& s2) {
293 return std::lexicographical_compare(
s1.begin(),
s1.end(), s2.begin(), s2.end(),
294 [](
char c1,
char c2) { return std::tolower(static_cast<unsigned char>(c1)) < std::tolower(static_cast<unsigned char>(c2)); });
296 std::sort(mRegisteredNames.begin(), mRegisteredNames.end(), caseInsensitiveCompare);
299 for (
auto& curHistName : mRegisteredNames) {
300 TNamed* rawPtr =
nullptr;
301 std::visit([&](
const auto& sharedPtr) { rawPtr = (TNamed*)sharedPtr.get(); }, mRegistryValue[getHistIndex(HistName{curHistName.data()})]);
303 std::deque<std::string>
path = splitPath(rawPtr->GetName());
306 TList* targetList{getSubList(
list,
path)};
308 rawPtr->SetName(
name.data());
309 targetList->Add(rawPtr);
311 LOGF(fatal,
"Specified subfolder could not be created.");
317 std::function<
void(TList*)> moveListsToTop;
318 moveListsToTop = [&](TList*
list) {
320 TNamed* subList =
nullptr;
321 std::vector<TObject*> subLists;
322 while ((subList = (TNamed*)next())) {
323 if (subList->InheritsFrom(TList::Class())) {
324 subLists.push_back(subList);
325 moveListsToTop((TList*)subList);
328 std::reverse(subLists.begin(), subLists.end());
329 for (
auto curList : subLists) {
330 list->Remove(curList);
331 list->AddFirst(curList);
334 moveListsToTop(
list);
337 if (mCreateRegistryDir) {
339 list->AddLast(
new TNamed(
"createFolder",
""));
345TList* HistogramRegistry::getSubList(TList*
list, std::deque<std::string>&
path)
350 TList* targetList{
nullptr};
351 std::string nextList =
path[0];
353 if (
auto subList = (TList*)
list->FindObject(nextList.data())) {
354 if (subList->InheritsFrom(TList::Class())) {
355 targetList = getSubList((TList*)subList,
path);
360 subList =
new TList();
361 subList->SetName(nextList.data());
363 targetList = getSubList(subList,
path);
369std::deque<std::string> HistogramRegistry::splitPath(
const std::string& pathAndNameUser)
371 std::istringstream pathAndNameStream(pathAndNameUser);
372 std::deque<std::string> pathAndName;
374 while (std::getline(pathAndNameStream, curDir,
'/')) {
375 pathAndName.push_back(curDir);
381void HistogramRegistry::registerName(
const std::string&
name)
383 if (
name.empty() ||
name.back() ==
'/') {
384 LOGF(fatal,
"Invalid name for a histogram.");
386 std::deque<std::string>
path = splitPath(
name);
387 std::string cumulativeName{};
389 for (
auto& step :
path) {
391 LOGF(fatal, R
"(Found empty group name in path for histogram "%s".)", name);
393 cumulativeName += step;
394 for (
auto& curName : mRegisteredNames) {
396 if (cumulativeName == curName) {
397 LOGF(fatal, R
"(Histogram name "%s" is not compatible with existing names.)", name);
401 if (curName.rfind(cumulativeName, 0) == 0 && curName.size() > cumulativeName.size() && curName.at(cumulativeName.size()) ==
'/') {
402 LOGF(fatal, R
"(Histogram name "%s" is not compatible with existing names.)", name);
407 cumulativeName += "/";
409 mRegisteredNames.push_back(
name);
412void HistFiller::badHistogramFill(
char const*
name)
414 LOGF(fatal,
"The number of arguments in fill function called for histogram %s is incompatible with histogram dimensions.",
name);
418HistPtr HistogramRegistry::insertClone(
const HistName& histName,
const std::shared_ptr<T> originalHist)
420 validateHistName(histName.str, histName.hash);
421 for (
auto i = 0u;
i < MAX_REGISTRY_SIZE; ++
i) {
423 std::visit([&](
const auto& sharedPtr) { rawPtr = sharedPtr.get(); }, mRegistryValue[imask(histName.idx +
i)]);
425 registerName(histName.str);
426 mRegistryKey[imask(histName.idx +
i)] = histName.hash;
427 mRegistryValue[imask(histName.idx +
i)] = std::shared_ptr<T>(
static_cast<T*
>(originalHist->Clone(histName.str)));
429 return mRegistryValue[imask(histName.idx +
i)];
432 LOGF(fatal, R
"(Internal array of HistogramRegistry "%s" is full.)", mName);
436template HistPtr HistogramRegistry::insertClone(
const HistName&,
const std::shared_ptr<TH1>);
437template HistPtr HistogramRegistry::insertClone(
const HistName&,
const std::shared_ptr<TH2>);
438template HistPtr HistogramRegistry::insertClone(
const HistName&,
const std::shared_ptr<TH3>);
439template HistPtr HistogramRegistry::insertClone(
const HistName&,
const std::shared_ptr<TProfile>);
440template HistPtr HistogramRegistry::insertClone(
const HistName&,
const std::shared_ptr<TProfile2D>);
441template HistPtr HistogramRegistry::insertClone(
const HistName&,
const std::shared_ptr<TProfile3D>);
442template HistPtr HistogramRegistry::insertClone(
const HistName&,
const std::shared_ptr<THnSparse>);
443template HistPtr HistogramRegistry::insertClone(
const HistName&,
const std::shared_ptr<THn>);
444template HistPtr HistogramRegistry::insertClone(
const HistName&,
const std::shared_ptr<StepTHn>);
449 auto histVariant =
add(
name, title, histConfigSpec, callSumw2);
450 if (
auto histPtr = std::get_if<std::shared_ptr<T>>(&histVariant)) {
453 throw runtime_error_f(R
"(Histogram type specified in add<>("%s") does not match the actual type of the histogram!)", name);
460 auto histVariant =
add(
name, title, histType, axes, callSumw2);
461 if (
auto histPtr = std::get_if<std::shared_ptr<T>>(&histVariant)) {
464 throw runtime_error_f(R
"(Histogram type specified in add<>("%s") does not match the actual type of the histogram!)", name);
468template std::shared_ptr<TH1> HistogramRegistry::add<TH1>(
char const*
const name,
char const*
const title,
const HistogramConfigSpec& histConfigSpec,
bool callSumw2);
469template std::shared_ptr<TH1> HistogramRegistry::add<TH1>(
char const*
const name,
char const*
const title,
HistType histType,
const std::vector<AxisSpec>& axes,
bool callSumw2);
470template std::shared_ptr<TH2> HistogramRegistry::add<TH2>(
char const*
const name,
char const*
const title,
const HistogramConfigSpec& histConfigSpec,
bool callSumw2);
471template std::shared_ptr<TH2> HistogramRegistry::add<TH2>(
char const*
const name,
char const*
const title,
HistType histType,
const std::vector<AxisSpec>& axes,
bool callSumw2);
472template std::shared_ptr<TH3> HistogramRegistry::add<TH3>(
char const*
const name,
char const*
const title,
const HistogramConfigSpec& histConfigSpec,
bool callSumw2);
473template std::shared_ptr<TH3> HistogramRegistry::add<TH3>(
char const*
const name,
char const*
const title,
HistType histType,
const std::vector<AxisSpec>& axes,
bool callSumw2);
474template std::shared_ptr<TProfile> HistogramRegistry::add<TProfile>(
char const*
const name,
char const*
const title,
const HistogramConfigSpec& histConfigSpec,
bool callSumw2);
475template std::shared_ptr<TProfile> HistogramRegistry::add<TProfile>(
char const*
const name,
char const*
const title,
HistType histType,
const std::vector<AxisSpec>& axes,
bool callSumw2);
476template std::shared_ptr<TProfile2D> HistogramRegistry::add<TProfile2D>(
char const*
const name,
char const*
const title,
const HistogramConfigSpec& histConfigSpec,
bool callSumw2);
477template std::shared_ptr<TProfile2D> HistogramRegistry::add<TProfile2D>(
char const*
const name,
char const*
const title,
HistType histType,
const std::vector<AxisSpec>& axes,
bool callSumw2);
478template std::shared_ptr<TProfile3D> HistogramRegistry::add<TProfile3D>(
char const*
const name,
char const*
const title,
const HistogramConfigSpec& histConfigSpec,
bool callSumw2);
479template std::shared_ptr<TProfile3D> HistogramRegistry::add<TProfile3D>(
char const*
const name,
char const*
const title,
HistType histType,
const std::vector<AxisSpec>& axes,
bool callSumw2);
480template std::shared_ptr<THn> HistogramRegistry::add<THn>(
char const*
const name,
char const*
const title,
const HistogramConfigSpec& histConfigSpec,
bool callSumw2);
481template std::shared_ptr<THn> HistogramRegistry::add<THn>(
char const*
const name,
char const*
const title,
HistType histType,
const std::vector<AxisSpec>& axes,
bool callSumw2);
482template std::shared_ptr<THnSparse> HistogramRegistry::add<THnSparse>(
char const*
const name,
char const*
const title,
const HistogramConfigSpec& histConfigSpec,
bool callSumw2);
483template std::shared_ptr<THnSparse> HistogramRegistry::add<THnSparse>(
char const*
const name,
char const*
const title,
HistType histType,
const std::vector<AxisSpec>& axes,
bool callSumw2);
484template std::shared_ptr<StepTHn> HistogramRegistry::add<StepTHn>(
char const*
const name,
char const*
const title,
const HistogramConfigSpec& histConfigSpec,
bool callSumw2);
485template std::shared_ptr<StepTHn> HistogramRegistry::add<StepTHn>(
char const*
const name,
char const*
const title,
HistType histType,
const std::vector<AxisSpec>& axes,
bool callSumw2);
bool const GPUTPCGMMerger::trackCluster * c1
bool const GPUTPCGMMerger::trackCluster const clcomparestruct * c2
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)
TList * getListOfHistograms()
returns the list of histograms, properly sorted for writing.
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)
OutputRef ref(uint16_t idx, uint16_t pipelineSize)
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
typedef void(APIENTRYP PFNGLCULLFACEPROC)(GLenum mode)
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.)