Belle II Software development
GeoCache.cc
1/**************************************************************************
2 * basf2 (Belle II Analysis Software Framework) *
3 * Author: The Belle II Collaboration *
4 * *
5 * See git log for contributors and copyright holders. *
6 * This file is licensed under LGPL-3.0, see LICENSE.md. *
7 **************************************************************************/
8
9
10#include <vxd/geometry/GeoCache.h>
11#include <vxd/simulation/SensitiveDetectorBase.h>
12#include <framework/gearbox/Unit.h>
13#include <framework/logging/Logger.h>
14#include <TMath.h>
15
16#include <stack>
17#include <memory>
18
19#include <G4LogicalVolume.hh>
20#include <G4VPhysicalVolume.hh>
21#include <G4NavigationHistory.hh>
22#include <G4Transform3D.hh>
23
24using namespace std;
25
26namespace Belle2 {
31 namespace VXD {
33 {
34 // Add callback to update ReconstructionTransformation whenever alignment changes
36 }
37
39 {
40 m_pxdLayers.clear();
41 m_svdLayers.clear();
42 m_telLayers.clear();
43 m_ladders.clear();
44 m_sensors.clear();
45 m_sensorInfo.clear();
46
48 m_ladderPlacements.clear();
49 m_sensorPlacements.clear();
50 }
51
53 {
54 id.setSegmentNumber(0);
55 SensorInfoMap::const_iterator info = m_sensorInfo.find(id);
56 return (info != m_sensorInfo.end());
57 }
58
59 const vector<VxdID> GeoCache::getListOfSensors() const
60 {
61 vector<VxdID> sensors;
62 for (auto entry : m_sensorInfo)
63 sensors.push_back(entry.first);
64 return sensors;
65 }
66
68 {
69 id.setSegmentNumber(0);
70 SensorInfoMap::const_iterator info = m_sensorInfo.find(id);
71 if (info == m_sensorInfo.end()) {
72 B2WARNING("VXD Sensor " << id << " does not exist.");
73 return *(m_sensorInfo.begin()->second);
74 }
75 return *(info->second);
76 }
77
78 void GeoCache::findVolumes(G4VPhysicalVolume* envelope)
79 {
80 //So, lets loop over the geometry tree and find all sensitive volumes.
81 //To get the correct Transformation matrices we use the
82 //G4NavigationHistory which is a stack of premultiplied transformations.
83 G4NavigationHistory nav;
84 //To avoid recursion we store all volumes in a stack, starting with the
85 //envelope we are about to search in
86 stack<G4VPhysicalVolume*> volumes;
87 volumes.push(envelope);
88
89 //Now lets just continue until the stack is empty
90 while (!volumes.empty()) {
91 G4VPhysicalVolume* physical = volumes.top();
92 volumes.pop();
93 //NULL indicates that we are finished with the children of a node, so
94 //pop a transformation level
95 if (!physical) {
96 nav.BackLevel();
97 continue;
98 }
99 //Add a NULL to so that we know that all children are finished once we
100 //emptied the stack of volumes back to this NULL
101 volumes.push(0);
102 //Now enter the volume
103 nav.NewLevel(physical);
104
105 G4LogicalVolume* logical = physical->GetLogicalVolume();
106
107 //Check if we found a sensitive volume with correct type
108 SensitiveDetectorBase* sensitive = dynamic_cast<SensitiveDetectorBase*>(logical->GetSensitiveDetector());
109 if (sensitive) {
110 //Apparently we did, so get the sensor Information and add it
111 SensorInfoBase* info = sensitive->getSensorInfo();
112 if (!info) B2FATAL("No SensorInfo found for Volume " << logical->GetName());
113
114 //Convert transformation to ROOT
115 const G4AffineTransform g4transform = nav.GetTopTransform().Inverse();
116 TGeoHMatrix transform;
117 double rotation[9] = {
118 g4transform[0], g4transform[4], g4transform[8],
119 g4transform[1], g4transform[5], g4transform[9],
120 g4transform[2], g4transform[6], g4transform[10]
121 };
122 transform.SetRotation(rotation);
123 transform.SetDx(g4transform[12]*Unit::mm);
124 transform.SetDy(g4transform[13]*Unit::mm);
125 transform.SetDz(g4transform[14]*Unit::mm);
126 info->setTransformation(transform); // cppcheck-suppress nullPointerRedundantCheck
127 info->setTransformation(transform, true); // cppcheck-suppress nullPointerRedundantCheck
128
129 addSensor(info);
130 }
131
132 int nDaughters = logical->GetNoDaughters();
133 //Add all children. Since we use a stack they will be processed in
134 //opposite order In principle we do not care, but for niceness sake we
135 //add them back to front so that they are processed in the "correct"
136 //order
137 for (int i = nDaughters - 1; i >= 0; --i) {
138 G4VPhysicalVolume* daughter = logical->GetDaughter(i);
139 volumes.push(daughter);
140 }
141 }
142
143 // Finally set-up reconstruction transformations
145 }
146
148 {
149 //Save pointer to the SensorInfo and update lists of all existing
150 //layers,ladders,sensors
151 VxdID sensorID = sensorinfo->getID();
152 VxdID ladderID = sensorID;
153 ladderID.setSensorNumber(0);
154 VxdID layerID = ladderID;
155 layerID.setLadderNumber(0);
156
157 m_sensorInfo[sensorID] = sensorinfo;
158
159 switch (sensorinfo->getType()) {
161 m_pxdLayers.insert(layerID);
162 break;
164 m_svdLayers.insert(layerID);
165 break;
167 m_telLayers.insert(layerID);
168 break;
169 default:
170 B2FATAL("Cannot use anything else as SensorTypes PXD, SVD, or TEL when creating VXD Sensors");
171 }
172 m_ladders[layerID].insert(ladderID);
173 m_sensors[ladderID].insert(sensorID);
174 }
175
177 {
178 switch (type) {
180 return m_pxdLayers;
182 return m_svdLayers;
184 return m_telLayers;
185 default:
186 std::set<VxdID> allLayers = m_pxdLayers;
187 allLayers.insert(m_svdLayers.begin(), m_svdLayers.end());
188 allLayers.insert(m_telLayers.begin(), m_telLayers.end());
189 return allLayers;
190 }
191 }
192
193 const set<VxdID>& GeoCache::getLadders(VxdID layer) const
194 {
195 //We only index by layer, so set everything else to 0
196 layer.setLadderNumber(0);
197 layer.setSensorNumber(0);
198 layer.setSegmentNumber(0);
199 SensorHierachy::const_iterator info = m_ladders.find(layer);
200 if (info == m_ladders.end()) B2FATAL("VXD Layer " << layer << "does not exist.");
201 return info->second;
202 }
203
204 const set<VxdID>& GeoCache::getSensors(VxdID ladder) const
205 {
206 //We only index by layer and ladder, set sensor to 0
207 ladder.setSensorNumber(0);
208 ladder.setSegmentNumber(0);
209 SensorHierachy::const_iterator info = m_sensors.find(ladder);
210 if (info == m_sensors.end()) B2FATAL("VXD Ladder " << ladder << "does not exist.");
211 return info->second;
212 }
213
215 {
216 static unique_ptr<GeoCache> instance(new GeoCache());
217 return *instance;
218 }
219
220 void GeoCache::addSensorPlacement(VxdID ladder, VxdID sensor, const G4Transform3D& placement)
221 {
222 m_sensorPlacements[ladder].push_back(std::make_pair(sensor, g4Transform3DToTGeo(placement)));
223 }
224
225 void GeoCache::addLadderPlacement(VxdID halfShell, VxdID ladder, const G4Transform3D& placement)
226 {
227 m_ladderPlacements[halfShell].push_back(std::make_pair(ladder, g4Transform3DToTGeo(placement)));
228 // Add the (empty) container for sensor placements inside this ladder
229 m_sensorPlacements[ladder] = std::vector<std::pair<VxdID, TGeoHMatrix>>();
230 }
231
232 void GeoCache::addHalfShellPlacement(VxdID halfShell, const G4Transform3D& placement)
233 {
234 m_halfShellPlacements[halfShell] = g4Transform3DToTGeo(placement);
235 // Add the (empty) container for ladder placements inside this halfshell
236 m_ladderPlacements[halfShell] = std::vector<std::pair<VxdID, TGeoHMatrix>>();
237 }
238
239 const map<VxdID, TGeoHMatrix>& GeoCache::getHalfShellPlacements() const {return m_halfShellPlacements;}
240
241 const vector< pair< VxdID, TGeoHMatrix > >& GeoCache::getSensorPlacements(VxdID ladder) const
242 {
243 auto placements = m_sensorPlacements.find(ladder);
244 if (placements == m_sensorPlacements.end())
245 throw std::invalid_argument("Invalid ladder id " + (std::string) ladder);
246
247 return placements->second;
248 }
249
250 const vector< pair< VxdID, TGeoHMatrix > >& GeoCache::getLadderPlacements(VxdID halfShell) const
251 {
252 auto placements = m_ladderPlacements.find(halfShell);
253 if (placements == m_ladderPlacements.end())
254 throw std::invalid_argument("Invalid half-shelve id " + (std::string) halfShell);
255
256 return placements->second;
257 }
258
260 {
261 if (!m_vxdAlignments.isValid()) {
262 B2WARNING("No VXD alignment data. Defaults (0's) will be used!");
263 return;
264 }
265
266 // Loop over VXD sensors to read parameters for description of planar defomration
267 for (auto& sensorID : getListOfSensors()) {
268 std::vector<double> planarParameters = {
269 // Numbering of VXD alignment parameters:
270 // -> 0-6: Rigid body alignment
271 // -> 31-33: First level of surface deformation
272 // -> 41-44: Second level of surface deformation
273 // -> 51-55: Third level of surface deformation
274 m_vxdAlignments->get(sensorID, 31),
275 m_vxdAlignments->get(sensorID, 32),
276 m_vxdAlignments->get(sensorID, 33),
277 m_vxdAlignments->get(sensorID, 41),
278 m_vxdAlignments->get(sensorID, 42),
279 m_vxdAlignments->get(sensorID, 43),
280 m_vxdAlignments->get(sensorID, 44),
281 m_vxdAlignments->get(sensorID, 51),
282 m_vxdAlignments->get(sensorID, 52),
283 m_vxdAlignments->get(sensorID, 53),
284 m_vxdAlignments->get(sensorID, 54),
285 m_vxdAlignments->get(sensorID, 55),
286 };
287
288 // Store parameters for planar deformation
289 VXD::SensorInfoBase& sensorInfo = const_cast<VXD::SensorInfoBase&>(getSensorInfo(sensorID));
290 sensorInfo.setSurfaceParameters(planarParameters);
291 }
292
304 for (auto& halfShellPlacement : getHalfShellPlacements()) {
305 TGeoHMatrix trafoHalfShell = halfShellPlacement.second;
306 trafoHalfShell *= getTGeoFromRigidBodyParams(
307 m_vxdAlignments->get(halfShellPlacement.first, VXDAlignment::dU),
308 m_vxdAlignments->get(halfShellPlacement.first, VXDAlignment::dV),
309 m_vxdAlignments->get(halfShellPlacement.first, VXDAlignment::dW),
310 m_vxdAlignments->get(halfShellPlacement.first, VXDAlignment::dAlpha),
311 m_vxdAlignments->get(halfShellPlacement.first, VXDAlignment::dBeta),
312 m_vxdAlignments->get(halfShellPlacement.first, VXDAlignment::dGamma)
313 );
314
315 for (auto& ladderPlacement : getLadderPlacements(halfShellPlacement.first)) {
316 // Updated trafo
317 TGeoHMatrix trafoLadder = ladderPlacement.second;
318 trafoLadder *= getTGeoFromRigidBodyParams(
319 m_vxdAlignments->get(ladderPlacement.first, VXDAlignment::dU),
320 m_vxdAlignments->get(ladderPlacement.first, VXDAlignment::dV),
321 m_vxdAlignments->get(ladderPlacement.first, VXDAlignment::dW),
322 m_vxdAlignments->get(ladderPlacement.first, VXDAlignment::dAlpha),
323 m_vxdAlignments->get(ladderPlacement.first, VXDAlignment::dBeta),
324 m_vxdAlignments->get(ladderPlacement.first, VXDAlignment::dGamma)
325 );
326
327 for (auto& sensorPlacement : getSensorPlacements(ladderPlacement.first)) {
328 // Updated trafo
329 TGeoHMatrix trafoSensor = sensorPlacement.second;
330 trafoSensor *= getTGeoFromRigidBodyParams(
331 m_vxdAlignments->get(sensorPlacement.first, VXDAlignment::dU),
332 m_vxdAlignments->get(sensorPlacement.first, VXDAlignment::dV),
333 m_vxdAlignments->get(sensorPlacement.first, VXDAlignment::dW),
334 m_vxdAlignments->get(sensorPlacement.first, VXDAlignment::dAlpha),
335 m_vxdAlignments->get(sensorPlacement.first, VXDAlignment::dBeta),
336 m_vxdAlignments->get(sensorPlacement.first, VXDAlignment::dGamma)
337 );
338
339 // Store new reco-transformation
340 VXD::SensorInfoBase& geometry = const_cast<VXD::SensorInfoBase&>(getSensorInfo(sensorPlacement.first));
341 geometry.setTransformation(trafoHalfShell * trafoLadder * trafoSensor, true);
342
343 }
344 }
345 }
346
347 }
348
349 TGeoHMatrix GeoCache::g4Transform3DToTGeo(const G4Transform3D& g4)
350 {
351 TGeoHMatrix trafo;
352 // Differential translation
353 TGeoTranslation translation;
354 // Differential rotation
355 TGeoRotation rotation;
356
357 //NOTE: for some reason, there is cm vs. mm difference
358 trafo.SetDx(g4.getTranslation()[0] / 10.);
359 trafo.SetDy(g4.getTranslation()[1] / 10.);
360 trafo.SetDz(g4.getTranslation()[2] / 10.);
361
362 Double_t rotMatrix[9];
363 for (int i = 0; i < 3; ++i) {
364 for (int j = 0; j < 3; ++j) {
365 rotMatrix[i * 3 + j] = g4.getRotation()[i][j];
366 }
367 }
368 trafo.SetRotation(rotMatrix);
369 return trafo;
370 }
371
372 TGeoHMatrix GeoCache::getTGeoFromRigidBodyParams(double dU, double dV, double dW, double dAlpha, double dBeta, double dGamma)
373 {
374 // Differential translation
375 TGeoTranslation translation;
376 // Differential rotation
377 TGeoRotation rotation;
378
379 translation.SetTranslation(dU, dV, dW);
380 rotation.RotateX(- dAlpha * TMath::RadToDeg());
381 rotation.RotateY(- dBeta * TMath::RadToDeg());
382 rotation.RotateZ(- dGamma * TMath::RadToDeg());
383
384 // Differential trafo (trans + rot)
385 TGeoCombiTrans combi(translation, rotation);
386 TGeoHMatrix trafo;
387 trafo = trafo * combi;
388 return trafo;
389 }
390 } //VXD namespace
392} //Belle2 namespace
static const double mm
[millimeters]
Definition: Unit.h:70
static const baseType dAlpha
Sensor/layer/ladder alignment in local alpha.
Definition: VXDAlignment.h:29
static const baseType dGamma
Sensor/layer/ladder alignment in local gamma.
Definition: VXDAlignment.h:33
static const baseType dW
Sensor/layer/ladder alignment in local w.
Definition: VXDAlignment.h:27
static const baseType dBeta
Sensor/layer/ladder alignment in local beta.
Definition: VXDAlignment.h:31
static const baseType dU
Sensor/layer/ladder alignment in local u.
Definition: VXDAlignment.h:23
static const baseType dV
Sensor/layer/ladder alignment in local v.
Definition: VXDAlignment.h:25
Class to faciliate easy access to sensor information of the VXD like coordinate transformations or pi...
Definition: GeoCache.h:39
DBObjPtr< VXDAlignment > m_vxdAlignments
DBObjPtr for the alignment.
Definition: GeoCache.h:191
static TGeoHMatrix getTGeoFromRigidBodyParams(double dU, double dV, double dW, double dAlpha, double dBeta, double dGamma)
Convert 6 rigid body params (alignment corrections) to corresponding TGeoHMatrix Angles in radians,...
Definition: GeoCache.cc:372
const std::set< Belle2::VxdID > getLayers(SensorInfoBase::SensorType sensortype=SensorInfoBase::VXD)
Return a set of all known Layers.
Definition: GeoCache.cc:176
const std::vector< VxdID > getListOfSensors() const
Get list of all sensors.
Definition: GeoCache.cc:59
const SensorInfoBase & getSensorInfo(Belle2::VxdID id) const
Return a referecne to the SensorInfo of a given SensorID.
Definition: GeoCache.cc:67
void addSensorPlacement(VxdID ladder, VxdID sensor, const G4Transform3D &placement)
Remember how sensor is placed into ladder.
Definition: GeoCache.cc:220
const std::set< Belle2::VxdID > & getSensors(Belle2::VxdID ladder) const
Return a set of all sensor IDs belonging to a given ladder.
Definition: GeoCache.cc:204
void setupReconstructionTransformations()
Initialize from DB for reconstruction Updates all SensorInfo transformations for reconstruction from ...
Definition: GeoCache.cc:259
static TGeoHMatrix g4Transform3DToTGeo(const G4Transform3D &g4)
Covenient function to convert G4Transform3D to TGeoHMatrix.
Definition: GeoCache.cc:349
void findVolumes(G4VPhysicalVolume *envelope)
Search a given Geometry for Sensors.
Definition: GeoCache.cc:78
void addSensor(SensorInfoBase *sensorinfo)
Add a SensorInfo instance to the list of known sensors This method will manually add a SensorInfo ins...
Definition: GeoCache.cc:147
static GeoCache & getInstance()
Return a reference to the singleton instance.
Definition: GeoCache.cc:214
const std::vector< std::pair< VxdID, TGeoHMatrix > > & getSensorPlacements(VxdID ladder) const
Retrieve stored sensor placements into ladders.
Definition: GeoCache.cc:241
std::set< Belle2::VxdID > m_pxdLayers
Set of all PXD layer IDs.
Definition: GeoCache.h:168
void addHalfShellPlacement(VxdID halfShell, const G4Transform3D &placement)
Remember how half-shell is placed into world volume.
Definition: GeoCache.cc:232
GeoCache()
Singleton class, hidden constructor.
Definition: GeoCache.cc:32
std::map< VxdID, std::vector< std::pair< VxdID, TGeoHMatrix > > > m_ladderPlacements
Map of shell ids and their associated ladder ids and their placements.
Definition: GeoCache.h:181
const std::map< VxdID, TGeoHMatrix > & getHalfShellPlacements() const
Retrieve stored half-shell placements into world volume.
Definition: GeoCache.cc:239
std::set< Belle2::VxdID > m_telLayers
Set of all Tel layer IDs.
Definition: GeoCache.h:172
SensorHierachy m_sensors
Map of all Sensor IDs belonging to a given Ladder ID.
Definition: GeoCache.h:176
SensorInfoMap m_sensorInfo
Map to find the SensorInfo for a given Sensor ID.
Definition: GeoCache.h:185
const std::vector< std::pair< VxdID, TGeoHMatrix > > & getLadderPlacements(VxdID halfShell) const
Retrieve stored ladder placements into half-shell.
Definition: GeoCache.cc:250
SensorHierachy m_ladders
Map of all Ladder IDs belonging to a given Layer ID.
Definition: GeoCache.h:174
void clear()
Clean up internal structures.
Definition: GeoCache.cc:38
std::map< VxdID, TGeoHMatrix > m_halfShellPlacements
Map of shell ids and their placements in top volume.
Definition: GeoCache.h:179
bool validSensorID(Belle2::VxdID id) const
Check that id is a valid sensor number.
Definition: GeoCache.cc:52
void addLadderPlacement(VxdID halfShell, VxdID ladder, const G4Transform3D &placement)
Remember how ladder is placed into half-shell.
Definition: GeoCache.cc:225
const std::set< Belle2::VxdID > & getLadders(Belle2::VxdID layer) const
Return a set of all ladder IDs belonging to a given layer.
Definition: GeoCache.cc:193
std::map< VxdID, std::vector< std::pair< VxdID, TGeoHMatrix > > > m_sensorPlacements
Map of ladder ids and their associated sensor ids and their placements.
Definition: GeoCache.h:183
std::set< Belle2::VxdID > m_svdLayers
Set of all SVD layer IDs.
Definition: GeoCache.h:170
Base class for Sensitive Detector implementation of PXD and SVD.
SensorInfoBase * getSensorInfo()
Return a pointer to the SensorInfo associated with this instance.
Base class to provide Sensor Information for PXD and SVD.
SensorType getType() const
Return the Type of the Sensor.
SensorType
Enum specifing the type of sensor the SensorInfo represents.
@ TEL
Testbeam telescope sensor.
VxdID getID() const
Return the ID of the Sensor.
void setSurfaceParameters(const std::vector< double > &planarParameters)
Fill parameters of planar deformation to vector.
Class to uniquely identify a any structure of the PXD and SVD.
Definition: VxdID.h:33
void setSensorNumber(baseType sensor)
Set the sensor id.
Definition: VxdID.h:111
void setLadderNumber(baseType ladder)
Set the ladder id.
Definition: VxdID.h:109
Abstract base class for different kinds of events.
STL namespace.