Belle II Software  release-08-01-10
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 
24 using namespace std;
25 
26 namespace Belle2 {
31  namespace VXD {
32  GeoCache::GeoCache()
33  {
34  // Add callback to update ReconstructionTransformation whenever alignment changes
35  m_vxdAlignments.addCallback(this, &VXD::GeoCache::setupReconstructionTransformations);
36  }
37 
38  void GeoCache::clear()
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 
47  m_halfShellPlacements.clear();
48  m_ladderPlacements.clear();
49  m_sensorPlacements.clear();
50  }
51 
52  bool GeoCache::validSensorID(Belle2::VxdID id) const
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 
67  const SensorInfoBase& GeoCache::getSensorInfo(VxdID id) const
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
144  setupReconstructionTransformations();
145  }
146 
147  void GeoCache::addSensor(SensorInfoBase* sensorinfo)
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()) {
160  case SensorInfoBase::PXD:
161  m_pxdLayers.insert(layerID);
162  break;
163  case SensorInfoBase::SVD:
164  m_svdLayers.insert(layerID);
165  break;
166  case SensorInfoBase::TEL:
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 
176  const set<VxdID> GeoCache::getLayers(SensorInfoBase::SensorType type)
177  {
178  switch (type) {
179  case SensorInfoBase::PXD:
180  return m_pxdLayers;
181  case SensorInfoBase::SVD:
182  return m_svdLayers;
183  case SensorInfoBase::TEL:
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 
214  GeoCache& GeoCache::getInstance()
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 
259  void GeoCache::setupReconstructionTransformations()
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
Class to faciliate easy access to sensor information of the VXD like coordinate transformations or pi...
Definition: GeoCache.h:39
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.
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.