Skip to content

feat: apply dRICH and pfRICH quantum efficiency at photon generation (stacking) stage#48

Open
Copilot wants to merge 11 commits into
mainfrom
copilot/enable-drichen-quantum-efficiency
Open

feat: apply dRICH and pfRICH quantum efficiency at photon generation (stacking) stage#48
Copilot wants to merge 11 commits into
mainfrom
copilot/enable-drichen-quantum-efficiency

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented May 17, 2026

dRICH QE was only applied in downstream digitization, forcing simulation of many photons that are later discarded. This PR moves dRICH QE suppression into npsim generation-time optical stacking, consistent with the existing hpDIRC pattern.

  • Generation-stage dRICH QE in npsim.py

    • Added dRICH QE table (wavelength/efficiency) to simulation steering.
    • Configured OpticalPhotonEfficiencyStackingAction for dRICH photosensitive logical volumes (DRICH_pss_sec0..5), so optical photons are filtered before full tracking/digitization.
    • Kept existing hpDIRC stacking configuration in place.
  • Stacking action support for non-uniform QE tables

    • Extended OpticalPhotonEfficiencyStackingAction with optional Wavelengths property.
    • Added interpolation on explicit wavelength grids (Wavelengths + Efficiency) while preserving legacy uniform-grid behavior (LambdaMin/LambdaMax + Efficiency).
  • Behavioral intent

    • dRICH QE is now applied at generation stage in npsim using the same QE values previously used in reconstruction digitization, reducing wasted optical-photon transport.
# npsim.py (new dRICH stack entries)
{
  "name": "OpticalPhotonEfficiencyStackingAction",
  "parameter": {
    "LambdaMin": "315*nm",
    "LambdaMax": "1000*nm",
    "Wavelengths": [315, 325, 340, ..., 1000],
    "LogicalVolume": "DRICH_pss_sec0",  # repeated for sec0..sec5
    "Efficiency": [0.00, 0.04, 0.10, ..., 0.00],
  }
}

Copilot AI linked an issue May 17, 2026 that may be closed by this pull request
Copilot AI changed the title [WIP] Enable DRICH quantum efficiency at generation stage Apply dRICH quantum efficiency at photon generation (stacking) stage May 17, 2026
Copilot AI requested a review from wdconinc May 17, 2026 15:07
Comment thread src/plugins/include/npdet/OpticalPhotonEfficiencyStackingAction.h Outdated
Comment thread src/dd4pod/python/npsim.py Outdated
Comment thread src/dd4pod/python/npsim.py Outdated
Copilot AI changed the title Apply dRICH quantum efficiency at photon generation (stacking) stage Apply dRICH and pfRICH quantum efficiency at photon generation (stacking) stage May 17, 2026
Copilot AI requested a review from wdconinc May 17, 2026 15:32
@wdconinc wdconinc marked this pull request as ready for review May 17, 2026 15:49
Copilot AI review requested due to automatic review settings May 17, 2026 15:49
Copy link
Copy Markdown
Contributor

Copilot AI left a 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 PR moves dRICH and pfRICH quantum-efficiency (QE) photon suppression from downstream digitization into the npsim generation/stacking stage, so unproductive optical photons are killed early. It also generalizes OpticalPhotonEfficiencyStackingAction to accept a non-uniform lambda grid (LambdaValues) and to match logical volumes by regex (needed because dRICH/pfRICH photocathode logical volumes are numbered, e.g. DRICH_pss_sec0..N and PFRICH-photocathode-00..NN).

Changes:

  • Generalize OpticalPhotonEfficiencyStackingAction to support LambdaValues (non-uniform grid), regex LogicalVolume matching, and a unified interpolation path via std::call_once initialization.
  • Add dRICH and pfRICH QE stacking-action entries to npsim.py, retaining the existing hpDIRC entry.
  • Use std::regex_match against compiled regex for per-photon volume filtering.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
