7 #include "cetlib_except/exception.h" 26 if (!listOfGaps.empty())
27 throw cet::exception(
"LArPandora") <<
" LArPandoraGeometry::LoadDetectorGaps --- the list of gaps already exists ";
44 const float maxDisplacement(30.
f);
49 const float gapX(deltaX - widthX);
51 if (gapX < 0.f || gapX > maxDisplacement || deltaY > maxDisplacement || deltaZ > maxDisplacement)
76 if (!outputVolumeList.empty())
77 throw cet::exception(
"LArPandora") <<
" LArPandoraGeometry::LoadGeometry --- the list of drift volumes already exists ";
89 (void) outputVolumeMap.insert(LArDriftVolumeMap::value_type(
LArPandoraGeometry::GetTpcID(tpcVolume.GetCryostat(), tpcVolume.GetTpc()), driftVolume));
98 if (driftVolumeMap.empty())
99 throw cet::exception(
"LArPandora") <<
" LArPandoraGeometry::GetVolumeID --- detector geometry map is empty";
103 if (driftVolumeMap.end() == iter)
104 throw cet::exception(
"LArPandora") <<
" LArPandoraGeometry::GetVolumeID --- found a TPC that doesn't belong to a drift volume";
106 return iter->second.GetVolumeID();
130 throw cet::exception(
"LArPandora") <<
" LArPandoraGeometry::GetGlobalView --- found an unknown plane view (not U, V or W) ";
140 throw cet::exception(
"LArPandora") <<
" LArPandoraGeometry::GetTpcID --- found a TPC with an ID greater than 10000 ";
142 return ((10000 * cstat) + tpc);
153 const bool isPositiveDrift(theTpc.DriftDirection() ==
geo::kPosX);
162 return isPositiveDrift;
171 if (!driftVolumeList.empty())
172 throw cet::exception(
"LArPandora") <<
" LArPandoraGeometry::LoadGeometry --- detector geometry has already been loaded ";
174 typedef std::set<unsigned int> UIntSet;
178 const unsigned int nWirePlanes(theGeometry->
MaxPlanes());
181 throw cet::exception(
"LArPandora") <<
" LArPandoraGeometry::LoadGeometry --- More than three wire planes present ";
184 if ((0 == theGeometry->
Ncryostats()) || (0 == theGeometry->
NTPC(0)))
185 throw cet::exception(
"LArPandora") <<
" LArPandoraGeometry::LoadGeometry --- unable to access first tpc in first cryostat ";
187 std::unordered_set<geo::_plane_proj> planeSet;
188 for (
unsigned int iPlane = 0; iPlane < nWirePlanes; ++iPlane)
189 (
void) planeSet.insert(theGeometry->
TPC(0, 0).
Plane(iPlane).
View());
191 if ((nWirePlanes != planeSet.size()) || !planeSet.count(
geo::kU) || !planeSet.count(
geo::kV) || (planeSet.count(
geo::kW) && planeSet.count(
geo::kY)))
192 throw cet::exception(
"LArPandora") <<
" LArPandoraGeometry::LoadGeometry --- expect to find u and v views; if there is one further view, it must be w or y ";
194 const bool useYPlane((nWirePlanes > 2) && planeSet.count(
geo::kY));
198 const float wirePitchW((nWirePlanes < 3) ? 0.5
f * (wirePitchU + wirePitchV) : (useYPlane) ? theGeometry->
WirePitch(
geo::kY) :
201 const float maxDeltaTheta(0.01
f);
204 for (
unsigned int icstat = 0; icstat < theGeometry->
Ncryostats(); ++icstat)
209 for (
unsigned int itpc1 = 0; itpc1 < theGeometry->
NTPC(icstat); ++itpc1)
211 if (cstatList.end() != cstatList.find(itpc1))
216 cstatList.insert(itpc1);
220 const float wireAngleW((nWirePlanes < 3) ? 0.
f : (useYPlane) ? (std::fabs(0.5
f * M_PI - theGeometry->
WireAngleToVertical(
geo::kY, itpc1, icstat))) :
223 double localCoord1[3] = {0., 0., 0.};
224 double worldCoord1[3] = {0., 0., 0.};
225 theTpc1.LocalToWorld(localCoord1, worldCoord1);
227 const double min1(worldCoord1[0] - 0.5 * theTpc1.ActiveHalfWidth());
228 const double max1(worldCoord1[0] + 0.5 * theTpc1.ActiveHalfWidth());
230 float driftMinX(worldCoord1[0] - theTpc1.ActiveHalfWidth());
231 float driftMaxX(worldCoord1[0] + theTpc1.ActiveHalfWidth());
232 float driftMinY(worldCoord1[1] - theTpc1.ActiveHalfHeight());
233 float driftMaxY(worldCoord1[1] + theTpc1.ActiveHalfHeight());
234 float driftMinZ(worldCoord1[2] - 0.5
f * theTpc1.ActiveLength());
235 float driftMaxZ(worldCoord1[2] + 0.5
f * theTpc1.ActiveLength());
237 const bool isPositiveDrift(theTpc1.DriftDirection() ==
geo::kPosX);
240 tpcList.insert(itpc1);
243 for (
unsigned int itpc2 = itpc1+1; itpc2 < theGeometry->
NTPC(icstat); ++itpc2)
245 if (cstatList.end() != cstatList.find(itpc2))
250 if (theTpc1.DriftDirection() != theTpc2.DriftDirection())
258 if (dThetaU > maxDeltaTheta || dThetaV > maxDeltaTheta || dThetaW > maxDeltaTheta)
261 double localCoord2[3] = {0., 0., 0.};
262 double worldCoord2[3] = {0., 0., 0.};
263 theTpc2.LocalToWorld(localCoord2, worldCoord2);
265 const double min2(worldCoord2[0] - 0.5 * theTpc2.ActiveHalfWidth());
266 const double max2(worldCoord2[0] + 0.5 * theTpc2.ActiveHalfWidth());
268 if ((min2 > max1) || (min1 > max2))
271 cstatList.insert(itpc2);
272 tpcList.insert(itpc2);
274 driftMinX =
std::min(driftMinX, static_cast<float>(worldCoord2[0] - theTpc2.ActiveHalfWidth()));
275 driftMaxX =
std::max(driftMaxX, static_cast<float>(worldCoord2[0] + theTpc2.ActiveHalfWidth()));
276 driftMinY =
std::min(driftMinY, static_cast<float>(worldCoord2[1] - theTpc2.ActiveHalfHeight()));
277 driftMaxY =
std::max(driftMaxY, static_cast<float>(worldCoord2[1] + theTpc2.ActiveHalfHeight()));
278 driftMinZ =
std::min(driftMinZ, static_cast<float>(worldCoord2[2] - 0.5
f * theTpc2.ActiveLength()));
279 driftMaxZ =
std::max(driftMaxZ, static_cast<float>(worldCoord2[2] + 0.5
f * theTpc2.ActiveLength()));
285 for(
const unsigned int itpc : tpcList)
291 driftVolumeList.push_back(
LArDriftVolume(driftVolumeList.size(), isPositiveDrift,
292 wirePitchU, wirePitchV, wirePitchW, wireAngleU, wireAngleV, wireAngleW,
293 0.5f * (driftMaxX + driftMinX), 0.5
f * (driftMaxY + driftMinY), 0.5f * (driftMaxZ + driftMinZ),
294 (driftMaxX - driftMinX), (driftMaxY - driftMinY), (driftMaxZ - driftMinZ),
295 (wirePitchU + wirePitchV + wirePitchW + 0.1f), tpcVolumeList));
299 if (driftVolumeList.empty())
300 throw cet::exception(
"LArPandora") <<
" LArPandoraGeometry::LoadGeometry --- failed to find any drift volumes in this detector geometry ";
312 if (!daughterVolumeList.empty())
313 throw cet::exception(
"LArPandora") <<
" LArPandoraGeometry::LoadGlobalDaughterGeometry --- daughter geometry has already been loaded ";
315 if (driftVolumeList.empty())
316 throw cet::exception(
"LArPandora") <<
" LArPandoraGeometry::LoadGlobalDaughterGeometry --- detector geometry has not yet been loaded ";
322 const float daughterWirePitchU(switchViews ? driftVolume.GetWirePitchV() : driftVolume.GetWirePitchU());
323 const float daughterWirePitchV(switchViews ? driftVolume.GetWirePitchU() : driftVolume.GetWirePitchV());
324 const float daughterWirePitchW(driftVolume.GetWirePitchW());
325 const float daughterWireAngleU(switchViews ? driftVolume.GetWireAngleV() : driftVolume.GetWireAngleU());
326 const float daughterWireAngleV(switchViews ? driftVolume.GetWireAngleU() : driftVolume.GetWireAngleV());
327 const float daughterWireAngleW(driftVolume.GetWireAngleW());
329 daughterVolumeList.push_back(
LArDriftVolume(driftVolume.GetVolumeID(), driftVolume.IsPositiveDrift(),
330 daughterWirePitchU, daughterWirePitchV, daughterWirePitchW, daughterWireAngleU, daughterWireAngleV, daughterWireAngleW,
331 driftVolume.GetCenterX(), driftVolume.GetCenterY() , driftVolume.GetCenterZ(),
332 driftVolume.GetWidthX(), driftVolume.GetWidthY(), driftVolume.GetWidthZ(),
333 driftVolume.GetSigmaUVZ(), driftVolume.GetTpcVolumeList()));
336 if (daughterVolumeList.empty())
337 throw cet::exception(
"LArPandora") <<
" LArPandoraGeometry::LoadGlobalDaughterGeometry --- failed to create daughter geometry list ";
344 const float wirePitchU,
const float wirePitchV,
const float wirePitchW,
const float wireAngleU,
const float wireAngleV,
const float wireAngleW,
345 const float centerX,
const float centerY,
const float centerZ,
const float widthX,
const float widthY,
const float widthZ,
347 m_volumeID(volumeID),
348 m_isPositiveDrift(isPositiveDrift),
349 m_wirePitchU(wirePitchU),
350 m_wirePitchV(wirePitchV),
351 m_wirePitchW(wirePitchW),
352 m_wireAngleU(wireAngleU),
353 m_wireAngleV(wireAngleV),
354 m_wireAngleW(wireAngleW),
361 m_sigmaUVZ(sigmaUVZ),
362 m_tpcVolumeList(tpcVolumeList)
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
std::vector< LArDetectorGap > LArDetectorGapList
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.
std::map< unsigned int, LArDriftVolume > LArDriftVolumeMap
LArDaughterDriftVolumeList m_tpcVolumeList
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.
unsigned int Ncryostats() const
Returns the number of cryostats in the detector.
geo::Length_t WirePitch(geo::PlaneID const &planeid) const
Returns the distance between two consecutive wires.
Planes which measure Y direction.
float GetCenterZ() const
Return Z position at centre of drift volume.
static void LoadGeometry(LArDriftVolumeList &outputVolumeList, LArDriftVolumeMap &outputVolumeMap)
Load drift volume geometry.
View_t View() const
Which coordinate does this plane measure.
unsigned int MaxPlanes() const
Returns the largest number of planes among all TPCs in this detector.
const LArDaughterDriftVolumeList & GetTpcVolumeList() const
Return list of daughter drift volumes associated with this drift volume.
static unsigned int GetTpcID(const unsigned int cstat, const unsigned int tpc)
Generate a unique identifier for each TPC.
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...
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
Drift towards positive X values.
Encapsulate the construction of a single detector plane.
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).
PlaneGeo const & Plane(geo::View_t view) const
Return the plane in the tpc with View_t view.
float GetWidthX() const
Return X span of drift volume.
double WireAngleToVertical(geo::View_t view, geo::TPCID const &tpcid) const
Returns the angle of the wires in the specified view from vertical.
art framework interface to geometry description
cet::coded_exception< error, detail::translate > exception
drift volume class to hold properties of drift volume
Encapsulate the construction of a single detector plane.
static void LoadDetectorGaps(LArDetectorGapList &listOfGaps)
Load the 2D gaps that go with the chosen geometry.