From 0755ad2832f36b5a35d5ea6ae86e86d26b12f64e Mon Sep 17 00:00:00 2001
From: Eric Torrence <eric.torrence@cern.ch>
Date: Tue, 22 Nov 2022 08:51:18 +0100
Subject: [PATCH] Updates to the LHC data schema

---
 .../FaserAuthentication/data/dblookup.xml     |  13 +-
 LHCData/LHCDataAlgs/src/LHCDataAlg.cxx        | 145 +++++++++++++++---
 LHCData/LHCDataAlgs/src/LHCDataAlg.h          |  12 +-
 .../LHCDataTools/LHCDataTools/ILHCDataTool.h  |  16 +-
 LHCData/LHCDataTools/src/LHCDataTool.cxx      | 108 +++++--------
 LHCData/LHCDataTools/src/LHCDataTool.h        |  30 ++--
 .../python/WaveformRangeConfig.py             |  10 +-
 ...CDataAux_v1.cxx => FaserLHCDataAux_v1.cxx} |  23 ++-
 ...aserLHCData_v1.cxx => FaserLHCData_v1.cxx} |  32 ++--
 .../versions/FaserLHCDataAux_v1.h             |  14 +-
 .../xAODFaserLHC/versions/FaserLHCData_v1.h   |  42 +++--
 11 files changed, 290 insertions(+), 155 deletions(-)
 rename xAOD/xAODFaserLHC/Root/{xAODFaserLHCDataAux_v1.cxx => FaserLHCDataAux_v1.cxx} (77%)
 rename xAOD/xAODFaserLHC/Root/{xAODFaserLHCData_v1.cxx => FaserLHCData_v1.cxx} (82%)

diff --git a/Database/ConnectionManagement/FaserAuthentication/data/dblookup.xml b/Database/ConnectionManagement/FaserAuthentication/data/dblookup.xml
index 9913f4be0..1518267ee 100644
--- a/Database/ConnectionManagement/FaserAuthentication/data/dblookup.xml
+++ b/Database/ConnectionManagement/FaserAuthentication/data/dblookup.xml
@@ -26,19 +26,24 @@
   <service name="sqlite_file:///cvmfs/faser.cern.ch/repo/sw/database/DBRelease/current/sqlite200/CABP200.db" accessMode="read" />
  </logicalservice>
 
+ <logicalservice name="COOLOFL_DIGITIZER">
+  <service name="sqlite_file:data/sqlite200/ALLP200.db" accessMode="read" />
+  <service name="sqlite_file:///cvmfs/faser.cern.ch/repo/sw/database/DBRelease/current/sqlite200/ALLP200.db" accessMode="read" />
+ </logicalservice>
+
  <logicalservice name="COOLOFL_INDET">
   <service name="sqlite_file:data/sqlite200/ALLP200.db" accessMode="read" />
   <service name="sqlite_file:///cvmfs/faser.cern.ch/repo/sw/database/DBRelease/current/sqlite200/ALLP200.db" accessMode="read" />
  </logicalservice>
 
 <logicalservice name="COOLOFL_TRIGGER">
-   <service name="sqlite_file:data/sqlite200/ALLP200.db" accessMode="read" />
-   <service name="sqlite_file:///cvmfs/faser.cern.ch/repo/sw/database/DBRelease/current/sqlite200/ALLP200.db" accessMode="read" />   
+  <service name="sqlite_file:data/sqlite200/ALLP200.db" accessMode="read" />
+  <service name="sqlite_file:///cvmfs/faser.cern.ch/repo/sw/database/DBRelease/current/sqlite200/ALLP200.db" accessMode="read" />   
 </logicalservice>
 
 <logicalservice name="COOLOFL_LHC">
-   <service name="sqlite_file:data/sqlite200/ALLP200.db" accessMode="read" />
-   <service name="sqlite_file:///cvmfs/faser.cern.ch/repo/sw/database/DBRelease/current/sqlite200/ALLP200.db" accessMode="read" />   
+ <service name="sqlite_file:data/sqlite200/ALLP200.db" accessMode="read" />
+  <service name="sqlite_file:///cvmfs/faser.cern.ch/repo/sw/database/DBRelease/current/sqlite200/ALLP200.db" accessMode="read" />   
 </logicalservice>
 
 </servicelist>
