Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions offline/packages/bcolumicount/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,10 @@ pkginclude_HEADERS = \
StreamingBcoInfov1.h \
StreamingLumiInfo.h \
StreamingLumiInfov1.h \
StreamingBcoLumiReco.h \
StreamingBcoLumiCheck.h
StreamingBcoReco.h \
StreamingBcoCheck.h \
StreamingLumiReco.h \
StreamingLumiCheck.h


libbcolumicount_io_la_SOURCES = \
Expand All @@ -59,8 +61,10 @@ libbcolumicount_io_la_SOURCES = \

libbcolumicount_la_SOURCES = \
BcoLumiReco.cc \
StreamingBcoLumiReco.cc \
StreamingBcoLumiCheck.cc
StreamingBcoReco.cc \
StreamingBcoCheck.cc \
StreamingLumiReco.cc \
StreamingLumiCheck.cc

BUILT_SOURCES = testexternals.cc

Expand Down
69 changes: 69 additions & 0 deletions offline/packages/bcolumicount/StreamingBcoCheck.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#include "StreamingBcoCheck.h"

//#include "BcoInfo.h"
#include "StreamingBcoInfo.h"
#include "StreamingLumiInfo.h"
//#include "BcoStreamingLumiInfov1.h"


#include <ffaobjects/SyncDefs.h>
#include <ffaobjects/SyncObject.h>

#include <ffarawobjects/Gl1Packet.h>

#include <fun4all/Fun4AllReturnCodes.h>
#include <fun4all/SubsysReco.h> // for SubsysReco
#include <fun4all/Fun4AllHistoManager.h>
#include <fun4all/Fun4AllServer.h>


#include <phool/PHCompositeNode.h>
#include <phool/PHNode.h> // for PHNode
#include <phool/PHNodeIterator.h> // for PHNodeIterator
#include <phool/getClass.h>
#include <phool/phool.h> // for PHWHERE


#include <iostream>

StreamingBcoCheck::StreamingBcoCheck(const std::string &name)
: SubsysReco(name)
{
return;
}

int StreamingBcoCheck::Init(PHCompositeNode *topNode)
{
int iret = CreateNodeTree(topNode);

return iret;
}

int StreamingBcoCheck::CreateNodeTree(PHCompositeNode *topNode)
{
PHNodeIterator iter(topNode);
PHCompositeNode *dstNode;
dstNode = dynamic_cast<PHCompositeNode *>(iter.findFirst("PHCompositeNode", "DST"));
if (!dstNode)
{
std::cout << PHWHERE << " DST Node is missing doing nothing" << std::endl;
return Fun4AllReturnCodes::ABORTRUN;
}
return Fun4AllReturnCodes::EVENT_OK;
}

