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