From f0380803a30ef81a2641f5c7fb8fe898e1df73da Mon Sep 17 00:00:00 2001
From: Steffen Maeland <steffen.maeland@cern.ch>
Date: Fri, 17 Jul 2015 18:31:38 +0200
Subject: [PATCH] HitDiscCnfg folder added also for online
 (PixelCabling-00-00-56)

	* share/SelectPixelMap.py: /PIXEL/HitDiscCnfg added also for
	online, tagged as PixelCabling-00-00-56

2015-07-16 Steffen Maeland <steffen.maeland @ cern.ch>
	* Implemented reading of FE-I4 hit discriminator settings (HitDiscCnfg)
	from COOL. Values are filled to a map and can be retrieved via
	getHitDiscCnfg().
	* Tagged as PixelCabling-00-00-55
---
 .../PixelCabling/IPixelCablingSvc.h           |   7 +-
 .../PixelCabling/share/SelectPixelMap.py      |   9 +-
 .../PixelCabling/src/PixelCablingData.cxx     |  52 +++++
 .../PixelCabling/src/PixelCablingData.h       |  14 ++
 .../PixelCabling/src/PixelCablingSvc.cxx      | 180 +++++++++++++++++-
 .../PixelCabling/src/PixelCablingSvc.h        |   8 +
 6 files changed, 258 insertions(+), 12 deletions(-)

