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