Skip to content

Initial version. Requires later updates to remove reference to user …#4288

Merged
osbornjd merged 6 commits into
sPHENIX-Collaboration:masterfrom
tkhemmick:PHGarfield
Jun 9, 2026
Merged

Initial version. Requires later updates to remove reference to user …#4288
osbornjd merged 6 commits into
sPHENIX-Collaboration:masterfrom
tkhemmick:PHGarfield

Conversation

@tkhemmick

@tkhemmick tkhemmick commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

…directories.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work for users)
  • Requiring change in macros repository (Please provide links to the macros pull request in the last section)
  • I am a member of GitHub organization of sPHENIX Collaboration, EIC, or ECCE (contact Chris Pinkenburg to join)

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)

PHGarfield Integration – Version 0.9

Motivation & Context

This PR introduces PHGarfield, a Garfield++ integration module for the sPHENIX TPC. The package provides electron drift and field simulation capabilities within the Fun4All framework, enabling detailed tracking and reconstruction studies. This is the initial 0.9 release presented to the Tracking Group on June 4, 2026.

Key Changes

  • PHGarfield module (PHGarfield.h/cc): Main SubsysReco class integrating Garfield++ with Fun4All. Features include:

    • Initialization of magnetic field maps and TPC pad/channel mappings from CDB
    • Gas model setup by loading and merging partitioned gas files (PART_0.gas, PART_1.gas, etc.)
    • Magnetic and electric field callbacks for Garfield
    • Electron drift reversal along computed trajectories (ReverseDrift)
    • Boundary condition checking (StopHere) for radial/z limits and membrane crossings
    • Diagnostic tools for field/gas/geometry visualization
  • GasModel utility (GasModel.cc): Standalone executable to generate gas tables for specified E/B/angle ranges with configurable grid parameters

  • MergeGasFiles utility (MergeGasFiles.cc): Standalone tool to merge gas file partitions and validate transport property changes via Monte Carlo sampling (outputs GarfieldValidity.root)

  • Build system (Makefile.am, configure.ac, autogen.sh, PHGarfieldLinkDef.h): Complete autotools configuration for library/executable compilation with ROOT dictionary generation

Potential Risk Areas

  • Hardcoded user directories (acknowledged in PR description): PHGarfield.cc contains absolute path /direct/phenix+u/workarea/hemmick/code.sphenix/tkh/gas/gasfiles/ that must be updated to a portable/configurable location
  • External gas file dependencies: Code assumes PART_*.gas files exist in a specific directory; missing files silently terminate gas initialization
  • Hard-coded gas mixture: Ar/CF4/isobutane (75/20/5) and temperature/pressure values are fixed; future flexibility may be needed
  • ROOT dictionary requirements: Relies on rootcint for CINT dictionary generation; build may fail in non-ROOT environments
  • CDB dependencies: Initialization requires CDB access for field maps and TPC mappings; offline/test environments must provide these

Possible Future Improvements

  • Make gas file directory configurable via initialization parameters or environment variables
  • Add validation of gas file existence before loading
  • Support configurable gas mixtures and operating conditions
  • Implement actual event-level processing in process_event() (currently a no-op)
  • Extend boundary condition logic for more sophisticated stopping criteria
  • Add thread-safety considerations if used in multi-threaded contexts

Note on Summary Accuracy: AI-generated analyses may contain errors or miss important implementation details. Review actual source files for authoritative behavior, especially regarding hardcoded paths, gas mixture specifications, and integration points with CDB and field systems.

@coderabbitai

coderabbitai Bot commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

This PR introduces PHGarfield, a Fun4All module integrating the Garfield electron-transport library. It provides the complete build configuration (Automake/Autoconf), the SubsysReco class with field callbacks and drift-trajectory visualization, and two standalone tools for gas table generation and validation.

Changes

PHGarfield integration

