File indexing completed on 2025-12-17 09:19:42
0001 #include "Fun4AllHistoManager.h"
0002
0003 #include "Fun4AllOutputManager.h"
0004 #include "TDirectoryHelper.h"
0005
0006 #include <phool/phool.h>
0007 #include <phool/recoConsts.h>
0008
0009 #include <TFile.h>
0010 #include <TH1.h>
0011 #include <THnBase.h>
0012 #include <TNamed.h>
0013 #include <TSystem.h>
0014 #include <TTree.h>
0015
0016 #include <filesystem>
0017 #include <format>
0018 #include <iomanip>
0019 #include <iostream>
0020 #include <sstream>
0021 #include <utility> // for pair
0022
0023 Fun4AllHistoManager::Fun4AllHistoManager(const std::string &name)
0024 : Fun4AllBase(name)
0025 {
0026 return;
0027 }
0028
0029 Fun4AllHistoManager::~Fun4AllHistoManager()
0030 {
0031 while (Histo.begin() != Histo.end())
0032 {
0033 if (Verbosity() > 0)
0034 {
0035 std::cout << PHWHERE << "deleting " << Histo.begin()->first
0036 << ", histo name " << Histo.begin()->second->GetName()
0037 << std::endl;
0038 }
0039 delete Histo.begin()->second;
0040 Histo.erase(Histo.begin());
0041 }
0042 return;
0043 }
0044
0045 int Fun4AllHistoManager::RunAfterClosing()
0046 {
0047 unsigned int iret = 0;
0048
0049 if (!m_RunAfterClosingScript.empty())
0050 {
0051 if (!std::filesystem::exists(m_RunAfterClosingScript))
0052 {
0053 std::cout << PHWHERE << "RunAfterClosing() closing script " << m_RunAfterClosingScript << " not found" << std::endl;
0054 return -1;
0055 }
0056 if (!((std::filesystem::status(m_RunAfterClosingScript).permissions() & std::filesystem::perms::owner_exec) == std::filesystem::perms::owner_exec))
0057 {
0058 std::cout << PHWHERE << "RunAfterClosing() closing script " << m_RunAfterClosingScript << " is not owner executable" << std::endl;
0059 return -1;
0060 }
0061 std::string fullcmd = m_RunAfterClosingScript + " " + m_LastClosedFileName + " " + m_ClosingArgs;
0062 if (Verbosity() > 1)
0063 {
0064 std::cout << PHWHERE << " running " << fullcmd << std::endl;
0065 }
0066 iret = gSystem->Exec(fullcmd.c_str());
0067 }
0068 if (iret)
0069 {
0070 iret = iret >> 8U;
0071 }
0072 return iret;
0073 }
0074
0075 int Fun4AllHistoManager::dumpHistos(const std::string &filename, const std::string &openmode)
0076 {
0077 int iret = 0;
0078 if (!filename.empty())
0079 {
0080 m_outfilename = filename;
0081 }
0082 else
0083 {
0084 if (m_outfilename.empty())
0085 {
0086 recoConsts *rc = recoConsts::instance();
0087 int runnumber = 0;
0088 if (rc->FlagExist("RUNNUMBER"))
0089 {
0090 runnumber = rc->get_IntFlag("RUNNUMBER");
0091 }
0092
0093
0094
0095 m_outfilename = Name() + std::format("-{:08}.root", runnumber);
0096 }
0097 }
0098 std::string theoutfile = m_outfilename;
0099 if (ApplyFileRule())
0100 {
0101
0102 std::filesystem::path p = m_outfilename;
0103
0104 recoConsts *rc = recoConsts::instance();
0105 int runnumber = 0;
0106 if (rc->FlagExist("RUNNUMBER"))
0107 {
0108 runnumber = rc->get_IntFlag("RUNNUMBER");
0109 }
0110 std::string fullpath = ".";
0111 if (p.has_parent_path())
0112 {
0113 fullpath = p.parent_path();
0114 }
0115 std::string runseg = std::format("-{:08}-{:05}",runnumber,m_CurrentSegment);
0116 theoutfile = fullpath + std::string("/") + std::string(p.stem()) + runseg + std::string(p.extension());
0117 m_CurrentSegment++;
0118 }
0119 m_LastClosedFileName = theoutfile;
0120 std::filesystem::path pout = theoutfile;
0121 theoutfile = theoutfile + std::string("?reproducible=") + std::string(pout.filename());
0122 std::cout << "Fun4AllHistoManager::dump() Writing root file: " << m_LastClosedFileName << std::endl;
0123
0124 const int compress = 505;
0125 std::string creator = "Created by " + Name();
0126 TFile hfile(theoutfile.c_str(), openmode.c_str(), creator.c_str());
0127 if (!hfile.IsOpen())
0128 {
0129 std::cout << PHWHERE << " Could not open output file" << theoutfile.c_str() << std::endl;
0130 return -1;
0131 }
0132 hfile.SetCompressionSettings(compress);
0133 std::map<const std::string, TNamed *>::const_iterator hiter;
0134 for (hiter = Histo.begin(); hiter != Histo.end(); ++hiter)
0135 {
0136 const std::string &hname = hiter->first;
0137 const TNamed *hptr = hiter->second;
0138 if (Verbosity() > 0)
0139 {
0140 std::cout << PHWHERE << " Saving histo "
0141 << hname
0142 << std::endl;
0143 }
0144
0145
0146 std::string::size_type pos = hname.find_last_of('/');
0147 std::string dirname;
0148 if (pos != std::string::npos)
0149 {
0150 dirname = hname.substr(0, pos);
0151 }
0152 else
0153 {
0154 dirname = "";
0155 }
0156
0157 if (Verbosity())
0158 {
0159 std::cout << " Histogram named " << hptr->GetName();
0160 std::cout << " key " << hname;
0161 if (!dirname.empty())
0162 {
0163 std::cout << " being saved to directory " << dirname;
0164 }
0165 std::cout << std::endl;
0166 }
0167
0168 if (!dirname.empty())
0169 {
0170 TDirectoryHelper::mkdir(&hfile, dirname);
0171 hfile.cd(dirname.c_str());
0172 }
0173
0174 if (hptr)
0175 {
0176 int byteswritten = hptr->Write();
0177 if (!byteswritten)
0178 {
0179 std::cout << PHWHERE << "Error saving histogram "
0180 << hptr->GetName()
0181 << std::endl;
0182 iret = -2;
0183 }
0184 }
0185 else
0186 {
0187 std::cout << PHWHERE << "dumpHistos : histogram "
0188 << hname << " is a null pointer! Won't be saved."
0189 << std::endl;
0190 }
0191 }
0192 hfile.Close();
0193 RunAfterClosing();
0194 return iret;
0195 }
0196
0197 bool Fun4AllHistoManager::registerHisto(TNamed *h1d, const int replace)
0198 {
0199 return registerHisto(h1d->GetName(), h1d, replace);
0200 }
0201
0202 bool Fun4AllHistoManager::registerHisto(const std::string &hname, TNamed *h1d, const int replace)
0203 {
0204 std::map<const std::string, TNamed *>::const_iterator histoiter = Histo.find(hname);
0205 if (histoiter != Histo.end() && replace == 0)
0206 {
0207 std::cout << "Histogram " << hname << " already registered, I won't overwrite it" << std::endl;
0208 std::cout << "Use a different name and try again" << std::endl;
0209 return false;
0210 }
0211
0212 std::string::size_type pos = hname.find_last_of('/');
0213 std::string histoname = hname;
0214 if (pos != std::string::npos)
0215 {
0216 histoname = hname.substr(pos + 1);
0217 }
0218 if (Verbosity() > 1)
0219 {
0220 if (histoname != h1d->GetName())
0221 {
0222 std::cout << PHWHERE << "Histogram " << h1d->GetName()
0223 << " at " << h1d << " renamed to " << histoname << std::endl;
0224 }
0225 }
0226
0227
0228 h1d->SetName(histoname.c_str());
0229 Histo[hname] = h1d;
0230
0231
0232 if (h1d->InheritsFrom("TTree"))
0233 {
0234 static_cast<TTree *>(h1d)->SetDirectory(nullptr);
0235 }
0236
0237
0238 if (h1d->InheritsFrom("TH1"))
0239 {
0240 static_cast<TH1 *>(h1d)->Sumw2();
0241 }
0242
0243 return true;
0244 }
0245
0246 int Fun4AllHistoManager::isHistoRegistered(const std::string &name) const
0247 {
0248 std::map<const std::string, TNamed *>::const_iterator histoiter = Histo.find(name);
0249 if (histoiter != Histo.end())
0250 {
0251 return 1;
0252 }
0253 return 0;
0254 }
0255
0256 TNamed *
0257 Fun4AllHistoManager::getHisto(const unsigned int ihisto) const
0258 {
0259 std::map<const std::string, TNamed *>::const_iterator histoiter = Histo.begin();
0260 unsigned int size = Histo.size();
0261 if (Verbosity() > 3)
0262 {
0263 std::cout << "Map contains " << size << " Elements" << std::endl;
0264 }
0265 if (ihisto < size)
0266 {
0267 for (unsigned int i = 0; i < ihisto; i++)
0268 {
0269 ++histoiter;
0270 }
0271 return histoiter->second;
0272 }
0273
0274 std::cout << "Fun4AllHistoManager::getHisto: ERROR Invalid histogram number: "
0275 << ihisto << ", maximum number is " << size << std::endl;
0276
0277 return nullptr;
0278 }
0279
0280 std::string
0281 Fun4AllHistoManager::getHistoName(const unsigned int ihisto) const
0282 {
0283 std::map<const std::string, TNamed *>::const_iterator histoiter = Histo.begin();
0284 unsigned int size = Histo.size();
0285 if (Verbosity() > 3)
0286 {
0287 std::cout << "Map contains " << size << " Elements" << std::endl;
0288 }
0289 if (ihisto < size)
0290 {
0291 for (unsigned int i = 0; i < ihisto; i++)
0292 {
0293 ++histoiter;
0294 }
0295 return histoiter->first;
0296 }
0297
0298 std::cout << "Fun4AllHistoManager::getHisto: ERROR Invalid histogram number: "
0299 << ihisto << ", maximum number is " << size << std::endl;
0300
0301 return "";
0302 }
0303
0304 TNamed *
0305 Fun4AllHistoManager::getHisto(const std::string &hname) const
0306 {
0307 std::map<const std::string, TNamed *>::const_iterator histoiter = Histo.find(hname);
0308 if (histoiter != Histo.end())
0309 {
0310 return histoiter->second;
0311 }
0312 std::cout << "Fun4AllHistoManager::getHisto: ERROR Unknown Histogram " << hname
0313 << ", The following are implemented: " << std::endl;
0314 Print("ALL");
0315 return nullptr;
0316 }
0317
0318 void Fun4AllHistoManager::Print(const std::string &what) const
0319 {
0320 if (what == "ALL" || what == "HISTOS")
0321 {
0322
0323 std::cout << "--------------------------------------" << std::endl
0324 << std::endl;
0325 std::cout << "List of Histos in Fun4AllHistoManager "
0326 << Name() << ":" << std::endl;
0327
0328 for (const auto &hiter : Histo)
0329 {
0330 std::cout << hiter.first << " is " << hiter.second << std::endl;
0331 }
0332 std::cout << std::endl;
0333 }
0334 if (what == "ALL" || what == "CONFIG")
0335 {
0336 std::cout << Name() << std::endl;
0337 std::cout << "Output Filename: " << m_outfilename << std::endl;
0338 std::cout << "use filerule: " << m_UseFileRuleFlag << std::endl;
0339 std::cout << "Event Rollover at " << GetEventNumberRollover() << std::endl;
0340 std::cout << "current last event " << LastEventNumber() << std::endl;
0341 std::cout << "current segment number: " << m_CurrentSegment << std::endl;
0342 }
0343 return;
0344 }
0345
0346 void Fun4AllHistoManager::Reset()
0347 {
0348 std::map<const std::string, TNamed *>::const_iterator hiter;
0349 for (hiter = Histo.begin(); hiter != Histo.end(); ++hiter)
0350 {
0351 TNamed *h = hiter->second;
0352 if (h->InheritsFrom("TH1"))
0353 {
0354 (dynamic_cast<TH1 *>(h))->Reset();
0355 }
0356 else if (h->InheritsFrom("THnBase"))
0357 {
0358 (dynamic_cast<THnBase *>(h))->Reset();
0359 }
0360 }
0361 return;
0362 }
0363
0364
0365
0366
0367
0368
0369
0370 void Fun4AllHistoManager::InitializeLastEvent(int eventnumber)
0371 {
0372 if (GetEventNumberRollover() == 0 || m_LastEventInitializedFlag || eventnumber < 0)
0373 {
0374 return;
0375 }
0376 m_LastEventInitializedFlag = true;
0377 unsigned int firstevent = eventnumber / GetEventNumberRollover();
0378 unsigned int newlastevent = firstevent * GetEventNumberRollover() + GetEventNumberRollover() - 1;
0379 if (Verbosity() > 1)
0380 {
0381 std::cout << "event number: " << eventnumber << ", rollover: " << GetEventNumberRollover() << ", multiple: "
0382 << eventnumber / GetEventNumberRollover() << ", new last event number "
0383 << newlastevent << std::endl;
0384 }
0385 SetLastEventNumber(firstevent * GetEventNumberRollover() + GetEventNumberRollover() - 1);
0386 return;
0387 }
0388
0389 void Fun4AllHistoManager::CopyRolloverSetting(const Fun4AllOutputManager *outman)
0390 {
0391 SetEventNumberRollover(outman->GetEventNumberRollover());
0392 UseFileRule(outman->ApplyFileRule());
0393 StartSegment(outman->Segment());
0394 SetClosingScript(outman->GetClosingScript());
0395 SetClosingScriptArgs(outman->GetClosingScriptArgs());
0396 }
0397
0398 bool Fun4AllHistoManager::isEmpty() const
0399 {
0400 bool thisempty = true;
0401 for (const auto &hiter : Histo)
0402 {
0403 TH1 *h1 = dynamic_cast<TH1 *> (hiter.second);
0404 if (h1)
0405 {
0406 if (h1->GetEntries() > 0 || h1->Integral() > 0)
0407 {
0408 std::cout << hiter.first << " has " << h1->GetEntries() << " entries"
0409 << " with integral " << h1->Integral() << std::endl;
0410 thisempty = false;
0411 break;
0412 }
0413 }
0414 else
0415 {
0416 THnBase *hn = dynamic_cast<THnBase *> (hiter.second);
0417 if (hn)
0418 {
0419 if (hn->GetEntries() > 0)
0420 {
0421 std::cout << hiter.first << " has " << hn->GetEntries() << " entries" << std::endl;
0422 thisempty = false;
0423 break;
0424 }
0425 }
0426 else
0427 {
0428 std::cout << hiter.first << " is not a TH1 or THnBase" << std::endl;
0429 }
0430 }
0431 }
0432 return thisempty;
0433 }