diff --git a/InnerDetector/InDetDetDescr/PixelCabling/PixelCabling/IPixelCablingSvc.h b/InnerDetector/InDetDetDescr/PixelCabling/PixelCabling/IPixelCablingSvc.h
index dac992a0436..727f82c975f 100644
--- a/InnerDetector/InDetDetDescr/PixelCabling/PixelCabling/IPixelCablingSvc.h
+++ b/InnerDetector/InDetDetDescr/PixelCabling/PixelCabling/IPixelCablingSvc.h
@@ -32,7 +32,10 @@ class IPixelCablingSvc: virtual public IInterface {
   static const InterfaceID& interfaceID( ) ;
 
   // change readout speed
-  virtual StatusCode IOVCallBack(IOVSVC_CALLBACK_ARGS) = 0;  
+  virtual StatusCode IOVCallBack(IOVSVC_CALLBACK_ARGS) = 0;
+
+  // change FE-I4 hit discriminator threshold level
+  virtual StatusCode IOVCallBack_HitDiscCnfg(IOVSVC_CALLBACK_ARGS) = 0;
 
   // Get a list of offlineIds from a RobId.
   virtual void getOfflineList(std::vector<IdentifierHash>& offlineIdHashList, int robid) = 0;
@@ -78,6 +81,8 @@ class IPixelCablingSvc: virtual public IInterface {
   enum moduletype {DBM, IBL, PIX_BARREL, PIX_ENDCAP, NONE};
   virtual moduletype getModuleType(const Identifier& id) = 0;
 
+  virtual int getHitDiscCnfg(const uint32_t robId, const int link) = 0;
+  virtual int getHitDiscCnfg(Identifier* pixelId) = 0;
 
 
    // Wrappers to PixelCablingData -- get maps
diff --git a/InnerDetector/InDetDetDescr/PixelCabling/share/SelectPixelMap.py b/InnerDetector/InDetDetDescr/PixelCabling/share/SelectPixelMap.py
index 1004258d1b2..ad5f7863a5e 100644
--- a/InnerDetector/InDetDetDescr/PixelCabling/share/SelectPixelMap.py
+++ b/InnerDetector/InDetDetDescr/PixelCabling/share/SelectPixelMap.py
@@ -14,6 +14,13 @@ from AthenaCommon.Logging import logging
 #geoFlags.dump()
 
 
+if not ('conddb' in dir()):
+    IOVDbSvc = Service("IOVDbSvc")
+    from IOVDbSvc.CondDB import conddb
+
+if conddb.dbdata == "CONDBR2" and not conddb.folderRequested("/PIXEL/HitDiscCnfg"):
+    conddb.addFolderSplitMC("PIXEL","/PIXEL/HitDiscCnfg","/PIXEL/HitDiscCnfg")
+
 
 # Online mode: Let PixelCablingSvc choose the most recent map
 if (athenaCommonFlags.isOnline == True):
@@ -63,6 +70,7 @@ else:
         # Run2:
         elif (geoFlags.Run() == "RUN2" or (geoFlags.Run() == "UNDEFINED" and geoFlags.isIBL() == True)):
 
+
             # Do map selection based on run number
             runNum = GetRunNumber()
 
@@ -97,4 +105,3 @@ try:
     logging.getLogger("PixelCablingSvc").info("Selected map from jobOpts: %s", ServiceMgr.PixelCablingSvc.MappingFile)
 except:
     logging.getLogger("PixelCablingSvc").info("Map not selected from jobOpts")
-        
diff --git a/InnerDetector/InDetDetDescr/PixelCabling/src/PixelCablingData.cxx b/InnerDetector/InDetDetDescr/PixelCabling/src/PixelCablingData.cxx
index a7996ba1bb1..a063d576e7a 100755
--- a/InnerDetector/InDetDetDescr/PixelCabling/src/PixelCablingData.cxx
+++ b/InnerDetector/InDetDetDescr/PixelCabling/src/PixelCablingData.cxx
@@ -46,6 +46,8 @@ std::size_t hash_value(Identifier const& id) {
 PixelCablingData::PixelCablingData() {
     m_allRods = new std::vector<uint32_t>;
     m_allRobs = new std::vector<uint32_t>;
+
+    m_commonHitDiscCnfg = 3;
 }
 
 
@@ -300,6 +302,56 @@ uint64_t PixelCablingData::getOnlineIdFromRobId(const uint32_t robid, const uint
     return 0;
 }
 
+
+
+
+
+////////////////////////
+// add_entryHitDiscCngf - insert or modify entry in map
+////////////////////////
+void PixelCablingData::add_entry_HitDiscCnfg(const uint32_t frontendId, const int hitdisccnfg) {
+
+    // Insert new key-value pair
+    if (m_HitDiscCnfgMap.find(frontendId) == m_HitDiscCnfgMap.end()) {
+        m_HitDiscCnfgMap.insert(std::make_pair(frontendId, hitdisccnfg));
+    }
+    // Modify an existing entry
+    else {
+        m_HitDiscCnfgMap[frontendId] = hitdisccnfg;
+    }
+}
+
+
+
+////////////////////////
+// getHitDiscCnfg - get HitDiscCnfg mode for given FE-I4
+////////////////////////
+int PixelCablingData::getHitDiscCnfg(const uint32_t frontendId) {
+
+    // Search the map for given frontend id
+    // If not found, return the common HitDiscCnfg setting.
+    boost::unordered_map<uint32_t,int>::const_iterator iter(m_HitDiscCnfgMap.find(frontendId));
+    if (iter != m_HitDiscCnfgMap.end()) return iter->second;
+    else return m_commonHitDiscCnfg;
+
+}
+
+
+////////////////////////
+// printHitDiscCnfg - print the contents of the  HitDiscCnfg map
+////////////////////////
+void PixelCablingData::printHitDiscCnfg() {
+
+    std::cout << "Common HitDiscCnfg value: " << m_commonHitDiscCnfg << std::endl;
+    std::cout << "Contents of HitDiscCnfg map: " << std::endl;
+    boost::unordered_map<uint32_t,int>::const_iterator iter = m_HitDiscCnfgMap.begin();
+    for (; iter != m_HitDiscCnfgMap.end(); iter++) {
+        std::cout << "  FE ID: 0x" << std::hex << iter->first << "  -  HDC = " << std::dec << iter->second << std::endl;
+    }
+}
+
+
+
 // void PixelCablingData::copy_offonMap (std::map< Identifier, uint64_t> &outputMap){
 //   outputMap = m_idMap_offon;
 // }
diff --git a/InnerDetector/InDetDetDescr/PixelCabling/src/PixelCablingData.h b/InnerDetector/InDetDetDescr/PixelCabling/src/PixelCablingData.h
index e892734aa36..fb0a659d46a 100755
--- a/InnerDetector/InDetDetDescr/PixelCabling/src/PixelCablingData.h
+++ b/InnerDetector/InDetDetDescr/PixelCabling/src/PixelCablingData.h
@@ -78,6 +78,13 @@ class PixelCablingData
    std::string find_entry_offlineDCS(const Identifier);
    uint64_t getOnlineIdFromRobId(const uint32_t robid, const uint32_t link);
 
+   // FE-I4 HitDiscCnfg functions
+   void setCommonHitDiscCngf(int hitdisccnfg) {m_commonHitDiscCnfg = hitdisccnfg;}
+   void add_entry_HitDiscCnfg(const uint32_t, const int);
+   int getHitDiscCnfg(const uint32_t frontendId);
+   void printHitDiscCnfg(); // for debugging
+
+
    std::vector<uint32_t>& get_allRods();
    std::vector<uint32_t>& get_allRobs();
    unsigned int get_size_onoff() {return m_idMap_onoff.size();}    // get the size of the on-off map
@@ -97,6 +104,7 @@ class PixelCablingData
    std::map<std::string, Identifier> get_idMapDCSoff();
 
 
+
  private:
 
 
@@ -110,6 +118,12 @@ class PixelCablingData
 
    std::map<uint32_t,bool> m_rodReadoutMap; // save readout speed for each ROD. false=40MBit, true=80MBit
 
+   // JUNE16:
+   // Map of HitDiscCnfg values for each IBL FE
+   // Format: [0xLDDRRR, H], where L = link, DD = subdet id, RRRR = rob id, H = HitDiscCnfg
+   boost::unordered_map<uint32_t, int> m_HitDiscCnfgMap;
+   int m_commonHitDiscCnfg;
+
 
    std::vector<uint32_t>* m_allRods;   // vector containing all RODs in the m_idMap_rodrob
    std::vector<uint32_t>* m_allRobs;   // vector containing all ROBs
diff --git a/InnerDetector/InDetDetDescr/PixelCabling/src/PixelCablingSvc.cxx b/InnerDetector/InDetDetDescr/PixelCabling/src/PixelCablingSvc.cxx
index 9457907a858..e5cdd4d5584 100644
--- a/InnerDetector/InDetDetDescr/PixelCabling/src/PixelCablingSvc.cxx
+++ b/InnerDetector/InDetDetDescr/PixelCabling/src/PixelCablingSvc.cxx
@@ -34,7 +34,7 @@
 #include "CoolKernel/IObject.h"
 
 
-#define PIXEL_DEBUG
+//#define PIXEL_DEBUG
 
 
 using namespace std;
@@ -61,7 +61,9 @@ PixelCablingSvc::PixelCablingSvc(const std::string& name, ISvcLocator*svc) :
     m_cablingTool("PixelFillCablingData_Final"),
     m_detStore("DetectorStore", name),
     m_IBLParameterSvc("IBLParameterSvc",name),
-    m_dataString(""),m_key("/PIXEL/ReadoutSpeed"),
+    m_dataString(""),
+    m_key("/PIXEL/ReadoutSpeed"),
+    m_keyFEI4("/PIXEL/HitDiscCnfg"),
     m_callback_calls(0),
     m_idHelper(0),
     m_cabling(0),
@@ -80,6 +82,7 @@ PixelCablingSvc::PixelCablingSvc(const std::string& name, ISvcLocator*svc) :
     declareProperty("Coral_Connectionstring", m_coraldbconnstring = "oracle://ATLAS_COOLPROD/ATLAS_COOLONL_PIXEL"); // used to configure CORAL based tool
     declareProperty("DictionaryTag", m_dictTag="PIXEL");
     declareProperty("ConnectivityTag", m_connTag="PIT-ALL-V39");
+    declareProperty("KeyFEI4", m_keyFEI4 = "/PIXEL/HitDiscCnfg");
     declareProperty("Key", m_key, "Key=/PIXEL/ReadoutSpeed");
 }
 
@@ -113,6 +116,7 @@ PixelCablingSvc::PixelCablingSvc(const PixelCablingSvc &other, const std::string
     m_dictTag = other.m_dictTag;
     m_connTag = other.m_connTag;
     m_key = other.m_key;
+    m_keyFEI4 = other.m_keyFEI4;
 }
 
 ////////////////////////
@@ -128,6 +132,7 @@ PixelCablingSvc& PixelCablingSvc::operator= (const PixelCablingSvc &other) {
         m_dictTag = other.m_dictTag;
         m_connTag = other.m_connTag;
         m_key = other.m_key;
+        m_keyFEI4 = other.m_keyFEI4;
     }
     return *this;
 }
@@ -168,6 +173,7 @@ StatusCode PixelCablingSvc::initialize( )
     }
 
 
