From d4a0a2cf432273e781e1405ca85fddc67f1a0ed1 Mon Sep 17 00:00:00 2001
From: Peter Onyisi <ponyisi@utexas.edu>
Date: Thu, 1 Aug 2019 09:41:34 +0000
Subject: [PATCH] Merge branch '21.0-fix-DQ-event-cleaning' into '21.0'

Improvements to DQ monitoring filters

See merge request atlas/athena!23496
---
 .../AthenaMonitoring/DQEventFlagFilterTool.h  | 37 +++++++++++++
 Control/AthenaMonitoring/python/DQMonFlags.py | 16 ++++++
 .../python/EventFlagFilterTool.py             | 27 ++++++++++
 .../share/DQMonFlagsConfig_jobOptions.py      |  2 +-
 .../share/DataQualitySteering_jobOptions.py   | 23 ++++++++
 .../src/DQEventFlagFilterTool.cxx             | 52 +++++++++++++++++++
 .../components/AthenaMonitoring_entries.cxx   |  2 +
 7 files changed, 158 insertions(+), 1 deletion(-)
 create mode 100644 Control/AthenaMonitoring/AthenaMonitoring/DQEventFlagFilterTool.h
 create mode 100644 Control/AthenaMonitoring/python/EventFlagFilterTool.py
 create mode 100644 Control/AthenaMonitoring/src/DQEventFlagFilterTool.cxx