int StreamingBcoCheck::process_event(PHCompositeNode *topNode)
{
StreamingBcoInfo *streaming_bco_info = findNode::getClass<StreamingBcoInfo>(topNode, "STREAMINGBCOINFO");
if (streaming_bco_info)
{
if (Verbosity() > 1)
{
std::cout << "bco : " << streaming_bco_info->get_bco() << std::endl;
std::cout << "usable bco tag : " << streaming_bco_info->get_usable_bco_tag() << std::endl;
std::cout << "bco streaming window : (" << streaming_bco_info->get_bco_streaming_window().first << ", " << streaming_bco_info->get_bco_streaming_window().second << ")" << std::endl;
}
}

return Fun4AllReturnCodes::EVENT_OK;
Comment on lines +55 to +68

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Fail fast when STREAMINGBCOINFO is missing.

This checker currently returns EVENT_OK even when its required input node is absent, so a broken StreamingBcoReco/checker wiring silently looks healthy. StreamingBcoReco's downstream contract treats a missing STREAMINGBCOINFO as an abort condition, so the validator should do the same here.

Suggested fix
 int StreamingBcoCheck::process_event(PHCompositeNode *topNode)
 {
   StreamingBcoInfo *streaming_bco_info = findNode::getClass<StreamingBcoInfo>(topNode, "STREAMINGBCOINFO");
-  if (streaming_bco_info)
-  {
-    if (Verbosity() > 1)
-    {
-      std::cout << "bco : " << streaming_bco_info->get_bco() << std::endl;
-      std::cout << "usable bco tag : " << streaming_bco_info->get_usable_bco_tag() << std::endl;
-      std::cout << "bco streaming window : (" <<  streaming_bco_info->get_bco_streaming_window().first << ", " << streaming_bco_info->get_bco_streaming_window().second << ")" << std::endl;
-    }
-  }
+  if (!streaming_bco_info)
+  {
+    std::cout << PHWHERE << " STREAMINGBCOINFO node missing" << std::endl;
+    return Fun4AllReturnCodes::ABORTEVENT;
+  }
+
+  if (Verbosity() > 1)
+  {
+    std::cout << "bco : " << streaming_bco_info->get_bco() << std::endl;
+    std::cout << "usable bco tag : " << streaming_bco_info->get_usable_bco_tag() << std::endl;
+    std::cout << "bco streaming window : (" << streaming_bco_info->get_bco_streaming_window().first
+              << ", " << streaming_bco_info->get_bco_streaming_window().second << ")" << std::endl;
+  }
   
   return Fun4AllReturnCodes::EVENT_OK;
 }

As per path instructions, this code path should prioritize correctness and error handling.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
int StreamingBcoCheck::process_event(PHCompositeNode *topNode)
{
StreamingBcoInfo *streaming_bco_info = findNode::getClass<StreamingBcoInfo>(topNode, "STREAMINGBCOINFO");
if (streaming_bco_info)
{
if (Verbosity() > 1)
{
std::cout << "bco : " << streaming_bco_info->get_bco() << std::endl;
std::cout << "usable bco tag : " << streaming_bco_info->get_usable_bco_tag() << std::endl;
std::cout << "bco streaming window : (" << streaming_bco_info->get_bco_streaming_window().first << ", " << streaming_bco_info->get_bco_streaming_window().second << ")" << std::endl;
}
}
return Fun4AllReturnCodes::EVENT_OK;
int StreamingBcoCheck::process_event(PHCompositeNode *topNode)
{
StreamingBcoInfo *streaming_bco_info = findNode::getClass<StreamingBcoInfo>(topNode, "STREAMINGBCOINFO");
if (!streaming_bco_info)
{
std::cout << PHWHERE << " STREAMINGBCOINFO node missing" << std::endl;
return Fun4AllReturnCodes::ABORTEVENT;
}
if (Verbosity() > 1)
{
std::cout << "bco : " << streaming_bco_info->get_bco() << std::endl;
std::cout << "usable bco tag : " << streaming_bco_info->get_usable_bco_tag() << std::endl;
std::cout << "bco streaming window : (" << streaming_bco_info->get_bco_streaming_window().first << ", " << streaming_bco_info->get_bco_streaming_window().second << ")" << std::endl;
}
return Fun4AllReturnCodes::EVENT_OK;

Source: Path instructions

}
25 changes: 25 additions & 0 deletions offline/packages/bcolumicount/StreamingBcoCheck.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#ifndef BCOLUMICOUNT_STREAMINGBCOCHECK_H
#define BCOLUMICOUNT_STREAMINGBCOCHECK_H

#include <fun4all/SubsysReco.h>
#include <fun4all/Fun4AllHistoManager.h>

#include <string>

#include <TH1.h>


class StreamingBcoCheck : public SubsysReco
{
public:
StreamingBcoCheck(const std::string &name = "BCOCHECKSTREAMINGOUTPUT");
~StreamingBcoCheck() override = default;

int Init(PHCompositeNode *topNode) override;
int process_event(PHCompositeNode *topNode) override;

private:
static int CreateNodeTree(PHCompositeNode *topNode);
};

#endif // BCOLUMICOUNT_STREAMINGBCOCHECK_H
26 changes: 0 additions & 26 deletions offline/packages/bcolumicount/StreamingBcoLumiCheck.h

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
#include "StreamingBcoLumiReco.h"
#include "StreamingBcoReco.h"

#include "BcoInfo.h"
#include "StreamingBcoInfo.h"
#include "StreamingBcoInfov1.h"
#include "StreamingLumiInfo.h"
#include "StreamingLumiInfov1.h"


#include <ffaobjects/SyncDefs.h>
Expand Down Expand Up @@ -32,7 +30,7 @@

#include <iostream>

StreamingBcoLumiReco::StreamingBcoLumiReco(const std::string &name)
StreamingBcoReco::StreamingBcoReco(const std::string &name)
: SubsysReco(name)
{
hm = new Fun4AllHistoManager("bco_histos");
Expand All @@ -41,7 +39,7 @@ StreamingBcoLumiReco::StreamingBcoLumiReco(const std::string &name)
return;
}

int StreamingBcoLumiReco::Init(PHCompositeNode *topNode)
int StreamingBcoReco::Init(PHCompositeNode *topNode)
{
int iret = CreateNodeTree(topNode);
h_bco_diff = new TH1I("h_bco_diff", ";bco diff;", 3500, 0, 3500);
Expand All @@ -59,27 +57,7 @@ int StreamingBcoLumiReco::Init(PHCompositeNode *topNode)
return iret;
}

int StreamingBcoLumiReco::InitRun(PHCompositeNode * topNode)
{
PHNodeIterator iter(topNode);
PHCompositeNode *runNode;
runNode = dynamic_cast<PHCompositeNode *>(iter.findFirst("PHCompositeNode", "RUN"));
if (!runNode)
{
std::cout << PHWHERE << " Run Node is missing doing nothing" << std::endl;
return Fun4AllReturnCodes::ABORTRUN;
}
m_streaming_lumi_info = findNode::getClass<StreamingLumiInfo>(topNode, "STREAMINGLUMIINFO");
if (!m_streaming_lumi_info)
{
m_streaming_lumi_info = new StreamingLumiInfov1();
PHIODataNode<PHObject> *luminode = new PHIODataNode<PHObject>(m_streaming_lumi_info, "STREAMINGLUMIINFO", "PHObject");
runNode->addNode(luminode);
}
return Fun4AllReturnCodes::EVENT_OK;
}

int StreamingBcoLumiReco::CreateNodeTree(PHCompositeNode *topNode)
int StreamingBcoReco::CreateNodeTree(PHCompositeNode *topNode)
{
PHNodeIterator iter(topNode);
PHCompositeNode *dstNode;
Expand All @@ -99,7 +77,7 @@ int StreamingBcoLumiReco::CreateNodeTree(PHCompositeNode *topNode)
return Fun4AllReturnCodes::EVENT_OK;
}

int StreamingBcoLumiReco::process_event(PHCompositeNode *topNode)
int StreamingBcoReco::process_event(PHCompositeNode *topNode)
{
BcoInfo *bcoinfo = findNode::getClass<BcoInfo>(topNode, "BCOINFO");
SyncObject *syncobject = findNode::getClass<SyncObject>(topNode, syncdefs::SYNCNODENAME);
Expand Down Expand Up @@ -140,17 +118,6 @@ int StreamingBcoLumiReco::process_event(PHCompositeNode *topNode)
return Fun4AllReturnCodes::ABORTEVENT;
}

// SYNTAX TAKEN FROM ZHIWANS CODE, why = and not +=? If this is correct it seems like a waste to call it for every event (would just need it for the last event in a particular crossing?)
m_bunchnumber_MBDNS_raw[bunchno] = packet->lValue(0, "GL1PRAW");
m_bunchnumber_MBDNS_live[bunchno] = packet->lValue(0, "GL1PLIVE");
m_bunchnumber_MBDNS_scaled[bunchno] = packet->lValue(0, "GL1PSCALED");


if(packet->lValue(0, 0))
{
m_rawgl1scaler = packet->lValue(0, 0);
}

delete packet;

if (Verbosity() > 2)
Expand Down Expand Up @@ -223,33 +190,6 @@ int StreamingBcoLumiReco::process_event(PHCompositeNode *topNode)
h_bco_diff_trigbits[bit]->Fill(bco_diff_prev);
}
}
// Double check Zhiwan's logic for assigning the adjusted bunch!
int lower = m_bco_streaming_window.first - m_bco;
int upper = m_bco_streaming_window.second - m_bco;
for(int i = lower; i< upper;i++)
{
int adjusted_bunch = bunchno + i;
while (adjusted_bunch < 0)
{
adjusted_bunch += 120;
}
while (adjusted_bunch > 119)
{
adjusted_bunch -= 120;
}
// ABORT GAP!
if (adjusted_bunch>110) { continue; }

// Make sure this is the correct way to count crossings! Need to zero out for each run!
if(i!=0 || m_usable_bco_tag)
{
m_bunchnumber_crossings[adjusted_bunch] += 1;
}
//else if (m_usable_bco_tag)
//{
// m_bunchnumber_crossings[adjusted_bunch] += 1;
//}
}

