Skip to content
Merged
Show file tree
Hide file tree
Changes from 34 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
38123c8
Add CMakeLists.txt for ddeicopticks plugin
ggalgoczi Mar 5, 2026
7ad57c3
Add OpticsEvent.cc
ggalgoczi Mar 5, 2026
10c7a1f
Remove license header from OpticsEvent.hh
ggalgoczi Mar 5, 2026
2c54e77
Clean up OpticsRun.cc by removing comments and header
ggalgoczi Mar 5, 2026
2bca8fb
Add OpticsRun class for eic-opticks run lifecycle
ggalgoczi Mar 5, 2026
e8e95f2
Add OpticsSteppingAction implementation
ggalgoczi Mar 5, 2026
620924b
Remove license header from OpticsSteppingAction.hh
ggalgoczi Mar 5, 2026
732496e
Move to physics genstep collection from stepping in CMakeLists.txt
ggalgoczi Mar 6, 2026
ca9dd60
Create OpticsPhysics.cc
ggalgoczi Mar 6, 2026
38d2764
Create OpticsPhysics.hh
ggalgoczi Mar 6, 2026
d78307e
Delete dd4hepplugins/OpticsSteppingAction.cc
ggalgoczi Mar 6, 2026
cfc869b
Delete dd4hepplugins/OpticsSteppingAction.hh
ggalgoczi Mar 6, 2026
d4fde26
hit injection into DD4hep collections
ggalgoczi Mar 8, 2026
c4a6751
hit injection OpticsEvent.hh
ggalgoczi Mar 8, 2026
5d36375
Create test_raindrop_dd4hep.py
ggalgoczi Mar 8, 2026
c084196
Create raindrop_dd4hep.xml
ggalgoczi Mar 8, 2026
cfb55ef
Create test_raindrop_cpu.py
ggalgoczi Mar 8, 2026
1350cd2
Merge branch 'main' (early part) into dd4hep_integration
ggalgoczi Apr 2, 2026
fba67e0
Add raindrop detector geometry implementation
ggalgoczi Apr 2, 2026
7717636
Create CMakeLists.txt for DD4hep example
ggalgoczi Apr 2, 2026
09f0701
build: integrate dd4hepplugins into top-level cmake as optional subdi…
ggalgoczi Apr 2, 2026
df563cc
fix(u4): remove PMT name requirement from sensor identification
ggalgoczi Apr 2, 2026
da2d0b4
fix(examples): remove hardcoded spack paths from dd4hep test scripts
ggalgoczi Apr 2, 2026
72fb922
build(examples): wire dd4hep raindrop plugin into top-level cmake
ggalgoczi Apr 2, 2026
4ee7da3
raindrop: move sensitive detector to lead, remove scintillation
ggalgoczi Apr 3, 2026
288a570
fix(dd4hep): enable GPU optical photon simulation via DDG4 plugins
ggalgoczi Apr 3, 2026
180f748
add GPU vs CPU optical photon benchmark script
ggalgoczi Apr 3, 2026
7b27080
rename test scripts to test_raindrop_dd4hep_{cpu,gpu}.py
ggalgoczi Apr 3, 2026
65bfcee
add photon batching to OpticsEvent for improved GPU throughput
ggalgoczi Apr 3, 2026
664b313
add thread safety and enable scintillation in OpticsSteppingAction
ggalgoczi Apr 3, 2026
8da8410
Merge branch 'main' into dd4hep_integration
plexoos Apr 3, 2026
0b7595e
move examples/dd4hep to dd4hepplugins/examples
ggalgoczi Apr 3, 2026
71d7f41
fix CMakeLists.txt path after examples move to dd4hepplugins
ggalgoczi Apr 3, 2026
8c53d91
address Copilot and Codex PR review feedback
ggalgoczi Apr 3, 2026
399228b
Remove EPIC calibrations/fieldmaps symlinks from repo
ggalgoczi Apr 5, 2026
6af15f6
Remove stray run.npy and run_meta.txt from repo
ggalgoczi Apr 5, 2026
277765c
revert sensor ID fix, moved to separate PR (fix-sensor-id branch)
ggalgoczi Apr 6, 2026
585d0da
Merge branch 'main' into dd4hep_integration
plexoos Apr 7, 2026
afff87a
chore(gitignore): stop ignoring ALL .npy files
plexoos Apr 7, 2026
d88a4b5
style: clang-format DD4hep integration files for dd4hep_integration m…
Copilot Apr 7, 2026
a81f9fe
Merge remote-tracking branch 'origin/main' into dd4hep_integration
plexoos Apr 7, 2026
8f76af5
style: apply clang-format Microsoft style to dd4hepplugins files
plexoos Apr 7, 2026
d5b8b6e
fix: add cudaDeviceSynchronize after GPU simulate for accurate timing
ggalgoczi Apr 7, 2026
656e529
add dRICH GPU vs CPU validation steering script
ggalgoczi Apr 9, 2026
3ec3797
Merge branch 'main' into dd4hep_integration
plexoos Apr 11, 2026
c5a3bc7
fix: use pmtid() instead of identity for hit cellID
ggalgoczi Apr 11, 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
10 changes: 10 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,16 @@ add_subdirectory(g4cx)
add_subdirectory(g4cx/tests)
add_subdirectory(src)

# Optional DD4hep integration plugins
find_package(DD4hep QUIET COMPONENTS DDG4 DDCore)
if(DD4hep_FOUND)
message(STATUS "DD4hep found -- building dd4hepplugins")
add_subdirectory(dd4hepplugins)
add_subdirectory(dd4hepplugins/examples)
else()
message(STATUS "DD4hep not found -- skipping dd4hepplugins")
endif()

