From eb2c379d3d20515a93c37b349fc785193db47334 Mon Sep 17 00:00:00 2001
From: Pavol Strizenec <pavol.strizenec@cern.ch>
Date: Mon, 17 Feb 2020 09:38:36 +0000
Subject: [PATCH] LAr calib. digits reading and monitoring

---
 .../python/LArRawCalibDataReadingConfig.py    |  49 +++
 .../src/LArRawCalibDataReadingAlg.cxx         | 313 ++++++++++++++++++
 .../src/LArRawCalibDataReadingAlg.h           |  55 +++
 .../src/components/LArByteStream_entries.cxx  |   2 +
 .../LArMonitoring/python/LArCalibMonAlg.py    |  88 +++++
 .../LArMonitoring/python/LArCalibPedMonAlg.py |  88 +++++
 .../LArMonitoring/python/LArFEBMonAlg.py      |  29 +-
 .../LArMonitoring/src/LArCalibPedMonAlg.cxx   | 117 +++++++
 .../LArMonitoring/src/LArCalibPedMonAlg.h     |  50 +++
 .../src/components/LArMonitoring_entries.cxx  |   2 +
 10 files changed, 778 insertions(+), 15 deletions(-)
 create mode 100644 LArCalorimeter/LArCnv/LArByteStream/python/LArRawCalibDataReadingConfig.py
 create mode 100644 LArCalorimeter/LArCnv/LArByteStream/src/LArRawCalibDataReadingAlg.cxx
 create mode 100644 LArCalorimeter/LArCnv/LArByteStream/src/LArRawCalibDataReadingAlg.h
 create mode 100644 LArCalorimeter/LArMonitoring/python/LArCalibMonAlg.py
 create mode 100644 LArCalorimeter/LArMonitoring/python/LArCalibPedMonAlg.py
 create mode 100644 LArCalorimeter/LArMonitoring/src/LArCalibPedMonAlg.cxx
 create mode 100644 LArCalorimeter/LArMonitoring/src/LArCalibPedMonAlg.h

