diff --git a/AtlasTest/CITest/Athena.cmake b/AtlasTest/CITest/Athena.cmake
index 179414a6e097251886edf60d286c018f93652a98..7493c56c7b6180d38173bbbfa30fe2b56f7d8c40 100644
--- a/AtlasTest/CITest/Athena.cmake
+++ b/AtlasTest/CITest/Athena.cmake
@@ -135,6 +135,10 @@ atlas_add_citest( DataQuality_r21ESD_Postprocessing
    SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/test/DataQuality_r21ESD_Postprocessing.sh
    DEPENDS_SUCCESS DataQuality_r21ESD )
 
+atlas_add_citest( DataQuality_Run3Data_AODtoHIST
+   SCRIPT Reco_tf.py --AMI=q449 --inputAODFile="../RecoRun3Data_Collisions/run_q449/myAOD.pool.root" --outputHISTFile=DataQuality_Run3Data_AODtoHIST.root  --athenaopts='--threads=1'
+   DEPENDS_SUCCESS RecoRun3Data_Collisions )
+
 
 #################################################################################
 # Special reconstruction
diff --git a/Control/AthenaConfiguration/python/AllConfigFlags.py b/Control/AthenaConfiguration/python/AllConfigFlags.py
index 04cee3056d9b98730b8c9bd6436225bdfddcac2a..b082448c9c18e19e6c7fc253d72fcf1572bfaae9 100644
--- a/Control/AthenaConfiguration/python/AllConfigFlags.py
+++ b/Control/AthenaConfiguration/python/AllConfigFlags.py
@@ -66,6 +66,11 @@ def _createCfgFlags():
     acf.addFlag('Input.TypedCollections', lambda prevFlags : _typedInputCollections(prevFlags.Input.Files) )
     acf.addFlag('Input.SecondaryTypedCollections', lambda prevFlags : _typedInputCollections(prevFlags.Input.SecondaryFiles) )
 
+    def _metadataItems(inputFile):
+        return GetFileMD(inputFile).get("metadata_items", {})
+
+    acf.addFlag('Input.MetadataItems', lambda prevFlags : _metadataItems(prevFlags.Input.Files) )
+
     acf.addFlag('Concurrency.NumProcs', 0)
     acf.addFlag('Concurrency.NumThreads', 0 )
     acf.addFlag('Concurrency.NumConcurrentEvents', lambda prevFlags : prevFlags.Concurrency.NumThreads)
diff --git a/Control/AthenaMonitoring/share/DataQualitySteering_jobOptions.py b/Control/AthenaMonitoring/share/DataQualitySteering_jobOptions.py
index 2a01a610ab95bc2358fa0597160a00c5dd2df4dc..40675188365353b1f8be49670190e09d727ac8b9 100644
--- a/Control/AthenaMonitoring/share/DataQualitySteering_jobOptions.py
+++ b/Control/AthenaMonitoring/share/DataQualitySteering_jobOptions.py
@@ -35,10 +35,11 @@ if DQMonFlags.doMonitoring():
          from LumiBlockComps.BunchCrossingCondAlgDefault import BunchCrossingCondAlgDefault
          BunchCrossingCondAlgDefault()
 
+         from AthenaConfiguration.ComponentAccumulator import CAtoGlobalWrapper
          from AthenaConfiguration.AllConfigFlags import ConfigFlags
 
          from AthenaMonitoring.AthenaMonitoringAODRecoCfg import AthenaMonitoringAODRecoCfg
-         ComponentAccumulator.CAtoGlobalWrapper(AthenaMonitoringAODRecoCfg, ConfigFlags)
+         CAtoGlobalWrapper(AthenaMonitoringAODRecoCfg, ConfigFlags)
 
    def doOldStylePostSetup(addlSequences=[]):
       #------------------------#
diff --git a/Control/AthenaMonitoring/share/Run3DQTestingDriver.py b/Control/AthenaMonitoring/share/Run3DQTestingDriver.py
index 211f422c5ae716b926362be3cfa045f784beac42..9c90c598b6748dc5dd6741ba0251c5408f92d6ef 100755
--- a/Control/AthenaMonitoring/share/Run3DQTestingDriver.py
+++ b/Control/AthenaMonitoring/share/Run3DQTestingDriver.py
@@ -101,7 +101,6 @@ if __name__=='__main__':
 
     # Initialize configuration object, add accumulator, merge, and run.
     from AthenaConfiguration.MainServicesConfig import MainServicesCfg
-    from AthenaPoolCnvSvc.PoolReadConfig import PoolReadCfg
     cfg = MainServicesCfg(ConfigFlags)
 
     # add FPE auditor
