Skip to content

Commit 75487ac

Browse files
sawenzelclaude
andcommitted
Resolve the TRD hit volume lookup to integers at initialisation
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
1 parent 9325616 commit 75487ac

2 files changed

Lines changed: 91 additions & 24 deletions

File tree

Detectors/TRD/simulation/include/TRDSimulation/Detector.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,14 @@ class Detector : public o2::base::DetImpl<Detector>
6161
// defines/sets-up the sensitive volumes
6262
void defineSensitiveVolumes();
6363

64+
// Fills the volume-id lookup tables below; called once from InitializeO2Detector().
65+
void buildVolumeIdTables();
66+
67+
// What a sensitive volume is, in mRegionByVolId
68+
enum Region : int8_t { kNotSensitive = 0,
69+
kDrift = 1,
70+
kAmplification = 2 };
71+
6472
// addHit
6573
template <typename T>
6674
void addHit(T x, T y, T z, T locC, T locR, T locT, T tof, int charge, int trackId, int detId, bool drift = false);
@@ -83,6 +91,20 @@ class Detector : public o2::base::DetImpl<Detector>
8391

8492
Geometry* mGeom = nullptr;
8593

94+
// Volume-id lookup tables, resolved once at initialisation so that ProcessHits does
95+
// integer indexing instead of an sscanf on a volume name at every step. Volume ids are
96+
// small and dense, so a flat vector beats a map here.
97+
std::vector<int8_t> mRegionByVolId; //!< drift / amplification / not sensitive, by volume id
98+
std::vector<int8_t> mChamberByVolId; //!< chamber within the supermodule (0..29), -1 elsewhere
99+
std::vector<int8_t> mSectorByVolId; //!< supermodule (0..17), -1 elsewhere
100+
101+
// How far above a sensitive volume the chamber and the supermodule sit. This depends on
102+
// how the transport engine represents the hierarchy -- a native-Geant4 conversion flattens
103+
// the chamber assembly away -- so it is resolved from the tables on the first hit rather
104+
// than hard-coded.
105+
int mChamberOffset = -1; //!
106+
int mSectorOffset = -1; //!
107+
86108
template <typename Det>
87109
friend class o2::base::DetImpl;
88110
ClassDefOverride(Detector, 1);

Detectors/TRD/simulation/src/Detector.cxx

Lines changed: 69 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,40 @@ void Detector::InitializeO2Detector()
5959
{
6060
// register the sensitive volumes with FairRoot
6161
defineSensitiveVolumes();
62+
buildVolumeIdTables();
63+
}
64+
65+
void Detector::buildVolumeIdTables()
66+
{
67+
auto* vmc = TVirtualMC::GetMC();
68+
const int nVols = vmc->NofVolumes() + 1;
69+
mRegionByVolId.assign(nVols, kNotSensitive);
70+
mChamberByVolId.assign(nVols, -1);
71+
mSectorByVolId.assign(nVols, -1);
72+
73+
auto record = [nVols](std::vector<int8_t>& table, int vid, int8_t value, const char* what) {
74+
if (vid <= 0 || vid >= nVols) {
75+
LOG(fatal) << "TRD volume " << what << " has no usable volume id (" << vid << ")";
76+
}
77+
table[vid] = value;
78+
};
79+
80+
// The drift and amplification gas volumes, distinguished by the second character of
81+
// their name exactly as Geometry::createVolume selects them as sensitive.
82+
for (const auto& name : mGeom->getSensitiveTRDVolumes()) {
83+
record(mRegionByVolId, vmc->VolId(name.c_str()), name[1] == 'J' ? kDrift : kAmplification, name.c_str());
84+
}
85+
86+
// The readout-chamber assemblies and the supermodule mother volumes
87+
char volName[16];
88+
for (int idet = 0; idet < NLAYER * NSTACK; ++idet) {
89+
snprintf(volName, sizeof(volName), "UT%02d", idet);
90+
record(mChamberByVolId, vmc->VolId(volName), idet, volName);
91+
}
92+
for (int sector = 0; sector < NSECTOR; ++sector) {
93+
snprintf(volName, sizeof(volName), "BTRD%d", sector);
94+
record(mSectorByVolId, vmc->VolId(volName), sector, volName);
95+
}
6296
}
6397