streaming_bco_info->set_bco(get_bco());
streaming_bco_info->set_usable_bco_tag(get_usable_bco_tag());
Expand All @@ -262,50 +202,3 @@ int StreamingBcoLumiReco::process_event(PHCompositeNode *topNode)
}
return Fun4AllReturnCodes::EVENT_OK;
}

int StreamingBcoLumiReco::EndRun(int /*runnumber*/)
{
uint64_t rawgl1scalers_per_bunch = m_rawgl1scaler/120.;
for (int i=0; i<m_bunches; i++)
{
m_bunchnumber_lumi_raw[i] = ( m_bunchnumber_crossings[i] * m_bunchnumber_MBDNS_raw[i] ) / ( rawgl1scalers_per_bunch * m_xsec_MBDNS );
m_bunchnumber_lumi_live[i] = ( m_bunchnumber_crossings[i] * m_bunchnumber_MBDNS_live[i]) / ( rawgl1scalers_per_bunch * m_xsec_MBDNS );
m_bunchnumber_lumi_scaled[i] = ( m_bunchnumber_crossings[i] * m_bunchnumber_MBDNS_scaled[i] ) / ( rawgl1scalers_per_bunch * m_xsec_MBDNS );

m_lumi_raw += m_bunchnumber_lumi_raw[i];
m_lumi_live += m_bunchnumber_lumi_live[i];
m_lumi_scaled += m_bunchnumber_lumi_scaled[i];

if (Verbosity() > 1)
{
std::cout << "bunchno : " << i << " lumi_raw : " << m_bunchnumber_lumi_raw[i] << std::endl;
}
}
if (!m_streaming_lumi_info)
{
std::cout << PHWHERE << " STREAMINGLUMIINFO node missing in EndRun" << std::endl;
return Fun4AllReturnCodes::ABORTRUN;
}
m_streaming_lumi_info->set_lumi_raw(get_lumi_raw());
m_streaming_lumi_info->set_lumi_live(get_lumi_live());
m_streaming_lumi_info->set_lumi_scaled(get_lumi_scaled());
if (Verbosity() > 1)
{
std::cout << "MBD xsec : " << m_xsec_MBDNS << std::endl;
std::cout << "total lumi (raw) : " << m_lumi_raw << std::endl;
}

m_bunchnumber_lumi_raw.fill(0);
m_bunchnumber_lumi_live.fill(0);
m_bunchnumber_lumi_scaled.fill(0);
m_bunchnumber_crossings.fill(0);
m_bunchnumber_MBDNS_raw.fill(0);
m_bunchnumber_MBDNS_live.fill(0);
m_bunchnumber_MBDNS_scaled.fill(0);
m_lumi_raw = 0.;
m_lumi_live = 0.;
m_lumi_scaled = 0.;
m_rawgl1scaler = 0;

return Fun4AllReturnCodes::EVENT_OK;
}
52 changes: 52 additions & 0 deletions offline/packages/bcolumicount/StreamingBcoReco.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#ifndef BCOLUMICOUNT_STREAMINGBCORECO_H
#define BCOLUMICOUNT_STREAMINGBCORECO_H

