From 245b3c48a7cfeab071a1b24639d2ecf1889e9ba1 Mon Sep 17 00:00:00 2001
From: John Chapman <jchapman@cern.ch>
Date: Thu, 22 Aug 2019 12:31:27 +0200
Subject: [PATCH] Fixes to make TileOverlay work with DoubleEventSelector

This consists of two fixes. The first ensures that `TileDigitsMaker`
declares the proper dependencies by adding `SG::ReadHandles` for the
background `TileDigitsContainer` and `TileRawChannelContainer` (although
this is not part of the background RDO file). In order to preserve old-style
approach using the `PileUpMergeSvc` then it is necessary to make a copy of
the `TileDigitsContainer`, but this can probably be dropped with  more substantial
refactoring.

The second fix involves changes to ensure that the `TileDQstatusTool` is only called
once during the event loop and to avoid there being two attempts to record the `TileDQstatus`
object in the ConditionsStore. Therefore `TileDQstatusAlg` is not added to the `AlgSequence`
in Overlay jobs.
Possibly it would be cleaner to remove the usage of the `TileDQstatusTool`
from `TileDigitsMaker` and just read the `TileDQstatus` object from the ConditionsStore.
`TileDQstatusAlg` could then be run, but be configured to read the background `TileDigitsContainer`.
---
 .../share/CaloOverlay_jobOptions.py           |   9 +-
 .../python/TileRawChannelGetter.py            |  10 +-
 .../TileSimAlgs/TileSimAlgs/TileDigitsMaker.h |  11 +-
 .../share/TileDigiCommon_jobOptions.py        |  14 +-
 .../TileSimAlgs/src/TileDigitsMaker.cxx       | 386 ++++++++++--------
 5 files changed, 241 insertions(+), 189 deletions(-)

diff --git a/Event/EventOverlay/EventOverlayJobTransforms/share/CaloOverlay_jobOptions.py b/Event/EventOverlay/EventOverlayJobTransforms/share/CaloOverlay_jobOptions.py
index e0e805b4e5d..58ea1fca709 100644
--- a/Event/EventOverlay/EventOverlayJobTransforms/share/CaloOverlay_jobOptions.py
+++ b/Event/EventOverlay/EventOverlayJobTransforms/share/CaloOverlay_jobOptions.py
@@ -64,6 +64,11 @@ if DetFlags.overlay.Tile_on():
     job.TileHitVecToCnt.DigitizationTool.RndmEvtOverlay = True
     job.TileHitVecToCnt.DigitizationTool.OnlyUseContainerName = not overlayFlags.isOverlayMT()
     theTileDigitsMaker.RndmEvtOverlay = True
+    theTileDigitsMaker.OverlayTileDigitContainerName = "TileDigitsCnt"
+    if overlayFlags.isOverlayMT():
+       theTileDigitsMaker.OverlayTileDigitContainerName = overlayFlags.bkgPrefix() + "TileDigitsCnt"
+       theTileDigitsMaker.OverlayTileRawChannelContainerName = overlayFlags.bkgPrefix() + "TileRawChannelCnt"
+       theTileDigitsMaker.OnlyUseContainerName = False
     if overlayFlags.isDataOverlay():
        theApp.Dlls += [ "TileByteStream"]
        ServiceMgr.ByteStreamAddressProviderSvc.TypeNames += [ "TileBeamElemContainer/TileBeamElemCnt"]
@@ -74,8 +79,4 @@ if DetFlags.overlay.Tile_on():
        ServiceMgr.ByteStreamAddressProviderSvc.TypeNames += [ "TileRawChannelContainer/MuRcvRawChCnt"]
        ServiceMgr.ByteStreamAddressProviderSvc.TypeNames += [ "TileDigitsContainer/MuRcvDigitsCnt"]
 
-    from TileRecUtils.TileDQstatusAlgDefault import TileDQstatusAlgDefault
-    dqstatus = TileDQstatusAlgDefault()
-    dqstatus.Enable = False
-
 #--------------------
diff --git a/TileCalorimeter/TileRecUtils/python/TileRawChannelGetter.py b/TileCalorimeter/TileRecUtils/python/TileRawChannelGetter.py
index 53d60801804..6cea7905ae4 100644
--- a/TileCalorimeter/TileRecUtils/python/TileRawChannelGetter.py
+++ b/TileCalorimeter/TileRecUtils/python/TileRawChannelGetter.py
@@ -72,11 +72,11 @@ class TileRawChannelGetter ( Configured)  :
             tileDigitsContainer=""
             tileRawChannelContainer=""
 