6498
void Detector::InitializeParams()
@@ -89,35 +123,46 @@ bool Detector::ProcessHits(FairVolume* v)
89123
fMC->SetMaxStep(mMaxMCStepDef); // Should we optimize this value?
90124

91125
// Inside sensitive volume ?
92-
bool drRegion = false;
93-
bool amRegion = false;
94-
char idRegion;
95-
int cIdChamber;
96-
int r1 = std::sscanf(fMC->CurrentVolName(), "U%c%d", &idRegion, &cIdChamber);
97-
if (r1 != 2) {
98-
LOG(fatal) << "Something went wrong with the geometry volume name " << fMC->CurrentVolName();
99-
}
100-
if (idRegion == 'J') {
101-
drRegion = true;
102-
} else if (idRegion == 'K') {
103-
amRegion = true;
104-
} else {
126+
int copy = 0;
127+
const int vid = fMC->CurrentVolID(copy);
128+
const int8_t region = (vid > 0 && vid < (int)mRegionByVolId.size()) ? mRegionByVolId[vid] : kNotSensitive;
129+
if (region == kNotSensitive) {
105130
return false;
106131
}
107-
108-
const int idChamber = mGeom->getDetectorSec(cIdChamber);
109-
if (idChamber < 0 || idChamber > 29) {
110-
LOG(fatal) << "Chamber ID out of bounds";
132+
const bool drRegion = (region == kDrift);
133+
const bool amRegion = (region == kAmplification);
134+
135+
// Find how far up the chamber and the supermodule sit, once, by walking up until the
136+
// ancestor's volume id is one we know. Hard-coding the depth breaks silently whenever a
137+
// level is added, removed, or flattened away by the transport engine's own conversion.
138+
if (mSectorOffset < 0) {
139+
for (int off = 0; off < 16; ++off) {
140+
const int oid = fMC->CurrentVolOffID(off, copy);
141+
if (oid <= 0 || oid >= (int)mChamberByVolId.size()) {
142+
continue;
143+
}
144+
if (mChamberOffset < 0 && mChamberByVolId[oid] >= 0) {
145+
mChamberOffset = off;
146+
}
147+
if (mSectorByVolId[oid] >= 0) {
148+
mSectorOffset = off;
149+
break;
150+
}
151+
}
152+
if (mChamberOffset < 0 || mSectorOffset < 0) {
153+
LOG(fatal) << "No TRD chamber/supermodule ancestor above sensitive volume " << fMC->CurrentVolName();
154+
}
155+
LOG(info) << "TRD: chamber at mother offset " << mChamberOffset << ", supermodule at " << mSectorOffset;
111156
}
112157

113-
int sector;
114-
int r2 = std::sscanf(fMC->CurrentVolOffName(7), "BTRD%d", &sector);
115-
if (r2 != 1) {
116-
LOG(fatal) << "Something went wrong with the geometry volume name " << fMC->CurrentVolOffName(7);
117-
}
118-
if (sector < 0 || sector >= NSECTOR) {
119-
LOG(fatal) << "Sector out of bounds";
158+
const int chamberVol = fMC->CurrentVolOffID(mChamberOffset, copy);
159+
const int sectorVol = fMC->CurrentVolOffID(mSectorOffset, copy);
160+
const int idChamber = (chamberVol > 0 && chamberVol < (int)mChamberByVolId.size()) ? mChamberByVolId[chamberVol] : -1;
161+
const int sector = (sectorVol > 0 && sectorVol < (int)mSectorByVolId.size()) ? mSectorByVolId[sectorVol] : -1;
162+
if (idChamber < 0 || sector < 0) {
163+
LOG(fatal) << "Cannot resolve TRD chamber/supermodule from volume " << fMC->CurrentVolName();
120164
}
165+
121166
// The detector number (0 - 539)
122167
int det = mGeom->getDetector(mGeom->getLayer(idChamber), mGeom->getStack(idChamber), sector);
123168
if (det < 0 || det >= MAXCHAMBER) {

0 commit comments

Comments
 (0)