diff --git a/Control/AthenaMonitoring/AthenaMonitoring/DQEventFlagFilterTool.h b/Control/AthenaMonitoring/AthenaMonitoring/DQEventFlagFilterTool.h
new file mode 100644
index 00000000000..2fac590257c
--- /dev/null
+++ b/Control/AthenaMonitoring/AthenaMonitoring/DQEventFlagFilterTool.h
@@ -0,0 +1,37 @@
+/*
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef DQEVENTFLAGFILTERTOOL_H
+#define DQEVENTFLAGFILTERTOOL_H
+
+#include "AthenaMonitoring/IDQFilterTool.h"
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "GaudiKernel/StatusCode.h"
+#include "GaudiKernel/ToolHandle.h"
+#include "xAODEventInfo/EventInfo.h"
+
+// This filter tool only accepts events which do not fail DP event cleaning cuts
+// @author Peter Onyisi <ponyisi@cern.ch>
+
+class DQEventFlagFilterTool :  public AthAlgTool, virtual public IDQFilterTool   {
+ public:
+  DQEventFlagFilterTool(const std::string&,const std::string&,const IInterface*);
+        
+  virtual ~DQEventFlagFilterTool () override;
+        
+  virtual StatusCode initialize() override;
+
+  virtual bool accept() const override;
+
+ private:
+  Gaudi::Property<bool> m_alwaysReturnTrue{this, "alwaysReturnTrue", false};
+  Gaudi::Property<bool> m_invert{this, "invert", false};
+  Gaudi::Property<bool> m_doLAr{this, "doLAr", true};
+  Gaudi::Property<bool> m_doTile{this, "doTile", true};
+  Gaudi::Property<bool> m_doSCT{this, "doSCT", true};
+  Gaudi::Property<bool> m_doCore{this, "doCore", true};
+  SG::ReadHandleKey<xAOD::EventInfo> m_EventInfoKey{this, "EventInfoKey", "EventInfo"};
+};
+
+#endif //DQEVENTFLAGFILTERTOOL_H
diff --git a/Control/AthenaMonitoring/python/DQMonFlags.py b/Control/AthenaMonitoring/python/DQMonFlags.py
index fba3359c081..e624702ee23 100644
--- a/Control/AthenaMonitoring/python/DQMonFlags.py
+++ b/Control/AthenaMonitoring/python/DQMonFlags.py
@@ -398,6 +398,22 @@ class enableLumiAccess(JobProperty):
     StoredValue=True
 list+=[enableLumiAccess]
 
+class includeInCleaning(JobProperty):
+    """ Tools matching regexes in this list will have event cleaning tool set up """
+    statusOn=True
+    allowedTypes=['list']
+    StoredValue=[ '.*JetMonitoring.*', '.*METMonTool.*', '.*tauMonTool.*',
+                  '.*DQTGlobalWZFinder.*', '.*jetTagMon.*', '.*phMonTool.*',
+                  '.*elMonTool.*', '.*fwdMonTool.*' ]
+list+=[includeInCleaning]
+
+class specialCleaningConfiguration(JobProperty):
+    """ Special event cleaning configurations (no regexes) """
+    statusOn=True
+    allowedTypes=['dict']
+    StoredValue={}
+list+=[specialCleaningConfiguration]
+
 ##-----------------------------------------------------------------------------
 ## 2nd step
 ## Definition of the DQMon flag container
diff --git a/Control/AthenaMonitoring/python/EventFlagFilterTool.py b/Control/AthenaMonitoring/python/EventFlagFilterTool.py
new file mode 100644
index 00000000000..3c0ac80ce83
--- /dev/null
+++ b/Control/AthenaMonitoring/python/EventFlagFilterTool.py
@@ -0,0 +1,27 @@
+# Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+
+from PyUtils.Decorators import memoize
+
+# Set up the event cleaning filter tool
+# Cache instances that are already created
+@memoize
+def GetEventFlagFilterTool(name, doLAr=True, doTile=True, doSCT=True, doCore=True, alwaysReturnTrue=False):
+    """
+    Configure an instance of the bad LB filter tool.  If called twice with the same options, will return the same instance.
+    Arguments:
+        - name: name of instance to create
+        - doLAr: do LAr cleaning (optional; default=True)
+        - doTile: do Tile cleaning (optional; default=True)
+        - doSCT: do SCT cleaning (optional; default=True)
+        - doCore: do Core event building cleaning (optional; default=True)
+        - alwaysReturnTrue: short-circuit all checks and return True (optional; default=False)
+    """
+    from AthenaCommon.AppMgr import ToolSvc
+    from AthenaCommon.Logging import logging
+    log = logging.getLogger('EventFlagFilterTool')
+
+    from AthenaMonitoring.AthenaMonitoringConf import DQEventFlagFilterTool
+    monFilterTool = DQEventFlagFilterTool(name, doLAr=doLAr, doTile=doTile,
+                                          doSCT=doSCT, doCore=doCore)
+
+    return monFilterTool
diff --git a/Control/AthenaMonitoring/share/DQMonFlagsConfig_jobOptions.py b/Control/AthenaMonitoring/share/DQMonFlagsConfig_jobOptions.py
index bb672ba9676..852e0111b60 100644
--- a/Control/AthenaMonitoring/share/DQMonFlagsConfig_jobOptions.py
+++ b/Control/AthenaMonitoring/share/DQMonFlagsConfig_jobOptions.py
@@ -451,7 +451,7 @@ else:
    local_logger.info("Stream-Aware monitoring is turned OFF")
 
 # If data type is '*comm' disable ATLAS Ready filter by default
-if (rec.projectName.get_Value().endswith('_comm') and 
+if (rec.projectName.get_Value().endswith('comm') and 
     not DQMonFlags.disableAtlasReadyFilter()
     ):
    local_logger.info("This is a commissioning project tag, will attempt to disable ATLAS Ready filter for monitoring tools. To really enable it, use DQMonFlags.disableAtlasReadyFilter.set_Value_and_Lock(False).")
diff --git a/Control/AthenaMonitoring/share/DataQualitySteering_jobOptions.py b/Control/AthenaMonitoring/share/DataQualitySteering_jobOptions.py
index f9576f4e667..cec2b412c2d 100644
--- a/Control/AthenaMonitoring/share/DataQualitySteering_jobOptions.py
+++ b/Control/AthenaMonitoring/share/DataQualitySteering_jobOptions.py
@@ -247,7 +247,11 @@ if DQMonFlags.doMonitoring():
    #--------------------------#
    # Post-setup configuration #
    #--------------------------#
+   if rec.triggerStream()=='express':
+      include("AthenaMonitoring/AtlasReadyFilterTool_jobOptions.py")
    local_logger.debug('DQ Post-Setup Configuration')
+   import re
+   from AthenaMonitoring.EventFlagFilterTool import GetEventFlagFilterTool
 
    # now the DQ tools are private, extract them from the set of monitoring algorithms
    toolset = set()
@@ -271,6 +275,25 @@ if DQMonFlags.doMonitoring():
          if rec.triggerStream()=='express':
             local_logger.info('Stream is express and we will add ready tool for %s', tool)
             tool.FilterTools += [GetAtlasReadyFilterTool()]
+         # if requested: configure a generic event cleaning tool
+         if not athenaCommonFlags.isOnline() and any(re.match(_, tool.name()) for _ in DQMonFlags.includeInCleaning()):
+            if tool.name() in DQMonFlags.specialCleaningConfiguration():
+               config_ = DQMonFlags.specialCleaningConfiguration()[tool.name()].copy()
+               for _ in config_:
+                  try:
+                     config_[_] = bool(config_[_])
+                  except:
+                     local_logger.error('Unable to enact special event cleaning configuration for tool %s; cannot cast %s=%s to bool', tool.name(), _, config_[_])
+               config_['name'] = 'DQEventFlagFilterTool_%s' % tool.name()
+               tool.FilterTools += [GetEventFlagFilterTool(**config_)]
+               del config_
+               local_logger.info('Configurating special event cleaning for tool %s', tool)
+            else:
+               local_logger.info('Configuring generic event cleaning for tool %s', tool)
+               tool.FilterTools += [GetEventFlagFilterTool('DQEventFlagFilterTool')]
+         else:
+            local_logger.info('NOT configuring event cleaning for tool %s', tool)
+
          # give all the tools the trigger translator
          if DQMonFlags.useTrigger():
             tool.TrigDecisionTool = monTrigDecTool
diff --git a/Control/AthenaMonitoring/src/DQEventFlagFilterTool.cxx b/Control/AthenaMonitoring/src/DQEventFlagFilterTool.cxx
new file mode 100644
index 00000000000..03c9b000b62
--- /dev/null
+++ b/Control/AthenaMonitoring/src/DQEventFlagFilterTool.cxx
@@ -0,0 +1,52 @@
+/*
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "AthenaMonitoring/DQEventFlagFilterTool.h"
+#include "AthenaKernel/errorcheck.h"
+
+DQEventFlagFilterTool::DQEventFlagFilterTool(const std::string& type,const std::string& name,const IInterface* parent)
+: AthAlgTool( type, name, parent )
+{
+ declareInterface<IDQFilterTool>(this);
+}
+        
+DQEventFlagFilterTool::~DQEventFlagFilterTool () {}
+
+StatusCode DQEventFlagFilterTool::initialize()
+{
+  ATH_MSG_VERBOSE("ATLAS Ready initialize");
+  // don't register callback if we always return true anyway
+  ATH_CHECK( m_EventInfoKey.initialize(!m_alwaysReturnTrue) );
+  return StatusCode::SUCCESS;
+}
+
+bool DQEventFlagFilterTool::accept() const {
+  if (m_alwaysReturnTrue) {
+    return true;
+  } else {
+    SG::ReadHandle<xAOD::EventInfo> eventInfo(m_EventInfoKey);
+    if (! eventInfo.isValid()) {
+      ATH_MSG_ERROR("Cannot retrieve EventInfo object, returning false (or true if invert is set)");
+      return m_invert;
+    }
+    bool passed(true); //event passes
+    auto errorcode(xAOD::EventInfo::Error);
+    if (m_doLAr && (eventInfo->errorState(xAOD::EventInfo::LAr) == errorcode)) {
+      ATH_MSG_DEBUG("Event fails LAr event veto");
+      passed = false;
+    } else if (m_doTile && (eventInfo->errorState(xAOD::EventInfo::Tile) == errorcode)) {
+      ATH_MSG_DEBUG("Event fails Tile event veto");
+      passed = false;
+    } else if (m_doSCT && (eventInfo->errorState(xAOD::EventInfo::SCT) == errorcode)) {
+      ATH_MSG_DEBUG("Event fails SCT event veto");
+      passed = false;
+    } else if (m_doCore && (eventInfo->eventFlags(xAOD::EventInfo::Core) & 0x40000)) {
+      ATH_MSG_DEBUG("Event fais data corruption veto");
+      passed = false;
+    }
+    passed ^= m_invert;
+    ATH_MSG_VERBOSE("Event flag DQ tool accept called, passed " << passed);
+    return passed;
+  }
+}
diff --git a/Control/AthenaMonitoring/src/components/AthenaMonitoring_entries.cxx b/Control/AthenaMonitoring/src/components/AthenaMonitoring_entries.cxx
index abf8f16afca..0d47102c0e7 100644
--- a/Control/AthenaMonitoring/src/components/AthenaMonitoring_entries.cxx
+++ b/Control/AthenaMonitoring/src/components/AthenaMonitoring_entries.cxx
@@ -7,6 +7,7 @@
 #include "AthenaMonitoring/ManagedMonitorToolTest.h"
 #include "AthenaMonitoring/DQAtlasReadyFilterTool.h"
 #include "AthenaMonitoring/DQFilledBunchFilterTool.h"
+#include "AthenaMonitoring/DQEventFlagFilterTool.h"
 #include "AthenaMonitoring/DQDummyFilterTool.h"
 #include "AthenaMonitoring/DQBadLBFilterTool.h"
 #include "AthenaMonitoring/DQBadLBFilterAlg.h"
@@ -20,6 +21,7 @@ DECLARE_COMPONENT( AthenaMonManager )
 DECLARE_COMPONENT( ManagedMonitorToolTest )
 DECLARE_COMPONENT( DQAtlasReadyFilterTool )
 DECLARE_COMPONENT( DQFilledBunchFilterTool )
+DECLARE_COMPONENT( DQEventFlagFilterTool )
 DECLARE_COMPONENT( DQDummyFilterTool )
 DECLARE_COMPONENT( DQBadLBFilterTool )
 DECLARE_COMPONENT( DQBadLBFilterAlg )
-- 
GitLab