9 #include "art/Framework/Services/Registry/ServiceHandle.h"
10 #include "cetlib_except/exception.h"
23 namespace lar_pandora {
27 const bool useActiveBoundingBox)
30 if (!listOfGaps.empty())
31 throw cet::exception(
"LArPandora")
32 <<
" LArPandoraGeometry::LoadDetectorGaps --- the list of gaps already exists ";
40 for (LArDriftVolumeList::const_iterator iter1 = driftVolumeList.begin(),
41 iterEnd1 = driftVolumeList.end();
46 for (LArDriftVolumeList::const_iterator iter2 = iter1, iterEnd2 = driftVolumeList.end();
63 const float gapX(deltaX - widthX);
64 const float gapY(deltaY - widthY);
65 const float gapZ(deltaZ - widthZ);
82 geo::Vector_t gaps(gapX, gapY, gapZ), deltas(deltaX, deltaY, deltaZ);
99 const bool useActiveBoundingBox)
101 if (!outputVolumeList.empty())
102 throw cet::exception(
"LArPandora")
103 <<
" LArPandoraGeometry::LoadGeometry --- the list of drift volumes already exists ";
110 (
void)outputVolumeMap.insert(LArDriftVolumeMap::value_type(
120 const unsigned int cstat,
121 const unsigned int tpc)
123 if (driftVolumeMap.empty())
124 throw cet::exception(
"LArPandora")
125 <<
" LArPandoraGeometry::GetVolumeID --- detector geometry map is empty";
127 LArDriftVolumeMap::const_iterator iter =
130 if (driftVolumeMap.end() == iter)
131 throw cet::exception(
"LArPandora")
132 <<
" LArPandoraGeometry::GetVolumeID --- found a TPC that doesn't belong to a drift volume";
134 return iter->second.GetVolumeID();
141 const unsigned int cstat,
142 const unsigned int tpc)
144 if (driftVolumeMap.empty())
145 throw cet::exception(
"LArPandora")
146 <<
" LArPandoraGeometry::GetDaughterVolumeID --- detector geometry map is empty";
148 LArDriftVolumeMap::const_iterator iter =
151 if (driftVolumeMap.end() == iter)
152 throw cet::exception(
"LArPandora") <<
" LArPandoraGeometry::GetDaughterVolumeID --- found a "
153 "TPC volume that doesn't belong to a drift volume";
155 for (LArDaughterDriftVolumeList::const_iterator
156 iterDghtr = iter->second.GetTpcVolumeList().begin(),
157 iterDghtrEnd = iter->second.GetTpcVolumeList().end();
158 iterDghtr != iterDghtrEnd;
162 return std::distance(iter->second.GetTpcVolumeList().begin(), iterDghtr);
164 throw cet::exception(
"LArPandora")
165 <<
" LArPandoraGeometry::GetDaughterVolumeID --- found a daughter volume that doesn't belong "
166 "to the drift volume ";
173 const unsigned int tpc,
179 if ((hit_View ==
geo::kW) || (hit_View ==
geo::kY)) {
return hit_View; }
180 else if (hit_View ==
geo::kU) {
183 else if (hit_View ==
geo::kV) {
187 throw cet::exception(
"LArPandora")
188 <<
" LArPandoraGeometry::GetGlobalView --- found an unknown plane view (not U, V or W) ";
199 throw cet::exception(
"LArPandora")
200 <<
" LArPandoraGeometry::GetTpcID --- found a TPC with an ID greater than 10000 ";
202 return ((10000 * cstat) + tpc);
211 art::ServiceHandle<geo::Geometry const> theGeometry;
212 const geo::TPCGeo& theTpc(theGeometry->TPC(tpc, cstat));
214 const bool isPositiveDrift(theTpc.DriftDirection() ==
geo::kPosX);
224 art::ServiceHandle<geo::Geometry const> theGeometry;
225 if (theGeometry->MaxPlanes() == 2)
return false;
228 return isPositiveDrift;
235 const bool useActiveBoundingBox)
239 if (!driftVolumeList.empty())
240 throw cet::exception(
"LArPandora")
241 <<
" LArPandoraGeometry::LoadGeometry --- detector geometry has already been loaded ";
243 typedef std::set<unsigned int> UIntSet;
246 art::ServiceHandle<geo::Geometry const> theGeometry;
248 const float wirePitchU(detType->
WirePitchU());
249 const float wirePitchV(detType->
WirePitchV());
250 const float wirePitchW(detType->
WirePitchW());
251 const float maxDeltaTheta(0.01f);
254 for (
unsigned int icstat = 0; icstat < theGeometry->Ncryostats(); ++icstat) {
258 for (
unsigned int itpc1 = 0; itpc1 < theGeometry->NTPC(icstat); ++itpc1) {
259 if (cstatList.end() != cstatList.find(itpc1))
continue;
262 const geo::TPCGeo& theTpc1(theGeometry->TPC(itpc1, icstat));
263 cstatList.insert(itpc1);
265 const float wireAngleU(detType->
WireAngleU(itpc1, icstat));
266 const float wireAngleV(detType->
WireAngleV(itpc1, icstat));
267 const float wireAngleW(detType->
WireAngleW(itpc1, icstat));
269 double localCoord1[3] = {0., 0., 0.};
270 double worldCoord1[3] = {0., 0., 0.};
273 float driftMinX(useActiveBoundingBox ? theTpc1.ActiveBoundingBox().MinX() :
274 (worldCoord1[0] - theTpc1.ActiveHalfWidth()));
275 float driftMaxX(useActiveBoundingBox ? theTpc1.ActiveBoundingBox().MaxX() :
276 (worldCoord1[0] + theTpc1.ActiveHalfWidth()));
277 float driftMinY(useActiveBoundingBox ? theTpc1.ActiveBoundingBox().MinY() :
278 (worldCoord1[1] - theTpc1.ActiveHalfHeight()));
279 float driftMaxY(useActiveBoundingBox ? theTpc1.ActiveBoundingBox().MaxY() :
280 (worldCoord1[1] + theTpc1.ActiveHalfHeight()));
281 float driftMinZ(useActiveBoundingBox ? theTpc1.ActiveBoundingBox().MinZ() :
282 (worldCoord1[2] - 0.5f * theTpc1.ActiveLength()));
283 float driftMaxZ(useActiveBoundingBox ? theTpc1.ActiveBoundingBox().MaxZ() :
284 (worldCoord1[2] + 0.5f * theTpc1.ActiveLength()));
287 useActiveBoundingBox ?
288 (0.5 * (driftMinX + driftMaxX) - 0.25 * std::fabs(driftMaxX - driftMinX)) :
289 (worldCoord1[0] - 0.5 * theTpc1.ActiveHalfWidth()));
291 useActiveBoundingBox ?
292 (0.5 * (driftMinX + driftMaxX) + 0.25 * std::fabs(driftMaxX - driftMinX)) :
293 (worldCoord1[0] + 0.5 * theTpc1.ActiveHalfWidth()));
295 const bool isPositiveDrift(theTpc1.DriftDirection() ==
geo::kPosX);
298 tpcList.insert(itpc1);
303 0.5f * (driftMaxX + driftMinX),
304 0.5f * (driftMaxY + driftMinY),
305 0.5f * (driftMaxZ + driftMinZ),
306 (driftMaxX - driftMinX),
307 (driftMaxY - driftMinY),
308 (driftMaxZ - driftMinZ)));
311 for (
unsigned int itpc2 = itpc1 + 1; itpc2 < theGeometry->NTPC(icstat); ++itpc2) {
312 if (cstatList.end() != cstatList.find(itpc2))
continue;
314 const geo::TPCGeo& theTpc2(theGeometry->TPC(itpc2, icstat));
316 if (theTpc1.DriftDirection() != theTpc2.DriftDirection())
continue;
318 const float dThetaU(detType->
WireAngleU(itpc1, icstat) -
320 const float dThetaV(detType->
WireAngleV(itpc1, icstat) -
322 const float dThetaW(detType->
WireAngleW(itpc1, icstat) -
324 if (dThetaU > maxDeltaTheta || dThetaV > maxDeltaTheta || dThetaW > maxDeltaTheta)
327 double localCoord2[3] = {0., 0., 0.};
328 double worldCoord2[3] = {0., 0., 0.};
331 const float driftMinX2(useActiveBoundingBox ?
332 theTpc2.ActiveBoundingBox().MinX() :
333 (worldCoord2[0] - theTpc2.ActiveHalfWidth()));
334 const float driftMaxX2(useActiveBoundingBox ?
335 theTpc2.ActiveBoundingBox().MaxX() :
336 (worldCoord2[0] + theTpc2.ActiveHalfWidth()));
339 useActiveBoundingBox ?
340 (0.5 * (driftMinX2 + driftMaxX2) - 0.25 * std::fabs(driftMaxX2 - driftMinX2)) :
341 (worldCoord2[0] - 0.5 * theTpc2.ActiveHalfWidth()));
343 useActiveBoundingBox ?
344 (0.5 * (driftMinX2 + driftMaxX2) + 0.25 * std::fabs(driftMaxX2 - driftMinX2)) :
345 (worldCoord2[0] + 0.5 * theTpc2.ActiveHalfWidth()));
347 if ((min2 > max1) || (min1 > max2))
continue;
349 cstatList.insert(itpc2);
350 tpcList.insert(itpc2);
352 const float driftMinY2(useActiveBoundingBox ?
353 theTpc2.ActiveBoundingBox().MinY() :
354 (worldCoord2[1] - theTpc2.ActiveHalfHeight()));
355 const float driftMaxY2(useActiveBoundingBox ?
356 theTpc2.ActiveBoundingBox().MaxY() :
357 (worldCoord2[1] + theTpc2.ActiveHalfHeight()));
358 const float driftMinZ2(useActiveBoundingBox ?
359 theTpc2.ActiveBoundingBox().MinZ() :
360 (worldCoord2[2] - 0.5f * theTpc2.ActiveLength()));
361 const float driftMaxZ2(useActiveBoundingBox ?
362 theTpc2.ActiveBoundingBox().MaxZ() :
363 (worldCoord2[2] + 0.5f * theTpc2.ActiveLength()));
365 driftMinX = std::min(driftMinX, driftMinX2);
366 driftMaxX = std::max(driftMaxX, driftMaxX2);
367 driftMinY = std::min(driftMinY, driftMinY2);
368 driftMaxY = std::max(driftMaxY, driftMaxY2);
369 driftMinZ = std::min(driftMinZ, driftMinZ2);
370 driftMaxZ = std::max(driftMaxZ, driftMaxZ2);
374 0.5f * (driftMaxX2 + driftMinX2),
375 0.5f * (driftMaxY2 + driftMinY2),
376 0.5f * (driftMaxZ2 + driftMinZ2),
377 (driftMaxX2 - driftMinX2),
378 (driftMaxY2 - driftMinY2),
379 (driftMaxZ2 - driftMinZ2)));
383 driftVolumeList.emplace_back(driftVolumeList.size(),
391 0.5f * (driftMaxX + driftMinX),
392 0.5f * (driftMaxY + driftMinY),
393 0.5f * (driftMaxZ + driftMinZ),
394 (driftMaxX - driftMinX),
395 (driftMaxY - driftMinY),
396 (driftMaxZ - driftMinZ),
397 (wirePitchU + wirePitchV + wirePitchW + 0.1f),
402 if (driftVolumeList.empty())
403 throw cet::exception(
"LArPandora") <<
" LArPandoraGeometry::LoadGeometry --- failed to find "
404 "any drift volumes in this detector geometry ";
418 if (!daughterVolumeList.empty())
419 throw cet::exception(
"LArPandora") <<
" LArPandoraGeometry::LoadGlobalDaughterGeometry --- "
420 "daughter geometry has already been loaded ";
422 if (driftVolumeList.empty())
423 throw cet::exception(
"LArPandora") <<
" LArPandoraGeometry::LoadGlobalDaughterGeometry --- "
424 "detector geometry has not yet been loaded ";
426 std::cout <<
"The size of the drif list is: " << driftVolumeList.size() << std::endl;
430 std::cout <<
"Looking at dau vol: " << count++ << std::endl;
433 const float daughterWirePitchU(switchViews ? driftVolume.GetWirePitchV() :
434 driftVolume.GetWirePitchU());
435 const float daughterWirePitchV(switchViews ? driftVolume.GetWirePitchU() :
436 driftVolume.GetWirePitchV());
437 const float daughterWirePitchW(driftVolume.GetWirePitchW());
438 const float daughterWireAngleU(switchViews ? driftVolume.GetWireAngleV() :
439 driftVolume.GetWireAngleU());
440 const float daughterWireAngleV(switchViews ? driftVolume.GetWireAngleU() :
441 driftVolume.GetWireAngleV());
442 const float daughterWireAngleW(driftVolume.GetWireAngleW());
444 daughterVolumeList.push_back(
LArDriftVolume(driftVolume.GetVolumeID(),
445 driftVolume.IsPositiveDrift(),
452 driftVolume.GetCenterX(),
453 driftVolume.GetCenterY(),
454 driftVolume.GetCenterZ(),
455 driftVolume.GetWidthX(),
456 driftVolume.GetWidthY(),
457 driftVolume.GetWidthZ(),
458 driftVolume.GetSigmaUVZ(),
459 driftVolume.GetTpcVolumeList()));
462 if (daughterVolumeList.empty())
463 throw cet::exception(
"LArPandora") <<
" LArPandoraGeometry::LoadGlobalDaughterGeometry --- "
464 "failed to create daughter geometry list ";
471 const bool isPositiveDrift,
472 const float wirePitchU,
473 const float wirePitchV,
474 const float wirePitchW,
475 const float wireAngleU,
476 const float wireAngleV,
477 const float wireAngleW,
484 const float sigmaUVZ,
486 : m_volumeID(volumeID)
487 , m_isPositiveDrift(isPositiveDrift)
488 , m_wirePitchU(wirePitchU)
489 , m_wirePitchV(wirePitchV)
490 , m_wirePitchW(wirePitchW)
491 , m_wireAngleU(wireAngleU)
492 , m_wireAngleV(wireAngleV)
493 , m_wireAngleW(wireAngleW)
500 , m_sigmaUVZ(sigmaUVZ)
501 , m_tpcVolumeList(tpcVolumeList)
float GetWidthZ() const
Return Z span of drift volume.
ROOT::Math::DisplacementVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Vector_t
Type for representation of momenta in 3D space.
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.
BEGIN_PROLOG supported so bottom corner of box bottom corner of box bottom corner of box top corner of box Y1
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.
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.
enum geo::_plane_proj View_t
Enumerate the possible plane projections.
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.
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.
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.
Planes which measure Y direction.
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 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.
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.
double distance(geo::Point_t const &point, CathodeDesc_t const &cathode)
Returns the distance of a point from the cathode.
float GetCenterX() const
Return X position at centre of drift volume.
unsigned int GetVolumeID() const
Return unique ID.
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 float WirePitchW() const =0
The wire pitch of the mapped W view.
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...
static void LoadDetectorGaps(LArDetectorGapList &listOfGaps, const bool useActiveBoundingBox)
Load the 2D gaps that go with the chosen geometry.
BEGIN_PROLOG supported so bottom corner of box bottom corner of box bottom corner of box top corner of box top corner of box Z1
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.
Encapsulate the geometry of a wire.
virtual float WirePitchV() const =0
The wire pitch of the mapped V view.
std::vector< LArDaughterDriftVolume > LArDaughterDriftVolumeList
virtual LArDetectorGap CreateDetectorGap(const geo::Point_t &point1, const geo::Point_t &point2, const geo::Vector_t &widths) const =0
Create a detector gap.
static float GetMaxGapSize() noexcept
Get maximum gap size.
LArPandoraDetectorType * GetDetectorType()
Factory class that returns the correct detector type interface.
Drift towards positive X values.
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.
drift volume class to hold properties of drift volume
Planes which measure W (third view for Bo, MicroBooNE, etc).
float GetWidthX() const
Return X span of drift volume.
std::size_t count(Cont const &cont)
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
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.
art framework interface to geometry description
BEGIN_PROLOG could also be cout
Encapsulate the construction of a single detector plane.
unsigned int GetTpc() const
Return tpc ID.