File indexing completed on 2024-06-13 03:24:05
0001 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0002 #include "DataFormats/Common/interface/ValueMap.h"
0003 #include "RecoLocalCalo/HGCalRecProducers/interface/ComputeClusterTime.h"
0004 #include "TrackstersPCA.h"
0005
0006 #include <iostream>
0007 #include <set>
0008
0009 #include <Eigen/Core>
0010 #include <Eigen/Dense>
0011
0012 void ticl::assignPCAtoTracksters(std::vector<Trackster> &tracksters,
0013 const std::vector<reco::CaloCluster> &layerClusters,
0014 const edm::ValueMap<std::pair<float, float>> &layerClustersTime,
0015 double z_limit_em,
0016 bool computeLocalTime,
0017 bool energyWeight) {
0018 LogDebug("TrackstersPCA_Eigen") << "------- Eigen -------" << std::endl;
0019
0020 for (auto &trackster : tracksters) {
0021 Eigen::Vector3d point;
0022 point << 0., 0., 0.;
0023 Eigen::Vector3d barycenter;
0024 barycenter << 0., 0., 0.;
0025
0026 auto fillPoint = [&](const reco::CaloCluster &c, const float weight = 1.f) {
0027 point[0] = weight * c.x();
0028 point[1] = weight * c.y();
0029 point[2] = weight * c.z();
0030 };
0031
0032
0033 trackster.setRawEnergy(0.f);
0034 trackster.setRawEmEnergy(0.f);
0035 trackster.setRawPt(0.f);
0036 trackster.setRawEmPt(0.f);
0037
0038 size_t N = trackster.vertices().size();
0039 if (N == 0)
0040 continue;
0041 float weight = 1.f / N;
0042 float weights2_sum = 0.f;
0043
0044 for (size_t i = 0; i < N; ++i) {
0045 auto fraction = 1.f / trackster.vertex_multiplicity(i);
0046 trackster.addToRawEnergy(layerClusters[trackster.vertices(i)].energy() * fraction);
0047 if (std::abs(layerClusters[trackster.vertices(i)].z()) <= z_limit_em)
0048 trackster.addToRawEmEnergy(layerClusters[trackster.vertices(i)].energy() * fraction);
0049
0050
0051 if (energyWeight)
0052 weight = layerClusters[trackster.vertices(i)].energy() * fraction;
0053 fillPoint(layerClusters[trackster.vertices(i)], weight);
0054 for (size_t j = 0; j < 3; ++j)
0055 barycenter[j] += point[j];
0056 }
0057 float raw_energy = trackster.raw_energy();
0058 float inv_raw_energy = 1.f / raw_energy;
0059 if (energyWeight)
0060 barycenter *= inv_raw_energy;
0061 trackster.setBarycenter(ticl::Trackster::Vector(barycenter));
0062 std::pair<float, float> timeTrackster;
0063 if (computeLocalTime)
0064 timeTrackster = ticl::computeLocalTracksterTime(trackster, layerClusters, layerClustersTime, barycenter, N);
0065 else
0066 timeTrackster = ticl::computeTracksterTime(trackster, layerClustersTime, N);
0067
0068 trackster.setTimeAndError(timeTrackster.first, timeTrackster.second);
0069 LogDebug("TrackstersPCA") << "Use energy weighting: " << energyWeight << std::endl;
0070 LogDebug("TrackstersPCA") << "\nTrackster characteristics: " << std::endl;
0071 LogDebug("TrackstersPCA") << "Size: " << N << std::endl;
0072 LogDebug("TrackstersPCA") << "Energy: " << trackster.raw_energy() << std::endl;
0073 LogDebug("TrackstersPCA") << "raw_pt: " << trackster.raw_pt() << std::endl;
0074 LogDebug("TrackstersPCA") << "Means: " << barycenter[0] << ", " << barycenter[1] << ", " << barycenter[2]
0075 << std::endl;
0076 LogDebug("TrackstersPCA") << "Time: " << trackster.time() << " +/- " << trackster.timeError() << std::endl;
0077
0078 if (N > 2) {
0079 Eigen::Vector3d sigmas;
0080 sigmas << 0., 0., 0.;
0081 Eigen::Vector3d sigmasEigen;
0082 sigmasEigen << 0., 0., 0.;
0083 Eigen::Matrix3d covM = Eigen::Matrix3d::Zero();
0084
0085
0086
0087 for (size_t i = 0; i < N; ++i) {
0088 fillPoint(layerClusters[trackster.vertices(i)]);
0089 if (energyWeight && trackster.raw_energy())
0090 weight = (layerClusters[trackster.vertices(i)].energy() / trackster.vertex_multiplicity(i)) * inv_raw_energy;
0091 weights2_sum += weight * weight;
0092 for (size_t x = 0; x < 3; ++x)
0093 for (size_t y = 0; y <= x; ++y) {
0094 covM(x, y) += weight * (point[x] - barycenter[x]) * (point[y] - barycenter[y]);
0095 covM(y, x) = covM(x, y);
0096 }
0097 }
0098 covM *= 1.f / (1.f - weights2_sum);
0099
0100
0101 Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d>::RealVectorType eigenvalues_fromEigen;
0102 Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d>::EigenvectorsType eigenvectors_fromEigen;
0103 Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> eigensolver(covM);
0104 if (eigensolver.info() != Eigen::Success) {
0105 eigenvalues_fromEigen = eigenvalues_fromEigen.Zero();
0106 eigenvectors_fromEigen = eigenvectors_fromEigen.Zero();
0107 } else {
0108 eigenvalues_fromEigen = eigensolver.eigenvalues();
0109 eigenvectors_fromEigen = eigensolver.eigenvectors();
0110 }
0111
0112
0113 for (size_t i = 0; i < N; ++i) {
0114 fillPoint(layerClusters[trackster.vertices(i)]);
0115 sigmas += weight * (point - barycenter).cwiseAbs2();
0116 Eigen::Vector3d point_transformed = eigenvectors_fromEigen * (point - barycenter);
0117 if (energyWeight && raw_energy)
0118 weight = (layerClusters[trackster.vertices(i)].energy() / trackster.vertex_multiplicity(i)) * inv_raw_energy;
0119 sigmasEigen += weight * (point_transformed.cwiseAbs2());
0120 }
0121 sigmas /= (1.f - weights2_sum);
0122 sigmasEigen /= (1.f - weights2_sum);
0123
0124 trackster.fillPCAVariables(eigenvalues_fromEigen,
0125 eigenvectors_fromEigen,
0126 sigmas,
0127 sigmasEigen,
0128 3,
0129 ticl::Trackster::PCAOrdering::ascending);
0130
0131 LogDebug("TrackstersPCA") << "EigenValues from Eigen/Tr(cov): " << eigenvalues_fromEigen[2] / covM.trace() << ", "
0132 << eigenvalues_fromEigen[1] / covM.trace() << ", "
0133 << eigenvalues_fromEigen[0] / covM.trace() << std::endl;
0134 LogDebug("TrackstersPCA") << "EigenValues from Eigen: " << eigenvalues_fromEigen[2] << ", "
0135 << eigenvalues_fromEigen[1] << ", " << eigenvalues_fromEigen[0] << std::endl;
0136 LogDebug("TrackstersPCA") << "EigenVector 3 from Eigen: " << eigenvectors_fromEigen(0, 2) << ", "
0137 << eigenvectors_fromEigen(1, 2) << ", " << eigenvectors_fromEigen(2, 2) << std::endl;
0138 LogDebug("TrackstersPCA") << "EigenVector 2 from Eigen: " << eigenvectors_fromEigen(0, 1) << ", "
0139 << eigenvectors_fromEigen(1, 1) << ", " << eigenvectors_fromEigen(2, 1) << std::endl;
0140 LogDebug("TrackstersPCA") << "EigenVector 1 from Eigen: " << eigenvectors_fromEigen(0, 0) << ", "
0141 << eigenvectors_fromEigen(1, 0) << ", " << eigenvectors_fromEigen(2, 0) << std::endl;
0142 LogDebug("TrackstersPCA") << "Original sigmas: " << sigmas[0] << ", " << sigmas[1] << ", " << sigmas[2]
0143 << std::endl;
0144 LogDebug("TrackstersPCA") << "SigmasEigen in PCA space: " << sigmasEigen[2] << ", " << sigmasEigen[1] << ", "
0145 << sigmasEigen[0] << std::endl;
0146 LogDebug("TrackstersPCA") << "covM: \n" << covM << std::endl;
0147 }
0148 }
0149 }
0150
0151 std::pair<float, float> ticl::computeLocalTracksterTime(const Trackster &trackster,
0152 const std::vector<reco::CaloCluster> &layerClusters,
0153 const edm::ValueMap<std::pair<float, float>> &layerClustersTime,
0154 const Eigen::Vector3d &barycenter,
0155 size_t N) {
0156 float tracksterTime = 0.;
0157 float tracksterTimeErr = 0.;
0158 std::set<uint32_t> usedLC;
0159
0160 auto project_lc_to_pca = [](const std::vector<double> &point, const std::vector<double> &segment_end) {
0161 double dot_product = 0.0;
0162 double segment_dot = 0.0;
0163
0164 for (int i = 0; i < 3; ++i) {
0165 dot_product += point[i] * segment_end[i];
0166 segment_dot += segment_end[i] * segment_end[i];
0167 }
0168
0169 double projection = 0.0;
0170 if (segment_dot != 0.0) {
0171 projection = dot_product / segment_dot;
0172 }
0173
0174 std::vector<double> closest_point(3);
0175 for (int i = 0; i < 3; ++i) {
0176 closest_point[i] = projection * segment_end[i];
0177 }
0178
0179 double distance = 0.0;
0180 for (int i = 0; i < 3; ++i) {
0181 distance += std::pow(point[i] - closest_point[i], 2);
0182 }
0183
0184 return std::sqrt(distance);
0185 };
0186
0187 constexpr double c = 29.9792458;
0188 for (size_t i = 0; i < N; ++i) {
0189
0190 if ((usedLC.insert(trackster.vertices(i))).second) {
0191 float timeE = layerClustersTime.get(trackster.vertices(i)).second;
0192 if (timeE > 0.f) {
0193 float time = layerClustersTime.get(trackster.vertices(i)).first;
0194 timeE = 1.f / pow(timeE, 2);
0195 float x = layerClusters[trackster.vertices(i)].x();
0196 float y = layerClusters[trackster.vertices(i)].y();
0197 float z = layerClusters[trackster.vertices(i)].z();
0198
0199 if (project_lc_to_pca({x, y, z}, {barycenter[0], barycenter[1], barycenter[2]}) < 3) {
0200 float deltaT = 1.f / c *
0201 std::sqrt(((barycenter[2] / z - 1.f) * x) * ((barycenter[2] / z - 1.f) * x) +
0202 ((barycenter[2] / z - 1.f) * y) * ((barycenter[2] / z - 1.f) * y) +
0203 (barycenter[2] - z) * (barycenter[2] - z));
0204 time = std::abs(barycenter[2]) < std::abs(z) ? time - deltaT : time + deltaT;
0205
0206 tracksterTime += time * timeE;
0207 tracksterTimeErr += timeE;
0208 }
0209 }
0210 }
0211 }
0212 if (tracksterTimeErr > 0.f)
0213 return {tracksterTime / tracksterTimeErr, 1.f / std::sqrt(tracksterTimeErr)};
0214 else
0215 return {-99.f, -1.f};
0216 }
0217
0218 std::pair<float, float> ticl::computeTracksterTime(const Trackster &trackster,
0219 const edm::ValueMap<std::pair<float, float>> &layerClustersTime,
0220 size_t N) {
0221 std::vector<float> times;
0222 std::vector<float> timeErrors;
0223 std::set<uint32_t> usedLC;
0224
0225 for (size_t i = 0; i < N; ++i) {
0226
0227 if ((usedLC.insert(trackster.vertices(i))).second) {
0228 float timeE = layerClustersTime.get(trackster.vertices(i)).second;
0229 if (timeE > 0.f) {
0230 times.push_back(layerClustersTime.get(trackster.vertices(i)).first);
0231 timeErrors.push_back(1.f / pow(timeE, 2));
0232 }
0233 }
0234 }
0235
0236 hgcalsimclustertime::ComputeClusterTime timeEstimator;
0237 return timeEstimator.fixSizeHighestDensity(times, timeErrors);
0238 }