File indexing completed on 2024-12-20 03:14:04
0001 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0002 #include <Math/VectorUtil.h>
0003 #include "DataFormats/Math/interface/deltaR.h"
0004 #include "DataFormats/HGCalReco/interface/Common.h"
0005 #include "DataFormats/GeometrySurface/interface/BoundDisk.h"
0006 #include "DataFormats/HGCalReco/interface/Trackster.h"
0007 #include "TrackingTools/TrajectoryState/interface/TrajectoryStateTransform.h"
0008 #include "RecoParticleFlow/PFProducer/interface/PFMuonAlgo.h"
0009 #include "RecoHGCal/TICL/interface/TracksterLinkingAlgoBase.h"
0010 #include "RecoHGCal/TICL/plugins/TracksterLinkingbySkeletons.h"
0011 #include "TICLGraph.h"
0012
0013 namespace {
0014 bool isRoundTrackster(std::array<ticl::Vector, 3> skeleton) { return (skeleton[0].Z() == skeleton[2].Z()); }
0015
0016 bool isGoodTrackster(const ticl::Trackster &trackster,
0017 const std::array<ticl::Vector, 3> &skeleton,
0018 const unsigned int min_num_lcs,
0019 const float min_trackster_energy,
0020 const float pca_quality_th) {
0021 bool isGood = false;
0022
0023 if (isRoundTrackster(skeleton) or trackster.vertices().size() < min_num_lcs) {
0024 if (trackster.raw_energy() > min_trackster_energy) {
0025 auto const &eigenvalues = trackster.eigenvalues();
0026 auto const sum = std::accumulate(std::begin(eigenvalues), std::end(eigenvalues), 0.f);
0027 float pcaQuality = sum > 0.f ? eigenvalues[0] / sum : 0.f;
0028 if (pcaQuality > pca_quality_th) {
0029 isGood = true;
0030 }
0031 }
0032 } else {
0033 auto const &eigenvalues = trackster.eigenvalues();
0034 auto const sum = std::accumulate(std::begin(eigenvalues), std::end(eigenvalues), 0.f);
0035 float pcaQuality = sum > 0.f ? eigenvalues[0] / sum : 0.f;
0036 if (pcaQuality > pca_quality_th) {
0037 isGood = true;
0038 }
0039 }
0040 return isGood;
0041 }
0042
0043
0044 inline float projective_distance(const ticl::Vector &point1, const ticl::Vector &point2) {
0045
0046 float r1 = std::sqrt(point1.x() * point1.x() + point1.y() * point1.y());
0047 float r2_at_z1 =
0048 std::sqrt(point2.x() * point2.x() + point2.y() * point2.y()) * std::abs(point1.z()) / std::abs(point2.z());
0049 float delta_phi = reco::deltaPhi(point1.Phi(), point2.Phi());
0050 float projective_distance = (r1 - r2_at_z1) * (r1 - r2_at_z1) + r2_at_z1 * r2_at_z1 * delta_phi * delta_phi;
0051 LogDebug("TracksterLinkingbySkeletons") << "Computing distance between point : " << point1 << " And point "
0052 << point2 << " Distance " << projective_distance << std::endl;
0053 return projective_distance;
0054 }
0055 }
0056
0057 using namespace ticl;
0058
0059 TracksterLinkingbySkeletons::TracksterLinkingbySkeletons(const edm::ParameterSet &conf,
0060 edm::ConsumesCollector iC,
0061 cms::Ort::ONNXRuntime const *onnxRuntime)
0062 : TracksterLinkingAlgoBase(conf, iC),
0063 lower_boundary_(conf.getParameter<std::vector<double>>("lower_boundary")),
0064 upper_boundary_(conf.getParameter<std::vector<double>>("upper_boundary")),
0065 upper_distance_projective_sqr_(conf.getParameter<std::vector<double>>("upper_distance_projective_sqr")),
0066 lower_distance_projective_sqr_(conf.getParameter<std::vector<double>>("lower_distance_projective_sqr")),
0067 min_distance_z_(conf.getParameter<std::vector<double>>("min_distance_z")),
0068 upper_distance_projective_sqr_closest_points_(
0069 conf.getParameter<std::vector<double>>("upper_distance_projective_sqr_closest_points")),
0070 lower_distance_projective_sqr_closest_points_(
0071 conf.getParameter<std::vector<double>>("lower_distance_projective_sqr_closest_points")),
0072 max_z_distance_closest_points_(conf.getParameter<std::vector<double>>("max_z_distance_closest_points")),
0073 cylinder_radius_sqr_(conf.getParameter<std::vector<double>>("cylinder_radius_sqr")),
0074 cylinder_radius_sqr_split_(conf.getParameter<double>("cylinder_radius_sqr_split")),
0075 proj_distance_split_(conf.getParameter<double>("proj_distance_split")),
0076 timing_quality_threshold_(conf.getParameter<double>("track_time_quality_threshold")),
0077 min_trackster_energy_(conf.getParameter<double>("min_trackster_energy")),
0078 pca_quality_th_(conf.getParameter<double>("pca_quality_th")),
0079 dot_prod_th_(conf.getParameter<double>("dot_prod_th")),
0080 deltaRxy_(conf.getParameter<double>("deltaRxy")),
0081 min_num_lcs_(conf.getParameter<unsigned int>("min_num_lcs"))
0082
0083 {}
0084
0085 void TracksterLinkingbySkeletons::buildLayers() {
0086
0087
0088 float zVal = hgcons_->waferZ(1, true);
0089 std::pair<float, float> rMinMax = hgcons_->rangeR(zVal, true);
0090
0091 float zVal_interface = rhtools_.getPositionLayer(rhtools_.lastLayerEE()).z();
0092 std::pair<float, float> rMinMax_interface = hgcons_->rangeR(zVal_interface, true);
0093
0094 for (int iSide = 0; iSide < 2; ++iSide) {
0095 float zSide = (iSide == 0) ? (-1. * zVal) : zVal;
0096 firstDisk_[iSide] =
0097 std::make_unique<GeomDet>(Disk::build(Disk::PositionType(0, 0, zSide),
0098 Disk::RotationType(),
0099 SimpleDiskBounds(rMinMax.first, rMinMax.second, zSide - 0.5, zSide + 0.5))
0100 .get());
0101
0102 zSide = (iSide == 0) ? (-1. * zVal_interface) : zVal_interface;
0103 interfaceDisk_[iSide] = std::make_unique<GeomDet>(
0104 Disk::build(Disk::PositionType(0, 0, zSide),
0105 Disk::RotationType(),
0106 SimpleDiskBounds(rMinMax_interface.first, rMinMax_interface.second, zSide - 0.5, zSide + 0.5))
0107 .get());
0108 }
0109 }
0110
0111 void TracksterLinkingbySkeletons::initialize(const HGCalDDDConstants *hgcons,
0112 const hgcal::RecHitTools rhtools,
0113 const edm::ESHandle<MagneticField> bfieldH,
0114 const edm::ESHandle<Propagator> propH) {
0115 hgcons_ = hgcons;
0116 rhtools_ = rhtools;
0117 buildLayers();
0118
0119 bfield_ = bfieldH;
0120 propagator_ = propH;
0121
0122
0123
0124 float etaStep = (TileConstants::maxEta - TileConstants::minEta) / TileConstants::nEtaBins;
0125 float expNeg2DeltaRxy = deltaRxy_ * std::exp(-2.f);
0126
0127 for (int i = 0; i < TileConstants::nEtaBins; ++i) {
0128 float eta = TileConstants::minEta + i * etaStep;
0129
0130 float expNegEta = std::exp(-eta);
0131 float R = z_surface * 2.f * expNegEta / (1.f - expNeg2DeltaRxy * expNegEta);
0132
0133 eta_windows_[i] = std::abs(atan(deltaRxy_ / R));
0134 }
0135 }
0136
0137 std::array<ticl::Vector, 3> TracksterLinkingbySkeletons::findSkeletonNodes(
0138 const ticl::Trackster &trackster,
0139 float lower_percentage,
0140 float upper_percentage,
0141 const std::vector<reco::CaloCluster> &layerClusters,
0142 const hgcal::RecHitTools &rhtools) {
0143 auto const &vertices = trackster.vertices();
0144 auto const trackster_raw_energy = trackster.raw_energy();
0145
0146 std::array<ticl::Vector, 3> skeleton;
0147 if (trackster.vertices().size() < 3) {
0148 const auto &v = layerClusters[trackster.vertices()[0]];
0149 const Vector intersection(v.x(), v.y(), v.z());
0150 skeleton = {{intersection, intersection, intersection}};
0151 return skeleton;
0152 }
0153
0154 std::vector<unsigned int> sortedVertices(vertices);
0155 std::sort(sortedVertices.begin(), sortedVertices.end(), [&layerClusters](unsigned int i, unsigned int j) {
0156 return std::abs(layerClusters[i].z()) < std::abs(layerClusters[j].z());
0157 });
0158
0159
0160
0161 float cumulativeEnergyFraction = 0.f;
0162 int innerLayerId = rhtools.getLayerWithOffset(layerClusters[sortedVertices[0]].hitsAndFractions()[0].first);
0163 float innerLayerZ = layerClusters[sortedVertices[0]].z();
0164 int outerLayerId = rhtools.getLayerWithOffset(layerClusters[sortedVertices.back()].hitsAndFractions()[0].first);
0165 float outerLayerZ = layerClusters[sortedVertices.back()].z();
0166 bool foundInnerLayer = false;
0167 bool foundOuterLayer = false;
0168 for (auto const &v : sortedVertices) {
0169 auto const &lc = layerClusters[v];
0170 auto const &n_lay = rhtools.getLayerWithOffset(lc.hitsAndFractions()[0].first);
0171 cumulativeEnergyFraction += lc.energy() / trackster_raw_energy;
0172 if (cumulativeEnergyFraction >= lower_percentage and not foundInnerLayer) {
0173 innerLayerId = n_lay;
0174 innerLayerZ = lc.z();
0175 foundInnerLayer = true;
0176 }
0177 if (cumulativeEnergyFraction >= upper_percentage and not foundOuterLayer) {
0178 outerLayerId = n_lay;
0179 outerLayerZ = lc.z();
0180 foundOuterLayer = true;
0181 }
0182 }
0183 int minimumDistanceInLayers = 4;
0184 if (outerLayerId - innerLayerId < minimumDistanceInLayers) {
0185 skeleton = {{trackster.barycenter(), trackster.barycenter(), trackster.barycenter()}};
0186 } else {
0187 auto intersectLineWithSurface = [](float surfaceZ, const Vector &origin, const Vector &direction) -> Vector {
0188 auto const t = (surfaceZ - origin.Z()) / direction.Z();
0189 auto const iX = t * direction.X() + origin.X();
0190 auto const iY = t * direction.Y() + origin.Y();
0191 auto const iZ = surfaceZ;
0192 const Vector intersection(iX, iY, iZ);
0193 return intersection;
0194 };
0195
0196 auto const &t0_p1 = trackster.barycenter();
0197 auto const t0_p0 = intersectLineWithSurface(innerLayerZ, t0_p1, trackster.eigenvectors(0));
0198 auto const t0_p2 = intersectLineWithSurface(outerLayerZ, t0_p1, trackster.eigenvectors(0));
0199 skeleton = {{t0_p0, t0_p1, t0_p2}};
0200 std::sort(skeleton.begin(), skeleton.end(), [](Vector &v1, Vector &v2) { return v1.Z() < v2.Z(); });
0201 }
0202
0203 return skeleton;
0204 }
0205
0206 inline bool isInCylinder(const std::array<ticl::Vector, 3> &mySkeleton,
0207 const std::array<ticl::Vector, 3> &otherSkeleton,
0208 const float radius_sqr) {
0209 const auto &first = mySkeleton[0];
0210 const auto &last = mySkeleton[2];
0211 const auto &pointToCheck = otherSkeleton[0];
0212
0213 const auto &cylAxis = last - first;
0214 const auto &vecToPoint = pointToCheck - first;
0215
0216 auto axisNorm = cylAxis.Dot(cylAxis);
0217 auto projLength = vecToPoint.Dot(cylAxis) / axisNorm;
0218 bool isWithinLength = projLength >= 0 && projLength <= 1;
0219
0220 if (!isWithinLength)
0221 return false;
0222
0223 const auto &proj = cylAxis * projLength;
0224
0225 const auto &pointOnAxis = first + proj;
0226
0227 const auto &distance = pointToCheck - pointOnAxis;
0228 auto distance2 = distance.Dot(distance);
0229 LogDebug("TracksterLinkingbySkeletons") << "is within lenght " << distance2 << " radius " << radius_sqr << std::endl;
0230 bool isWithinRadius = distance2 <= radius_sqr;
0231
0232 return isWithinRadius;
0233 }
0234
0235 inline float computeParameter(float energy, float en_th_low, float cut1, float en_th_high, float cut2) {
0236 if (en_th_low == en_th_high) {
0237 return (energy <= en_th_low) ? cut1 : cut2;
0238 }
0239 if (energy < en_th_low) {
0240 return cut1;
0241 } else if (energy >= en_th_low && energy <= en_th_high) {
0242 return ((cut2 - cut1) / (en_th_high - en_th_low)) * (energy - en_th_low) + cut1;
0243 } else {
0244 return cut2;
0245 }
0246 }
0247
0248
0249 inline bool TracksterLinkingbySkeletons::isSplitComponent(const ticl::Trackster &myTrackster,
0250 const ticl::Trackster &otherTrackster,
0251 const std::array<ticl::Vector, 3> &mySkeleton,
0252 const std::array<ticl::Vector, 3> &otherSkeleton,
0253 float proj_distance) {
0254
0255 if (otherSkeleton[1].z() < mySkeleton[2].z() && otherSkeleton[1].z() > mySkeleton[0].z()) {
0256 if (proj_distance < proj_distance_split_) {
0257 return true;
0258 } else {
0259
0260
0261 float distance2 = (myTrackster.barycenter().x() - otherTrackster.barycenter().x()) *
0262 (myTrackster.barycenter().x() - otherTrackster.barycenter().x()) +
0263 (myTrackster.barycenter().y() - otherTrackster.barycenter().y()) *
0264 (myTrackster.barycenter().y() - otherTrackster.barycenter().y());
0265 if (distance2 < cylinder_radius_sqr_split_) {
0266 return true;
0267 }
0268 }
0269 }
0270 return false;
0271 }
0272
0273 bool TracksterLinkingbySkeletons::areCompatible(const ticl::Trackster &myTrackster,
0274 const ticl::Trackster &otherTrackster,
0275 const std::array<ticl::Vector, 3> &mySkeleton,
0276 const std::array<ticl::Vector, 3> &otherSkeleton) {
0277 float zVal_interface = rhtools_.getPositionLayer(rhtools_.lastLayerEE()).z();
0278
0279 if (!isGoodTrackster(myTrackster, mySkeleton, min_num_lcs_, min_trackster_energy_, pca_quality_th_)) {
0280 LogDebug("TracksterLinkingbySkeletons") << "Inner Trackster with energy " << myTrackster.raw_energy() << " Num LCs "
0281 << myTrackster.vertices().size() << " NOT GOOD " << std::endl;
0282 return false;
0283 }
0284
0285 LogDebug("TracksterLinkingbySkeletons") << "Inner Trackster with energy " << myTrackster.raw_energy() << " Num LCs "
0286 << myTrackster.vertices().size() << " IS GOOD " << std::endl;
0287
0288 float proj_distance = projective_distance(mySkeleton[1], otherSkeleton[1]);
0289 auto isEE = mySkeleton[1].z() <= zVal_interface ? 0 : 1;
0290 auto const max_distance_proj_sqr = computeParameter(myTrackster.raw_energy(),
0291 lower_boundary_[isEE],
0292 lower_distance_projective_sqr_[isEE],
0293 upper_boundary_[isEE],
0294 upper_distance_projective_sqr_[isEE]);
0295 bool areAlignedInProjectiveSpace = proj_distance < max_distance_proj_sqr;
0296
0297 LogDebug("TracksterLinkingbySkeletons")
0298 << "\t Trying to compare with outer Trackster with energy " << otherTrackster.raw_energy() << " Num LCS "
0299 << otherTrackster.vertices().size() << " Projective distance " << proj_distance << " areAlignedProjective "
0300 << areAlignedInProjectiveSpace << " TH " << max_distance_proj_sqr << std::endl;
0301
0302 if (isGoodTrackster(otherTrackster, otherSkeleton, min_num_lcs_, min_trackster_energy_, pca_quality_th_)) {
0303 if (areAlignedInProjectiveSpace) {
0304 LogDebug("TracksterLinkingbySkeletons") << "\t\t Linked! " << std::endl;
0305 return true;
0306 } else {
0307
0308
0309 if (isSplitComponent(myTrackster, otherTrackster, mySkeleton, otherSkeleton, proj_distance)) {
0310 LogDebug("TracksterLinkingbySkeletons") << "\t\t Linked! Splitted components!" << std::endl;
0311 return true;
0312 }
0313
0314 if (isEE) {
0315 return false;
0316 }
0317
0318
0319 return checkClosestPoints(myTrackster, otherTrackster, mySkeleton, otherSkeleton, isEE);
0320 }
0321 } else {
0322 if (otherTrackster.vertices().size() >= 3) {
0323 if (areAlignedInProjectiveSpace) {
0324 LogDebug("TracksterLinkingbySkeletons") << "\t\t Linked! " << std::endl;
0325 return true;
0326 } else {
0327 LogDebug("TracksterLinkingbySkeletons")
0328 << "\t Not aligned in projective space, check distance between closest points in the two skeletons "
0329 << std::endl;
0330 if (checkClosestPoints(myTrackster, otherTrackster, mySkeleton, otherSkeleton, isEE)) {
0331 return true;
0332 } else {
0333 return checkCylinderAlignment(mySkeleton, otherSkeleton, isEE);
0334 }
0335 }
0336 } else {
0337 return checkCylinderAlignment(mySkeleton, otherSkeleton, isEE);
0338 }
0339 }
0340 }
0341
0342 bool TracksterLinkingbySkeletons::checkCylinderAlignment(const std::array<ticl::Vector, 3> &mySkeleton,
0343 const std::array<ticl::Vector, 3> &otherSkeleton,
0344 int isEE) {
0345 bool isInCyl = isInCylinder(mySkeleton, otherSkeleton, cylinder_radius_sqr_[isEE]);
0346 if (isInCyl) {
0347 LogDebug("TracksterLinkingbySkeletons") << "Two Points are in Cylinder " << isInCyl << " Linked! " << std::endl;
0348 }
0349 return isInCyl;
0350 }
0351
0352 bool TracksterLinkingbySkeletons::checkSkeletonAlignment(const ticl::Trackster &myTrackster,
0353 const ticl::Trackster &otherTrackster) {
0354 auto dotProdSkeletons = myTrackster.eigenvectors(0).Dot(otherTrackster.eigenvectors(0));
0355 bool alignedSkeletons = dotProdSkeletons > dot_prod_th_;
0356
0357 LogDebug("TracksterLinkingbySkeletons")
0358 << "\t Outer Trackster is Good, checking for skeleton alignment " << alignedSkeletons << " dotProd "
0359 << dotProdSkeletons << " Threshold " << dot_prod_th_ << std::endl;
0360
0361 if (alignedSkeletons) {
0362 LogDebug("TracksterLinkingbySkeletons") << "\t\t Linked! " << std::endl;
0363 }
0364
0365 return alignedSkeletons;
0366 }
0367
0368 bool TracksterLinkingbySkeletons::checkClosestPoints(const ticl::Trackster &myTrackster,
0369 const ticl::Trackster &otherTrackster,
0370 const std::array<ticl::Vector, 3> &mySkeleton,
0371 const std::array<ticl::Vector, 3> &otherSkeleton,
0372 int isEE) {
0373 int myClosestPoint = -1;
0374 int otherClosestPoint = -1;
0375 float minDistance_z = std::numeric_limits<float>::max();
0376
0377 for (int i = 1; i < 3; i++) {
0378 for (int j = 0; j < 3; j++) {
0379 float dist_z = std::abs(mySkeleton[i].Z() - otherSkeleton[j].Z());
0380 if (dist_z < minDistance_z) {
0381 myClosestPoint = i;
0382 otherClosestPoint = j;
0383 minDistance_z = dist_z;
0384 }
0385 }
0386 }
0387
0388 float d = projective_distance(mySkeleton[myClosestPoint], otherSkeleton[otherClosestPoint]);
0389 auto const max_distance_proj_sqr_closest = computeParameter(myTrackster.raw_energy(),
0390 lower_boundary_[isEE],
0391 lower_distance_projective_sqr_closest_points_[isEE],
0392 upper_boundary_[isEE],
0393 upper_distance_projective_sqr_closest_points_[isEE]);
0394
0395 LogDebug("TracksterLinkingbySkeletons")
0396 << "\t\t Distance between closest points " << d << " TH " << 10.f << " Z Distance " << minDistance_z << " TH "
0397 << max_distance_proj_sqr_closest << std::endl;
0398
0399 if (d < max_distance_proj_sqr_closest && minDistance_z < max_z_distance_closest_points_[isEE]) {
0400 LogDebug("TracksterLinkingbySkeletons") << "\t\t\t Linked! " << d << std::endl;
0401 return true;
0402 }
0403
0404 LogDebug("TracksterLinkingbySkeletons") << "Distance between closest point " << d << " Distance in z "
0405 << max_z_distance_closest_points_[isEE] << std::endl;
0406
0407 return checkCylinderAlignment(mySkeleton, otherSkeleton, isEE);
0408 }
0409
0410 void TracksterLinkingbySkeletons::linkTracksters(
0411 const Inputs &input,
0412 std::vector<Trackster> &resultTracksters,
0413 std::vector<std::vector<unsigned int>> &linkedResultTracksters,
0414 std::vector<std::vector<unsigned int>> &linkedTracksterIdToInputTracksterId) {
0415 const auto &tracksters = input.tracksters;
0416 const auto &layerClusters = input.layerClusters;
0417
0418
0419 std::vector<unsigned int> sortedTracksters(tracksters.size());
0420 std::iota(sortedTracksters.begin(), sortedTracksters.end(), 0);
0421 std::sort(sortedTracksters.begin(), sortedTracksters.end(), [&tracksters](unsigned int i, unsigned int j) {
0422 return tracksters[i].raw_energy() > tracksters[j].raw_energy();
0423 });
0424
0425
0426
0427 std::array<TICLLayerTile, 2> tracksterTile;
0428
0429
0430 std::vector<std::array<ticl::Vector, 3>> skeletons(tracksters.size());
0431 for (auto const t_idx : sortedTracksters) {
0432 const auto &trackster = tracksters[t_idx];
0433 skeletons[t_idx] = findSkeletonNodes(tracksters[t_idx], 0.1, 0.9, layerClusters, rhtools_);
0434 tracksterTile[trackster.barycenter().eta() > 0.f].fill(
0435 trackster.barycenter().eta(), trackster.barycenter().phi(), t_idx);
0436 }
0437 std::vector<int> maskReceivedLink(tracksters.size(), 1);
0438 std::vector<int> isRootTracksters(tracksters.size(), 1);
0439
0440 std::vector<ticl::Node> allNodes;
0441 for (size_t it = 0; it < tracksters.size(); ++it) {
0442 allNodes.emplace_back(it);
0443 }
0444
0445
0446 for (auto const &t_idx : sortedTracksters) {
0447 auto const &trackster = tracksters[t_idx];
0448 auto const &skeleton = skeletons[t_idx];
0449
0450 auto const &bary = trackster.barycenter();
0451 int tileIndex = bary.eta() > 0.f;
0452 const auto &tiles = tracksterTile[tileIndex];
0453 auto const window = eta_windows_[tiles.etaBin(bary.eta())];
0454 float eta_min = std::max(abs(bary.eta()) - window, TileConstants::minEta);
0455 float eta_max = std::min(abs(bary.eta()) + window, TileConstants::maxEta);
0456 std::array<int, 4> search_box = tiles.searchBoxEtaPhi(eta_min, eta_max, bary.phi() - window, bary.phi() + window);
0457
0458 if (search_box[2] > search_box[3]) {
0459 search_box[3] += TileConstants::nPhiBins;
0460 }
0461
0462 for (int eta_i = search_box[0]; eta_i <= search_box[1]; ++eta_i) {
0463 for (int phi_i = search_box[2]; phi_i <= search_box[3]; ++phi_i) {
0464 auto &neighbours = tiles[tiles.globalBin(eta_i, (phi_i % TileConstants::nPhiBins))];
0465 for (auto n : neighbours) {
0466 if (t_idx == n)
0467 continue;
0468
0469 auto const &tracksterOut = tracksters[n];
0470 auto const &skeletonOut = skeletons[n];
0471 auto const deltaphi = reco::deltaPhi(trackster.barycenter().phi(), tracksterOut.barycenter().phi());
0472 if (abs(trackster.barycenter().eta() - tracksterOut.barycenter().eta()) <= window && deltaphi <= window) {
0473 bool isInGood = isGoodTrackster(trackster, skeleton, min_num_lcs_, min_trackster_energy_, pca_quality_th_);
0474 bool isOutGood =
0475 isGoodTrackster(tracksterOut, skeletonOut, min_num_lcs_, min_trackster_energy_, pca_quality_th_);
0476 if (isInGood) {
0477 LogDebug("TracksterLinkingbySkeletons")
0478 << "Trying to Link Trackster " << t_idx << " With Trackster " << n << std::endl;
0479 if (areCompatible(trackster, tracksters[n], skeleton, skeletonOut)) {
0480 LogDebug("TracksterLinkingbySkeletons")
0481 << "\t==== LINK: Trackster " << t_idx << " Linked with Trackster " << n << std::endl;
0482
0483 if (isOutGood) {
0484 if (abs(skeleton[0].z()) < abs(skeletonOut[0].z())) {
0485 LogDebug("TracksterLinkingbySkeletons") << "Trackster in energy " << trackster.raw_energy()
0486 << " Out is good " << tracksterOut.raw_energy() << " Sk In "
0487 << skeleton[0] << " Sk out " << skeletonOut[0] << std::endl;
0488 LogDebug("TracksterLinkingbySkeletons") << "\t " << t_idx << " --> " << n << std::endl;
0489 allNodes[t_idx].addOuterNeighbour(n);
0490 allNodes[n].addInnerNeighbour(t_idx);
0491 isRootTracksters[n] = 0;
0492 } else if (abs(skeleton[0].z()) > abs(skeletonOut[0].z())) {
0493 LogDebug("TracksterLinkingbySkeletons") << "Trackster in energy " << trackster.raw_energy()
0494 << " Out is good " << tracksterOut.raw_energy() << " Sk In "
0495 << skeleton[0] << " Sk out " << skeletonOut[0] << std::endl;
0496 LogDebug("TracksterLinkingbySkeletons") << "\t " << n << " --> " << t_idx << std::endl;
0497 allNodes[n].addOuterNeighbour(t_idx);
0498 allNodes[t_idx].addInnerNeighbour(n);
0499 isRootTracksters[t_idx] = 0;
0500 } else {
0501 if (trackster.raw_energy() >= tracksterOut.raw_energy()) {
0502 LogDebug("TracksterLinkingbySkeletons")
0503 << "Trackster in energy " << trackster.raw_energy() << " Out is good "
0504 << tracksterOut.raw_energy() << " Sk In " << skeleton[0] << " Sk out " << skeletonOut[0]
0505 << std::endl;
0506 LogDebug("TracksterLinkingbySkeletons") << "\t " << t_idx << " --> " << n << std::endl;
0507 allNodes[t_idx].addOuterNeighbour(n);
0508 allNodes[n].addInnerNeighbour(t_idx);
0509 isRootTracksters[n] = 0;
0510 } else {
0511 LogDebug("TracksterLinkingbySkeletons")
0512 << "Trackster in energy " << trackster.raw_energy() << " Out is good "
0513 << tracksterOut.raw_energy() << " Sk In " << skeleton[0] << " Sk out " << skeletonOut[0]
0514 << std::endl;
0515 LogDebug("TracksterLinkingbySkeletons") << "\t " << n << " --> " << t_idx << std::endl;
0516 allNodes[n].addOuterNeighbour(t_idx);
0517 allNodes[t_idx].addInnerNeighbour(n);
0518 isRootTracksters[t_idx] = 0;
0519 }
0520 }
0521 } else {
0522 LogDebug("TracksterLinkingbySkeletons")
0523 << "Trackster in energy " << trackster.raw_energy() << " Out is NOT good "
0524 << tracksterOut.raw_energy() << " Sk In " << skeleton[0] << " Sk out " << skeletonOut[0]
0525 << std::endl;
0526 LogDebug("TracksterLinkingbySkeletons") << "\t " << t_idx << " --> " << n << std::endl;
0527 allNodes[t_idx].addOuterNeighbour(n);
0528 allNodes[n].addInnerNeighbour(t_idx);
0529 isRootTracksters[n] = 0;
0530 }
0531 }
0532 }
0533 }
0534 }
0535 }
0536 }
0537 }
0538
0539 TICLGraph graph(allNodes);
0540 auto sortedRootNodes = graph.getRootNodes();
0541 std::sort(sortedRootNodes.begin(), sortedRootNodes.end(), [&tracksters](const ticl::Node &n1, const ticl::Node &n2) {
0542 unsigned int n1Id = n1.getId();
0543 unsigned int n2Id = n2.getId();
0544 return tracksters[n1Id].raw_energy() > tracksters[n2Id].raw_energy();
0545 });
0546
0547 int ic = 0;
0548 auto const &components = graph.findSubComponents(sortedRootNodes);
0549 linkedTracksterIdToInputTracksterId.resize(components.size());
0550 for (auto const &comp : components) {
0551 LogDebug("TracksterLinkingbySkeletons") << "Component " << ic << " Node: ";
0552 std::vector<unsigned int> linkedTracksters;
0553 Trackster outTrackster;
0554 if (comp.size() == 1) {
0555 if (input.tracksters[comp[0]].vertices().size() <= 3 && input.tracksters[comp[0]].raw_energy() < 5.f) {
0556 continue;
0557 }
0558 }
0559 for (auto const &node : comp) {
0560 LogDebug("TracksterLinkingbySkeletons") << node << " ";
0561 linkedTracksterIdToInputTracksterId[ic].push_back(node);
0562 outTrackster.mergeTracksters(input.tracksters[node]);
0563 }
0564 linkedTracksters.push_back(resultTracksters.size());
0565 LogDebug("TracksterLinkingbySkeletons") << "\nOut Trackster " << outTrackster.raw_energy() << std::endl;
0566 resultTracksters.push_back(outTrackster);
0567 linkedResultTracksters.push_back(linkedTracksters);
0568 LogDebug("TracksterLinkingbySkeletons") << "\n";
0569 ++ic;
0570 }
0571 LogDebug("TracksterLinkingbySkeletons") << "\n";
0572
0573 }