LArPandoraGeometry.cxx
Go to the documentation of this file.
1 /**
2  * @file larpandora/LArPandoraInterface/LArPandoraGeometry.cxx
3  *
4  * @brief Helper functions for extracting detector geometry for use in reconsruction
5  */
6 
7 #include "cetlib_except/exception.h"
8 
13 
16 
17 #include <iomanip>
18 #include <set>
19 
20 namespace lar_pandora {
21 
22  void
24  const bool useActiveBoundingBox)
25  {
26  // Detector gaps can only be loaded once - throw an exception if the output lists are already filled
27  if (!listOfGaps.empty())
28  throw cet::exception("LArPandora")
29  << " LArPandoraGeometry::LoadDetectorGaps --- the list of gaps already exists ";
30 
31  // Loop over drift volumes and write out the dead regions at their boundaries
32  LArDriftVolumeList driftVolumeList;
33  LArPandoraGeometry::LoadGeometry(driftVolumeList, useActiveBoundingBox);
34 
36 
37  for (LArDriftVolumeList::const_iterator iter1 = driftVolumeList.begin(),
38  iterEnd1 = driftVolumeList.end();
39  iter1 != iterEnd1;
40  ++iter1) {
41  const LArDriftVolume& driftVolume1 = *iter1;
42 
43  for (LArDriftVolumeList::const_iterator iter2 = iter1, iterEnd2 = driftVolumeList.end();
44  iter2 != iterEnd2;
45  ++iter2) {
46  const LArDriftVolume& driftVolume2 = *iter2;
47 
48  if (driftVolume1.GetVolumeID() == driftVolume2.GetVolumeID()) continue;
49 
50  const float maxDisplacement(LArDetectorGap::GetMaxGapSize());
51 
52  const float deltaX(std::fabs(driftVolume1.GetCenterX() - driftVolume2.GetCenterX()));
53  const float deltaY(std::fabs(driftVolume1.GetCenterY() - driftVolume2.GetCenterY()));
54  const float deltaZ(std::fabs(driftVolume1.GetCenterZ() - driftVolume2.GetCenterZ()));
55 
56  const float widthX(0.5f * (driftVolume1.GetWidthX() + driftVolume2.GetWidthX()));
57  const float widthY(0.5f * (driftVolume1.GetWidthY() + driftVolume2.GetWidthY()));
58  const float widthZ(0.5f * (driftVolume1.GetWidthZ() + driftVolume2.GetWidthZ()));
59 
60  const float gapX(deltaX - widthX);
61  const float gapY(deltaY - widthY);
62  const float gapZ(deltaZ - widthZ);
63 
64  const float X1((driftVolume1.GetCenterX() < driftVolume2.GetCenterX()) ?
65  (driftVolume1.GetCenterX() + 0.5f * driftVolume1.GetWidthX()) :
66  (driftVolume2.GetCenterX() + 0.5f * driftVolume2.GetWidthX()));
67  const float X2((driftVolume1.GetCenterX() > driftVolume2.GetCenterX()) ?
68  (driftVolume1.GetCenterX() - 0.5f * driftVolume1.GetWidthX()) :
69  (driftVolume2.GetCenterX() - 0.5f * driftVolume2.GetWidthX()));
70  const float Y1(std::min((driftVolume1.GetCenterY() - 0.5f * driftVolume1.GetWidthY()),
71  (driftVolume2.GetCenterY() - 0.5f * driftVolume2.GetWidthY())));
72  const float Y2(std::max((driftVolume1.GetCenterY() + 0.5f * driftVolume1.GetWidthY()),
73  (driftVolume2.GetCenterY() + 0.5f * driftVolume2.GetWidthY())));
74  const float Z1(std::min((driftVolume1.GetCenterZ() - 0.5f * driftVolume1.GetWidthZ()),
75  (driftVolume2.GetCenterZ() - 0.5f * driftVolume2.GetWidthZ())));
76  const float Z2(std::max((driftVolume1.GetCenterZ() + 0.5f * driftVolume1.GetWidthZ()),
77  (driftVolume2.GetCenterZ() + 0.5f * driftVolume2.GetWidthZ())));
78 
79  geo::Vector_t gaps(gapX, gapY, gapZ), deltas(deltaX, deltaY, deltaZ);
80  if (detType->CheckDetectorGapSize(gaps, deltas, maxDisplacement)) {
81  geo::Point_t point1(X1, Y1, Z1), point2(X2, Y2, Z2);
82  geo::Vector_t widths(widthX, widthY, widthZ);
83  listOfGaps.emplace_back(detType->CreateDetectorGap(point1, point2, widths));
84  }
85  }
86 
87  detType->LoadDaughterDetectorGaps(driftVolume1, LArDetectorGap::GetMaxGapSize(), listOfGaps);
88  }
89  }
90 
91  //------------------------------------------------------------------------------------------------------------------------------------------
92 
93  void
95  LArDriftVolumeMap& outputVolumeMap,
96  const bool useActiveBoundingBox)
97  {
98  if (!outputVolumeList.empty())
99  throw cet::exception("LArPandora")
100  << " LArPandoraGeometry::LoadGeometry --- the list of drift volumes already exists ";
101 
102  LArPandoraGeometry::LoadGeometry(outputVolumeList, useActiveBoundingBox);
103 
104  // Create mapping between tpc/cstat labels and drift volumes
105  for (const LArDriftVolume& driftVolume : outputVolumeList) {
106  for (const LArDaughterDriftVolume& tpcVolume : driftVolume.GetTpcVolumeList()) {
107  (void)outputVolumeMap.insert(LArDriftVolumeMap::value_type(
108  LArPandoraGeometry::GetTpcID(tpcVolume.GetCryostat(), tpcVolume.GetTpc()), driftVolume));
109  }
110  }
111  }
112 
113  //------------------------------------------------------------------------------------------------------------------------------------------
114 
115  unsigned int
117  const unsigned int cstat,
118  const unsigned int tpc)
119  {
120  if (driftVolumeMap.empty())
121  throw cet::exception("LArPandora")
122  << " LArPandoraGeometry::GetVolumeID --- detector geometry map is empty";
123 
125  driftVolumeMap.find(LArPandoraGeometry::GetTpcID(cstat, tpc));
126 
127  if (driftVolumeMap.end() == iter)
128  throw cet::exception("LArPandora")
129  << " LArPandoraGeometry::GetVolumeID --- found a TPC that doesn't belong to a drift volume";
130 
131  return iter->second.GetVolumeID();
132  }
133 
134  //------------------------------------------------------------------------------------------------------------------------------------------
135 
136  unsigned int
138  const unsigned int cstat,
139  const unsigned int tpc)
140  {
141  if (driftVolumeMap.empty())
142  throw cet::exception("LArPandora")
143  << " LArPandoraGeometry::GetDaughterVolumeID --- detector geometry map is empty";
144 
146  driftVolumeMap.find(LArPandoraGeometry::GetTpcID(cstat, tpc));
147 
148  if (driftVolumeMap.end() == iter)
149  throw cet::exception("LArPandora") << " LArPandoraGeometry::GetDaughterVolumeID --- found a "
150  "TPC volume that doesn't belong to a drift volume";
151 
153  iterDghtr = iter->second.GetTpcVolumeList().begin(),
154  iterDghtrEnd = iter->second.GetTpcVolumeList().end();
155  iterDghtr != iterDghtrEnd;
156  ++iterDghtr) {
157  const LArDaughterDriftVolume& daughterVolume(*iterDghtr);
158  if (cstat == daughterVolume.GetCryostat() && tpc == daughterVolume.GetTpc())
159  return std::distance(iter->second.GetTpcVolumeList().begin(), iterDghtr);
160  }
161  throw cet::exception("LArPandora")
162  << " LArPandoraGeometry::GetDaughterVolumeID --- found a daughter volume that doesn't belong "
163  "to the drift volume ";
164  }
165 
166  //------------------------------------------------------------------------------------------------------------------------------------------
167 
169  LArPandoraGeometry::GetGlobalView(const unsigned int cstat,
170  const unsigned int tpc,
171  const geo::View_t hit_View)
172  {
173  const bool switchUV(LArPandoraGeometry::ShouldSwitchUV(cstat, tpc));
174 
175  // ATTN This implicitly assumes that there will be u, v and (maybe) one of either w or y views
176  if ((hit_View == geo::kW) || (hit_View == geo::kY)) { return hit_View; }
177  else if (hit_View == geo::kU) {
178  return (switchUV ? geo::kV : geo::kU);
179  }
180  else if (hit_View == geo::kV) {
181  return (switchUV ? geo::kU : geo::kV);
182  }
183  else {
184  throw cet::exception("LArPandora")
185  << " LArPandoraGeometry::GetGlobalView --- found an unknown plane view (not U, V or W) ";
186  }
187  }
188 
189  //------------------------------------------------------------------------------------------------------------------------------------------
190 
191  unsigned int
192  LArPandoraGeometry::GetTpcID(const unsigned int cstat, const unsigned int tpc)
193  {
194  // We assume there will never be more than 10000 TPCs in a cryostat!
195  if (tpc >= 10000)
196  throw cet::exception("LArPandora")
197  << " LArPandoraGeometry::GetTpcID --- found a TPC with an ID greater than 10000 ";
198 
199  return ((10000 * cstat) + tpc);
200  }
201 
202  //------------------------------------------------------------------------------------------------------------------------------------------
203 
204  bool
205  LArPandoraGeometry::ShouldSwitchUV(const unsigned int cstat, const unsigned int tpc)
206  {
207  // We determine whether U and V views should be switched by checking the drift direction
209  const geo::TPCGeo& theTpc(theGeometry->TPC(tpc, cstat));
210 
211  const bool isPositiveDrift(theTpc.DriftDirection() == geo::kPosX);
212  return LArPandoraGeometry::ShouldSwitchUV(isPositiveDrift);
213  }
214 
215  //------------------------------------------------------------------------------------------------------------------------------------------
216 
217  bool
218  LArPandoraGeometry::ShouldSwitchUV(const bool isPositiveDrift)
219  {
220  // ATTN: In the dual phase scenario the wire planes pointing along two orthogonal directions and so interchanging U and V is unnecessary
222  if (theGeometry->MaxPlanes() == 2) return false;
223 
224  // We assume that all multiple drift volume detectors have the APA - CPA - APA - CPA design
225  return isPositiveDrift;
226  }
227 
228  //------------------------------------------------------------------------------------------------------------------------------------------
229 
230  void
232  const bool useActiveBoundingBox)
233  {
234  // This method will group TPCs into "drift volumes" (these are regions of the detector that share a common drift direction,
235  // common range of x coordinates, and common detector parameters such as wire pitch and wire angle).
236  if (!driftVolumeList.empty())
237  throw cet::exception("LArPandora")
238  << " LArPandoraGeometry::LoadGeometry --- detector geometry has already been loaded ";
239 
240  typedef std::set<unsigned int> UIntSet;
241 
242  // Pandora requires three independent images, and ability to correlate features between images (via wire angles and transformation plugin).
245  const float wirePitchU(detType->WirePitchU());
246  const float wirePitchV(detType->WirePitchV());
247  const float wirePitchW(detType->WirePitchW());
248  const float maxDeltaTheta(0.01f); // leave this hard-coded for now
249 
250  // Loop over cryostats
251  for (unsigned int icstat = 0; icstat < theGeometry->Ncryostats(); ++icstat) {
252  UIntSet cstatList;
253 
254  // Loop over TPCs in in this cryostat
255  for (unsigned int itpc1 = 0; itpc1 < theGeometry->NTPC(icstat); ++itpc1) {
256  if (cstatList.end() != cstatList.find(itpc1)) continue;
257 
258  // Use this TPC to seed a drift volume
259  const geo::TPCGeo& theTpc1(theGeometry->TPC(itpc1, icstat));
260  cstatList.insert(itpc1);
261 
262  const float wireAngleU(detType->WireAngleU(itpc1, icstat));
263  const float wireAngleV(detType->WireAngleV(itpc1, icstat));
264  const float wireAngleW(detType->WireAngleW(itpc1, icstat));
265 
266  double localCoord1[3] = {0., 0., 0.};
267  double worldCoord1[3] = {0., 0., 0.};
268  theTpc1.LocalToWorld(localCoord1, worldCoord1);
269 
270  float driftMinX(useActiveBoundingBox ? theTpc1.ActiveBoundingBox().MinX() :
271  (worldCoord1[0] - theTpc1.ActiveHalfWidth()));
272  float driftMaxX(useActiveBoundingBox ? theTpc1.ActiveBoundingBox().MaxX() :
273  (worldCoord1[0] + theTpc1.ActiveHalfWidth()));
274  float driftMinY(useActiveBoundingBox ? theTpc1.ActiveBoundingBox().MinY() :
275  (worldCoord1[1] - theTpc1.ActiveHalfHeight()));
276  float driftMaxY(useActiveBoundingBox ? theTpc1.ActiveBoundingBox().MaxY() :
277  (worldCoord1[1] + theTpc1.ActiveHalfHeight()));
278  float driftMinZ(useActiveBoundingBox ? theTpc1.ActiveBoundingBox().MinZ() :
279  (worldCoord1[2] - 0.5f * theTpc1.ActiveLength()));
280  float driftMaxZ(useActiveBoundingBox ? theTpc1.ActiveBoundingBox().MaxZ() :
281  (worldCoord1[2] + 0.5f * theTpc1.ActiveLength()));
282 
283  const double min1(
284  useActiveBoundingBox ?
285  (0.5 * (driftMinX + driftMaxX) - 0.25 * std::fabs(driftMaxX - driftMinX)) :
286  (worldCoord1[0] - 0.5 * theTpc1.ActiveHalfWidth()));
287  const double max1(
288  useActiveBoundingBox ?
289  (0.5 * (driftMinX + driftMaxX) + 0.25 * std::fabs(driftMaxX - driftMinX)) :
290  (worldCoord1[0] + 0.5 * theTpc1.ActiveHalfWidth()));
291 
292  const bool isPositiveDrift(theTpc1.DriftDirection() == geo::kPosX);
293 
294  UIntSet tpcList;
295  tpcList.insert(itpc1);
296 
297  LArDaughterDriftVolumeList tpcVolumeList;
298  tpcVolumeList.emplace_back(LArDaughterDriftVolume(icstat,
299  itpc1,
300  0.5f * (driftMaxX + driftMinX),
301  0.5f * (driftMaxY + driftMinY),
302  0.5f * (driftMaxZ + driftMinZ),
303  (driftMaxX - driftMinX),
304  (driftMaxY - driftMinY),
305  (driftMaxZ - driftMinZ)));
306 
307  // Now identify the other TPCs associated with this drift volume
308  for (unsigned int itpc2 = itpc1 + 1; itpc2 < theGeometry->NTPC(icstat); ++itpc2) {
309  if (cstatList.end() != cstatList.find(itpc2)) continue;
310 
311  const geo::TPCGeo& theTpc2(theGeometry->TPC(itpc2, icstat));
312 
313  if (theTpc1.DriftDirection() != theTpc2.DriftDirection()) continue;
314 
315  const float dThetaU(detType->WireAngleU(itpc1, icstat) -
316  detType->WireAngleU(itpc2, icstat));
317  const float dThetaV(detType->WireAngleV(itpc1, icstat) -
318  detType->WireAngleV(itpc2, icstat));
319  const float dThetaW(detType->WireAngleW(itpc1, icstat) -
320  detType->WireAngleW(itpc2, icstat));
321  if (dThetaU > maxDeltaTheta || dThetaV > maxDeltaTheta || dThetaW > maxDeltaTheta)
322  continue;
323 
324  double localCoord2[3] = {0., 0., 0.};
325  double worldCoord2[3] = {0., 0., 0.};
326  theTpc2.LocalToWorld(localCoord2, worldCoord2);
327 
328  const float driftMinX2(useActiveBoundingBox ?
329  theTpc2.ActiveBoundingBox().MinX() :
330  (worldCoord2[0] - theTpc2.ActiveHalfWidth()));
331  const float driftMaxX2(useActiveBoundingBox ?
332  theTpc2.ActiveBoundingBox().MaxX() :
333  (worldCoord2[0] + theTpc2.ActiveHalfWidth()));
334 
335  const double min2(
336  useActiveBoundingBox ?
337  (0.5 * (driftMinX2 + driftMaxX2) - 0.25 * std::fabs(driftMaxX2 - driftMinX2)) :
338  (worldCoord2[0] - 0.5 * theTpc2.ActiveHalfWidth()));
339  const double max2(
340  useActiveBoundingBox ?
341  (0.5 * (driftMinX2 + driftMaxX2) + 0.25 * std::fabs(driftMaxX2 - driftMinX2)) :
342  (worldCoord2[0] + 0.5 * theTpc2.ActiveHalfWidth()));
343 
344  if ((min2 > max1) || (min1 > max2)) continue;
345 
346  cstatList.insert(itpc2);
347  tpcList.insert(itpc2);
348 
349  const float driftMinY2(useActiveBoundingBox ?
350  theTpc2.ActiveBoundingBox().MinY() :
351  (worldCoord2[1] - theTpc2.ActiveHalfHeight()));
352  const float driftMaxY2(useActiveBoundingBox ?
353  theTpc2.ActiveBoundingBox().MaxY() :
354  (worldCoord2[1] + theTpc2.ActiveHalfHeight()));
355  const float driftMinZ2(useActiveBoundingBox ?
356  theTpc2.ActiveBoundingBox().MinZ() :
357  (worldCoord2[2] - 0.5f * theTpc2.ActiveLength()));
358  const float driftMaxZ2(useActiveBoundingBox ?
359  theTpc2.ActiveBoundingBox().MaxZ() :
360  (worldCoord2[2] + 0.5f * theTpc2.ActiveLength()));
361 
362  driftMinX = std::min(driftMinX, driftMinX2);
363  driftMaxX = std::max(driftMaxX, driftMaxX2);
364  driftMinY = std::min(driftMinY, driftMinY2);
365  driftMaxY = std::max(driftMaxY, driftMaxY2);
366  driftMinZ = std::min(driftMinZ, driftMinZ2);
367  driftMaxZ = std::max(driftMaxZ, driftMaxZ2);
368 
369  tpcVolumeList.emplace_back(LArDaughterDriftVolume(icstat,
370  itpc2,
371  0.5f * (driftMaxX2 + driftMinX2),
372  0.5f * (driftMaxY2 + driftMinY2),
373  0.5f * (driftMaxZ2 + driftMinZ2),
374  (driftMaxX2 - driftMinX2),
375  (driftMaxY2 - driftMinY2),
376  (driftMaxZ2 - driftMinZ2)));
377  }
378 
379  // Create new daughter drift volume (volume ID = 0 to N-1)
380  driftVolumeList.emplace_back(driftVolumeList.size(),
381  isPositiveDrift,
382  wirePitchU,
383  wirePitchV,
384  wirePitchW,
385  wireAngleU,
386  wireAngleV,
387  wireAngleW,
388  0.5f * (driftMaxX + driftMinX),
389  0.5f * (driftMaxY + driftMinY),
390  0.5f * (driftMaxZ + driftMinZ),
391  (driftMaxX - driftMinX),
392  (driftMaxY - driftMinY),
393  (driftMaxZ - driftMinZ),
394  (wirePitchU + wirePitchV + wirePitchW + 0.1f),
395  tpcVolumeList);
396  }
397  }
398 
399  if (driftVolumeList.empty())
400  throw cet::exception("LArPandora") << " LArPandoraGeometry::LoadGeometry --- failed to find "
401  "any drift volumes in this detector geometry ";
402  }
403 
404  //------------------------------------------------------------------------------------------------------------------------------------------
405 
406  void
408  LArDriftVolumeList& daughterVolumeList)
409  {
410  // This method will create one or more daughter volumes (these share a common drift orientation along the X-axis,
411  // have parallel or near-parallel wire angles, and similar wire pitches)
412  //
413  // ATTN: we assume that the U and V planes have equal and opposite wire orientations
414 
415  if (!daughterVolumeList.empty())
416  throw cet::exception("LArPandora") << " LArPandoraGeometry::LoadGlobalDaughterGeometry --- "
417  "daughter geometry has already been loaded ";
418 
419  if (driftVolumeList.empty())
420  throw cet::exception("LArPandora") << " LArPandoraGeometry::LoadGlobalDaughterGeometry --- "
421  "detector geometry has not yet been loaded ";
422 
423  std::cout << "The size of the drif list is: " << driftVolumeList.size() << std::endl;
424  int count(0);
425  // Create daughter drift volumes
426  for (const LArDriftVolume& driftVolume : driftVolumeList) {
427  std::cout << "Looking at dau vol: " << count++ << std::endl;
428  const bool switchViews(LArPandoraGeometry::ShouldSwitchUV(driftVolume.IsPositiveDrift()));
429 
430  const float daughterWirePitchU(switchViews ? driftVolume.GetWirePitchV() :
431  driftVolume.GetWirePitchU());
432  const float daughterWirePitchV(switchViews ? driftVolume.GetWirePitchU() :
433  driftVolume.GetWirePitchV());
434  const float daughterWirePitchW(driftVolume.GetWirePitchW());
435  const float daughterWireAngleU(switchViews ? driftVolume.GetWireAngleV() :
436  driftVolume.GetWireAngleU());
437  const float daughterWireAngleV(switchViews ? driftVolume.GetWireAngleU() :
438  driftVolume.GetWireAngleV());
439  const float daughterWireAngleW(driftVolume.GetWireAngleW());
440 
441  daughterVolumeList.push_back(LArDriftVolume(driftVolume.GetVolumeID(),
442  driftVolume.IsPositiveDrift(),
443  daughterWirePitchU,
444  daughterWirePitchV,
445  daughterWirePitchW,
446  daughterWireAngleU,
447  daughterWireAngleV,
448  daughterWireAngleW,
449  driftVolume.GetCenterX(),
450  driftVolume.GetCenterY(),
451  driftVolume.GetCenterZ(),
452  driftVolume.GetWidthX(),
453  driftVolume.GetWidthY(),
454  driftVolume.GetWidthZ(),
455  driftVolume.GetSigmaUVZ(),
456  driftVolume.GetTpcVolumeList()));
457  }
458 
459  if (daughterVolumeList.empty())
460  throw cet::exception("LArPandora") << " LArPandoraGeometry::LoadGlobalDaughterGeometry --- "
461  "failed to create daughter geometry list ";
462  }
463 
464  //------------------------------------------------------------------------------------------------------------------------------------------
465  //------------------------------------------------------------------------------------------------------------------------------------------
466 
467  LArDriftVolume::LArDriftVolume(const unsigned int volumeID,
468  const bool isPositiveDrift,
469  const float wirePitchU,
470  const float wirePitchV,
471  const float wirePitchW,
472  const float wireAngleU,
473  const float wireAngleV,
474  const float wireAngleW,
475  const float centerX,
476  const float centerY,
477  const float centerZ,
478  const float widthX,
479  const float widthY,
480  const float widthZ,
481  const float sigmaUVZ,
482  const LArDaughterDriftVolumeList& tpcVolumeList)
483  : m_volumeID(volumeID)
484  , m_isPositiveDrift(isPositiveDrift)
485  , m_wirePitchU(wirePitchU)
486  , m_wirePitchV(wirePitchV)
487  , m_wirePitchW(wirePitchW)
488  , m_wireAngleU(wireAngleU)
489  , m_wireAngleV(wireAngleV)
490  , m_wireAngleW(wireAngleW)
491  , m_centerX(centerX)
492  , m_centerY(centerY)
493  , m_centerZ(centerZ)
494  , m_widthX(widthX)
495  , m_widthY(widthY)
496  , m_widthZ(widthZ)
497  , m_sigmaUVZ(sigmaUVZ)
498  , m_tpcVolumeList(tpcVolumeList)
499  {}
500 
501 } // namespace lar_pandora
float GetWidthZ() const
Return Z span of drift volume.
static geo::View_t GetGlobalView(const unsigned int cstat, const unsigned int tpc, const geo::View_t hit_View)
Convert to global coordinate system.
daughter drift volume class to hold properties of daughter drift volumes
static void LoadGeometry(LArDriftVolumeList &outputVolumeList, LArDriftVolumeMap &outputVolumeMap, const bool useActiveBoundingBox)
Load drift volume geometry.
virtual float WireAngleV(const geo::TPCID::TPCID_t tpc, const geo::CryostatID::CryostatID_t cstat) const =0
The angle of the wires in the mapped V view.
LArDriftVolume(const unsigned int volumeID, const bool isPositiveDrift, const float wirePitchU, const float wirePitchV, const float wirePitchW, const float wireAngleU, const float wireAngleV, const float wireAngleW, const float centerX, const float centerY, const float centerZ, const float widthX, const float widthY, const float widthZ, const float sigmaUVZ, const LArDaughterDriftVolumeList &tpcVolumeList)
Constructor.
Helper functions for extracting detector geometry for use in reconsruction.
enum geo::_plane_proj View_t
Enumerate the possible plane projections.
Planes which measure V.
Definition: geo_types.h:130
std::map< unsigned int, LArDriftVolume > LArDriftVolumeMap
unsigned int GetCryostat() const
Return cryostat ID.
Empty interface to map pandora to specifics in the LArSoft geometry.
Geometry information for a single TPC.
Definition: TPCGeo.h:38
std::vector< LArDriftVolume > LArDriftVolumeList
static unsigned int GetVolumeID(const LArDriftVolumeMap &driftVolumeMap, const unsigned int cstat, const unsigned int tpc)
Get drift volume ID from a specified cryostat/tpc pair.
intermediate_table::const_iterator const_iterator
ROOT::Math::DisplacementVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Vector_t
Type for representation of momenta in 3D space.
Definition: geo_vectors.h:164
virtual float WirePitchV() const =0
The wire pitch of the mapped V view.
unsigned int Ncryostats() const
Returns the number of cryostats in the detector.
Planes which measure Y direction.
Definition: geo_types.h:133
art framework interface to geometry description
float GetCenterZ() const
Return Z position at centre of drift volume.
static unsigned int GetDaughterVolumeID(const LArDriftVolumeMap &driftVolumeMap, const unsigned int cstat, const unsigned int tpc)
Get daughter volume ID from a specified cryostat/tpc pair.
virtual float WireAngleU(const geo::TPCID::TPCID_t tpc, const geo::CryostatID::CryostatID_t cstat) const =0
The angle of the wires in the mapped U view.
Planes which measure U.
Definition: geo_types.h:129
unsigned int MaxPlanes() const
Returns the largest number of planes among all TPCs in this detector.
static unsigned int GetTpcID(const unsigned int cstat, const unsigned int tpc)
Generate a unique identifier for each TPC.
virtual float WirePitchU() const =0
The wire pitch of the mapped U view.
virtual bool CheckDetectorGapSize(const geo::Vector_t &gaps, const geo::Vector_t &deltas, const float maxDisplacement) const =0
Check whether a gap size is small enough to be registered as a detector gap.
float GetCenterX() const
Return X position at centre of drift volume.
unsigned int GetVolumeID() const
Return unique ID.
static bool ShouldSwitchUV(const unsigned int cstat, const unsigned int tpc)
Return whether U/V should be switched in global coordinate system for this cryostat/tpc.
static void LoadGlobalDaughterGeometry(const LArDriftVolumeList &driftVolumeList, LArDriftVolumeList &daughterVolumeList)
This method will create one or more daughter volumes (these share a common drift orientation along th...
virtual void LoadDaughterDetectorGaps(const LArDriftVolume &driftVolume, const float maxDisplacement, LArDetectorGapList &listOfGaps) const =0
Create detector gaps for all daughter volumes in a logical TPC volume.
double distance(double x1, double y1, double z1, double x2, double y2, double z2)
static void LoadDetectorGaps(LArDetectorGapList &listOfGaps, const bool useActiveBoundingBox)
Load the 2D gaps that go with the chosen geometry.
static int max(int a, int b)
virtual float WireAngleW(const geo::TPCID::TPCID_t tpc, const geo::CryostatID::CryostatID_t cstat) const =0
The angle of the wires in the mapped V view.
virtual LArDetectorGap CreateDetectorGap(const geo::Point_t &point1, const geo::Point_t &point2, const geo::Vector_t &widths) const =0
Create a detector gap.
virtual float WirePitchW() const =0
The wire pitch of the mapped W view.
Encapsulate the geometry of a wire.
unsigned int NTPC(unsigned int cstat=0) const
Returns the total number of TPCs in the specified cryostat.
std::vector< LArDaughterDriftVolume > LArDaughterDriftVolumeList
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
static float GetMaxGapSize() noexcept
Get maximum gap size.
LArPandoraDetectorType * GetDetectorType()
Factory class that returns the correct detector type interface.
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
Definition: statistics.h:55
Drift towards positive X values.
Definition: geo_types.h:161
Encapsulate the construction of a single detector plane.
std::vector< LArDetectorGap > LArDetectorGapList
float GetWidthY() const
Return Y span of drift volume.
float GetCenterY() const
Return Y position at centre of drift volume.
TPCGeo const & TPC(unsigned int const tpc=0, unsigned int const cstat=0) const
Returns the specified TPC.
drift volume class to hold properties of drift volume
Planes which measure W (third view for Bo, MicroBooNE, etc).
Definition: geo_types.h:131
float GetWidthX() const
Return X span of drift volume.
Helper functions for extracting detector geometry for use in reconsruction.
void LocalToWorld(const double *tpc, double *world) const
Transform point from local TPC frame to world frame.
Definition: TPCGeo.h:563
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
QTextStream & endl(QTextStream &s)
Encapsulate the construction of a single detector plane.
unsigned int GetTpc() const
Return tpc ID.