-
Notifications
You must be signed in to change notification settings - Fork 0
Test2 #13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Test2 #13
Conversation
Fill ntuple for both matched and unmatched waveforms
…s_pool_evaluation_update Small update on TPOT event combining evaluation
if multiple hits are found on the same strip only the first one, timewise, is kept.
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
add quality flag to total energy calc and correlations
fix: clang-format track fitter
…e into KFParticle
…-afterburner No flow afterburner
…transforms New tpc transforms
…e-cout Preserve cout
abort events with any mbd packet empty
New QA module to make cluster-state residual plots
…ticle Stop KFP from aborting events
…runer feat: flag to prune all seeds
Additional calo embedding features
📝 WalkthroughWalkthroughThe pull request spans multiple detector subsystems with diverse enhancements: introduces a new HepMC particle-based trigger class with configurable kinematic cuts, modernizes codebase with C++20 features (std::format), enhances stream state preservation during framework initialization, extends micromegas hit key tracking to include sample indices, adds new state-cluster residuals QA module, improves calorimeter QA gating logic, and refactors legacy code with const-correctness and contemporary C++ idioms throughout TPC, MVTX, and framework components. Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes The review spans heterogeneous changes across 70+ files with mixed complexity: new particle-based trigger class with kinematic filtering logic, modernized C++ patterns throughout, const-correctness additions, new QA module with configurable residuals, stream state preservation mechanisms, forward declaration removals (compilation risk), refactored raw-data processing loops, extended hit key representation, and framework hook additions. While many individual changes follow consistent patterns (formatting, const-correctness, auto→auto*), each cohort requires separate reasoning. The duplicate member declaration in Fun4AllServer.h is a potential blocker requiring clarification. High disparity between file count, change heterogeneity, and logic density. Poem
🚥 Pre-merge checks | ❌ 3❌ Failed checks (2 warnings, 1 inconclusive)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This pull request contains a large set of code modernization, refactoring, and feature additions across the offline reconstruction and analysis framework. The changes include code style improvements (const-correctness, auto* usage, formatting), algorithmic optimizations (std::min/max), new analysis modules, and bug fixes.
Changes:
- Code style modernization: const-correctness for string parameters, auto* for pointers, consistent formatting
- Performance improvements: replacing manual comparisons with std::min/std::max
- New features: flow calibration system for jet background, tower combination utility, state-cluster residuals QA
- Bug fixes: micromegas hit key sample tracking, MVTX/INTT pool filling logic, MBD empty packet handling
Reviewed changes
Copilot reviewed 87 out of 87 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| PHTpcDeltaZCorrection.h, PHSimpleVertexFinder.h, PHActsTrkFitter.h, PHActsTrkFitter.cc | Added const to string parameter references for setters |
| PHSiliconTpcTrackMatching.h/.cc | Added cluster map name configurability |
| DSTClusterPruning.h/.cc | Added pruneAllSeeds feature |
| AlignmentTransformation.h/.cc | Enhanced TPC module tilt handling and transform logic |
| TrainingHits.cc | Moved member initializations to initializer list |
| TpcSimpleClusterizer.cc, TpcClusterizer.cc, etc. | Replaced manual min/max with std::min/std::max, changed auto to auto* |
| TpcRawDataTree.cc | Changed array access to .data() method |
| TpcDistortionCorrection.cc | Removed inline keyword from constexpr |
| LaserClusterizer.cc | Major formatting improvements and code cleanup |
| SegmentationAlpide.cc | Replaced boost::format with std::format |
| MvtxHitPruner.cc, MvtxClusterizer.cc | Formatting and const-correctness improvements |
| CylinderGeom_Mvtx.h/.cc | Added const to methods, removed using namespace std |
| MicromegasDefs.h/.cc | Added sample field to hit keys |
| MicromegasCombinedDataDecoder.cc | Enhanced to track sample with maximum ADC |
| MicromegasClusterizer.cc | Fixed duplicate hit handling by sample |
| MbdReco.cc, MbdEvent.cc, MbdCalib.cc | Added event number to warnings, added empty packet checks |
| DetermineTowerBackground.h/.cc | Added flow v2 calibration system |
| TriggerDSTSkimmer.h/.cc | Added max event acceptance feature |
| KFParticle_sPHENIX.cc | Changed ABORTEVENT to EVENT_OK for missing tracks/vertices |
| PhotonClusterBuilder.cc | Added e22 shower shape parameter |
| CombineTowerInfo.h/.cc | New utility for combining tower information |
| CopyIODataNodes.h/.cc | Added TowerInfo copying capability |
| SingleTriggeredInput.h/.cc | Enhanced GL1 skip logic and BCO alignment |
| SingleMvtxPoolInput.cc | Adjusted negative BCO handling |
| SingleMicromegasPoolInput_v2.h/.cc | Added matched flag to waveform structure |
| Fun4AllStreamingInputManager.cc | Refactored INTT and MVTX filling logic |
| InputFileHandler.h/.cc | Added script execution before file opening |
| Fun4AllServer.h/.cc | Added cout state restoration |
| CreateFileList.pl | Added O+O hijing production type |
| Timing.h/.cc, SyncReco.h, HeadReco.h/.cc, FlagHandler.h, CDBInterface.h/.cc | Minor cleanups |
| StateClusterResidualsQA.h/.cc | New QA module for track state-cluster residuals |
| MicromegasClusterQA.h/.cc | Added sample range filtering |
| CaloValid.h | Added trigger index 12 |
| PHHepMCGenEventv1.cc | Return NaN instead of 0 for missing flow psi |
| PHGenFit Track.cc, Fitter.cc | Code cleanup and style improvements |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 15
Note
Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (4)
offline/framework/fun4allraw/SingleMvtxPoolInput.cc (1)
210-229: Guard against emptym_BclkStackbefore dereferencingitWhen
m_BclkStackis empty,lower_boundreturnsbegin()==end()and Line 214 dereferences*it, which is UB and can crash. Add an early empty check before dereferencing.🐛 Proposed fix
- auto strb_it = m_BclkStack.cend(); + if (m_BclkStack.empty()) + { + continue; + } + auto strb_it = m_BclkStack.cend(); if (it == m_BclkStack.begin()) { if (*it == lv1Bco) { strb_it = it; } else { strb_it = m_BclkStack.cend(); } } else { // safe because it != begin() auto prev = it; --prev; strb_it = prev; }offline/framework/fun4allraw/SingleMicromegasPoolInput_v2.cc (1)
914-967: Resetfee_bco_predicted_matchedwhen no prediction is available.When the prediction is absent on a matched waveform, the field can retain the prior value and pollute QA output. Clearing it before the optional assignment avoids stale data.
♻️ Proposed fix
- { - const auto predicted = bco_matching_information.get_predicted_fee_bco(gtm_bco);; - if( predicted ) - { - m_waveform.fee_bco_predicted_matched = predicted.value(); - } - } + m_waveform.fee_bco_predicted_matched = 0; + { + const auto predicted = bco_matching_information.get_predicted_fee_bco(gtm_bco); + if (predicted) + { + m_waveform.fee_bco_predicted_matched = predicted.value(); + } + }offline/packages/trackreco/DSTClusterPruning.cc (1)
173-211: Guard condition blockspruneAllSeeds()in minimal setups.The function requires
m_track_seed_containerunconditionally (line 173), but thepruneAllSeedsbranch (lines 180–211) only needs TPC and Silicon seed containers. The non-pruneAllSeedspath (starting line 213) is wherem_track_seed_containeris actually used. Workflows withoutSvtxTrackSeedContainerthat enablepruneAllSeedswill unnecessarily bail out.🔧 Suggested fix
- if (!(m_cluster_map && m_reduced_cluster_map && m_track_seed_container && m_silicon_track_seed_container && m_tpc_track_seed_container)) + if (!(m_cluster_map && m_reduced_cluster_map && m_silicon_track_seed_container && m_tpc_track_seed_container)) { if (Verbosity() > 1){ std::cout << "Missing container" << std::endl; } return; } + if (!m_pruneAllSeeds && !m_track_seed_container) + { + if (Verbosity() > 1){ + std::cout << "Missing track seed container" << std::endl; + } + return; + }offline/packages/tpc/Tpc3DClusterizer.cc (1)
684-706: Uncommentrtree.remove()or make rtree parameter const-reference.The
rtree.remove(clusHit)call at line 694 is commented out, butrtreeis passed by non-const reference. The similar implementation inLaserClusterizer::remove_hits(lines 223) actively callsrtree.remove(clusHit), suggesting this should not be commented out. Either:
- Uncomment the removal to match the expected behavior
- If rtree should remain unmodified, change the parameter to
const bgi::rtree<...> &rtreeto document intentThe
rtree.empty()check (line 690) can be removed if rtree isn't being modified—it serves no algorithmic purpose and only logs a diagnostic message.
🤖 Fix all issues with AI agents
In `@generators/Herwig/HepMCTrigger/HepMCParticleTrigger.cc`:
- Around line 239-266: The AbsEta setters (SetAbsEtaHigh, SetAbsEtaLow,
SetAbsEtaHighLow) currently write into the signed-eta members
_theEtaHigh/_theEtaLow, causing signed-eta cuts to be unintentionally modified;
change the implementation to use dedicated abs-eta members (e.g. add
_theAbsEtaHigh and _theAbsEtaLow initialized in the constructor) and have
SetAbsEtaHigh/SetAbsEtaLow/SetAbsEtaHighLow assign those new members and set
_doAbsEtaHighCut/_doAbsEtaLowCut/_doBothAbsEtaCut, or alternatively explicitly
disable the signed-eta cuts inside those setters (clear
_doEtaHighCut/_doEtaLowCut) so the signed-eta thresholds are not used when
absolute-eta cuts are enabled; update any other occurrences (e.g. the similar
block at the other location noted) to use the new abs members or disabling
logic.
- Around line 22-58: The constructor HepMCParticleTrigger's initializer list
contains standalone commas that create empty initializers and break compilation;
edit the HepMCParticleTrigger(...) initializer list to remove the stray
comma-only lines so each member (threshold, goal_event_number, set_event_limit,
_theEtaHigh, _theEtaLow, _thePtHigh, _thePtLow, _thePHigh, _thePLow, _thePzHigh,
_thePzLow, _doEtaHighCut, _doEtaLowCut, _doBothEtaCut, _doAbsEtaHighCut,
_doAbsEtaLowCut, _doBothAbsEtaCut, _doPtHighCut, _doPtLowCut, _doBothPtCut,
_doPHighCut, _doPLowCut, _doBothPCut, _doPzHighCut, _doPzLowCut, _doBothPzCut)
is separated by a single comma with no empty lines; ensure no trailing commas or
blank comma lines remain in the initializer list for HepMCParticleTrigger.
In `@offline/framework/fun4all/InputFileHandler.cc`:
- Around line 183-187: The code builds a shell command by concatenating
m_RunBeforeOpeningScript, m_OpeningArgs and elements of stringvec into fullcmd
which allows shell injection; fix by avoiding passing a single shell
string—either construct an argument vector and invoke the helper directly with
an exec/spawn family call (use execvp/posix_spawn or equivalent) or, if
retaining shell execution, robustly escape/shell-quote each element
(m_OpeningArgs and each element of stringvec) before concatenation; update the
call site that uses fullcmd to accept an argv-style array or the sanitized,
safely-quoted command and reference the symbols m_RunBeforeOpeningScript,
m_OpeningArgs, stringvec and fullcmd when making changes.
In `@offline/framework/fun4allraw/Fun4AllStreamingInputManager.cc`:
- Line 1367: The calculation of ref_bco_minus_range in
Fun4AllStreamingInputManager.cc uses a fallback of m_mvtx_negative_bco when
m_RefBCO < m_mvtx_negative_bco, which is inconsistent with other places
(FillMvtx, FillInttPool) that default to 0; change the ternary so that when
m_RefBCO < m_mvtx_negative_bco the result defaults to 0 instead of
m_mvtx_negative_bco (i.e., update the computation of ref_bco_minus_range using
m_RefBCO, m_mvtx_negative_bco to return 0 on underflow) and ensure any logic
relying on ref_bco_minus_range continues to treat 0 as the minimum valid BCO.
- Around line 974-986: The computation of lower_limit in
Fun4AllStreamingInputManager::... can underflow when m_mvtx_is_triggered is
false (lower_limit = select_crossings - m_mvtx_bco_range - m_mvtx_negative_bco);
change this to perform a safe subtraction and clamp to zero (or use a
signed/extended intermediate like int64_t temp = (int64_t)select_crossings -
(int64_t)m_mvtx_bco_range - (int64_t)m_mvtx_negative_bco; lower_limit = temp < 0
? 0 : (uint64_t)temp) so that when m_RefBCO < m_mvtx_negative_bco you do not
wrap to a huge unsigned value; apply the same pattern/guarding used earlier
around line 839 and ensure the for-loop over m_MvtxRawHitMap continues to use
lower_limit and upper_limit as before.
In `@offline/framework/fun4allraw/SingleTriggeredInput.cc`:
- Around line 436-511: The skiptrace block leaks evt (and sometimes pkt) on
early continues and lacks handling when the 5-retry clock consistency loop
fails; update the block around GetEventIterator()/pkt retrieval so that whenever
you continue you first delete evt and/or pkt as appropriate (references:
GetEventIterator()->getNextEvent(), pkt from evt->getPacket(representative_pid),
FillPacketClock, m_bclkdiffarray_map, Gl1Input()/gl1), and after the
clockconsistency retry loop exhausts (clockconstcount>=5) add deterministic
failure handling—delete any allocated evt/pkt, log an error with Name(), and
propagate a failure (e.g. return -1 or call FilesDone/close) rather than falling
through so no dangling objects remain and misaligned data isn’t processed.
In `@offline/packages/CaloEmbedding/CombineTowerInfo.cc`:
- Around line 46-72: DetNode (the PHCompositeNode returned by iter.findFirst and
stored in DetNode) may be null before calling DetNode->addNode(...); update
CombineTowerInfo to check DetNode for null and handle it safely: if DetNode is
null either create and insert a new PHCompositeNode with the detector name into
the appropriate parent (so subsequent addNode calls are valid) or fail early
with a clear exception/log; ensure this null-check and handling occurs before
using DetNode to add the PHIODataNode for m_towersOut and reference the symbols
DetNode, m_outputNode, m_towersOut, and the PHIODataNode<PHObject> construction
in your change.
In `@offline/packages/CaloEmbedding/CopyIODataNodes.cc`:
- Around line 307-327: CopyTowerInfo dereferences TowerInfoContainer pointers
without null checks which can crash if findNode::getClass fails for
from_towerInfo_name or to_towerInfo_name; add null checks right after retrieving
from_towerInfo and to_towerInfo in CopyTowerInfo and bail out (log an error via
Verbosity()/std::cout or return) when either is null, and also guard the loop
that calls get_tower_at_channel/ch->copy_tower by verifying from_tow and the
result of to_towerInfo->get_tower_at_channel(ch) are non-null before calling
copy_tower; keep the existing identify() debug prints but only call them when
containers are valid.
In `@offline/packages/jetbackground/DetermineTowerBackground.cc`:
- Around line 76-108: The function DetermineTowerBackground::LoadCalibrations
currently calls exit(-1) when calibdir is empty; instead, remove the exit call
and return an error code so InitRun can handle it—specifically, when
calibdir.empty() is true (taking into account m_overwrite_average_calo_v2 and
m_overwrite_average_calo_v2_path), replace the exit(-1) with returning
Fun4AllReturnCodes::ABORTRUN and ensure callers (e.g., InitRun) will propagate
that failure.
In `@offline/packages/mvtx/MvtxHitPruner.cc`:
- Around line 158-167: Check for a nullptr return from m_hits->findHitSet inside
MvtxHitPruner::process_event before dereferencing hitset: if hitset is null,
emit a warning (or debug) message using the existing Verbosity() branch and skip
processing/continue the loop instead of accessing hitset->size() or calling
TrkrHitSet::ConstRange hitrangei = hitset->getHits(); this prevents
dereferencing a null pointer and keeps existing logging behavior consistent.
In `@offline/packages/tpc/Tpc3DClusterizer.cc`:
- Around line 659-681: The block that builds the fX array and calls
m_clusterNT->Fill(fX) must be guarded because m_clusterNT is only created when
m_output is true; restore a null-check or the original if (m_output) guard
around that block (or at minimum check m_clusterNT != nullptr before calling
Fill) to avoid a potential null pointer dereference; update the code around the
fX construction and the call to m_clusterNT->Fill so it only executes when
m_output is true and m_clusterNT is valid.
- Around line 554-559: The variables iphimin/iphimax are being assigned the
double angle phi (radians) causing type/semantic mismatch; either (A) treat them
as angle bounds: rename iphimin/iphimax to phimin/phimax and change their type
to double, update all uses (including phisize calculation) to compute angular
size from phimin/phimax, or (B) keep the iphi semantics and assign the integer
iphi (from coords[1]) instead of phi so iphimin/iphimax remain integer indices;
update any downstream code that computes phisize on the basis of index vs angle
accordingly (check uses of phi, iphi, coords[1], phisize to ensure consistency).
In `@offline/packages/trackreco/PHActsTrkFitter.cc`:
- Around line 391-409: The code currently leaves crossing_estimate set to
SHRT_MAX when m_pp_mode is true and m_enable_crossing_estimate is false, which
can propagate an invalid sentinel into drift corrections and fits; update the
logic in PHActsTrkFitter (the block referencing m_pp_mode,
m_enable_crossing_estimate, crossing, crossing_estimate and SHRT_MAX) to handle
the "no INTT crossing" case when estimate mode is disabled by either (1)
skipping the track (return/continue) or (2) setting crossing_estimate to a safe
default (e.g., 0) and not attempting fit; ensure use_estimate and nvary are only
set when m_enable_crossing_estimate is true and add a clear comment explaining
the chosen behavior.
In `@offline/QA/Tracking/StateClusterResidualsQA.cc`:
- Around line 181-198: The code calls
geometry->getGlobalPosition(state->get_cluskey(), cluster) before verifying
cluster is non-null, risking a crash; reorder and null-check so you call
cluster_map->findCluster(...) into cluster, then immediately if (!cluster)
continue (or skip) and only then call geometry->getGlobalPosition(..., cluster)
and use its result to compute cluster_x/cluster_y/cluster_z for filling
m_histograms_x/y/z; update the block around findCluster, getGlobalPosition, and
the if (cluster) check accordingly.
In `@offline/QA/Tracking/StateClusterResidualsQA.h`:
- Around line 56-101: These setters (setNMvtx, setNIntt, setNTpc, setPhiRange,
setEtaRange, setPtRange, setPositiveTracks, setNegativeTracks) assume
m_pending.back() exists and cause UB if called before an addHistogram; guard
each setter by ensuring m_pending is non-empty (e.g., if m_pending.empty()
push_back(default-constructed PendingEntry) or throw/assert with a clear
message) before accessing m_pending.back(), so callers can safely call any
setter before addHistogram; update all listed methods to perform the same
presence check and create a default pending entry when missing.
🟡 Minor comments (12)
offline/packages/mvtx/MvtxClusterPruner.cc-228-241 (1)
228-241: Guard against division by zero when computing fraction.If no MVTX clusters are processed during the run (e.g., empty events or missing data),
m_cluster_counter_totalremains 0, causing undefined behavior on line 237.Proposed fix
std::cout << "MvtxClusterPruner::End -" << " m_cluster_counter_deleted: " << m_cluster_counter_deleted - << " fraction: " << double(m_cluster_counter_deleted) / m_cluster_counter_total + << " fraction: " << (m_cluster_counter_total > 0 ? double(m_cluster_counter_deleted) / m_cluster_counter_total : 0.0) << std::endl;offline/framework/fun4all/InputFileHandler.cc-177-182 (1)
177-182: Permission check may be too restrictive.The check only verifies
owner_execpermission. If the process runs under a different user who has execute permission via group or other bits, the script will be incorrectly rejected.Suggested fix: check any execute permission
- if (!((std::filesystem::status(m_RunBeforeOpeningScript).permissions() & std::filesystem::perms::owner_exec) == std::filesystem::perms::owner_exec)) + auto perms = std::filesystem::status(m_RunBeforeOpeningScript).permissions(); + bool is_executable = (perms & std::filesystem::perms::owner_exec) != std::filesystem::perms::none || + (perms & std::filesystem::perms::group_exec) != std::filesystem::perms::none || + (perms & std::filesystem::perms::others_exec) != std::filesystem::perms::none; + if (!is_executable) { std::cout << PHWHERE << "RunBeforeOpeningScript script " << m_RunBeforeOpeningScript << " is not owner executable" << std::endl; return -1; }offline/packages/CaloEmbedding/CopyIODataNodes.cc-322-322 (1)
322-322: Typo: "TowerInfoCOntainer" should be "TowerInfoContainer".🔧 Fix typo
- std::cout << "To TowerInfoCOntainer identify()" << std::endl; + std::cout << "To TowerInfoContainer identify()" << std::endl;offline/packages/CaloEmbedding/CombineTowerInfo.cc-25-28 (1)
25-28: Missing validation form_detector.The
m_detectormember is used inCreateNodesto locate the detector node, but it's not validated inInitRunalongside the other node names.🔧 Proposed fix
- if (m_inputNodeA.empty() || m_inputNodeB.empty() || m_outputNode.empty()) + if (m_inputNodeA.empty() || m_inputNodeB.empty() || m_outputNode.empty() || m_detector.empty()) { - throw std::runtime_error("CombineTowerInfo: input/output node names not set"); + throw std::runtime_error("CombineTowerInfo: input/output node names or detector not set"); }offline/packages/micromegas/MicromegasClusterizer.cc-159-166 (1)
159-166: Remove incomplete comment and use const reference in range-based for loop.Line 166 contains
//mawhich appears to be an incomplete comment or debug artifact that should be removed before merging.Additionally, consider using
const std::string&in the range-based for loop to avoid unnecessary string copies.Proposed fix
- for( std::string geonodename: {"CYLINDERGEOM_MICROMEGAS_FULL", "CYLINDERGEOM_MICROMEGAS" } ) + for( const std::string& geonodename: {"CYLINDERGEOM_MICROMEGAS_FULL", "CYLINDERGEOM_MICROMEGAS" } ) { // try load node and test geonode = findNode::getClass<PHG4CylinderGeomContainer>(topNode, geonodename); if( geonode ) { break;} } - - //maoffline/packages/tpc/Tpc3DClusterizer.cc-150-158 (1)
150-158: Fix inconsistent fallback value form_seed.
m_seedis initialized asint m_seed {-1};in the header, but when theRANDOMSEEDflag is absent, the code sets it tostd::numeric_limits<int>::quiet_NaN(), which returns0for integer types. This creates an inconsistency in sentinel values.Use
-1consistently instead ofquiet_NaN(), or choose another explicit sentinel value that matches the member initialization.offline/packages/trackreco/PHActsTrkFitter.cc-411-418 (1)
411-418: Clarify or enforce the “veto others” behavior in non‑pp mode.The comment says “veto others,” but the code now forces
crossing = 0and continues. Either update the comment or re‑enable the veto (continue) so behavior matches intent.Example: update comment to match behavior
- // non pp mode, we want only crossing zero, veto others + // non-pp mode: force crossing to zero for all tracksoffline/packages/Skimmers/Trigger/TriggerDSTSkimmer.h-25-29 (1)
25-29: Guard against non‑positivemax_events.Passing
0or negative values currently enables the cap and will abort all events. Consider treating<= 0as “no cap” (or assert) to avoid accidental shutdowns.🩹 Suggested fix
void set_accept_max(int max_events) { - use_max_accept = true; - max_accept = max_events; - return; + if (max_events <= 0) + { + use_max_accept = false; + max_accept = 0; + return; + } + use_max_accept = true; + max_accept = max_events; }offline/packages/jetbackground/DetermineTowerBackground.h-41-45 (1)
41-45: Make SetOverwriteCaloV2 accept a const string reference.
Line 41 takes a non-const reference, which blocks temporaries and const strings. Other setters in this class (SetBackgroundOutputName, set_towerNodePrefix) correctly useconst std::string&.♻️ Proposed fix
- void SetOverwriteCaloV2(std::string &url) + void SetOverwriteCaloV2(const std::string &url) { m_overwrite_average_calo_v2 = true; m_overwrite_average_calo_v2_path = url; }offline/packages/jetbackground/DetermineTowerBackground.cc-948-971 (1)
948-971: Replace hardcoded centrality bin bounds with dynamic vector size check.The
_CENTRALITY_V2vector is initialized with exactly 100 elements (indices 0–99) and populated for all centrality bins. The conditioncentrality_bin > 0 && centrality_bin < 95incorrectly excludes valid bins 0 and 95–99, causing them to be treated as flow failures despite having populated v2 values. Use the vector size for bounds checking instead.Fix
- if (centrality_bin > 0 && centrality_bin < 95) + if (centrality_bin >= 0 && + centrality_bin < static_cast<int>(_CENTRALITY_V2.size())) { _v2 = _CENTRALITY_V2[centrality_bin]; }offline/framework/fun4all/Fun4AllServer.cc-904-905 (1)
904-905: Add cout formatting restore to the NewSubsystems loop for consistency.The Subsystems loop (line 904) restores cout formatting after calling BeginRunSubsystem, but the NewSubsystems loop (lines 906-910) does not. Since BeginRunSubsystem produces output that could modify formatting, this inconsistency can allow formatting changes to leak to subsequent code. Add the restore after the BeginRunSubsystem call in the NewSubsystems loop.
♻️ Proposed fix
for (; !NewSubsystems.empty(); NewSubsystems.pop_front()) { registerSubsystem((NewSubsystems.front()).first, (NewSubsystems.front()).second); BeginRunSubsystem(std::make_pair(NewSubsystems.front().first, topNode(NewSubsystems.front().second))); + std::cout.copyfmt(m_saved_cout_state); }offline/packages/jetbackground/DetermineTowerBackground.cc-536-621 (1)
536-621: Add null check before dereferencing sEPDNS pointer.
Lines 605-607 assumeEventplaneinfoMap::sEPDNSexists whenever the map is non-empty. Theget()method returnsnullptrif the key is absent, and a non-empty map does not guarantee this entry exists. Without a null check, dereferencingEPDNSwill crash ifsEPDNSwas not inserted into the map.♻️ Proposed fix
- if (!(epmap->empty())) - { - auto *EPDNS = epmap->get(EventplaneinfoMap::sEPDNS); - _Psi2 = EPDNS->get_shifted_psi(2); - } + if (!(epmap->empty())) + { + auto *EPDNS = epmap->get(EventplaneinfoMap::sEPDNS); + if (EPDNS) + { + _Psi2 = EPDNS->get_shifted_psi(2); + } + else + { + _is_flow_failure = true; + _Psi2 = 0; + } + }
🧹 Nitpick comments (34)
offline/packages/mbd/MbdSig.h (1)
35-36: LGTM!The new getter correctly exposes the private
_nsamplesmember and follows the existing naming conventions in the class.Optional improvement: Consider adding
constqualifier for const-correctness:- int GetNSamples() { return _nsamples; } + int GetNSamples() const { return _nsamples; }This applies to other getters in the class as well, but can be deferred to a broader const-correctness cleanup.
offline/packages/tpc/TpcClusterMover.cc (1)
161-191: LGTM! Const qualification is correct.The method correctly doesn't modify any member state, so the
constqualifier is appropriate.Minor nit: There's an unnecessary nested brace block on lines 169-175. The outer braces around the
ifblock serve no scoping purpose here.🔧 Optional cleanup for redundant braces
if (std::isnan(xplus)) { - { - if (_verbosity > 1) - { - std::cout << " circle/circle intersection calculation failed, skip this cluster" << std::endl; - std::cout << " target_radius " << target_radius << " fitted R " << R << " fitted X0 " << X0 << " fitted Y0 " << Y0 << std::endl; - } + if (_verbosity > 1) + { + std::cout << " circle/circle intersection calculation failed, skip this cluster" << std::endl; + std::cout << " target_radius " << target_radius << " fitted R " << R << " fitted X0 " << X0 << " fitted Y0 " << Y0 << std::endl; } return Fun4AllReturnCodes::ABORTEVENT; // skip to next cluster }offline/packages/tpc/LaserEventIdentifier.cc (1)
141-141: Consider using integer arithmetic for BCO threshold comparison.The comparison mixes unsigned integer subtraction with a floating-point expression (
350.0/30*16≈ 186.67). If the intent is a timing window based on clock cycles, using explicit integer arithmetic would improve clarity.💡 Suggested clarification
- else if ((gl1pkt->getBCO() - prev_BCO) < 350.0/30*16) + // 350 ns timing window: 350/30 MHz * 16 clocks ≈ 186 BCO ticks + else if ((gl1pkt->getBCO() - prev_BCO) < 187)Or keep the calculation explicit with a constexpr if the derivation is important for documentation.
offline/packages/tpc/TpcRawDataTree.cc (1)
180-206: Pre-existing: Duplicatem_fee == 16condition causes dead code.This is not related to your change, but
m_fee == 16appears in both conditions (line 185 and line 196). Since it's checked first in the R1 block, it will never match the R2 block—making the duplicate on line 196 unreachable. Consider removing it from one of the conditions or verifying which region FEE 16 should belong to.🔧 Suggested fix
else if (m_fee == 11 || m_fee == 12 || m_fee == 19 || m_fee == 18 || m_fee == 01 || m_fee == 00 || - m_fee == 16 || m_fee == 15)offline/framework/fun4allraw/SingleTriggeredInput.h (1)
115-115: Consider usingm_prefix for naming consistency.Most private members in this class use the
m_prefix (e.g.,m_EventNumber,m_Event,m_EventIterator), whileeventcounterfollows the pattern of existing exceptions likefirstcallandfirstclockcheck. For consistency with the dominant naming convention, consider renaming tom_EventCounter.offline/packages/trackbase/AlignmentTransformation.h (1)
131-132: Consider passinguse_module_tiltas a parameter tonewMakeTransforminstead of using member state.This flag is set within a nested loop in
createMapand read innewMakeTransform. Using member state for this transient communication is fragile—ifnewMakeTransformis ever called from another context, the state may be incorrect. Additionally, the comment "starts at false in all cases" is redundant given the initializer.Suggested approach
Add a
bool use_module_tiltparameter tonewMakeTransformand pass the value directly from the call site, removing the member variable entirely.offline/packages/trackbase/AlignmentTransformation.cc (1)
280-291: Consider replacing magic numbertest_layer < 4with a named constant or clearer condition.The value 4 is a magic number. Based on context, TPC module hitsetkeys have
test_layervalues of 0, 1, or 2 (for the three regions). A named constant or explicit comparison against the module layer range would improve readability.Example
+ constexpr unsigned int kMaxModuleLayer = 3; use_module_tilt = false; - if (test_layer < 4 || use_module_tilt_always) + if (test_layer < kMaxModuleLayer || use_module_tilt_always)offline/packages/mvtx/MvtxHitPruner.cc (2)
54-67: Consider markingbegin()andend()asconstmember functions.These accessor methods don't modify state and should be
constfor correctness and to allow use with constrange_adaptorinstances.♻️ Suggested improvement
- const typename T::first_type& begin() { return m_range.first; } - const typename T::second_type& end() { return m_range.second; } + const typename T::first_type& begin() const { return m_range.first; } + const typename T::second_type& end() const { return m_range.second; }
140-140: Consider using[[maybe_unused]]or just_for the unused structured binding element.The variable
unusedis intentionally unused. Using[[maybe_unused]]or the common convention of a single underscore makes the intent clearer and may suppress compiler warnings.♻️ Suggested improvement
- for (const auto& [unused, hitsetkey] : range_adaptor(bare_hitsetrange)) + for ([[maybe_unused]] const auto& [unused, hitsetkey] : range_adaptor(bare_hitsetrange))Or simply:
- for (const auto& [unused, hitsetkey] : range_adaptor(bare_hitsetrange)) + for (const auto& [_, hitsetkey] : range_adaptor(bare_hitsetrange))offline/packages/PHGenFitPkg/PHGenFit/Fitter.cc (1)
53-58: VerifyTGeoManager::Importownership/overrides with pre-allocation.
_tgeo_manageris allocated beforeTGeoManager::Import(...); depending on ROOT semantics, Import may create/replace the current manager, which could leave_tgeo_managerunused or stale. Please confirm the ROOT version’s behavior and consider assigning_tgeo_managerto the Import result to avoid leaks or dangling references if replacement occurs.offline/framework/fun4allraw/SingleMvtxPoolInput.cc (1)
463-467: Avoid the magic number120form_NegativeBcoLine 466 hard-codes
120without rationale. Consider a named constant (e.g., inMvtxRawDefs) or a brief comment tying it to the strobe-width window to prevent accidental regressions.offline/packages/CaloEmbedding/CombineTowerInfo.cc (1)
85-95: Consider adding defensive null checks for tower pointers.The
get_tower_at_channelcalls assume valid returns. While the size check inCreateNodesshould ensure valid indices, defensive null checks would prevent crashes if tower data is inconsistent.♻️ Optional defensive checks
for (unsigned int ich = 0; ich < ntowers; ++ich) { TowerInfo* towerA = m_towersA->get_tower_at_channel(ich); TowerInfo* towerB = m_towersB->get_tower_at_channel(ich); TowerInfo* towerO = m_towersOut->get_tower_at_channel(ich); + if (!towerA || !towerB || !towerO) + { + continue; // or log a warning + } towerO->copy_tower(towerA);offline/packages/CaloEmbedding/CopyIODataNodes.h (2)
38-44: Minor: Unnecessaryreturnstatement in void setter.The
return;at line 43 is unnecessary in a void function. Other setters in this class (lines 31-37) don't use explicit returns.♻️ Align with existing style
void set_CopyTowerInfo(const std::string& set_from_towerInfo_name,const std::string& set_to_towerInfo_name) { from_towerInfo_name = set_from_towerInfo_name; to_towerInfo_name = set_to_towerInfo_name; m_CopyTowerInfoFlag = true; - return; }
76-79: Naming inconsistency: missingm_prefix on member variables.The new
from_towerInfo_nameandto_towerInfo_namemembers don't follow them_prefix convention used by other members in this class.♻️ Align naming with class convention
bool m_CopyTowerInfoFlag = false; - std::string from_towerInfo_name = {}; - std::string to_towerInfo_name = {}; + std::string m_fromTowerInfoName; + std::string m_toTowerInfoName;offline/packages/CaloEmbedding/CopyIODataNodes.cc (1)
369-369: Unconditional debug print should be gated by verbosity.This print will appear for every run regardless of verbosity settings, unlike similar debug outputs elsewhere in this file which are guarded by
Verbosity() > 0.♻️ Gate debug output
void CopyIODataNodes::CreateTowerInfo(PHCompositeNode *from_topNode, PHCompositeNode *to_topNode) { - std::cout << "copying tower info" << std::endl; + if (Verbosity() > 0) + { + std::cout << "copying tower info" << std::endl; + } TowerInfoContainer *from_towerInfo = findNode::getClass<TowerInfoContainer>(from_topNode, from_towerInfo_name);offline/packages/tpc/Tpc3DClusterizer.cc (2)
284-343: Consider extracting magic numbers into named constants.The iphi boundary values (191, 206, 383, 576, etc.) appear to be hardware-specific pad boundaries. While the brace additions are good, extracting these into named constants or a lookup table would improve maintainability and self-documentation.
♻️ Example refactor
// At class or namespace level static constexpr std::array<int, 14> kExcludedPadBoundaries = { 0, 191, 206, 383, 576, 767, 960, 1344, 1522, 1536, 1728, 1920, 2111, 2303 }; static constexpr std::array<int, 14> kBoundaryTolerances = { 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 }; // In the loop if (layer >= 7 + 32) { for (size_t i = 0; i < kExcludedPadBoundaries.size(); ++i) { if (abs(iphi - kExcludedPadBoundaries[i]) <= kBoundaryTolerances[i]) { continue; // Note: would need restructuring to break outer loop } } }
523-528: Usestd::numeric_limitsfor min/max initialization.The magic numbers (6666, -1, 66666666.6, -6666666666.6) are fragile. If hardware configurations change to support larger values, these could produce incorrect results.
♻️ Recommended fix
- int iphimin = 6666; - int iphimax = -1; - int ilaymin = 6666; - int ilaymax = -1; - float itmin = 66666666.6; - float itmax = -6666666666.6; + int iphimin = std::numeric_limits<int>::max(); + int iphimax = std::numeric_limits<int>::min(); + int ilaymin = std::numeric_limits<int>::max(); + int ilaymax = std::numeric_limits<int>::min(); + float itmin = std::numeric_limits<float>::max(); + float itmax = std::numeric_limits<float>::lowest();offline/packages/tpc/LaserClusterizer.cc (3)
69-70: Consider making global arrays const.The global arrays
layerMinsandlayerMaxesappear to hold constant configuration data. Declaring themconst(and potentiallyconstexpr) would prevent accidental modification and clarify intent.♻️ Proposed refactor
-int layerMins[3] = {7, 23, 39}; -int layerMaxes[3] = {22, 38, 54}; +constexpr int layerMins[3] = {7, 23, 39}; +constexpr int layerMaxes[3] = {22, 38, 54};
295-338: Consider usingstd::setfor duplicate detection.The current implementation performs linear searches through
usedLayer,usedIPhi, andusedITvectors for each hit, resulting in O(n²) complexity. Since<set>is already included (Line 51), usingstd::setwould improve this to O(n log n).♻️ Proposed refactor using std::set
- std::vector<float> usedLayer; - std::vector<float> usedIPhi; - std::vector<float> usedIT; + std::set<float> usedLayer; + std::set<float> usedIPhi; + std::set<float> usedIT; // ... in the loop: - bool foundLayer = false; - for (float i : usedLayer) - { - if (coords[0] == i) - { - foundLayer = true; - break; - } - } - - if (!foundLayer) - { - usedLayer.push_back(coords[0]); - } + usedLayer.insert(coords[0]); - bool foundIPhi = false; - for (float i : usedIPhi) - { - if (coords[1] == i) - { - foundIPhi = true; - break; - } - } - - if (!foundIPhi) - { - usedIPhi.push_back(coords[1]); - } + usedIPhi.insert(coords[1]); - bool foundIT = false; - for (float i : usedIT) - { - if (coords[2] == i) - { - foundIT = true; - break; - } - } - - if (!foundIT) - { - usedIT.push_back(coords[2]); - } + usedIT.insert(coords[2]);Note: You'll also need to update the sorting and access patterns later (Lines 392-394, 409) to work with
std::setiterators.
833-833: Consider extracting the event selection logic for clarity.The conditional combines run number checks with different laser event flags, making it harder to understand at a glance. Extracting this logic to a named helper function would improve readability.
♻️ Proposed refactor
Add a helper method to the class:
bool LaserClusterizer::isValidLaserEvent() const { const auto runNumber = eventHeader->get_RunNumber(); if (runNumber > 66153) { return m_laserEventInfo->isGl1LaserEvent(); } return m_laserEventInfo->isLaserEvent(); }Then simplify the conditional:
- if ((eventHeader->get_RunNumber() > 66153 && !m_laserEventInfo->isGl1LaserEvent()) || (eventHeader->get_RunNumber() <= 66153 && !m_laserEventInfo->isLaserEvent())) + if (!isValidLaserEvent()) { return Fun4AllReturnCodes::EVENT_OK; }offline/framework/fun4allraw/SingleTriggeredInput.cc (2)
355-359: Static local variablefirstclockarraymay not behave as intended.The
static bool firstclockarrayis shared across all instances ofSingleTriggeredInputand all iterations of the pid loop. It will only log for the very first pid encountered across the entire program lifetime, not once per instance or once per pool fill. If the intent is to log the first clock for each instance, this should be a member variable instead.Consider using a member variable if per-instance logging is desired
- static bool firstclockarray=true; - if(firstclockarray){ - std::cout << "first clock call pid " << pid << " m_bclkarray_map[pid][0] : " << m_bclkarray_map[pid][0] << std::endl; - firstclockarray=false; - } + if(m_firstClockLogged.insert(pid).second) { + std::cout << "first clock call pid " << pid << " m_bclkarray_map[pid][0] : " << m_bclkarray_map[pid][0] << std::endl; + }This requires adding
std::unordered_set<int> m_firstClockLogged;as a member variable.
437-491: Consider extracting repeated event-fetch-with-file-handling pattern.The pattern of fetching the next event with file close/reopen handling appears three times in
FillEventVector()(lines 391-401, 440-448, 482-490). This duplication increases maintenance burden and risk of inconsistent behavior.Consider extracting to a helper method
// Helper method to fetch next event, handling file transitions Event* SingleTriggeredInput::FetchNextEvent() { Event* evt = GetEventIterator()->getNextEvent(); while (!evt) { fileclose(); if (OpenNextFile() == InputFileHandlerReturnCodes::FAILURE) { FilesDone(1); return nullptr; } evt = GetEventIterator()->getNextEvent(); } return evt; }Then replace the duplicated blocks with:
evt = FetchNextEvent(); if (!evt) { return -1; }Additionally, consider making the retry limit (5) a named constant:
static constexpr int kMaxClockRecoveryRetries = 5;offline/packages/tpc/TpcClusterizer.cc (1)
1205-1211: Guard the geometry down-casts to avoid UB.
static_castassumes the container always returnsPHG4TpcGeomv1. If a different version appears, this is undefined behavior. Considerdynamic_castwith a null check (or a checked helper) to fail fast.♻️ Safer cast pattern (apply similarly to g2/g3)
- auto *g1 = static_cast<PHG4TpcGeomv1*> (geom->GetFirstLayerCellGeom()); // cast because << not in the base class + auto *g1 = dynamic_cast<PHG4TpcGeomv1*>(geom->GetFirstLayerCellGeom()); + if (!g1) + { + std::cout << PHWHERE << "Unexpected TPC geometry type for first layer" << std::endl; + return Fun4AllReturnCodes::ABORTRUN; + }offline/framework/fun4allraw/Fun4AllStreamingInputManager.cc (1)
797-797: Minor: Trailing whitespace.Line 797 has a trailing space after the closing brace.
Fix
- } + }offline/packages/trackreco/PHActsTrkFitter.cc (1)
316-338: Guard silicon seed lookup before callingget().
m_siliconSeeds->get(siid)is called before checkingsiid == std::numeric_limits<unsigned int>::max(). Ifget()doesn’t tolerate invalid IDs, this can read past bounds. Consider guarding first or confirmget()safely returnsnullptrfor invalid IDs.Suggested defensive guard
- auto *siseed = m_siliconSeeds->get(siid); - if (siseed) - { - silicon_crossing = siseed->get_crossing(); - } + TrackSeed* siseed = nullptr; + if (siid != std::numeric_limits<unsigned int>::max()) + { + siseed = m_siliconSeeds->get(siid); + if (siseed) + { + silicon_crossing = siseed->get_crossing(); + } + }offline/QA/Tracking/MicromegasClusterQA.h (1)
54-58: Clarify the sample range as inclusive/exclusive.The implementation uses a half‑open range (
< m_sample_max), but the setter/member comments read like inclusive bounds. Clarifying avoids off‑by‑one misconfigurations.✏️ Suggested comment tweak
- /// set min sample for signal hits + /// set min sample for signal hits (inclusive) void set_sample_min(uint16_t value) { m_sample_min = value; } - /// set max sample for signal hits + /// set max sample for signal hits (exclusive) void set_sample_max(uint16_t value) { m_sample_max = value; } - /// min sample for signal + /// min sample for signal (inclusive) uint16_t m_sample_min = 0; - /// max sample for signal + /// max sample for signal (exclusive) uint16_t m_sample_max = 1024;Also applies to: 108-113
offline/QA/Tracking/MicromegasClusterQA.cc (1)
76-78: Add a quick sanity check for sample range.If
m_sample_min >= m_sample_max, the new gating silently drops all clusters. A simple assert (or warning) inInitRunwould make misconfigurations obvious.✅ Minimal guard
std::cout << "MicromegasClusterQA::InitRun - m_sample_min: " << m_sample_min << std::endl; std::cout << "MicromegasClusterQA::InitRun - m_sample_max: " << m_sample_max << std::endl; + assert(m_sample_min < m_sample_max);offline/packages/micromegas/MicromegasCombinedDataDecoder.cc (1)
261-265: Gate duplicate-hit log behind Verbosity to avoid log spam.This keeps logging consistent with the rest of the function and reduces overhead.
♻️ Proposed tweak
- if (hit) - { - std::cout << "MicromegasCombinedDataDecoder::process_event - duplicated hit, hitsetkey: " << hitsetkey << " strip: " << strip << std::endl; - continue; - } + if (hit) + { + if (Verbosity()) + { + std::cout << "MicromegasCombinedDataDecoder::process_event - duplicated hit, hitsetkey: " << hitsetkey << " strip: " << strip << std::endl; + } + continue; + }generators/Herwig/HepMCTrigger/HepMCJetTrigger.cc (1)
130-133: Confirm hard |eta| cut is intended (or make it configurable).This introduces a fixed acceptance cut before the pT threshold. Please confirm this matches the physics requirement, or consider exposing it as a parameter for flexibility.
offline/packages/Skimmers/Trigger/TriggerDSTSkimmer.cc (1)
54-54: Replace the magic GL1 packet ID with a named constant.Using a named constant will make the intent clearer and reduce maintenance risk if the ID changes.
♻️ Proposed refactor
+namespace +{ +constexpr int kGL1PacketNodeId = 14001; +} // namespace + - Gl1Packet *_gl1PacketInfo = findNode::getClass<Gl1Packet>(topNode, 14001); + Gl1Packet *_gl1PacketInfo = findNode::getClass<Gl1Packet>(topNode, kGL1PacketNodeId);generators/PHPythia8/PHPythia8.cc (1)
62-67: Prefer an RAII guard for cout formatting.The manual save/restore pairs are easy to miss on future edits. A tiny guard makes restoration automatic on all paths (including early returns).
♻️ Suggested pattern (apply in ctor / Init / process_event)
+namespace +{ +struct CoutFormatGuard +{ + explicit CoutFormatGuard(std::ostream& os) : _os(os), _old(nullptr) { _old.copyfmt(os); } + ~CoutFormatGuard() { _os.copyfmt(_old); } + std::ostream& _os; + std::ios _old; +}; +} // namespace @@ - std::ios old_state(nullptr); - old_state.copyfmt(std::cout); - m_Pythia8.reset(new Pythia8::Pythia(thePath)); - std::cout.copyfmt(old_state); + CoutFormatGuard cout_guard(std::cout); + m_Pythia8.reset(new Pythia8::Pythia(thePath)); @@ - std::ios old_state(nullptr); - old_state.copyfmt(std::cout); // save current state + CoutFormatGuard cout_guard(std::cout); @@ - std::cout.copyfmt(old_state); // restore state to saved state - return Fun4AllReturnCodes::ABORTRUN; + return Fun4AllReturnCodes::ABORTRUN; @@ - std::cout.copyfmt(old_state); // restore state to saved stateAlso applies to: 126-133, 210-213, 288-289, 309-310
generators/Herwig/HepMCTrigger/HepMCParticleTrigger.h (1)
83-87: Align in‑class defaults with constructor initialization.
_thePtLowis initialized to-999.9in the header but to0(then overridden) in the constructor. Consider aligning the in‑class default or removing it to avoid drift.♻️ Possible adjustment
- float _thePtLow{-999.9}; + float _thePtLow{0};offline/framework/fun4all/Fun4AllServer.cc (1)
131-134: Verify the cout baseline is intended to be the InitAll snapshot.
Line 131 captures std::cout once; subsequent restores reset formatting to that initial state, which can override caller formatting changes made after InitAll. If the intent is “restore to pre-call state,” consider capturing/restoring locally around each call (or refreshing the saved state).generators/Herwig/HepMCTrigger/Makefile.am (1)
18-20: Consider linking the new lib in testexternals for a link check.
Line 19 addslibHepMCParticleTrigger.la, buttestexternalsstill only linkslibHepMCJetTrigger.la, so the new lib isn’t link-checked. Consider including it there.♻️ Proposed fix
-testexternals_LDADD = libHepMCJetTrigger.la +testexternals_LDADD = libHepMCJetTrigger.la libHepMCParticleTrigger.la
| HepMCParticleTrigger::HepMCParticleTrigger(float trigger_thresh, int n_incom, bool up_lim, const std::string& name) | ||
| : SubsysReco(name) | ||
| , threshold(trigger_thresh) | ||
| , goal_event_number(n_incom) | ||
| , set_event_limit(up_lim) | ||
| , _theEtaHigh(1.1) | ||
| , _theEtaLow(-1.1) | ||
| , _thePtHigh(999.9) | ||
| , _thePtLow(0) | ||
| , _thePHigh(999.9) | ||
| , _thePLow(-999.9) | ||
| , _thePzHigh(999.9) | ||
| , _thePzLow(-999.9) | ||
| , | ||
|
|
||
| _doEtaHighCut(true) | ||
| , _doEtaLowCut(true) | ||
| , _doBothEtaCut(true) | ||
| , | ||
|
|
||
| _doAbsEtaHighCut(false) | ||
| , _doAbsEtaLowCut(false) | ||
| , _doBothAbsEtaCut(false) | ||
| , | ||
|
|
||
| _doPtHighCut(false) | ||
| , _doPtLowCut(false) | ||
| , _doBothPtCut(false) | ||
| , | ||
| _doPHighCut(false) | ||
| , _doPLowCut(false) | ||
| , _doBothPCut(false) | ||
| , | ||
|
|
||
| _doPzHighCut(false) | ||
| , _doPzLowCut(false) | ||
| , _doBothPzCut(false) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix initializer list syntax (standalone commas).
The empty comma-only lines create empty initializers and will not compile.
🐛 Proposed fix
, _thePzHigh(999.9)
, _thePzLow(-999.9)
- ,
-
- _doEtaHighCut(true)
+ , _doEtaHighCut(true)
, _doEtaLowCut(true)
, _doBothEtaCut(true)
- ,
-
- _doAbsEtaHighCut(false)
+ , _doAbsEtaHighCut(false)
, _doAbsEtaLowCut(false)
, _doBothAbsEtaCut(false)
- ,
-
- _doPtHighCut(false)
+ , _doPtHighCut(false)
, _doPtLowCut(false)
, _doBothPtCut(false)
- ,
- _doPHighCut(false)
+ , _doPHighCut(false)
, _doPLowCut(false)
, _doBothPCut(false)
- ,
-
- _doPzHighCut(false)
+ , _doPzHighCut(false)
, _doPzLowCut(false)
, _doBothPzCut(false)📝 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.
| HepMCParticleTrigger::HepMCParticleTrigger(float trigger_thresh, int n_incom, bool up_lim, const std::string& name) | |
| : SubsysReco(name) | |
| , threshold(trigger_thresh) | |
| , goal_event_number(n_incom) | |
| , set_event_limit(up_lim) | |
| , _theEtaHigh(1.1) | |
| , _theEtaLow(-1.1) | |
| , _thePtHigh(999.9) | |
| , _thePtLow(0) | |
| , _thePHigh(999.9) | |
| , _thePLow(-999.9) | |
| , _thePzHigh(999.9) | |
| , _thePzLow(-999.9) | |
| , | |
| _doEtaHighCut(true) | |
| , _doEtaLowCut(true) | |
| , _doBothEtaCut(true) | |
| , | |
| _doAbsEtaHighCut(false) | |
| , _doAbsEtaLowCut(false) | |
| , _doBothAbsEtaCut(false) | |
| , | |
| _doPtHighCut(false) | |
| , _doPtLowCut(false) | |
| , _doBothPtCut(false) | |
| , | |
| _doPHighCut(false) | |
| , _doPLowCut(false) | |
| , _doBothPCut(false) | |
| , | |
| _doPzHighCut(false) | |
| , _doPzLowCut(false) | |
| , _doBothPzCut(false) | |
| HepMCParticleTrigger::HepMCParticleTrigger(float trigger_thresh, int n_incom, bool up_lim, const std::string& name) | |
| : SubsysReco(name) | |
| , threshold(trigger_thresh) | |
| , goal_event_number(n_incom) | |
| , set_event_limit(up_lim) | |
| , _theEtaHigh(1.1) | |
| , _theEtaLow(-1.1) | |
| , _thePtHigh(999.9) | |
| , _thePtLow(0) | |
| , _thePHigh(999.9) | |
| , _thePLow(-999.9) | |
| , _thePzHigh(999.9) | |
| , _thePzLow(-999.9) | |
| , _doEtaHighCut(true) | |
| , _doEtaLowCut(true) | |
| , _doBothEtaCut(true) | |
| , _doAbsEtaHighCut(false) | |
| , _doAbsEtaLowCut(false) | |
| , _doBothAbsEtaCut(false) | |
| , _doPtHighCut(false) | |
| , _doPtLowCut(false) | |
| , _doBothPtCut(false) | |
| , _doPHighCut(false) | |
| , _doPLowCut(false) | |
| , _doBothPCut(false) | |
| , _doPzHighCut(false) | |
| , _doPzLowCut(false) | |
| , _doBothPzCut(false) |
🤖 Prompt for AI Agents
In `@generators/Herwig/HepMCTrigger/HepMCParticleTrigger.cc` around lines 22 - 58,
The constructor HepMCParticleTrigger's initializer list contains standalone
commas that create empty initializers and break compilation; edit the
HepMCParticleTrigger(...) initializer list to remove the stray comma-only lines
so each member (threshold, goal_event_number, set_event_limit, _theEtaHigh,
_theEtaLow, _thePtHigh, _thePtLow, _thePHigh, _thePLow, _thePzHigh, _thePzLow,
_doEtaHighCut, _doEtaLowCut, _doBothEtaCut, _doAbsEtaHighCut, _doAbsEtaLowCut,
_doBothAbsEtaCut, _doPtHighCut, _doPtLowCut, _doBothPtCut, _doPHighCut,
_doPLowCut, _doBothPCut, _doPzHighCut, _doPzLowCut, _doBothPzCut) is separated
by a single comma with no empty lines; ensure no trailing commas or blank comma
lines remain in the initializer list for HepMCParticleTrigger.
| void HepMCParticleTrigger::SetAbsEtaHigh(double pt) | ||
| { | ||
| _theEtaHigh = pt; | ||
| _doAbsEtaHighCut = true; | ||
| if (_doAbsEtaLowCut) | ||
| { | ||
| _doBothAbsEtaCut = true; | ||
| } | ||
| return; | ||
| } | ||
| void HepMCParticleTrigger::SetAbsEtaLow(double pt) | ||
| { | ||
| _theEtaLow = pt; | ||
| _doAbsEtaLowCut = true; | ||
| if (_doAbsEtaHighCut) | ||
| { | ||
| _doBothAbsEtaCut = true; | ||
| } | ||
| return; | ||
| } | ||
| void HepMCParticleTrigger::SetAbsEtaHighLow(double ptHigh, double ptLow) | ||
| { | ||
| _theEtaHigh = ptHigh; | ||
| _doAbsEtaHighCut = true; | ||
| _theEtaLow = ptLow; | ||
| _doAbsEtaLowCut = true; | ||
| _doBothAbsEtaCut = true; | ||
| return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AbsEta setters overwrite signed-eta thresholds (risk of asymmetric selection).
SetAbsEta* writes into _theEtaHigh/_theEtaLow, which are also used by the always-enabled signed-eta cuts. This means SetAbsEtaLow(>0) will also set the signed-eta lower bound > 0, effectively discarding all negative-eta particles. Unless that is intended, you should separate abs-eta thresholds (or disable signed-eta cuts when abs-eta cuts are enabled).
🔧 Suggested direction (separate abs-eta thresholds)
void HepMCParticleTrigger::SetAbsEtaHigh(double pt)
{
- _theEtaHigh = pt;
+ _theAbsEtaHigh = pt;
_doAbsEtaHighCut = true;
if (_doAbsEtaLowCut)
{
_doBothAbsEtaCut = true;
}
return;
}
void HepMCParticleTrigger::SetAbsEtaLow(double pt)
{
- _theEtaLow = pt;
+ _theAbsEtaLow = pt;
_doAbsEtaLowCut = true;
if (_doAbsEtaHighCut)
{
_doBothAbsEtaCut = true;
}
return;
}
void HepMCParticleTrigger::SetAbsEtaHighLow(double ptHigh, double ptLow)
{
- _theEtaHigh = ptHigh;
+ _theAbsEtaHigh = ptHigh;
_doAbsEtaHighCut = true;
- _theEtaLow = ptLow;
+ _theAbsEtaLow = ptLow;
_doAbsEtaLowCut = true;
_doBothAbsEtaCut = true;
return;
}
- if ((_doAbsEtaHighCut || _doBothAbsEtaCut) && std::abs(eta) > _theEtaHigh)
+ if ((_doAbsEtaHighCut || _doBothAbsEtaCut) && std::abs(eta) > _theAbsEtaHigh)
{
continue;
}
- if ((_doAbsEtaLowCut || _doBothAbsEtaCut) && std::abs(eta) < _theEtaLow)
+ if ((_doAbsEtaLowCut || _doBothAbsEtaCut) && std::abs(eta) < _theAbsEtaLow)
{
continue;
}Note: this requires adding _theAbsEtaHigh/_theAbsEtaLow members and constructor initialization in the header/initializer list.
Also applies to: 312-318
🤖 Prompt for AI Agents
In `@generators/Herwig/HepMCTrigger/HepMCParticleTrigger.cc` around lines 239 -
266, The AbsEta setters (SetAbsEtaHigh, SetAbsEtaLow, SetAbsEtaHighLow)
currently write into the signed-eta members _theEtaHigh/_theEtaLow, causing
signed-eta cuts to be unintentionally modified; change the implementation to use
dedicated abs-eta members (e.g. add _theAbsEtaHigh and _theAbsEtaLow initialized
in the constructor) and have SetAbsEtaHigh/SetAbsEtaLow/SetAbsEtaHighLow assign
those new members and set _doAbsEtaHighCut/_doAbsEtaLowCut/_doBothAbsEtaCut, or
alternatively explicitly disable the signed-eta cuts inside those setters (clear
_doEtaHighCut/_doEtaLowCut) so the signed-eta thresholds are not used when
absolute-eta cuts are enabled; update any other occurrences (e.g. the similar
block at the other location noted) to use the new abs members or disabling
logic.
| std::string fullcmd = m_RunBeforeOpeningScript + " " + m_OpeningArgs; | ||
| for (const auto& iter : stringvec) | ||
| { | ||
| fullcmd += " " + iter; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Potential shell command injection vulnerability.
The command is built by string concatenation without sanitizing m_OpeningArgs or elements of stringvec. If filenames or arguments contain shell metacharacters (e.g., ; rm -rf /, $(cmd), or backticks), they will be interpreted by the shell.
This is a security risk if:
- File paths come from untrusted sources (e.g., user-provided list files)
m_OpeningArgsis set from external input
Consider quoting or escaping the arguments, or using an exec-style API that doesn't invoke a shell.
Minimal mitigation: shell-quote filenames
+#include <sstream>
+
+// Helper to shell-quote a string
+static std::string ShellQuote(const std::string& s) {
+ std::string result = "'";
+ for (char c : s) {
+ if (c == '\'') {
+ result += "'\\''";
+ } else {
+ result += c;
+ }
+ }
+ result += "'";
+ return result;
+}
- std::string fullcmd = m_RunBeforeOpeningScript + " " + m_OpeningArgs;
+ std::string fullcmd = ShellQuote(m_RunBeforeOpeningScript);
+ if (!m_OpeningArgs.empty()) {
+ fullcmd += " " + m_OpeningArgs; // User is responsible for quoting args
+ }
for (const auto& iter : stringvec)
{
- fullcmd += " " + iter;
+ fullcmd += " " + ShellQuote(iter);
}🤖 Prompt for AI Agents
In `@offline/framework/fun4all/InputFileHandler.cc` around lines 183 - 187, The
code builds a shell command by concatenating m_RunBeforeOpeningScript,
m_OpeningArgs and elements of stringvec into fullcmd which allows shell
injection; fix by avoiding passing a single shell string—either construct an
argument vector and invoke the helper directly with an exec/spawn family call
(use execvp/posix_spawn or equivalent) or, if retaining shell execution,
robustly escape/shell-quote each element (m_OpeningArgs and each element of
stringvec) before concatenation; update the call site that uses fullcmd to
accept an argv-style array or the sanitized, safely-quoted command and reference
the symbols m_RunBeforeOpeningScript, m_OpeningArgs, stringvec and fullcmd when
making changes.
| 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) | ||
| { | ||
| while (select_crossings <= m_MvtxRawHitMap.begin()->first && m_MvtxRawHitMap.begin()->first <= select_crossings + m_mvtx_bco_range) // triggered | ||
| if (bco < lower_limit) | ||
| { | ||
| if (Verbosity() > 2) | ||
| { | ||
| std::cout << "Adding 0x" << std::hex << m_MvtxRawHitMap.begin()->first | ||
| << " ref: 0x" << select_crossings << std::dec << std::endl; | ||
| } | ||
| for (auto *mvtxFeeIdInfo : m_MvtxRawHitMap.begin()->second.MvtxFeeIdInfoVector) | ||
| { | ||
| if (Verbosity() > 1) | ||
| { | ||
| mvtxFeeIdInfo->identify(); | ||
| } | ||
| mvtxEvtHeader->AddFeeIdInfo(mvtxFeeIdInfo); | ||
| delete mvtxFeeIdInfo; | ||
| } | ||
| m_MvtxRawHitMap.begin()->second.MvtxFeeIdInfoVector.clear(); | ||
| mvtxEvtHeader->AddL1Trg(m_MvtxRawHitMap.begin()->second.MvtxL1TrgBco); | ||
| continue; | ||
| } | ||
| if (bco > upper_limit) | ||
| { | ||
| break; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Potential unsigned underflow in lower_limit calculation.
When m_mvtx_is_triggered is false, Line 974 computes:
lower_limit = select_crossings - m_mvtx_bco_range - m_mvtx_negative_bcoSince select_crossings = m_RefBCO + m_mvtx_bco_range (when not triggered), this simplifies to m_RefBCO - m_mvtx_negative_bco. If m_RefBCO < m_mvtx_negative_bco, this will underflow, causing lower_limit to wrap to a very large value and the loop to skip all entries.
Consider adding underflow protection consistent with line 839:
Proposed fix
- uint64_t lower_limit = m_mvtx_is_triggered ? select_crossings : select_crossings - m_mvtx_bco_range - m_mvtx_negative_bco;
+ uint64_t lower_limit = m_mvtx_is_triggered ? select_crossings : (select_crossings > m_mvtx_bco_range + m_mvtx_negative_bco ? select_crossings - m_mvtx_bco_range - m_mvtx_negative_bco : 0);🤖 Prompt for AI Agents
In `@offline/framework/fun4allraw/Fun4AllStreamingInputManager.cc` around lines
974 - 986, The computation of lower_limit in Fun4AllStreamingInputManager::...
can underflow when m_mvtx_is_triggered is false (lower_limit = select_crossings
- m_mvtx_bco_range - m_mvtx_negative_bco); change this to perform a safe
subtraction and clamp to zero (or use a signed/extended intermediate like
int64_t temp = (int64_t)select_crossings - (int64_t)m_mvtx_bco_range -
(int64_t)m_mvtx_negative_bco; lower_limit = temp < 0 ? 0 : (uint64_t)temp) so
that when m_RefBCO < m_mvtx_negative_bco you do not wrap to a huge unsigned
value; apply the same pattern/guarding used earlier around line 839 and ensure
the for-loop over m_MvtxRawHitMap continues to use lower_limit and upper_limit
as before.
| int Fun4AllStreamingInputManager::FillMvtxPool() | ||
| { | ||
| uint64_t ref_bco_minus_range = m_RefBCO < m_mvtx_bco_range ? m_mvtx_bco_range : m_RefBCO - m_mvtx_bco_range; | ||
| uint64_t ref_bco_minus_range = m_RefBCO < m_mvtx_negative_bco ? m_mvtx_negative_bco : m_RefBCO - m_mvtx_negative_bco; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Inconsistent underflow protection value.
Line 1367 defaults to m_mvtx_negative_bco when m_RefBCO < m_mvtx_negative_bco:
uint64_t ref_bco_minus_range = m_RefBCO < m_mvtx_negative_bco ? m_mvtx_negative_bco : m_RefBCO - m_mvtx_negative_bco;This is inconsistent with:
- Line 839 (
FillMvtx): defaults to0 - Lines 1243-1247 (
FillInttPool): defaults to0
Defaulting to m_mvtx_negative_bco doesn't represent a valid minimum BCO value. This should likely default to 0 for consistency.
Proposed fix
- uint64_t ref_bco_minus_range = m_RefBCO < m_mvtx_negative_bco ? m_mvtx_negative_bco : m_RefBCO - m_mvtx_negative_bco;
+ uint64_t ref_bco_minus_range = m_RefBCO < m_mvtx_negative_bco ? 0 : m_RefBCO - m_mvtx_negative_bco;🤖 Prompt for AI Agents
In `@offline/framework/fun4allraw/Fun4AllStreamingInputManager.cc` at line 1367,
The calculation of ref_bco_minus_range in Fun4AllStreamingInputManager.cc uses a
fallback of m_mvtx_negative_bco when m_RefBCO < m_mvtx_negative_bco, which is
inconsistent with other places (FillMvtx, FillInttPool) that default to 0;
change the ternary so that when m_RefBCO < m_mvtx_negative_bco the result
defaults to 0 instead of m_mvtx_negative_bco (i.e., update the computation of
ref_bco_minus_range using m_RefBCO, m_mvtx_negative_bco to return 0 on
underflow) and ensure any logic relying on ref_bco_minus_range continues to
treat 0 as the minimum valid BCO.
| iphimin = std::min<double>(phi, iphimin); | ||
| iphimax = std::max<double>(phi, iphimax); | ||
| ilaymin = std::min(lay, ilaymin); | ||
| ilaymax = std::max(lay, ilaymax); | ||
| itmin = std::min<float>(tbin, itmin); | ||
| itmax = std::max<float>(tbin, itmax); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Variable naming inconsistency: iphimin/iphimax store phi (radians), not iphi (integer index).
Lines 554-555 assign phi (a double representing an angle in radians) to iphimin/iphimax, but the variable names suggest they should store integer phi indices. This causes:
- Precision loss when storing doubles in
intvariables - Confusing semantics - the variables are used to compute
phisizeon line 631
Either rename the variables to phimin/phimax and change their type to double, or use the integer iphi value from coords[1] instead.
🐛 Proposed fix (if tracking phi angles)
- int iphimin = 6666;
- int iphimax = -1;
+ double phimin = std::numeric_limits<double>::max();
+ double phimax = std::numeric_limits<double>::lowest();
...
- iphimin = std::min<double>(phi, iphimin);
- iphimax = std::max<double>(phi, iphimax);
+ phimin = std::min(phi, phimin);
+ phimax = std::max(phi, phimax);
...
- int phisize = iphimax - iphimin + 1;
+ double phisize = phimax - phimin; // Note: units are radians, not bins🐛 Alternative fix (if tracking iphi indices)
- iphimin = std::min<double>(phi, iphimin);
- iphimax = std::max<double>(phi, iphimax);
+ iphimin = std::min(static_cast<int>(coords[1]), iphimin);
+ iphimax = std::max(static_cast<int>(coords[1]), iphimax);📝 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.
| iphimin = std::min<double>(phi, iphimin); | |
| iphimax = std::max<double>(phi, iphimax); | |
| ilaymin = std::min(lay, ilaymin); | |
| ilaymax = std::max(lay, ilaymax); | |
| itmin = std::min<float>(tbin, itmin); | |
| itmax = std::max<float>(tbin, itmax); | |
| iphimin = std::min(static_cast<int>(coords[1]), iphimin); | |
| iphimax = std::max(static_cast<int>(coords[1]), iphimax); | |
| ilaymin = std::min(lay, ilaymin); | |
| ilaymax = std::max(lay, ilaymax); | |
| itmin = std::min<float>(tbin, itmin); | |
| itmax = std::max<float>(tbin, itmax); |
🤖 Prompt for AI Agents
In `@offline/packages/tpc/Tpc3DClusterizer.cc` around lines 554 - 559, The
variables iphimin/iphimax are being assigned the double angle phi (radians)
causing type/semantic mismatch; either (A) treat them as angle bounds: rename
iphimin/iphimax to phimin/phimax and change their type to double, update all
uses (including phisize calculation) to compute angular size from phimin/phimax,
or (B) keep the iphi semantics and assign the integer iphi (from coords[1])
instead of phi so iphimin/iphimax remain integer indices; update any downstream
code that computes phisize on the basis of index vs angle accordingly (check
uses of phi, iphi, coords[1], phisize to ensure consistency).
| // if (m_output){ | ||
| float fX[20] = {0}; | ||
| int n = 0; | ||
| fX[n++] = m_event; | ||
| fX[n++] = m_seed; | ||
| fX[n++] = clusX; | ||
| fX[n++] = clusY; | ||
| fX[n++] = clusZ; | ||
| fX[n++] = clusR; | ||
| fX[n++] = clusPhi; | ||
| fX[n++] = clusiPhi; | ||
| fX[n++] = clusT; | ||
| fX[n++] = adcSum; | ||
| fX[n++] = maxAdc; | ||
| fX[n++] = (layerSum/adcSum); | ||
| fX[n++] = maxsector; | ||
| fX[n++] = maxside; | ||
| fX[n++] = nHits; | ||
| fX[n++] = phisize; | ||
| fX[n++] = tsize; | ||
| fX[n++] = lsize; | ||
| m_clusterNT->Fill(fX); | ||
| // } | ||
| float fX[20] = {0}; | ||
| int n = 0; | ||
| fX[n++] = m_event; | ||
| fX[n++] = m_seed; | ||
| fX[n++] = clusX; | ||
| fX[n++] = clusY; | ||
| fX[n++] = clusZ; | ||
| fX[n++] = clusR; | ||
| fX[n++] = clusPhi; | ||
| fX[n++] = clusiPhi; | ||
| fX[n++] = clusT; | ||
| fX[n++] = adcSum; | ||
| fX[n++] = maxAdc; | ||
| fX[n++] = (layerSum / adcSum); | ||
| fX[n++] = maxsector; | ||
| fX[n++] = maxside; | ||
| fX[n++] = nHits; | ||
| fX[n++] = phisize; | ||
| fX[n++] = tsize; | ||
| fX[n++] = lsize; | ||
| m_clusterNT->Fill(fX); | ||
| // } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Potential null pointer dereference: m_clusterNT->Fill() called unconditionally.
m_clusterNT is only created when m_output is true (line 120), but m_clusterNT->Fill(fX) at line 680 is called unconditionally. If m_output is false, this will crash with a null pointer dereference.
The commented // if (m_output){ at line 659 and // } at line 681 suggest this guard was accidentally removed.
🐛 Proposed fix
- // if (m_output){
float fX[20] = {0};
int n = 0;
fX[n++] = m_event;
...
fX[n++] = lsize;
- m_clusterNT->Fill(fX);
- // }
+ if (m_output)
+ {
+ m_clusterNT->Fill(fX);
+ }📝 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.
| // if (m_output){ | |
| float fX[20] = {0}; | |
| int n = 0; | |
| fX[n++] = m_event; | |
| fX[n++] = m_seed; | |
| fX[n++] = clusX; | |
| fX[n++] = clusY; | |
| fX[n++] = clusZ; | |
| fX[n++] = clusR; | |
| fX[n++] = clusPhi; | |
| fX[n++] = clusiPhi; | |
| fX[n++] = clusT; | |
| fX[n++] = adcSum; | |
| fX[n++] = maxAdc; | |
| fX[n++] = (layerSum/adcSum); | |
| fX[n++] = maxsector; | |
| fX[n++] = maxside; | |
| fX[n++] = nHits; | |
| fX[n++] = phisize; | |
| fX[n++] = tsize; | |
| fX[n++] = lsize; | |
| m_clusterNT->Fill(fX); | |
| // } | |
| float fX[20] = {0}; | |
| int n = 0; | |
| fX[n++] = m_event; | |
| fX[n++] = m_seed; | |
| fX[n++] = clusX; | |
| fX[n++] = clusY; | |
| fX[n++] = clusZ; | |
| fX[n++] = clusR; | |
| fX[n++] = clusPhi; | |
| fX[n++] = clusiPhi; | |
| fX[n++] = clusT; | |
| fX[n++] = adcSum; | |
| fX[n++] = maxAdc; | |
| fX[n++] = (layerSum / adcSum); | |
| fX[n++] = maxsector; | |
| fX[n++] = maxside; | |
| fX[n++] = nHits; | |
| fX[n++] = phisize; | |
| fX[n++] = tsize; | |
| fX[n++] = lsize; | |
| m_clusterNT->Fill(fX); | |
| // } | |
| if (m_output) | |
| { | |
| float fX[20] = {0}; | |
| int n = 0; | |
| fX[n++] = m_event; | |
| fX[n++] = m_seed; | |
| fX[n++] = clusX; | |
| fX[n++] = clusY; | |
| fX[n++] = clusZ; | |
| fX[n++] = clusR; | |
| fX[n++] = clusPhi; | |
| fX[n++] = clusiPhi; | |
| fX[n++] = clusT; | |
| fX[n++] = adcSum; | |
| fX[n++] = maxAdc; | |
| fX[n++] = (layerSum / adcSum); | |
| fX[n++] = maxsector; | |
| fX[n++] = maxside; | |
| fX[n++] = nHits; | |
| fX[n++] = phisize; | |
| fX[n++] = tsize; | |
| fX[n++] = lsize; | |
| m_clusterNT->Fill(fX); | |
| } |
🤖 Prompt for AI Agents
In `@offline/packages/tpc/Tpc3DClusterizer.cc` around lines 659 - 681, The block
that builds the fX array and calls m_clusterNT->Fill(fX) must be guarded because
m_clusterNT is only created when m_output is true; restore a null-check or the
original if (m_output) guard around that block (or at minimum check m_clusterNT
!= nullptr before calling Fill) to avoid a potential null pointer dereference;
update the code around the fX construction and the call to m_clusterNT->Fill so
it only executes when m_output is true and m_clusterNT is valid.
| if (m_pp_mode) | ||
| { | ||
| if (m_enable_crossing_estimate && crossing == SHRT_MAX) | ||
| { | ||
| // this only happens if there is a silicon seed but no assigned INTT crossing, and only in pp_mode | ||
| // If there is no INTT crossing, start with the crossing_estimate value, vary up and down, fit, and choose the best chisq/ndf | ||
| use_estimate = true; | ||
| nvary = max_bunch_search; | ||
| if (Verbosity() > 1) | ||
| { | ||
| std::cout << " No INTT crossing: use crossing_estimate " << crossing_estimate << " with nvary " << nvary << std::endl; | ||
| } | ||
| } | ||
| else | ||
| { | ||
| if (m_enable_crossing_estimate && crossing == SHRT_MAX) | ||
| { | ||
| // this only happens if there is a silicon seed but no assigned INTT crossing, and only in pp_mode | ||
| // If there is no INTT crossing, start with the crossing_estimate value, vary up and down, fit, and choose the best chisq/ndf | ||
| use_estimate = true; | ||
| nvary = max_bunch_search; | ||
| if (Verbosity() > 1) | ||
| { | ||
| std::cout << " No INTT crossing: use crossing_estimate " << crossing_estimate << " with nvary " << nvary << std::endl; | ||
| } | ||
| } | ||
| else | ||
| { | ||
| // use INTT crossing | ||
| crossing_estimate = crossing; | ||
| } | ||
| // use INTT crossing | ||
| crossing_estimate = crossing; | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid using SHRT_MAX as a real crossing when estimates are disabled.
In pp mode, if there’s a silicon seed but no INTT crossing and m_enable_crossing_estimate is false, the code proceeds with crossing_estimate = SHRT_MAX. That sentinel value is likely invalid for drift corrections and fit. Consider skipping the track or defaulting to a safe crossing (e.g., 0) when estimate mode is off.
One possible safeguard (skip when no crossing)
- if (m_pp_mode)
- {
- if (m_enable_crossing_estimate && crossing == SHRT_MAX)
- {
- // this only happens if there is a silicon seed but no assigned INTT crossing, and only in pp_mode
- // If there is no INTT crossing, start with the crossing_estimate value, vary up and down, fit, and choose the best chisq/ndf
- use_estimate = true;
- nvary = max_bunch_search;
- if (Verbosity() > 1)
- {
- std::cout << " No INTT crossing: use crossing_estimate " << crossing_estimate << " with nvary " << nvary << std::endl;
- }
- }
- else
- {
- // use INTT crossing
- crossing_estimate = crossing;
- }
- }
+ if (m_pp_mode)
+ {
+ if (m_enable_crossing_estimate && crossing == SHRT_MAX)
+ {
+ // this only happens if there is a silicon seed but no assigned INTT crossing, and only in pp_mode
+ // If there is no INTT crossing, start with the crossing_estimate value, vary up and down, fit, and choose the best chisq/ndf
+ use_estimate = true;
+ nvary = max_bunch_search;
+ if (Verbosity() > 1)
+ {
+ std::cout << " No INTT crossing: use crossing_estimate " << crossing_estimate << " with nvary " << nvary << std::endl;
+ }
+ }
+ else if (crossing == SHRT_MAX)
+ {
+ if (Verbosity() > 1)
+ {
+ std::cout << " No INTT crossing and estimates disabled; skipping track" << std::endl;
+ }
+ continue;
+ }
+ else
+ {
+ // use INTT crossing
+ crossing_estimate = crossing;
+ }
+ }📝 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.
| if (m_pp_mode) | |
| { | |
| if (m_enable_crossing_estimate && crossing == SHRT_MAX) | |
| { | |
| // this only happens if there is a silicon seed but no assigned INTT crossing, and only in pp_mode | |
| // If there is no INTT crossing, start with the crossing_estimate value, vary up and down, fit, and choose the best chisq/ndf | |
| use_estimate = true; | |
| nvary = max_bunch_search; | |
| if (Verbosity() > 1) | |
| { | |
| std::cout << " No INTT crossing: use crossing_estimate " << crossing_estimate << " with nvary " << nvary << std::endl; | |
| } | |
| } | |
| else | |
| { | |
| if (m_enable_crossing_estimate && crossing == SHRT_MAX) | |
| { | |
| // this only happens if there is a silicon seed but no assigned INTT crossing, and only in pp_mode | |
| // If there is no INTT crossing, start with the crossing_estimate value, vary up and down, fit, and choose the best chisq/ndf | |
| use_estimate = true; | |
| nvary = max_bunch_search; | |
| if (Verbosity() > 1) | |
| { | |
| std::cout << " No INTT crossing: use crossing_estimate " << crossing_estimate << " with nvary " << nvary << std::endl; | |
| } | |
| } | |
| else | |
| { | |
| // use INTT crossing | |
| crossing_estimate = crossing; | |
| } | |
| // use INTT crossing | |
| crossing_estimate = crossing; | |
| } | |
| } | |
| if (m_pp_mode) | |
| { | |
| if (m_enable_crossing_estimate && crossing == SHRT_MAX) | |
| { | |
| // this only happens if there is a silicon seed but no assigned INTT crossing, and only in pp_mode | |
| // If there is no INTT crossing, start with the crossing_estimate value, vary up and down, fit, and choose the best chisq/ndf | |
| use_estimate = true; | |
| nvary = max_bunch_search; | |
| if (Verbosity() > 1) | |
| { | |
| std::cout << " No INTT crossing: use crossing_estimate " << crossing_estimate << " with nvary " << nvary << std::endl; | |
| } | |
| } | |
| else if (crossing == SHRT_MAX) | |
| { | |
| if (Verbosity() > 1) | |
| { | |
| std::cout << " No INTT crossing and estimates disabled; skipping track" << std::endl; | |
| } | |
| continue; | |
| } | |
| else | |
| { | |
| // use INTT crossing | |
| crossing_estimate = crossing; | |
| } | |
| } |
🤖 Prompt for AI Agents
In `@offline/packages/trackreco/PHActsTrkFitter.cc` around lines 391 - 409, The
code currently leaves crossing_estimate set to SHRT_MAX when m_pp_mode is true
and m_enable_crossing_estimate is false, which can propagate an invalid sentinel
into drift corrections and fits; update the logic in PHActsTrkFitter (the block
referencing m_pp_mode, m_enable_crossing_estimate, crossing, crossing_estimate
and SHRT_MAX) to handle the "no INTT crossing" case when estimate mode is
disabled by either (1) skipping the track (return/continue) or (2) setting
crossing_estimate to a safe default (e.g., 0) and not attempting fit; ensure
use_estimate and nvary are only set when m_enable_crossing_estimate is true and
add a clear comment explaining the chosen behavior.
| for (auto const& [path_length, state] : range_adaptor(track->begin_states(), track->end_states())) | ||
| { | ||
| if (path_length == 0) { continue; } | ||
|
|
||
| auto *cluster = cluster_map->findCluster(state->get_cluskey()); | ||
| float state_x = state->get_x(); | ||
| float state_y = state->get_y(); | ||
| float state_z = state->get_z(); | ||
| Acts::Vector3 glob = geometry->getGlobalPosition(state->get_cluskey(), cluster); | ||
| float cluster_x = glob.x(); | ||
| float cluster_y = glob.y(); | ||
| float cluster_z = glob.z(); | ||
| if (cluster) | ||
| { | ||
| m_histograms_x[h]->Fill(state_x - cluster_x); | ||
| m_histograms_y[h]->Fill(state_y - cluster_y); | ||
| m_histograms_z[h]->Fill(state_z - cluster_z); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Null-check cluster before calling ActsGeometry::getGlobalPosition.
findCluster can return null; getGlobalPosition is invoked before the null check, which can crash.
🐛 Proposed fix
- auto *cluster = cluster_map->findCluster(state->get_cluskey());
- float state_x = state->get_x();
- float state_y = state->get_y();
- float state_z = state->get_z();
- Acts::Vector3 glob = geometry->getGlobalPosition(state->get_cluskey(), cluster);
- float cluster_x = glob.x();
- float cluster_y = glob.y();
- float cluster_z = glob.z();
- if (cluster)
- {
- m_histograms_x[h]->Fill(state_x - cluster_x);
- m_histograms_y[h]->Fill(state_y - cluster_y);
- m_histograms_z[h]->Fill(state_z - cluster_z);
- }
+ auto *cluster = cluster_map->findCluster(state->get_cluskey());
+ if (!cluster) { continue; }
+
+ float state_x = state->get_x();
+ float state_y = state->get_y();
+ float state_z = state->get_z();
+ Acts::Vector3 glob = geometry->getGlobalPosition(state->get_cluskey(), cluster);
+ float cluster_x = glob.x();
+ float cluster_y = glob.y();
+ float cluster_z = glob.z();
+ m_histograms_x[h]->Fill(state_x - cluster_x);
+ m_histograms_y[h]->Fill(state_y - cluster_y);
+ m_histograms_z[h]->Fill(state_z - cluster_z);🤖 Prompt for AI Agents
In `@offline/QA/Tracking/StateClusterResidualsQA.cc` around lines 181 - 198, The
code calls geometry->getGlobalPosition(state->get_cluskey(), cluster) before
verifying cluster is non-null, risking a crash; reorder and null-check so you
call cluster_map->findCluster(...) into cluster, then immediately if (!cluster)
continue (or skip) and only then call geometry->getGlobalPosition(..., cluster)
and use its result to compute cluster_x/cluster_y/cluster_z for filling
m_histograms_x/y/z; update the block around findCluster, getGlobalPosition, and
the if (cluster) check accordingly.
| StateClusterResidualsQA& setNMvtx(int min, int max) | ||
| { | ||
| m_pending.back().min_mvtx_clusters = min; | ||
| m_pending.back().max_mvtx_clusters = max; | ||
| return *this; | ||
| } | ||
| StateClusterResidualsQA& setNIntt(int min, int max) | ||
| { | ||
| m_pending.back().min_intt_clusters = min; | ||
| m_pending.back().max_intt_clusters = max; | ||
| return *this; | ||
| } | ||
| StateClusterResidualsQA& setNTpc(int min, int max) | ||
| { | ||
| m_pending.back().min_tpc_clusters = min; | ||
| m_pending.back().max_tpc_clusters = max; | ||
| return *this; | ||
| } | ||
| StateClusterResidualsQA& setPhiRange(float min, float max) | ||
| { | ||
| m_pending.back().phi_min = min; | ||
| m_pending.back().phi_max = max; | ||
| return *this; | ||
| } | ||
| StateClusterResidualsQA& setEtaRange(float min, float max) | ||
| { | ||
| m_pending.back().eta_min = min; | ||
| m_pending.back().eta_max = max; | ||
| return *this; | ||
| } | ||
| StateClusterResidualsQA& setPtRange(float min, float max) | ||
| { | ||
| m_pending.back().pt_min = min; | ||
| m_pending.back().pt_max = max; | ||
| return *this; | ||
| } | ||
| StateClusterResidualsQA& setPositiveTracks() | ||
| { | ||
| m_pending.back().charge = 1; | ||
| return *this; | ||
| } | ||
| StateClusterResidualsQA& setNegativeTracks() | ||
| { | ||
| m_pending.back().charge = -1; | ||
| return *this; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid UB when setters are called before addHistogram.
All setters assume m_pending is non-empty; calling a setter first dereferences an empty vector.
🐛 Proposed fix
StateClusterResidualsQA& setNMvtx(int min, int max)
{
- m_pending.back().min_mvtx_clusters = min;
- m_pending.back().max_mvtx_clusters = max;
+ auto& cfg = current_config();
+ cfg.min_mvtx_clusters = min;
+ cfg.max_mvtx_clusters = max;
return *this;
}
StateClusterResidualsQA& setNIntt(int min, int max)
{
- m_pending.back().min_intt_clusters = min;
- m_pending.back().max_intt_clusters = max;
+ auto& cfg = current_config();
+ cfg.min_intt_clusters = min;
+ cfg.max_intt_clusters = max;
return *this;
}
StateClusterResidualsQA& setNTpc(int min, int max)
{
- m_pending.back().min_tpc_clusters = min;
- m_pending.back().max_tpc_clusters = max;
+ auto& cfg = current_config();
+ cfg.min_tpc_clusters = min;
+ cfg.max_tpc_clusters = max;
return *this;
}
StateClusterResidualsQA& setPhiRange(float min, float max)
{
- m_pending.back().phi_min = min;
- m_pending.back().phi_max = max;
+ auto& cfg = current_config();
+ cfg.phi_min = min;
+ cfg.phi_max = max;
return *this;
}
StateClusterResidualsQA& setEtaRange(float min, float max)
{
- m_pending.back().eta_min = min;
- m_pending.back().eta_max = max;
+ auto& cfg = current_config();
+ cfg.eta_min = min;
+ cfg.eta_max = max;
return *this;
}
StateClusterResidualsQA& setPtRange(float min, float max)
{
- m_pending.back().pt_min = min;
- m_pending.back().pt_max = max;
+ auto& cfg = current_config();
+ cfg.pt_min = min;
+ cfg.pt_max = max;
return *this;
}
StateClusterResidualsQA& setPositiveTracks()
{
- m_pending.back().charge = 1;
+ current_config().charge = 1;
return *this;
}
StateClusterResidualsQA& setNegativeTracks()
{
- m_pending.back().charge = -1;
+ current_config().charge = -1;
return *this;
}
private:
+ ResidualHistConfig& current_config()
+ {
+ if (m_pending.empty())
+ {
+ m_pending.emplace_back();
+ }
+ return m_pending.back();
+ }
std::vector<ResidualHistConfig> m_pending;📝 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.
| StateClusterResidualsQA& setNMvtx(int min, int max) | |
| { | |
| m_pending.back().min_mvtx_clusters = min; | |
| m_pending.back().max_mvtx_clusters = max; | |
| return *this; | |
| } | |
| StateClusterResidualsQA& setNIntt(int min, int max) | |
| { | |
| m_pending.back().min_intt_clusters = min; | |
| m_pending.back().max_intt_clusters = max; | |
| return *this; | |
| } | |
| StateClusterResidualsQA& setNTpc(int min, int max) | |
| { | |
| m_pending.back().min_tpc_clusters = min; | |
| m_pending.back().max_tpc_clusters = max; | |
| return *this; | |
| } | |
| StateClusterResidualsQA& setPhiRange(float min, float max) | |
| { | |
| m_pending.back().phi_min = min; | |
| m_pending.back().phi_max = max; | |
| return *this; | |
| } | |
| StateClusterResidualsQA& setEtaRange(float min, float max) | |
| { | |
| m_pending.back().eta_min = min; | |
| m_pending.back().eta_max = max; | |
| return *this; | |
| } | |
| StateClusterResidualsQA& setPtRange(float min, float max) | |
| { | |
| m_pending.back().pt_min = min; | |
| m_pending.back().pt_max = max; | |
| return *this; | |
| } | |
| StateClusterResidualsQA& setPositiveTracks() | |
| { | |
| m_pending.back().charge = 1; | |
| return *this; | |
| } | |
| StateClusterResidualsQA& setNegativeTracks() | |
| { | |
| m_pending.back().charge = -1; | |
| return *this; | |
| } | |
| StateClusterResidualsQA& setNMvtx(int min, int max) | |
| { | |
| auto& cfg = current_config(); | |
| cfg.min_mvtx_clusters = min; | |
| cfg.max_mvtx_clusters = max; | |
| return *this; | |
| } | |
| StateClusterResidualsQA& setNIntt(int min, int max) | |
| { | |
| auto& cfg = current_config(); | |
| cfg.min_intt_clusters = min; | |
| cfg.max_intt_clusters = max; | |
| return *this; | |
| } | |
| StateClusterResidualsQA& setNTpc(int min, int max) | |
| { | |
| auto& cfg = current_config(); | |
| cfg.min_tpc_clusters = min; | |
| cfg.max_tpc_clusters = max; | |
| return *this; | |
| } | |
| StateClusterResidualsQA& setPhiRange(float min, float max) | |
| { | |
| auto& cfg = current_config(); | |
| cfg.phi_min = min; | |
| cfg.phi_max = max; | |
| return *this; | |
| } | |
| StateClusterResidualsQA& setEtaRange(float min, float max) | |
| { | |
| auto& cfg = current_config(); | |
| cfg.eta_min = min; | |
| cfg.eta_max = max; | |
| return *this; | |
| } | |
| StateClusterResidualsQA& setPtRange(float min, float max) | |
| { | |
| auto& cfg = current_config(); | |
| cfg.pt_min = min; | |
| cfg.pt_max = max; | |
| return *this; | |
| } | |
| StateClusterResidualsQA& setPositiveTracks() | |
| { | |
| current_config().charge = 1; | |
| return *this; | |
| } | |
| StateClusterResidualsQA& setNegativeTracks() | |
| { | |
| current_config().charge = -1; | |
| return *this; | |
| } | |
| private: | |
| ResidualHistConfig& current_config() | |
| { | |
| if (m_pending.empty()) | |
| { | |
| m_pending.emplace_back(); | |
| } | |
| return m_pending.back(); | |
| } | |
| std::vector<ResidualHistConfig> m_pending; |
🤖 Prompt for AI Agents
In `@offline/QA/Tracking/StateClusterResidualsQA.h` around lines 56 - 101, These
setters (setNMvtx, setNIntt, setNTpc, setPhiRange, setEtaRange, setPtRange,
setPositiveTracks, setNegativeTracks) assume m_pending.back() exists and cause
UB if called before an addHistogram; guard each setter by ensuring m_pending is
non-empty (e.g., if m_pending.empty() push_back(default-constructed
PendingEntry) or throw/assert with a clear message) before accessing
m_pending.back(), so callers can safely call any setter before addHistogram;
update all listed methods to perform the same presence check and create a
default pending entry when missing.
|
Note Docstrings generation - SUCCESS |
Docstrings generation was requested by @blackcathj. * #13 (comment) The following files were modified: * `generators/Herwig/HepMCTrigger/HepMCJetTrigger.cc` * `generators/Herwig/HepMCTrigger/HepMCParticleTrigger.cc` * `generators/Herwig/HepMCTrigger/HepMCParticleTrigger.h` * `generators/PHPythia8/PHPythia8.cc` * `generators/phhepmc/PHHepMCGenEventv1.cc` * `offline/QA/Calorimeters/CaloValid.cc` * `offline/QA/Tracking/MicromegasClusterQA.cc` * `offline/QA/Tracking/MicromegasClusterQA.h` * `offline/QA/Tracking/StateClusterResidualsQA.cc` * `offline/QA/Tracking/StateClusterResidualsQA.h` * `offline/framework/ffamodules/CDBInterface.cc` * `offline/framework/ffamodules/FlagHandler.h` * `offline/framework/ffamodules/HeadReco.cc` * `offline/framework/ffamodules/HeadReco.h` * `offline/framework/ffamodules/SyncReco.h` * `offline/framework/ffamodules/Timing.cc` * `offline/framework/ffamodules/Timing.h` * `offline/framework/fun4all/Fun4AllServer.cc` * `offline/framework/fun4all/Fun4AllServer.h` * `offline/framework/fun4all/InputFileHandler.cc` * `offline/framework/fun4all/InputFileHandler.h` * `offline/framework/fun4allraw/Fun4AllStreamingInputManager.cc` * `offline/framework/fun4allraw/SingleMicromegasPoolInput_v2.cc` * `offline/framework/fun4allraw/SingleMicromegasPoolInput_v2.h` * `offline/framework/fun4allraw/SingleMvtxPoolInput.cc` * `offline/framework/fun4allraw/SingleTriggeredInput.cc` * `offline/framework/fun4allraw/SingleTriggeredInput.h` * `offline/packages/CaloEmbedding/CombineTowerInfo.cc` * `offline/packages/CaloEmbedding/CombineTowerInfo.h` * `offline/packages/CaloEmbedding/CopyIODataNodes.cc` * `offline/packages/CaloEmbedding/CopyIODataNodes.h` * `offline/packages/CaloReco/PhotonClusterBuilder.cc` * `offline/packages/KFParticle_sPHENIX/KFParticle_sPHENIX.cc` * `offline/packages/PHGenFitPkg/PHGenFit/Fitter.cc` * `offline/packages/PHGenFitPkg/PHGenFit/Track.cc` * `offline/packages/Skimmers/Trigger/TriggerDSTSkimmer.cc` * `offline/packages/Skimmers/Trigger/TriggerDSTSkimmer.h` * `offline/packages/jetbackground/DetermineTowerBackground.cc` * `offline/packages/jetbackground/DetermineTowerBackground.h` * `offline/packages/mbd/MbdCalib.cc` * `offline/packages/mbd/MbdEvent.cc` * `offline/packages/mbd/MbdReco.cc` * `offline/packages/mbd/MbdSig.h` * `offline/packages/micromegas/MicromegasClusterizer.cc` * `offline/packages/micromegas/MicromegasCombinedDataDecoder.cc` * `offline/packages/micromegas/MicromegasCombinedDataDecoder.h` * `offline/packages/micromegas/MicromegasDefs.cc` * `offline/packages/micromegas/MicromegasDefs.h` * `offline/packages/mvtx/CylinderGeom_Mvtx.cc` * `offline/packages/mvtx/CylinderGeom_Mvtx.h` * `offline/packages/mvtx/MvtxClusterPruner.cc` * `offline/packages/mvtx/MvtxClusterizer.cc` * `offline/packages/mvtx/MvtxHitPruner.cc` * `offline/packages/mvtx/SegmentationAlpide.cc` * `offline/packages/tpc/LaserClusterizer.cc` * `offline/packages/tpc/LaserEventIdentifier.cc` * `offline/packages/tpc/Tpc3DClusterizer.cc` * `offline/packages/tpc/TpcClusterMover.cc` * `offline/packages/tpc/TpcClusterMover.h` * `offline/packages/tpc/TpcClusterizer.cc` * `offline/packages/tpc/TpcCombinedRawDataUnpacker.cc` * `offline/packages/tpc/TpcCombinedRawDataUnpackerDebug.cc` * `offline/packages/tpc/TpcDistortionCorrection.cc` * `offline/packages/tpc/TpcLoadDistortionCorrection.cc` * `offline/packages/tpc/TpcRawDataTree.cc` * `offline/packages/tpc/TpcRawWriter.cc` * `offline/packages/tpc/TpcSimpleClusterizer.cc` * `offline/packages/tpc/TrainingHits.cc` * `offline/packages/trackbase/AlignmentTransformation.cc` * `offline/packages/trackbase/AlignmentTransformation.h` * `offline/packages/trackreco/DSTClusterPruning.cc` * `offline/packages/trackreco/DSTClusterPruning.h` * `offline/packages/trackreco/PHActsTrkFitter.cc` * `offline/packages/trackreco/PHActsTrkFitter.h` * `offline/packages/trackreco/PHSiliconTpcTrackMatching.cc` * `offline/packages/trackreco/PHSiliconTpcTrackMatching.h` * `offline/packages/trackreco/PHSimpleVertexFinder.h` * `offline/packages/trackreco/PHTpcDeltaZCorrection.h`
Types of changes
What kind of change does this PR introduce? (Bug fix, feature, ...)
TODOs (if applicable)
Links to other PRs in macros and calibration repositories (if applicable)
Summary by CodeRabbit
New Features
Improvements
✏️ Tip: You can customize this high-level summary in your review settings.