Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
f00a1b6
Enable DRICH generation-stage QE in npsim
Copilot May 17, 2026
d7fbedc
Address PR feedback on QE interpolation and volume matching
Copilot May 17, 2026
f795cf6
Require LambdaValues in dd4hep units
Copilot May 17, 2026
8eadf60
Normalize RICH efficiency tables to fractions
Copilot May 17, 2026
3134a1e
Use std::lerp in stacking interpolation
Copilot May 17, 2026
2ed77b2
Remove redundant zero-efficiency branch
Copilot May 17, 2026
99c9935
Kill photons outside QE range and promote suppression summary to WARNING
wdconinc May 17, 2026
60136b5
Apply QE stacking action to Cherenkov radiator volumes, not sensor vo…
wdconinc May 17, 2026
68039cf
Print percentage of suppressed photons in stacking action summary
wdconinc May 17, 2026
cd0d00a
fix: import DDG4 and use g4units for nm definition
wdconinc May 17, 2026
6379d10
fix: from g4units import mm not keV
wdconinc May 17, 2026
7c39c33
feat: add performance profiler as stepping action
wdconinc Jun 24, 2025
c4e5af7
feat: fill xy and zr histograms weighted with time
wdconinc Jun 24, 2025
1c923f5
feat: fill better xy and rz histograms
wdconinc Jun 25, 2025
2b846c0
feat: add per-PDG histograms and timestamp-named output file
May 20, 2026
4651d8c
fix: sync m_zr histogram range with npsim reference
May 20, 2026
3e49588
feat: add per-track overhead profiling and analysis scripts
May 21, 2026
00486ea
Potential fix for pull request finding 'CodeQL / Use of potentially d…
rahmans1 May 21, 2026
8467af8
Potential fix for pull request finding 'CodeQL / Use of potentially d…
rahmans1 May 21, 2026
f46b799
Potential fix for pull request finding 'Unused import'
rahmans1 May 21, 2026
6b67f4d
Potential fix for pull request finding 'Unused local variable'
rahmans1 May 21, 2026
0c316b6
feat: add per-PDG begin/end overhead instrumentation
May 21, 2026
d962357
feat: split heatmap into central/far-forward zones with ZDC separation
May 22, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 81 additions & 0 deletions scripts/plot_overhead_pdg.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
"""
Per-track overhead distribution overlay by particle species.
Usage: python3 plot_overhead_pdg.py <histos_overhead.root> [output.png]
"""
import sys
import uproot
import numpy as np
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt

RFILE = sys.argv[1] if len(sys.argv) > 1 else '/tmp/latest_histos_overhead.root'
OUTFILE = sys.argv[2] if len(sys.argv) > 2 else '/tmp/overhead_pdg.png'

species = [
('m_overhead_dist_pdg11', 'e⁻', '#1f77b4'),
('m_overhead_dist_pdg22', 'γ', '#ff7f0e'),
('m_overhead_dist_pdg-22', 'opt-γ', '#d62728'),
('m_overhead_dist_pdg-11', 'e⁺', '#9467bd'),
('m_overhead_dist_pdg2112', 'n', '#2ca02c'),
('m_overhead_dist_pdg2212', 'p', '#8c564b'),
('m_overhead_dist_pdg211', 'π⁺', '#e377c2'),
('m_overhead_dist_pdg-211', 'π⁻', '#bcbd22'),
]

XMIN, XMAX, SMOOTH = 2.0, 100.0, 7

fig, axes = plt.subplots(1, 2, figsize=(13, 5))
fig.patch.set_facecolor('white')

with uproot.open(RFILE) as f:
for hname, label, color in species:
if hname not in f:
continue
h = f[hname]
vals, edges = h.to_numpy()
centers = (edges[:-1] + edges[1:]) / 2
mask = (centers >= XMIN) & (centers <= XMAX)
x = centers[mask]
y = vals[mask].astype(float)
total = y.sum()
if total == 0:
continue
y_norm = y / total
y_smooth = np.convolve(y_norm, np.ones(SMOOTH) / SMOOTH, mode='same')
n_tracks = int(vals.sum())
mean_us = (centers * vals).sum() / vals.sum() if vals.sum() > 0 else 0
full_label = f'{label} ({n_tracks/1e6:.1f}M, mean={mean_us:.0f}µs)'
for ax in axes:
ax.plot(x, y_smooth, label=full_label, color=color, linewidth=1.8)