#include <fun4all/SubsysReco.h>
#include <fun4all/Fun4AllHistoManager.h>

#include <string>
#include <utility>
#include <array>

class TH1;

class StreamingBcoReco : public SubsysReco

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is replacing StreamingBcoLumiReco.h but you didn't do a git mv StreamingBcoLumiReco.h StreamingBcoReco.h - is my understanding right? Then we should git rm the old file

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I did not use the cleanest workflow here. I started with the StreamingBcoLumiReco* files, made copies of them (just with cp), renamed the old and new set of files (just with mv), and then dealt with all of the git stuff when all was said and done just using git rm and git add. I must have missed one, and I don't know how git decided which files I renamed since I never used git mv. I can be more careful about this in the future.

I believe you are right and we can git rm StreamingBcoLumiReco.h

@dillfitz dillfitz Jun 27, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After double checking, it looks like all the correct files are already there with no extras, though it looks very confusing how git decided to rename vs remove / add files. Ignoring the small changes to the StreamingLumiInfo class, I had to create 4 new files, and modify 4 existing files, basically by copying the 4 old StreamingBcoLumiReco and StreamingBcoLumiCheck files and renaming them accordingly. In the end, git decided that I added 5 files, removed 1, and renamed 3, which is effectively the same as renaming 4 and adding 4. I think git decided some files were just renamed based on how closely they resembled the old files -- but I only used git add and git rm.

