22 #include "cetlib_except/exception.h" 34 #include <type_traits> 44 template <
typename T,
typename CONT>
45 void append(std::vector<T>& dest, CONT
const& src) {
48 dest.insert(dest.end(), cbegin(src), cend(src));
53 void append(std::vector<T>& dest, std::vector<T>&& src) {
54 if (dest.empty()) dest = std::move(src);
55 else append(dest, src);
61 template <
typename Cont>
62 auto keys(Cont
const& m) {
64 std::vector<typename Cont::value_type::first_type> result;
65 result.reserve(m.size());
68 std::back_inserter(result), [](
auto const& p){
return p.first; }
85 auto iVol = volumeAfter(drift);
86 if (iVol == volumes.cbegin())
return nullptr;
87 if (!(--iVol)->coversDrift(drift))
return nullptr;
96 return (volume && volume->partition)
97 ? volume->partition->atPoint(comp.projection.X(), comp.projection.Y())
124 struct CoverageExtractor {
148 TPCpart.
walk(extractor);
149 return extractor.coverage;
164 std::vector<geo::TPCGeo const*>
TPCs;
167 TPCgroup_t(
double pos, std::vector<geo::TPCGeo const*>&& TPCs)
168 : pos(pos), TPCs(
std::move(TPCs)) {}
182 <std::pair<geo::DriftPartitions::DriftDir_t, std::vector<geo::TPCGeo const*>>>
201 auto const nTPCs = cryo.
NTPC();
202 for (
unsigned int iTPC = 0; iTPC < nTPCs; ++iTPC) {
205 decltype(
auto) driftDir = TPC.
DriftDir();
207 std::size_t iGroup = 0;
208 for (; iGroup < result.size(); ++iGroup) {
209 if (vectorIs.nonEqual(driftDir, result[iGroup].first))
continue;
210 result[iGroup].second.push_back(&TPC);
215 if (iGroup == result.size()) {
218 std::vector<geo::TPCGeo const*>{ &TPC }
230 std::vector<geo::TPCGeo const*>
const& TPCs,
246 {
return decomp.
PointNormalComponent(geo::vect::convertTo<geo::DriftPartitions::Position_t>(TPC.FirstPlane().GetCenter())); };
248 std::vector<TPCandPos_t> result;
249 result.reserve(TPCs.size());
250 std::transform(TPCs.cbegin(), TPCs.cend(), std::back_inserter(result),
256 std::sort(result.begin(), result.end());
263 (std::vector<TPCandPos_t>
const& TPCs)
271 if (TPCs.empty())
return {};
273 geo::TPCGeo const& firstTPC = *(TPCs.front().second);
277 double const groupThickness = 10.0
280 auto iFirstTPC = TPCs.cbegin(), tend = TPCs.cend();
282 std::vector<TPCgroup_t> result;
283 while (iFirstTPC != tend) {
284 double const posEnd = iFirstTPC->first + groupThickness;
286 std::vector<geo::TPCGeo const*> TPCs;
287 auto iEndGroup = iFirstTPC;
289 TPCs.push_back(iEndGroup->second);
290 sumPos += iEndGroup->first;
292 }
while ((iEndGroup != tend) && (iEndGroup->first < posEnd));
294 double const averagePos = sumPos / TPCs.size();
295 result.emplace_back(averagePos, std::move(TPCs));
297 iFirstTPC = iEndGroup;
315 auto iTPC = TPCs.cbegin(), tend = TPCs.cend();
318 <<
"checkTPCcoords() got an empty partition.";
323 decltype(
auto) refDriftDir = refTPC.
DriftDir();
326 {
return geo::vect::dot(TPC.FirstPlane().GetCenter(), refDriftDir); };
333 unsigned int nErrors = 0U;
334 while (++iTPC != tend) {
337 if (vectorIs.nonEqual(TPC.
DriftDir(), refDriftDir)) {
339 <<
"Incompatible drift directions between " << TPC.
ID()
345 if (coordIs.
nonEqual(driftPos, refDriftPos)) {
347 <<
"Incompatible drift coordinate between " << TPC.
ID()
348 <<
" (" << driftPos <<
"( and " << refTPC.
ID() <<
" (" 349 << refDriftPos <<
")";
358 template <
typename Range>
366 auto iDir = cbegin(directions);
367 auto dend = cend(directions);
368 if (!(iDir != dend)) {
370 <<
"detectGlobalDriftDir(): no TPCs provided!\n";
374 auto compatibleDir = [comp](
auto const& a,
auto const& b)
377 auto const dir = *(iDir++);
378 for (; iDir != dend; ++iDir) {
379 if (compatibleDir(
dir, *iDir))
continue;
386 return ((
dir.X() <= 0.0) && (
dir.Y() <= 0.0) && (
dir.Z() <= 0.0))? -
dir:
dir;
398 :
geo::
part::AreaOwner(area), TPC(TPC) {}
422 { lowerProj.X(), upperProj.X(),
true },
423 { lowerProj.Y(), upperProj.Y(),
true }
430 std::vector<geo::TPCGeo const*>
const& TPCs,
436 std::vector<TPCwithArea_t> result;
437 result.reserve(TPCs.size());
439 for (
auto const& TPC: TPCs)
440 result.emplace_back(
TPCarea(*TPC, decomposer), TPC);
447 template <
typename BeginIter,
typename EndIter>
449 (BeginIter TPCbegin, EndIter TPCend)
456 auto iTPC = TPCbegin;
465 template <
typename Key,
typename ExtractKey,
typename Comparer = std::less<Key>>
474 template <
typename Data>
475 static Key_t key(Data
const& obj) {
return ExtractKey()(obj); }
477 template <
typename A,
typename B>
478 bool operator() (A
const& a,
B const& b)
const 479 {
return sortKey(key(a), key(b)); }
486 template<geo::part::AreaOwner::AreaRangeMember_t Range>
499 typename BeginIter,
typename EndIter
503 (BeginIter beginTPCwithArea, EndIter endTPCwithArea)
521 auto gbegin = beginTPCwithArea;
522 while (gbegin != endTPCwithArea) {
524 groupStart.push_back(gbegin);
529 auto range = (*gbegin)->area().*sortingRange;
531 while (++gend != endTPCwithArea) {
540 auto const& TPCrange = (*gend)->area().*sortingRange;
541 if (coordIs.
nonSmaller(TPCrange.lower, range.upper))
543 range.extendToInclude(TPCrange);
559 typename BeginIter,
typename EndIter
562 std::vector<TPCwithArea_t const*>,
566 (BeginIter beginTPCwithArea, EndIter endTPCwithArea)
571 std::vector<TPCwithArea_t const*> TPCs(beginTPCwithArea, endTPCwithArea);
572 if (TPCs.size() <= 1)
return {};
580 = groupTPCsByRangeCoord<sortingRange>(TPCs.cbegin(), TPCs.cend());
581 assert(!TPCgroups.empty());
583 return { std::move(TPCs), std::move(TPCgroups) };
590 typename BeginIter,
typename EndIter,
typename TPCendIter,
591 typename SubpartMaker
594 BeginIter itTPCbegin, EndIter itTPCend, TPCendIter TPCend,
595 SubpartMaker subpartMaker
624 auto igbegin = itTPCbegin;
625 while (igbegin != itTPCend) {
626 auto const gbegin = *igbegin;
627 auto const gend = (++igbegin == itTPCend)? TPCend: *igbegin;
632 if (std::distance(gbegin, gend) == 1) {
636 auto subpart = subpartMaker(gbegin, gend);
637 if (!subpart)
return {};
639 subparts.emplace_back(std::move(subpart));
649 return std::make_unique<geo::part::PartitionElement<geo::TPCGeo const>>
656 template <
typename BeginIter,
typename EndIter>
658 (BeginIter beginTPCwithArea, EndIter endTPCwithArea);
659 template <
typename BeginIter,
typename EndIter>
661 (BeginIter beginTPCwithArea, EndIter endTPCwithArea);
662 template <
typename BeginIter,
typename EndIter>
664 (BeginIter beginTPCwithArea, EndIter endTPCwithArea);
665 template <
typename BeginIter,
typename EndIter>
666 std::unique_ptr<geo::part::Partition<geo::TPCGeo const>>
makePartition 667 (BeginIter beginTPCwithArea, EndIter endTPCwithArea);
672 typename TPCPartitionResultType,
674 typename BeginIter,
typename EndIter,
675 typename SubpartMaker
678 BeginIter beginTPCwithArea, EndIter endTPCwithArea,
679 SubpartMaker subpartMaker
704 auto const TPCgroupInfo
705 = sortAndGroupTPCsByRangeCoord<Range>(beginTPCwithArea, endTPCwithArea);
706 std::vector<TPCwithArea_t const*>
const& TPCs = TPCgroupInfo.first;
708 TPCgroups = TPCgroupInfo.second;
710 if (TPCs.empty())
return {};
716 (TPCgroups.cbegin(), TPCgroups.cend(), TPCs.cend(), subpartMaker);
719 if (subparts.size() == 1)
return {};
729 return std::make_unique<TPCPartitionResultType>
730 (totalArea, std::move(subparts));
736 template <
typename BeginIter,
typename EndIter>
738 (BeginIter beginTPCwithArea, EndIter endTPCwithArea)
744 (beginTPCwithArea, endTPCwithArea, &makeDepthPartition<BeginIter, EndIter>);
748 template <
typename BeginIter,
typename EndIter>
750 (BeginIter beginTPCwithArea, EndIter endTPCwithArea)
756 (beginTPCwithArea, endTPCwithArea, &makeWidthPartition<BeginIter, EndIter>);
761 template <
typename BeginIter,
typename EndIter>
763 (BeginIter beginTPCwithArea, EndIter endTPCwithArea)
786 auto const TPCgroupInfo = sortAndGroupTPCsByRangeCoord<&Area_t::width>
787 (beginTPCwithArea, endTPCwithArea);
788 std::vector<TPCwithArea_t const*>
const& TPCs = TPCgroupInfo.first;
790 TPCgroups = TPCgroupInfo.second;
792 if (TPCs.empty())
return {};
794 if (TPCs.size() < 4)
return {};
796 unsigned int const nWidthParts = TPCgroups.size();
797 if (nWidthParts <= 1)
return {};
802 auto const FirstColGroupInfo
803 = sortAndGroupTPCsByRangeCoord<&Area_t::depth>(TPCgroups[0], TPCgroups[1]);
804 std::vector<TPCwithArea_t const*>
const& FirstColTPCs
805 = FirstColGroupInfo.first;
807 FirstColGroups = FirstColGroupInfo.second;
809 if (FirstColTPCs.empty())
return {};
810 if (FirstColGroups.size() <= 1 )
return {};
822 std::vector<Area_t::Range_t> depthGaps;
823 auto icnext = FirstColGroups.cbegin(), icprev = icnext,
824 icend = FirstColGroups.cend();
825 while (++icnext != icend) {
830 auto const cprev = *icprev;
831 auto const cnext = *icnext;
833 depthGaps.emplace_back
834 ((*cprev)->area().depth.upper, (*cnext)->area().depth.lower);
838 assert(!depthGaps.empty());
843 auto igbegin = TPCgroups.cbegin();
844 while (++igbegin != TPCgroups.cend()) {
848 auto igend = std::next(igbegin);
849 auto gbegin = *igbegin;
850 auto gend = (igend == TPCgroups.cend())? TPCs.cend(): *igend;
852 auto const ColGroupInfo
853 = sortAndGroupTPCsByRangeCoord<&Area_t::depth>(gbegin, gend);
854 std::vector<TPCwithArea_t const*>
const& ColTPCs = ColGroupInfo.first;
856 ColGroups = ColGroupInfo.second;
859 if (ColTPCs.empty())
return {};
860 if (ColGroups.size() <= 1)
return {};
865 std::vector<TPCwithArea_t::Area_t::Range_t> groupDepths(ColGroups.size());
866 auto iGDepth = groupDepths.begin();
867 for (
auto icgstart = ColGroups.cbegin(); icgstart != ColGroups.cend();
868 ++icgstart, ++iGDepth)
870 auto const icgend = std::next(icgstart);
871 auto ictpc = *icgstart;
872 auto const ictend = (icgend == ColGroups.cend())? ColTPCs.cend(): *icgend;
873 while (ictpc != ictend)
874 iGDepth->extendToInclude((*(ictpc++))->area().depth);
880 auto iGap = depthGaps.begin();
881 while (iGap != depthGaps.end()) {
882 Area_t::Range_t& gap = *iGap;
887 bool bGoodGap =
false;
889 auto iCGroup = std::lower_bound(
890 groupDepths.cbegin(), groupDepths.cend(), gap.upper,
895 if ((iCGroup != groupDepths.begin()) && (iCGroup != groupDepths.end())) {
896 Area_t::Range_t
const& before = *(std::prev(iCGroup));
897 Area_t::Range_t
const& after = *iCGroup;
898 Area_t::Range_t
const TPCgap{ before.upper, after.lower };
902 iGap->lower = TPCgap.lower;
904 iGap->upper = TPCgap.upper;
907 bGoodGap = coordIs.
nonSmaller(iGap->upper, iGap->lower);
913 if (bGoodGap) ++iGap;
914 else iGap = depthGaps.erase(iGap);
918 if (depthGaps.empty())
return {};
925 std::vector<double> depthSep;
927 depthGaps.cbegin(), depthGaps.cend(), std::back_inserter(depthSep),
928 [](
auto const& r){
return (r.lower + r.upper) / 2.0; }
930 unsigned int const nDepthParts = depthSep.size() + 1;
936 (nWidthParts * nDepthParts);
939 unsigned int iWidth = 0;
940 for (
auto igbegin = TPCgroups.cbegin(); igbegin != TPCgroups.cend();
945 auto igend = std::next(igbegin);
946 auto gbegin = *igbegin;
947 auto gend = (igend == TPCgroups.cend())? TPCs.cend(): *igend;
948 std::vector<TPCwithArea_t const*> ColTPCs(gbegin, gend);
949 std::sort(ColTPCs.begin(), ColTPCs.end(),
952 unsigned int iDepth = 0;
953 auto cgstart = ColTPCs.cbegin(), TPCend = ColTPCs.cend();
954 for (
double sep: depthSep) {
964 while (cgend != cgstart) {
965 auto cglast = std::prev(cgend);
966 if (coordIs.
strictlySmaller((*cglast)->area().depth.lower, sep))
break;
969 assert(cgstart != cgend);
975 if (!
part)
return {};
976 totalArea.extendToInclude(
part->area());
977 subparts[iDepth * nWidthParts + iWidth] = std::move(
part);
987 if (!
part)
return {};
988 totalArea.extendToInclude(
part->area());
989 subparts[iDepth * nWidthParts + iWidth] = std::move(
part);
993 return std::make_unique<geo::part::GridPartition<geo::TPCGeo const>>
994 (totalArea, std::move(subparts), nWidthParts, nDepthParts);
1000 template <
typename BeginIter,
typename EndIter>
1001 std::unique_ptr<geo::part::Partition<geo::TPCGeo const>>
makePartition 1002 (BeginIter beginTPCwithArea, EndIter endTPCwithArea)
1027 using value_type = std::remove_reference_t<decltype(*beginTPCwithArea)>;
1029 std::is_pointer<value_type>()
1031 <std::decay_t<std::remove_pointer_t<value_type>>,
TPCwithArea_t>(),
1032 "Iterators must point to TPCwithArea_t pointers." 1036 auto const size = std::distance(beginTPCwithArea, endTPCwithArea);
1042 if (gPart)
return gPart;
1050 if (wPart->nParts() < dPart->nParts())
return wPart;
1073 template <
typename BeginIter,
typename EndIter>
1075 using value_type =
typename BeginIter::value_type;
1076 std::vector<value_type const*> result;
1077 result.reserve(std::distance(b, e));
1078 std::transform(b, e, std::back_inserter(result),
1079 [](
auto& obj){
return std::addressof(obj); });
1083 template <
typename T>
1089 std::unique_ptr<geo::DriftPartitions::TPCPartition_t>
makePartition 1090 (std::vector<TPCwithArea_t>
const& TPCs)
1126 std::vector<TPCgroup_t> TPCgroups;
1127 for (
auto const& TPCsOnDriftDir: TPCsByDriftDir) {
1135 for (
auto const& TPCgroup: TPCgroups) {
1139 <<
"TPCs in partition have different drift directions (" 1140 << errors <<
" errors found in " << TPCgroup.TPCs.size() <<
" TPCs).\n";
1148 for (
auto const& TPCgroup: TPCgroups) {
1153 e <<
"Failed to construct partition out of " << TPCs.size() <<
" TPCs:";
1154 for (
auto const& TPCinfo: TPCs) {
1155 e <<
"\n at " << TPCinfo.area() <<
" TPC ";
1156 TPCinfo.TPC->PrintTPCInfo(e,
" ", 5U);
Range_t computeCoverage(TPCPartition_t const &TPCpart) const
Computes the coverage of the specified partition in the drift direction.
geo::TPCID const & ID() const
Returns the identifier of this TPC.
double driftCoord(Position_t const &pos) const
Returns drift coordinate (in the drift-volume-specific frame) of pos.
Data structures and algorithms to partition a cryostat volume.
A basic interface for objects owning an area.
Vector DriftDir() const
Returns the direction of the drift (vector pointing toward the planes).
Decomposer_t decomposer
Decomposition on drift, width and depth axes.
std::unique_ptr< geo::part::Partition< geo::TPCGeo const > > makePartition(BeginIter beginTPCwithArea, EndIter endTPCwithArea)
auto vector3D(Vector3D const &v)
Returns a manipulator which will print the specified vector.
constexpr auto dot(Vector const &a, Vector const &b)
Return cross product of two vectors.
auto PointNormalComponent(Point_t const &point) const
Returns the secondary component of a point.
static Key_t key(Data const &obj)
geo::part::Partition< geo::TPCGeo const >::Subpartitions_t createSubpartitions(BeginIter itTPCbegin, EndIter itTPCend, TPCendIter TPCend, SubpartMaker subpartMaker)
constexpr bool nonEqual(Value_t a, Value_t b) const
Returns whether a and b are farther than the threshold.
Partition of area along the width dimension.
Encapsulate the construction of a single cyostat.
geo::part::AreaOwner::Area_t computeTotalArea(BeginIter TPCbegin, EndIter TPCend)
unsigned int Nplanes() const
Number of planes in this tpc.
Provides simple real number checks.
TPCgroup_t(double pos, std::vector< geo::TPCGeo const * > &&TPCs)
std::vector< DriftVolume_t >::iterator volumeAfter(double pos)
Returns an iterator to the drift volume starting after pos.
Point GetCathodeCenter() const
double MinX() const
Returns the world x coordinate of the start of the box.
void extendToInclude(Data_t)
Extends the range to include the specified point.
Geometry information for a single TPC.
SortTPCareaByAreaRangeLower<&geo::part::AreaOwner::Area_t::depth > SortTPCwithAreaByDepth
DriftPartitions buildDriftVolumes(geo::CryostatGeo const &cryo)
Creates a DriftPartitions object from the TPCs in a cryostat.
Vector RefWidthDir() const
Return the direction of reference plane width.
double MaxX() const
Returns the world x coordinate of the end of the box.
virtual Data_t * data() const
Returns the datum directly stored (nullptr if none).
Geometry information for a single cryostat.
geo::part::AreaOwner::Area_t TPCarea(geo::TPCGeo const &TPC, geo::DriftPartitions::Decomposer_t const &decomposer)
geo::TPCGeo const * TPCat(Position_t const &pos) const
Returns which TPC contains the specified position (nullptr if none).
Class for approximate comparisons.
Projection_t ProjectPointOnPlane(Point_t const &point) const
Returns the projection of the specified point on the plane.
std::vector< TPCwithArea_t > addAreaToTPCs(std::vector< geo::TPCGeo const * > const &TPCs, geo::DriftPartitions::Decomposer_t const &decomposer)
constexpr bool strictlySmaller(Value_t a, Value_t b) const
Returns whether a is strictly smaller than b.
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
MaybeLogger_< ELseverityLevel::ELsev_error, true > LogProblem
constexpr bool strictlyGreater(Value_t a, Value_t b) const
Returns whether a is strictly greater than b.
std::vector< std::unique_ptr< Partition_t const >> Subpartitions_t
Type of list of subpartitions. It needs to preserve polymorphism.
Base element of a partitioned structure.
Partition of area along the depth dimension.
DriftVolume_t const * driftVolumeAt(Position_t const &pos) const
auto makeCPointerVector(BeginIter b, EndIter e)
Utilities to dump objects into a stream.
Vector RefDepthDir() const
Return the direction of reference plane depth.
auto makeVector3DComparison(RealType threshold)
Creates a Vector3DComparison from a RealComparisons object.
geo::Point_t Position_t
Type representing a position in 3D space.
std::unique_ptr< geo::part::Partition< geo::TPCGeo const > > makeDepthPartition(BeginIter beginTPCwithArea, EndIter endTPCwithArea)
Classes to project and compose a vector on a plane.
geo::DriftPartitions::DriftDir_t detectGlobalDriftDir(Range &&directions)
static bool sortKey(Key_t a, Key_t b)
std::unique_ptr< geo::part::Partition< geo::TPCGeo const > > makeWidthPartition(BeginIter beginTPCwithArea, EndIter endTPCwithArea)
lar::util::simple_geo::Rectangle< double > Area_t
Type of area covered by the partition.
static double Position(TPCgroup_t const &tpcg)
Point GetCenter() const
Returns the centre of the wire plane in world coordinates [cm].
Class managing comparisons between T objects via a Key key.
double MinZ() const
Returns the world z coordinate of the start of the box.
Area_t const & area() const
Returns the covered area.
unsigned int NTPC() const
Number of TPCs in this cryostat.
DecomposedVector_t DecomposePoint(Point_t const &point) const
Decomposes a 3D point in two components.
std::pair< double, geo::TPCGeo const * > TPCandPos_t
std::pair< std::vector< TPCwithArea_t const * >, std::vector< std::vector< TPCwithArea_t const * >::const_iterator > > sortAndGroupTPCsByRangeCoord(BeginIter beginTPCwithArea, EndIter endTPCwithArea)
void walk(Pred &&pred) const
Applies pred to all partitions.
Range_t width
Range along width direction.
auto makeTPCPartitionElement(TPCwithArea_t const &TPCinfo)
double Plane0Pitch(unsigned int p) const
Returns the center of the TPC volume in world coordinates [cm].
Provides a base class aware of world box coordinates.
Vector rounded01(Vector const &v, Scalar tol)
Returns a vector with all components rounded if close to 0, -1 or +1.
double MaxY() const
Returns the world y coordinate of the end of the box.
void addPartition(std::unique_ptr< TPCPartition_t > &&part)
Adds the specified partition as a new drift volume.
Range_t depth
Range along depth direction.
std::vector< TPCgroup_t > groupByDriftCoordinate(std::vector< TPCandPos_t > const &TPCs)
std::vector< DriftVolume_t > volumes
All drift volumes, sorted by position.
const TPCGeo & TPC(unsigned int itpc) const
Return the itpc'th TPC in the cryostat.
std::unique_ptr< geo::part::Partition< geo::TPCGeo const > > makeSortedPartition(BeginIter beginTPCwithArea, EndIter endTPCwithArea, SubpartMaker subpartMaker)
double MaxZ() const
Returns the world z coordinate of the end of the box.
std::vector< std::pair< geo::DriftPartitions::DriftDir_t, std::vector< geo::TPCGeo const * > > > groupTPCsByDriftDir(geo::CryostatGeo const &cryo)
geo::PlaneGeo const & LastPlane() const
Returns the last wire plane (the farther from TPC center).
std::vector< geo::TPCGeo const * > TPCs
TPCwithArea_t(Area_t area, geo::TPCGeo const *TPC)
void extendToInclude(Rectangle_t const &r)
Extends the range to include the specified point.
constexpr bool nonSmaller(Value_t a, Value_t b) const
Returns whether a is greater than (or equal to) b.
static Key_t key(Key_t k)
Direction_t DriftDir_t
Type representing the drift direction (assumed to have norm 1).
constexpr bool equal(Value_t a, Value_t b) const
Returns whether a and b are no farther than the threshold.
Data associated to a single drift volume.
std::unique_ptr< geo::part::Partition< geo::TPCGeo const > > makeGridPartition(BeginIter beginTPCwithArea, EndIter endTPCwithArea)
Namespace collecting geometry-related classes utilities.
std::vector< std::vector< TPCwithArea_t const * >::const_iterator > groupTPCsByRangeCoord(BeginIter beginTPCwithArea, EndIter endTPCwithArea)
double MinY() const
Returns the world y coordinate of the start of the box.
unsigned int checkTPCcoords(std::vector< geo::TPCGeo const * > const &TPCs)
cet::coded_exception< error, detail::translate > exception
Area_t::Range_t(Area_t::*) AreaRangeMember_t
Type of pointer to Area_t data member of type Range_t.
Encapsulate the construction of a single detector plane.
geo::Vector_t Direction_t
Type representing a direction in 3D space (norm is not constrained).
geo::Point_t Center() const
Returns the center point of the box.
std::vector< TPCandPos_t > sortTPCsByDriftCoord(std::vector< geo::TPCGeo const * > const &TPCs, geo::DriftPartitions::Decomposer_t const &decomp)