32#ifdef HAS_RNTUPLE_SUPPORT
33 , fEnableRNTuples(kFALSE)
39#ifdef QW_ENABLE_MAPFILE
43 TString mapfilename =
"/dev/shm/";
45 mapfilename +=
"/QwMemMapFile.map";
50 QwError <<
"Memory-mapped file " << mapfilename
55 QwMessage <<
"================== RealTime Producer Memory Map File =================" <<
QwLog::endl;
57 QwMessage <<
"======================================================================" <<
QwLog::endl;
63 TString hostname = gSystem -> HostName();
71 rootfilename += Form(
"/%s%s.%s.%d.root",
73 hostname.Data(), pid);
82 if (gSystem->AccessPathName(rootfilename.Data()) == 0) {
83 QwVerbose <<
"Removing existing temporary file before RECREATE: " << rootfilename <<
QwLog::endl;
84 gSystem->Unlink(rootfilename.Data());
90 if (gSystem->AccessPathName(rootfilename.Data()) == 0) {
92 int unlink_result = gSystem->Unlink(rootfilename.Data());
93 if (unlink_result == 0) {
108 fRootFile = TFile::Open(rootfilename.Data(),
"RECREATE",
"myfile1");
110 QwError <<
"ROOT file " << rootfilename
120 TString run_condition_name = Form(
"condition_%s", run_label.Data());
121 TList *run_cond_list = (TList*)
fRootFile -> FindObjectAny(run_condition_name);
122 if (not run_cond_list) {
160 TString rootfilename =
fRootFile->GetName();
178 err = remove( rootfilename.Data() );
192 std::map< const std::string, std::vector<QwRootTree*> >::iterator map_iter;
193 std::vector<QwRootTree*>::iterator vec_iter;
195 for (vec_iter = map_iter->second.begin(); vec_iter != map_iter->second.end(); vec_iter++) {
210 "directory of the output ROOT files");
215 "stem of the output ROOT filename");
219 (
"enable-mapfile", po::value<bool>()->default_bool_value(
false),
220 "enable output to memory-mapped file\n(likely requires circular-buffer too)");
222 (
"write-temporary-rootfiles", po::value<bool>()->default_bool_value(
true),
223 "When writing ROOT files, use the PID to create a temporary filename");
227 (
"disable-tree", po::value<std::vector<std::string>>()->composing(),
228 "disable output to tree regex");
230 (
"disable-trees", po::value<bool>()->default_bool_value(
false),
231 "disable output to all trees");
233 (
"disable-histos", po::value<bool>()->default_bool_value(
false),
234 "disable output to all histograms");
238 (
"disable-mps-tree", po::value<bool>()->default_bool_value(
false),
239 "disable helicity window output");
241 (
"disable-pair-tree", po::value<bool>()->default_bool_value(
false),
242 "disable helicity pairs output");
244 (
"disable-hel-tree", po::value<bool>()->default_bool_value(
false),
245 "disable helicity pattern output");
247 (
"disable-burst-tree", po::value<bool>()->default_bool_value(
false),
248 "disable burst tree");
250 (
"disable-slow-tree", po::value<bool>()->default_bool_value(
false),
251 "disable slow control tree");
253#ifdef HAS_RNTUPLE_SUPPORT
256 (
"enable-rntuples", po::value<bool>()->default_bool_value(
false),
257 "enable RNTuple output");
262 (
"num-mps-accepted-events", po::value<int>()->default_value(0),
263 "number of accepted consecutive MPS events");
265 (
"num-mps-discarded-events", po::value<int>()->default_value(0),
266 "number of discarded consecutive MPS events");
268 (
"num-hel-accepted-events", po::value<int>()->default_value(0),
269 "number of accepted consecutive pattern events");
271 (
"num-hel-discarded-events", po::value<int>()->default_value(0),
272 "number of discarded consecutive pattern events");
274 (
"mapfile-update-interval", po::value<int>()->default_value(-1),
275 "Events between a map file update");
278 options.
AddOptions(
"ROOT performance options")
279 (
"autoflush", po::value<int>()->default_value(0),
281 options.
AddOptions(
"ROOT performance options")
282 (
"autosave", po::value<int>()->default_value(300000000),
284 options.
AddOptions(
"ROOT performance options")
285 (
"basket-size", po::value<int>()->default_value(16000),
286 "TTree basket size");
287 options.
AddOptions(
"ROOT performance options")
288 (
"circular-buffer", po::value<int>()->default_value(0),
289 "TTree circular buffer");
290 options.
AddOptions(
"ROOT performance options")
291 (
"compression-algorithm", po::value<int>()->default_value(1),
292 "TFile compression algorithm (1=ZLIB, 2=LZMA, 4=LZ4, 5=ZSTD, default=1 ZLIB)");
293 options.
AddOptions(
"ROOT performance options")
294 (
"compression-level", po::value<int>()->default_value(1),
295 "TFile compression level (default = 1, no compression = 0)");
296 options.
AddOptions(
"ROOT performance options")
297 (
"rntuple-compression-algorithm", po::value<int>()->default_value(4),
298 "RNTuple compression algorithm (1=ZLIB, 2=LZMA, 4=LZ4, 5=ZSTD, default=4 LZ4)");
299 options.
AddOptions(
"ROOT performance options")
300 (
"rntuple-compression-level", po::value<int>()->default_value(0),
301 "RNTuple compression level (0-12, default=0 for maximum performance)");
314 if( ! fs::exists(tmppath) || ! fs::is_directory(tmppath)) {
316 <<
", does not exist. Exiting."
326#ifndef QW_ENABLE_MAPFILE
329 QwWarning <<
"QwRootFile::ProcessOptions: "
330 <<
"The 'enable-mapfile' flag is not supported by the ROOT "
331 "version with which this app is built. Disabling it."
338#ifdef HAS_RNTUPLE_SUPPORT
340 fEnableRNTuples = options.
GetValue<
bool>(
"enable-rntuples");
347 QwWarning <<
"QwRootFile::ProcessOptions: "
348 <<
"RNTuple output is not supported alongside --enable-mapfile "
349 "(TMapFile is not a TDirectory). Disabling RNTuples."
351 fEnableRNTuples =
false;
358 std::for_each(v.begin(), v.end(), [&](
const std::string& s){ this->DisableTree(s); });
382 const UInt_t kMapFileCircularDefault = 100;
384 QwWarning <<
"QwRootFile::ProcessOptions: "
385 <<
"--enable-mapfile requires a bounded TTree to avoid "
387 <<
" MiB mmap region. "
388 "Forcing --circular-buffer=" << kMapFileCircularDefault
389 <<
" (pass --circular-buffer=N to override; pass "
390 "--disable-trees to suppress tree output entirely)."
395#ifdef HAS_RNTUPLE_SUPPORT
404 if (fEnableRNTuples) {
406 QwMessage <<
"QwRootFile::ProcessOptions: "
407 <<
"--enable-rntuples is set; disabling tree output "
408 "(channels share layout state between TTree and RNTuple "
409 "writers, so the two cannot be produced in the same run)."
440 if ((ROOT_VERSION_CODE < ROOT_VERSION(5,26,00)) &&
fAutoFlush != -30000000){
442 QwWarning <<
"QwRootFile::ProcessOptions: "
443 <<
"The 'autoflush' flag is not supported by ROOT version "
466 for (
auto& tree : pair.second) {
467 if (tree && tree->GetTree()) {
468 Long64_t entries = tree->GetTree()->GetEntries();
477#ifdef HAS_RNTUPLE_SUPPORT
479 for (
auto& pair : fNTupleByName) {
480 for (
auto& ntuple : pair.second) {
481 if (ntuple && ntuple->fCurrentEvent > 0) {
489 TList* l = d->GetListOfKeys();
492 for(
int i=0; i < l->GetEntries(); ++i) {
493 const char* name = l->At(i)->GetName();
494 TObject* obj = d->FindObjectAny(name);
505 if ( TString(name).Contains(
"parameter_file") ) {
509 if ( TString(name).Contains(
"mapfile") ) {
512 if ( TString(name).Contains(
"_condition") ) {
516 if ( TString(name).Contains(
"slow") ) {
521 if (obj->IsA()->InheritsFrom(
"TDirectory" )) {
522 if (this->
HasAnyFilled( (TDirectory*)obj ))
return true;
525 if (obj->IsA()->InheritsFrom(
"TTree" )) {
526 Long64_t entries = ((TTree*) obj)->GetEntries();
527 if ( entries )
return true;
530 if (obj->IsA()->InheritsFrom(
"TH1" )) {
531 Double_t entries = ((TH1*) obj)->GetEntries();
532 if ( entries )
return true;
Int_t WriteObject(const T *obj, const char *name, Option_t *option="", Int_t bufsize=0)
Write any object to the ROOT file (only valid for TFile)