-        from TileRecUtils.TileDQstatusAlgDefault import TileDQstatusAlgDefault
-        TileDQstatusAlgDefault (TileRawChannelContainer = tileRawChannelContainer,
-                                TileDigitsContainer = tileDigitsContainer,
-                                TileBeamElemContainer = tileBeamElemContainer)
-                                
+        if not globalflags.isOverlay():
+            from TileRecUtils.TileDQstatusAlgDefault import TileDQstatusAlgDefault
+            TileDQstatusAlgDefault (TileRawChannelContainer = tileRawChannelContainer,
+                                    TileDigitsContainer = tileDigitsContainer,
+                                    TileBeamElemContainer = tileBeamElemContainer)
 
         # set time window for amplitude correction if it was not set correctly before
         if jobproperties.TileRecFlags.TimeMaxForAmpCorrection() <= jobproperties.TileRecFlags.TimeMinForAmpCorrection() :
diff --git a/TileCalorimeter/TileSimAlgs/TileSimAlgs/TileDigitsMaker.h b/TileCalorimeter/TileSimAlgs/TileSimAlgs/TileDigitsMaker.h
index accc7a8337f..5170faeba44 100644
--- a/TileCalorimeter/TileSimAlgs/TileSimAlgs/TileDigitsMaker.h
+++ b/TileCalorimeter/TileSimAlgs/TileSimAlgs/TileDigitsMaker.h
@@ -85,7 +85,9 @@ class TileDigitsMaker: public AthAlgorithm {
     StatusCode finalize();   //!< finalize method
 
   private:
-    StatusCode FillDigitCollection(TileHitContainer::const_iterator hitContItr, std::vector<double *> &drawerBufferLo, std::vector<double *> &drawerBufferHi, int igain[], int overgain[], double ech_int[], std::vector<bool> &signal_in_channel) const;
+    StatusCode overlayBackgroundDigits( const TileDigitsCollection *bkgDigitCollection, const TileHitCollection* hitCollection, int igain[], int ros, int drawer, int drawerIdx, int over_gain[] );
+
+    StatusCode FillDigitCollection(const TileHitCollection* hitCollection, std::vector<double *> &drawerBufferLo, std::vector<double *> &drawerBufferHi, int igain[], int overgain[], double ech_int[], std::vector<bool> &signal_in_channel) const;
 
     SG::ReadHandleKey<TileHitContainer> m_hitContainerKey{this,"TileHitContainer","TileHitCnt",
                                                           "input Tile hit container key"};
@@ -93,6 +95,13 @@ class TileDigitsMaker: public AthAlgorithm {
     SG::ReadHandleKey<TileHitContainer> m_hitContainer_DigiHSTruthKey{this,"TileHitContainer_DigiHSTruth","TileHitCnt_DigiHSTruth",
                                                           "input Tile hit container key"};
 
+    Gaudi::Property<bool> m_onlyUseContainerName{this, "OnlyUseContainerName", true, "Don't use the ReadHandleKey directly. Just extract the container name from it."};
+    SG::ReadHandleKey<TileDigitsContainer> m_overlayDigitContainerKey{this, "OverlayTileDigitContainerName","",""};
+    std::string m_overlayDigitContainerName{""};
+
+    SG::ReadHandleKey<TileRawChannelContainer> m_overlayRawChannelContainerKey{this, "OverlayTileRawChannelContainerName","TileRawChannelCnt",""};
+    std::string m_overlayRawChannelContainerName{""};
+
     SG::WriteHandleKey<TileDigitsContainer> m_digitsContainerKey{this,"TileDigitsContainer",
                                                                  "TileDigitsCnt",
                                                                  "Output Tile digits container key"};
diff --git a/TileCalorimeter/TileSimAlgs/share/TileDigiCommon_jobOptions.py b/TileCalorimeter/TileSimAlgs/share/TileDigiCommon_jobOptions.py
index a4004c46f08..2482e59e0a0 100644
--- a/TileCalorimeter/TileSimAlgs/share/TileDigiCommon_jobOptions.py
+++ b/TileCalorimeter/TileSimAlgs/share/TileDigiCommon_jobOptions.py
@@ -196,12 +196,14 @@ if doTileDigitToRawChannel:
     if TileRawChannelBuilderMF:
         TileRawChannelBuilderMF.DSPContainer = ''
 
-# Change default parameters for TileDQstatusAlg.
-from TileRecUtils.TileDQstatusAlgDefault import TileDQstatusAlgDefault
-dqstatus = TileDQstatusAlgDefault()
-dqstatus.TileBeamElemContainer=""; # disable reading of trigger type from BeamElem container
-dqstatus.TileDigitsContainer="";   # disable checking of Digits container size for bi-gain mode
-dqstatus.TileRawChannelContainer=""; # disable checking of DQstatus for simulated data
+from AthenaCommon.GlobalFlags import globalflags
+if not globalflags.isOverlay():
+    # Change default parameters for TileDQstatusAlg.
+    from TileRecUtils.TileDQstatusAlgDefault import TileDQstatusAlgDefault
+    dqstatus = TileDQstatusAlgDefault()
+    dqstatus.TileBeamElemContainer=""; # disable reading of trigger type from BeamElem container
+    dqstatus.TileDigitsContainer="";   # disable checking of Digits container size for bi-gain mode
+    dqstatus.TileRawChannelContainer=""; # disable checking of DQstatus for simulated data
 
 
 #
diff --git a/TileCalorimeter/TileSimAlgs/src/TileDigitsMaker.cxx b/TileCalorimeter/TileSimAlgs/src/TileDigitsMaker.cxx
index 2baac41e0e4..2a343c78f3a 100644
--- a/TileCalorimeter/TileSimAlgs/src/TileDigitsMaker.cxx
+++ b/TileCalorimeter/TileSimAlgs/src/TileDigitsMaker.cxx
@@ -224,6 +224,10 @@ StatusCode TileDigitsMaker::initialize() {
 
     ATH_CHECK( m_DQstatusTool.retrieve() );
     ATH_CHECK( m_DQstatusKey.initialize() );
+    m_overlayDigitContainerName = m_overlayDigitContainerKey.key();
+    ATH_CHECK( m_overlayDigitContainerKey.initialize(!m_onlyUseContainerName) );
+    m_overlayRawChannelContainerName = m_overlayRawChannelContainerKey.key();
+    ATH_CHECK( m_overlayRawChannelContainerKey.initialize(!m_onlyUseContainerName) );
 
   } else {
     m_DQstatusTool.disable();
@@ -500,54 +504,85 @@ StatusCode TileDigitsMaker::execute() {
     }
   }
 
-  TileDigitsContainer::const_iterator collItrRndm;
-  TileDigitsContainer::const_iterator lastCollRndm;
+  TileMutableDigitsContainer::const_iterator collItrRndm;
+  TileMutableDigitsContainer::const_iterator lastCollRndm;
+  std::unique_ptr<TileMutableDigitsContainer> backgroundDigitContainer{};
   if (m_rndmEvtOverlay) {
+    backgroundDigitContainer = std::make_unique<TileMutableDigitsContainer>(true,
+                                                                            TileFragHash::Digitizer,
+                                                                            TileRawChannelUnit::ADCcounts);
+    ATH_CHECK( backgroundDigitContainer->status() );
 
-    typedef PileUpMergeSvc::TimedList<TileDigitsContainer>::type TimedDigitContList;
-    TileDigitsContainer::const_iterator rndm_digititer_begin;
-    TileDigitsContainer::const_iterator rndm_digititer_end;
-    TileDigitsContainer::const_iterator rndm_digititer;
-
-    TimedDigitContList digitContList;
-    ATH_CHECK( m_mergeSvc->retrieveSubEvtsData("TileDigitsCnt", digitContList));
-    ATH_MSG_DEBUG( "TileDigitsCnt successfully retrieved ");
-
+    const TileRawChannelContainer* rndm_rawchan_container{};
+    auto dqStatus = std::make_unique<TileDQstatus>();
+    if (m_onlyUseContainerName) {
+      typedef PileUpMergeSvc::TimedList<TileDigitsContainer>::type TimedDigitContList;
+      TimedDigitContList digitContList;
+      ATH_CHECK( m_mergeSvc->retrieveSubEvtsData(m_overlayDigitContainerName, digitContList));
+      ATH_MSG_DEBUG( "TileDigitsCnt successfully retrieved ");
 
-    if (digitContList.size() == 0) {
-      ATH_MSG_WARNING( "No overlay done ... ");
-      return StatusCode::SUCCESS;
-    }
 
-    TimedDigitContList::iterator iTzeroDigitCont(digitContList.begin());
-    const TileDigitsContainer * rndm_digit_container = (iTzeroDigitCont->second);
-    collItrRndm = rndm_digit_container->begin();
-    lastCollRndm = rndm_digit_container->end();
+      if (digitContList.size() == 0) {
+        ATH_MSG_WARNING( "No overlay done ... ");
+        return StatusCode::SUCCESS;
+      }
 
-    typedef PileUpMergeSvc::TimedList<TileRawChannelContainer>::type TimedRawChanContList;
-    TimedRawChanContList rawchanContList;
-    if (!(m_mergeSvc->retrieveSubEvtsData("TileRawChannelCnt", rawchanContList).isSuccess())) {
-      ATH_MSG_ERROR( "Cannot retrieve TileRawChannelContainer for DQ check");
-    } else {
-      ATH_MSG_DEBUG( "TileRawChannelContainer for DQ check retrieved");
-    }
+      TimedDigitContList::iterator iTzeroDigitCont(digitContList.begin());
+      for (const auto* digitCollection : *(iTzeroDigitCont->second)) {
+        for (const auto* digit : *digitCollection) {
+          auto pDigits = std::make_unique<TileDigits>(*digit);
+          ATH_CHECK(backgroundDigitContainer->push_back(std::move(pDigits)));
+        }
+      }
+      typedef PileUpMergeSvc::TimedList<TileRawChannelContainer>::type TimedRawChanContList;
+      TimedRawChanContList rawchanContList;
+      if (!(m_mergeSvc->retrieveSubEvtsData(m_overlayRawChannelContainerName, rawchanContList).isSuccess())) {
+        ATH_MSG_ERROR( "Cannot retrieve TileRawChannelContainer for DQ check");
+      } else {
+        ATH_MSG_DEBUG( "TileRawChannelContainer for DQ check retrieved");
+      }
 
-    const TileRawChannelContainer* rndm_rawchan_container(nullptr);
-    if (!rawchanContList.empty()) {
-      TimedRawChanContList::iterator iTzeroRawChanCont(rawchanContList.begin());
-      rndm_rawchan_container = iTzeroRawChanCont->second;
+      if (!rawchanContList.empty()) {
+        TimedRawChanContList::iterator iTzeroRawChanCont(rawchanContList.begin());
+        rndm_rawchan_container = iTzeroRawChanCont->second;
+      }
+      ATH_CHECK( m_DQstatusTool->makeStatus (ctx,
+                                             rndm_rawchan_container,
+                                             backgroundDigitContainer.get(),
+                                             nullptr, // TileBeamElemContainer
+                                             *dqStatus) );
     }
-
-    auto dqStatus = std::make_unique<TileDQstatus>();
-    ATH_CHECK( m_DQstatusTool->makeStatus (ctx,
-                                           rndm_rawchan_container,
-                                           rndm_digit_container,
-                                           nullptr, // TileBeamElemContainer
+    else {
+      SG::ReadHandle<TileDigitsContainer> tileDigitsContainerHandle(m_overlayDigitContainerKey);
+      if (tileDigitsContainerHandle.isValid()) {
+        for (const auto* digitCollection : *tileDigitsContainerHandle) {
+          for (const auto* digit : *digitCollection) {
+            auto pDigits = std::make_unique<TileDigits>(*digit);
+            ATH_CHECK(backgroundDigitContainer->push_back(std::move(pDigits)));
+          }
+        }
+      }
+      else {
+        ATH_MSG_ERROR("ReadHandle to Background Digits is invalid.");
+      }
+      SG::ReadHandle<TileRawChannelContainer> tileRawChannelContainerHandle(m_overlayRawChannelContainerKey);
+      if (tileRawChannelContainerHandle.isValid()) {
+        rndm_rawchan_container = &*tileRawChannelContainerHandle;
+      }
+      else {
+        ATH_MSG_WARNING("ReadHandle to Background Raw Channels is invalid.");
+      }
+      ATH_CHECK( m_DQstatusTool->makeStatus (ctx,
+                                             rndm_rawchan_container,
+                                             backgroundDigitContainer.get(),
+                                             nullptr, // TileBeamElemContainer
                                            *dqStatus) );
-
+    }
     m_DQstatus = dqStatus.get();
 
     ATH_CHECK( SG::makeHandle (m_DQstatusKey, ctx).record (std::move (dqStatus)) );
+    collItrRndm = backgroundDigitContainer->begin();
+    lastCollRndm = backgroundDigitContainer->end();
   }
 
   // iterate over all collections in a container
@@ -564,9 +599,9 @@ StatusCode TileDigitsMaker::execute() {
   /*-------------------------------------------------------------------*/
 
   for (; collItr != lastColl; ++collItr) {
-
+    const TileHitCollection *hitCollection(*collItr);
     /* Get array of HWID's for this drawer (stored locally). */
-    HWIdentifier drawer_id = m_tileHWID->drawer_id((*collItr)->identify());
+    HWIdentifier drawer_id = m_tileHWID->drawer_id(hitCollection->identify());
     int ros = m_tileHWID->ros(drawer_id);
     int drawer = m_tileHWID->drawer(drawer_id);
     int drawerIdx = TileCalibUtils::getDrawerIdx(ros, drawer);
@@ -576,6 +611,9 @@ StatusCode TileDigitsMaker::execute() {
       if (m_rndmEvtOverlay && collItrRndm != lastCollRndm) {
         ++collItrRndm; // skip also one drawer in digi overlay container
       }
+      if (m_doDigiTruth) {
+        ++collItr_DigiHSTruth;
+      } // End DigiHSTruth stuff
       continue;
     }
 
@@ -616,142 +654,16 @@ StatusCode TileDigitsMaker::execute() {
     }
 
     if (m_rndmEvtOverlay && collItrRndm != lastCollRndm) {
-
-      if ((*collItr)->identify() != (*collItrRndm)->identify()) {
-        ATH_MSG_ERROR ( "Frag IDs for hit collection and digits overlay collection do not match "
-                        << MSG::hex << (*collItr)->identify() << " != " << (*collItrRndm)->identify()
-                        << MSG::dec );
-        return StatusCode::FAILURE;
-      }
-
-      // iterate over all digits in a collection 
-      TileDigitsCollection::const_iterator digitItr = (*collItrRndm)->begin();
-      TileDigitsCollection::const_iterator lastDigit = (*collItrRndm)->end();
-
-      for (; digitItr != lastDigit; ++digitItr) {
-
-        /* Get digit HWIdentifier (= adc_id) */
-        HWIdentifier adcId = (*digitItr)->adc_HWID();
-        int channel = m_tileHWID->channel(adcId);
-        int gain = m_tileHWID->adc(adcId);
-
-        igain[channel] = gain;
-
-        // get channel status
-        bool good_dq = m_DQstatus->isAdcDQgood(ros, drawer, channel, gain);
-        bool good_ch = (!m_tileBadChanTool->getAdcStatus(drawerIdx, channel, gain).isBad());
-
-        // get digits
-        std::vector<float> digits = (*digitItr)->samples();
-        // get number of time samples & compare with nSamp
-        int nSamp2 = digits.size();
-        int goodDigits = nSamp2;
-        float dig(2047.),digmin(65536.),digmax(-65536.);
-        if (good_dq) {
-          for (int js = 0; js < nSamp2; ++js) {
-            dig=digits[js];
-            if (dig<digmin) digmin=dig;
-            if (dig>digmax) digmax=dig;
-            if (dig<0.01) { // skip zeros
-              --goodDigits;
-            } else if (dig>1022.99) { // skip overflows
-              if (dig>1023.01) { // ignore everything in case of invalid digits
-                dig=2047.0;
-                goodDigits = 0;
-                break;
-              }
-              --goodDigits;
-            }
-          } 
-        } else if (goodDigits>0) {
-          goodDigits = 0;
-          dig = digmin = digmax = digits[0];
-          for (int js = 1; js < nSamp2; ++js) {
-            dig=digits[js];
-            if (dig<digmin) digmin=dig;
-            else if (dig>digmax) digmax=dig;
-          }
-        }
-        
-        if (goodDigits>0) {
-          over_gain[channel] = gain;
-          if (nSamp2 != m_nSamples) {
-            digits.resize(m_nSamples);
-            for (int js = nSamp2; js < m_nSamples; ++js)
-              digits[js] = digits[js - 1]; // repeat last value in vector (nSamp-nSamp2) times
-          }
-
-          double * buffer;
-          double * bufferLG=0;
-          if (gain == TileID::HIGHGAIN) {
-            if (digmax - digmin > 5. && good_ch ) {// 5 ADC counts cut - to ignore pure noise in HG (less than 0.1 count effect in LG)
-              float ratio = m_tileToolEmscale->doCalibCisOnl(drawerIdx, channel, TileID::HIGHGAIN, 1.)
-                          / m_tileToolEmscale->doCalibCisOnl(drawerIdx, channel, TileID::LOWGAIN, 1.); // ratio between low and high gain
-              dig=std::min(digits[0],std::max(digmin,m_tileToolNoiseSample->getPed(drawerIdx, channel, TileID::HIGHGAIN)));
-              bufferLG = m_drawerBufferLo[channel]; 
-              for (int js = 0; js < m_nSamples; ++js)        // in case low gain background is needed later
-                bufferLG[js] = (digits[js]-dig)*ratio;    // put in low gain buffer signal divided by 64 (LG/HG ratio) 
-            }
-            buffer = m_drawerBufferHi[channel];
-          } else {
-            buffer = m_drawerBufferLo[channel];
-          }
-          for (int js = 0; js < m_nSamples; ++js)
-            buffer[js] = digits[js];
-
-          if (msgLvl(MSG::VERBOSE)) {
-            msg(MSG::VERBOSE) << "RNDM BG ADC " << m_tileHWID->to_string(adcId)
-                              << " samples=";
-            for (int js = 0; js < m_nSamples; ++js)
-              msg(MSG::VERBOSE) << " " << buffer[js];
-            if (!good_ch)
-              msg(MSG::VERBOSE) << " BCH";
-            if (!good_dq) {
-              msg(MSG::VERBOSE) << " BDQ";
-            } else if (bufferLG) {
-              msg(MSG::VERBOSE) << "  LG=";
-              for (int js = 0; js < m_nSamples; ++js)
-                msg(MSG::VERBOSE) << " " << int(bufferLG[js]*100)/100.;
-            }
-            msg(MSG::VERBOSE) << endmsg;
-          }
-
-        } else if (nSamp2 > 0) {
-          over_gain[channel] = 10+gain; // flag problematic channel
-
-          double * buffer;
-          if (gain == TileID::HIGHGAIN) {
-            buffer = m_drawerBufferHi[channel];
-          } else {
-            buffer = m_drawerBufferLo[channel];
-          }
-
-          if (digmin != digmax || (dig!=0. && dig!=1023.)) dig=2047.; // keep only 0 or 1023 as it is
-          for (int js = 0; js < m_nSamples; ++js)
-            buffer[js] = dig;
-
-          if (msgLvl(MSG::VERBOSE)) {
-            msg(MSG::VERBOSE) << "BAD BG  ADC " << m_tileHWID->to_string(adcId)
-                              << " samples=";
-            for (int js = 0; js < nSamp2; ++js)
-              msg(MSG::VERBOSE) << " " << digits[js];
-            msg(MSG::VERBOSE) << ((good_ch)?"":" BCH") << ((good_dq)?"":" BDQ") << endmsg;
-          }
-
-        } else {
-          ATH_MSG_VERBOSE( "NO BG   ADC " << m_tileHWID->to_string(adcId)
-                           << " samples= 0 0 0 0 0 0 0"
-                           << ((good_ch)?"":" BCH") << ((good_dq)?"":" BDQ") );
-        }
-      }
+      const TileDigitsCollection *bkgDigitCollection(*collItrRndm);
+      ATH_CHECK(overlayBackgroundDigits(bkgDigitCollection, hitCollection, igain, ros, drawer, drawerIdx, over_gain));
       ++collItrRndm; // skip to next digi collection
     }
 
     std::vector<bool> signal_in_channel(nchMax, 0);
     std::vector<bool> signal_in_channel_DigiHSTruth(nchMax, 0);
-    ATH_CHECK(FillDigitCollection( collItr, m_drawerBufferLo, m_drawerBufferHi, igain, over_gain, ech_int, signal_in_channel));
+    ATH_CHECK(FillDigitCollection( *collItr, m_drawerBufferLo, m_drawerBufferHi, igain, over_gain, ech_int, signal_in_channel));
     if(m_doDigiTruth){
-      ATH_CHECK(FillDigitCollection( collItr_DigiHSTruth, m_drawerBufferLo_DigiHSTruth, m_drawerBufferHi_DigiHSTruth, igain, over_gain, ech_int_DigiHSTruth, signal_in_channel_DigiHSTruth));
+      ATH_CHECK(FillDigitCollection( *collItr_DigiHSTruth, m_drawerBufferLo_DigiHSTruth, m_drawerBufferHi_DigiHSTruth, igain, over_gain, ech_int_DigiHSTruth, signal_in_channel_DigiHSTruth));
     } // End DigiHSTruth stuff
 
     /* Now all signals for this collection are stored in m_drawerBuffer, 
@@ -1293,7 +1205,7 @@ StatusCode TileDigitsMaker::finalize() {
   return StatusCode::SUCCESS;
 }
 
-StatusCode TileDigitsMaker::FillDigitCollection(TileHitContainer::const_iterator hitContItr, std::vector<double *> &drawerBufferLo, std::vector<double *> &drawerBufferHi, int igain[], int over_gain[], double ech_int[], std::vector<bool> &signal_in_channel) const{
+StatusCode TileDigitsMaker::FillDigitCollection(const TileHitCollection* hitCollection, std::vector<double *> &drawerBufferLo, std::vector<double *> &drawerBufferHi, int igain[], int over_gain[], double ech_int[], std::vector<bool> &signal_in_channel) const{
   
   // Zero sums for monitoring.
   int nChSum = 0;
@@ -1311,15 +1223,15 @@ StatusCode TileDigitsMaker::FillDigitCollection(TileHitContainer::const_iterator
   /* Set up buffers for handling information in a single collection. */
   IdentifierHash idhash;
 
-  HWIdentifier drawer_id = m_tileHWID->drawer_id((*hitContItr)->identify());
+  HWIdentifier drawer_id = m_tileHWID->drawer_id(hitCollection->identify());
   int ros = m_tileHWID->ros(drawer_id);
   int drawer = m_tileHWID->drawer(drawer_id);
   int drawerIdx = TileCalibUtils::getDrawerIdx(ros, drawer);
 
 
   // iterate over all hits in a collection
-  TileHitCollection::const_iterator hitItr = (*hitContItr)->begin();
-  TileHitCollection::const_iterator lastHit = (*hitContItr)->end();
+  TileHitCollection::const_iterator hitItr = hitCollection->begin();
+  TileHitCollection::const_iterator lastHit = hitCollection->end();
 
   for (; hitItr != lastHit; ++hitItr) {
 
@@ -1455,3 +1367,131 @@ StatusCode TileDigitsMaker::FillDigitCollection(TileHitContainer::const_iterator
   return StatusCode::SUCCESS;
 
 }
+
+StatusCode TileDigitsMaker::overlayBackgroundDigits( const TileDigitsCollection *bkgDigitCollection, const TileHitCollection* hitCollection, int igain[], int ros, int drawer, int drawerIdx, int over_gain[] ) {
+  if (hitCollection->identify() != bkgDigitCollection->identify()) {
+    ATH_MSG_ERROR ( "Frag IDs for hit collection and digits overlay collection do not match "
+                    << MSG::hex << hitCollection->identify() << " != " << bkgDigitCollection->identify()
+                    << MSG::dec );
+    return StatusCode::FAILURE;
+  }
+
+  // iterate over all digits in a collection
+  for (const auto* bkgDigit : *bkgDigitCollection) {
+
+    /* Get digit HWIdentifier (= adc_id) */
+    HWIdentifier adcId = bkgDigit->adc_HWID();
+    int channel = m_tileHWID->channel(adcId);
+    int gain = m_tileHWID->adc(adcId);
+
+    igain[channel] = gain;
+
+    // get channel status
+    bool good_dq = m_DQstatus->isAdcDQgood(ros, drawer, channel, gain);
+    bool good_ch = (!m_tileBadChanTool->getAdcStatus(drawerIdx, channel, gain).isBad());
+
+    // get digits
+    std::vector<float> digits = bkgDigit->samples();
+    // get number of time samples & compare with nSamp
+    int nSamp2 = digits.size();
+    int goodDigits = nSamp2;
+    float dig(2047.),digmin(65536.),digmax(-65536.);
+    if (good_dq) {
+      for (int js = 0; js < nSamp2; ++js) {
+        dig=digits[js];
+        if (dig<digmin) digmin=dig;
+        if (dig>digmax) digmax=dig;
+        if (dig<0.01) { // skip zeros
+          --goodDigits;
+        } else if (dig>1022.99) { // skip overflows
+          if (dig>1023.01) { // ignore everything in case of invalid digits
+            dig=2047.0;
+            goodDigits = 0;
+            break;
+          }
+          --goodDigits;
+        }
+      } 
+    } else if (goodDigits>0) {
+      goodDigits = 0;
+      dig = digmin = digmax = digits[0];
+      for (int js = 1; js < nSamp2; ++js) {
+        dig=digits[js];
+        if (dig<digmin) digmin=dig;
+        else if (dig>digmax) digmax=dig;
+      }
+    }
+        
+    if (goodDigits>0) {
+      over_gain[channel] = gain;
+      if (nSamp2 != m_nSamples) {
+        digits.resize(m_nSamples);
+        for (int js = nSamp2; js < m_nSamples; ++js)
+          digits[js] = digits[js - 1]; // repeat last value in vector (nSamp-nSamp2) times
+      }
+
+      double * buffer;
+      double * bufferLG=0;
+      if (gain == TileID::HIGHGAIN) {
+        if (digmax - digmin > 5. && good_ch ) {// 5 ADC counts cut - to ignore pure noise in HG (less than 0.1 count effect in LG)
+          float ratio = m_tileToolEmscale->doCalibCisOnl(drawerIdx, channel, TileID::HIGHGAIN, 1.)
+            / m_tileToolEmscale->doCalibCisOnl(drawerIdx, channel, TileID::LOWGAIN, 1.); // ratio between low and high gain
+          dig=std::min(digits[0],std::max(digmin,m_tileToolNoiseSample->getPed(drawerIdx, channel, TileID::HIGHGAIN)));
+          bufferLG = m_drawerBufferLo[channel]; 
+          for (int js = 0; js < m_nSamples; ++js)        // in case low gain background is needed later
+            bufferLG[js] = (digits[js]-dig)*ratio;    // put in low gain buffer signal divided by 64 (LG/HG ratio) 
+        }
+        buffer = m_drawerBufferHi[channel];
+      } else {
+        buffer = m_drawerBufferLo[channel];
+      }
+      for (int js = 0; js < m_nSamples; ++js)
+        buffer[js] = digits[js];
+
+      if (msgLvl(MSG::VERBOSE)) {
+        msg(MSG::VERBOSE) << "RNDM BG ADC " << m_tileHWID->to_string(adcId)
+                          << " samples=";
+        for (int js = 0; js < m_nSamples; ++js)
+          msg(MSG::VERBOSE) << " " << buffer[js];
+        if (!good_ch)
+          msg(MSG::VERBOSE) << " BCH";
+        if (!good_dq) {
+          msg(MSG::VERBOSE) << " BDQ";
+        } else if (bufferLG) {
+          msg(MSG::VERBOSE) << "  LG=";
+          for (int js = 0; js < m_nSamples; ++js)
+            msg(MSG::VERBOSE) << " " << int(bufferLG[js]*100)/100.;
+        }
+        msg(MSG::VERBOSE) << endmsg;
+      }
+
+    } else if (nSamp2 > 0) {
+      over_gain[channel] = 10+gain; // flag problematic channel
+
+      double * buffer;
+      if (gain == TileID::HIGHGAIN) {
+        buffer = m_drawerBufferHi[channel];
+      } else {
+        buffer = m_drawerBufferLo[channel];
+      }
+
+      if (digmin != digmax || (dig!=0. && dig!=1023.)) dig=2047.; // keep only 0 or 1023 as it is
+      for (int js = 0; js < m_nSamples; ++js)
+        buffer[js] = dig;
+
+      if (msgLvl(MSG::VERBOSE)) {
+        msg(MSG::VERBOSE) << "BAD BG  ADC " << m_tileHWID->to_string(adcId)
+                          << " samples=";
+        for (int js = 0; js < nSamp2; ++js)
+          msg(MSG::VERBOSE) << " " << digits[js];
+        msg(MSG::VERBOSE) << ((good_ch)?"":" BCH") << ((good_dq)?"":" BDQ") << endmsg;
+      }
+
+    } else {
+      ATH_MSG_VERBOSE( "NO BG   ADC " << m_tileHWID->to_string(adcId)
+                       << " samples= 0 0 0 0 0 0 0"
+                       << ((good_ch)?"":" BCH") << ((good_dq)?"":" BDQ") );
+    }
+  }
+  return StatusCode::SUCCESS;
+}
-- 
GitLab