axes[0].set_xlim(XMIN, 40)
axes[0].set_ylim(bottom=0)
axes[0].set_xlabel('per-track overhead [µs]', fontsize=11)
axes[0].set_ylabel('fraction of tracks (normalized)', fontsize=10)
axes[0].set_title('Linear scale', fontsize=11)
axes[0].legend(fontsize=8, framealpha=0.95)
axes[0].grid(True, color='#dddddd', linewidth=0.5)

axes[1].set_yscale('log')
axes[1].set_xlim(XMIN, XMAX)
axes[1].set_ylim(1e-6, 0.2)
axes[1].set_xlabel('per-track overhead [µs]', fontsize=11)
axes[1].set_ylabel('fraction of tracks (normalized)', fontsize=10)
axes[1].set_title('Log scale', fontsize=11)
axes[1].legend(fontsize=8, framealpha=0.95)
axes[1].grid(True, color='#dddddd', linewidth=0.5, which='both')

for ax in axes:
ax.set_facecolor('white')
for sp in ax.spines.values():
sp.set_edgecolor('#aaaaaa')

fig.suptitle(
'Per-track overhead by species (normalized, smoothed, <2µs excluded)\n'
f'{RFILE}',
fontsize=10, y=1.01
)
plt.tight_layout()
plt.savefig(OUTFILE, dpi=150, bbox_inches='tight', facecolor='white')
print(f'saved {OUTFILE}')
63 changes: 63 additions & 0 deletions scripts/plot_overhead_spatial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
"""
Per-track overhead spatial heatmaps (xy and zr).
Usage: python3 plot_overhead_spatial.py <histos_overhead.root> [output.png]
"""
import sys
import uproot
import numpy as np
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
from matplotlib.colors import LogNorm

RFILE = sys.argv[1] if len(sys.argv) > 1 else '/tmp/latest_histos_overhead.root'
OUTFILE = sys.argv[2] if len(sys.argv) > 2 else '/tmp/overhead_spatial.png'

with uproot.open(RFILE) as f:
hxy = f['m_overhead_xy']
xy_vals, xy_xe, xy_ye = hxy.to_numpy()
hzr = f['m_overhead_zr']
zr_vals, zr_xe, zr_ye = hzr.to_numpy()

# mm -> cm
xy_xe /= 10; xy_ye /= 10
zr_xe /= 10; zr_ye /= 10

# zoom zr: z in [-500, 500] cm, r in [0, 200] cm
zmask = (zr_xe >= -500) & (zr_xe <= 500)
rmask = (zr_ye >= 0) & (zr_ye <= 200)
zi = np.where(zmask)[0]
ri = np.where(rmask)[0]
zr_zoom = zr_vals[zi[0]:zi[-1], ri[0]:ri[-1]]
zr_xe_z = zr_xe[zi[0]:zi[-1]+1]
zr_ye_z = zr_ye[ri[0]:ri[-1]+1]

fig, axes = plt.subplots(1, 2, figsize=(15, 6))
fig.patch.set_facecolor('white')

def heatmap(ax, xe, ye, vals, xlabel, ylabel, title):
vp = np.where(vals > 0, vals, np.nan)
vmin = np.nanpercentile(vp, 20)
vmax = np.nanpercentile(vp, 99.5)
im = ax.pcolormesh(xe, ye, vp.T, norm=LogNorm(vmin=vmin, vmax=vmax), cmap='plasma')
cb = plt.colorbar(im, ax=ax)
cb.set_label('overhead [ns·tracks]', fontsize=10)
ax.set_xlabel(xlabel, fontsize=11)
ax.set_ylabel(ylabel, fontsize=11)
ax.set_title(title, fontsize=12)
ax.set_facecolor('#f0f0f0')
for sp in ax.spines.values():
sp.set_edgecolor('#999999')

heatmap(axes[0], xy_xe, xy_ye, xy_vals, 'x [cm]', 'y [cm]', 'Overhead map — xy')
axes[0].set_aspect('equal')
heatmap(axes[1], zr_xe_z, zr_ye_z, zr_zoom, 'z [cm]', 'r [cm]', 'Overhead map — zr (|z|<500cm, r<200cm)')

fig.suptitle(
'Per-track overhead spatial map (track start position weighted by overhead)\n'
f'{RFILE}',
fontsize=10, y=1.01
)
plt.tight_layout()
plt.savefig(OUTFILE, dpi=150, bbox_inches='tight', facecolor='white')
print(f'saved {OUTFILE}')
Loading