Back to home page

sPhenix code displayed by LXR

 
 

    


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       // this will set the filename to the name of the manager
0093       // add the runnumber in the std 10 digit format and
0094       // end it with a .root extension
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     //  Decode the string to see if it wants a directory
0146     std::string::size_type pos = hname.find_last_of('/');
0147     std::string dirname;
0148     if (pos != std::string::npos)  // string::npos is the result if search unsuccessful
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)  // okay someone wants damn TDirectories
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   // this one did some very ugly mutilation to a const char *
0227   // using a string seems to avoid the damage
0228   h1d->SetName(histoname.c_str());
0229   Histo[hname] = h1d;
0230 
0231   // reset directory for TTree
0232   if (h1d->InheritsFrom("TTree"))
0233   {
0234     static_cast<TTree *>(h1d)->SetDirectory(nullptr); // NOLINT(cppcoreguidelines-pro-type-static-cast-downcast)
0235   }
0236 
0237   // For histograms, enforce error calculation and propagation
0238   if (h1d->InheritsFrom("TH1"))
0239   {
0240     static_cast<TH1 *>(h1d)->Sumw2();// NOLINT(cppcoreguidelines-pro-type-static-cast-downcast)
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     // loop over the map and print out the content (name and location in memory)
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 // this method figures out the last event number to be saved before rolling over
0365 // an integer div of the current event by the number of events gives the first event we can expect
0366 // in this process (this is not needed), then adding the number of events we want gives us the last event
0367 // since want ranges like 1-99999, 100,000 - 199,999 we need to subtract 1
0368 // from the calculated range.
0369 // This is just run for the first event - later we just add the number of events to the last event number
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 }