303 std::vector<unsigned int> mergedClusters;
305 std::vector<art::PtrVector<recob::Hit> > oldClusters = planeClusters;
308 std::sort(oldClusters.begin(), oldClusters.end(), [](
const art::PtrVector<recob::Hit> &
a,
const art::PtrVector<recob::Hit> &b) {
return a.size() > b.size();} );
311 unsigned int nclusters = 0;
312 for (
auto &
cluster : oldClusters)
316 bool mergedAllClusters =
false;
317 while (!mergedAllClusters) {
320 art::PtrVector<recob::Hit>
cluster;
323 for (
unsigned int initCluster = 0; initCluster < oldClusters.size(); ++initCluster) {
324 if (oldClusters.at(initCluster).size() <
fMinMergeClusterSize or std::find(mergedClusters.begin(), mergedClusters.end(), initCluster) != mergedClusters.end())
continue;
325 cluster = oldClusters.at(initCluster);
326 mergedClusters.push_back(initCluster);
331 bool mergedAllToThisCluster =
false;
332 while (!mergedAllToThisCluster) {
336 for (
unsigned int trialCluster = 0; trialCluster < oldClusters.size(); ++trialCluster) {
338 if (oldClusters.at(trialCluster).size() <
fMinMergeClusterSize or std::find(mergedClusters.begin(), mergedClusters.end(), trialCluster) != mergedClusters.end())
continue;
341 TPrincipal *pca1 =
new TPrincipal(2,
""), *pca2 =
new TPrincipal(2,
"");
346 TVector2 chargePoint1 = TVector2(0,0), chargePoint2 = TVector2(0,0);
347 double totalCharge1 = 0, totalCharge2 = 0;
349 for (
auto &hit1 : cluster) {
354 chargePoint1 += hit1->Integral() * pos;
355 totalCharge1 += hit1->Integral();
357 for (
auto &hit2 : oldClusters.at(trialCluster)) {
362 chargePoint2 += hit2->Integral() * pos;
363 totalCharge2 += hit2->Integral();
366 pca1->MakePrincipals();
367 pca2->MakePrincipals();
370 TVector2 direction1 = TVector2( (*pca1->GetEigenVectors())[0][0], (*pca1->GetEigenVectors())[1][0] ).Unit();
371 TVector2 direction2 = TVector2( (*pca2->GetEigenVectors())[0][0], (*pca2->GetEigenVectors())[1][0] ).Unit();
372 TVector2 direction = ((direction1+direction2)/2).Unit();
373 TVector2 centre1 = chargePoint1 / totalCharge1;
374 TVector2 centre2 = chargePoint2 / totalCharge2;
375 TVector2 centre = (centre1+centre2)/2;
376 TVector2 start1, end1;
377 TVector2 start2, end2;
380 double length1 = (end1-start1).Mod();
381 double length2 = (end2-start2).Mod();
385 double projectedWidth =
FindProjectedWidth(centre1, start1, end1, centre2, start2, end2);
386 double angle = direction1.DeltaPhi(direction2);
387 if (angle > 1.57) angle = 3.14159 -
angle;
393 if (
PassCuts(angle, crossingDistance, projectedWidth, separation, overlap,
TMath::Max(length1, length2))) {
395 for (
auto &
hit : oldClusters.at(trialCluster))
396 cluster.push_back(
hit);
398 mergedClusters.push_back(trialCluster);
408 if (nadded == 0) mergedAllToThisCluster =
true;
412 clusters.push_back(cluster);
413 if (mergedClusters.size() == nclusters) mergedAllClusters =
true;
417 return clusters.size();
void FindClusterEndPoints(art::PtrVector< recob::Hit > const &cluster, TVector2 const ¢re, TVector2 const &direction, TVector2 &start, TVector2 &end) const
double FindClusterOverlap(TVector2 const &direction, TVector2 const ¢re, TVector2 const &start1, TVector2 const &end1, TVector2 const &start2, TVector2 const &end2) const
bool PassCuts(double const &angle, double const &crossingDistance, double const &projectedWidth, double const &separation, double const &overlap, double const &longLength) const
TVector2 HitCoordinates(art::Ptr< recob::Hit > const &hit) const
double FindMinSeparation(art::PtrVector< recob::Hit > const &cluster1, art::PtrVector< recob::Hit > const &cluster2) const
double FindCrossingDistance(TVector2 const &direction1, TVector2 const ¢re1, TVector2 const &direction2, TVector2 const ¢re2) const
finds tracks best matching by angle
double FindProjectedWidth(TVector2 const ¢re1, TVector2 const &start1, TVector2 const &end1, TVector2 const ¢re2, TVector2 const &start2, TVector2 const &end2) const
unsigned int fMinMergeClusterSize
double fMaxMergeSeparation