+
     // Get the PixelID Helper
     if (m_detStore->retrieve(m_idHelper, "PixelID").isFailure()) {
         msg(MSG::FATAL) << "Could not get Pixel ID helper" << endreq;
@@ -346,17 +352,48 @@ StatusCode PixelCablingSvc::initialize( )
         return StatusCode::FAILURE;
     }
 */
-    // Register callback
-    const DataHandle<AthenaAttributeList> attrList;
-    sc = m_detStore->regFcn(&IPixelCablingSvc::IOVCallBack,
-                            dynamic_cast<IPixelCablingSvc*>(this),
-                            attrList, m_key);
-    if (!sc.isSuccess()) {
-        ATH_MSG_FATAL("Unable to register callback");
-        return StatusCode::FAILURE;
+
+    // Register callback to ReadoutSpeed
+    const DataHandle<AthenaAttributeList> attrlist_rs;
+    if (m_detStore->contains<AthenaAttributeList>(m_key)) {
+
+        sc = m_detStore->regFcn(&IPixelCablingSvc::IOVCallBack,
+                                dynamic_cast<IPixelCablingSvc*>(this),
+                                attrlist_rs, m_key);
+        // If regFcn fails even when folder is present -> abort
+        if (!sc.isSuccess()) {
+            ATH_MSG_FATAL("Unable to register readoutspeed callback");
+            return StatusCode::FAILURE;
+        }
+    }
+    else {
+        ATH_MSG_INFO("Folder " << m_key << " not found, using default readoutspeed"
+                     << " values (all modules at SINGLE_40)");
+    }
+
+    // Register callback to HitDiscCnfg
+    if (m_IBLpresent) {
+        const DataHandle<AthenaAttributeList> attrlist_hdc;
+        if (m_detStore->contains<AthenaAttributeList>(m_keyFEI4)) {
+
+            sc = m_detStore->regFcn(&IPixelCablingSvc::IOVCallBack_HitDiscCnfg,
+                                    dynamic_cast<IPixelCablingSvc*>(this),
+                                    attrlist_hdc, m_keyFEI4);
+
+            // If regFcn fails even when folder is present -> abort
+            if (!sc.isSuccess()) {
+                ATH_MSG_FATAL("Unable to register HitDiscCnfg callback");
+                return StatusCode::FAILURE;
+            }
+        }
+        else {
+            ATH_MSG_INFO("Folder " << m_keyFEI4 << " not found, using default HitDiscCnfg"
+                         << " values (all FEs at HitDiscCnfg = 3)");
+        }
     }
 
 
+
     return sc;
 }
 
