Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-16 08:17:09

0001 #pragma once
0002 
0003 #include <iostream>
0004 #include <vector>
0005 #include <string>
0006 #include <mutex>
0007 
0008 #include <JANA/JApplicationFwd.h>
0009 #include "services/log/Log_service.h"
0010 #include <JANA/Services/JGlobalRootLock.h>
0011 #include <JANA/Services/JServiceLocator.h>
0012 
0013 #include <TFile.h>
0014 
0015 /**
0016  * This Service centralizes creation of a root file for histograms
0017  */
0018 class RootFile_service : public JService {
0019 public:
0020   explicit RootFile_service(JApplication* app) : m_app(app) {}
0021   ~RootFile_service() override { CloseHistFile(); }
0022 
0023   void acquire_services(JServiceLocator* /* locayor */) override {
0024     auto log_service = m_app->GetService<Log_service>();
0025     m_log            = log_service->logger("RootFile");
0026   }
0027 
0028   /// This will return a pointer to the top-level directory of the
0029   /// common output root file for histograms. If create_if_needed
0030   /// is true and the root file has not already been created, then
0031   /// one will be created. If create_if_needed is false, the pointer
0032   /// to the existing file will be returned or nullptr if it does
0033   /// not already exist.
0034   ///
0035   /// NOTE: This should only be called by a thread already holding
0036   /// the global root lock, e.g.:
0037   ///
0038   ///    auto rootfile_service = japp->GetService<RootFile_service>();
0039   ///    auto globalRootLock = japp->GetService<JGlobalRootLock>();
0040   ///    globalRootLock->acquire_write_lock();
0041   ///    auto rootfile = rootfile_service->GetHistFile();
0042   ///    globalWriteLock->release_lock();
0043   ///
0044   /// \param create_if_needed create file if not already created
0045   /// \return
0046   TDirectory* GetHistFile(bool create_if_needed = true) {
0047 
0048     if (create_if_needed) {
0049       std::call_once(init_flag, &RootFile_service::CreateHistFile, this);
0050     }
0051     return m_histfile;
0052   }
0053 
0054   /// Close the histogram file. If no histogram file was opened,
0055   /// then this does nothing.
0056   ///
0057   /// This should generally never be called by anything other than
0058   /// the destructor so that it is
0059   /// automatically closed when the service is destructed at
0060   /// the end of processing. This is only here for use in
0061   /// execptional circumstances like the program is suffering
0062   /// a fatal crash and we want to try and save the work by
0063   /// closing the file cleanly.
0064   void CloseHistFile() {
0065     if (m_histfile) {
0066       std::string filename = m_histfile->GetName();
0067       m_histfile->Write();
0068       delete m_histfile;
0069       m_log->info("Closed user histogram file: {}", filename);
0070     }
0071     m_histfile = nullptr;
0072   }
0073 
0074 private:
0075   /// Create the output rootfile. This will be called only once
0076   /// which will happen the first time GetHistFile is called.
0077   void CreateHistFile() {
0078     // Get root file name
0079     std::string filename = "eicrecon.root";
0080     m_app->SetDefaultParameter("histsfile", filename,
0081                                "Name of root file to be created for plugin histograms/trees");
0082     if (!m_histfile) {
0083       try {
0084         m_histfile = new TFile(filename.c_str(), "RECREATE", "user histograms/trees");
0085         m_log->info("Created file: {} for user histograms", filename);
0086       } catch (std::exception& ex) {
0087         m_log->error("Problem opening root file for histograms: {}", ex.what());
0088         throw ex;
0089       }
0090     }
0091   }
0092 
0093   RootFile_service() = default;
0094 
0095   JApplication* m_app = nullptr;
0096   std::shared_ptr<spdlog::logger> m_log;
0097   TFile* m_histfile = nullptr;
0098   std::once_flag init_flag;
0099 };