Layer / File(s) Summary
Build system: Automake, Autoconf, and bootstrap
offline/packages/PHGarfield/Makefile.am, autogen.sh, configure.ac
Automake rules build libPHGarfield and two executables (GasModel, MergeGasFiles), generate ROOT CINT dictionaries via rootcint, and define strict C++ warnings. Autotools bootstrap script invokes the configuration sequence with forwarded arguments.
PHGarfield class interface and ROOT dictionary
offline/packages/PHGarfield/PHGarfield.h, PHGarfieldLinkDef.h
PHGarfield extends SubsysReco with lifecycle hooks (InitRun, process_event), public field callbacks for Garfield, trajectory visualization (ReverseDrift), stopping conditions, diagnostics (PrintGarfield, PrintMaps), and a radii[48] array. LinkDef pragma enables ROOT dictionary generation.
PHGarfield constructor and InitRun
offline/packages/PHGarfield/PHGarfield.cc (lines 1–87)
Constructor initializes phi-wrap constant; InitRun loads CDB-backed magnetic field map and TPC pad calibration, creates Garfield::ComponentUser, registers field-getter lambdas, initializes gas from disk, and populates diagnostics.
Field callbacks and gas initialization
offline/packages/PHGarfield/PHGarfield.cc (lines 189–263)
GetMagneticFieldTesla converts cm coordinates to PHField3DCartesian units and returns Tesla-scaled field; GetElectricFieldVcm returns fixed z-directed field; InitializeGas loads PART_0.gas and merges successive PART_i.gas files into a MediumMagboltz until the first missing part.
Diagnostics: FillRadii, PrintGarfield, PrintMaps
offline/packages/PHGarfield/PHGarfield.cc (lines 89–187)
FillRadii scans TPC pad-map entries and populates the radii array; PrintGarfield queries E/B fields and electron drift velocity at a point and prints values; PrintMaps samples probe points and pad-map entries, computing phi and radius for debugging output.
Trajectory tracing and boundary utilities
offline/packages/PHGarfield/PHGarfield.cc (lines 276–366)
ReverseDrift back-steps a point iteratively along electron drift velocity using Garfield E/B and gas model, building and returning a TPolyLine3D; StopHere terminates when radial/z bounds are exceeded or z changes sign (membrane crossing); bounder wraps angles; process_event is a no-op.
GasModel: standalone gas table generator
offline/packages/PHGarfield/GasModel.cc
Command-line tool requiring 10 arguments (E/B/angle grid ranges and point counts, output filename). Parses arguments, validates count, configures fixed Ar/CF4/isobutane gas with hard-coded T/P, sets field grid, generates a Magboltz table via GenerateGasTable(10), and writes output via WriteGasFile.
MergeGasFiles: merge and validation utility
offline/packages/PHGarfield/MergeGasFiles.cc
Loads PART_0.gas into two gas instances; iteratively merges successive PART_i.gas files into the primary instance. Validates merged gas via Monte Carlo: samples electric field fixed at 400, draws magnetic field direction uniformly, and compares electron velocities from merged vs. unmerged gas in both in-range and out-of-range B field regimes, writing normalized velocity deltas to a ROOT TNtuple.

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 Infer (1.2.0)
offline/packages/PHGarfield/MergeGasFiles.cc

offline/packages/PHGarfield/MergeGasFiles.cc:1:10: fatal error: 'TMath.h' file not found
1 | #include <TMath.h>
| ^~~~~~~~~
1 error generated.
Error: the following clang command did not run successfully:
/opt/infer-linux-x86_64-v1.2.0/lib/infer/facebook-clang-plugins/clang/install/bin/clang-18
@/tmp/coderabbit-infer/391555cfaf7c57ff55bb2425370a5e43ad072f9b-77048d2b2d98d3bd/tmp/clang_command_.tmp.e017e7.txt
++Contents of '/tmp/coderabbit-infer/391555cfaf7c57ff55bb2425370a5e43ad072f9b-77048d2b2d98d3bd/tmp/clang_command_.tmp.e017e7.txt':
"-cc1" "-load"
"/opt/infer-linux-x86_64-v1.2.0/lib/infer/infer/bin/../../facebook-clang-plugins/libtooling/build/FacebookClangPlugin.dylib"
"-add-plugin" "BiniouASTExporter" "-plugin-arg-BiniouASTExporter" "-"
"-plugin-arg-BiniouASTExporter" "PREPEND_CURRENT_DIR=1"
"-plugin-arg-BiniouASTExporter" "MAX_STRING_SIZE=65535" "-cc1" "-triple"
"x86_64-unknown-linux-gnu" "-emit-obj" "-mrelax-all" "-disable-free

... [truncated 1091 characters] ...