@@ -937,6 +974,11 @@ StatusCode PixelCablingSvc::IOVCallBack(IOVSVC_CALLBACK_ARGS_P(I, keys)){
         return StatusCode::FAILURE;
     }
 
+    if (msgLvl(MSG::DEBUG)) {
+        ATH_MSG_DEBUG("AthenaAttributeList for " << m_key << ":");
+        attrlist->print(std::cout);
+    }
+
     const coral::Blob& blob=(*attrlist)["readoutspeed_per_ROD"].data<coral::Blob>();
     const char* p = static_cast<const char*>(blob.startingAddress());
     unsigned int len = blob.size();
@@ -979,6 +1021,100 @@ StatusCode PixelCablingSvc::IOVCallBack(IOVSVC_CALLBACK_ARGS_P(I, keys)){
 
 
 
+
+////////////////////////
+// callback for changing the FE-I4 HitDiscCnfg property
+////////////////////////
+StatusCode PixelCablingSvc::IOVCallBack_HitDiscCnfg(IOVSVC_CALLBACK_ARGS_P(I, keys)) {
+
+    m_callback_calls++;
+
+    ATH_MSG_INFO("                     -----   HitDiscCnfg callback   -----");
+    for(std::list<std::string>::const_iterator key=keys.begin(); key != keys.end(); ++key)
+        ATH_MSG_INFO("IOVCALLBACK for key " << *key << " number " << I << "\n\t\t\t\t\t-----mtst-----\n");
+
+
+
+    const AthenaAttributeList* attrlist = 0;
+    StatusCode sc = m_detStore->retrieve(attrlist, m_keyFEI4);
+    if(!sc.isSuccess()){
+        ATH_MSG_FATAL("Unable to retrieve AthenaAttributeList");
+        return StatusCode::FAILURE;
+    }
+
+    if (msgLvl(MSG::DEBUG)) {
+        ATH_MSG_DEBUG("AthenaAttributeList for " << m_key << ":");
+        attrlist->print(std::cout);
+    }
+
+    const coral::Blob& blob=(*attrlist)["HitDiscCnfgData"].data<coral::Blob>();
+    const uint32_t* p = static_cast<const uint32_t*>(blob.startingAddress());
+
+
+    uint32_t cooldata;
+    unsigned int len = blob.size()/sizeof(uint32_t);
+    ATH_MSG_DEBUG("blob.size() = " << blob.size() << ", len = " << len);
+
+
+    for (unsigned int i = 0; i < len; ++i) {
+
+        cooldata = *p++;
+
+        ATH_MSG_DEBUG("Got hitdisccnfgData[" << i << "] = 0x" << std::hex << cooldata << std::dec);
+
+        // The implementation below uses one common value, one common 3D value,
+        // and an exception list of individual FEs, in order to save DB space.
+        // Here we convert this into only one common value and an exception list, i.e.
+        // if the 3D FEs have a different common value they are all added to the exception list
+
+        // Update the most common value, identified by 0xH0000000, where H = 00HH
+        if ((cooldata & 0x8FFFFFFF) == 0x0) {
+            ATH_MSG_DEBUG("Setting common HitDiscCnfg value to " << ((cooldata&0x30000000) >> 28));
+            m_cabling->setCommonHitDiscCngf((cooldata&0x30000000) >> 28);
+        }
+
+        // Update all 3D sensors with a common value, identified by 0xZ0000000, where Z = 10hh
+        else if ((cooldata & 0x8FFFFFFF) == 0x80000000) {
+
+            ATH_MSG_DEBUG("Setting common 3D HitDiscCnfg value to " << ((cooldata&0x30000000) >> 28));
+
+            // Loop over list of robs, find the 3D sensors and insert them in HitDiscCnfg map
+            for (auto robid : m_cabling->get_allRobs()) {
+
+                // Skip non-IBL ROBs (DBM is not affected by the common 3D value)
+                if (!isIBL(robid)) continue;
+
+                for (int link = 0 ; link < 8 ; ++link) {
+
+                    if (((robid&0xF)==1 && link > 3) || (((robid&0xF)==2) && link < 4))  {
+                        m_cabling->add_entry_HitDiscCnfg((robid | (link >> 24)), (cooldata & 0x30000000) >> 28);
+                    }
+                }
+            }
+        }
+
+
+        // Update a single link, 0xHLDDRRRR
+        else {
+            ATH_MSG_DEBUG("Setting HitDiscCnfg value to " << ((cooldata&0x30000000) >> 28)
+                          << " for ROB 0x" << std::hex << (cooldata & 0xFFFFFF)
+                          << ", link " << std::dec << ((cooldata & 0xF000000) >> 24));
+            m_cabling->add_entry_HitDiscCnfg((cooldata & 0xFFFFFFF), (cooldata & 0x30000000) >> 28);
+        }
+
+    }
+
+    ATH_MSG_INFO("                     -----   DONE  Callback " << m_callback_calls << "  -----");
+
+    // Print map contents
+    if (msgLvl(MSG::DEBUG)) m_cabling->printHitDiscCnfg();
+
+
+    return StatusCode::SUCCESS;
+}
+
+
+
 ////////////////////////
 // getOnlineIdFromRobId
 // Wrapper function to PixelCablingData::getOnlineIdFromRobId
@@ -1048,3 +1184,27 @@ PixelCablingSvc::moduletype PixelCablingSvc::getModuleType(const Identifier& id)
 
     return isType;
 }
