All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
sbncode/sbncode/GeometryTools/CRTGeoAlg.cc
Go to the documentation of this file.
1 #include "CRTGeoAlg.h"
2 
3 namespace sbn{
4 
5 // Constructor - get values from the auxdet geometry service
7  CRTGeoAlg::CRTGeoAlg(lar::providerFrom<geo::Geometry>(), ((const geo::AuxDetGeometry*)&(*art::ServiceHandle<geo::AuxDetGeometry>()))->GetProviderPtr())
8 {}
9 
12  fAuxDetGeoCore = auxdet_geometry;
13 
14  // Keep track of which objects we've recorded
15  std::vector<std::string> usedTaggers;
16  std::vector<std::string> usedModules;
17  std::vector<std::string> usedStrips;
18 
19  // Get the auxdets (strip arrays for some reason)
20  const std::vector<geo::AuxDetGeo>& auxDets = fAuxDetGeoCore->AuxDetGeoVec();
21 
22  int ad_i = 0;
23  // Loop over them
24  for(auto const& auxDet : auxDets){
25 
26  int sv_i = 0;
27  // Loop over the strips in the arrays
28  for(size_t i = 0; i < auxDet.NSensitiveVolume(); i++){
29 
30  // Get the geometry object for the strip
31  geo::AuxDetSensitiveGeo const& auxDetSensitive = auxDet.SensitiveVolume(i);
32  std::set<std::string> volNames = {auxDetSensitive.TotalVolume()->GetName()};
33  std::vector<std::vector<TGeoNode const*>> paths = fGeometryService->FindAllVolumePaths(volNames);
34 
35  // Build up a path that ROOT understands
36  std::string path = "";
37  for (size_t inode = 0; inode < paths.at(0).size(); inode++){
38  path += paths.at(0).at(inode)->GetName();
39  if(inode < paths.at(0).size() - 1){
40  path += "/";
41  }
42  }
43 
44  // Access the path
45  TGeoManager* manager = fGeometryService->ROOTGeoManager();
46  manager->cd(path.c_str());
47 
48  // Get all of the things we're intersted in in the path
49  TGeoNode* nodeStrip = manager->GetCurrentNode();
50  TGeoNode* nodeModule = manager->GetMother(2);
51  TGeoNode* nodeTagger = manager->GetMother(3);
52  TGeoNode* nodeDet = manager->GetMother(4);
53 
54  // Fill the tagger information
55  std::string taggerName = nodeTagger->GetName();
56  if(std::find(usedTaggers.begin(), usedTaggers.end(), taggerName) == usedTaggers.end()){
57  usedTaggers.push_back(taggerName);
58 
59  // Get the limits in local coords
60  double halfWidth = ((TGeoBBox*)nodeTagger->GetVolume()->GetShape())->GetDX();
61  double halfHeight = ((TGeoBBox*)nodeTagger->GetVolume()->GetShape())->GetDY();
62  double halfLength = ((TGeoBBox*)nodeTagger->GetVolume()->GetShape())->GetDZ()/2;
63 
64  // Transform those limits to world coords
65  double limits[3] = {halfWidth, halfHeight, halfLength};
66  double limitsDet[3];
67  nodeTagger->LocalToMaster(limits, limitsDet);
68  double limitsWorld[3];
69  nodeDet->LocalToMaster(limitsDet, limitsWorld);
70 
71  double limits2[3] = {-halfWidth, -halfHeight, -halfLength};
72  double limitsDet2[3];
73  nodeTagger->LocalToMaster(limits2, limitsDet2);
74  double limitsWorld2[3];
75  nodeDet->LocalToMaster(limitsDet2, limitsWorld2);
76 
77  // Create a tagger geometry object
78  CRTTaggerGeo tagger = {};
79  tagger.name = taggerName;
80  tagger.minX = std::min(limitsWorld[0], limitsWorld2[0]);
81  tagger.maxX = std::max(limitsWorld[0], limitsWorld2[0]);
82  tagger.minY = std::min(limitsWorld[1], limitsWorld2[1]);
83  tagger.maxY = std::max(limitsWorld[1], limitsWorld2[1]);
84  tagger.minZ = std::min(limitsWorld[2], limitsWorld2[2]);
85  tagger.maxZ = std::max(limitsWorld[2], limitsWorld2[2]);
86  tagger.null = false;
87  fTaggers[taggerName] = tagger;
88  }
89 
90  // Fill the module information
91  std::string moduleName = nodeModule->GetName();
92  if(std::find(usedModules.begin(), usedModules.end(), moduleName) == usedModules.end()){
93  usedModules.push_back(moduleName);
94 
95  // Technically the auxdet is the strip array but this is basically the same as the module
96  // Get the limits in local coordinates
97  double halfWidth = auxDet.HalfWidth1();
98  double halfHeight = auxDet.HalfHeight();
99  double halfLength = auxDet.Length()/2;
100 
101  // Transform to world coordinates
102  double limits[3] = {halfWidth, halfHeight, halfLength};
103  double limitsWorld[3];
104  auxDet.LocalToWorld(limits, limitsWorld);
105 
106  double limits2[3] = {-halfWidth, -halfHeight, -halfLength};
107  double limitsWorld2[3];
108  auxDet.LocalToWorld(limits2, limitsWorld2);
109 
110  // Determine which plane the module is in in the tagger (XY configuration)
111  double origin[3] = {0, 0, 0};
112  double modulePosMother[3];
113  nodeModule->LocalToMaster(origin, modulePosMother);
114  size_t planeID = (modulePosMother[2] > 0);
115  // Are the sipms at the top or bottom
116  bool top = (planeID == 1) ? (modulePosMother[1] > 0) : (modulePosMother[0] < 0);
117 
118  // Create a module geometry object
119  CRTModuleGeo module = {};
120  module.name = moduleName;
121  module.auxDetID = ad_i;
122  module.minX = std::min(limitsWorld[0], limitsWorld2[0]);
123  module.maxX = std::max(limitsWorld[0], limitsWorld2[0]);
124  module.minY = std::min(limitsWorld[1], limitsWorld2[1]);
125  module.maxY = std::max(limitsWorld[1], limitsWorld2[1]);
126  module.minZ = std::min(limitsWorld[2], limitsWorld2[2]);
127  module.maxZ = std::max(limitsWorld[2], limitsWorld2[2]);
128  module.normal = auxDet.GetNormalVector();
129  module.null = false;
130  module.planeID = planeID;
131  module.top = top;
132  module.tagger = taggerName;
133  fModules[moduleName] = module;
134  }
135 
136  // Fill the strip information
137  std::string stripName = nodeStrip->GetName();
138  if(std::find(usedStrips.begin(), usedStrips.end(), stripName) == usedStrips.end()){
139  usedStrips.push_back(stripName);
140 
141  // Get the limits in local coordinates
142  double halfWidth = auxDetSensitive.HalfWidth1();
143  double halfHeight = auxDetSensitive.HalfHeight();
144  double halfLength = auxDetSensitive.Length()/2;
145 
146  // Transform to world coordinates
147  double limits[3] = {halfWidth, halfHeight, halfLength};
148  double limitsWorld[3];
149  auxDetSensitive.LocalToWorld(limits, limitsWorld);
150 
151  double limits2[3] = {-halfWidth, -halfHeight, -halfLength};
152  double limitsWorld2[3];
153  auxDetSensitive.LocalToWorld(limits2, limitsWorld2);
154 
155  // Create a strip geometry object
156  CRTStripGeo strip = {};
157  strip.name = stripName;
158  strip.sensitiveVolumeID = sv_i;
159  strip.minX = std::min(limitsWorld[0], limitsWorld2[0]);
160  strip.maxX = std::max(limitsWorld[0], limitsWorld2[0]);
161  strip.minY = std::min(limitsWorld[1], limitsWorld2[1]);
162  strip.maxY = std::max(limitsWorld[1], limitsWorld2[1]);
163  strip.minZ = std::min(limitsWorld[2], limitsWorld2[2]);
164  strip.maxZ = std::max(limitsWorld[2], limitsWorld2[2]);
165  strip.normal = auxDetSensitive.GetNormalVector();
166  strip.width = halfWidth * 2.;
167  strip.null = false;
168  strip.module = moduleName;
169 
170  // Create a sipm geometry object
171  uint32_t channel0 = 32 * ad_i + 2 * sv_i + 0;
172  uint32_t channel1 = 32 * ad_i + 2 * sv_i + 1;
173  // Sipm0 is on the left in local coords
174  double sipm0X = -halfWidth;
175  double sipm1X = halfWidth;
176  // In local coordinates the Y position is at half height (top if top) (bottom if not)
177  double sipmY = halfHeight;
178  if(!fModules[moduleName].top) sipmY = - halfHeight;
179  double sipm0XYZ[3] = {sipm0X, sipmY, 0};
180  double sipm0XYZWorld[3];
181  auxDetSensitive.LocalToWorld(sipm0XYZ, sipm0XYZWorld);
182 
183  CRTSipmGeo sipm0 = {};
184  sipm0.channel = channel0;
185  sipm0.x = sipm0XYZWorld[0];
186  sipm0.y = sipm0XYZWorld[1];
187  sipm0.z = sipm0XYZWorld[2];
188  sipm0.strip = stripName;
189  sipm0.null = false;
190  fSipms[channel0] = sipm0;
191 
192  double sipm1XYZ[3] = {sipm1X, sipmY, 0};
193  double sipm1XYZWorld[3];
194  auxDetSensitive.LocalToWorld(sipm1XYZ, sipm1XYZWorld);
195 
196  CRTSipmGeo sipm1 = {};
197  sipm1.channel = channel1;
198  sipm1.x = sipm1XYZWorld[0];
199  sipm1.y = sipm1XYZWorld[1];
200  sipm1.z = sipm1XYZWorld[2];
201  sipm1.strip = stripName;
202  sipm1.null = false;
203  fSipms[channel1] = sipm1;
204 
205  strip.sipms = std::make_pair(channel0, channel1);
206  fStrips[stripName] = strip;
207  // Add the strip to the relevant module
208  fModules[moduleName].strips[stripName] = strip;
209  }
210  sv_i++;
211  }
212  ad_i++;
213  }
214 
215  // Need to fill the tagger modules after all the strip associations have been made
216  // Loop over the modules
217  for(auto const& module : fModules){
218  // Fill the tagger map
219  std::string taggerName = module.second.tagger;
220  std::string moduleName = module.second.name;
221  fTaggers[taggerName].modules[moduleName] = module.second;
222  }
223 
224 }
225 
226 
228 
229 }
230 
231 // ----------------------------------------------------------------------------------
232 // Return the volume enclosed by the whole CRT system
233 std::vector<double> CRTGeoAlg::CRTLimits() const {
234  std::vector<double> limits;
235 
236  std::vector<double> minXs;
237  std::vector<double> minYs;
238  std::vector<double> minZs;
239  std::vector<double> maxXs;
240  std::vector<double> maxYs;
241  std::vector<double> maxZs;
242  for(auto const& tagger : fTaggers){
243  minXs.push_back(tagger.second.minX);
244  minYs.push_back(tagger.second.minY);
245  minZs.push_back(tagger.second.minZ);
246  maxXs.push_back(tagger.second.maxX);
247  maxYs.push_back(tagger.second.maxY);
248  maxZs.push_back(tagger.second.maxZ);
249  }
250  limits.push_back(*std::min_element(minXs.begin(), minXs.end()));
251  limits.push_back(*std::min_element(minYs.begin(), minYs.end()));
252  limits.push_back(*std::min_element(minZs.begin(), minZs.end()));
253  limits.push_back(*std::max_element(maxXs.begin(), maxXs.end()));
254  limits.push_back(*std::max_element(maxYs.begin(), maxYs.end()));
255  limits.push_back(*std::max_element(maxZs.begin(), maxZs.end()));
256 
257  return limits;
258 }
259 
260 // ----------------------------------------------------------------------------------
261 // Get the number of taggers in the geometry
262 size_t CRTGeoAlg::NumTaggers() const{
263  return fTaggers.size();
264 }
265 
266 
267 // ----------------------------------------------------------------------------------
268 // Get the total number of modules in the geometry
269 size_t CRTGeoAlg::NumModules() const{
270  return fModules.size();
271 }
272 
273 // Get the number of modules in a tagger by name
274 size_t CRTGeoAlg::NumModules(std::string taggerName) const{
275  CRTTaggerGeo tagger = GetTagger(taggerName);
276  if(!tagger.null) return tagger.modules.size();
277  return 0;
278 }
279 
280 // Get the number of modules in a tagger by index
281 size_t CRTGeoAlg::NumModules(size_t tagger_i) const{
282  CRTTaggerGeo tagger = GetTagger(tagger_i);
283  if(!tagger.null) return tagger.modules.size();
284  return 0;
285 }
286 
287 
288 // ----------------------------------------------------------------------------------
289 // Get the total number of strips in the geometry
290 size_t CRTGeoAlg::NumStrips() const{
291  return fStrips.size();
292 }
293 
294 // Get the number of strips in module by name
295 size_t CRTGeoAlg::NumStrips(std::string moduleName) const{
296  CRTModuleGeo module = GetModule(moduleName);
297  if(!module.null) return module.strips.size();
298  return 0;
299 }
300 
301 // Get the number of strips in module by global index
302 size_t CRTGeoAlg::NumStrips(size_t module_i) const{
303  CRTModuleGeo module = GetModule(module_i);
304  if(!module.null) return module.strips.size();
305  return 0;
306 }
307 
308 // Get the number of strips in module by tagger index and local module index
309 size_t CRTGeoAlg::NumStrips(size_t tagger_i, size_t module_i) const{
310  CRTModuleGeo module = GetModule(tagger_i, module_i);
311  if(!module.null) return module.strips.size();
312  return 0;
313 }
314 
315 // ----------------------------------------------------------------------------------
316 // Get the tagger geometry object by name
317 CRTTaggerGeo CRTGeoAlg::GetTagger(std::string taggerName) const{
318  for(auto const& tagger : fTaggers){
319  if(taggerName == tagger.first) return tagger.second;
320  }
321  CRTTaggerGeo nullTagger = {};
322  nullTagger.null = true;
323  return nullTagger;
324 }
325 
326 // Get the tagger geometry object by index
327 CRTTaggerGeo CRTGeoAlg::GetTagger(size_t tagger_i) const{
328  size_t index = 0;
329  for(auto const& tagger : fTaggers){
330  if(tagger_i == index) return tagger.second;
331  index++;
332  }
333  CRTTaggerGeo nullTagger = {};
334  nullTagger.null = true;
335  return nullTagger;
336 }
337 
338 
339 // ----------------------------------------------------------------------------------
340 // Get the module geometry object by name
341 CRTModuleGeo CRTGeoAlg::GetModule(std::string moduleName) const{
342  for(auto const& module : fModules){
343  if(moduleName == module.first) return module.second;
344  }
345  CRTModuleGeo nullModule = {};
346  nullModule.null = true;
347  return nullModule;
348 }
349 
350 // Get the module geometry object by global index
351 CRTModuleGeo CRTGeoAlg::GetModule(size_t module_i) const{
352  size_t index = 0;
353  for(auto const& module : fModules){
354  if(module_i == index) return module.second;
355  index++;
356  }
357  CRTModuleGeo nullModule = {};
358  nullModule.null = true;
359  return nullModule;
360 }
361 
362 // Get the module geometry object by tagger index and local module index
363 CRTModuleGeo CRTGeoAlg::GetModule(size_t tagger_i, size_t module_i) const{
364  CRTModuleGeo nullModule = {};
365  nullModule.null = true;
366 
367  CRTTaggerGeo tagger = GetTagger(tagger_i);
368  if(tagger.null) return nullModule;
369 
370  size_t index = 0;
371  for(auto const& module : tagger.modules){
372  if(module_i == index) return module.second;
373  index++;
374  }
375  return nullModule;
376 }
377 
378 
379 // ----------------------------------------------------------------------------------
380 // Get the strip geometry object by name
381 CRTStripGeo CRTGeoAlg::GetStrip(std::string stripName) const{
382  for(auto const& strip : fStrips){
383  if(stripName == strip.first) return strip.second;
384  }
385  CRTStripGeo nullStrip = {};
386  nullStrip.null = true;
387  return nullStrip;
388 }
389 
390 // Get the strip geometry object by global index
391 CRTStripGeo CRTGeoAlg::GetStrip(size_t strip_i) const{
392  size_t index = 0;
393  for(auto const& strip : fStrips){
394  if(strip_i == index) return strip.second;
395  index++;
396  }
397  CRTStripGeo nullStrip = {};
398  nullStrip.null = true;
399  return nullStrip;
400 }
401 
402 // Get the strip geometry object by global module index and local strip index
403 CRTStripGeo CRTGeoAlg::GetStrip(size_t module_i, size_t strip_i) const{
404  CRTStripGeo nullStrip = {};
405  nullStrip.null = true;
406 
407  CRTModuleGeo module = GetModule(module_i);
408  if(module.null) return nullStrip;
409 
410  size_t index = 0;
411  for(auto const& strip : module.strips){
412  if(strip_i == index) return strip.second;
413  index++;
414  }
415  return nullStrip;
416 }
417 
418 // Get the strip geometry object by tagger index, local module index and local strip index
419 CRTStripGeo CRTGeoAlg::GetStrip(size_t tagger_i, size_t module_i, size_t strip_i) const{
420  CRTStripGeo nullStrip = {};
421  nullStrip.null = true;
422 
423  CRTModuleGeo module = GetModule(tagger_i, module_i);
424  if(module.null) return nullStrip;
425 
426  size_t index = 0;
427  for(auto const& strip : module.strips){
428  if(strip_i == index) return strip.second;
429  index++;
430  }
431  return nullStrip;
432 }
433 
434 
435 // Get the tagger name from strip or module name
436 std::string CRTGeoAlg::GetTaggerName(std::string name) const{
437  if(fModules.find(name) != fModules.end()){
438  return fModules.at(name).tagger;
439  }
440  if(fStrips.find(name) != fStrips.end()){
441  return fModules.at(fStrips.at(name).module).tagger;
442  }
443  return "";
444 }
445 
446 // Get the name of the strip from the SiPM channel ID
447 std::string CRTGeoAlg::ChannelToStripName(size_t channel) const{
448  for(auto const& sipm : fSipms){
449  if(sipm.second.channel == channel){
450  return sipm.second.strip;
451  }
452  }
453  return "";
454 }
455 
456 
457 // Recalculate strip limits including charge sharing
458 std::vector<double> CRTGeoAlg::StripLimitsWithChargeSharing(std::string stripName, double x, double ex){
459  int module = fModules.at(fStrips.at(stripName).module).auxDetID;
460  std::string moduleName = fGeometryService->AuxDet(module).TotalVolume()->GetName();
461  auto const& sensitiveGeo = fAuxDetGeoCore->ChannelToAuxDetSensitive(moduleName,
462  2*fStrips.at(stripName).sensitiveVolumeID);
463 
464  double halfWidth = sensitiveGeo.HalfWidth1();
465  double halfHeight = sensitiveGeo.HalfHeight();
466  double halfLength = sensitiveGeo.HalfLength();
467 
468  // Get the maximum strip limits in world coordinates
469  double l1[3] = {-halfWidth + x + ex, halfHeight, halfLength};
470  double w1[3];
471  sensitiveGeo.LocalToWorld(l1, w1);
472 
473  // Get the minimum strip limits in world coordinates
474  double l2[3] = {-halfWidth + x - ex, -halfHeight, -halfLength};
475  double w2[3];
476  sensitiveGeo.LocalToWorld(l2, w2);
477 
478  // Use this to get the limits in the two variable directions
479  std::vector<double> limits = {std::min(w1[0],w2[0]), std::max(w1[0],w2[0]),
480  std::min(w1[1],w2[1]), std::max(w1[1],w2[1]),
481  std::min(w1[2],w2[2]), std::max(w1[2],w2[2])};
482  return limits;
483 }
484 
485 // Get the world position of Sipm from the channel ID
487  for(auto const& sipm : fSipms){
488  if(sipm.second.channel == channel){
489  geo::Point_t position {sipm.second.x, sipm.second.y, sipm.second.z};
490  return position;
491  }
492  }
493  geo::Point_t null {-99999, -99999, -99999};
494  return null;
495 }
496 
497 // Get the sipm channels on a strip
498 std::pair<int, int> CRTGeoAlg::GetStripSipmChannels(std::string stripName) const{
499  for(auto const& strip : fStrips){
500  if(stripName == strip.first) return strip.second.sipms;
501  }
502  return std::make_pair(-99999, -99999);
503 }
504 
505 // Return the distance to a sipm in the plane of the sipms
506 double CRTGeoAlg::DistanceBetweenSipms(geo::Point_t position, size_t channel) const{
507  double distance = -99999;
508 
509  for(auto const& sipm : fSipms){
510  if(sipm.second.channel == channel){
511  geo::Point_t pos {sipm.second.x, sipm.second.y, sipm.second.z};
512  // Get the other sipm
513  int otherChannel = channel + 1;
514  if(channel % 2) otherChannel = channel - 1;
515  // Work out which coordinate is different
516  if(fSipms.at(otherChannel).x != pos.X()) distance = position.X() - pos.X();
517  if(fSipms.at(otherChannel).y != pos.Y()) distance = position.Y() - pos.Y();
518  if(fSipms.at(otherChannel).z != pos.Z()) distance = position.Z() - pos.Z();
519  // Return distance in that coordinate
520  return distance;
521  }
522  }
523  return distance;
524 }
525 
526 // Returns max distance from sipms in strip
527 double CRTGeoAlg::DistanceBetweenSipms(geo::Point_t position, std::string stripName) const{
528  std::pair<int, int> sipms = GetStripSipmChannels(stripName);
529  double sipmDist = std::max(DistanceBetweenSipms(position, sipms.first), DistanceBetweenSipms(position, sipms.second));
530  return sipmDist;
531 }
532 
533 // Return the distance along the strip (from sipm end)
534 double CRTGeoAlg::DistanceDownStrip(geo::Point_t position, std::string stripName) const{
535  double distance = -99999;
536  for(auto const& strip : fStrips){
537  if(stripName == strip.first){
538  geo::Point_t pos = ChannelToSipmPosition(strip.second.sipms.first);
539  // Work out the longest dimension of strip
540  double xdiff = std::abs(strip.second.maxX-strip.second.minX);
541  double ydiff = std::abs(strip.second.maxY-strip.second.minY);
542  double zdiff = std::abs(strip.second.maxZ-strip.second.minZ);
543  if(xdiff > ydiff && xdiff > zdiff) distance = position.X() - pos.X();
544  if(ydiff > xdiff && ydiff > zdiff) distance = position.Y() - pos.Y();
545  if(zdiff > xdiff && zdiff > ydiff) distance = position.Z() - pos.Z();
546  return std::abs(distance);
547  }
548  }
549  return distance;
550 }
551 
552 // ----------------------------------------------------------------------------------
553 // Determine if a point is inside CRT volume
554 bool CRTGeoAlg::IsInsideCRT(TVector3 point){
555  geo::Point_t pt {point.X(), point.Y(), point.Z()};
556  return IsInsideCRT(pt);
557 }
558 
560  std::vector<double> limits = CRTLimits();
561  if(point.X() > limits[0] && point.Y() > limits[1] && point.Z() > limits[2]
562  && point.X() < limits[3] && point.Y() < limits[4] && point.Z() < limits[5]){
563  return true;
564  }
565  return false;
566 }
567 
568 // ----------------------------------------------------------------------------------
569 // Determine if a point is inside a tagger by name
570 bool CRTGeoAlg::IsInsideTagger(std::string taggerName, geo::Point_t point){
571  CRTTaggerGeo tagger = GetTagger(taggerName);
572  return IsInsideTagger(tagger, point);
573 }
574 
576  if(tagger.null) return false;
577  double x = point.X();
578  double y = point.Y();
579  double z = point.Z();
580  double xmin = tagger.minX;
581  double ymin = tagger.minY;
582  double zmin = tagger.minZ;
583  double xmax = tagger.maxX;
584  double ymax = tagger.maxY;
585  double zmax = tagger.maxZ;
586  if(x > xmin && x < xmax && y > ymin && y < ymax && z > zmin && z < zmax) return true;
587  return false;
588 }
589 
590 // ----------------------------------------------------------------------------------
591 // Determine if a point is inside a module by name
592 bool CRTGeoAlg::IsInsideModule(std::string moduleName, geo::Point_t point){
593  CRTModuleGeo module = GetModule(moduleName);
594  return IsInsideModule(module, point);
595 }
596 
598  if(module.null) return false;
599  double x = point.X();
600  double y = point.Y();
601  double z = point.Z();
602  double xmin = module.minX;
603  double ymin = module.minY;
604  double zmin = module.minZ;
605  double xmax = module.maxX;
606  double ymax = module.maxY;
607  double zmax = module.maxZ;
608  // Make the width limits a bit more generous to account for steps in true trajectory
609  /*if(std::abs(xmax-xmin)==1){ xmin-=1; xmax+=1; }
610  if(std::abs(ymax-ymin)==1){ ymin-=1; ymax+=1; }
611  if(std::abs(zmax-zmin)==1){ zmin-=1; zmax+=1; }*/
612  if(x > xmin && x < xmax && y > ymin && y < ymax && z > zmin && z < zmax) return true;
613  return false;
614 }
615 
616 // ----------------------------------------------------------------------------------
617 // Determine if a point is inside a strip by name
618 bool CRTGeoAlg::IsInsideStrip(std::string stripName, geo::Point_t point){
619  CRTStripGeo strip = GetStrip(stripName);
620  return IsInsideStrip(strip, point);
621 }
622 
624  if(strip.null) return false;
625  double x = point.X();
626  double y = point.Y();
627  double z = point.Z();
628  double xmin = strip.minX;
629  double ymin = strip.minY;
630  double zmin = strip.minZ;
631  double xmax = strip.maxX;
632  double ymax = strip.maxY;
633  double zmax = strip.maxZ;
634  // Make the width limits a bit more generous to account for steps in true trajectory
635  /*if(std::abs(xmax-xmin)==1){ xmin-=0.5; xmax+=0.5; }
636  if(std::abs(ymax-ymin)==1){ ymin-=0.5; ymax+=0.5; }
637  if(std::abs(zmax-zmin)==1){ zmin-=0.5; zmax+=0.5; }*/
638  if(x > xmin && x < xmax && y > ymin && y < ymax && z > zmin && z < zmax) return true;
639  return false;
640 }
641 
642 // ----------------------------------------------------------------------------------
643 // Check if two modules overlap in 2D
644 bool CRTGeoAlg::CheckOverlap(const CRTModuleGeo& module1, const CRTModuleGeo& module2){
645  // Get the minimum and maximum X, Y, Z coordinates
646  double minX = std::max(module1.minX, module2.minX);
647  double maxX = std::min(module1.maxX, module2.maxX);
648  double minY = std::max(module1.minY, module2.minY);
649  double maxY = std::min(module1.maxY, module2.maxY);
650  double minZ = std::max(module1.minZ, module2.minZ);
651  double maxZ = std::min(module1.maxZ, module2.maxZ);
652 
653  // If the two strips overlap in 2 dimensions then return true
654  if ((minX<maxX && minY<maxY) || (minX<maxX && minZ<maxZ) || (minY<maxY && minZ<maxZ)) return true;
655  // Otherwise return a "null" value
656  return false;
657 }
658 
659 // ----------------------------------------------------------------------------------
660 // Check is a module overlaps with a perpendicual module in the same tagger
662  // Record plane of mother module
663  size_t planeID = module.planeID;
664  // Get mother tagger of module
665  std::string taggerName = module.tagger;
666  // Loop over other modules in tagger
667  for(auto const& module2 : fTaggers[taggerName].modules){
668  // If in other plane loop over strips
669  if(module2.second.planeID == planeID) continue;
670  // Check for overlaps
671  if(CheckOverlap(module, module2.second)) return true;
672  }
673  return false;
674 }
675 
676 bool CRTGeoAlg::StripHasOverlap(std::string stripName){
677  return HasOverlap(fModules.at(fStrips.at(stripName).module));
678 }
679 
680 std::vector<double> CRTGeoAlg::StripOverlap(std::string strip1Name, std::string strip2Name){
681  auto const& strip1 = fStrips.at(strip1Name);
682  auto const& strip2 = fStrips.at(strip2Name);
683 
684  double minX = std::max(strip1.minX, strip2.minX);
685  double maxX = std::min(strip1.maxX, strip2.maxY);
686  double minY = std::max(strip1.minY, strip2.minY);
687  double maxY = std::min(strip1.maxY, strip2.maxY);
688  double minZ = std::max(strip1.minZ, strip2.minZ);
689  double maxZ = std::min(strip1.maxZ, strip2.maxZ);
690 
691  std::vector<double> null = {-99999, -99999, -99999, -99999, -99999, -99999};
692  std::vector<double> overlap = {minX, maxX, minY, maxY, minZ, maxZ};
693 
694  // If the two strips overlap in 2 dimensions then return the overlap
695  if ((minX<maxX && minY<maxY) || (minX<maxX && minZ<maxZ) || (minY<maxY && minZ<maxZ)) return overlap;
696  // Otherwise return a "null" value
697  return null;
698 }
699 
700 // ----------------------------------------------------------------------------------
701 // Find the average of the tagger entry and exit points of a true particle trajectory
702 geo::Point_t CRTGeoAlg::TaggerCrossingPoint(std::string taggerName, const simb::MCParticle& particle){
703  const CRTTaggerGeo& tagger = fTaggers.at(taggerName);
704  return TaggerCrossingPoint(tagger, particle);
705 }
706 
707 geo::Point_t CRTGeoAlg::TaggerCrossingPoint(const CRTTaggerGeo& tagger, const simb::MCParticle& particle){
708  geo::Point_t entry {-99999, -99999, -99999};
709  geo::Point_t exit {-99999, -99999, -99999};
710 
711  bool first = true;
712  for(size_t i = 0; i < particle.NumberTrajectoryPoints(); i++){
713  geo::Point_t point {particle.Vx(i), particle.Vy(i), particle.Vz(i)};
714  if(!IsInsideTagger(tagger, point)) continue;
715  if(first){
716  entry = point;
717  first = false;
718  }
719  exit = point;
720  }
721 
722  geo::Point_t cross {(entry.X()+exit.X())/2., (entry.Y()+exit.Y())/2., (entry.Z()+exit.Z())/2};
723  return cross;
724 }
725 
726 bool CRTGeoAlg::CrossesTagger(const CRTTaggerGeo& tagger, const simb::MCParticle& particle){
727  for(size_t i = 0; i < particle.NumberTrajectoryPoints(); i++){
728  geo::Point_t point {particle.Vx(i), particle.Vy(i), particle.Vz(i)};
729  if(IsInsideTagger(tagger, point)) return true;
730  }
731  return false;
732 }
733 
734 // ----------------------------------------------------------------------------------
735 // Find the average of the module entry and exit points of a true particle trajectory
736 geo::Point_t CRTGeoAlg::ModuleCrossingPoint(std::string moduleName, const simb::MCParticle& particle){
737  const CRTModuleGeo& module = fModules.at(moduleName);
738  return ModuleCrossingPoint(module, particle);
739 }
740 
741 geo::Point_t CRTGeoAlg::ModuleCrossingPoint(const CRTModuleGeo& module, const simb::MCParticle& particle){
742  geo::Point_t entry {-99999, -99999, -99999};
743  geo::Point_t exit {-99999, -99999, -99999};
744 
745  bool first = true;
746  for(size_t i = 0; i < particle.NumberTrajectoryPoints(); i++){
747  geo::Point_t point {particle.Vx(i), particle.Vy(i), particle.Vz(i)};
748  if(!IsInsideModule(module, point)){
749  // Look at the mid point
750  if(i == particle.NumberTrajectoryPoints()-1) continue;
751  geo::Point_t next {particle.Vx(i+1), particle.Vy(i+1), particle.Vz(i+1)};
752  geo::Point_t mid {(point.X()+next.X())/2, (point.Y()+next.Y())/2, (point.Z()+next.Z())/2};
753  if(!IsInsideModule(module, mid)) continue;
754  point = mid;
755  }
756  if(first){
757  entry = point;
758  first = false;
759  }
760  exit = point;
761 
762  if(i == particle.NumberTrajectoryPoints()-1) continue;
763  geo::Point_t next {particle.Vx(i+1), particle.Vy(i+1), particle.Vz(i+1)};
764  geo::Point_t mid {(point.X()+next.X())/2, (point.Y()+next.Y())/2, (point.Z()+next.Z())/2};
765  if(!IsInsideModule(module, mid)) continue;
766  exit = mid;
767  }
768 
769  geo::Point_t cross {(entry.X()+exit.X())/2., (entry.Y()+exit.Y())/2., (entry.Z()+exit.Z())/2};
770  return cross;
771 }
772 
773 bool CRTGeoAlg::CrossesModule(const CRTModuleGeo& module, const simb::MCParticle& particle){
774  for(size_t i = 0; i < particle.NumberTrajectoryPoints(); i++){
775  geo::Point_t point {particle.Vx(i), particle.Vy(i), particle.Vz(i)};
776  if(IsInsideModule(module, point)) return true;
777 
778  // Also look at midpoint with next point
779  if(i == particle.NumberTrajectoryPoints()-1) continue;
780  geo::Point_t next {particle.Vx(i+1), particle.Vy(i+1), particle.Vz(i+1)};
781  geo::Point_t mid {(point.X()+next.X())/2, (point.Y()+next.Y())/2, (point.Z()+next.Z())/2};
782  if(IsInsideModule(module, mid)) return true;
783  }
784  return false;
785 }
786 
787 // ----------------------------------------------------------------------------------
788 // Find the average of the strip entry and exit points of a true particle trajectory
789 geo::Point_t CRTGeoAlg::StripCrossingPoint(std::string stripName, const simb::MCParticle& particle){
790  const CRTStripGeo& strip = fStrips.at(stripName);
791  return StripCrossingPoint(strip, particle);
792 }
793 
794 geo::Point_t CRTGeoAlg::StripCrossingPoint(const CRTStripGeo& strip, const simb::MCParticle& particle){
795  geo::Point_t entry {-99999, -99999, -99999};
796  geo::Point_t exit {-99999, -99999, -99999};
797 
798  bool first = true;
799  for(size_t i = 0; i < particle.NumberTrajectoryPoints(); i++){
800  geo::Point_t point {particle.Vx(i), particle.Vy(i), particle.Vz(i)};
801  if(!IsInsideStrip(strip, point)){
802  if(i == particle.NumberTrajectoryPoints()-1) continue;
803  geo::Point_t next {particle.Vx(i+1), particle.Vy(i+1), particle.Vz(i+1)};
804  geo::Point_t mid {(point.X()+next.X())/2, (point.Y()+next.Y())/2, (point.Z()+next.Z())/2};
805  if(!IsInsideStrip(strip, mid)) continue;
806  point = mid;
807  }
808  if(first){
809  entry = point;
810  first = false;
811  }
812  exit = point;
813  if(i == particle.NumberTrajectoryPoints()-1) continue;
814  geo::Point_t next {particle.Vx(i+1), particle.Vy(i+1), particle.Vz(i+1)};
815  geo::Point_t mid {(point.X()+next.X())/2, (point.Y()+next.Y())/2, (point.Z()+next.Z())/2};
816  if(!IsInsideStrip(strip, mid)) continue;
817  exit = mid;
818  }
819 
820  geo::Point_t cross {(entry.X()+exit.X())/2., (entry.Y()+exit.Y())/2., (entry.Z()+exit.Z())/2};
821  return cross;
822 }
823 
824 bool CRTGeoAlg::CrossesStrip(const CRTStripGeo& strip, const simb::MCParticle& particle){
825  for(size_t i = 0; i < particle.NumberTrajectoryPoints(); i++){
826  geo::Point_t point {particle.Vx(i), particle.Vy(i), particle.Vz(i)};
827  if(IsInsideStrip(strip, point)) return true;
828 
829  // Also look at midpoint with next point
830  if(i == particle.NumberTrajectoryPoints()-1) continue;
831  geo::Point_t next {particle.Vx(i+1), particle.Vy(i+1), particle.Vz(i+1)};
832  geo::Point_t mid {(point.X()+next.X())/2, (point.Y()+next.Y())/2, (point.Z()+next.Z())/2};
833  if(IsInsideStrip(strip, mid)) return true;
834  }
835  return false;
836 }
837 
838 
839 // ----------------------------------------------------------------------------------
840 // Work out which strips the true particle crosses
841 std::vector<std::string> CRTGeoAlg::CrossesStrips(const simb::MCParticle& particle){
842  std::vector<std::string> stripNames;
843  for(auto const& tagger : fTaggers){
844  if(!CrossesTagger(tagger.second, particle)) continue;
845  for(auto const& module : tagger.second.modules){
846  if(!CrossesModule(module.second, particle)) continue;
847  for(auto const& strip : module.second.strips){
848  if(!CrossesStrip(strip.second, particle)) continue;
849  if(std::find(stripNames.begin(), stripNames.end(), strip.first) != stripNames.end()) continue;
850  stripNames.push_back(strip.first);
851  }
852  }
853  }
854  return stripNames;
855 }
856 
857 
858 // ----------------------------------------------------------------------------------
859 // Find the angle of true particle trajectory to tagger
860 double CRTGeoAlg::AngleToTagger(std::string taggerName, const simb::MCParticle& particle){
861  // Get normal to tagger using the top modules
862  TVector3 normal (0,0,0);
863  for(auto const& module : GetTagger(taggerName).modules){
864  normal.SetXYZ(module.second.normal.X(), module.second.normal.Y(), module.second.normal.Z());
865  break;
866  }
867  //FIXME this is pretty horrible
868  if(normal.X()<0.5 && normal.X()>-0.5) normal.SetX(0);
869  if(normal.Y()<0.5 && normal.Y()>-0.5) normal.SetY(0);
870  if(normal.Z()<0.5 && normal.Z()>-0.5) normal.SetZ(0);
871 
872  if(std::abs(normal.X())==1 && GetTagger(taggerName).minX < 0) normal.SetX(-1);
873  if(std::abs(normal.X())==1 && GetTagger(taggerName).minX > 0) normal.SetX(1);
874  if(std::abs(normal.Y())==1 && GetTagger(taggerName).minY < 0) normal.SetY(-1);
875  if(std::abs(normal.Y())==1 && GetTagger(taggerName).minY > 0) normal.SetY(1);
876  if(std::abs(normal.Z())==1 && GetTagger(taggerName).minZ < 0) normal.SetZ(-1);
877  if(std::abs(normal.Z())==1 && GetTagger(taggerName).minZ > 0) normal.SetZ(1);
878 
879  TVector3 start (particle.Vx(), particle.Vy(), particle.Vz());
880  TVector3 end (particle.EndX(), particle.EndY(), particle.EndZ());
881  TVector3 diff = end - start;
882 
883  if(normal.X() == 1 && start.X() > end.X()) diff = start - end;
884  if(normal.X() == -1 && start.X() < end.X()) diff = start - end;
885  if(normal.Y() == 1 && start.Y() > end.Y()) diff = start - end;
886  if(normal.Y() == -1 && start.Y() < end.Y()) diff = start - end;
887  if(normal.Z() == 1 && start.Z() > end.Z()) diff = start - end;
888  if(normal.Z() == -1 && start.Z() < end.Z()) diff = start - end;
889 
890  return normal.Angle(diff);
891 }
892 
893 
894 // ----------------------------------------------------------------------------------
895 // Check if a particle enters the CRT volume
896 bool CRTGeoAlg::EntersVolume(const simb::MCParticle& particle){
897  bool enters = false;
898  bool startOutside = false;
899  bool endOutside = false;
900  std::vector<double> limits = CRTLimits();
901  for(size_t i = 0; i < particle.NumberTrajectoryPoints(); i++){
902  geo::Point_t point {particle.Vx(i), particle.Vy(i), particle.Vz(i)};
903  if(IsInsideCRT(point)){
904  enters = true;
905  }
906  else if(i == 0) startOutside = true;
907  else if(i == particle.NumberTrajectoryPoints()-1) endOutside = true;
908  }
909  if(enters && (startOutside || endOutside)) return true;
910  return false;
911 }
912 
913 // ----------------------------------------------------------------------------------
914 // Check if a particle crosses the CRT volume
915 bool CRTGeoAlg::CrossesVolume(const simb::MCParticle& particle){
916  bool enters = false;
917  bool startOutside = false;
918  bool endOutside = false;
919  std::vector<double> limits = CRTLimits();
920  for(size_t i = 0; i < particle.NumberTrajectoryPoints(); i++){
921  geo::Point_t point {particle.Vx(i), particle.Vy(i), particle.Vz(i)};
922  if(IsInsideCRT(point)){
923  enters = true;
924  }
925  else if(i == 0) startOutside = true;
926  else if(i == particle.NumberTrajectoryPoints()-1) endOutside = true;
927  }
928  if(startOutside && enters && endOutside) return true;
929  return false;
930 }
931 
932 
933 // ----------------------------------------------------------------------------------
934 // Determine if a particle would be able to produce a hit in a tagger
935 bool CRTGeoAlg::ValidCrossingPoint(std::string taggerName, const simb::MCParticle& particle){
936 
937  // Get all the crossed strips in the tagger
938  std::vector<std::string> crossedModules;
939  for(auto const& module : fTaggers[taggerName].modules){
940  geo::Point_t crossPoint = ModuleCrossingPoint(module.second.name, particle);
941  if(crossPoint.X() != -99999) crossedModules.push_back(module.second.name);
942  }
943 
944  // Check if the strip has a possible overlap, return true if not
945  for(size_t i = 0; i < crossedModules.size(); i++){
946  if(!HasOverlap(fModules[crossedModules[i]])) return true;
947  // Check if any of the crossed strips overlap, return true if they do
948  for(size_t j = i; j < crossedModules.size(); j++){
949  if(CheckOverlap(fModules[crossedModules[i]], fModules[crossedModules[j]])) return true;
950  }
951  }
952  return false;
953 }
954 
955 }
956 
geo::Point_t ModuleCrossingPoint(std::string moduleName, const simb::MCParticle &particle)
process_name opflash particleana ie ie ie z
bool CrossesStrip(const CRTStripGeo &strip, const simb::MCParticle &particle)
std::map< std::string, CRTModuleGeo > fModules
geo::Point_t ChannelToSipmPosition(size_t channel) const
finds tracks best matching by with limits
bool StripHasOverlap(std::string stripName)
const geo::GeometryCore * geometry
process_name opflash particleana ie x
geo::Vector_t GetNormalVector() const
Returns the unit normal vector to the detector.
T::provider_type const * providerFrom()
Returns a constant pointer to the provider of specified service.
Definition: ServiceUtil.h:77
bool CrossesVolume(const simb::MCParticle &particle)
bool IsInsideModule(std::string moduleName, geo::Point_t point)
double AngleToTagger(std::string taggerName, const simb::MCParticle &particle)
bool HasOverlap(const CRTModuleGeo &module)
std::map< std::string, CRTTaggerGeo > fTaggers
services AuxDetGeometry
std::string GetTaggerName(std::string name) const
bool IsInsideStrip(std::string stripName, geo::Point_t point)
Description of geometry of one set of auxiliary detectors.
TGeoManager * ROOTGeoManager() const
Access to the ROOT geometry description manager.
std::map< std::string, CRTModuleGeo > modules
std::map< std::string, CRTStripGeo > fStrips
std::map< int, CRTSipmGeo > fSipms
process_name pandoraGausCryo1 vertexChargeCryo1 vertexStubCryo1 xmin
BEGIN_PROLOG triggeremu_data_config_icarus settings PMTADCthresholds sequence::icarus_stage0_multiTPC_TPC physics sequence::icarus_stage0_EastHits_TPC physics sequence::icarus_stage0_WestHits_TPC physics producers purityana0 caloskimCalorimetryCryoE physics caloskimCalorimetryCryoW physics path
walls no top
Definition: selectors.fcl:105
geo::Point_t TaggerCrossingPoint(std::string taggerName, const simb::MCParticle &particle)
T abs(T value)
process_name opflash particleana ie ie y
double distance(geo::Point_t const &point, CathodeDesc_t const &cathode)
Returns the distance of a point from the cathode.
bool IsInsideTagger(std::string taggerName, geo::Point_t point)
const AuxDetSensitiveGeo & ChannelToAuxDetSensitive(std::string const &auxDetName, uint32_t const &channel) const
const TGeoVolume * TotalVolume() const
auto end(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:585
CRTModuleGeo GetModule(std::string moduleName) const
std::string ChannelToStripName(size_t channel) const
std::vector< double > StripLimitsWithChargeSharing(std::string stripName, double x, double ex)
Description of geometry of one entire detector.
bool EntersVolume(const simb::MCParticle &particle)
std::map< std::string, CRTStripGeo > strips
AuxDetGeo const & AuxDet(unsigned int const ad=0) const
Returns the specified auxiliary detector.
double DistanceDownStrip(geo::Point_t position, std::string stripName) const
double DistanceBetweenSipms(geo::Point_t position, size_t channel) const
bool CrossesTagger(const CRTTaggerGeo &tagger, const simb::MCParticle &particle)
geo::GeometryCore const * fGeometryService
CRTTaggerGeo GetTagger(std::string taggerName) const
std::pair< int, int > GetStripSipmChannels(std::string stripName) const
std::vector< AuxDetGeo > const & AuxDetGeoVec() const
Returns the full list of pointer to the auxiliary detectors.
geo::Point_t StripCrossingPoint(std::string stripName, const simb::MCParticle &particle)
const geo::AuxDetGeometryCore * fAuxDetGeoCore
const TGeoVolume * TotalVolume() const
Definition: AuxDetGeo.h:106
bool CheckOverlap(const CRTModuleGeo &module1, const CRTModuleGeo &module2)
then echo fcl name
CRTStripGeo GetStrip(std::string stripName) const
std::vector< std::vector< TGeoNode const * > > FindAllVolumePaths(std::set< std::string > const &vol_names) const
Returns paths of all nodes with volumes with the specified names.
std::vector< double > StripOverlap(std::string strip1Name, std::string strip2Name)
Vector cross(Vector const &a, Vector const &b)
Return cross product of two vectors.
void LocalToWorld(const double *auxdet, double *world) const
Transform point from local auxiliary detector frame to world frame.
bool ValidCrossingPoint(std::string taggerName, const simb::MCParticle &particle)
std::vector< double > CRTLimits() const
std::vector< std::string > CrossesStrips(const simb::MCParticle &particle)
bool CrossesModule(const CRTModuleGeo &module, const simb::MCParticle &particle)
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
Definition: geo_vectors.h:184
constexpr Point origin()
Returns a origin position with a point of the specified type.
Definition: geo_vectors.h:227