Skip to content
Open
99 changes: 97 additions & 2 deletions offline/framework/fun4allraw/Fun4AllStreamingInputManager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -710,6 +710,38 @@ int Fun4AllStreamingInputManager::FillIntt()
}
}

// hit duplication:add hits in N + [1..M] * shift BCOs
if (m_InttHitDuplication)
{
if (m_InttHitCarryOverShiftMaxMultiple < 1)
{
std::cout << __FILE__ << ":" << __PRETTY_FUNCTION__ << ":" << __LINE__ << ": m_InttHitDuplication is set to true but m_InttHitCarryOverShiftMaxMultiple=" << m_InttHitCarryOverShiftMaxMultiple << "is not positive. Default to 1" << std::endl;
m_InttHitCarryOverShiftMaxMultiple = 1;
}

const uint64_t max_shift = m_InttHitCarryOverShift * m_InttHitCarryOverShiftMaxMultiple;
const uint64_t bco_duplicate_high = select_crossings + max_shift;

// now fill the pool until the highest bco in the map is higher than the duplication threshold, which is the select_crossings + the maximum shift we want to do
while (m_InttRawHitMap.rbegin()->first < bco_duplicate_high) // if the highest bco is still smaller than the duplication threshold, keep duplicating
{
const uint64_t previous_high_bco = m_InttRawHitMap.rbegin()->first;
iret = FillInttPool();
if (iret)
{
break; // if FillInttPool returns non zero, there is no more data to read and we can stop trying to duplicate
}
// Note: need this guard. FillInttPool() only returns non-0 if m_InttRawHitMap is empty
// FillInttPool() calls SingleInttPoolInput::FillPool() returns regardless of whether it actually fill new data or not
// So if FillInttPool() is called and there is no new data to pool, it will return 0 but m_InttRawHitMap will not have changed (non-empty)
// If we don't check for this, it would cause an infinite loop
if (m_InttRawHitMap.rbegin()->first == previous_high_bco)
{
break;
}
}
}

unsigned int refbcobitshift = m_RefBCO & 0x3FU;
bool allpackets = true;
int allpacketsallfees = 0;
Expand Down Expand Up @@ -777,7 +809,7 @@ int Fun4AllStreamingInputManager::FillIntt()
h_taggedAllFee_intt->Fill(refbcobitshift);
}

for (auto& [bco, hitinfo] : m_InttRawHitMap)
for (auto &[bco, hitinfo] : m_InttRawHitMap)
{
if (bco > select_crossings)
{
Expand All @@ -794,6 +826,69 @@ int Fun4AllStreamingInputManager::FillIntt()
}
inttcont->AddHit(intthititer);
}

// The duplication consists of 2 passes
// Pass 1: Insert duplication of hits in N + [1..M] * shift BCOs
// the "second" pass duplicates hits whose FPHX BCO was reset to 0
// Also, the "second" pass needs to handle the case where the hits with FPHX BCO = 0 are already duplicated from the "first" pass
// This happens when target_refbco = bco % m_InttHitCarryOverShift is 0 and reset_shift = m_InttHitCarryOverShift * s
// If this is the case, do not duplicate the hits again
if (m_InttHitDuplication)
{
const uint64_t target_refbco = bco % m_InttHitCarryOverShift;

for (int shift_multiple = 1; shift_multiple <= m_InttHitCarryOverShiftMaxMultiple; ++shift_multiple)
{
const uint64_t shift = m_InttHitCarryOverShift * shift_multiple;
const uint64_t source_bco = bco + shift;
auto source_iter = m_InttRawHitMap.find(source_bco);

if (source_iter != m_InttRawHitMap.end())
{
for (auto *source_hit : source_iter->second.InttRawHitVector)
{
if (source_hit->get_bco() < shift)
{
continue;
}

auto *copied_hit = inttcont->AddHit(source_hit);
copied_hit->set_bco(source_hit->get_bco() - shift);
}
}

if (target_refbco == 0)
{
continue; // if target_refbco is 0, the hits with FPHX BCO = 0 are already duplicated in the first pass, so skip the second pass to avoid double duplication
}

const uint64_t reset_shift = shift - target_refbco;
const uint64_t reset_source_bco = bco + reset_shift;
auto reset_source_iter = m_InttRawHitMap.find(reset_source_bco);
if (reset_source_iter == m_InttRawHitMap.end())
{
continue;
}

for (auto *source_hit : reset_source_iter->second.InttRawHitVector)
{
// skip hits whose FPHX BCO is not 0
if (source_hit->get_FPHX_BCO() != 0)
{
continue;
}

// also skip hits whose strobe BCO is smaller than the reset shift
if (source_hit->get_bco() < reset_shift)
{
continue;
}

auto *copied_hit = inttcont->AddHit(source_hit);
copied_hit->set_bco(source_hit->get_bco() - reset_shift);
}
}
}
}
return 0;
}
Expand Down Expand Up @@ -974,7 +1069,7 @@ int Fun4AllStreamingInputManager::FillMvtx()
uint64_t lower_limit = m_mvtx_is_triggered ? select_crossings : select_crossings - m_mvtx_bco_range - m_mvtx_negative_bco;
uint64_t upper_limit = m_mvtx_is_triggered ? select_crossings + m_mvtx_bco_range : select_crossings;

for (auto& [bco, hitinfo] : m_MvtxRawHitMap)
for (auto &[bco, hitinfo] : m_MvtxRawHitMap)
{
if (bco < lower_limit)
{
Expand Down
11 changes: 10 additions & 1 deletion offline/framework/fun4allraw/Fun4AllStreamingInputManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <map>
#include <set>
#include <string>
#include <vector>

class SingleStreamingInput;
class Gl1Packet;
Expand Down Expand Up @@ -69,6 +70,10 @@ class Fun4AllStreamingInputManager : public Fun4AllInputManager

void runMvtxTriggered(bool b = true) { m_mvtx_is_triggered = b; }

// configuration for INTT hit carry-over issue mitigation (hit duplication)
void EnableInttHitDuplication(bool b = true) { m_InttHitDuplication = b; }
void InttHitCarryOverShiftMaxMultiple(const int i) { m_InttHitCarryOverShiftMaxMultiple = i; }

private:
struct MvtxRawHitInfo
{
Expand Down Expand Up @@ -159,6 +164,10 @@ class Fun4AllStreamingInputManager : public Fun4AllInputManager
TH1 *h_taggedAllFees_intt[8]{nullptr};
TH1 *h_gl1taggedfee_intt[8][14]{{nullptr}};
TH2 *h_bcodiff_intt[8]{nullptr};
};

// for INTT hit carry-over issue mitigation (hit duplication)
bool m_InttHitDuplication{false}; // default to false; Should be set to true when running streaming data
const unsigned int m_InttHitCarryOverShift{120}; // 120 BCOs as the default shift. Fixed value
int m_InttHitCarryOverShiftMaxMultiple{4}; // the max multiple of the shift. For a max multiple of M, duplicate hits from N + [1..M] * shift BCOs to N
};
#endif /* FUN4ALL_FUN4ALLSTREAMINGINPUTMANAGER_H */