11 #ifndef LARCOREALG_GEOMETRY_PARTITIONS_H
12 #define LARCOREALG_GEOMETRY_PARTITIONS_H
26 #include <type_traits>
59 template <
typename Stream>
71 template <AreaOwner::AreaRangeMember_t Range>
96 template <
typename Data>
99 template <
typename Stream>
102 std::string indent =
"", std::string firstIndent =
""
124 template <
typename Stream,
typename Data>
127 std::string indent =
"", std::string firstIndent =
""
156 (std::string indent, std::string firstIndent)
const;
187 template <
typename Data>
221 (std::string indent, std::string firstIndent)
const
225 std::string
describe(std::string indent =
"")
const
226 {
return describe(indent, indent); }
245 template <
typename Pred>
260 (std::string indent, std::string firstIndent)
const
265 template <
typename Pred>
274 template <
typename Data>
285 :
Base_t(area), myData(myData)
300 (std::string indent, std::string firstIndent)
const override;
307 template <
typename Data>
321 template <
typename Data>
371 (std::string indent, std::string firstIndent)
const override;
395 template <
typename Data,
typename Sorter>
427 Data_t* defData =
nullptr,
448 template<
typename Data, PartitionBase::AreaRangeMember_t Range>
450 <Data, details::PartitionSorterByAreaRangeLower<Range>>
463 template <
typename Data>
476 (
double ,
double d)
const override
488 template <
typename Data>
501 (
double w,
double )
const override
513 template <
typename Data>
541 unsigned int nDepthPartitions,
unsigned int nWidthPartitions,
550 unsigned int nDepthPartitions,
Data_t* defData =
nullptr
563 auto part(std::size_t iDepth, std::size_t iWidth) ->decltype(
auto)
565 auto part(std::size_t iDepth, std::size_t iWidth)
const ->decltype(
auto)
573 (
unsigned int nD,
unsigned int nW)
const;
576 (
unsigned int nD,
unsigned int nW)
const;
580 (std::string indent, std::string firstIndent)
const override;
584 typename BeginIter,
typename EndIter
587 BeginIter b, EndIter
e,
588 std::size_t
const nGroups,
589 std::size_t
const startDelta,
590 std::size_t
const stride
606 (std::string, std::string firstIndent)
const
608 std::ostringstream sstr;
609 sstr << firstIndent <<
"partition covers ";
627 template <
typename T,
typename =
void>
630 template <
typename Part>
635 <std::is_base_of<PartitionBase, std::decay_t<Part>>::value>
637 :
public std::true_type
641 template <
typename T>
647 template <
typename,
typename =
void>
650 template <
typename PartPtr>
655 <is_partition_type_v<decltype(*std::declval<PartPtr>())>>
657 :
public std::true_type
661 template <
typename T>
667 template <
typename,
typename =
void>
670 template <
typename Iter>
675 <is_partition_ptr_v<std::decay_t<typename Iter::value_type>>>
677 :
public std::true_type
685 template <AreaOwner::AreaRangeMember_t Range>
687 static constexpr
auto range = Range;
692 {
return (*
this)(r.
lower); }
694 {
return (*
this)(area.*
range); }
696 {
return (*
this)(area.
area()); }
698 {
return (*
this)(*ptr); }
706 template <PartitionBase::AreaRangeMember_t Range>
715 using Base_t::operator();
730 template <PartitionBase::AreaRangeMember_t Range>
731 struct PartitionSorterByAreaRangeLower {
736 static constexpr
auto range = Range;
738 template <
typename T>
747 template <
typename A,
typename B>
765 template <
typename Data>
766 template <
typename Stream>
769 std::string indent , std::string firstIndent
773 std::string typeName = lar::debug::demangle<Data>();
775 out << typeName <<
"[" << ((
void*) data) <<
"]";
778 out <<
"no '" << typeName <<
"' data";
783 template <
typename Stream,
typename Data>
786 std::string indent , std::string firstIndent
790 (std::forward<Stream>(out), data, indent, firstIndent);
797 template <
typename Data>
802 template <
typename Data>
803 template <
typename Pred>
809 for (
auto const& subPart: start->
parts())
810 subPart->walk(std::forward<Pred>(pred));
818 template <
typename Data>
820 (std::string indent, std::string firstIndent)
const
822 std::string
msg = Base_t::doDescribe(indent, firstIndent);
824 std::ostringstream sstr;
840 template <
typename Data>
844 if (!Base_t::contains(
w, d))
return nullptr;
846 auto part = findPart(
w, d);
847 return part? part->atPoint(
w, d): Base_t::data();
852 template <
typename Data>
854 (std::string indent, std::string firstIndent)
const
856 std::string
msg = firstIndent + describeIntro();
857 if (Base_t::data()) {
858 std::ostringstream sstr;
864 for (
auto const& part: parts()) {
865 msg +=
"\n" + indent +
" * ";
866 msg += part->describe(indent +
" ",
"");
874 template <
typename Data>
883 template <
typename Data,
typename Sorter>
887 auto pbegin = Base_t::parts().cbegin();
888 auto iPart = std::upper_bound(pbegin, Base_t::parts().
cend(), key, sorter);
889 return (iPart == pbegin)?
nullptr: (--iPart)->
get();
894 template <
typename Data,
typename Sorter>
901 std::sort(Base_t::myParts.
begin(), Base_t::myParts.
end(), sorter);
909 template <
typename Data>
911 std::ostringstream sstr;
913 <<
Base_t::size() <<
" partitions along depth covering " << Base_t::area();
921 template <
typename Data>
923 std::ostringstream sstr;
925 <<
Base_t::size() <<
" partitions along width covering " << Base_t::area();
933 template <
typename Data>
937 unsigned int nDepthPartitions,
unsigned int nWidthPartitions,
940 :
Base_t(area,
std::move(subpartitions), defData)
941 , widthSeps(computeWidthSeps(nDepthPartitions, nWidthPartitions))
942 , depthSeps(computeDepthSeps(nDepthPartitions, nWidthPartitions))
944 assert(nWidthPartitions * nDepthPartitions ==
Base_t::size());
948 template <
typename Data>
952 unsigned int nDepthPartitions,
Data_t* defData
955 area,
std::move(subpartitions), nDepthPartitions,
956 (nDepthPartitions? subpartitions.
size()/nDepthPartitions: 0),
963 template <
typename Data>
965 (std::string indent, std::string firstIndent)
const
967 std::ostringstream sstr;
968 sstr << firstIndent << Base_t::describeIntro()
969 <<
" in a (WxD) = " << nWidthParts() <<
" x " << nDepthParts() <<
" grid";
970 if (Base_t::data()) {
974 for (std::size_t iDepth = 0; iDepth < nDepthParts(); ++iDepth) {
975 for (std::size_t iWidth = 0; iWidth < nWidthParts(); ++iWidth) {
976 sstr <<
"\n" << indent <<
" [" << iDepth <<
"][" << iWidth <<
"] "
977 << part(iDepth, iWidth)->describe(indent +
" ",
"");
986 template <
typename Data>
990 auto const iWidth = std::upper_bound(widthSeps.cbegin(), widthSeps.cend(),
w);
991 if (iWidth == widthSeps.cbegin())
return nullptr;
992 auto const iDepth = std::upper_bound(depthSeps.cbegin(), depthSeps.cend(), d);
993 if (iDepth == depthSeps.cbegin())
return nullptr;
1002 template <
typename Data>
1004 (
unsigned int,
unsigned int nW)
const
1006 return detectSeparators<&Area_t::width>
1007 (Base_t::parts().cbegin(), Base_t::parts().cend(), nW, 1U, nW);
1011 template <
typename Data>
1013 (
unsigned int nD,
unsigned int nW)
const
1015 return detectSeparators<&Area_t::depth>
1016 (Base_t::parts().cbegin(), Base_t::parts().cend(), nD, nW, 1U);
1020 template <
typename Data>
1023 typename BeginIter,
typename EndIter
1026 BeginIter b, EndIter
e,
1027 std::size_t
const nGroups,
1028 std::size_t
const startDelta,
1029 std::size_t
const stride
1060 "Begin iterator does not point to a pointer to partition type");
1065 std::size_t
const nPartsInGroup = nParts / nGroups;
1068 = [b](std::size_t index){
return std::next(b, index)->get(); };
1070 std::vector<double> seps(nGroups);
1071 for (
size_t g = 0;
g < nGroups; ++
g) {
1073 double& sep = seps[
g];
1076 std::size_t index =
g * startDelta;
1077 sep = lowerBound(part(index));
1079 std::size_t
const iend = index + nPartsInGroup * stride;
1080 while ((index += stride) < iend) {
1081 double const l = lowerBound(part(index));
1082 if (sep > l) sep = l;
1092 #endif // LARCOREALG_GEOMETRY_PARTITIONS_H
Partition_t const * findPartWithKey(double key) const
Returns the only partition which could contain the specified key.
AreaOwner(Area_t const &area)
Constructor: sets the covered area and no subpartitions.
Trait type evaluating true if T is iterator to some PartitionBase.
PartitionBase(Area_t const &area)
Constructor: sets the covered area and no subpartitions.
PartitionContainer(Area_t const &area, Subpartitions_t &&subpartitions, Data_t *defData=nullptr)
Constructor: sets the partition.
A basic interface for objects owning an area.
double std(const std::vector< short > &wf, const double ped_mean, size_t start, size_t nsample)
void describePartitionData(Stream &&out, Data const *data, std::string indent="", std::string firstIndent="")
Describes a data object for Partition::describe() method.
virtual Partition_t const * findPart(double w, double d) const =0
Returns the only partition which could contain the specified width.
std::vector< double > computeDepthSeps(unsigned int nD, unsigned int nW) const
Computes and returns width separation levels proper for depthSeps.
constexpr bool is_partition_type_v
Constant true if T is derived from PartitionBase.
static Key_t key(Key_t k)
static auto key(T const &obj)
Partition of area along the width dimension.
void initParts()
Performs initialization on the specified subpartition list.
Partition< Data > Partition_t
Base type of the partition.
virtual std::string describeIntro() const override
Introduction to the description of the subpartitions.
bool contains(Data_t w, Data_t d) const
Returns whether the specified point is in the area.
std::size_t size(FixedBins< T, C > const &) noexcept
Class providing custom dump for data contained in the partition.
std::vector< double > depthSeps
Separators for depth dimension.
virtual Data_t * data() const
Returns the datum directly stored (nullptr if none).
Ordering class to sort partition by specified range (lower boundary).
auto part(std::size_t iDepth, std::size_t iWidth) -> decltype(auto)
virtual Data_t * atPoint(double w, double d) const override
Returns stored datum only if point is covered, nullptr otherwise.
bool operator()(A const &a, B const &b) const
std::vector< double > widthSeps
Separators for width dimension.
AreaOwner::AreaRangeMember_t AreaRangeMember_t
virtual std::string doDescribe(std::string indent, std::string firstIndent) const
Returns a description of the partition.
virtual std::string describeIntro() const override
Introduction to the description of the subpartitions.
PartitionRangeLowerBoundExtractor< Range > KeyExtractor_t
auto cend(FixedBins< T, C > const &) noexcept
bool contains(double w, double d) const
Returns whether the specified point is covered by this object.
std::vector< double > computeWidthSeps(unsigned int nD, unsigned int nW) const
Computes and returns width separation levels proper for widthSeps.
std::string describe(std::string indent="") const
Returns a description of the partition.
Partition(Area_t const &area)
Constructor: sets the covered area and no subpartitions.
Trait type evaluating true if T is derived from PartitionBase.
Non-template definitions and data for Partition class hierarchy.
virtual std::string doDescribe(std::string indent, std::string firstIndent) const override
Describes this and each of the subpartitions.
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.
virtual Subpartitions_t const & parts() const
Returns a list of all subpartitions.
Partition of area along the depth dimension.
virtual Base_t::Partition_t const * findPart(double w, double) const override
Returns the only partition which could contain the specified depth.
virtual Data_t * atPoint(double w, double d) const =0
Returns the (sub)partition including the specified coordinates.
Area_t myArea
Covered area.
double distance(geo::Point_t const &point, CathodeDesc_t const &cathode)
Returns the distance of a point from the cathode.
virtual std::string doDescribe(std::string indent, std::string firstIndent) const override
Returns a description of the partition.
Partition of area along a area range dimension (width or depth).
lar::util::simple_geo::Rectangle< double > Area_t
Type of area covered by the partition.
Partition< Data > Partition_t
This type.
auto end(FixedBins< T, C > const &) noexcept
typename std::enable_if< B, T >::type enable_if_t
Area_t const & area() const
Returns the covered area.
PartitionWithData(Area_t const &area, Data_t *myData)
Constructor: sets the covered area and the contained datum.
std::size_t size() const
Returns the number of contained subpartitions.
void walk(Pred &&pred) const
Applies pred to all partitions.
Range< Data_t > Range_t
Type for dimension boundaries.
static Subpartitions_t const NoSubparts
Subpartitions (if any).
Subpartitions_t myParts
List of subpartitions.
virtual Data_t * data() const override
Returns the datum directly stored (nullptr if none).
Data_t * myData
The contained datum.
void dumpArea(Stream &&out) const
Output the owned area into an output stream.
std::string describe(std::string indent, std::string firstIndent) const
Returns a description of the partition.
std::size_t nWidthParts() const
Number of partitions on width direction.
virtual Subpartitions_t const & parts() const override
Returns a list of the subpartitions owned.
auto begin(FixedBins< T, C > const &) noexcept
static bool sortKey(Key_t a, Key_t b)
static constexpr auto range
Unpartitioned element ("leaf") of a partitioned area.
Partition divided in subpartitions (abstract).
decltype(Sorter_t::key(std::declval< PartitionBase >())) Key_t
Type of sorting key. In short: double.
Data Data_t
Type of data stored in the partition.
SortedPartition(Area_t const &area, Subpartitions_t &&subpartitions, Data_t *defData=nullptr, Sorter_t sorter={})
Constructor: sets the partition.
Functions to help debugging by instrumenting code.
virtual Partition_t const * findPart(double w, double d) const override
Returns the only partition which could contain the specified depth.
constexpr bool is_partition_ptr_v
Constant true if T is pointer to some PartitionBase.
std::string to_string(WindowPattern const &pattern)
Sorter_t sorter
Object used for sorting and binary search.
static std::vector< double > detectSeparators(BeginIter b, EndIter e, std::size_t const nGroups, std::size_t const startDelta, std::size_t const stride)
virtual std::string doDescribe(std::string indent, std::string firstIndent) const override
Prints the information about the partition grid.
auto part(std::size_t iDepth, std::size_t iWidth) const -> decltype(auto)
SortedPartition< Data, details::PartitionSorterByAreaRangeLower< Range >> Base_t
Base class.
Some simple functions to represent geometry entities.
Partition of area sorted across a dimension.
virtual std::string describeIntro() const
Introduction to the description of the subpartitions.
std::size_t nDepthParts() const
virtual Base_t::Partition_t const * findPart(double, double d) const override
Returns the only partition which could contain the specified depth.
A container of partitions organised in a width/depth rectangular grid.
Trait type evaluating true if T is pointer to some PartitionBase.
typename Partition_t::Subpartitions_t Subpartitions_t
Partition< Data > Partition_t
Base type of the partition.
std::size_t nParts() const
Returns the number of subparts in the partition (0 if simple element).
PartitionBase::Area_t Area_t
Type of area.
virtual Data_t * atPoint(double w, double d) const override
Returns stored datum only if point is covered, nullptr otherwise.
std::string describeArea(std::string indent, std::string firstIndent) const
Returns a description of the partition area.
Partition< Data > Base_t
Base class.
Data_t lower
Starting coordinate.
GridPartition(Area_t const &area, Subpartitions_t &&subpartitions, unsigned int nDepthPartitions, unsigned int nWidthPartitions, Data_t *defData=nullptr)
Creates a partition with a grid of subpartitions.
Partition also containing data directly.
PartitionDataDescriber(Stream &&out, Data const *data, std::string indent="", std::string firstIndent="")
Constructor; see describePartitionData() for argument description.
PartitionContainer< Data > Base_t
Base class.
typename Partition_t::Data_t Data_t
Type of contained data.
Area_t::Range_t(Area_t::*) AreaRangeMember_t
Type of pointer to Area_t data member of type Range_t.
virtual ~Partition()=default
Destructor (default, virtual).