+
+
+
+////////////////////////
+// getHitDiscCnfg - wrapper function to PixelCablingData::getHitDiscCnfg
+////////////////////////
+int PixelCablingSvc::getHitDiscCnfg(const uint32_t robId, const int link) {
+    return m_cabling->getHitDiscCnfg((link << 24) | robId);
+}
+
+
+////////////////////////
+// getHitDiscCnfg - overloaded function to be used by offline
+////////////////////////
+int PixelCablingSvc::getHitDiscCnfg(Identifier* pixelId) {
+
+    uint32_t robId = getRobId(m_idHelper->wafer_id(*pixelId));
+    int link = getFEwrtSlink(pixelId);
+    return getHitDiscCnfg(robId, link);
+}
+
+
+
+
diff --git a/InnerDetector/InDetDetDescr/PixelCabling/src/PixelCablingSvc.h b/InnerDetector/InDetDetDescr/PixelCabling/src/PixelCablingSvc.h
index a70c084aa01..e1486b94f8f 100644
--- a/InnerDetector/InDetDetDescr/PixelCabling/src/PixelCablingSvc.h
+++ b/InnerDetector/InDetDetDescr/PixelCabling/src/PixelCablingSvc.h
@@ -67,6 +67,9 @@ public:
   StatusCode finalize();
   StatusCode IOVCallBack(IOVSVC_CALLBACK_ARGS);
 
+  StatusCode IOVCallBack_HitDiscCnfg(IOVSVC_CALLBACK_ARGS);
+
+
   StatusCode queryInterface(const InterfaceID & riid, void** ppvInterface );
   
   // Get a list of offlineIds from a RobId.
@@ -103,6 +106,10 @@ public:
   uint32_t getRow(Identifier * pixelId, Identifier offlineId);
   uint32_t getFEwrtSlink(Identifier *pixelId);
   unsigned int getLocalFEI4(const uint32_t fe, const uint64_t onlineId);
+
+
+  int getHitDiscCnfg(const uint32_t robId, const int link);
+  int getHitDiscCnfg(Identifier* pixelId);
   
   bool isIBL(const uint32_t robId);
   bool isIBL(const Identifier& id);
@@ -132,6 +139,7 @@ private:
   ServiceHandle<IBLParameterSvc> m_IBLParameterSvc; 
   std::string m_dataString ;
   std::string m_key;
+  std::string m_keyFEI4;
   unsigned int m_callback_calls;
 
   const PixelID* m_idHelper;
-- 
GitLab