include"
"-internal-isystem" "/usr/local/include" "-internal-isystem"
"/usr/lib/gcc/x86_64-linux-gnu/12/../../../../x86_64-linux-gnu/include"
"-internal-externc-isystem" "/usr/include/x86_64-linux-gnu"
"-internal-externc-isystem" "/include" "-internal-externc-isystem"
"/usr/include" "-Wno-ignored-optimization-argument" "-Wno-everything"
"-fdeprecated-macro" "-ferror-limit" "19" "-fgnuc-version=4.2.1"
"-fskip-odr-check-in-gmf" "-fcxx-exceptions" "-fexceptions"
"-D__GCC_HAVE_DWARF2_CFI_ASM=1" "-o"
"/tmp/coderabbit-infer/77048d2b2d98d3bd/file.o" "-x" "c++"
"offline/packages/PHGarfield/MergeGasFiles.cc" "-O0" "-fno-builtin"
"-include"
"/opt/infer-linux-x86_64-v1.2.0/lib/infer/infer/bin/../lib/clang_wrappers/global_defines.h"
"-Wno-everything"

offline/packages/PHGarfield/GasModel.cc

offline/packages/PHGarfield/GasModel.cc:4:10: fatal error: 'Garfield/ComponentUser.hh' file not found
4 | #include <Garfield/ComponentUser.hh>
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
Error: the following clang command did not run successfully:
/opt/infer-linux-x86_64-v1.2.0/lib/infer/facebook-clang-plugins/clang/install/bin/clang-18
@/tmp/coderabbit-infer/391555cfaf7c57ff55bb2425370a5e43ad072f9b-20acc2671eb4cfca/tmp/clang_command_.tmp.c57c0d.txt
++Contents of '/tmp/coderabbit-infer/391555cfaf7c57ff55bb2425370a5e43ad072f9b-20acc2671eb4cfca/tmp/clang_command_.tmp.c57c0d.txt':
"-cc1" "-load"
"/opt/infer-linux-x86_64-v1.2.0/lib/infer/infer/bin/../../facebook-clang-plugins/libtooling/build/FacebookClangPlugin.dylib"
"-add-plugin" "BiniouASTExporter" "-plugin-arg-BiniouASTExporter" "-"
"-plugin-arg-BiniouASTExporter" "PREPEND_CURRENT_DIR=1"
"-plugin-arg-BiniouASTExporter" "MAX_STRING_SIZE=65535" "-cc1" "-triple"
"x86_64-unknown-li

... [truncated 1126 characters] ...

clang/18/include"
"-internal-isystem" "/usr/local/include" "-internal-isystem"
"/usr/lib/gcc/x86_64-linux-gnu/12/../../../../x86_64-linux-gnu/include"
"-internal-externc-isystem" "/usr/include/x86_64-linux-gnu"
"-internal-externc-isystem" "/include" "-internal-externc-isystem"
"/usr/include" "-Wno-ignored-optimization-argument" "-Wno-everything"
"-fdeprecated-macro" "-ferror-limit" "19" "-fgnuc-version=4.2.1"
"-fskip-odr-check-in-gmf" "-fcxx-exceptions" "-fexceptions"
"-D__GCC_HAVE_DWARF2_CFI_ASM=1" "-o"
"/tmp/coderabbit-infer/20acc2671eb4cfca/file.o" "-x" "c++"
"offline/packages/PHGarfield/GasModel.cc" "-O0" "-fno-builtin" "-include"
"/opt/infer-linux-x86_64-v1.2.0/lib/infer/infer/bin/../lib/clang_wrappers/global_defines.h"
"-Wno-everything"

offline/packages/PHGarfield/PHGarfield.cc

In file included from offline/packages/PHGarfield/PHGarfield.cc:1:
offline/packages/PHGarfield/PHGarfield.h:7:10: fatal error: 'fun4all/SubsysReco.h' file not found
7 | #include <fun4all/SubsysReco.h>
| ^~~~~~~~~~~~~~~~~~~~~~
1 error generated.
Error: the following clang command did not run successfully:
/opt/infer-linux-x86_64-v1.2.0/lib/infer/facebook-clang-plugins/clang/install/bin/clang-18
@/tmp/coderabbit-infer/391555cfaf7c57ff55bb2425370a5e43ad072f9b-c2b745a77dabe20a/tmp/clang_command_.tmp.0efd39.txt
++Contents of '/tmp/coderabbit-infer/391555cfaf7c57ff55bb2425370a5e43ad072f9b-c2b745a77dabe20a/tmp/clang_command_.tmp.0efd39.txt':
"-cc1" "-load"
"/opt/infer-linux-x86_64-v1.2.0/lib/infer/infer/bin/../../facebook-clang-plugins/libtooling/build/FacebookClangPlugin.dylib"
"-add-plugin" "BiniouASTExporter" "-plugin-arg-BiniouASTExporter" "-"
"-plugin-arg-BiniouASTExporter" "PREPEND_CURRENT_DIR=1"
"-plugin-arg-BiniouASTExporter" "MAX_STRIN