src/plugins/include/npdet/OpticalPhotonEfficiencyStackingAction.h Adds LambdaValues property, regex volume matching, unified interpolation, lazy initialization.
src/dd4pod/python/npsim.py Registers generation-stage QE stacking actions for dRICH and pfRICH photocathodes.
Comments suppressed due to low confidence (1)

src/plugins/include/npdet/OpticalPhotonEfficiencyStackingAction.h:136

  • Behavior regression for the single-element Efficiency case when only LambdaValues (and not LambdaMin/LambdaMax) is provided. In initialize(), m_interp_lambda_values is only populated when m_efficiency.size() > 1 or m_lambda_values.size() > 1. With Efficiency=[x] and a single LambdaValues=[y], m_interp_lambda_values stays empty, so the range check at lines 78-80 falls back to m_lambda_min/m_lambda_max (defaults of 0), and no photon ever passes the range test. The previous code supported "single constant value over [LambdaMin, LambdaMax] range"; the new code only supports that case when LambdaMin/LambdaMax are also provided. Consider populating m_interp_lambda_values (or otherwise tracking the effective lambda range) for the single-efficiency case as well, or document the constraint.
        if (m_efficiency.size() > 1) {
          if (m_lambda_values.size() == m_efficiency.size()) {
            m_interp_lambda_values = m_lambda_values;
          } else {
            auto lambda_min_nm = m_lambda_min / CLHEP::nm;
            auto lambda_max_nm = m_lambda_max / CLHEP::nm;
            m_interp_lambda_values.reserve(m_efficiency.size());
            auto lambda_step = (lambda_max_nm - lambda_min_nm) / (m_efficiency.size() - 1);
            for (std::size_t i = 0; i < m_efficiency.size(); ++i) {
              m_interp_lambda_values.push_back(lambda_min_nm + i * lambda_step);
            }
          }
        } else if (m_lambda_values.size() > 1) {
          m_interp_lambda_values = m_lambda_values;
        }

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/plugins/include/npdet/OpticalPhotonEfficiencyStackingAction.h
Comment thread src/plugins/include/npdet/OpticalPhotonEfficiencyStackingAction.h Outdated
Comment thread src/dd4pod/python/npsim.py Outdated
Comment thread src/dd4pod/python/npsim.py Outdated
Comment thread src/dd4pod/python/npsim.py Outdated
Comment thread src/plugins/include/npdet/OpticalPhotonEfficiencyStackingAction.h Outdated
Agent-Logs-Url: https://github.com/eic/npsim/sessions/f21a9097-2f8b-4486-92e3-771e522e8a8f

Co-authored-by: wdconinc <4656391+wdconinc@users.noreply.github.com>
Copilot AI and others added 5 commits May 17, 2026 12:20
Agent-Logs-Url: https://github.com/eic/npsim/sessions/1a0bce3d-a9bd-4818-9cc7-9f6d4ea19785

Co-authored-by: wdconinc <4656391+wdconinc@users.noreply.github.com>
Agent-Logs-Url: https://github.com/eic/npsim/sessions/ba4e2433-66ae-4dbf-8578-1179788a6269

Co-authored-by: wdconinc <4656391+wdconinc@users.noreply.github.com>
Agent-Logs-Url: https://github.com/eic/npsim/sessions/45003b90-638f-41c1-82a2-67a63baea600

Co-authored-by: wdconinc <4656391+wdconinc@users.noreply.github.com>
Agent-Logs-Url: https://github.com/eic/npsim/sessions/cadf4be9-5ff6-4152-b088-8895b02fa8a8

Co-authored-by: wdconinc <4656391+wdconinc@users.noreply.github.com>
@wdconinc wdconinc force-pushed the copilot/enable-drichen-quantum-efficiency branch from 0bb9f1c to 2ed77b2 Compare May 17, 2026 17:20
@wdconinc wdconinc changed the title Apply dRICH and pfRICH quantum efficiency at photon generation (stacking) stage feat: apply dRICH and pfRICH quantum efficiency at photon generation (stacking) stage May 17, 2026
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 17, 2026