diff --git a/LHCData/LHCDataAlgs/src/LHCDataAlg.cxx b/LHCData/LHCDataAlgs/src/LHCDataAlg.cxx
index 9463ab877..de2269858 100644
--- a/LHCData/LHCDataAlgs/src/LHCDataAlg.cxx
+++ b/LHCData/LHCDataAlgs/src/LHCDataAlg.cxx
@@ -40,21 +40,20 @@ LHCDataAlg::execute(const EventContext& ctx) const {
 
   lhcDataHandle->set_fillNumber(m_lhcTool->getFillNumber(ctx));
   lhcDataHandle->set_machineMode(m_lhcTool->getMachineMode(ctx));
-  lhcDataHandle->set_injectionScheme(m_lhcTool->getInjectionScheme(ctx));
+  lhcDataHandle->set_beamMode(m_lhcTool->getBeamMode(ctx));
   lhcDataHandle->set_beamType1(m_lhcTool->getBeamType1(ctx));
   lhcDataHandle->set_beamType2(m_lhcTool->getBeamType2(ctx));
 
-  lhcDataHandle->set_numBunchBeam1(m_lhcTool->getNumBunchBeam1(ctx));
-  lhcDataHandle->set_numBunchBeam2(m_lhcTool->getNumBunchBeam2(ctx));
-  lhcDataHandle->set_numBunchColliding(m_lhcTool->getNumBunchColl(ctx));
-
-  lhcDataHandle->set_beamMode(m_lhcTool->getBeamMode(ctx));
   lhcDataHandle->set_betaStar(m_lhcTool->getBetaStar(ctx));
   lhcDataHandle->set_crossingAngle(m_lhcTool->getCrossingAngle(ctx));
 
-  //lhcDataHandle->set_beam1Bunches(m_lhcTool->getBeam1Bunches(ctx));
-  //lhcDataHandle->set_beam2Bunches(m_lhcTool->getBeam2Bunches(ctx));
-  //lhcDataHandle->set_luminousBunches(m_lhcTool->getLuminousBunches(ctx));
+  lhcDataHandle->set_stableBeams(m_lhcTool->getStableBeams(ctx));
+  lhcDataHandle->set_injectionScheme(m_lhcTool->getInjectionScheme(ctx));
+
+  // Slight naming mismatch here, but oh well
+  lhcDataHandle->set_numBunchBeam1(m_lhcTool->getBeam1Bunches(ctx));
+  lhcDataHandle->set_numBunchBeam2(m_lhcTool->getBeam2Bunches(ctx));
+  lhcDataHandle->set_numBunchColliding(m_lhcTool->getCollidingBunches(ctx));
 
   // Fill BCID information
 
@@ -65,28 +64,48 @@ LHCDataAlg::execute(const EventContext& ctx) const {
   SG::ReadHandle<xAOD::EventInfo> xevt(m_eventInfo, ctx);
   unsigned int bcid = xevt->bcid();
 
-  int nearest = findDistance(bcid, bcid_mask, 3);  // Colliding beams
+  int nearest = findNearest(bcid, bcid_mask, 3);  // Colliding beams
   lhcDataHandle->set_distanceToCollidingBCID(nearest);
   ATH_MSG_DEBUG("Found distance of " << nearest << " from BCID " << bcid 
 		<< " to the nearest colliding BCID ");
 
-  nearest = findDistance(bcid, bcid_mask, 1);  // Beam1 unpaired
+  nearest = findNearest(bcid, bcid_mask, 1);  // Beam1 unpaired
   lhcDataHandle->set_distanceToUnpairedB1(nearest);
   ATH_MSG_DEBUG("Found distance of " << nearest << " from BCID " << bcid 
 		<< " to the nearest unpaired B1 ");
 
-  nearest = findDistance(bcid, bcid_mask, 2);  // Beam2 unpaired
+  nearest = findNearest(bcid, bcid_mask, 2);  // Beam2 unpaired
   lhcDataHandle->set_distanceToUnpairedB2(nearest);
   ATH_MSG_DEBUG("Found distance of " << nearest << " from BCID " << bcid 
 		<< " to the nearest unpaired B2 ");
 
+  // Add 127 to current BCID to check if inbound B1 is nearby FASER
+  int offset_bcid = (bcid + 127) % 3564;
+  nearest = findNearest(offset_bcid, bcid_mask, 1);  // Inbound B1
+  int nearest2 = findNearest(offset_bcid, bcid_mask, 3);  // Inbound B1
+  if (abs(nearest2) < abs(nearest)) nearest = nearest2;
+  lhcDataHandle->set_distanceToInboundB1(nearest);
+  ATH_MSG_DEBUG("Found distance of " << nearest << " from BCID " << bcid 
+  		<< " to the nearest inbound B1 ");
+
+  unsigned int previous;
+  previous = previousColliding(bcid, bcid_mask);
+  lhcDataHandle->set_distanceToPreviousColliding(previous);
+  ATH_MSG_DEBUG("Found distance of " << previous << " from BCID " << bcid 
+		<< " to the previous colliding bunch ");
+
+  previous = previousTrain(bcid, bcid_mask);
+  lhcDataHandle->set_distanceToTrainStart(previous);
+  ATH_MSG_DEBUG("Found distance of " << previous << " from BCID " << bcid 
+		<< " to the start of the previous train ");
+
   return StatusCode::SUCCESS;
 }
 
 // Function to find distance to nearest BCID
 // mask indicates the condition: 1 - unpaired B1, 2 - unpaired B2, 3 - colliding
 int
-LHCDataAlg::findDistance(unsigned int bcid, const std::vector<unsigned char>& bcid_mask, unsigned char mask) const {
+LHCDataAlg::findNearest(unsigned int bcid, const std::vector<unsigned char>& bcid_mask, unsigned char mask) const {
 
   // Does the BCID make sense?
   if ((bcid > 3564) || (bcid <= 0)) {
@@ -100,10 +119,7 @@ LHCDataAlg::findDistance(unsigned int bcid, const std::vector<unsigned char>& bc
   for (unsigned int i=0; i < 3564/2; i++) {
 
     // Try positive offsets
-    test_bcid = bcid + i;
-
-    // Wrap around
-    if (test_bcid >= 3564) test_bcid -= 3564;
+    test_bcid = (bcid + i) % 3564;
 
     // BCID 0 doesn't exist in the real machine
     // BCID 3564 doesn't exist in our array (but will always be empty in real machine)
@@ -114,15 +130,12 @@ LHCDataAlg::findDistance(unsigned int bcid, const std::vector<unsigned char>& bc
     if(i == 0) continue;  // No need to check -0
 
     // Try negative offsets
-    test_bcid = bcid - i;
-
-    // Wrap around
-    if (test_bcid < 1) test_bcid += 3564;
+    test_bcid = (bcid - i) % 3564;
 
     // BCID 0 doesn't exist in the real machine
     // BCID 3564 doesn't exist in our array (but will always be empty)
     // So avoid these pathologies
-    if (test_bcid != 3564) 
+    if (test_bcid != 0) 
       if (mask == bcid_mask[test_bcid]) return -i;
 
   }
@@ -134,3 +147,91 @@ LHCDataAlg::findDistance(unsigned int bcid, const std::vector<unsigned char>& bc
   return -3565;
 
 }
+
+// Function to find previous colliding BCID
+unsigned int
+LHCDataAlg::previousColliding(unsigned int bcid, const std::vector<unsigned char>& bcid_mask) const {
+
+  // Does the BCID make sense?
+  if ((bcid > 3564) || (bcid <= 0)) {
+    ATH_MSG_WARNING("Requested distance from invalid BCID " << bcid << "!");
+    return 9999;
+  }
+
+  unsigned int test_bcid;
+
+  // Move backwards from the bcid (starting at offset of 0)
+  for (unsigned int i=0; i < 3564; i++) {
+
+    // Try positive offsets
+    test_bcid = (bcid - i) % 3564;
+
+    // BCID 3564 doesn't exist in our array (but will always be empty)
+    // So avoid these pathologies
+    if (test_bcid != 0) 
+      if (0x03 == bcid_mask[test_bcid]) return i;
+
+  }
+
+  // If we got to here, there was no match
+  // Does the BCID make sense?
+  ATH_MSG_WARNING("Couldn't find colliding from BCID " << bcid << "!");
+  ATH_MSG_WARNING(bcid_mask);
+  return 9999;
+
+}
+
+unsigned int
+LHCDataAlg::previousTrain(unsigned int bcid, const std::vector<unsigned char>& bcid_mask) const {
+
+  // Does the BCID make sense?
+  if ((bcid > 3564) || (bcid <= 0)) {
+    ATH_MSG_WARNING("Requested distance from invalid BCID " << bcid << "!");
+    return 9999;
+  }
+
+  unsigned int test_bcid;
+
+  bool in_train = false;
+  // Move backwards from the bcid (starting at offset of 0)
+  for (unsigned int i=0; i < 3564; i++) {
+
+    // BCID to test
+    test_bcid = (bcid - i) % 3564;
+
+    // BCID 3564 doesn't exist in our array (but will always be empty)
+    // So avoid these pathologies
+    ATH_MSG_DEBUG("Test " << test_bcid << " In train: " << in_train << " mask[test_bcid]");
+
+    // If we are not in a train before, lets see if we are in a train now
+    if (!in_train) {
+
+      // If we found a colliding bunch, set in_train, otherwise we are still not in a train
+      if ((test_bcid != 0) && (0x03 == bcid_mask[test_bcid]))
+	in_train = true;
+
+      // Either way, move to next BCID
+      continue;
+
+    } else {
+
+      // Currently in a train, lets see if now we are not
+      if ((test_bcid == 0) || (0x03 != bcid_mask[test_bcid])) {
+	in_train = false;
+	// Previous BCID was first in train
+	return i-1;
+      } else {
+	in_train = true;
+      }
+	
+    }
+
+  }
+
+  // If we got to here, there was no match
+  // Does the BCID make sense?
+  ATH_MSG_WARNING("Couldn't find first in train from BCID " << bcid << "!");
+  ATH_MSG_WARNING(bcid_mask);
+  return 9999;
+
+}
diff --git a/LHCData/LHCDataAlgs/src/LHCDataAlg.h b/LHCData/LHCDataAlgs/src/LHCDataAlg.h
index f53257bc5..a8785725a 100644
--- a/LHCData/LHCDataAlgs/src/LHCDataAlg.h
+++ b/LHCData/LHCDataAlgs/src/LHCDataAlg.h
@@ -32,10 +32,16 @@ class LHCDataAlg : public AthReentrantAlgorithm {
     {this, "FaserLHCDataKey", "FaserLHCData"};
 
   // Utility function to find nearest BCID
-  int findDistance(unsigned int bcid, const std::vector<unsigned char>& bcid_mask, 
-		   unsigned char mask) const;
+  int findNearest(unsigned int bcid, const std::vector<unsigned char>& bcid_mask, 
+		  unsigned char mask) const;
+
+  unsigned int 
+    previousColliding(unsigned int bcid, const std::vector<unsigned char>& bcid_mask) const;
+
+  // Find the distance to the first BCID of the previous train
+  unsigned int 
+    previousTrain(unsigned int bcid, const std::vector<unsigned char>& bcid_mask) const;
 
-  //ServiceHandle<ICondSvc> m_condSvc{this, "CondSvc", "CondSvc"};
 };
 
 #endif // LHCDATAALG_H
diff --git a/LHCData/LHCDataTools/LHCDataTools/ILHCDataTool.h b/LHCData/LHCDataTools/LHCDataTools/ILHCDataTool.h
index cf6abd17d..6e469d0eb 100644
--- a/LHCData/LHCDataTools/LHCDataTools/ILHCDataTool.h
+++ b/LHCData/LHCDataTools/LHCDataTools/ILHCDataTool.h
@@ -43,15 +43,6 @@ class ILHCDataTool: virtual public IAlgTool {
   virtual int getBeamType2(const EventContext& ctx) const = 0;
   virtual int getBeamType2(void) const = 0;
 
-  virtual unsigned int getNumBunchBeam1(const EventContext& ctx) const = 0;
-  virtual unsigned int getNumBunchBeam1(void) const = 0;
-
-  virtual unsigned int getNumBunchBeam2(const EventContext& ctx) const = 0;
-  virtual unsigned int getNumBunchBeam2(void) const = 0;
-
-  virtual unsigned int getNumBunchColl(const EventContext& ctx) const = 0;
-  virtual unsigned int getNumBunchColl(void) const = 0;
-
   // Methods to return beam data
   virtual std::string getBeamMode(const EventContext& ctx) const = 0;
   virtual std::string getBeamMode(void) const = 0;
@@ -62,6 +53,9 @@ class ILHCDataTool: virtual public IAlgTool {
   virtual float getCrossingAngle(const EventContext& ctx) const = 0;
   virtual float getCrossingAngle(void) const = 0;
 
+  virtual bool getStableBeams(const EventContext& ctx) const = 0;
+  virtual bool getStableBeams(void) const = 0;
+
   // Methods to return BCID data
   virtual unsigned int getBeam1Bunches(const EventContext& ctx) const = 0;
   virtual unsigned int getBeam1Bunches(void) const = 0;
@@ -69,8 +63,8 @@ class ILHCDataTool: virtual public IAlgTool {
   virtual unsigned int getBeam2Bunches(const EventContext& ctx) const = 0;
   virtual unsigned int getBeam2Bunches(void) const = 0;
 
-  virtual unsigned int getLuminousBunches(const EventContext& ctx) const = 0;
-  virtual unsigned int getLuminousBunches(void) const = 0;
+  virtual unsigned int getCollidingBunches(const EventContext& ctx) const = 0;
+  virtual unsigned int getCollidingBunches(void) const = 0;
 
   virtual std::vector<unsigned char> getBCIDMasks(const EventContext& ctx) const = 0;
   virtual std::vector<unsigned char> getBCIDMasks(void) const = 0;
diff --git a/LHCData/LHCDataTools/src/LHCDataTool.cxx b/LHCData/LHCDataTools/src/LHCDataTool.cxx
index 64a2d5365..7b0fafe00 100644
--- a/LHCData/LHCDataTools/src/LHCDataTool.cxx
+++ b/LHCData/LHCDataTools/src/LHCDataTool.cxx
@@ -22,7 +22,7 @@ LHCDataTool::initialize() {
   ATH_MSG_DEBUG("LHCDataTool::initialize()");
 
   // Read Handles
-  ATH_CHECK(m_fillDataKey.initialize());
+  //ATH_CHECK(m_fillDataKey.initialize());
   ATH_CHECK(m_beamDataKey.initialize());
   ATH_CHECK(m_bcidDataKey.initialize());
 
@@ -40,7 +40,7 @@ LHCDataTool::finalize() {
 int
 LHCDataTool::getFillNumber(const EventContext& ctx) const {
   // Read Cond Handle
-  SG::ReadCondHandle<AthenaAttributeList> readHandle{m_fillDataKey, ctx};
+  SG::ReadCondHandle<AthenaAttributeList> readHandle{m_beamDataKey, ctx};
   return (**readHandle)["FillNumber"].data<int>();
 } 
 
@@ -54,7 +54,7 @@ LHCDataTool::getFillNumber(void) const {
 std::string
 LHCDataTool::getMachineMode(const EventContext& ctx) const {
   // Read Cond Handle
-  SG::ReadCondHandle<AthenaAttributeList> readHandle{m_fillDataKey, ctx};
+  SG::ReadCondHandle<AthenaAttributeList> readHandle{m_beamDataKey, ctx};
   return (**readHandle)["MachineMode"].data<std::string>();
 } 
 
@@ -66,23 +66,22 @@ LHCDataTool::getMachineMode(void) const {
 
 //----------------------------------------------------------------------
 std::string
-LHCDataTool::getInjectionScheme(const EventContext& ctx) const {
-  // Read Cond Handle
-  SG::ReadCondHandle<AthenaAttributeList> readHandle{m_fillDataKey, ctx};
-  return (**readHandle)["InjectionScheme"].data<std::string>();
-} 
+LHCDataTool::getBeamMode(const EventContext& ctx) const {
+  SG::ReadCondHandle<AthenaAttributeList> readHandle{m_beamDataKey, ctx};
+  return(**readHandle)["BeamMode"].data<std::string>();
+}
 
 std::string
-LHCDataTool::getInjectionScheme(void) const {
+LHCDataTool::getBeamMode(void) const {
   const EventContext& ctx{Gaudi::Hive::currentContext()};
-  return getInjectionScheme(ctx);
+  return getBeamMode(ctx);
 }
 
 //----------------------------------------------------------------------
 int
 LHCDataTool::getBeamType1(const EventContext& ctx) const {
   // Read Cond Handle
-  SG::ReadCondHandle<AthenaAttributeList> readHandle{m_fillDataKey, ctx};
+  SG::ReadCondHandle<AthenaAttributeList> readHandle{m_beamDataKey, ctx};
   return (**readHandle)["BeamType1"].data<int>();
 } 
 
@@ -96,7 +95,7 @@ LHCDataTool::getBeamType1(void) const {
 int
 LHCDataTool::getBeamType2(const EventContext& ctx) const {
   // Read Cond Handle
-  SG::ReadCondHandle<AthenaAttributeList> readHandle{m_fillDataKey, ctx};
+  SG::ReadCondHandle<AthenaAttributeList> readHandle{m_beamDataKey, ctx};
   return (**readHandle)["BeamType2"].data<int>();
 } 
 
@@ -106,56 +105,6 @@ LHCDataTool::getBeamType2(void) const {
   return getBeamType2(ctx);
 }
 
-//----------------------------------------------------------------------
-unsigned int
-LHCDataTool::getNumBunchBeam1(const EventContext& ctx) const {
-  SG::ReadCondHandle<AthenaAttributeList> readHandle{m_fillDataKey, ctx};
-  return(**readHandle)["NumBunchBeam1"].data<unsigned int>();
-}
-
-unsigned int
-LHCDataTool::getNumBunchBeam1(void) const {
-  const EventContext& ctx{Gaudi::Hive::currentContext()};
-  return getNumBunchBeam1(ctx);
-}
-
-unsigned int
-LHCDataTool::getNumBunchBeam2(const EventContext& ctx) const {
-  SG::ReadCondHandle<AthenaAttributeList> readHandle{m_fillDataKey, ctx};
-  return(**readHandle)["NumBunchBeam2"].data<unsigned int>();
-}
-
-unsigned int
-LHCDataTool::getNumBunchBeam2(void) const {
-  const EventContext& ctx{Gaudi::Hive::currentContext()};
-  return getNumBunchBeam2(ctx);
-}
-
-unsigned int
-LHCDataTool::getNumBunchColl(const EventContext& ctx) const {
-  SG::ReadCondHandle<AthenaAttributeList> readHandle{m_fillDataKey, ctx};
-  return(**readHandle)["NumBunchColl"].data<unsigned int>();
-}
-
-unsigned int
-LHCDataTool::getNumBunchColl(void) const {
-  const EventContext& ctx{Gaudi::Hive::currentContext()};
-  return getNumBunchColl(ctx);
-}
-
-//----------------------------------------------------------------------
-std::string
-LHCDataTool::getBeamMode(const EventContext& ctx) const {
-  SG::ReadCondHandle<AthenaAttributeList> readHandle{m_beamDataKey, ctx};
-  return(**readHandle)["BeamMode"].data<std::string>();
-}
-
-std::string
-LHCDataTool::getBeamMode(void) const {
-  const EventContext& ctx{Gaudi::Hive::currentContext()};
-  return getBeamMode(ctx);
-}
-
 //----------------------------------------------------------------------
 float
 LHCDataTool::getBetaStar(const EventContext& ctx) const {
@@ -182,6 +131,33 @@ LHCDataTool::getCrossingAngle(void) const {
   return getCrossingAngle(ctx);
 }
 
+//----------------------------------------------------------------------
+bool
+LHCDataTool::getStableBeams(const EventContext& ctx) const {
+  SG::ReadCondHandle<AthenaAttributeList> readHandle{m_beamDataKey, ctx};
+  return(**readHandle)["StableBeams"].data<bool>();
+}
+
+bool
+LHCDataTool::getStableBeams(void) const {
+  const EventContext& ctx{Gaudi::Hive::currentContext()};
+  return getStableBeams(ctx);
+}
+
+//----------------------------------------------------------------------
+std::string
+LHCDataTool::getInjectionScheme(const EventContext& ctx) const {
+  // Read Cond Handle
+  SG::ReadCondHandle<AthenaAttributeList> readHandle{m_beamDataKey, ctx};
+  return (**readHandle)["InjectionScheme"].data<std::string>();
+} 
+
+std::string
+LHCDataTool::getInjectionScheme(void) const {
+  const EventContext& ctx{Gaudi::Hive::currentContext()};
+  return getInjectionScheme(ctx);
+}
+
 //----------------------------------------------------------------------
 unsigned int
 LHCDataTool::getBeam1Bunches(const EventContext& ctx) const {
@@ -208,15 +184,15 @@ LHCDataTool::getBeam2Bunches(void) const {
 }
 
 unsigned int
-LHCDataTool::getLuminousBunches(const EventContext& ctx) const {
+LHCDataTool::getCollidingBunches(const EventContext& ctx) const {
   SG::ReadCondHandle<AthenaAttributeList> readHandle{m_bcidDataKey, ctx};
-  return(**readHandle)["LuminousBunches"].data<unsigned int>();
+  return(**readHandle)["CollidingBunches"].data<unsigned int>();
 }
 
 unsigned int
-LHCDataTool::getLuminousBunches(void) const {
+LHCDataTool::getCollidingBunches(void) const {
   const EventContext& ctx{Gaudi::Hive::currentContext()};
-  return getLuminousBunches(ctx);
+  return getCollidingBunches(ctx);
 }
 
 
diff --git a/LHCData/LHCDataTools/src/LHCDataTool.h b/LHCData/LHCDataTools/src/LHCDataTool.h
index 6a969cc02..3acabfb75 100644
--- a/LHCData/LHCDataTools/src/LHCDataTool.h
+++ b/LHCData/LHCDataTools/src/LHCDataTool.h
@@ -43,14 +43,15 @@ class LHCDataTool: public extends<AthAlgTool, ILHCDataTool> {
   virtual StatusCode finalize() override; //!< Gaudi finaliser
 
   // Methods to return fill data
+  // Methods to return beam data
   virtual int getFillNumber(const EventContext& ctx) const override;
   virtual int getFillNumber(void) const override;
 
   virtual std::string getMachineMode(const EventContext& ctx) const override;
   virtual std::string getMachineMode(void) const override;
 
-  virtual std::string getInjectionScheme(const EventContext& ctx) const override;
-  virtual std::string getInjectionScheme(void) const override;
+  virtual std::string getBeamMode(const EventContext& ctx) const override;
+  virtual std::string getBeamMode(void) const override;
 
   virtual int getBeamType1(const EventContext& ctx) const override;
   virtual int getBeamType1(void) const override;
@@ -58,25 +59,18 @@ class LHCDataTool: public extends<AthAlgTool, ILHCDataTool> {
   virtual int getBeamType2(const EventContext& ctx) const override;
   virtual int getBeamType2(void) const override;
 
-  virtual unsigned int getNumBunchBeam1(const EventContext& ctx) const override;
-  virtual unsigned int getNumBunchBeam1(void) const override;
-
-  virtual unsigned int getNumBunchBeam2(const EventContext& ctx) const override;
-  virtual unsigned int getNumBunchBeam2(void) const override;
-
-  virtual unsigned int getNumBunchColl(const EventContext& ctx) const override;
-  virtual unsigned int getNumBunchColl(void) const override;
-
-  // Methods to return beam data
-  virtual std::string getBeamMode(const EventContext& ctx) const override;
-  virtual std::string getBeamMode(void) const override;
-
   virtual float getBetaStar(const EventContext& ctx) const override;
   virtual float getBetaStar(void) const override;
 
   virtual float getCrossingAngle(const EventContext& ctx) const override;
   virtual float getCrossingAngle(void) const override;
 
+  virtual bool getStableBeams(const EventContext& ctx) const override;
+  virtual bool getStableBeams(void) const override;
+
+  virtual std::string getInjectionScheme(const EventContext& ctx) const override;
+  virtual std::string getInjectionScheme(void) const override;
+
   // Methods to return BCID data
   virtual unsigned int getBeam1Bunches(const EventContext& ctx) const override;
   virtual unsigned int getBeam1Bunches(void) const override;
@@ -84,8 +78,8 @@ class LHCDataTool: public extends<AthAlgTool, ILHCDataTool> {
   virtual unsigned int getBeam2Bunches(const EventContext& ctx) const override;
   virtual unsigned int getBeam2Bunches(void) const override;
 
-  virtual unsigned int getLuminousBunches(const EventContext& ctx) const override;
-  virtual unsigned int getLuminousBunches(void) const override;
+  virtual unsigned int getCollidingBunches(const EventContext& ctx) const override;
+  virtual unsigned int getCollidingBunches(void) const override;
 
   // This returns a char for each BCID encoding beam1/beam2
   // A colliding BCID will have value 3
@@ -95,7 +89,7 @@ class LHCDataTool: public extends<AthAlgTool, ILHCDataTool> {
 
  private:
   // Read Cond Handles
-  SG::ReadCondHandleKey<AthenaAttributeList> m_fillDataKey{this, "FillDataKey", "/LHC/FillData", "Key of fill data folder"};
+  //SG::ReadCondHandleKey<AthenaAttributeList> m_fillDataKey{this, "FillDataKey", "/LHC/FillData", "Key of fill data folder"};
   SG::ReadCondHandleKey<AthenaAttributeList> m_beamDataKey{this, "BeamDataKey", "/LHC/BeamData", "Key of fill data folder"};
   SG::ReadCondHandleKey<AthenaAttributeList> m_bcidDataKey{this, "BcidDataKey", "/LHC/BCIDData", "Key of fill data folder"};
 
diff --git a/Waveform/WaveformConditions/WaveformConditionsTools/python/WaveformRangeConfig.py b/Waveform/WaveformConditions/WaveformConditionsTools/python/WaveformRangeConfig.py
index 6450bcec8..8ac69d912 100644
--- a/Waveform/WaveformConditions/WaveformConditionsTools/python/WaveformRangeConfig.py
+++ b/Waveform/WaveformConditions/WaveformConditionsTools/python/WaveformRangeConfig.py
@@ -20,8 +20,14 @@ def WaveformRangeCfg(flags, **kwargs):
     acc = ComponentAccumulator()
     # tool = kwargs.get("WaveformRangeTool", WaveformRangeTool(flags))
     # Probably need to figure this out!
-    dbInstance = kwargs.get("dbInstance", "TDAQ_OFL")
+
+    dbInstance = kwargs.get("dbInstance", "COOLOFL_DIGITIZER")
     dbFolder = kwargs.get("dbFolder", "/WAVE/DAQ/Range")
-    acc.merge(addFolders(flags, dbFolder, dbInstance, className="CondAttrListCollection"))
+    dbName = flags.IOVDb.DatabaseInstance # e.g. CONDBR3 
+
+    # COOLOFL_DIGITIZER is not known to ATLAS IOVDBSvc
+    # Must use non-shorthand folder specification here
+    folder_string = f"<db>{dbInstance}/{dbName}</db> {dbFolder}"
+    acc.merge(addFolders(flags, folder_string, className="CondAttrListCollection"))
     return acc
 
diff --git a/xAOD/xAODFaserLHC/Root/xAODFaserLHCDataAux_v1.cxx b/xAOD/xAODFaserLHC/Root/FaserLHCDataAux_v1.cxx
similarity index 77%
rename from xAOD/xAODFaserLHC/Root/xAODFaserLHCDataAux_v1.cxx
rename to xAOD/xAODFaserLHC/Root/FaserLHCDataAux_v1.cxx
index 37e37fa78..e9b981b33 100644
--- a/xAOD/xAODFaserLHC/Root/xAODFaserLHCDataAux_v1.cxx
+++ b/xAOD/xAODFaserLHC/Root/FaserLHCDataAux_v1.cxx
@@ -16,30 +16,39 @@ namespace xAOD {
       beamMode(""),
       beamType1(0),
       beamType2(0),
-      numBunchBeam1(0),
-      numBunchBeam2(0),
-      numBunchColliding(0),
       betaStar(0),
       crossingAngle(0),
+      stableBeams(false),
       injectionScheme(""),
+      numBunchBeam1(0),
+      numBunchBeam2(0),
+      numBunchColliding(0),
       distanceToCollidingBCID(0),
       distanceToUnpairedB1(0),
-      distanceToUnpairedB2(0)
+      distanceToUnpairedB2(0),
+      distanceToInboundB1(0),
+      distanceToTrainStart(0),
+      distanceToPreviousColliding(0)
   {
     AUX_VARIABLE( fillNumber );
     AUX_VARIABLE( machineMode );
     AUX_VARIABLE( beamMode );
     AUX_VARIABLE( beamType1 );
     AUX_VARIABLE( beamType2 );
-    AUX_VARIABLE( numBunchBeam1 );
-    AUX_VARIABLE( numBunchBeam2 );
-    AUX_VARIABLE( numBunchColliding );
     AUX_VARIABLE( betaStar );
     AUX_VARIABLE( crossingAngle );
+    AUX_VARIABLE( stableBeams );
     AUX_VARIABLE( injectionScheme );
+    AUX_VARIABLE( numBunchBeam1 );
+    AUX_VARIABLE( numBunchBeam2 );
+    AUX_VARIABLE( numBunchColliding );
     AUX_VARIABLE( distanceToCollidingBCID );
     AUX_VARIABLE( distanceToUnpairedB1 );
     AUX_VARIABLE( distanceToUnpairedB2 );
+    AUX_VARIABLE( distanceToInboundB1 );
+    AUX_VARIABLE( distanceToTrainStart );
+    AUX_VARIABLE( distanceToPreviousColliding );
+
   }
 
 } // namespace xAOD
diff --git a/xAOD/xAODFaserLHC/Root/xAODFaserLHCData_v1.cxx b/xAOD/xAODFaserLHC/Root/FaserLHCData_v1.cxx
similarity index 82%
rename from xAOD/xAODFaserLHC/Root/xAODFaserLHCData_v1.cxx
rename to xAOD/xAODFaserLHC/Root/FaserLHCData_v1.cxx
index 05403bcfc..b09c8c85d 100644
--- a/xAOD/xAODFaserLHC/Root/xAODFaserLHCData_v1.cxx
+++ b/xAOD/xAODFaserLHC/Root/FaserLHCData_v1.cxx
@@ -34,24 +34,27 @@ namespace xAOD {
   AUXSTORE_PRIMITIVE_SETTER_AND_GETTER( FaserLHCData_v1, int,
 					beamType2, set_beamType2 )
 
-  AUXSTORE_PRIMITIVE_SETTER_AND_GETTER( FaserLHCData_v1, unsigned int, 
-					numBunchBeam1, set_numBunchBeam1 )
-
-  AUXSTORE_PRIMITIVE_SETTER_AND_GETTER( FaserLHCData_v1, unsigned int, 
-					numBunchBeam2, set_numBunchBeam2 )
-
-  AUXSTORE_PRIMITIVE_SETTER_AND_GETTER( FaserLHCData_v1, unsigned int, 
-					numBunchColliding, set_numBunchColliding )
-
   AUXSTORE_PRIMITIVE_SETTER_AND_GETTER( FaserLHCData_v1, float, 
 					betaStar, set_betaStar )
 
   AUXSTORE_PRIMITIVE_SETTER_AND_GETTER( FaserLHCData_v1, float, 
 					crossingAngle, set_crossingAngle )
 
+  AUXSTORE_PRIMITIVE_SETTER_AND_GETTER( FaserLHCData_v1, bool, 
+					stableBeams, set_stableBeams )
+
   AUXSTORE_PRIMITIVE_SETTER_AND_GETTER( FaserLHCData_v1, std::string, 
 					injectionScheme, set_injectionScheme )
 
+  AUXSTORE_PRIMITIVE_SETTER_AND_GETTER( FaserLHCData_v1, unsigned int, 
+					numBunchBeam1, set_numBunchBeam1 )
+
+  AUXSTORE_PRIMITIVE_SETTER_AND_GETTER( FaserLHCData_v1, unsigned int, 
+					numBunchBeam2, set_numBunchBeam2 )
+
+  AUXSTORE_PRIMITIVE_SETTER_AND_GETTER( FaserLHCData_v1, unsigned int, 
+					numBunchColliding, set_numBunchColliding )
+
   AUXSTORE_PRIMITIVE_SETTER_AND_GETTER( FaserLHCData_v1, int, 
 					distanceToCollidingBCID, set_distanceToCollidingBCID )
 
@@ -61,6 +64,17 @@ namespace xAOD {
   AUXSTORE_PRIMITIVE_SETTER_AND_GETTER( FaserLHCData_v1, int, 
 					distanceToUnpairedB2, set_distanceToUnpairedB2 )
 
+  AUXSTORE_PRIMITIVE_SETTER_AND_GETTER( FaserLHCData_v1, int, 
+					distanceToInboundB1, set_distanceToInboundB1 )
+
+  AUXSTORE_PRIMITIVE_SETTER_AND_GETTER( FaserLHCData_v1, unsigned int, 
+					distanceToTrainStart, set_distanceToTrainStart )
+
+  AUXSTORE_PRIMITIVE_SETTER_AND_GETTER( FaserLHCData_v1, unsigned int, 
+					distanceToPreviousColliding, set_distanceToPreviousColliding )
+
+
+
 } // namespace xAOD
 
 namespace xAOD {
diff --git a/xAOD/xAODFaserLHC/xAODFaserLHC/versions/FaserLHCDataAux_v1.h b/xAOD/xAODFaserLHC/xAODFaserLHC/versions/FaserLHCDataAux_v1.h
index c2daf68db..bc1034143 100644
--- a/xAOD/xAODFaserLHC/xAODFaserLHC/versions/FaserLHCDataAux_v1.h
+++ b/xAOD/xAODFaserLHC/xAODFaserLHC/versions/FaserLHCDataAux_v1.h
@@ -41,18 +41,24 @@ namespace xAOD {
     int beamType1;
     int beamType2;
 
-    unsigned int numBunchBeam1;
-    unsigned int numBunchBeam2;
-    unsigned int numBunchColliding;
-
     float betaStar;
     float crossingAngle;
 
+    bool stableBeams;
     std::string injectionScheme;
 
+    unsigned int numBunchBeam1;
+    unsigned int numBunchBeam2;
+    unsigned int numBunchColliding;
+
     int distanceToCollidingBCID;
     int distanceToUnpairedB1;
     int distanceToUnpairedB2;
+    int distanceToInboundB1;
+
+    unsigned int distanceToTrainStart;
+    unsigned int distanceToPreviousColliding;
+
     /// @}
 
   }; // class FaserLHCDataAuxContainer_v1
diff --git a/xAOD/xAODFaserLHC/xAODFaserLHC/versions/FaserLHCData_v1.h b/xAOD/xAODFaserLHC/xAODFaserLHC/versions/FaserLHCData_v1.h
index 982ce1053..fd6c68cc0 100644
--- a/xAOD/xAODFaserLHC/xAODFaserLHC/versions/FaserLHCData_v1.h
+++ b/xAOD/xAODFaserLHC/xAODFaserLHC/versions/FaserLHCData_v1.h
@@ -31,6 +31,7 @@ namespace xAOD {
 
     /// First batch comes from ATLAS /LHC/DCS/FILLSTATE folder
     /// which is a copy of information sent to ATLAS by LHC over DIP
+    /// This is from the FASER COOL folder /LHC/BeamData
 
     /// LHC fill number
     unsigned int fillNumber() const;
@@ -51,14 +52,6 @@ namespace xAOD {
     int beamType2() const;
     void set_beamType2(int value);
 
-    /// Nominal bunches (derived from DIP "Circulating Bunch Configuration")
-    unsigned int numBunchBeam1() const;
-    void set_numBunchBeam1(unsigned int value);
-    unsigned int numBunchBeam2() const;
-    void set_numBunchBeam2(unsigned int value);
-    unsigned int numBunchColliding() const;
-    void set_numBunchColliding(unsigned int value);
-
     // Beta* at IP1, in cm
     float betaStar() const;
     void set_betaStar(float value);
@@ -67,14 +60,29 @@ namespace xAOD {
     float crossingAngle() const;
     void set_crossingAngle(float value);
 
+    // LHC stable beam flag
+    bool stableBeams() const;
+    void set_stableBeams(bool value);
+
     // Injection scheme
     std::string injectionScheme() const;
     void set_injectionScheme(std::string value);
 
     // Second batch is information is related to the BCID structure
+    // This comes from the LPC filling scheme (nominal values)
+    // and is stored in /LHC/BCIDData
+
+    /// Nominal bunches (derived from DIP "Circulating Bunch Configuration")
+    unsigned int numBunchBeam1() const;
+    void set_numBunchBeam1(unsigned int value);
+    unsigned int numBunchBeam2() const;
+    void set_numBunchBeam2(unsigned int value);
+    unsigned int numBunchColliding() const;
+    void set_numBunchColliding(unsigned int value);
 
     // Number of BCIDs difference between current event BCID (from EventInfo)
     // and a colliding BCID in the nominal bunch pattern
+
     int distanceToCollidingBCID() const;
     void set_distanceToCollidingBCID(int value);
 
@@ -84,8 +92,24 @@ namespace xAOD {
     int distanceToUnpairedB2() const;
     void set_distanceToUnpairedB2(int value);
 
-    /// Collimator settings?
+    int distanceToInboundB1() const;
+    void set_distanceToInboundB1(int value);
+
+    /// Distance of current BCID to start of previous bunch train
+    unsigned int distanceToTrainStart() const;
+    void set_distanceToTrainStart(unsigned int value);
+
+    /// Distance of current BCID frmo previous colliding BCID (0 if this is colliding)
+    unsigned int distanceToPreviousColliding() const;
+    void set_distanceToPreviousColliding(unsigned int value);
 
+    /// Simple boolean functions to access useful values
+    /// In most cases, these check that the distance above is zero
+    bool isStable() const { return this->stableBeams(); }
+    bool isColliding() const { return this->distanceToCollidingBCID() == 0; }
+    bool isUnpairedBeam1() const { return this->distanceToUnpairedB1() == 0; }
+    bool isUnpairedBeam2() const { return this->distanceToUnpairedB2() == 0; }
+    bool isInboundBeam1() const { return this->distanceToInboundB1() == 0; }
 
     /// @}
 
-- 
GitLab