From 41b8e428bd376cc1ceff54dcdb0ec69794cf6ca5 Mon Sep 17 00:00:00 2001
From: Peter Onyisi <ponyisi@utexas.edu>
Date: Sat, 21 Dec 2019 15:28:10 +0100
Subject: [PATCH 1/2] Fix typo (EXPRES -> EXPRESS)

---
 .../src/HistogramFiller/HistogramFactory.cxx                  | 4 ++--
 .../AthenaMonitoringKernel/test/HistogramFactoryTestSuite.cxx | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/Control/AthenaMonitoringKernel/src/HistogramFiller/HistogramFactory.cxx b/Control/AthenaMonitoringKernel/src/HistogramFiller/HistogramFactory.cxx
index 0e63fe174e3c..0f434c51af82 100644
--- a/Control/AthenaMonitoringKernel/src/HistogramFiller/HistogramFactory.cxx
+++ b/Control/AthenaMonitoringKernel/src/HistogramFiller/HistogramFactory.cxx
@@ -187,8 +187,8 @@ void HistogramFactory::setLabels(TH1* hist, const std::vector<std::string>& labe
   }
 }
 
-std::string HistogramFactory::getFullName(const HistogramDef& def) {
-  const static std::set<std::string> online( { "EXPERT", "SHIFT", "DEBUG", "RUNSTAT", "EXPRES" } );
+std::string HistogramFactory::getFullName(const HistogramDef& def) const {
+  const static std::set<std::string> online( { "EXPERT", "SHIFT", "DEBUG", "RUNSTAT", "EXPRESS" } );
   
   std::string path;
   if ( online.count( def.path)!=0 ) {
diff --git a/Control/AthenaMonitoringKernel/test/HistogramFactoryTestSuite.cxx b/Control/AthenaMonitoringKernel/test/HistogramFactoryTestSuite.cxx
index b22fff601563..34ffeae9733f 100644
--- a/Control/AthenaMonitoringKernel/test/HistogramFactoryTestSuite.cxx
+++ b/Control/AthenaMonitoringKernel/test/HistogramFactoryTestSuite.cxx
@@ -138,7 +138,7 @@ class HistogramFactoryTestSuite {
         make_tuple("SHIFT", "/SHIFT/HistogramFactoryTestSuite/onlineHistAlias"),
         make_tuple("DEBUG", "/DEBUG/HistogramFactoryTestSuite/onlineHistAlias"),
         make_tuple("RUNSTAT", "/RUNSTAT/HistogramFactoryTestSuite/onlineHistAlias"),
-        make_tuple("EXPRES", "/EXPRES/HistogramFactoryTestSuite/onlineHistAlias"),
+        make_tuple("EXPRESS", "/EXPRESS/HistogramFactoryTestSuite/onlineHistAlias"),
       };
   
       for (auto possibleCase : possibleCases) {
-- 
GitLab


From d393ae42f8c8b63daf582198ff3ab1163fa8f83f Mon Sep 17 00:00:00 2001
From: Peter Onyisi <ponyisi@utexas.edu>
Date: Sat, 21 Dec 2019 15:29:33 +0100
Subject: [PATCH 2/2] Add metadata trees to offline HIST output (ATLASDQ-726)

---
 .../src/HistogramFiller/HistogramFactory.h    | 27 +++----
 .../OfflineHistogramProvider.h                | 72 ++++++++++++++++++-
 2 files changed, 83 insertions(+), 16 deletions(-)

diff --git a/Control/AthenaMonitoringKernel/src/HistogramFiller/HistogramFactory.h b/Control/AthenaMonitoringKernel/src/HistogramFiller/HistogramFactory.h
index e11adc023c50..6b19db84c25d 100644
--- a/Control/AthenaMonitoringKernel/src/HistogramFiller/HistogramFactory.h
+++ b/Control/AthenaMonitoringKernel/src/HistogramFiller/HistogramFactory.h
@@ -46,6 +46,20 @@ namespace Monitored {
      * @return ROOT object handler
      */
     virtual TNamed* create(const HistogramDef& def);
+
+    /**
+     * @brief Invent path name
+     *
+     * If def path contains any of: EXPERT, SHIFT, DEBUG, RUNSTAT, EXPRESS this is online 
+     * convention this becomes the first element of the path followed by the group name.
+     * Else if the def.path is DEFAULT then only the group name is used if the path yet 
+     * different is concatenated with the group name.
+     * 
+     * @param def Histogram definition 
+     * @return Full path to histogram
+    */
+    std::string getFullName(const HistogramDef& def) const;
+
   private:
     /**
      * @brief Create and register histogram
@@ -124,19 +138,6 @@ namespace Monitored {
      */
     static void setLabels(TH1* hist, const std::vector<std::string>& labels);
 
-    /**
-     * @brief Invent path name
-     *
-     * If def path contains any of: EXPERT, SHIFT, DEBUG, RUNSTAT, EXPRES this is online 
-     * convention this becomes the first element of the path followed by the group name.
-     * Else if the def.path is DEFAULT then only the group name is used if the path yet 
-     * different is concatenated with the group name.
-     * 
-     * @param def Histogram definition 
-     * @return Efficiency graph handler
-    */
-    std::string getFullName(const HistogramDef& def);
-
     ServiceHandle<ITHistSvc> m_histSvc;
     std::string m_streamName; //!< defines the stream for THistSvc
     std::string m_groupName;  //!< defines location of group of histograms
diff --git a/Control/AthenaMonitoringKernel/src/HistogramFiller/OfflineHistogramProvider.h b/Control/AthenaMonitoringKernel/src/HistogramFiller/OfflineHistogramProvider.h
index 5106d4ddf980..fb277e4d0f4c 100644
--- a/Control/AthenaMonitoringKernel/src/HistogramFiller/OfflineHistogramProvider.h
+++ b/Control/AthenaMonitoringKernel/src/HistogramFiller/OfflineHistogramProvider.h
@@ -15,6 +15,8 @@
 
 #include "HistogramFactory.h"
 
+#include "TTree.h"
+
 namespace Monitored {
   /**
    * @brief Implementation of IHistogramProvider for offline histograms
@@ -38,6 +40,9 @@ namespace Monitored {
     , m_objcache({0, 0, nullptr})
     {}
 
+    // store metadata trees on object destruction
+    virtual ~OfflineHistogramProvider() override { storeMetadata(); }
+
     /**
      * @brief Getter of ROOT object
      *
@@ -55,9 +60,9 @@ namespace Monitored {
       std::scoped_lock lock(m_cacheMutex);
       objcache& objcacheref = m_objcache;
       if (objcacheref.lumiBlock == lumiBlock
-	  && objcacheref.runNumber == runNumber
-	  && objcacheref.object) {
-	return objcacheref.object;
+	        && objcacheref.runNumber == runNumber
+	        && objcacheref.object) {
+	      return objcacheref.object;
       }
 
       std::string conv = m_histDef->convention;
@@ -75,6 +80,10 @@ namespace Monitored {
       objcacheref.lumiBlock = lumiBlock;
       objcacheref.runNumber = runNumber;
       objcacheref.object = m_factory->create(*m_histDef);
+      const auto fullName = m_factory->getFullName(*m_histDef);
+      if (std::find(m_storedPaths.begin(), m_storedPaths.end(), fullName) == m_storedPaths.end()) {
+        m_storedPaths.push_back(fullName);
+      }
       return objcacheref.object;
     }
 
@@ -90,6 +99,63 @@ namespace Monitored {
     };
     mutable Gaudi::Hive::ContextSpecificData<objcache> m_objcache ATLAS_THREAD_SAFE;
     std::mutex m_cacheMutex;
+
+    std::vector<std::string> m_storedPaths;
+
+    /**
+     * @brief Store metadata trees
+     *
+     * Offline ROOT output should have "metadata" TTrees; this function makes them
+     *
+     */ 
+    void storeMetadata() const {
+      for (const auto &path : m_storedPaths) {
+        //std::cout << "Path " << path << std::endl;
+        size_t pos = path.find_last_of('/');
+        auto splitPath = std::make_pair(path.substr(0, pos), path.substr(pos + 1));
+        std::string treePath = splitPath.first + "/metadata";
+        auto &histSvc = m_gmTool->histogramService();
+        std::string interval;
+        std::string conv = m_histDef->convention;
+        char triggerData[] = "<none>";
+        char mergeData[] = "<default>";
+        if (conv.find("run") != std::string::npos) {
+          interval = "run";
+        } else if (conv.find("lowStat") != std::string::npos) {
+          interval = "lowStat";
+        } else {
+          interval = "lumiBlock";
+        }
+        if (!histSvc->existsTree(treePath)) {
+          auto tree = std::make_unique<TTree>("metadata", "Monitoring Metadata");
+
+          tree->Branch("Name", &(splitPath.second[0]), "Name/C");
+          tree->Branch("Interval", &(interval[0]), "Interval/C");
+          tree->Branch("TriggerChain", triggerData, "TriggerChain/C");
+          tree->Branch("MergeMethod", mergeData, "MergeMethod/C");
+          tree->Fill();
+
+          if (!histSvc->regTree(treePath, std::move(tree))) {
+            MsgStream log(Athena::getMessageSvc(), "OfflineHistogramProvider");
+            log << MSG::ERROR
+                << "Failed to register DQ metadata TTree " << treePath << endmsg;
+          }
+        } else {
+          TTree *tree{nullptr};
+          if (histSvc->getTree(treePath, tree).isSuccess()) {
+            tree->SetBranchAddress("Name", &(splitPath.second[0]));
+            tree->SetBranchAddress("Interval", &(interval[0]));
+            tree->SetBranchAddress("TriggerChain", triggerData);
+            tree->SetBranchAddress("MergeMethod", mergeData);
+            tree->Fill();
+          } else {
+            MsgStream log(Athena::getMessageSvc(), "OfflineHistogramProvider");
+            log << MSG::ERROR
+                << "Failed to retrieve DQ metadata TTree " << treePath << " which is reported to exist" << endmsg;
+          }
+        }
+      }
+    }
   };
 }
 
-- 
GitLab