Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-15 07:41:49

0001 #pragma once
0002 /**
0003 DD4hepSensorIdentifier.hh
0004 ===========================
0005 
0006 Custom sensor identifier for DD4hep geometries.
0007 
0008 Unlike the default U4SensorIdentifierDefault which relies on
0009 GLOBAL_SENSOR_BOUNDARY_LIST env var for non-instanced geometries,
0010 this implementation directly checks G4VSensitiveDetector on volumes.
0011 
0012 This works for DD4hep geometries where sensitive detectors are
0013 explicitly set via DetElement::setSensitiveDetector().
0014 **/
0015 
0016 #include <iostream>
0017 #include <vector>
0018 
0019 #include "G4PVPlacement.hh"
0020 #include "G4VSensitiveDetector.hh"
0021 
0022 #include "U4SensorIdentifier.h"
0023 
0024 struct DD4hepSensorIdentifier : public U4SensorIdentifier
0025 {
0026     int level = 0;
0027     int counter = 0; // auto-increment sensor ID (1-based; 0 means "not a sensor" in opticks)
0028 
0029     void setLevel(int _level) override
0030     {
0031         level = _level;
0032     }
0033 
0034     /**
0035     getGlobalIdentity
0036     -------------------
0037     Checks if the physical volume has a G4VSensitiveDetector attached.
0038     Returns a unique 1-based sensor_id, or -1 if not sensitive.
0039 
0040     Note: opticks treats sensor_id == 0 as "not a sensor", so IDs must be >= 1.
0041     PV copy numbers are not reliable (e.g. dRICH SiPMs all have copyNo=0).
0042     **/
0043     int getGlobalIdentity(const G4VPhysicalVolume *pv, const G4VPhysicalVolume * /*ppv*/) override
0044     {
0045         if (!pv)
0046             return -1;
0047 
0048         const G4LogicalVolume *lv = pv->GetLogicalVolume();
0049         G4VSensitiveDetector *sd = lv->GetSensitiveDetector();
0050 
0051         if (!sd)
0052             return -1;
0053 
0054         int sensor_id = ++counter; // 1-based unique ID
0055 
0056         if (level > 0)
0057             std::cout << "DD4hepSensorIdentifier::getGlobalIdentity" << " sensor_id " << sensor_id << " sd "
0058                       << sd->GetName() << " pv " << pv->GetName() << std::endl;
0059 
0060         return sensor_id;
0061     }
0062 
0063     /**
0064     getInstanceIdentity
0065     ---------------------
0066     Same as default: recursively search for G4VSensitiveDetector
0067     within the instance subtree.
0068     **/
0069     int getInstanceIdentity(const G4VPhysicalVolume *instance_outer_pv) const override
0070     {
0071         if (!instance_outer_pv)
0072             return -1;
0073 
0074         std::vector<const G4VPhysicalVolume *> sdpv;
0075         FindSD_r(sdpv, instance_outer_pv, 0);
0076 
0077         if (sdpv.empty())
0078             return -1;
0079 
0080         const G4PVPlacement *pvp = dynamic_cast<const G4PVPlacement *>(instance_outer_pv);
0081         return pvp ? pvp->GetCopyNo() : 0;
0082     }
0083 
0084     static void FindSD_r(std::vector<const G4VPhysicalVolume *> &sdpv, const G4VPhysicalVolume *pv, int depth)
0085     {
0086         const G4LogicalVolume *lv = pv->GetLogicalVolume();
0087         G4VSensitiveDetector *sd = lv->GetSensitiveDetector();
0088         if (sd)
0089             sdpv.push_back(pv);
0090         for (size_t i = 0; i < size_t(lv->GetNoDaughters()); i++)
0091             FindSD_r(sdpv, lv->GetDaughter(i), depth + 1);
0092     }
0093 };