CMS 3D CMS Logo

TrackstersPCA.cc
Go to the documentation of this file.
4 #include "TrackstersPCA.h"
5 
6 #include <iostream>
7 #include <set>
8 
9 #include <Eigen/Core>
10 #include <Eigen/Dense>
11 
12 void ticl::assignPCAtoTracksters(std::vector<Trackster> &tracksters,
13  const std::vector<reco::CaloCluster> &layerClusters,
14  const edm::ValueMap<std::pair<float, float>> &layerClustersTime,
15  double z_limit_em,
16  bool computeLocalTime,
17  bool energyWeight) {
18  LogDebug("TrackstersPCA_Eigen") << "------- Eigen -------" << std::endl;
19 
20  for (auto &trackster : tracksters) {
22  point << 0., 0., 0.;
23  Eigen::Vector3d barycenter;
24  barycenter << 0., 0., 0.;
25 
26  auto fillPoint = [&](const reco::CaloCluster &c, const float weight = 1.f) {
27  point[0] = weight * c.x();
28  point[1] = weight * c.y();
29  point[2] = weight * c.z();
30  };
31 
32  // Initialize this trackster with default, dummy values
33  trackster.setRawEnergy(0.f);
34  trackster.setRawEmEnergy(0.f);
35  trackster.setRawPt(0.f);
36  trackster.setRawEmPt(0.f);
37 
38  size_t N = trackster.vertices().size();
39  if (N == 0)
40  continue;
41  float weight = 1.f / N;
42  float weights2_sum = 0.f;
43 
44  for (size_t i = 0; i < N; ++i) {
45  auto fraction = 1.f / trackster.vertex_multiplicity(i);
46  trackster.addToRawEnergy(layerClusters[trackster.vertices(i)].energy() * fraction);
47  if (std::abs(layerClusters[trackster.vertices(i)].z()) <= z_limit_em)
48  trackster.addToRawEmEnergy(layerClusters[trackster.vertices(i)].energy() * fraction);
49 
50  // Compute the weighted barycenter.
51  if (energyWeight)
52  weight = layerClusters[trackster.vertices(i)].energy() * fraction;
53  fillPoint(layerClusters[trackster.vertices(i)], weight);
54  for (size_t j = 0; j < 3; ++j)
55  barycenter[j] += point[j];
56  }
57  float raw_energy = trackster.raw_energy();
58  float inv_raw_energy = 1.f / raw_energy;
59  if (energyWeight)
60  barycenter *= inv_raw_energy;
61  trackster.setBarycenter(ticl::Trackster::Vector(barycenter));
62  std::pair<float, float> timeTrackster;
63  if (computeLocalTime)
64  timeTrackster = ticl::computeLocalTracksterTime(trackster, layerClusters, layerClustersTime, barycenter, N);
65  else
66  timeTrackster = ticl::computeTracksterTime(trackster, layerClustersTime, N);
67 
68  trackster.setTimeAndError(timeTrackster.first, timeTrackster.second);
69  LogDebug("TrackstersPCA") << "Use energy weighting: " << energyWeight << std::endl;
70  LogDebug("TrackstersPCA") << "\nTrackster characteristics: " << std::endl;
71  LogDebug("TrackstersPCA") << "Size: " << N << std::endl;
72  LogDebug("TrackstersPCA") << "Energy: " << trackster.raw_energy() << std::endl;
73  LogDebug("TrackstersPCA") << "raw_pt: " << trackster.raw_pt() << std::endl;
74  LogDebug("TrackstersPCA") << "Means: " << barycenter[0] << ", " << barycenter[1] << ", " << barycenter[2]
75  << std::endl;
76  LogDebug("TrackstersPCA") << "Time: " << trackster.time() << " +/- " << trackster.timeError() << std::endl;
77 
78  if (N > 2) {
79  Eigen::Vector3d sigmas;
80  sigmas << 0., 0., 0.;
81  Eigen::Vector3d sigmasEigen;
82  sigmasEigen << 0., 0., 0.;
83  Eigen::Matrix3d covM = Eigen::Matrix3d::Zero();
84  // Compute the Covariance Matrix and the sum of the squared weights, used
85  // to compute the correct normalization.
86  // The barycenter has to be known.
87  for (size_t i = 0; i < N; ++i) {
88  fillPoint(layerClusters[trackster.vertices(i)]);
89  if (energyWeight && trackster.raw_energy())
90  weight = (layerClusters[trackster.vertices(i)].energy() / trackster.vertex_multiplicity(i)) * inv_raw_energy;
91  weights2_sum += weight * weight;
92  for (size_t x = 0; x < 3; ++x)
93  for (size_t y = 0; y <= x; ++y) {
94  covM(x, y) += weight * (point[x] - barycenter[x]) * (point[y] - barycenter[y]);
95  covM(y, x) = covM(x, y);
96  }
97  }
98  covM *= 1.f / (1.f - weights2_sum);
99 
100  // Perform the actual decomposition
101  Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d>::RealVectorType eigenvalues_fromEigen;
102  Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d>::EigenvectorsType eigenvectors_fromEigen;
103  Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> eigensolver(covM);
104  if (eigensolver.info() != Eigen::Success) {
105  eigenvalues_fromEigen = eigenvalues_fromEigen.Zero();
106  eigenvectors_fromEigen = eigenvectors_fromEigen.Zero();
107  } else {
108  eigenvalues_fromEigen = eigensolver.eigenvalues();
109  eigenvectors_fromEigen = eigensolver.eigenvectors();
110  }
111 
112  // Compute the spread in the both spaces.
113  for (size_t i = 0; i < N; ++i) {
114  fillPoint(layerClusters[trackster.vertices(i)]);
115  sigmas += weight * (point - barycenter).cwiseAbs2();
116  Eigen::Vector3d point_transformed = eigenvectors_fromEigen * (point - barycenter);
117  if (energyWeight && raw_energy)
118  weight = (layerClusters[trackster.vertices(i)].energy() / trackster.vertex_multiplicity(i)) * inv_raw_energy;
119  sigmasEigen += weight * (point_transformed.cwiseAbs2());
120  }
121  sigmas /= (1.f - weights2_sum);
122  sigmasEigen /= (1.f - weights2_sum);
123 
124  trackster.fillPCAVariables(eigenvalues_fromEigen,
125  eigenvectors_fromEigen,
126  sigmas,
127  sigmasEigen,
128  3,
130 
131  LogDebug("TrackstersPCA") << "EigenValues from Eigen/Tr(cov): " << eigenvalues_fromEigen[2] / covM.trace() << ", "
132  << eigenvalues_fromEigen[1] / covM.trace() << ", "
133  << eigenvalues_fromEigen[0] / covM.trace() << std::endl;
134  LogDebug("TrackstersPCA") << "EigenValues from Eigen: " << eigenvalues_fromEigen[2] << ", "
135  << eigenvalues_fromEigen[1] << ", " << eigenvalues_fromEigen[0] << std::endl;
136  LogDebug("TrackstersPCA") << "EigenVector 3 from Eigen: " << eigenvectors_fromEigen(0, 2) << ", "
137  << eigenvectors_fromEigen(1, 2) << ", " << eigenvectors_fromEigen(2, 2) << std::endl;
138  LogDebug("TrackstersPCA") << "EigenVector 2 from Eigen: " << eigenvectors_fromEigen(0, 1) << ", "
139  << eigenvectors_fromEigen(1, 1) << ", " << eigenvectors_fromEigen(2, 1) << std::endl;
140  LogDebug("TrackstersPCA") << "EigenVector 1 from Eigen: " << eigenvectors_fromEigen(0, 0) << ", "
141  << eigenvectors_fromEigen(1, 0) << ", " << eigenvectors_fromEigen(2, 0) << std::endl;
142  LogDebug("TrackstersPCA") << "Original sigmas: " << sigmas[0] << ", " << sigmas[1] << ", " << sigmas[2]
143  << std::endl;
144  LogDebug("TrackstersPCA") << "SigmasEigen in PCA space: " << sigmasEigen[2] << ", " << sigmasEigen[1] << ", "
145  << sigmasEigen[0] << std::endl;
146  LogDebug("TrackstersPCA") << "covM: \n" << covM << std::endl;
147  }
148  }
149 }
150 
151 std::pair<float, float> ticl::computeLocalTracksterTime(const Trackster &trackster,
152  const std::vector<reco::CaloCluster> &layerClusters,
153  const edm::ValueMap<std::pair<float, float>> &layerClustersTime,
154  const Eigen::Vector3d &barycenter,
155  size_t N) {
156  float tracksterTime = 0.;
157  float tracksterTimeErr = 0.;
158  std::set<uint32_t> usedLC;
159 
160  auto project_lc_to_pca = [](const std::vector<double> &point, const std::vector<double> &segment_end) {
161  double dot_product = 0.0;
162  double segment_dot = 0.0;
163 
164  for (int i = 0; i < 3; ++i) {
165  dot_product += point[i] * segment_end[i];
166  segment_dot += segment_end[i] * segment_end[i];
167  }
168 
169  double projection = 0.0;
170  if (segment_dot != 0.0) {
171  projection = dot_product / segment_dot;
172  }
173 
174  std::vector<double> closest_point(3);
175  for (int i = 0; i < 3; ++i) {
176  closest_point[i] = projection * segment_end[i];
177  }
178 
179  double distance = 0.0;
180  for (int i = 0; i < 3; ++i) {
181  distance += std::pow(point[i] - closest_point[i], 2);
182  }
183 
184  return std::sqrt(distance);
185  };
186 
187  constexpr double c = 29.9792458; // cm/ns
188  for (size_t i = 0; i < N; ++i) {
189  // Add timing from layerClusters not already used
190  if ((usedLC.insert(trackster.vertices(i))).second) {
191  float timeE = layerClustersTime.get(trackster.vertices(i)).second;
192  if (timeE > 0.f) {
193  float time = layerClustersTime.get(trackster.vertices(i)).first;
194  timeE = 1.f / pow(timeE, 2);
195  float x = layerClusters[trackster.vertices(i)].x();
196  float y = layerClusters[trackster.vertices(i)].y();
197  float z = layerClusters[trackster.vertices(i)].z();
198 
199  if (project_lc_to_pca({x, y, z}, {barycenter[0], barycenter[1], barycenter[2]}) < 3) { // set MR to 3
200  float deltaT = 1.f / c *
201  std::sqrt(((barycenter[2] / z - 1.f) * x) * ((barycenter[2] / z - 1.f) * x) +
202  ((barycenter[2] / z - 1.f) * y) * ((barycenter[2] / z - 1.f) * y) +
203  (barycenter[2] - z) * (barycenter[2] - z));
204  time = std::abs(barycenter[2]) < std::abs(z) ? time - deltaT : time + deltaT;
205 
206  tracksterTime += time * timeE;
207  tracksterTimeErr += timeE;
208  }
209  }
210  }
211  }
212  if (tracksterTimeErr > 0.f)
213  return {tracksterTime / tracksterTimeErr, 1.f / std::sqrt(tracksterTimeErr)};
214  else
215  return {-99.f, -1.f};
216 }
217 
218 std::pair<float, float> ticl::computeTracksterTime(const Trackster &trackster,
219  const edm::ValueMap<std::pair<float, float>> &layerClustersTime,
220  size_t N) {
221  std::vector<float> times;
222  std::vector<float> timeErrors;
223  std::set<uint32_t> usedLC;
224 
225  for (size_t i = 0; i < N; ++i) {
226  // Add timing from layerClusters not already used
227  if ((usedLC.insert(trackster.vertices(i))).second) {
228  float timeE = layerClustersTime.get(trackster.vertices(i)).second;
229  if (timeE > 0.f) {
230  times.push_back(layerClustersTime.get(trackster.vertices(i)).first);
231  timeErrors.push_back(1.f / pow(timeE, 2));
232  }
233  }
234  }
235 
237  return timeEstimator.fixSizeHighestDensity(times, timeErrors);
238 }
Eigen::Vector3d Vector3d
Definition: FitResult.h:11
Eigen::Matrix3d Matrix3d
Definition: FitResult.h:15
math::XYZVectorF Vector
Definition: Trackster.h:21
std::pair< float, float > computeLocalTracksterTime(const Trackster &trackster, const std::vector< reco::CaloCluster > &layerClusters, const edm::ValueMap< std::pair< float, float >> &layerClustersTime, const Eigen::Vector3d &barycenter, size_t N)
Definition: weight.py:1
float float float z
U second(std::pair< T, U > const &p)
std::pair< float, float > fixSizeHighestDensity(std::vector< float > &time, std::vector< float > weight=std::vector< float >(), unsigned int minNhits=3, float deltaT=0.210, float timeWidthBy=0.5)
T sqrt(T t)
Definition: SSEVec.h:23
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
double f[11][100]
std::pair< float, float > computeTracksterTime(const Trackster &trackster, const edm::ValueMap< std::pair< float, float >> &layerClustersTime, size_t N)
std::vector< unsigned int > & vertices()
Definition: Trackster.h:57
#define N
Definition: blowfish.cc:9
float x
void assignPCAtoTracksters(std::vector< Trackster > &, const std::vector< reco::CaloCluster > &, const edm::ValueMap< std::pair< float, float >> &, double, bool computeLocalTime=false, bool energyWeight=true)
Power< A, B >::type pow(const A &a, const B &b)
Definition: Power.h:29
*vegas h *****************************************************used in the default bin number in original ***version of VEGAS is ***a higher bin number might help to derive a more precise ***grade subtle point
Definition: invegas.h:5
#define LogDebug(id)