FairRoot/PandaRoot
PndLmdGeometryHelper.cxx
Go to the documentation of this file.
1 #include "PndLmdGeometryHelper.h"
2 #include "PndGeoHandling.h"
3 
4 #include <regex>
5 #include <iostream>
6 #include <string>
7 #include <vector>
8 
9 #include "TGeoPhysicalNode.h"
10 
11 using std::string;
12 
14 }
15 
16 /*
17  * This function does all the important work of translating a lmd volume path to
18  * the PndLmdHitLocationInfo. It uses the navigation paths as given in the
19  * lmd geometry parameter config file.
20  * The structure is as following
21  * -> half: up: 0; down: 1
22  * -> plane: 0 to n_p (n_p: number of detector planes -1); counting in beam
23  * direction
24  * -> module: 0 to n_m (n_m: number of modules per half plane -1);
25  * for top half: counting from left to right (clockwise) in beam direction
26  * for top half: counting from right to left (clockwise) in beam direction
27  * -> sensor: sensor counter for a module. Total number of sensors per module is
28  * 2x (modules per side). Counting starts on front (w.r.t. beam direction)
29  */
31  const std::string &volume_path) const {
32  PndLmdHitLocationInfo hit_info;
33  std::stringstream reg_exp;
34  for (auto const &nav_path : navigation_paths) {
35  reg_exp << "/" << nav_path.first << "_(\\d+)";
36  }
37 
38  std::smatch match;
39 
40  if (std::regex_search(volume_path, match, std::regex(reg_exp.str()))) {
41  hit_info.detector_half = (unsigned char) std::stoul(match[2]);
42  hit_info.plane = (unsigned char) std::stoul(match[3]);
43  hit_info.module = (unsigned char) std::stoul(match[4]);
44  unsigned char sensor_id((unsigned char) std::stoul(match[5]));
45  hit_info.module_side = 0;
46  hit_info.module_sensor_id = sensor_id;
47 
48  unsigned int sensors_per_module_side = geometry_properties.get<unsigned int>(
49  "general.sensors_per_module_side");
50 
51  if (sensor_id > sensors_per_module_side - 1) {
52  hit_info.module_side = 1;
53  sensor_id = sensor_id % (sensors_per_module_side - 1);
54  }
55 
56  // now we have to make sure the TGeoManager builds the matrix cache
57  // correctly the only way we found (analogous to PndGeoHandling) is to
58  // dive down to this node from the top, then the matrix multiplications
59  // are done correctly
60  TString actPath = fGeoManager->GetPath();
61  fGeoManager->cd(volume_path.c_str());
62  PndGeoHandling::Instance()->cd(fGeoManager->GetCurrentNode());
63  if (actPath != "" && actPath != " ") fGeoManager->cd(actPath);
64 
65  }
66  else {
67  throw std::runtime_error("PndLmdGeometryHelper::translateVolumePathToHitLocationInfo: geometry "
68  "navigation paths mismatch!"
69  " Seems like you used a different lmd geo config file to create a lmd "
70  "root geometry which was use in your simulations...");
71  }
72 
73  return hit_info;
74 }
75 
77  PndGeoHandling *geo_handling = PndGeoHandling::Instance();
78 
79  std::string vol_path(geo_handling->GetPath(sensor_id).Data());
80 
82  volume_path_to_hit_info_mapping[vol_path] = hit_loc_info;
83  sensor_id_to_hit_info_mapping[sensor_id] = hit_loc_info;
84 
85  return sensor_id_to_hit_info_mapping[sensor_id];
86 }
87 
88 const PndLmdHitLocationInfo& PndLmdGeometryHelper::createMappingEntry(const std::string &volume_path) {
89  PndGeoHandling *geo_handling = PndGeoHandling::Instance();
90 
91  int sensor_id(geo_handling->GetShortID(volume_path.c_str()));
92 
94  volume_path_to_hit_info_mapping[volume_path] = hit_loc_info;
95  sensor_id_to_hit_info_mapping[sensor_id] = hit_loc_info;
96 
97  return volume_path_to_hit_info_mapping[volume_path];
98 }
99 
100 const PndLmdHitLocationInfo& PndLmdGeometryHelper::getHitLocationInfo(const std::string &volume_path) {
101  auto const &result = volume_path_to_hit_info_mapping.find(volume_path);
102  if (result != volume_path_to_hit_info_mapping.end()) {
103  return result->second;
104  }
105  else {
106  return createMappingEntry(volume_path);
107  }
108 }
109 
111  auto const &result = sensor_id_to_hit_info_mapping.find(sensor_id);
112  if (result != sensor_id_to_hit_info_mapping.end()) {
113  return result->second;
114  }
115  else {
116  return createMappingEntry(sensor_id);
117  }
118 }
119 
121  std::vector<int> result;
122  int overlapID;
123  for (int iHalf = 0; iHalf < 2; iHalf++) {
124  for (int iPlane = 0; iPlane < 4; iPlane++) {
125  for (int iModule = 0; iModule < 5; iModule++) {
126  for (int iOverlap = 0; iOverlap < 9; iOverlap++) {
127  overlapID = 1000 * iHalf + 100 * iPlane + 10 * iModule + iOverlap;
128  result.push_back(overlapID);
129  }
130  }
131  }
132  }
133  return result;
134 }
135 
137  Double_t result[3];
138  Double_t temp[3];
139 
140  global.GetXYZ(temp);
141 
142  auto matrix = getMatrixPndGlobalToLmdLocal();
143  matrix.MasterToLocal(temp, result);
144 
145  return TVector3(result);
146 }
147 
148 TVector3 PndLmdGeometryHelper::transformPndGlobalToSensor(const TVector3 &global, int sensor_id) {
149  Double_t result[3];
150  Double_t temp[3];
151 
152  global.GetXYZ(temp);
153 
154  auto matrix = getMatrixPndGlobalToSensor(sensor_id);
155  matrix.MasterToLocal(temp, result);
156 
157  return TVector3(result);
158 }
159 
160 const TGeoHMatrix PndLmdGeometryHelper::getMatrixPndGlobalToSensor(const int sensorId) {
161  PndGeoHandling *geo_handling = PndGeoHandling::Instance();
162  std::string vol_path(geo_handling->GetPath(int(sensorId)));
163 
164  TString actPath = fGeoManager->GetPath();
165  // go to active part of sensor
166  fGeoManager->cd(vol_path.c_str());
167  // we want the matrix of the whole sensor. so just cd up once
168  fGeoManager->CdUp();
169 
170  TGeoHMatrix matrix = *fGeoManager->GetCurrentMatrix();
171  if (actPath != "" && actPath != " ") fGeoManager->cd(actPath);
172 
173  return matrix;
174 }
175 
176 const TGeoHMatrix PndLmdGeometryHelper::getMatrixSensorToPndGlobal(const int sensorId) {
177  auto result = getMatrixPndGlobalToSensor(sensorId);
178  return TGeoHMatrix(result.Inverse());
179 }
180 
182 
183  int fhalf, fplane, fmodule, fside, fsensor;
184  int bhalf, bplane, bmodule, bside, bsensor;
185 
186  auto const &infoOne = getHitLocationInfo(id1);
187  auto const &infoTwo = getHitLocationInfo(id2);
188 
189  int smalloverlap = -1;
190 
191  fhalf = infoOne.detector_half;
192  bhalf = infoTwo.detector_half;
193 
194  if (bhalf != fhalf) {
195  return -1;
196  }
197 
198  fside = infoOne.module_side;
199  bside = infoTwo.module_side;
200 
201  fplane = infoOne.plane;
202  bplane = infoTwo.plane;
203 
204  fmodule = infoOne.module;
205  bmodule = infoTwo.module;
206 
207  fsensor = infoOne.module_sensor_id;
208  bsensor = infoTwo.module_sensor_id;
209 
210  if (fside == bside) {
211  return -1;
212  }
213 
214  if (bplane != fplane) {
215  return -1;
216  }
217  if (bmodule != fmodule) {
218  return -1;
219  }
220 
221  // 0to5
222  if (fsensor == 0 && bsensor == 5) {
223  smalloverlap = 0;
224  }
225  // 3to8
226  else if (fsensor == 3 && bsensor == 8) {
227  smalloverlap = 1;
228  }
229  // 4to9
230  else if (fsensor == 4 && bsensor == 9) {
231  smalloverlap = 2;
232  }
233  // 3to6
234  else if (fsensor == 3 && bsensor == 6) {
235  smalloverlap = 3;
236  }
237  // 1to8
238  else if (fsensor == 1 && bsensor == 8) {
239  smalloverlap = 4;
240  }
241  // 2to8
242  else if (fsensor == 2 && bsensor == 8) {
243  smalloverlap = 5;
244  }
245  // 2to9
246  else if (fsensor == 2 && bsensor == 9) {
247  smalloverlap = 6;
248  }
249  // 3to7
250  else if (fsensor == 3 && bsensor == 7) {
251  smalloverlap = 7;
252  }
253  // 4to7
254  else if (fsensor == 4 && bsensor == 7) {
255  smalloverlap = 8;
256  }
257  return 1000 * fhalf + 100 * fplane + 10 * fmodule + smalloverlap;
258 }
259 
261 
262  TString actPath = fGeoManager->GetPath();
263 
264  fGeoManager->cd(lmd_root_path.c_str());
265  TGeoHMatrix *matrix = (TGeoHMatrix *) (fGeoManager->GetCurrentNode()->GetMatrix());
266 
267  if (actPath != "" && actPath != " ") fGeoManager->cd(actPath);
268 
269  return *matrix;
270 }
271 
273  return getMatrixPndGlobalToLmdLocal().Inverse();
274 }
275 
276 bool PndLmdGeometryHelper::isOverlappingArea(const int id1, const int id2) {
277 
278  int fhalf, fplane, fmodule, fside, fsensor;
279  int bhalf, bplane, bmodule, bside, bsensor;
280 
281  auto &infoOne = getHitLocationInfo(id1);
282  auto &infoTwo = getHitLocationInfo(id2);
283 
284  fhalf = infoOne.detector_half;
285  bhalf = infoTwo.detector_half;
286 
287  //the necessities for overlapping, must be on same half, plane, module and other side
288  if (bhalf != fhalf) {
289  return false;
290  }
291 
292  fside = infoOne.module_side;
293  bside = infoTwo.module_side;
294 
295  fplane = infoOne.plane;
296  bplane = infoTwo.plane;
297 
298  fmodule = infoOne.module;
299  bmodule = infoTwo.module;
300 
301  fsensor = infoOne.module_sensor_id;
302  bsensor = infoTwo.module_sensor_id;
303 
304  if (bplane != fplane) {
305  return false;
306  }
307  if (bmodule != fmodule) {
308  return false;
309  }
310  if (bside == fside) {
311  return false;
312  }
313 
314  //0to5
315  if (fsensor == 0 && bsensor == 5) {
316  return true;
317  }
318  //3to8
319  if (fsensor == 3 && bsensor == 8) {
320  return true;
321  }
322  //4to9
323  if (fsensor == 4 && bsensor == 9) {
324  return true;
325  }
326  //3to6
327  if (fsensor == 3 && bsensor == 6) {
328  return true;
329  }
330  //1to8
331  if (fsensor == 1 && bsensor == 8) {
332  return true;
333  }
334  //2to8
335  if (fsensor == 2 && bsensor == 8) {
336  return true;
337  }
338  //2to9
339  if (fsensor == 2 && bsensor == 9) {
340  return true;
341  }
342  //3to7
343  if (fsensor == 3 && bsensor == 7) {
344  return true;
345  }
346  //4to7
347  if (fsensor == 4 && bsensor == 7) {
348  return true;
349  }
350  //all other checks are negative? then the sensors don't overlap!
351  return false;
352 }
353 
354 std::vector<std::string> PndLmdGeometryHelper::getAllAlignPaths(bool sensors, bool modules, bool planes,
355  bool halfs, bool detector) {
356 
357  std::vector<std::string> result;
358  auto all_volume_paths = getAllAlignableVolumePaths();
359 
360  std::vector<std::string> filter_strings;
361 
362  if (detector) filter_strings.push_back(navigation_paths[0].first);
363  if (halfs) filter_strings.push_back(navigation_paths[1].first);
364  if (planes) filter_strings.push_back(navigation_paths[2].first);
365  if (modules) filter_strings.push_back(navigation_paths[3].first);
366  if (sensors) filter_strings.push_back(navigation_paths[4].first);
367 
368  std::cout << "total number of alignable volumes: " << all_volume_paths.size() << std::endl;
369 
370  for (auto filter_string : filter_strings) {
371  auto found(all_volume_paths.begin());
372  while (found != all_volume_paths.end()) {
373  found = std::find_if(found, all_volume_paths.end(), [&](const std::string& s) {
374  std::stringstream reg_exp;
375  reg_exp<<"^.*/" << filter_string << "_(\\d+)/*$";
376  std::smatch match;
377  return std::regex_search(s, match, std::regex(reg_exp.str()));
378  });
379 
380  if (found != all_volume_paths.end()) {
381  result.push_back(*found);
382  ++found;
383  }
384  }
385  }
386 
387  // just for fun and so it's easier to examine it
388  std::sort(result.begin(), result.end());
389 
390  return result;
391 }
392 
393 std::vector<std::string> PndLmdGeometryHelper::getAllAlignableVolumePaths() const {
394  TGeoNode* node = fGeoManager->GetTopNode();
395 
396  std::vector<std::string> alignable_volumes;
397 
398  if (fGeoManager->GetNAlignable() > 0) {
399  for (int i = 0; i < fGeoManager->GetNAlignable(); ++i) {
400  TGeoPNEntry* entry = fGeoManager->GetAlignableEntry(i);
401  if (entry) alignable_volumes.push_back(entry->GetPath());
402  }
403  }
404  else {
405  std::vector<std::pair<TGeoNode*, std::string> > current_paths;
406  current_paths.push_back(std::make_pair(node, fGeoManager->GetPath()));
407 
408  while (current_paths.size() > 0) {
409  auto temp_current_paths = current_paths;
410  current_paths.clear();
411  for (auto const curpath : temp_current_paths) {
412  std::stringstream reg_exp;
413  for (auto nav_path : navigation_paths) {
414  reg_exp << "/" + nav_path.first << "_(\\d+)";
415  std::smatch match;
416  if (std::regex_search(curpath.second, match, std::regex(reg_exp.str() + "/*$"))) {
417  if (nav_path.second) alignable_volumes.push_back(curpath.second);
418  break;
419  }
420  }
421  for (int i = 0; i < curpath.first->GetNdaughters(); ++i) {
422  node = curpath.first->GetDaughter(i);
423  std::stringstream full_path;
424  full_path << curpath.second << "/" << node->GetName();
425  current_paths.push_back(std::make_pair(node, full_path.str()));
426  }
427  }
428  }
429  }
430  return alignable_volumes;
431 }
432 
TVector3 transformPndGlobalToSensor(const TVector3 &vec, int sensorId)
PndLmdHitLocationInfo translateVolumePathToHitLocationInfo(const std::string &volume_path) const
static std::vector< int > getAvailableOverlapIDs()
Int_t i
Definition: run_full.C:25
const PndLmdHitLocationInfo & createMappingEntry(int sensor_id)
TLorentzVector s
Definition: Pnd2DStar.C:50
std::vector< std::pair< std::string, bool > > navigation_paths
TString GetPath(Int_t shortID)
for a given shortID the path is returned
const TGeoHMatrix getMatrixSensorToPndGlobal(const int sensorId)
std::vector< std::string > getAllAlignPaths(bool sensors=true, bool modules=false, bool planes=false, bool halfs=false, bool detector=false)
std::vector< std::string > getAllAlignableVolumePaths() const
std::map< std::string, PndLmdHitLocationInfo > volume_path_to_hit_info_mapping
Class to access the naming information of the MVD.
const TGeoHMatrix getMatrixPndGlobalToLmdLocal()
Double_t
const TGeoHMatrix getMatrixPndGlobalToSensor(const int sensorId)
const PndLmdHitLocationInfo & getHitLocationInfo(const std::string &volume_path)
Bool_t cd(Int_t id)
as the cd command of TGeoManager just with the ID
Int_t GetShortID(TString path)
for a given path the (unique) position of the sensor path in the fSensorNamePar-List is given...
static PndGeoHandling * Instance()
std::map< int, PndLmdHitLocationInfo > sensor_id_to_hit_info_mapping
const TGeoHMatrix getMatrixLmdLocalToPndGlobal()
TGeoHMatrix * global
boost::property_tree::ptree geometry_properties
TVector3 transformPndGlobalToLmdLocal(const TVector3 &vec)
int getOverlapIdFromSensorIDs(int id1, int id2)
bool isOverlappingArea(const int id1, const int id2)