- Photons outside the specified lambda range now get killed (efficiency=0
  outside the QE table boundaries) instead of being kept. This is
  physically correct: a photocathode with 0% QE at its wavelength
  boundaries has 0% QE outside that range too. Previously, UV Cherenkov
  photons (below 315 nm) were passing unfiltered, dramatically reducing
  the expected hit count reduction.

- Change the destructor summary printout from DEBUG to WARNING so the
  'Suppressed N of M photons in lv ...' message appears in CI runs
  (which use -v WARNING). This provides in-CI verification that the
  stacking action is active and killing photons at the expected rate.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
wdconinc and others added 2 commits May 17, 2026 16:30
…lumes

The stacking action should filter photons when they are created in the
radiator volumes, not when they arrive at the sensor surface. This is
the correct place to apply generation-stage QE: the photon wavelength
is set at creation, and any photon that would not pass the sensor QE
can be killed immediately, saving simulation time.

DRICH radiator volumes (both gas ring Cherenkov and proximity-focus
aerogel): DRICH_gas and DRICH_aerogel -> regex DRICH_(gas|aerogel)

PFRICH radiator volumes (gas volume and individual aerogel tiles):
PFRICH_GasVol and PFRICH-aerogel-{ir}-{ia} -> regex
PFRICH(_GasVol|-aerogel-[0-9]+-[0-9]+)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@wdconinc
Copy link
Copy Markdown
Contributor

OpticalPhotonEfficiencyStackingAction WARN  Suppressed 347927 of 396322 photons (87.8%) in lv DRICH_(gas|aerogel)
OpticalPhotonEfficiencyStackingAction WARN  Suppressed 62128 of 68891 photons (90.2%) in lv PFRICH(_GasVol|-aerogel-[0-9]+-[0-9]+)
OpticalPhotonEfficiencyStackingAction WARN  Suppressed 420093 of 539330 photons (77.9%) in lv bar_vol

Comment thread src/dd4pod/python/npsim.py Fixed
Comment thread src/dd4pod/python/npsim.py Fixed
Updated import statements for consistency and clarity.
@wdconinc
Copy link
Copy Markdown
Contributor

FYI @chchatte92 This reduces the number of optical photons we need to handle in simulation, speeding up the simulations. Of course, we then cannot again apply QE in the digitization in EICrecon.

https://eic.github.io/npsim/pr/48/capybara/sim_dis_18x275_minQ2=1000_epic_craterlake/index.html#DRICHHits

@wdconinc wdconinc requested a review from a team May 17, 2026 22:23
@chchatte92
Copy link
Copy Markdown
Member

FYI @chchatte92 This reduces the number of optical photons we need to handle in simulation, speeding up the simulations. Of course, we then cannot again apply QE in the digitization in EICrecon.

https://eic.github.io/npsim/pr/48/capybara/sim_dis_18x275_minQ2=1000_epic_craterlake/index.html#DRICHHits

Hi Wouter, so whenever we change the QE in future for our testing purpose, we change directly in here?

Chandra

@wdconinc
Copy link
Copy Markdown
Contributor

FYI @chchatte92 This reduces the number of optical photons we need to handle in simulation, speeding up the simulations. Of course, we then cannot again apply QE in the digitization in EICrecon.
https://eic.github.io/npsim/pr/48/capybara/sim_dis_18x275_minQ2=1000_epic_craterlake/index.html#DRICHHits

Hi Wouter, so whenever we change the QE in future for our testing purpose, we change directly in here?

You can do either. It's the product that matters. If you want to study the impact of the quantum efficiency, then you'll probably want to run 1 simulation, and then apply QE in EICrecon for multiple assumptions of QE. But for production campaigns it makes more sense to apply the QE here in npsim, so that should be the one that should be correct.

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.

Enable DRICH quantum efficiency at generation stage

4 participants