diff --git a/LArCalorimeter/LArCnv/LArByteStream/python/LArRawCalibDataReadingConfig.py b/LArCalorimeter/LArCnv/LArByteStream/python/LArRawCalibDataReadingConfig.py
new file mode 100644
index 00000000000..f90fc3aafca
--- /dev/null
+++ b/LArCalorimeter/LArCnv/LArByteStream/python/LArRawCalibDataReadingConfig.py
@@ -0,0 +1,49 @@
+# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+
+from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator
+from AthenaConfiguration.ComponentFactory import CompFactory
+from ByteStreamCnvSvc.ByteStreamConfig import ByteStreamReadCfg
+LArRawCalibDataReadingAlg=CompFactory.LArRawCalibDataReadingAlg
+
+def LArRawCalibDataReadingCfg(configFlags,gain="HIGH",doAccDigit=False,doAccCalibDigit=False,doCalibDigit=False):
+    acc=ComponentAccumulator()
+    from DetDescrCnvSvc.DetDescrCnvSvcConfig import DetDescrCnvSvcCfg
+    acc.merge(DetDescrCnvSvcCfg(configFlags))
+    acc.merge(ByteStreamReadCfg(configFlags))    
+    accKey=""
+    accCalibKey=""
+    calibKey=""
+    if doAccDigit:
+       accKey=gain
+    if doAccCalibDigit:
+       accCalibKey=gain
+    if doCalibDigit:
+       calibKey=gain
+
+    cread = LArRawCalibDataReadingAlg(LArAccDigitKey=accKey, LArAccCalibDigitKey=accCalibKey,
+                                      LArCalibDigitKey=calibKey, LArFebHeaderKey="LArFebHeader")
+    acc.addEventAlgo(cread)
+    return acc
+
+
+if __name__=="__main__":
+
+    from AthenaConfiguration.AllConfigFlags import ConfigFlags
+    from AthenaCommon.Logging import log
+    from AthenaCommon.Constants import DEBUG
+    from AthenaCommon.Configurable import Configurable
+    Configurable.configurableRun3Behavior=1
+    log.setLevel(DEBUG)
+
+    ConfigFlags.LAr.doAlign=False
+    ConfigFlags.Input.Files = ["/eos/atlas/atlastier0/rucio/data20_calib/calibration_LArElec-Pedestal-32s-High-All/00374735/data20_calib.00374735.calibration_LArElec-Pedestal-32s-High-All.daq.RAW/data20_calib.00374735.calibration_LArElec-Pedestal-32s-High-All.daq.RAW._lb0000._SFO-3._0001.data"]
+    ConfigFlags.lock()
+
+    acc=LArRawCalibDataReadingCfg(ConfigFlags)
+    
+    from LArCabling.LArCablingConfig import LArOnOffIdMappingCfg 
+    acc.merge(LArOnOffIdMappingCfg(ConfigFlags))
+
+    f=open("LArRawCalibDataReading.pkl","wb")
+    acc.store(f)
+    f.close()
diff --git a/LArCalorimeter/LArCnv/LArByteStream/src/LArRawCalibDataReadingAlg.cxx b/LArCalorimeter/LArCnv/LArByteStream/src/LArRawCalibDataReadingAlg.cxx
new file mode 100644
index 00000000000..b46998e7653
--- /dev/null
+++ b/LArCalorimeter/LArCnv/LArByteStream/src/LArRawCalibDataReadingAlg.cxx
@@ -0,0 +1,313 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "LArRawCalibDataReadingAlg.h"
+#include "LArIdentifier/LArOnlineID.h"
+#include "ByteStreamCnvSvcBase/IROBDataProviderSvc.h" 
+#include "LArRawEvent/LArCalibDigitContainer.h"
+#include "LArRawEvent/LArAccumulatedDigitContainer.h"
+#include "LArRawEvent/LArAccumulatedCalibDigitContainer.h"
+#include "LArRawEvent/LArFebHeaderContainer.h"
+#include "eformat/Version.h"
+#include "eformat/index.h"
+
+#include "LArByteStream/LArRodBlockStructure.h"
+#include "LArByteStream/LArRodBlockAccumulatedV3.h"
+#include "LArByteStream/LArRodBlockCalibrationV3.h"
+#include "LArByteStream/LArRodBlockTransparentV0.h"
+
+LArRawCalibDataReadingAlg::LArRawCalibDataReadingAlg(const std::string& name, ISvcLocator* pSvcLocator) :  
+  AthReentrantAlgorithm(name, pSvcLocator) {}
+
+  StatusCode LArRawCalibDataReadingAlg::initialize() {
+
+  if (m_calibDigitKey.key().size()>0) {
+    ATH_CHECK(m_calibDigitKey.initialize());
+    m_doCalibDigits=true;
+  }
+  else {
+    m_doCalibDigits=false;
+  }
+
+  if (m_accDigitKey.key().size()>0) {
+    ATH_CHECK(m_accDigitKey.initialize());
+    m_doAccDigits=true;
+  }
+  else {
+    m_doAccDigits=false;
+  }
+
+  if (m_accCalibDigitKey.key().size()>0) {
+    ATH_CHECK(m_accCalibDigitKey.initialize());
+    m_doAccCalibDigits=true;
+  }
+  else {
+    m_doAccCalibDigits=false;
+  }
+
+  if (m_febHeaderKey.key().size()>0) {
+    ATH_CHECK(m_febHeaderKey.initialize());
+    m_doFebHeaders=true;
+  }
+  else {
+    m_doFebHeaders=false;
+  }
+  
+  if(!(m_doCalibDigits || m_doAccDigits || m_doAccCalibDigits)) {
+     ATH_MSG_FATAL("Needs ether CalibDigits or AccDigits  or AccCalibDigit Key");
+     return StatusCode::FAILURE;
+  }
+
+  if(m_doCalibDigits && m_doAccCalibDigits) {
+     ATH_MSG_FATAL("Could not have both CalibDigits, AccCalibDigits Key");
+     return StatusCode::FAILURE;
+  }
+
+  if(m_doAccDigits && (m_doCalibDigits || m_doAccCalibDigits)) {
+     ATH_MSG_FATAL("Could not have AccDigits with Calib Key");
+     return StatusCode::FAILURE;
+  }
+
+  ATH_CHECK(m_robDataProviderSvc.retrieve());
+  ATH_CHECK(detStore()->retrieve(m_onlineId,"LArOnlineID"));  
+  return StatusCode::SUCCESS;
+}     
+  
+StatusCode LArRawCalibDataReadingAlg::execute(const EventContext& ctx) const {
+  LArCalibDigitContainer* cdigits=nullptr;
+  LArAccumulatedDigitContainer* accdigits=nullptr;
+  LArAccumulatedCalibDigitContainer* caccdigits=nullptr;
+  LArFebHeaderContainer* febHeaders=nullptr;
+
+  if (m_doCalibDigits) {
+    SG::WriteHandle<LArCalibDigitContainer> cdigitsHdl(m_calibDigitKey,ctx);
+    ATH_CHECK(cdigitsHdl.record(std::make_unique<LArCalibDigitContainer>()));
+    cdigits=cdigitsHdl.ptr();
+    cdigits->reserve(200000); //Enough space for the full calo
+  }
+
+  if (m_doAccDigits) {
+    SG::WriteHandle<LArAccumulatedDigitContainer> accdigitsHdl(m_accDigitKey,ctx);
+    ATH_CHECK(accdigitsHdl.record(std::make_unique<LArAccumulatedDigitContainer>()));
+    accdigits=accdigitsHdl.ptr();
+    accdigits->reserve(200000); //Enough space for the full calo
+  }
+
+  if (m_doAccCalibDigits) {
+    SG::WriteHandle<LArAccumulatedCalibDigitContainer> caccdigitsHdl(m_accCalibDigitKey,ctx);
+    ATH_CHECK(caccdigitsHdl.record(std::make_unique<LArAccumulatedCalibDigitContainer>()));
+    caccdigits=caccdigitsHdl.ptr();
+    caccdigits->reserve(200000); //Enough space for the full calo
+  }
+
+  if (m_doFebHeaders) {
+    SG::WriteHandle<LArFebHeaderContainer> febHeadersHdl(m_febHeaderKey,ctx);
+    ATH_CHECK(febHeadersHdl.record(std::make_unique<LArFebHeaderContainer>()));
+    febHeaders=febHeadersHdl.ptr();
+    febHeaders->reserve(1524); //Total number of LAr Front End Boards
+  }
+
+  //Get full events and filter out LAr ROBs
+  const RawEvent* fullEvent=m_robDataProviderSvc->getEvent(ctx);
+  std::map<eformat::SubDetectorGroup, std::vector<const uint32_t*> > rawEventTOC;
+  eformat::helper::build_toc(*fullEvent, rawEventTOC);
+  auto larRobs=rawEventTOC.find(eformat::LAR);
+  if (larRobs==rawEventTOC.end()) {
+     ATH_MSG_DEBUG("No LAr data found in this event.");
+     return StatusCode::SUCCESS;
+  } 
+  
+  
+  std::unique_ptr<LArRodBlockStructure> rodBlock;
+  uint16_t rodMinorVersion=0x0;
+  uint32_t rodBlockType=0x0;
+
+
+  for (const uint32_t* robPtr : larRobs->second) {
+    OFFLINE_FRAGMENTS_NAMESPACE::ROBFragment rob(robPtr);
+    ATH_MSG_VERBOSE("Decoding ROB fragment 0x" << std::hex << rob.rob_source_id () << " with " << std::dec << rob.rod_fragment_size_word() << "ROB words");
+
+    if (rob.rod_fragment_size_word() <3) {
+      ATH_MSG_ERROR("Encountered corrupt ROD fragment, less than 3 words!");
+      if (m_failOnCorruption) {
+	return StatusCode::FAILURE;
+      }else 
+	continue;
+    }
+    
+     eformat::helper::Version ver(rob.rod_version());
+    //(re-)init rodBlock only once per event or if (very unlikly or even impossible) some FEBs have a differnt firmware
+    if (rodBlock==nullptr || rodMinorVersion !=ver.minor_version() || rodBlockType!=(rob.rod_detev_type()&0xff)) {
+      rodMinorVersion=ver.minor_version();
+      rodBlockType=rob.rod_detev_type()&0xff;
+      ATH_MSG_VERBOSE("Found version " << rodMinorVersion <<  " of Rod Block Type  " <<  rodBlockType);
+      if (rodBlockType==10) { // Accumulated calib. digits
+	  rodBlock.reset(new LArRodBlockAccumulatedV3);
+      }//end of rodBlockType ==10
+      else if (rodBlockType==7 || rodBlockType==2) { // Calib. digits
+         if(rodMinorVersion>=6) {
+            rodBlock.reset(new LArRodBlockCalibrationV3);
+         } else {
+            ATH_MSG_ERROR("Found unsupported ROD Block version " << rodMinorVersion
+                        << " of ROD block type " << rodBlockType);
+            return m_failOnCorruption ? StatusCode::FAILURE : StatusCode::SUCCESS;
+         }
+      } else {
+	ATH_MSG_ERROR("Found unsupported Rod block type " << rodBlockType);
+	return m_failOnCorruption ? StatusCode::FAILURE : StatusCode::SUCCESS;
+      }
+    }//End if need to re-init RodBlock
+
+    const uint32_t* pData=rob.rod_data();
+    const uint32_t  nData=rob.rod_ndata();
+    if (!rodBlock->setFragment(pData,nData)) {
+      ATH_MSG_ERROR("Failed to assign fragment pointer to LArRodBlockStructure");
+      return StatusCode::FAILURE;
+    }
+
+    if(m_verifyChecksum) {
+      const uint32_t onsum  = rodBlock->onlineCheckSum();
+      const uint32_t offsum = rodBlock->offlineCheckSum();
+      if(onsum!=offsum) {
+	ATH_MSG_ERROR("Checksum error:");
+	ATH_MSG_ERROR("online checksum  = 0x" << MSG::hex << onsum);
+	ATH_MSG_ERROR("offline checksum = 0x" << MSG::hex << offsum << MSG::dec);
+	if (m_failOnCorruption) 
+	  return StatusCode::FAILURE;
+	else
+	  continue; //Jump to the next ROD-block
+      }
+    }
+
+    //Loop over FEBs in ROD:
+    do {
+      HWIdentifier fId(Identifier32(rodBlock->getFEBID()));
+      if (!m_onlineId->isValidId(fId)) {
+	ATH_MSG_ERROR("Invalid FEB identifer 0x" << std::hex << fId.get_identifier32().get_compact()); 
+	if (m_failOnCorruption) 
+	  return StatusCode::FAILURE;
+	else
+	  continue;
+      }
+      const int NthisFebChannel=m_onlineId->channelInSlotMax(fId);
+
+      //Decode LArCalibDigits (if requested)
+      if (m_doCalibDigits) {
+	uint32_t gain;
+        uint16_t dac;
+        uint16_t delay;
+        bool ispulsed;
+	int fcNb;
+	std::vector<short> samples;
+	while (rodBlock->getNextRawData(fcNb,samples,gain)) {
+	  if (fcNb>=NthisFebChannel)
+	    continue;
+	  if (samples.size()==0) continue; // Ignore missing cells
+          dac = rodBlock->getDAC();
+          delay = rodBlock->getDelay();
+          ispulsed = rodBlock->getPulsed(fcNb);
+	  HWIdentifier cId = m_onlineId->channel_Id(fId,fcNb);
+	  cdigits->emplace_back(new LArCalibDigit(cId, (CaloGain::CaloGain)gain, std::move(samples), dac, delay, ispulsed));
+	  samples.clear();
+	}//end getNextRawData loop
+      }//end if m_doCalibDigits
+
+      //Decode LArAccumulatedDigits (if requested)
+      if (m_doAccDigits && rodBlockType==10) {
+	uint32_t gain;
+	int fcNb;
+	std::vector<uint32_t> samplesSum;
+	std::vector<uint32_t> samples2Sum;
+        uint32_t nTrigger;
+	while (rodBlock->getNextAccumulatedDigit(fcNb,samplesSum,samples2Sum,gain)) {
+	  if (fcNb>=NthisFebChannel)
+	    continue;
+	  if (samplesSum.size()==0 || samples2Sum.size()==0) continue; // Ignore missing cells
+          nTrigger = rodBlock->getNTrigger();
+	  HWIdentifier cId = m_onlineId->channel_Id(fId,fcNb);
+	  accdigits->emplace_back(new LArAccumulatedDigit(cId, (CaloGain::CaloGain)gain, std::move(samplesSum), std::move(samples2Sum), nTrigger));
+	  samplesSum.clear();
+	  samples2Sum.clear();
+	}//end getNext loop
+      }//end if m_doAccDigits
+
+      //Decode LArAccumulatedCalibDigits (if requested)
+      if (m_doAccCalibDigits) {
+	uint32_t gain;
+	uint32_t itmp;
+        uint16_t dac;
+        uint16_t delay;
+        uint16_t nstep;
+        uint16_t istep;
+        bool ispulsed;
+	int fcNb;
+	std::vector<uint32_t> samplesSum;
+	std::vector<uint32_t> samples2Sum;
+        uint32_t nTrigger;
+	while (rodBlock->getNextAccumulatedCalibDigit(fcNb,samplesSum,samples2Sum,itmp,gain)) {
+	  if (fcNb>=NthisFebChannel)
+	    continue;
+	  if (samplesSum.size()==0 || samples2Sum.size()==0) continue; // Ignore missing cells
+          dac = rodBlock->getDAC();
+          delay = rodBlock->getDelay();
+          ispulsed = rodBlock->getPulsed(fcNb);
+          nTrigger = rodBlock->getNTrigger();
+          nstep = rodBlock->getNStep();
+          istep = rodBlock->getStepIndex();
+	  HWIdentifier cId = m_onlineId->channel_Id(fId,fcNb);
+	  caccdigits->emplace_back(new LArAccumulatedCalibDigit(cId, (CaloGain::CaloGain)gain, std::move(samplesSum), std::move(samples2Sum), nTrigger, dac, delay, ispulsed, nstep, istep));
+	  samplesSum.clear();
+	  samples2Sum.clear();
+	}//end getNext loop
+      }//end if m_doAccDigits
+
+      //Decode FebHeaders (if requested)
+      if (m_doFebHeaders) {
+	std::unique_ptr<LArFebHeader> larFebHeader(new LArFebHeader(fId));
+	larFebHeader->SetFormatVersion(rob.rod_version());
+	larFebHeader->SetSourceId(rob.rod_source_id());
+	larFebHeader->SetRunNumber(rob.rod_run_no());
+	larFebHeader->SetELVL1Id(rob.rod_lvl1_id());
+	larFebHeader->SetBCId(rob.rod_bc_id());
+	larFebHeader->SetLVL1TigType(rob.rod_lvl1_trigger_type());
+	larFebHeader->SetDetEventType(rob.rod_detev_type());
+  
+	//set DSP data
+	const unsigned nsample=rodBlock->getNumberOfSamples();
+	larFebHeader->SetRodStatus(rodBlock->getStatus());
+	larFebHeader->SetDspCodeVersion(rodBlock->getDspCodeVersion()); 
+	larFebHeader->SetDspEventCounter(rodBlock->getDspEventCounter()); 
+	larFebHeader->SetRodResults1Size(rodBlock->getResults1Size()); 
+	larFebHeader->SetRodResults2Size(rodBlock->getResults2Size()); 
+	larFebHeader->SetRodRawDataSize(rodBlock->getRawDataSize()); 
+	larFebHeader->SetNbSweetCells1(rodBlock->getNbSweetCells1()); 
+	larFebHeader->SetNbSweetCells2(rodBlock->getNbSweetCells2()); 
+	larFebHeader->SetNbSamples(nsample); 
+	larFebHeader->SetOnlineChecksum(rodBlock->onlineCheckSum());
+	larFebHeader->SetOfflineChecksum(rodBlock->offlineCheckSum());
+
+	if(!rodBlock->hasControlWords()) {
+	  larFebHeader->SetFebELVL1Id(rob.rod_lvl1_id());
+	  larFebHeader->SetFebBCId(rob.rod_bc_id());
+	} else {
+	  const uint16_t evtid = rodBlock->getCtrl1(0) & 0x1f;
+	  const uint16_t bcid  = rodBlock->getCtrl2(0) & 0x1fff;
+	  larFebHeader->SetFebELVL1Id(evtid);
+	  larFebHeader->SetFebBCId(bcid);
+	  for(int iadc=0;iadc<16;iadc++) {
+	    larFebHeader->SetFebCtrl1(rodBlock->getCtrl1(iadc));
+	    larFebHeader->SetFebCtrl2(rodBlock->getCtrl2(iadc));
+	    larFebHeader->SetFebCtrl3(rodBlock->getCtrl3(iadc));
+	  }
+	  for(unsigned int i = 0; i<nsample; i++ ) {
+	    larFebHeader->SetFebSCA(rodBlock->getRadd(0,i) & 0xff);
+	  }
+	}//end else no control words
+	febHeaders->push_back(std::move(larFebHeader));
+      }//end if m_doFebHeaders
+
+    }while (rodBlock->nextFEB()); //Get NextFeb
+  } //end loop over ROBs
+  return StatusCode::SUCCESS;
+}
diff --git a/LArCalorimeter/LArCnv/LArByteStream/src/LArRawCalibDataReadingAlg.h b/LArCalorimeter/LArCnv/LArByteStream/src/LArRawCalibDataReadingAlg.h
new file mode 100644
index 00000000000..1c5b1121fb7
--- /dev/null
+++ b/LArCalorimeter/LArCnv/LArByteStream/src/LArRawCalibDataReadingAlg.h
@@ -0,0 +1,55 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef LARBYTESTREAM_LARRAWCALIBDATAREADINDINGALG_H
+#define LARBYTESTREAM_LARRAWCALIBDATAREADINDINGALG_H
+
+#include "AthenaBaseComps/AthReentrantAlgorithm.h"
+#include "StoreGate/WriteHandle.h"
+#include "StoreGate/ReadCondHandle.h"
+#include "LArCabling/LArOnOffIdMapping.h"
+#include "GaudiKernel/ServiceHandle.h"
+
+
+//Event classes
+class LArCalibDigitContainer;
+class LArAccumulatedDigitContainer;
+class LArAccumulatedCalibDigitContainer;
+class LArFebHeaderContainer;
+class LArOnlineID;
+class IROBDataProviderSvc;
+
+class LArRawCalibDataReadingAlg : public  AthReentrantAlgorithm {
+ public:
+  LArRawCalibDataReadingAlg(const std::string& name, ISvcLocator* pSvcLocator);
+
+  StatusCode initialize() override;
+  StatusCode execute(const EventContext& ctx) const override;
+
+ private:
+  //Event output:
+  SG::WriteHandleKey<LArCalibDigitContainer> m_calibDigitKey{this,"LArCalibDigitKey",""};
+  SG::WriteHandleKey<LArAccumulatedDigitContainer> m_accDigitKey{this,"LArAccDigitKey",""};
+  SG::WriteHandleKey<LArAccumulatedCalibDigitContainer> m_accCalibDigitKey{this,"LArAccCalibDigitKey",""};
+  SG::WriteHandleKey<LArFebHeaderContainer> m_febHeaderKey{this,"LArFebHeaderKey",""};
+    
+  //Service providing the input data
+  ServiceHandle<IROBDataProviderSvc> m_robDataProviderSvc{this,"ROBDataProviderSvc","ROBDataProviderSvc"};
+  
+  //Other properties:
+  BooleanProperty m_verifyChecksum{this,"VerifyChecksum",true,"Calculate and compare checksums to detect data transmission errors"}; 
+  BooleanProperty m_failOnCorruption{this,"FailOnCorruption",true,"Return FAILURE if data corruption is found"};
+
+  //Identifier helper
+  const LArOnlineID* m_onlineId=nullptr;
+
+  //Switches set in initialize() based of SG keys of output object
+  bool m_doCalibDigits;
+  bool m_doAccDigits;
+  bool m_doAccCalibDigits;
+  bool m_doFebHeaders;
+ 
+};
+
+#endif
diff --git a/LArCalorimeter/LArCnv/LArByteStream/src/components/LArByteStream_entries.cxx b/LArCalorimeter/LArCnv/LArByteStream/src/components/LArByteStream_entries.cxx
index a60b8cb93d2..29f49925929 100644
--- a/LArCalorimeter/LArCnv/LArByteStream/src/components/LArByteStream_entries.cxx
+++ b/LArCalorimeter/LArCnv/LArByteStream/src/components/LArByteStream_entries.cxx
@@ -9,6 +9,7 @@
 #include "LArByteStream/LArABBADecoder.h"
 #include "ByteStreamCnvSvcBase/CollectionByteStreamCnv.h"
 #include "../LArRawDataReadingAlg.h"
