22 #include "cetlib_except/exception.h" 31 #include <type_traits> 41 template <
typename T,
typename CONT>
42 void append(std::vector<T>&
dest, CONT
const& src) {
45 dest.insert(dest.end(),
cbegin(src),
cend(src));
50 void append(std::vector<T>& dest, std::vector<T>&& src) {
52 else append(dest, src);
58 template <
typename Cont>
59 auto keys(Cont
const&
m) {
61 std::vector<typename Cont::value_type::first_type>
result;
62 result.reserve(m.size());
65 std::back_inserter(result), [](
auto const&
p){
return p.first; }
82 auto iVol = volumeAfter(drift);
83 if (iVol == volumes.cbegin())
return nullptr;
84 if (!(--iVol)->coversDrift(drift))
return nullptr;
94 ?
volume->partition->atPoint(comp.projection.X(), comp.projection.Y())
121 struct CoverageExtractor {
145 TPCpart.
walk(extractor);
146 return extractor.coverage;
161 std::vector<geo::TPCGeo const*>
TPCs;
164 TPCgroup_t(
double pos, std::vector<geo::TPCGeo const*>&& TPCs)
165 : pos(pos), TPCs(
std::
move(TPCs)) {}
179 <std::pair<geo::DriftPartitions::DriftDir_t, std::vector<geo::TPCGeo const*>>>
198 auto const nTPCs = cryo.
NTPC();
199 for (
unsigned int iTPC = 0; iTPC < nTPCs; ++iTPC) {
202 decltype(
auto) driftDir = TPC.
DriftDir();
204 std::size_t iGroup = 0;
205 for (; iGroup < result.size(); ++iGroup) {
206 if (vectorIs.nonEqual(driftDir, result[iGroup].first))
continue;
207 result[iGroup].second.push_back(&TPC);
212 if (iGroup == result.size()) {
215 std::vector<geo::TPCGeo const*>{ &TPC }
227 std::vector<geo::TPCGeo const*>
const& TPCs,
243 {
return decomp.
PointNormalComponent(geo::vect::convertTo<geo::DriftPartitions::Position_t>(
TPC.FirstPlane().GetCenter())); };
245 std::vector<TPCandPos_t>
result;
246 result.reserve(TPCs.size());
247 std::transform(TPCs.cbegin(), TPCs.cend(), std::back_inserter(result),
253 std::sort(result.begin(), result.end());
260 (std::vector<TPCandPos_t>
const& TPCs)
268 if (TPCs.empty())
return {};
270 geo::TPCGeo const& firstTPC = *(TPCs.front().second);
274 double const groupThickness = 10.0
277 auto iFirstTPC = TPCs.cbegin(), tend = TPCs.cend();
279 std::vector<TPCgroup_t>
result;
280 while (iFirstTPC != tend) {
281 double const posEnd = iFirstTPC->first + groupThickness;
283 std::vector<geo::TPCGeo const*> TPCs;
284 auto iEndGroup = iFirstTPC;
286 TPCs.push_back(iEndGroup->second);
287 sumPos += iEndGroup->first;
289 }
while ((iEndGroup != tend) && (iEndGroup->first < posEnd));
291 double const averagePos = sumPos / TPCs.size();
292 result.emplace_back(averagePos,
std::move(TPCs));
294 iFirstTPC = iEndGroup;
312 auto iTPC = TPCs.cbegin(), tend = TPCs.cend();
315 <<
"checkTPCcoords() got an empty partition.";
320 decltype(
auto) refDriftDir = refTPC.
DriftDir();
331 while (++iTPC != tend) {
334 if (vectorIs.nonEqual(TPC.
DriftDir(), refDriftDir)) {
336 <<
"Incompatible drift directions between " << TPC.
ID()
342 if (coordIs.
nonEqual(driftPos, refDriftPos)) {
344 <<
"Incompatible drift coordinate between " << TPC.
ID()
345 <<
" (" << driftPos <<
"( and " << refTPC.
ID() <<
" (" 346 << refDriftPos <<
")";
355 template <
typename Range>
363 auto iDir =
cbegin(directions);
364 auto dend =
cend(directions);
365 if (!(iDir != dend)) {
367 <<
"detectGlobalDriftDir(): no TPCs provided!\n";
371 auto compatibleDir = [comp](
auto const&
a,
auto const&
b)
374 auto const dir = *(iDir++);
375 for (; iDir != dend; ++iDir) {
376 if (compatibleDir(
dir, *iDir))
continue;
383 return ((
dir.X() <= 0.0) && (
dir.Y() <= 0.0) && (
dir.Z() <= 0.0))? -
dir:
dir;
395 :
geo::part::AreaOwner(area), TPC(TPC) {}
419 { lowerProj.X(), upperProj.X(),
true },
420 { lowerProj.Y(), upperProj.Y(),
true }
427 std::vector<geo::TPCGeo const*>
const& TPCs,
433 std::vector<TPCwithArea_t>
result;
434 result.reserve(TPCs.size());
436 for (
auto const& TPC: TPCs)
437 result.emplace_back(
TPCarea(*TPC, decomposer), TPC);
444 template <
typename BeginIter,
typename EndIter>
446 (BeginIter TPCbegin, EndIter TPCend)
453 auto iTPC = TPCbegin;
462 template <
typename Key,
typename ExtractKey,
typename Comparer = std::less<Key>>
471 template <
typename Data>
474 template <
typename A,
typename B>
475 bool operator() (
A const&
a,
B const&
b)
const 476 {
return sortKey(
key(a),
key(b)); }
483 template<geo::part::AreaOwner::AreaRangeMember_t Range>
496 typename BeginIter,
typename EndIter
500 (BeginIter beginTPCwithArea, EndIter endTPCwithArea)
518 auto gbegin = beginTPCwithArea;
519 while (gbegin != endTPCwithArea) {
521 groupStart.push_back(gbegin);
526 auto range = (*gbegin)->area().*sortingRange;
528 while (++gend != endTPCwithArea) {
537 auto const& TPCrange = (*gend)->area().*sortingRange;
538 if (coordIs.
nonSmaller(TPCrange.lower, range.upper))
540 range.extendToInclude(TPCrange);
556 typename BeginIter,
typename EndIter
559 std::vector<TPCwithArea_t const*>,
563 (BeginIter beginTPCwithArea, EndIter endTPCwithArea)
568 std::vector<TPCwithArea_t const*> TPCs(beginTPCwithArea, endTPCwithArea);
569 if (TPCs.size() <= 1)
return {};
577 = groupTPCsByRangeCoord<sortingRange>(TPCs.cbegin(), TPCs.cend());
578 assert(!TPCgroups.empty());
587 typename BeginIter,
typename EndIter,
typename TPCendIter,
588 typename SubpartMaker
591 BeginIter itTPCbegin, EndIter itTPCend, TPCendIter TPCend,
592 SubpartMaker subpartMaker
621 auto igbegin = itTPCbegin;
622 while (igbegin != itTPCend) {
623 auto const gbegin = *igbegin;
624 auto const gend = (++igbegin == itTPCend)? TPCend: *igbegin;
633 auto subpart = subpartMaker(gbegin, gend);
634 if (!subpart)
return {};
636 subparts.emplace_back(
std::move(subpart));
646 return std::make_unique<geo::part::PartitionElement<geo::TPCGeo const>>
653 template <
typename BeginIter,
typename EndIter>
655 (BeginIter beginTPCwithArea, EndIter endTPCwithArea);
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>
663 std::unique_ptr<geo::part::Partition<geo::TPCGeo const>>
makePartition 664 (BeginIter beginTPCwithArea, EndIter endTPCwithArea);
669 typename TPCPartitionResultType,
671 typename BeginIter,
typename EndIter,
672 typename SubpartMaker
675 BeginIter beginTPCwithArea, EndIter endTPCwithArea,
676 SubpartMaker subpartMaker
701 auto const TPCgroupInfo
702 = sortAndGroupTPCsByRangeCoord<Range>(beginTPCwithArea, endTPCwithArea);
703 std::vector<TPCwithArea_t const*>
const& TPCs = TPCgroupInfo.first;
705 TPCgroups = TPCgroupInfo.second;
707 if (TPCs.empty())
return {};
713 (TPCgroups.cbegin(), TPCgroups.cend(), TPCs.cend(), subpartMaker);
716 if (subparts.size() == 1)
return {};
726 return std::make_unique<TPCPartitionResultType>
733 template <
typename BeginIter,
typename EndIter>
735 (BeginIter beginTPCwithArea, EndIter endTPCwithArea)
741 (beginTPCwithArea, endTPCwithArea, &makeDepthPartition<BeginIter, EndIter>);
745 template <
typename BeginIter,
typename EndIter>
747 (BeginIter beginTPCwithArea, EndIter endTPCwithArea)
753 (beginTPCwithArea, endTPCwithArea, &makeWidthPartition<BeginIter, EndIter>);
758 template <
typename BeginIter,
typename EndIter>
760 (BeginIter beginTPCwithArea, EndIter endTPCwithArea)
783 auto const TPCgroupInfo = sortAndGroupTPCsByRangeCoord<&Area_t::width>
784 (beginTPCwithArea, endTPCwithArea);
785 std::vector<TPCwithArea_t const*>
const& TPCs = TPCgroupInfo.first;
787 TPCgroups = TPCgroupInfo.second;
789 if (TPCs.empty())
return {};
791 if (TPCs.size() < 4)
return {};
793 unsigned int const nWidthParts = TPCgroups.size();
794 if (nWidthParts <= 1)
return {};
799 auto const FirstColGroupInfo
800 = sortAndGroupTPCsByRangeCoord<&Area_t::depth>(TPCgroups[0], TPCgroups[1]);
801 std::vector<TPCwithArea_t const*>
const& FirstColTPCs
802 = FirstColGroupInfo.first;
804 FirstColGroups = FirstColGroupInfo.second;
806 if (FirstColTPCs.empty())
return {};
807 if (FirstColGroups.size() <= 1 )
return {};
819 std::vector<Area_t::Range_t> depthGaps;
820 auto icnext = FirstColGroups.cbegin(), icprev = icnext,
821 icend = FirstColGroups.cend();
822 while (++icnext != icend) {
827 auto const cprev = *icprev;
828 auto const cnext = *icnext;
830 depthGaps.emplace_back
831 ((*cprev)->area().depth.upper, (*cnext)->area().depth.lower);
835 assert(!depthGaps.empty());
840 auto igbegin = TPCgroups.cbegin();
841 while (++igbegin != TPCgroups.cend()) {
845 auto igend = std::next(igbegin);
846 auto gbegin = *igbegin;
847 auto gend = (igend == TPCgroups.cend())? TPCs.cend(): *igend;
849 auto const ColGroupInfo
850 = sortAndGroupTPCsByRangeCoord<&Area_t::depth>(gbegin, gend);
851 std::vector<TPCwithArea_t const*>
const& ColTPCs = ColGroupInfo.first;
853 ColGroups = ColGroupInfo.second;
856 if (ColTPCs.empty())
return {};
857 if (ColGroups.size() <= 1)
return {};
862 std::vector<TPCwithArea_t::Area_t::Range_t> groupDepths(ColGroups.size());
863 auto iGDepth = groupDepths.begin();
864 for (
auto icgstart = ColGroups.cbegin(); icgstart != ColGroups.cend();
865 ++icgstart, ++iGDepth)
867 auto const icgend = std::next(icgstart);
868 auto ictpc = *icgstart;
869 auto const ictend = (icgend == ColGroups.cend())? ColTPCs.cend(): *icgend;
870 while (ictpc != ictend)
871 iGDepth->extendToInclude((*(ictpc++))->area().depth);
877 auto iGap = depthGaps.begin();
878 while (iGap != depthGaps.end()) {
879 Area_t::Range_t& gap = *iGap;
884 bool bGoodGap =
false;
886 auto iCGroup = std::lower_bound(
887 groupDepths.cbegin(), groupDepths.cend(), gap.upper,
892 if ((iCGroup != groupDepths.begin()) && (iCGroup != groupDepths.end())) {
893 Area_t::Range_t
const& before = *(std::prev(iCGroup));
894 Area_t::Range_t
const& after = *iCGroup;
895 Area_t::Range_t
const TPCgap{ before.upper, after.lower };
899 iGap->lower = TPCgap.lower;
901 iGap->upper = TPCgap.upper;
904 bGoodGap = coordIs.
nonSmaller(iGap->upper, iGap->lower);
910 if (bGoodGap) ++iGap;
911 else iGap = depthGaps.erase(iGap);
915 if (depthGaps.empty())
return {};
922 std::vector<double> depthSep;
924 depthGaps.cbegin(), depthGaps.cend(), std::back_inserter(depthSep),
925 [](
auto const&
r){
return (
r.lower +
r.upper) / 2.0; }
927 unsigned int const nDepthParts = depthSep.size() + 1;
933 (nWidthParts * nDepthParts);
936 unsigned int iWidth = 0;
937 for (
auto igbegin = TPCgroups.cbegin(); igbegin != TPCgroups.cend();
942 auto igend = std::next(igbegin);
943 auto gbegin = *igbegin;
944 auto gend = (igend == TPCgroups.cend())? TPCs.cend(): *igend;
945 std::vector<TPCwithArea_t const*> ColTPCs(gbegin, gend);
946 std::sort(ColTPCs.begin(), ColTPCs.end(),
949 unsigned int iDepth = 0;
950 auto cgstart = ColTPCs.cbegin(), TPCend = ColTPCs.cend();
951 for (
double sep: depthSep) {
961 while (cgend != cgstart) {
962 auto cglast = std::prev(cgend);
963 if (coordIs.
strictlySmaller((*cglast)->area().depth.lower, sep))
break;
966 assert(cgstart != cgend);
972 if (!part)
return {};
973 totalArea.extendToInclude(part->area());
974 subparts[iDepth * nWidthParts + iWidth] =
std::move(part);
984 if (!part)
return {};
985 totalArea.extendToInclude(part->area());
986 subparts[iDepth * nWidthParts + iWidth] =
std::move(part);
990 return std::make_unique<geo::part::GridPartition<geo::TPCGeo const>>
991 (totalArea,
std::move(subparts), nWidthParts, nDepthParts);
997 template <
typename BeginIter,
typename EndIter>
998 std::unique_ptr<geo::part::Partition<geo::TPCGeo const>>
makePartition 999 (BeginIter beginTPCwithArea, EndIter endTPCwithArea)
1024 using value_type = std::remove_reference_t<decltype(*beginTPCwithArea)>;
1026 std::is_pointer<value_type>()
1028 <std::decay_t<std::remove_pointer_t<value_type>>,
TPCwithArea_t>(),
1029 "Iterators must point to TPCwithArea_t pointers." 1039 if (gPart)
return gPart;
1047 if (wPart->nParts() < dPart->nParts())
return wPart;
1070 template <
typename BeginIter,
typename EndIter>
1072 using value_type =
typename BeginIter::value_type;
1073 std::vector<value_type const*>
result;
1075 std::transform(b, e, std::back_inserter(result),
1076 [](
auto& obj){
return std::addressof(obj); });
1080 template <
typename T>
1086 std::unique_ptr<geo::DriftPartitions::TPCPartition_t>
makePartition 1087 (std::vector<TPCwithArea_t>
const& TPCs)
1123 std::vector<TPCgroup_t> TPCgroups;
1124 for (
auto const& TPCsOnDriftDir: TPCsByDriftDir) {
1132 for (
auto const& TPCgroup: TPCgroups) {
1136 <<
"TPCs in partition have different drift directions (" 1137 << errors <<
" errors found in " << TPCgroup.TPCs.size() <<
" TPCs).\n";
1145 for (
auto const& TPCgroup: TPCgroups) {
1150 e <<
"Failed to construct partition out of " << TPCs.size() <<
" TPCs:";
1151 for (
auto const& TPCinfo: TPCs) {
1152 e <<
"\n at " << TPCinfo.area() <<
" TPC ";
1153 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)
decltype(auto) constexpr cend(T &&obj)
ADL-aware version of std::cend.
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.
Geometry information for a single TPC.
SortTPCareaByAreaRangeLower<&geo::part::AreaOwner::Area_t::depth > SortTPCwithAreaByDepth
static const std::string volume[nvol]
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.
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
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)
void extendToInclude(Data_t)
Extends the range to include the specified point.
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 distance(double x1, double y1, double z1, double x2, double y2, double z2)
double Plane0Pitch(unsigned int p) const
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.
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
Encapsulate the construction of a single detector plane.
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).
decltype(auto) constexpr cbegin(T &&obj)
ADL-aware version of std::cbegin.
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)
LArSoft geometry interface.
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)