... [truncated 1187 characters] ...

18/include"
"-internal-isystem" "/usr/local/include" "-internal-isystem"
"/usr/lib/gcc/x86_64-linux-gnu/12/../../../../x86_64-linux-gnu/include"
"-internal-externc-isystem" "/usr/include/x86_64-linux-gnu"
"-internal-externc-isystem" "/include" "-internal-externc-isystem"
"/usr/include" "-Wno-ignored-optimization-argument" "-Wno-everything"
"-fdeprecated-macro" "-ferror-limit" "19" "-fgnuc-version=4.2.1"
"-fskip-odr-check-in-gmf" "-fcxx-exceptions" "-fexceptions"
"-D__GCC_HAVE_DWARF2_CFI_ASM=1" "-o"
"/tmp/coderabbit-infer/c2b745a77dabe20a/file.o" "-x" "c++"
"offline/packages/PHGarfield/PHGarfield.cc" "-O0" "-fno-builtin"
"-include"
"/opt/infer-linux-x86_64-v1.2.0/lib/infer/infer/bin/../lib/clang_wrappers/global_defines.h"
"-Wno-everything"


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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 8


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 5e0f17e5-1657-436d-af8c-fca4e98300c8

📥 Commits

Reviewing files that changed from the base of the PR and between 9128ec0 and 708f777.

📒 Files selected for processing (11)
  • offline/packages/PHGarfield/GasModel.cc
  • offline/packages/PHGarfield/Makefile.am
  • offline/packages/PHGarfield/MergeGasFiles.cc
  • offline/packages/PHGarfield/PHGarfield.cc
  • offline/packages/PHGarfield/PHGarfield.h
  • offline/packages/PHGarfield/PHGarfieldLinkDef.h
  • offline/packages/PHGarfield/autogen.sh
  • offline/packages/PHGarfield/configure.ac
  • offline/packages/PHGarfield/macros/GasModel_condor.job
  • offline/packages/PHGarfield/macros/StartScript.sh
  • offline/packages/PHGarfield/macros/TestFieldMap.C

Comment on lines +5 to +8
(cd $srcdir; aclocal -I ${OFFLINE_MAIN}/share;\
libtoolize --force; automake -a --add-missing; autoconf)

$srcdir/configure "$@"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Fail fast during autotools bootstrap instead of masking intermediate failures.

Using ; means a failing aclocal/libtoolize/automake can be hidden if a later command succeeds, and the script still proceeds to configure.

Proposed fix
 #!/bin/sh
-srcdir=`dirname $0`
+set -e
+srcdir="$(dirname "$0")"
 test -z "$srcdir" && srcdir=.
 
-(cd $srcdir; aclocal -I ${OFFLINE_MAIN}/share;\
-libtoolize --force; automake -a --add-missing; autoconf)
+(
+  cd "$srcdir" || exit 1
+  aclocal -I "${OFFLINE_MAIN}/share"
+  libtoolize --force
+  automake -a --add-missing
+  autoconf
+)
 
-$srcdir/configure  "$@"
+"$srcdir/configure" "$@"
🧰 Tools
🪛 Shellcheck (0.11.0)

[warning] 5-5: Use 'cd ... || exit' or 'cd ... || return' in case cd fails.

(SC2164)


[info] 5-5: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 5-5: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 8-8: Double quote to prevent globbing and word splitting.

(SC2086)

Comment on lines +35 to +46
const double Emin = std::atof(argv[1]);
const double Emax = std::atof(argv[2]);
const int nE = std::atoi(argv[3]);

const double Bmin = std::atof(argv[4]);
const double Bmax = std::atof(argv[5]);
const int nB = std::atoi(argv[6]);

const double Amin = std::atof(argv[7]);
const double Amax = std::atof(argv[8]);
const int nA = std::atoi(argv[9]);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Validate grid bounds and bin counts before calling SetFieldGrid.

The program accepts nE/nB/nA and min/max ranges without sanity checks. Zero/negative counts or inverted ranges can produce invalid gas-table requests and runtime failures.