+#include "../LArRawCalibDataReadingAlg.h"
 //#include "LArByteStream/LArRawChannelCollByteStreamTool.h"
 
 // Containers 
@@ -16,6 +17,7 @@ DECLARE_COMPONENT( LArRawDataContByteStreamTool )
 DECLARE_COMPONENT( LArRodDecoder )
 DECLARE_COMPONENT( LArABBADecoder )
 DECLARE_COMPONENT( LArRawDataReadingAlg )
+DECLARE_COMPONENT( LArRawCalibDataReadingAlg )
 
 DECLARE_CONVERTER( LArRawChannelContByteStreamCnv )
 DECLARE_CONVERTER( LArDigitContByteStreamCnv )
diff --git a/LArCalorimeter/LArMonitoring/python/LArCalibMonAlg.py b/LArCalorimeter/LArMonitoring/python/LArCalibMonAlg.py
new file mode 100644
index 00000000000..bb8176002ba
--- /dev/null
+++ b/LArCalorimeter/LArMonitoring/python/LArCalibMonAlg.py
@@ -0,0 +1,88 @@
+#
+#  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+#
+
+def LArCalibMonConfig(inputFlags,gain="",doAccDigit=False,doCalibDigit=False,doAccCalibDigit=False):
+
+    from AthenaMonitoring import AthMonitorCfgHelper
+    helper = AthMonitorCfgHelper(inputFlags,'LArCalibMonCfg')
+
+    from LArMonitoring.GlobalVariables import lArDQGlobals
+
+    from AthenaConfiguration.ComponentFactory import CompFactory
+    larCalibMonAlg = helper.addAlgorithm(CompFactory.LArCalibPedMonAlg,'larCalibMonAlg')
+    if gain != "":
+       if doAccDigit:
+          larCalibMonAlg.LArAccumulatedDigitContainerKey=gain
+       elif doAccCalibDigit:
+          larCalibMonAlg.LArAccumulatedCalibDigitContainerKey=gain
+       elif doCalibDigit:
+          larCalibMonAlg.LArCalibDigitContainerKey=gain
+
+    GroupName="CalibMonGroup"
+
+    larCalibMonAlg.LArPedGroupName=GroupName
+
+    Group = helper.addGroup(
+        larCalibMonAlg,
+        GroupName,
+        '/LAr/'+GroupName+'/'
+    )
+
+
+    #Summary histos
+    summary_hist_path='Summary/'
+    
+
+    Group.defineHistogram('nbChan;NbOfReadoutChannelsGlobal', 
+                                  title='# of readout channels',
+                                  type='TH1I',
+                                  path=summary_hist_path,
+                                  xbins=lArDQGlobals.N_FEB*lArDQGlobals.FEB_N_channels+5, 
+                                  xmin=-0.5, xmax=lArDQGlobals.N_FEB*lArDQGlobals.FEB_N_channels+4.5)
+
+    return helper.result()
+
+    
+
+if __name__=='__main__':
+
+   from AthenaConfiguration.AllConfigFlags import ConfigFlags
+   from AthenaCommon.Logging import log
+   from AthenaCommon.Constants import DEBUG
+   from AthenaCommon.Configurable import Configurable
+   Configurable.configurableRun3Behavior=1
+   log.setLevel(DEBUG)
+
+
+   from LArMonitoring.LArMonConfigFlags import createLArMonConfigFlags
+   createLArMonConfigFlags()
+
+   ConfigFlags.Input.Files = ["/eos/atlas/atlastier0/rucio/data20_calib/calibration_LArElec-Delay-32s-Medium-Em/00374740/data20_calib.00374740.calibration_LArElec-Delay-32s-Medium-Em.daq.RAW/data20_calib.00374740.calibration_LArElec-Delay-32s-Medium-Em.daq.RAW._lb0000._SFO-2._0001.data"]
+   ConfigFlags.Output.HISTFileName = 'LArCalibMonOutput.root'
+   ConfigFlags.DQ.enableLumiAccess = False
+   ConfigFlags.DQ.useTrigger = False
+   ConfigFlags.Beam.Type = 'collisions'
+   ConfigFlags.DQ.DataType = 'collisions'
+   ConfigFlags.AtlasVersion = 'ATLAS-R2-2016-01-00-01'
+   ConfigFlags.Detector.GeometryCSC=False
+   ConfigFlags.Detector.GeometrysTGC=False
+   ConfigFlags.Detector.GeometryMM=False
+   ConfigFlags.lock()
+
+   from AthenaConfiguration.MainServicesConfig import MainServicesSerialCfg
+   cfg = MainServicesSerialCfg()
+
+   from LArByteStream.LArRawCalibDataReadingConfig import LArRawCalibDataReadingCfg
+   cfg.merge(LArRawCalibDataReadingCfg(ConfigFlags,gain="MEDIUM",doAccCalibDigit=True))
+
+   cfg.merge(LArCalibMonConfig(ConfigFlags, gain="MEDIUM",doAccCalibDigit=True))
+
+   cfg.printConfig()
+
+   ConfigFlags.dump()
+   f=open("LArCalibPedMon.pkl","w")
+   cfg.store(f)
+   f.close()
+
+   cfg.run(500,OutputLevel=DEBUG)
diff --git a/LArCalorimeter/LArMonitoring/python/LArCalibPedMonAlg.py b/LArCalorimeter/LArMonitoring/python/LArCalibPedMonAlg.py
new file mode 100644
index 00000000000..ed2b1451f3f
--- /dev/null
+++ b/LArCalorimeter/LArMonitoring/python/LArCalibPedMonAlg.py
@@ -0,0 +1,88 @@
+#
+#  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+#
+
+def LArCalibPedMonConfig(inputFlags,gain="",doAccDigit=False,doCalibDigit=False,doAccCalibDigit=False):
+
+    from AthenaMonitoring import AthMonitorCfgHelper
+    helper = AthMonitorCfgHelper(inputFlags,'LArCalibPedMonCfg')
+
+    from LArMonitoring.GlobalVariables import lArDQGlobals
+
+    from AthenaConfiguration.ComponentFactory import CompFactory
+    larPedMonAlg = helper.addAlgorithm(CompFactory.LArCalibPedMonAlg,'larCalibPedMonAlg')
+    if gain != "":
+       if doAccDigit:
+          larPedMonAlg.LArAccumulatedDigitContainerKey=gain
+       elif doAccCalibDigit:
+          larPedMonAlg.LArAccumulatedCalibDigitContainerKey=gain
+       elif doCalibDigit:
+          larPedMonAlg.LArCalibDigitContainerKey=gain
+
+    GroupName="PedMonGroup"
+
+    larPedMonAlg.LArPedGroupName=GroupName
+
+    Group = helper.addGroup(
+        larPedMonAlg,
+        GroupName,
+        '/LAr/'+GroupName+'/'
+    )
+
+
+    #Summary histos
+    summary_hist_path='Summary/'
+    
+
+    Group.defineHistogram('nbChan;NbOfReadoutChannelsGlobal', 
+                                  title='# of readout channels',
+                                  type='TH1I',
+                                  path=summary_hist_path,
+                                  xbins=lArDQGlobals.N_FEB*lArDQGlobals.FEB_N_channels+5, 
+                                  xmin=-0.5, xmax=lArDQGlobals.N_FEB*lArDQGlobals.FEB_N_channels+4.5)
+
+    return helper.result()
+
+    
+
+if __name__=='__main__':
+
+   from AthenaConfiguration.AllConfigFlags import ConfigFlags
+   from AthenaCommon.Logging import log
+   from AthenaCommon.Constants import DEBUG
+   from AthenaCommon.Configurable import Configurable
+   Configurable.configurableRun3Behavior=1
+   log.setLevel(DEBUG)
+
+
+   from LArMonitoring.LArMonConfigFlags import createLArMonConfigFlags
+   createLArMonConfigFlags()
+
+   ConfigFlags.Input.Files = ["/eos/atlas/atlastier0/rucio/data20_calib/calibration_LArElec-Pedestal-32s-High-All/00374735/data20_calib.00374735.calibration_LArElec-Pedestal-32s-High-All.daq.RAW/data20_calib.00374735.calibration_LArElec-Pedestal-32s-High-All.daq.RAW._lb0000._SFO-3._0001.data"]
+   ConfigFlags.Output.HISTFileName = 'LArCalibPedMonOutput.root'
+   ConfigFlags.DQ.enableLumiAccess = False
+   ConfigFlags.DQ.useTrigger = False
+   ConfigFlags.Beam.Type = 'collisions'
+   ConfigFlags.DQ.DataType = 'collisions'
+   ConfigFlags.AtlasVersion = 'ATLAS-R2-2016-01-00-01'
+   ConfigFlags.Detector.GeometryCSC=False
+   ConfigFlags.Detector.GeometrysTGC=False
+   ConfigFlags.Detector.GeometryMM=False
+   ConfigFlags.lock()
+
+   from AthenaConfiguration.MainServicesConfig import MainServicesSerialCfg
+   cfg = MainServicesSerialCfg()
+
+   from LArByteStream.LArRawCalibDataReadingConfig import LArRawCalibDataReadingCfg
+   cfg.merge(LArRawCalibDataReadingCfg(ConfigFlags,gain="HIGH",doAccDigit=True))
+
+   cfg.merge(LArCalibPedMonConfig(ConfigFlags, gain="HIGH",doAccDigit=True))
+
+   cfg.printConfig()
+
+   ConfigFlags.dump()
+   f=open("LArCalibPedMon.pkl","w")
+   cfg.store(f)
+   f.close()
+
+   cfg.run(500,OutputLevel=DEBUG)
diff --git a/LArCalorimeter/LArMonitoring/python/LArFEBMonAlg.py b/LArCalorimeter/LArMonitoring/python/LArFEBMonAlg.py
index 882010a57f8..233d820cc0f 100644
--- a/LArCalorimeter/LArMonitoring/python/LArFEBMonAlg.py
+++ b/LArCalorimeter/LArMonitoring/python/LArFEBMonAlg.py
@@ -22,6 +22,11 @@ def LArFEBMonConfig(inputFlags, cellDebug=False, dspDebug=False):
     larFEBMonAlg.SubDetNames=lArDQGlobals.SubDet
     larFEBMonAlg.Streams=lArDQGlobals.defaultStreamNames
 