{
public:
StreamingBcoReco(const std::string &name = "STREAMINGBCOLUMIRECO");
~StreamingBcoReco() override = default;

int Init(PHCompositeNode *topNode) override;
int process_event(PHCompositeNode *topNode) override;

virtual int get_evtno() const { return m_evtno; }

virtual uint64_t get_bco() const { return m_bco; }

virtual bool get_usable_bco_tag() const { return m_usable_bco_tag; }

virtual std::pair<uint64_t, uint64_t> get_bco_streaming_window() const { return m_bco_streaming_window; }

virtual void set_default_positive_window_length(int val) { m_default_positive_window_length = val; }
virtual void set_default_negative_window_length(int val) { m_default_negative_window_length = val; }
Comment on lines +30 to +31

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Reject negative window lengths at the API boundary.

These setters take int, but the stored members are unsigned int (Lines 48-49). A negative value from a macro/config silently wraps to a multi-billion-crossing window and poisons the downstream BCO/lumi windowing. If the signed signature is needed for compatibility, please range-check before assignment; the same issue is mirrored in StreamingLumiReco.h. As per path instructions, **/*.{h,hpp,hxx,hh} reviews should focus on API clarity/stability and only raise Critical or Major findings.

Source: Path instructions




private:
static int CreateNodeTree(PHCompositeNode *topNode);
const int trigbits = 40;
Fun4AllHistoManager *hm = nullptr;
TH1 *h_bco_diff = nullptr;
TH1 *h_bco_diff_trigbits[40] = {nullptr};
TH1 *h_bco_tag = nullptr;

uint64_t m_bco{0};
int m_bunches = 120;
int m_evtno{0};
bool m_usable_bco_tag = false;
std::pair<uint64_t, uint64_t> m_bco_streaming_window;
unsigned int m_default_positive_window_length{340};
unsigned int m_default_negative_window_length{20};
};

#endif // BCOLUMICOUNT_STREAMINGBCORECO_H
Loading