@@ -118,6 +117,7 @@ if __name__=='__main__':
         from CaloRec.CaloRecoConfig import CaloRecoCfg
         cfg.merge(CaloRecoCfg(ConfigFlags))
     else:
+        from AthenaPoolCnvSvc.PoolReadConfig import PoolReadCfg
         cfg.merge(PoolReadCfg(ConfigFlags))
 
     # load DQ
diff --git a/LumiBlock/LumiBlockComps/CMakeLists.txt b/LumiBlock/LumiBlockComps/CMakeLists.txt
index 861ff96d17831cd54cfc6babcfe39b503cb72156..e109404d1aa4b96ed725af145444d34c9af70668 100644
--- a/LumiBlock/LumiBlockComps/CMakeLists.txt
+++ b/LumiBlock/LumiBlockComps/CMakeLists.txt
@@ -12,7 +12,7 @@ find_package( ROOT COMPONENTS Core Tree RIO )
 set( extra_libs )
 set( extra_srcs )
 if( NOT XAOD_ANALYSIS )
-   set( extra_libs CoolLumiUtilitiesLib TrigConfInterfaces TrigConfL1Data LumiBlockData )
+   set( extra_libs CoolLumiUtilitiesLib TrigConfInterfaces TrigConfData LumiBlockData )
    set( extra_srcs src/*.cxx )
 endif()
 atlas_add_library( LumiBlockCompsLib
diff --git a/LumiBlock/LumiBlockComps/python/BunchCrossingCondAlgConfig.py b/LumiBlock/LumiBlockComps/python/BunchCrossingCondAlgConfig.py
index ad38714d1ad326773f2046a928e80f2a74ea2c8b..1b7f861cc864cd349746113ff47f46407cfd34f5 100644
--- a/LumiBlock/LumiBlockComps/python/BunchCrossingCondAlgConfig.py
+++ b/LumiBlock/LumiBlockComps/python/BunchCrossingCondAlgConfig.py
@@ -14,6 +14,7 @@ def BunchCrossingCondAlgCfg(configFlags):
     run1=(configFlags.IOVDb.DatabaseInstance=='COMP200')
     cfgsvc = None
     folder = ''
+    bgkey = ''
 
     if configFlags.Beam.BunchStructureSource == BunchStructureSource.MC:
         folder = "/Digitization/Parameters"
@@ -31,6 +32,19 @@ def BunchCrossingCondAlgCfg(configFlags):
     elif configFlags.Beam.BunchStructureSource == BunchStructureSource.TrigConf:
         from TrigConfxAOD.TrigConfxAODConfig import getxAODConfigSvc
         cfgsvc = result.getPrimaryAndMerge(getxAODConfigSvc(configFlags))
+        if cfgsvc.UseInFileMetadata:
+            if 'TriggerMenuJson_BG' not in configFlags.Input.MetadataItems:
+                # this is for when we need to configure the BunchGroupCondAlg with info extracted from converted JSON
+                # in this case avoid using the xAODConfigSvc, because it will be set up incorrectly
+                from TrigConfigSvc.TrigConfigSvcCfg import BunchGroupCondAlgCfg
+                configFlags_with_DB = configFlags.clone()
+                configFlags_with_DB.Trigger.triggerConfig = 'FILE'
+                result.merge(BunchGroupCondAlgCfg(configFlags_with_DB))
+                bgkey = 'L1BunchGroup'
+            else:  # trust that we can use the in-file metadata
+                bgkey = ''
+        else:
+            bgkey = 'L1BunchGroup'
     elif configFlags.Beam.BunchStructureSource == BunchStructureSource.Lumi:
         from .LuminosityCondAlgConfig import LuminosityCondAlgCfg
         result.merge(LuminosityCondAlgCfg(configFlags))
@@ -39,7 +53,8 @@ def BunchCrossingCondAlgCfg(configFlags):
                                Run1=run1,
                                FillParamsFolderKey=folder,
                                Mode=configFlags.Beam.BunchStructureSource.value,
-                               TrigConfigSvc=cfgsvc 
+                               TrigConfigSvc=cfgsvc,
+                               L1BunchGroupCondData=bgkey
                                )
 
     result.addCondAlgo(alg)
diff --git a/LumiBlock/LumiBlockComps/python/BunchCrossingCondAlgDefault.py b/LumiBlock/LumiBlockComps/python/BunchCrossingCondAlgDefault.py
index 2d2c700b23a998864ff005fd22574a11e73f7252..6d4932c3b8f75d59681d27a8fe815167f83c888b 100644
--- a/LumiBlock/LumiBlockComps/python/BunchCrossingCondAlgDefault.py
+++ b/LumiBlock/LumiBlockComps/python/BunchCrossingCondAlgDefault.py
@@ -20,6 +20,7 @@ def BunchCrossingCondAlgDefault():
 
     run1=(conddb.dbdata == 'COMP200')
     folder = None
+    bgkey = ''
 
     if conddb.isMC and beamFlags.bunchStructureSource() != 1:
         mlog.info('This is MC, trying to reset beamFlags.bunchStructureSource to 1')
@@ -40,6 +41,13 @@ def BunchCrossingCondAlgDefault():
             # /Digitization/Parameters metadata is not present in the
             # input file and will be created during the job
             mlog.info("Folder %s will be created during the job.", folder)
+    elif beamFlags.bunchStructureSource() == 2:
+        bgkey = 'L1BunchGroup'  # unless we use in file metadata...
+        from AthenaCommon.AppMgr import ServiceMgr as svcMgr
+        if getattr(svcMgr, 'xAODConfigSvc'):
+            if svcMgr.xAODConfigSvc.UseInFileMetadata:
+                bgkey = ''
+        # this probably fails for reading R21 ESD but not going to support that case
     elif beamFlags.bunchStructureSource() == 0:
         folder = '/TDAQ/OLC/LHC/FILLPARAMS'
         # Mistakenly created as multi-version folder, must specify HEAD 
@@ -51,7 +59,8 @@ def BunchCrossingCondAlgDefault():
     alg = BunchCrossingCondAlg(name,
                                Run1=run1,
                                FillParamsFolderKey =folder,
-                               Mode=beamFlags.bunchStructureSource() )
+                               Mode=beamFlags.bunchStructureSource(),
+                               L1BunchGroupCondData=bgkey )
 
     condSeq += alg
 
diff --git a/LumiBlock/LumiBlockComps/python/LBDurationCondAlgConfig.py b/LumiBlock/LumiBlockComps/python/LBDurationCondAlgConfig.py
index c8b93cad0506f5825f94e4db6cba446a03da5cac..53bbe7219c358b2221805263c5ba7b8cda301143 100644
--- a/LumiBlock/LumiBlockComps/python/LBDurationCondAlgConfig.py
+++ b/LumiBlock/LumiBlockComps/python/LBDurationCondAlgConfig.py
@@ -13,7 +13,6 @@ def LBDurationCondAlgCfg (configFlags):
     name = 'LBDurationCondAlg'
     result = ComponentAccumulator()
 
-    from IOVDbSvc.CondDB import conddb   # noqa: F401
     folder = "/TRIGGER/LUMI/LBLB"
     result.merge (addFolders (configFlags, folder, 'TRIGGER',
                               className = 'AthenaAttributeList'))
diff --git a/LumiBlock/LumiBlockComps/src/BunchCrossingCondAlg.cxx b/LumiBlock/LumiBlockComps/src/BunchCrossingCondAlg.cxx
index c6ff6dd9a44f46050703a914c418b82cf57113f3..f4f316dfc40f60415ca5415e2e732040ab6747dd 100644
--- a/LumiBlock/LumiBlockComps/src/BunchCrossingCondAlg.cxx
+++ b/LumiBlock/LumiBlockComps/src/BunchCrossingCondAlg.cxx
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration.
+ * Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration.
  */
 
 #include "BunchCrossingCondAlg.h"
@@ -11,10 +11,9 @@
 #include <cstdint>
 
 #include "CoralBase/AttributeListException.h"
-#include "TrigConfL1Data/BunchGroupSet.h"
 
 namespace {
-   // helper to set timestamp based IOV with infinit range
+   // helper to set timestamp based IOV with infinite range
   EventIDBase infiniteIOVBegin() {
      return EventIDBase( 0, // run,
                         EventIDBase::UNDEFEVT,  // event
@@ -24,7 +23,7 @@ namespace {
                         );
   }
 
-  EventIDBase infiniteIOVEend() {
+  EventIDBase infiniteIOVEnd() {
      return EventIDBase( std::numeric_limits<int>::max() - 1, // run
                          EventIDBase::UNDEFEVT,  // event
                          std::numeric_limits<int>::max() - 1, // seconds
@@ -38,6 +37,7 @@ namespace {
 StatusCode BunchCrossingCondAlg::initialize() {
   if (m_mode == 2) {
     ATH_CHECK( m_trigConfigSvc.retrieve() );
+    ATH_CHECK( m_bunchGroupCondDataKey.initialize( SG::AllowEmpty ) );
   }
   ATH_CHECK( m_fillParamsFolderKey.initialize( m_mode == 0 || m_mode == 1 ) );
   ATH_CHECK( m_lumiCondDataKey.initialize( m_mode == 3 ) );
@@ -56,29 +56,38 @@ StatusCode BunchCrossingCondAlg::execute (const EventContext& ctx) const {
   // make sure that the output IOV has a valid timestamp, otherwise the conditions
   // data cannot be added to the "mixed" conditions data container. A mixed container
   // is needed when the conditions depends on e.g. the LuminosityCondData
-  EventIDRange infinite_range(infiniteIOVBegin(),infiniteIOVEend());
+  EventIDRange infinite_range(infiniteIOVBegin(),infiniteIOVEnd());
   writeHdl.addDependency(infinite_range);
 
   //Output object & range:
   auto bccd=std::make_unique<BunchCrossingCondData>();
 
   if (m_mode == 2) { // use trigger bunch groups
-    const std::vector< TrigConf::BunchGroup >& bgs =
-        m_trigConfigSvc->bunchGroupSet()->bunchGroups();
+    const TrigConf::L1BunchGroupSet* bgs{nullptr};
+    if (!m_bunchGroupCondDataKey.empty()) {
+      SG::ReadCondHandle<TrigConf::L1BunchGroupSet> bgsh(m_bunchGroupCondDataKey, ctx);
+      if (! bgsh.isValid()) {
+        ATH_MSG_ERROR("Unable to retrieve L1BunchGroupSet object " << m_bunchGroupCondDataKey);
+        return StatusCode::FAILURE;
+      }
+      bgs = *bgsh;
+    } else {
+      bgs = &(m_trigConfigSvc->l1BunchGroupSet(ctx));
+    }
     // bunch group 1 = paired
-    ATH_MSG_INFO("BG1 bunches " << bgs[1].bunches() );
-    for (const auto& pos : bgs[1].bunches() ) {
+    ATH_MSG_DEBUG("from BunchGroupCondData: BG1 bunches " << bgs->getBunchGroup(1)->bunches() );
+    for (const auto& pos : bgs->getBunchGroup(1)->bunches() ) {
       bccd->m_beam1.set(pos);
       bccd->m_beam2.set(pos);
       bccd->m_luminous.set(pos);
     }
     // in Run 1 we don't have bunch group information to determine beam 1 or beam 2 unpaired
     // so test if we have at least 15 bunch groups, then assume BG13/14 are the unpaired bunches
-    if (bgs.size() >= 15) {
-      for (const auto& pos : bgs[13].bunches() ) {
+    if (bgs->size() >= 15) {
+      for (const auto& pos : bgs->getBunchGroup(13)->bunches() ) {
         bccd->m_beam1.set(pos);
       }
-      for (const auto& pos : bgs[14].bunches() ) {
+      for (const auto& pos : bgs->getBunchGroup(14)->bunches() ) {
         bccd->m_beam2.set(pos);
       }
     }
diff --git a/LumiBlock/LumiBlockComps/src/BunchCrossingCondAlg.h b/LumiBlock/LumiBlockComps/src/BunchCrossingCondAlg.h
index d41147bcff3fc234712575510df87dc45d934f21..126f7bb7d737daea900f0633e9655259d2cb2c4b 100644
--- a/LumiBlock/LumiBlockComps/src/BunchCrossingCondAlg.h
+++ b/LumiBlock/LumiBlockComps/src/BunchCrossingCondAlg.h
@@ -1,6 +1,6 @@
 // This file's extension implies that it's C, but it's really -*- C++ -*-.
 /*
- * Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration.
+ * Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration.
  */
 /**
  * @file BunchCrossingCondAlg.h
@@ -21,6 +21,7 @@
 #include "StoreGate/WriteCondHandleKey.h"
 #include "TrigConfInterfaces/ILVL1ConfigSvc.h"
 #include "LumiBlockData/LuminosityCondData.h"
+#include "TrigConfData/L1BunchGroupSet.h"
 
 /**
  * @brief Conditions algorithm to unpack fill parameters from COOL.
@@ -47,6 +48,7 @@ private:
   /// Input conditions object.
   SG::ReadCondHandleKey<AthenaAttributeList> m_fillParamsFolderKey{ this, "FillParamsFolderKey", "/TDAQ/OLC/LHC/FILLPARAMS", "" };
   SG::ReadCondHandleKey<LuminosityCondData> m_lumiCondDataKey{this, "LumiCondData", "LuminosityCondData", "Lumi cond data key"};
+  SG::ReadCondHandleKey<TrigConf::L1BunchGroupSet> m_bunchGroupCondDataKey{this, "L1BunchGroupCondData", "L1BunchGroup", "Bunch group cond data key"};
   /// Output conditions object.
   SG::WriteCondHandleKey<BunchCrossingCondData> m_outputKey{this, "OutputKey", "BunchCrossingData", "Key of output CDO" };