+    # adding LArFebErrorSummary algo
+    from LArROD.LArFebErrorSummaryMakerConfig import LArFebErrorSummaryMakerCfg
+    acc = LArFebErrorSummaryMakerCfg(inputFlags)
+    helper.resobj.merge(acc)
+
     if "COMP200" not in inputFlags.IOVDb.DatabaseInstance:
        iovDbSvc=helper.resobj.getService("IOVDbSvc")
        condLoader=helper.resobj.getCondAlgo("CondInputLoader")
@@ -38,14 +43,6 @@ def LArFEBMonConfig(inputFlags, cellDebug=False, dspDebug=False):
        helper.resobj.addFolderList(inputFlags,[(fld,db,obj)])
        larFEBMonAlg.keyDSPThresholds="LArDSPThresholds"
 
-    #from AthenaCommon.Constants import VERBOSE
-    #larFEBMonAlg.OutputLevel=VERBOSE
-
-    # adding LArFebErrorSummary algo
-    from LArROD.LArFebErrorSummaryMakerConfig import LArFebErrorSummaryMakerCfg
-    acc = LArFebErrorSummaryMakerCfg(inputFlags)
-    helper.resobj.merge(acc)
-
     Group = helper.addGroup(
         larFEBMonAlg,
         GroupName,
@@ -361,7 +358,7 @@ if __name__=='__main__':
 
    from AthenaConfiguration.AllConfigFlags import ConfigFlags
    from AthenaCommon.Logging import log
-   from AthenaCommon.Constants import DEBUG
+   from AthenaCommon.Constants import DEBUG,WARNING
    from AthenaCommon.Configurable import Configurable
    Configurable.configurableRun3Behavior=1
    log.setLevel(DEBUG)
@@ -370,18 +367,20 @@ if __name__=='__main__':
    from LArMonitoring.LArMonConfigFlags import createLArMonConfigFlags
    createLArMonConfigFlags()
 
-   from AthenaConfiguration.TestDefaults import defaultTestFiles
-   ConfigFlags.Input.Files = defaultTestFiles.RAW
+   ConfigFlags.Input.Files = ["/cvmfs/atlas-nightlies.cern.ch/repo/data/data-art/Tier0ChainTests/data17_13TeV.00330470.physics_Main.daq.RAW._lb0310._SFO-1._0001.data",]
 
    ConfigFlags.Output.HISTFileName = 'LArFEBMonOutput.root'
-   ConfigFlags.DQ.enableLumiAccess = True
-   ConfigFlags.DQ.useTrigger = True
+   ConfigFlags.DQ.enableLumiAccess = False
+   ConfigFlags.DQ.useTrigger = False
    ConfigFlags.Beam.Type = 'collisions'
    ConfigFlags.lock()
 
+   from AthenaConfiguration.MainServicesConfig import MainServicesSerialCfg
+   cfg = MainServicesSerialCfg()
+
 
    from CaloRec.CaloRecoConfig import CaloRecoCfg
-   cfg=CaloRecoCfg(ConfigFlags)
+   cfg.merge(CaloRecoCfg(ConfigFlags))
 
    #from CaloD3PDMaker.CaloD3PDConfig import CaloD3PDCfg,CaloD3PDAlg
    #cfg.merge(CaloD3PDCfg(ConfigFlags, filename=ConfigFlags.Output.HISTFileName, streamname='CombinedMonitoring'))
@@ -396,4 +395,4 @@ if __name__=='__main__':
    cfg.store(f)
    f.close()
 
-   #cfg.run(100,OutputLevel=WARNING)
+   cfg.run(10,OutputLevel=WARNING)
diff --git a/LArCalorimeter/LArMonitoring/src/LArCalibPedMonAlg.cxx b/LArCalorimeter/LArMonitoring/src/LArCalibPedMonAlg.cxx
new file mode 100644
index 00000000000..757c2648d57
--- /dev/null
+++ b/LArCalorimeter/LArMonitoring/src/LArCalibPedMonAlg.cxx
@@ -0,0 +1,117 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "LArCalibPedMonAlg.h"
+
+
+/*---------------------------------------------------------*/
+LArCalibPedMonAlg::LArCalibPedMonAlg(const std::string& name,ISvcLocator* pSvcLocator )
+  : AthMonitorAlgorithm(name,pSvcLocator)
+{}
+
+/*---------------------------------------------------------*/
+LArCalibPedMonAlg::~LArCalibPedMonAlg()
+{}
+
+/*---------------------------------------------------------*/
+StatusCode 
+LArCalibPedMonAlg::initialize()
+{
+  ATH_MSG_INFO( "Initialize LArCalibPedMonAlg"  );
+
+  ATH_MSG_INFO( "m_accDigitContainerKey.empty() " << m_accDigitContainerKey.empty()
+        );
+  if(!m_calibDigitContainerKey.empty()) {
+    ATH_CHECK( m_calibDigitContainerKey.initialize() );
+  } else if(!m_accDigitContainerKey.empty()) {
+    ATH_CHECK( m_accDigitContainerKey.initialize() );
+  } else if(!m_accCalibDigitContainerKey.empty()) {
+    ATH_CHECK( m_accCalibDigitContainerKey.initialize() );
+  } else {
+     ATH_MSG_FATAL("Either LArCalibDigitContainerKey or LArAccumulatedDigitContainerKey or LArAccumulatedCalibDigitContainerKey must be set");
+     return StatusCode::FAILURE;
+  }
+
+  return AthMonitorAlgorithm::initialize();
+}
+
+
+/*---------------------------------------------------------*/
+StatusCode 
+LArCalibPedMonAlg::fillHistograms( const EventContext& ctx ) const
+{
+
+  ATH_MSG_DEBUG( "in fillHists()"  );
+  
+  SG::ReadHandle<LArCalibDigitContainer> pLArCalibDigitContainer;
+  SG::ReadHandle<LArAccumulatedDigitContainer> pLArAccDigitContainer;
+  SG::ReadHandle<LArAccumulatedCalibDigitContainer> pLArAccCalibDigitContainer;
+
+  std::unordered_set<unsigned int> chanids;
+
+  if(!m_calibDigitContainerKey.empty()) {
+    pLArCalibDigitContainer= SG::ReadHandle<LArCalibDigitContainer>{m_calibDigitContainerKey,ctx};
+    if(pLArCalibDigitContainer.isValid()){
+       ATH_MSG_DEBUG("Got LArCalibDigitContainer with key "<< m_calibDigitContainerKey.key());
+    } else {
+       ATH_MSG_WARNING("Do not have LArCalibDigitContainer with key "<< m_calibDigitContainerKey.key());
+    }  
+  }
+
+  if(!m_accDigitContainerKey.empty()) {
+    pLArAccDigitContainer= SG::ReadHandle<LArAccumulatedDigitContainer>{m_accDigitContainerKey,ctx};
+    if(pLArAccDigitContainer.isValid()){
+       ATH_MSG_DEBUG("Got LArAccumulatedDigitContainer with key "<< m_accDigitContainerKey.key());
+    } else {
+       ATH_MSG_WARNING("Do not have LArAccumulatedDigitContainer with key "<< m_accDigitContainerKey.key());
+    }  
+
+    if(pLArAccDigitContainer->empty()) return StatusCode::SUCCESS; // Nothing to fill
+
+    LArAccumulatedDigitContainer::const_iterator itDig = pLArAccDigitContainer->begin();
+    LArAccumulatedDigitContainer::const_iterator itDig_e = pLArAccDigitContainer->end();
+    const LArAccumulatedDigit* pLArDigit;
+    for ( ; itDig!=itDig_e;++itDig) {
+        pLArDigit = *itDig;
+        unsigned int id = (pLArDigit->hardwareID()).get_identifier32().get_compact();
+        if(chanids.find(id) == chanids.end()) chanids.emplace(id);
+    }
+
+    ATH_MSG_DEBUG("Filling nbChan: "<<chanids.size());
+
+    auto nbchan = Monitored::Scalar<unsigned int>("nbChan",chanids.size());
+    fill(m_MonGroupName,nbchan);
+    
+  }
+
+  if(!m_accCalibDigitContainerKey.empty()) {
+    pLArAccCalibDigitContainer= SG::ReadHandle<LArAccumulatedCalibDigitContainer>{m_accCalibDigitContainerKey,ctx};
+    if(pLArAccCalibDigitContainer.isValid()){
+       ATH_MSG_DEBUG("Got LArAccumulatedCalibDigitContainer with key "<< m_accCalibDigitContainerKey.key());
+    } else {
+       ATH_MSG_WARNING("Do not have LArAcumulatedCalibDigitContainer with key "<< m_accCalibDigitContainerKey.key());
+    }  
+
+    if(pLArAccCalibDigitContainer->empty()) return StatusCode::SUCCESS; // Nothing to fill
+
+    LArAccumulatedCalibDigitContainer::const_iterator itDig = pLArAccCalibDigitContainer->begin();
+    LArAccumulatedCalibDigitContainer::const_iterator itDig_e = pLArAccCalibDigitContainer->end();
+    const LArAccumulatedCalibDigit* pLArDigit;
+    for ( ; itDig!=itDig_e;++itDig) {
+        pLArDigit = *itDig;
+        unsigned int id = (pLArDigit->hardwareID()).get_identifier32().get_compact();
+        if(chanids.find(id) == chanids.end()) chanids.emplace(id);
+    }
+
+    ATH_MSG_DEBUG("Filling nbChan: "<<chanids.size());
+
+    auto nbchan = Monitored::Scalar<unsigned int>("nbChan",chanids.size());
+    fill(m_MonGroupName,nbchan);
+    
+  }
+  return StatusCode::SUCCESS;
+}
+
+
+
diff --git a/LArCalorimeter/LArMonitoring/src/LArCalibPedMonAlg.h b/LArCalorimeter/LArMonitoring/src/LArCalibPedMonAlg.h
new file mode 100644
index 00000000000..e97cb61443f
--- /dev/null
+++ b/LArCalorimeter/LArMonitoring/src/LArCalibPedMonAlg.h
@@ -0,0 +1,50 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef LARCALIBPEDMONALG_H
+#define LARCALIBPEDMONALG_H
+
+#include "AthenaMonitoring/AthMonitorAlgorithm.h"
+#include "AthenaMonitoringKernel/Monitored.h"
+
+#include "StoreGate/ReadHandleKey.h"
+#include "LArRawEvent/LArCalibDigitContainer.h"
+#include "LArRawEvent/LArAccumulatedDigitContainer.h"
+#include "LArRawEvent/LArAccumulatedCalibDigitContainer.h"
+
+#include <string>
+
+
+
+
+class LArCalibPedMonAlg: public AthMonitorAlgorithm
+{
+ public:
+  LArCalibPedMonAlg(const std::string& name,ISvcLocator* pSvcLocator );		      
+
+  /** @brief Default destructor */
+  virtual ~LArCalibPedMonAlg();
+
+  /** @brief Overwrite dummy method from AlgTool */
+  virtual StatusCode initialize() override;
+
+
+  /** Called each event */
+  virtual StatusCode fillHistograms( const EventContext& ctx ) const override;
+
+ private:
+
+  // keys to access info
+  SG::ReadHandleKey<LArCalibDigitContainer> m_calibDigitContainerKey{this,"LArCalibDigitContainerKey","","SG key of LArCalibDigitContainer read from Bytestream"};
+  SG::ReadHandleKey<LArAccumulatedDigitContainer> m_accDigitContainerKey{this,"LArAccumulatedDigitContainerKey","","SG key of LArAccumulatedDigitContainer read from Bytestream"};
+  SG::ReadHandleKey<LArAccumulatedCalibDigitContainer> m_accCalibDigitContainerKey{this,"LArAccumulatedCalibDigitContainerKey","","SG key of LArAccumulatedCalibDigitContainer read from Bytestream"};
+
+  // Properties
+  //MonGroup(s) name
+  Gaudi::Property<std::string> m_MonGroupName {this,"LArPedGroupName","LArPedMonGroup"};
+
+};
+
+#endif
+
diff --git a/LArCalorimeter/LArMonitoring/src/components/LArMonitoring_entries.cxx b/LArCalorimeter/LArMonitoring/src/components/LArMonitoring_entries.cxx
index 8992b957305..720db6dc172 100755
--- a/LArCalorimeter/LArMonitoring/src/components/LArMonitoring_entries.cxx
+++ b/LArCalorimeter/LArMonitoring/src/components/LArMonitoring_entries.cxx
@@ -4,6 +4,7 @@
 #include "../LArFEBMonAlg.h"
 #include "../LArRODMonAlg.h"
 #include "../LArHVCorrectionMonAlg.h"
+#include "../LArCalibPedMonAlg.h"
 
 
 DECLARE_COMPONENT(LArCollisionTimeMonAlg)
@@ -12,4 +13,5 @@ DECLARE_COMPONENT(LArDigitMonAlg)
 DECLARE_COMPONENT(LArFEBMonAlg)
 DECLARE_COMPONENT(LArRODMonAlg)
 DECLARE_COMPONENT(LArHVCorrectionMonAlg)
+DECLARE_COMPONENT(LArCalibPedMonAlg)
 
-- 
GitLab