20 LArGraph::LArGraph(
const bool fullyConnect,
const int nSourceEdges,
const float maxSecondaryCosine,
const float maxSecondaryDistance) :
21 m_fullyConnect{fullyConnect},
47 Eigen::MatrixXf hitMatrix(caloHitList.size(), 2);
50 std::map<const CaloHit *, std::map<const CaloHit *, bool>> edgeMap;
51 for (
int r = 0;
r < hitMatrix.rows(); ++
r)
53 Eigen::RowVectorXf row(2);
54 row << hitMatrix(
r, 0), hitMatrix(
r, 1);
55 Eigen::MatrixXf norms((hitMatrix.rowwise() - row).
array().pow(2).rowwise().sum());
56 norms(
r, 0) = std::numeric_limits<float>::max();
58 norms.col(0).minCoeff(&index);
59 auto iter0{caloHitList.begin()};
60 std::advance(iter0,
r);
61 auto iter1{caloHitList.begin()};
62 std::advance(iter1, index);
63 edgeMap[*iter0][*iter1] =
true;
64 edgeMap[*iter1][*iter0] =
true;
65 norms(index, 0) = std::numeric_limits<float>::max();
68 CartesianPointVector sourceEdges({((*iter1)->GetPositionVector() - (*iter0)->GetPositionVector()).GetUnitVector()});
73 auto val{norms.col(0).minCoeff(&index)};
76 auto iter2{caloHitList.begin()};
77 std::advance(iter2, index);
78 norms(index, 0) = std::numeric_limits<float>::max();
79 const CartesianVector &vec{((*iter2)->GetPositionVector() - (*iter0)->GetPositionVector()).GetUnitVector()};
80 bool notColinear{
true};
81 for (
const CartesianVector &
other : sourceEdges)
91 sourceEdges.emplace_back(vec);
92 edgeMap[*iter0][*iter2] =
true;
93 edgeMap[*iter2][*iter0] =
true;
98 std::map<const CaloHit *, std::map<const CaloHit *, bool>> usedEdges;
99 for (
const auto &[pCaloHit1, map] : edgeMap)
101 for (
const auto &[pCaloHit2, dummy] : map)
103 if (usedEdges.find(pCaloHit1) != usedEdges.end())
105 std::map<const CaloHit *, bool> &innerMap{usedEdges[pCaloHit1]};
106 if (innerMap.find(pCaloHit2) != innerMap.end())
109 usedEdges[pCaloHit1][pCaloHit2] =
true;
110 usedEdges[pCaloHit2][pCaloHit1] =
true;
111 this->
m_edges.emplace_back(
new Edge(pCaloHit1, pCaloHit2));
119 hitToEdgesMap[pEdge->m_v0].emplace_back(pEdge);
120 hitToEdgesMap[pEdge->m_v1].emplace_back(pEdge);
124 while (graphs.size() > 1)
137 if (connectedHits.find(pRootCaloHit) != connectedHits.end())
139 graph.emplace_back(pRootCaloHit);
140 connectedHits[pRootCaloHit] =
true;
141 const EdgeVector &assocEdges{hitToEdgesMap.at(pRootCaloHit)};
142 for (
const Edge *
const edge : assocEdges)
144 if (pRootCaloHit == edge->m_v0)
145 this->
Walk(edge->m_v1, hitToEdgesMap, graph, connectedHits);
147 this->
Walk(edge->m_v0, hitToEdgesMap, graph, connectedHits);
156 for (
const auto &[pCaloHit, assocEdges] : hitToEdgesMap)
158 if (connectedHits.find(pCaloHit) != connectedHits.end())
160 graphs[pCaloHit] = CaloHitList{pCaloHit};
161 connectedHits[pCaloHit] =
true;
162 for (
const Edge *
const edge : assocEdges)
164 if (pCaloHit == edge->m_v0)
165 this->
Walk(edge->m_v1, hitToEdgesMap, graphs[pCaloHit], connectedHits);
167 this->
Walk(edge->m_v0, hitToEdgesMap, graphs[pCaloHit], connectedHits);
176 std::map<int, std::vector<int>> connectedGraphMap;
177 int i{0}, idx1{0}, idx2{0};
178 for (
const auto &[pCaloHit1, caloHitList1] : graphs)
181 Eigen::MatrixXf subGraphMatrix(caloHitList1.size(), 2);
182 this->
Vectorize(caloHitList1, subGraphMatrix);
183 float closestApproach{std::numeric_limits<float>::max()};
184 const CaloHit *pClosestHit1{
nullptr};
185 const CaloHit *pClosestHit2{
nullptr};
187 for (
const auto &[pCaloHit2, caloHitList2] : graphs)
190 auto begin{connectedGraphMap[i].begin()},
end{connectedGraphMap[i].end()};
191 if (pCaloHit1 == pCaloHit2 || std::find(
begin,
end, j) !=
end)
193 for (
const CaloHit *
const pCaloHit : caloHitList2)
195 const CartesianVector &pos{pCaloHit->GetPositionVector()};
196 Eigen::RowVectorXf row(2);
197 row << pos.GetX(), pos.GetZ();
198 Eigen::MatrixXf norms((subGraphMatrix.rowwise() - row).
array().pow(2).rowwise().sum());
200 float val{norms.col(0).minCoeff(&index)};
201 if (val < closestApproach)
203 auto iter{caloHitList1.begin()};
204 std::advance(iter, index);
205 pClosestHit1 = *iter;
206 pClosestHit2 = pCaloHit;
207 closestApproach = val;
213 if (pClosestHit1 && pClosestHit2)
215 const Edge *pEdge{
new Edge(pClosestHit1, pClosestHit2)};
216 this->
m_edges.emplace_back(pEdge);
217 hitToEdgesMap[pEdge->m_v0].emplace_back(pEdge);
218 hitToEdgesMap[pEdge->m_v1].emplace_back(pEdge);
219 connectedGraphMap[idx1].emplace_back(idx2);
220 connectedGraphMap[idx2].emplace_back(idx1);
230 for (
const CaloHit *
const pCaloHit : caloHitList)
232 const CartesianVector &pos{pCaloHit->GetPositionVector()};
233 hitMatrix(i, 0) = pos.GetX();
234 hitMatrix(i, 1) = pos.GetZ();
252 const CartesianVector &pos0{this->
m_v0->GetPositionVector()}, &pos1{this->
m_v1->GetPositionVector()};
253 const float dx{pos0.GetX() - pos1.GetX()}, dz{pos0.GetZ() - pos1.GetZ()};
255 return dx * dx + dz * dz;
int m_nSourceEdges
The number of edges to consider emerging from a source.
const EdgeVector & GetEdges() const
Retrieve the edges for this graph.
const pandora::CaloHit *const m_v1
An endpoint of the edge.
std::map< const pandora::CaloHit *, bool > HitUseMap
Header file for the lar calo hit class.
float m_maxSecondaryCosine
The number of edges to consider emerging from a source.
boost::graph_traits< ModuleGraph >::edge_descriptor Edge
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
std::vector< const Edge * > EdgeVector
void MakeGraph(const pandora::CaloHitList &caloHitList)
Construct a graph from a list of calo hits.
auto array(Array const &a)
Returns a manipulator which will print the specified array.
void ConnectRegions(const HitConnectionsMap &graphs, HitEdgeMap &hitToEdgesMap)
Identify the different disconnected sub graphs in a set of eges.
float m_maxSecondaryDistance
The number of edges to consider emerging from a source.
Edge(const pandora::CaloHit *const pVertex0, const pandora::CaloHit *const pVertex1)
Constructor.
EdgeVector m_edges
The edges defining the graph.
std::map< const pandora::CaloHit *, pandora::CaloHitList > HitConnectionsMap
const pandora::CaloHit *const m_v0
An endpoint of the edge.
void Walk(const pandora::CaloHit *const pCaloHit, const HitEdgeMap &hitToEdgesMap, pandora::CaloHitList &graph, HitUseMap &connectedHits) const
Walk along node edges to define a connected graph.
void IdentifyDisconnectedRegions(const HitEdgeMap &hitToEdgesMap, HitConnectionsMap &graphs) const
Identify the different disconnected sub graphs in a set of eges.
decltype(auto) constexpr begin(T &&obj)
ADL-aware version of std::begin.
float LengthSquared() const
Compute the square of the length of this edge.
void Vectorize(const pandora::CaloHitList &caloHitList, Eigen::MatrixXf &hitMatrix) const
Convert a list of calo hits into an Eigen matrix.
std::map< const pandora::CaloHit *, EdgeVector > HitEdgeMap
bool m_fullyConnect
Whether or not to connect any disconnected regions.