14#include <fmt/format.h>
22#if defined(DEBUG_STREAMER)
24o2::utils::DebugStreamer::DebugStreamer()
26 ROOT::EnableThreadSafety();
29void o2::utils::DebugStreamer::setStreamer(
const char* outFile,
const char* option,
const size_t id)
31 if (!isStreamerSet(
id)) {
32 mTreeStreamer[
id] = std::make_unique<o2::utils::TreeStreamRedirector>(fmt::format(
"{}_{}.root", outFile,
id).
data(), option);
38 setStreamer(outFile, option,
id);
39 return getStreamer(
id);
42void o2::utils::DebugStreamer::flush(
const size_t id)
44 if (isStreamerSet(
id)) {
45 mTreeStreamer[
id].reset();
49void o2::utils::DebugStreamer::flush()
51 for (
const auto& pair : mTreeStreamer) {
56bool o2::utils::DebugStreamer::checkStream(
const StreamFlags streamFlag,
const size_t samplingID,
const float weight)
58 const bool isStreamerSet = ((getStreamFlags() & streamFlag) == streamFlag);
64 const auto sampling = getSamplingTypeFrequency(streamFlag);
66 auto sampleTrack = [&]() {
67 if (samplingID == -1) {
68 LOGP(fatal,
"Sampling type sampleID not supported for stream flag {}", (
int)streamFlag);
71 static thread_local std::unordered_map<StreamFlags, std::pair<size_t, bool>> idMap;
73 if (idMap[streamFlag].
first != samplingID) {
74 idMap[streamFlag] = std::pair<size_t, bool>{samplingID, (getRandom() < sampling.second)};
76 return idMap[streamFlag].second;
81 return (getRandom() < sampling.second);
86 static tbb::concurrent_unordered_map<int, tbb::concurrent_unordered_map<size_t, bool>> refIDs;
90 auto it = refIDs[
index].find(samplingID);
96 const bool storeTrk = sampleTrack();
97 refIDs[
index][samplingID] = storeTrk;
102 return (
weight * getRandom() < sampling.second);
108float o2::utils::DebugStreamer::getRandom(
float min,
float max)
111 static thread_local std::mt19937 generator(std::random_device{}());
113 const float rnd =
distr(generator);
117int o2::utils::DebugStreamer::getIndex(
const StreamFlags streamFlag)
120 uint32_t
v = streamFlag;
122 v =
v - ((
v >> 1) & 0x55555555);
123 v = (
v & 0x33333333) + ((
v >> 2) & 0x33333333);
124 const uint32_t ind = (((
v + (
v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24);
128std::pair<o2::utils::SamplingTypes, float> o2::utils::DebugStreamer::getSamplingTypeFrequency(
const StreamFlags streamFlag)
130 const int ind =
getIndex(streamFlag);
134std::string o2::utils::DebugStreamer::getUniqueTreeName(
const char*
tree,
const size_t id)
const {
return fmt::format(
"{}_{}",
tree, getNTrees(
id)); }
136size_t o2::utils::DebugStreamer::getCPUID() {
return std::hash<std::thread::id>{}(std::this_thread::get_id()); }
140 auto it = mTreeStreamer.find(
id);
141 if (it != mTreeStreamer.end()) {
142 return (it->second).get();
148int o2::utils::DebugStreamer::getNTrees(
const size_t id)
const {
return isStreamerSet(
id) ? getStreamerPtr(
id)->
GetFile()->GetListOfKeys()->GetEntries() : -1; }
150void o2::utils::DebugStreamer::mergeTrees(
const char* inpFile,
const char* outFile,
const char* option)
152 TFile fInp(inpFile,
"READ");
153 std::unordered_map<std::string, TList>
lists;
154 for (
TObject* keyAsObj : *fInp.GetListOfKeys()) {
155 const auto key =
dynamic_cast<TKey*
>(keyAsObj);
156 TTree*
tree = (TTree*)fInp.Get(
key->GetName());
158 const int entries =
tree->GetListOfBranches()->GetEntries();
159 const std::string brName =
key->GetName();
160 const std::string nameBr = brName.substr(0, brName.find_last_of(
"_"));
164 TFile fOut(outFile,
"RECREATE");
165 for (
auto& list :
lists) {
166 auto tree = TTree::MergeTrees(&
list.second, option);
167 fOut.WriteObject(
tree,
list.first.data());
171void o2::utils::DebugStreamer::enableStream(
const StreamFlags streamFlag)
174 streamlevel = streamFlag | streamlevel;
175 setStreamFlags(streamlevel);
178void o2::utils::DebugStreamer::disableStream(
const StreamFlags streamFlag)
181 streamlevel = (~streamFlag) & streamlevel;
182 setStreamFlags(streamlevel);
#define O2ParamImpl(classname)
Definition of class for writing debug informations.
static const ParameterDebugStreamer & Instance()
GLuint GLuint GLfloat weight
bool list(IEventListener &reporter, Config const &config)
constexpr auto getIndex(const container_T &container, typename container_T::const_iterator iter) -> typename container_T::source_type
@ sampleIDGlobal
in case different streamers have access to the same IDs use this gloabl ID
@ sampleAll
use all data (default)
@ sampleID
sample every n IDs (per example track)
@ sampleWeights
perform sampling on weights, defined where the streamer is called
@ sampleRandom
sample randomly every n points
StreamFlags
struct defining the flags which can be used to check if a certain debug streamer is used
struct for setting and storing the streamer level
int sampleIDGlobal[StreamFlags::streamFlagsCount]
storage of reference streamer used for sampleIDFromOtherStreamer
float samplingFrequency[StreamFlags::streamFlagsCount]
frequency which is used for the sampling (0.1 -> 10% is written if sampling is used)
SamplingTypes samplingType[StreamFlags::streamFlagsCount]
flag to store what will be streamed
std::unique_ptr< TTree > tree((TTree *) flIn.Get(std::string(o2::base::NameConf::CTFTREENAME).c_str()))
std::uniform_int_distribution< unsigned long long > distr