Enable externally-filled surface hits for Simphony optical photon transport - #97
Open
Ningclover wants to merge 3 commits into
Open
Enable externally-filled surface hits for Simphony optical photon transport#97Ningclover wants to merge 3 commits into
Ningclover wants to merge 3 commits into
Conversation
- Use CreateAttValues() instead of deprecated GetAttValues() in PersistencyManager - Null-check theStackingAction before calling SetKillOpticalPhotons in SurfaceSD - Move external actions call before early-return in UserEventAction so GPU optical plugins always run per event Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- HitSurface: add a value constructor for photon transport that is offloaded from Geant4 (e.g. GPU tracking), where no G4Step exists to copy the hit information from. Pure initializer list; no change for existing callers or the persistent TG4PhotonHit/ROOT I/O layer. - PersistencyManager: null-guard the hit collections in SummarizePhotonDetectors and SummarizeSegmentDetectors. The G4HCtable lists every registered collection, but GetHC() returns null for a slot not filled in a given event - possible for sensitive detectors that are not attached to a volume (their Initialize() is never called). The old code dereferenced unconditionally and segfaulted. Together these let an external plugin convert offloaded photon hits into a HitSurface collection that lands in TG4Event.PhotonDetectors under its own sensitive-detector name, with any persistency backend. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
ClarkMcGrew
reviewed
Aug 4, 2026
| void EDepSim::UserEventAction::EndOfEventAction(const G4Event* theEvent) { | ||
| EDepSimInfo("Event " << theEvent->GetEventID() << " completed."); | ||
|
|
||
| // Run external actions unconditionally first, before the early-return |
Owner
There was a problem hiding this comment.
Moving this code earlier means that the EDepSim::Trajectory will not be completely filled when the G4UserEventAction is called. I wonder if this means that there should be two call backs (e.g. the current EndOfEventAction() that doesn't modify the trajectories, and a new "PreEndOfEventAction()" that can add stuff).
Owner
There was a problem hiding this comment.
Actually, a better solution might be to leave the original call at the end, and move this into the "if (!HCofEvent)".
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
edep-sim already provides the framework for surface sensitive detectors,
EDepSim::HitSurface, photon-detector summarisation, and thefExternalActionshook on the user event action. This PR makes thatframework usable from an external plugin that transports optical photons
outside Geant4 (e.g. on a GPU) and fills the resulting hits back into the
event.
The changes are deliberately minimal and additive — no existing behaviour
changes for a normal CPU-only run.
Changes
EDepSimHitSurface.{hh,cc}— new value-based constructor.Adds
HitSurface(primaryId, energyDeposit, position, start, pdgEncoding, creatorType, creatorSubtype). Photons transported outside Geant4 have noG4Step, so the existingG4Step-based constructor can't be used torecord their hits. The original constructor is untouched.
EDepSimUserEventAction.cc— run external actions before the earlyreturn. The
fExternalActionsloop is moved to the top ofEndOfEventAction, ahead of the ionization-hit handling that can returnearly. An external optical plugin must run on every event, including
events with no ionization hits in any sensitive detector.
EDepSimSurfaceSD.cc— null-guard the stacking action. When photontransport is offloaded the user stacking action may not be installed;
SetKillOpticalPhotonsis now only called when it is present, avoiding anull dereference.
EDepSimPersistencyManager.cc— null-guard hit collections. InSummarizePhotonDetectorsandSummarizeSegmentDetectors, guard against anull
G4VHitsCollection(which can occur when collections are filledexternally) before calling
GetSize().EDepSimPersistencyManager.cc— useCreateAttValues()in thetrajectory-point debug print.
GetAttValues()can return null in thispath;
CreateAttValues()is the safe accessor. This only affects anerror-logging branch. (Minor correctness fix noticed while working here —
happy to split it out if preferred.)
Testing
Built against Clark's
masterand exercised with an external GPU opticalplugin (eic-opticks / simphony). CPU-only runs are unaffected. Branch merges
cleanly into
master.