Proposed fix
   const double Amin = std::atof(argv[7]);
   const double Amax = std::atof(argv[8]);
   const int    nA   = std::atoi(argv[9]);

+  if (nE <= 0 || nB <= 0 || nA <= 0) {
+    std::cerr << "Grid sizes must be > 0.\n";
+    return 1;
+  }
+  if (Emin > Emax || Bmin > Bmax || Amin > Amax) {
+    std::cerr << "Each min value must be <= max value.\n";
+    return 1;
+  }
+
   const string output_file(argv[10]);

As per coding guidelines: **/*.{cc,cpp,cxx,c} reviews must prioritize correctness/error handling and only raise Critical or Major findings.

Also applies to: 74-76

Comment thread offline/packages/PHGarfield/macros/GasModel_condor.job Outdated
Comment on lines +24 to +31
output="/direct/phenix+u/workarea/hemmick/code.sphenix/tkh/gas/gasfiles/PART_"$1".gas"

echo $output

echo GasModel $emin $emax $ne $bnow $bnow 1 $amin $amax $na $output
GasModel $emin $emax $ne $bnow $bnow 1 $amin $amax $na $output

echo all done

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Preserve command failure status and avoid hardcoded output path.

The script currently masks GasModel failures (final echo returns 0) and writes to a user-specific absolute path, which breaks portability and can mark failed jobs as successful.

Proposed fix
 #! /bin/bash
+set -euo pipefail
@@
-output="/direct/phenix+u/workarea/hemmick/code.sphenix/tkh/gas/gasfiles/PART_"$1".gas"
+script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+mkdir -p "${script_dir}/gasfiles"
+output="${script_dir}/gasfiles/PART_${1}.gas"
@@
-GasModel $emin $emax $ne $bnow $bnow 1 $amin $amax $na $output
+GasModel "$emin" "$emax" "$ne" "$bnow" "$bnow" 1 "$amin" "$amax" "$na" "$output"
 
 echo all done
📝 Committable suggestion

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

Suggested change
output="/direct/phenix+u/workarea/hemmick/code.sphenix/tkh/gas/gasfiles/PART_"$1".gas"
echo $output
echo GasModel $emin $emax $ne $bnow $bnow 1 $amin $amax $na $output
GasModel $emin $emax $ne $bnow $bnow 1 $amin $amax $na $output
echo all done
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
mkdir -p "${script_dir}/gasfiles"
output="${script_dir}/gasfiles/PART_${1}.gas"
echo $output
echo GasModel "$emin" "$emax" "$ne" "$bnow" "$bnow" 1 "$amin" "$amax" "$na" "$output"
GasModel "$emin" "$emax" "$ne" "$bnow" "$bnow" 1 "$amin" "$amax" "$na" "$output"
echo all done
🧰 Tools
🪛 Shellcheck (0.11.0)

[warning] 24-24: The surrounding quotes actually unquote this. Remove or escape them.

(SC2027)


[info] 26-26: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 28-28: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 28-28: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 28-28: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 29-29: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 29-29: Double quote to prevent globbing and word splitting.

(SC2086)


[info] 29-29: Double quote to prevent globbing and word splitting.

(SC2086)


[warning] 31-31: Use semicolon or linefeed before 'done' (or quote to make it literal).

(SC1010)

Comment on lines +153 to +156
double DelVx = (vx-vx0)/((vx+vx0)/2.);
double DelVy = (vy-vy0)/((vy+vy0)/2.);
double DelVz = (vz-vz0)/((vz+vz0)/2.);
Validity->Fill(1,sqrt(ex*ex + ey*ey + ez*ez),sqrt(bx*bx + by*by + bz*bz),a,DelVx, DelVy, DelVz);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Guard the relative-difference denominator to avoid NaN/Inf in validation output.

If (v + v0) is zero (or very small), these divisions produce unstable/invalid values that pollute GarfieldValidity.root.

Proposed fix
+  auto rel_diff = [](double v, double v0) {
+    const double denom = 0.5 * (v + v0);
+    constexpr double eps = 1e-12;
+    if (std::abs(denom) < eps) return 0.0;
+    return (v - v0) / denom;
+  };
...
-      double DelVx = (vx-vx0)/((vx+vx0)/2.);
-      double DelVy = (vy-vy0)/((vy+vy0)/2.);
-      double DelVz = (vz-vz0)/((vz+vz0)/2.);
+      double DelVx = rel_diff(vx, vx0);
+      double DelVy = rel_diff(vy, vy0);
+      double DelVz = rel_diff(vz, vz0);
...
-      double DelVx = (vx-vx0)/((vx+vx0)/2.);
-      double DelVy = (vy-vy0)/((vy+vy0)/2.);
-      double DelVz = (vz-vz0)/((vz+vz0)/2.);
+      double DelVx = rel_diff(vx, vx0);
+      double DelVy = rel_diff(vy, vy0);
+      double DelVz = rel_diff(vz, vz0);

As per coding guidelines: **/*.{cc,cpp,cxx,c} reviews must prioritize correctness/error handling and only raise Critical or Major findings.

