Motivation
The quantum efficiency (QE) curves for the DRICH SiPM and PFRICH HRPPD photocathode sensors are currently hardcoded as explicit lambda/efficiency tables in npsim.py. These are physical properties of the sensors and belong in the epic geometry repository alongside the rest of the detector description.
Key finding
optical_materials.xml in epic already defines SensorSurface_DRICH with a placeholder flat efficiency:
<opticalsurface name="SensorSurface_DRICH" model="glisur" finish="polished" type="dielectric_dielectric">
<property name="EFFICIENCY" coldim="2" values="
1*eV 1
7*eV 1
"/>
</opticalsurface>
This surface is already applied as a SkinSurface to each pss volume in DRICH_geo.cpp. The infrastructure is in place — we just need to replace the placeholder with real data.
Proposed design
Part 1 — epic (compact/optical_materials.xml)
- Replace the flat
EFFICIENCY = 1.0 on SensorSurface_DRICH with real SiPM (S13361-3050NE-08) QE values, converting λ[nm] → E[eV] via E = 1239.84 / λ.
- Add a new
SensorSurface_PFRICH with HRPPD photocathode QE values.
- Reference
SensorSurface_PFRICH from compact/pid/pfrich.xml on the photocathode element.
Part 2 — npsim stacking action (OpticalPhotonEfficiencyStackingAction.h)
- Add a
SensorSurface property (a surface name string).
- In
initialize(), if SensorSurface is set, look up the named optical surface, read its EFFICIENCY from the G4MaterialPropertiesTable, convert photon energy back to wavelength, and populate the existing interpolation table (m_interp_lambda_values / m_efficiency).
- Keep
LambdaValues + Efficiency as explicit fallback for backward compatibility.
Priority in initialize():
SensorSurface set → read QE from G4 optical surface MPT
LambdaValues + Efficiency set → use explicit tables (current behaviour)
LambdaMin/LambdaMax + Efficiency → linspace fallback (legacy hpDIRC path)
Part 3 — npsim.py
Replace hardcoded lambda/efficiency tables:
# Before (hardcoded in npsim):
{
"name": "OpticalPhotonEfficiencyStackingAction",
"parameter": {
"LambdaValues": [315e-6, 325e-6, ...], # 17 values
"Efficiency": [0.00, 0.04, ...], # 17 values
"LogicalVolume": "DRICH_(gas|aerogel)",
}
},
# After (QE lives in epic):
{
"name": "OpticalPhotonEfficiencyStackingAction",
"parameter": {
"SensorSurface": "SensorSurface_DRICH",
"LogicalVolume": "DRICH_(gas|aerogel)",
}
},
Separation of concerns
| Repository |
Responsibility |
| epic |
Sensor QE physics (what wavelengths does this photocathode detect?) |
| npsim |
Simulation topology (which radiator volumes feed which sensor surface?) |
npsim.py retains only the LogicalVolume regex — a simulation choice about where to kill photons early. The QE numbers themselves are geometry data.
Scope
- DRICH (SiPM) and PFRICH (HRPPD) are the primary targets.
- hpDIRC can be migrated in a follow-up once epic defines a
SensorSurface_DIRC with the barPMT QE.
- The
LambdaValues/Efficiency fallback must be retained until all detectors have migrated.
Motivation
The quantum efficiency (QE) curves for the DRICH SiPM and PFRICH HRPPD photocathode sensors are currently hardcoded as explicit lambda/efficiency tables in
npsim.py. These are physical properties of the sensors and belong in the epic geometry repository alongside the rest of the detector description.Key finding
optical_materials.xmlin epic already definesSensorSurface_DRICHwith a placeholder flat efficiency:This surface is already applied as a
SkinSurfaceto each pss volume inDRICH_geo.cpp. The infrastructure is in place — we just need to replace the placeholder with real data.Proposed design
Part 1 — epic (
compact/optical_materials.xml)EFFICIENCY = 1.0onSensorSurface_DRICHwith real SiPM (S13361-3050NE-08) QE values, converting λ[nm] → E[eV] viaE = 1239.84 / λ.SensorSurface_PFRICHwith HRPPD photocathode QE values.SensorSurface_PFRICHfromcompact/pid/pfrich.xmlon the photocathode element.Part 2 — npsim stacking action (
OpticalPhotonEfficiencyStackingAction.h)SensorSurfaceproperty (a surface name string).initialize(), ifSensorSurfaceis set, look up the named optical surface, read itsEFFICIENCYfrom theG4MaterialPropertiesTable, convert photon energy back to wavelength, and populate the existing interpolation table (m_interp_lambda_values/m_efficiency).LambdaValues+Efficiencyas explicit fallback for backward compatibility.Priority in
initialize():SensorSurfaceset → read QE from G4 optical surface MPTLambdaValues+Efficiencyset → use explicit tables (current behaviour)LambdaMin/LambdaMax+Efficiency→ linspace fallback (legacy hpDIRC path)Part 3 — npsim.py
Replace hardcoded lambda/efficiency tables:
Separation of concerns
npsim.pyretains only theLogicalVolumeregex — a simulation choice about where to kill photons early. The QE numbers themselves are geometry data.Scope
SensorSurface_DIRCwith the barPMT QE.LambdaValues/Efficiencyfallback must be retained until all detectors have migrated.