diff --git a/src/mana_plugin_root_histogram.cc b/src/mana_plugin_root_histogram.cc index 58f2080..ad7b704 100644 --- a/src/mana_plugin_root_histogram.cc +++ b/src/mana_plugin_root_histogram.cc @@ -1,6 +1,11 @@ #include #include +#include +#include +#include + #include "internal/mana_lib.hpp" + extern "C" { #include "internal/rxi/log.h" @@ -11,7 +16,8 @@ using namespace mesytec::mnode; struct Context { std::unique_ptr outputFile; - std::vector> histograms; + std::vector> hitCounts; + std::vector> rawHistograms; }; MANA_DEFINE_PLUGIN_INIT(init) @@ -28,25 +34,132 @@ MANA_DEFINE_PLUGIN_SHUTDOWN(shutdown) log_debug("shutdown"); } +struct ObjectPath +{ + std::string path; + std::string objectName; + std::vector components; + + ObjectPath(const std::string &path, const std::string &sep = "\\.") + : path(path) + { + std::regex re(sep); + std::sregex_token_iterator it(path.begin(), path.end(), re, -1); + std::copy(it, std::sregex_token_iterator(), std::back_inserter(components)); + + if (!components.empty()) + { + objectName = components.back(); + components.pop_back(); + } + + spdlog::debug("ObjectPath: objectName={}, components={}", objectName, + fmt::join(components, ", ")); + } +}; + +template TDirectory *root_mkpath_cd(It begin, It end) +{ + TDirectory *result = nullptr; + for (auto it = begin; it != end; ++it) + { + result = gDirectory->mkdir(it->c_str(), "", true); + result->cd(); + } + + return result; +} + +inline std::vector> make_hitcount_histos(TDirectory *baseDir, + const nlohmann::json &jRun) +{ + std::vector> result; + + for (const auto &jEvent: jRun["events"]) + { + std::vector eventHistos; + for (const auto &jOutput: jEvent["outputs"]) + { + auto size = jOutput["size"].get(); + ObjectPath path(jOutput["name"].get()); + path.components.emplace_back("hit_counts"); + baseDir->cd(); + root_mkpath_cd(path.components.begin(), path.components.end()); + auto histoName = fmt::format("{}_hits", path.path); + auto histoTitle = fmt::format("Hit Counts {}", path.path); + auto th1 = new TH1F(histoName.c_str(), histoTitle.c_str(), size, 0.0, size); + th1->GetXaxis()->SetTitle("Index"); + th1->GetYaxis()->SetTitle("Hits"); + eventHistos.emplace_back(std::move(th1)); + } + result.emplace_back(std::move(eventHistos)); + } + + return result; +} + +inline std::vector> make_raw_histos(TDirectory *baseDir, + const nlohmann::json &jRun) +{ + std::vector> result; + + for (const auto &jEvent: jRun["events"]) + { + std::vector eventHistos; + for (const auto &jOutput: jEvent["outputs"]) + { + auto histoCount = jOutput["size"].get(); + auto bits = jOutput["bits"].get(); + auto bins = 1u << std::min(bits, 16u); + auto maxValue = std::pow(2.0, bits); + ObjectPath path(jOutput["name"].get()); + spdlog::info("path={}, bins={}, maxValue={}", path.path, bins, maxValue); + baseDir->cd(); + root_mkpath_cd(path.components.begin(), path.components.end()); + + for (size_t i = 0; i < histoCount; ++i) + { + auto histoName = fmt::format("{}_{:04d}", path.objectName, i); + auto histoTitle = fmt::format("{}[{}]", path.path, i); + auto th1 = new TH1F(histoName.c_str(), histoTitle.c_str(), bins, 0.0, maxValue); + eventHistos.emplace_back(std::move(th1)); + } + } + result.emplace_back(std::move(eventHistos)); + } + + return result; +} + +inline std::string histo_info(const std::vector> &histos) +{ + size_t histoCount = 0; + size_t histoMem = 0; + + for (size_t ei = 0; ei < histos.size(); ++ei) + { + for (size_t mi = 0; mi < histos[ei].size(); ++mi) + { + auto histo = histos[ei][mi]; + histoCount++; + histoMem += histo->GetNbinsX() * sizeof(float); + } + } + + return fmt::format("histoCount={}, histoMem={} MiB", histoCount, histoMem / (1024.0 * 1024)); +} + MANA_DEFINE_PLUGIN_BEGIN_RUN(begin_run) { log_debug("begin_run: context=%p, descriptor_json=%s", context, descriptor_json); auto jRun = nlohmann::json::parse(descriptor_json); auto ctx = reinterpret_cast(context); - ctx->histograms.clear(); + ctx->hitCounts.clear(); ctx->outputFile = std::make_unique("output.root", "RECREATE"); - for (const auto &jEvent: jRun["events"]) - { - std::vector eventHistograms; - for (const auto &jOutput: jEvent["outputs"]) - { - auto name = jOutput["name"].get(); - auto size = jOutput["size"].get(); - auto th1 = new TH1F(name.c_str(), name.c_str(), size, 0.0, size); - eventHistograms.emplace_back(std::move(th1)); - } - ctx->histograms.emplace_back(std::move(eventHistograms)); - } + ctx->hitCounts = make_hitcount_histos(ctx->outputFile.get(), jRun); + ctx->rawHistograms = make_raw_histos(ctx->outputFile.get(), jRun); + spdlog::info("hitCount histograms: {}", histo_info(ctx->hitCounts)); + spdlog::info("raw histograms: {}", histo_info(ctx->rawHistograms)); } MANA_DEFINE_PLUGIN_END_RUN(end_run) @@ -63,19 +176,25 @@ MANA_DEFINE_PLUGIN_EVENT_DATA(process_event) arrayCount, totalBytes); auto ctx = reinterpret_cast(context); - auto &eventHistograms = ctx->histograms.at(eventIndex); + auto &hitCountHistograms = ctx->hitCounts.at(eventIndex); + auto &rawHistograms = ctx->rawHistograms.at(eventIndex); + size_t rawHistoIndex = 0; for (size_t ai = 0; ai < arrayCount; ++ai) { - auto &histogram = eventHistograms.at(ai); + auto &hitCountHisto = hitCountHistograms.at(ai); auto input = mana::get_span(arrays[ai]); + for (size_t i = 0; i < input.size(); ++i) { if (!std::isnan(input[i])) { - histogram->Fill(i); + hitCountHisto->Fill(i); + rawHistograms.at(rawHistoIndex + i)->Fill(input[i]); } } + + rawHistoIndex += input.size(); } }