Also applies to: 211-214

m_component = new Garfield::ComponentUser();
m_component->SetMagneticField([this](double x, double y, double z,double& bx, double& by, double& bz) { GetMagneticFieldTesla(x, y, z, bx, by, bz); });
m_component->SetElectricField([this](double x, double y, double z,double& ex, double& ey, double& ez) { GetElectricFieldVcm (x, y, z, ex, ey, ez); });
InitializeGas("/direct/phenix+u/workarea/hemmick/code.sphenix/tkh/gas/gasfiles/");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Fail InitRun when gas table loading fails, and remove user-specific path coupling.

Line 81 hardcodes a user directory, and InitializeGas (Lines 221-262) only logs on failure but does not propagate status. Line 87 still returns EVENT_OK, so the subsystem continues after failed gas setup.

Suggested fix pattern
-  InitializeGas("/direct/phenix+u/workarea/hemmick/code.sphenix/tkh/gas/gasfiles/");
+  const std::string gas_dir = /* resolve from config/CDB/env */;
+  if (!InitializeGas(gas_dir))
+  {
+    std::cerr << "PHGarfield: gas initialization failed for " << gas_dir << std::endl;
+    return Fun4AllReturnCodes::ABORTRUN;
+  }
...
-void PHGarfield::InitializeGas(std::string dir)
+bool PHGarfield::InitializeGas(const std::string& dir)
 {
-  m_gas = new Garfield::MediumMagboltz();
+  m_gas = new Garfield::MediumMagboltz();
...
-      return;
+      return false;
...
-      return;
+      return false;
...
-      return;
+      return false;
...
+  return true;
}

As per coding guidelines **/*.{cc,cpp,cxx,c}: “Prioritize correctness, memory safety, error handling, and thread-safety.”

Also applies to: 221-262, 87-87

Comment on lines +286 to +313
TPolyLine3D *PHGarfield::ReverseDrift (double x, double y, double z, double step_ns)
{
vector<double> xlist;
vector<double> ylist;
vector<double> zlist;

xlist.push_back(x);
ylist.push_back(y);
zlist.push_back(z);

double ex, ey, ez, bx, by, bz, vx, vy, vz;

double zPrevious = z;
while (!StopHere(x,y,z,zPrevious))
{
zPrevious = z;
GetMagneticFieldTesla( x, y, z, bx, by, bz);
GetElectricFieldVcm ( x, y, z, ex, ey, ez);
m_gas->ElectronVelocity(ex, ey, ez, bx, by, bz, vx, vy, vz);

x = x - vx*step_ns;
y = y - vy*step_ns;
z = z - vz*step_ns;

xlist.push_back(x);
ylist.push_back(y);
zlist.push_back(z);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Guard ReverseDrift against non-positive step_ns to avoid hangs.

If step_ns <= 0, the state does not progress toward termination and the loop at Line 299 can become non-terminating.

Minimal guard
 TPolyLine3D *PHGarfield::ReverseDrift (double x, double y, double z, double step_ns)
 {
+  if (step_ns <= 0.0)
+  {
+    std::cerr << "ReverseDrift requires step_ns > 0" << std::endl;
+    return new TPolyLine3D(0);
+  }
   vector<double> xlist;

As per coding guidelines **/*.{cc,cpp,cxx,c}: “Prioritize correctness … and thread-safety.”

📝 Committable suggestion

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

