Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-06 08:34:53

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. The root lock will already be held if
0037   /// calling from JEventProcessorSequentialRoot. For pretty much
0038   /// everyplace else, the lock should be acquired manually.
0039   /// e.g.
0040   ///
0041   ///    auto rootfile_service = japp->GetService<RootFile_service>();
0042   ///    auto globalRootLock = japp->GetService<JGlobalRootLock>();
0043   ///    globalRootLock->acquire_write_lock();
0044   ///    auto rootfile = rootfile_service->GetHistFile();
0045   ///    globalWriteLock->release_lock();
0046   ///
0047   /// \param create_if_needed create file if not already created
0048   /// \return
0049   TDirectory* GetHistFile(bool create_if_needed = true) {
0050 
0051     if (create_if_needed) {
0052       std::call_once(init_flag, &RootFile_service::CreateHistFile, this);
0053     }
0054     return m_histfile;
0055   }
0056 
0057   /// Close the histogram file. If no histogram file was opened,
0058   /// then this does nothing.
0059   ///
0060   /// This should generally never be called by anything other than
0061   /// the destructor so that it is
0062   /// automatically closed when the service is destructed at
0063   /// the end of processing. This is only here for use in
0064   /// execptional circumstances like the program is suffering
0065   /// a fatal crash and we want to try and save the work by
0066   /// closing the file cleanly.
0067   void CloseHistFile() {
0068     if (m_histfile) {
0069       std::string filename = m_histfile->GetName();
0070       m_histfile->Write();
0071       delete m_histfile;
0072       m_log->info("Closed user histogram file: {}", filename);
0073     }
0074     m_histfile = nullptr;
0075   }
0076 
0077 private:
0078   /// Create the output rootfile. This will be called only once
0079   /// which will happen the first time GetHistFile is called.
0080   void CreateHistFile() {
0081     // Get root file name
0082     std::string filename = "eicrecon.root";
0083     m_app->SetDefaultParameter("histsfile", filename,
0084                                "Name of root file to be created for plugin histograms/trees");
0085     if (!m_histfile) {
0086       try {
0087         m_histfile = new TFile(filename.c_str(), "RECREATE", "user histograms/trees");
0088         m_log->info("Created file: {} for user histograms", filename);
0089       } catch (std::exception& ex) {
0090         m_log->error("Problem opening root file for histograms: {}", ex.what());
0091         throw ex;
0092       }
0093     }
0094   }
0095 
0096   RootFile_service() = default;
0097 
0098   JApplication* m_app = nullptr;
0099   std::shared_ptr<spdlog::logger> m_log;
0100   TFile* m_histfile = nullptr;
0101   std::once_flag init_flag;
0102 };