# Export configs
include(CMakePackageConfigHelpers)

Expand Down
63 changes: 63 additions & 0 deletions dd4hepplugins/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#------------------------------- -*- cmake -*- -------------------------------#
# eic-opticks DD4hep integration plugins
#
# Builds DD4hep action plugins that integrate eic-opticks GPU-accelerated
# optical photon simulation into DD4hep/Geant4.
#
# Works both as part of the top-level eic-opticks build (in-tree) and as a
# standalone project against an installed eic-opticks.
#
# Usage from a DD4hep steering file:
# OpticsRun -- initializes/finalizes G4CXOpticks per run
# OpticsEvent -- triggers GPU simulation per event
#----------------------------------------------------------------------------#

# Detect standalone vs in-tree build
if(NOT TARGET G4CX)
cmake_minimum_required(VERSION 3.18 FATAL_ERROR)
project(ddeicopticks VERSION 0.1.0 LANGUAGES CXX)
find_package(DD4hep REQUIRED COMPONENTS DDG4 DDCore)
find_package(eic-opticks REQUIRED)
find_package(Geant4 REQUIRED)
set(_g4cx eic-opticks::G4CX)
set(_u4 eic-opticks::U4)
set(_sysrap eic-opticks::SysRap)
else()
# In-tree: DD4hep already found by parent, targets use local names
find_package(Geant4 REQUIRED)
set(_g4cx G4CX)
set(_u4 U4)
set(_sysrap SysRap)
endif()

dd4hep_set_compiler_flags()

set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
set(LIBRARY_OUTPUT_PATH "${CMAKE_CURRENT_BINARY_DIR}")

dd4hep_add_plugin(ddeicopticks
SOURCES
OpticsRun.cc
OpticsEvent.cc
OpticsSteppingAction.cc
USES
DD4hep::DDG4
DD4hep::DDCore
${_g4cx}
${_u4}
${_sysrap}
)
# STANDALONE changes class export macros in eic-opticks headers;
# only needed when building outside the main eic-opticks tree.
if(NOT TARGET G4CX)
target_compile_definitions(ddeicopticks PRIVATE STANDALONE)
endif()

install(TARGETS ddeicopticks
LIBRARY DESTINATION lib
)

install(FILES
${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_SHARED_MODULE_PREFIX}ddeicopticks.components
DESTINATION lib
)
91 changes: 91 additions & 0 deletions dd4hepplugins/DD4hepSensorIdentifier.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
#pragma once
/**
DD4hepSensorIdentifier.hh
===========================

Custom sensor identifier for DD4hep geometries.

Unlike the default U4SensorIdentifierDefault which relies on
GLOBAL_SENSOR_BOUNDARY_LIST env var for non-instanced geometries,
this implementation directly checks G4VSensitiveDetector on volumes.

This works for DD4hep geometries where sensitive detectors are
explicitly set via DetElement::setSensitiveDetector().
**/

#include <iostream>
#include <vector>

#include "G4PVPlacement.hh"
#include "G4VSensitiveDetector.hh"

#include "U4SensorIdentifier.h"

struct DD4hepSensorIdentifier : public U4SensorIdentifier
{
int level = 0 ;
int counter = 0 ; // auto-increment sensor ID (1-based; 0 means "not a sensor" in opticks)

void setLevel(int _level) override { level = _level ; }

/**
getGlobalIdentity
-------------------
Checks if the physical volume has a G4VSensitiveDetector attached.
Returns a unique 1-based sensor_id, or -1 if not sensitive.

Note: opticks treats sensor_id == 0 as "not a sensor", so IDs must be >= 1.
PV copy numbers are not reliable (e.g. dRICH SiPMs all have copyNo=0).
**/
int getGlobalIdentity(const G4VPhysicalVolume* pv,
const G4VPhysicalVolume* /*ppv*/) override
{
if (!pv) return -1 ;

const G4LogicalVolume* lv = pv->GetLogicalVolume() ;
G4VSensitiveDetector* sd = lv->GetSensitiveDetector() ;

if (!sd) return -1 ;

int sensor_id = ++counter ; // 1-based unique ID

if (level > 0)
std::cout << "DD4hepSensorIdentifier::getGlobalIdentity"
<< " sensor_id " << sensor_id
<< " sd " << sd->GetName()
<< " pv " << pv->GetName()
<< std::endl ;

return sensor_id ;
}

/**
getInstanceIdentity
---------------------
Same as default: recursively search for G4VSensitiveDetector
within the instance subtree.
**/
int getInstanceIdentity(const G4VPhysicalVolume* instance_outer_pv) const override
{
if (!instance_outer_pv) return -1 ;

std::vector<const G4VPhysicalVolume*> sdpv ;
FindSD_r(sdpv, instance_outer_pv, 0) ;

if (sdpv.empty()) return -1 ;

const G4PVPlacement* pvp =
dynamic_cast<const G4PVPlacement*>(instance_outer_pv) ;
return pvp ? pvp->GetCopyNo() : 0 ;
}

static void FindSD_r(std::vector<const G4VPhysicalVolume*>& sdpv,
const G4VPhysicalVolume* pv, int depth)
{
const G4LogicalVolume* lv = pv->GetLogicalVolume() ;
G4VSensitiveDetector* sd = lv->GetSensitiveDetector() ;
if (sd) sdpv.push_back(pv) ;
for (size_t i = 0; i < size_t(lv->GetNoDaughters()); i++)
FindSD_r(sdpv, lv->GetDaughter(i), depth + 1) ;
}
};
Loading
Loading