Suggested change
TPolyLine3D *PHGarfield::ReverseDrift (double x, double y, double z, double step_ns)
{
vector<double> xlist;
vector<double> ylist;
vector<double> zlist;
xlist.push_back(x);
ylist.push_back(y);
zlist.push_back(z);
double ex, ey, ez, bx, by, bz, vx, vy, vz;
double zPrevious = z;
while (!StopHere(x,y,z,zPrevious))
{
zPrevious = z;
GetMagneticFieldTesla( x, y, z, bx, by, bz);
GetElectricFieldVcm ( x, y, z, ex, ey, ez);
m_gas->ElectronVelocity(ex, ey, ez, bx, by, bz, vx, vy, vz);
x = x - vx*step_ns;
y = y - vy*step_ns;
z = z - vz*step_ns;
xlist.push_back(x);
ylist.push_back(y);
zlist.push_back(z);
}
TPolyLine3D *PHGarfield::ReverseDrift (double x, double y, double z, double step_ns)
{
if (step_ns <= 0.0)
{
std::cerr << "ReverseDrift requires step_ns > 0" << std::endl;
return new TPolyLine3D(0);
}
vector<double> xlist;
vector<double> ylist;
vector<double> zlist;
xlist.push_back(x);
ylist.push_back(y);
zlist.push_back(z);
double ex, ey, ez, bx, by, bz, vx, vy, vz;
double zPrevious = z;
while (!StopHere(x,y,z,zPrevious))
{
zPrevious = z;
GetMagneticFieldTesla( x, y, z, bx, by, bz);
GetElectricFieldVcm ( x, y, z, ex, ey, ez);
m_gas->ElectronVelocity(ex, ey, ez, bx, by, bz, vx, vy, vz);
x = x - vx*step_ns;
y = y - vy*step_ns;
z = z - vz*step_ns;
xlist.push_back(x);
ylist.push_back(y);
zlist.push_back(z);
}

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate the header
ls -la offline/packages/PHGarfield/PHGarfield.h 2>/dev/null || true

# Show the relevant parts of the header (around destructor + members)
sed -n '1,120p' offline/packages/PHGarfield/PHGarfield.h | nl -ba

# Find InitRun implementation and inspect allocations
rg -n "InitRun\\s*\\(" -S . || true
rg -n "PHGarfield::InitRun" -S . || true

# If an implementation file exists, print it around the allocation sites.
# Best-effort: search for the member names in InitRun or around allocations.
rg -n "m_field|m_cdbTPCMAPttree|m_component|m_gas" offline/packages/PHGarfield -S || true

# Also check if there is any destructor / cleanup elsewhere for these members.
rg -n "~PHGarfield|Cleanup|Finalize|clear\\(|delete\\s+(m_field|m_cdbTPCMAPttree|m_component|m_gas)" -S offline/packages/PHGarfield || true

Repository: sPHENIX-Collaboration/coresoftware

Length of output: 229


🏁 Script executed:

#!/bin/bash
set -euo pipefail

H="offline/packages/PHGarfield/PHGarfield.h"
ls -la "$H" 2>/dev/null || true

echo "=== PHGarfield.h (first 220 lines) ==="
sed -n '1,220p' "$H" || true

echo "=== PHGarfield.h: members + destructor area ==="
rg -n "class\\s+PHGarfield|~PHGarfield|InitRun|m_field|m_cdbTPCMAPttree|m_component|m_gas" "$H" -n -S || true

echo "=== Find InitRun in PHGarfield package ==="
rg -n "InitRun\\s*\\(" -S offline/packages/PHGarfield || true
rg -n "PHGarfield::InitRun" -S offline/packages/PHGarfield || true

echo "=== Locate member cleanup / deletes in PHGarfield package ==="
rg -n "~PHGarfield|Cleanup|Finalize|clear\\(|delete\\s+(m_field|m_cdbTPCMAPttree|m_component|m_gas)" -S offline/packages/PHGarfield || true

echo "=== Show PHGarfield*.cc/.cpp/.cxx/.hxx for InitRun allocations context ==="
ls -la offline/packages/PHGarfield || true
fd -t f -ecc -ecc -e cpp -e cxx -e cc -e c -e h -e hxx -e hh offline/packages/PHGarfield -x echo >/dev/null 2>&1 || true
fd -t f offline/packages/PHGarfield -g '*PHGarfield*' || true

Repository: sPHENIX-Collaboration/coresoftware

Length of output: 4829


🏁 Script executed:

#!/bin/bash
set -euo pipefail

H="offline/packages/PHGarfield/PHGarfield.cc"
echo "=== PHGarfield.cc size (lines) ==="
wc -l "$H" || true

echo "=== PHGarfield.cc: include + member allocations context near InitRun ==="
sed -n '1,120p' "$H" || true

echo "=== PHGarfield.cc: InitRun body (line-focused) ==="
# Print a window around InitRun definition
LINE=$(rg -n "int PHGarfield::InitRun" "$H" | head -n1 | cut -d: -f1)
echo "InitRun line: $LINE"
START=$((LINE-10))
END=$((LINE+220))
sed -n "${START},${END}p" "$H" || true

echo "=== PHGarfield.cc: occurrences of member pointers ==="
rg -n "m_field|m_cdbTPCMAPttree|m_component|m_gas" "$H" -n || true

echo "=== PHGarfield.cc: delete/free calls ==="
rg -n "delete\\s+(m_field|m_cdbTPCMAPttree|m_component|m_gas)|delete\\s+.*m_field|delete\\s+.*m_cdbTPCMAPttree|delete\\s+.*m_component|delete\\s+.*m_gas|free\\(|Destroy|Finalize|Stop\\b|End\\b" "$H" -S || true

Repository: sPHENIX-Collaboration/coresoftware

Length of output: 12040


Fix ownership of PHGarfield raw pointers to prevent leaks (RAII)
PHGarfield::~PHGarfield() is defaulted inline, while PHGarfield::InitRun allocates m_field (new PHField3DCartesian), m_cdbTPCMAPttree (new CDBTTree), m_component (new Garfield::ComponentUser), and m_gas (new Garfield::MediumMagboltz) with no corresponding delete/cleanup in PHGarfield.cc, so memory leaks on teardown and any InitRun re-initialization path.
Switch these owning members to std::unique_ptr and make sure the destructor is defined out-of-line (or include complete type headers) so unique_ptr can safely delete the forward-declared types.

@sphenix-jenkins-ci

Copy link
Copy Markdown

Build & test report

Report for commit 708f7774f9da38341ea24861dfd4a552e9a52eb8:
Jenkins on fire


Automatically generated by sPHENIX Jenkins continuous integration
sPHENIX             jenkins.io

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
offline/packages/PHGarfield/PHGarfield.cc (1)

101-106: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Potential out-of-bounds write if CDB returns unexpected layer values.

radii is declared as double radii[48]{} in the header. The indexing radii[layer - 7] assumes 7 ≤ layer ≤ 54. If the CDB map ever contains a layer value ≥ 55 (e.g., due to data corruption or schema evolution), this writes past the array bounds, causing undefined behavior.

Consider adding a bounds check:

Suggested guard
          if (layer > 6)
          {
+           if (layer - 7 >= 48)
+           {
+             std::cerr << "PHGarfield::FillRadii: layer " << layer << " out of range" << std::endl;
+             continue;
+           }
            radii[layer - 7] = r;
          }

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 683aa11d-73c1-4311-ab2e-11b8830923c9

📥 Commits

Reviewing files that changed from the base of the PR and between b2b274d and 391555c.

📒 Files selected for processing (4)
  • offline/packages/PHGarfield/GasModel.cc
  • offline/packages/PHGarfield/MergeGasFiles.cc
  • offline/packages/PHGarfield/PHGarfield.cc
  • offline/packages/PHGarfield/PHGarfield.h
🚧 Files skipped from review as they are similar to previous changes (3)
  • offline/packages/PHGarfield/PHGarfield.h
  • offline/packages/PHGarfield/GasModel.cc
  • offline/packages/PHGarfield/MergeGasFiles.cc

@sphenix-jenkins-ci

Copy link
Copy Markdown

Build & test report

Report for commit b2b274d3bc53a742b1dadea98191702448aeb200:
Jenkins on fire


Automatically generated by sPHENIX Jenkins continuous integration
sPHENIX             jenkins.io

@sphenix-jenkins-ci

Copy link
Copy Markdown

Build & test report

Report for commit 391555cfaf7c57ff55bb2425370a5e43ad072f9b:
Jenkins passed


Automatically generated by sPHENIX Jenkins continuous integration
sPHENIX             jenkins.io

@sphenix-jenkins-ci

Copy link
Copy Markdown

Build & test report

Report for commit 3f7025659ac13cb1162e67635483be3a2af3e0e5:
Jenkins passed


Automatically generated by sPHENIX Jenkins continuous integration
sPHENIX             jenkins.io

@osbornjd osbornjd merged commit 42bdd11 into sPHENIX-Collaboration:master Jun 9, 2026
21 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants