11#include "TMatrixDSym.h"
12#include "TMatrixDSymEigen.h"
14#include "TDecompChol.h"
15#include "Math/Vector3D.h"
16#include "Math/Point3D.h"
21 for (
const auto &p : scifi_planes)
25 return p.GetStation();
34 for (
auto p = scifi_planes.rbegin();
p != scifi_planes.rend();
p++) {
37 return p->GetStation();
46 for (
const auto &p : us_planes)
50 return p.GetStation();
59 for (
auto p = us_planes.rbegin();
p != us_planes.rend();
p++) {
62 return p->GetStation();
70 std::vector<double> positions_x;
71 std::vector<double> positions_y;
72 std::vector<double> positions_z;
73 std::vector<double> err_positions_x;
74 std::vector<double> err_positions_y;
75 std::vector<double> err_positions_z;
77 auto collect_centroids = [&](
const auto &planes) {
78 for (
const auto &p : planes) {
79 auto centroid =
p.GetCentroid();
80 auto centroid_error =
p.GetCentroidError();
82 if (!(std::isnan(centroid.X()) || std::isnan(centroid.Y()) || std::isnan(centroid.Z()))) {
83 positions_x.push_back(centroid.X());
84 positions_y.push_back(centroid.Y());
85 positions_z.push_back(centroid.Z());
86 err_positions_x.push_back(centroid_error.X());
87 err_positions_y.push_back(centroid_error.Y());
88 err_positions_z.push_back(centroid_error.Z());
93 collect_centroids(scifi_planes);
94 collect_centroids(us_planes);
97 return std::make_pair(ROOT::Math::XYZPoint(std::nan(
""), std::nan(
""), std::nan(
"")), ROOT::Math::XYZVector(std::nan(
""), std::nan(
""), std::nan(
"")));
100 auto weighted_linear_fit = [](
const std::vector<double> &
z,
const std::vector<double> &
val,
const std::vector<double> &err)
102 const int n_points =
z.size();
103 const int n_variables = 2;
107 v_z.Use(n_points,
const_cast<double*
>(
z.data()));
109 v_y.Use(n_points,
const_cast<double*
>(
val.data()));
111 v_e.Use(n_points,
const_cast<double*
>(err.data()));
113 TMatrixD matrix(n_points, n_variables);
114 TMatrixDColumn(matrix,0) = 1.0;
115 TMatrixDColumn(matrix,1) = v_z;
118 TVectorD coeffs = NormalEqn(matrix, v_y, v_e);
120 return std::make_pair(coeffs[0], coeffs[1]);
123 auto [intercept_x, slope_x] = weighted_linear_fit(positions_z, positions_x, err_positions_x);
124 auto [intercept_y, slope_y] = weighted_linear_fit(positions_z, positions_y, err_positions_y);
126 ROOT::Math::XYZPoint shower_intercept(intercept_x, intercept_y, 0.0);
127 ROOT::Math::XYZVector shower_direction(slope_x, slope_y, 1.0);
129 return std::make_pair(shower_intercept, shower_direction.Unit());
132std::pair<std::vector<snd::analysis_tools::ScifiPlane>, std::vector<snd::analysis_tools::USPlane>>
snd::analysis_tools::GetShoweringPlanes(
const std::vector<snd::analysis_tools::ScifiPlane> &scifi_planes,
const std::vector<snd::analysis_tools::USPlane> &us_planes)
134 std::vector<snd::analysis_tools::ScifiPlane> sh_scifi_planes;
135 std::vector<snd::analysis_tools::USPlane> sh_us_planes;
138 std::copy_if(scifi_planes.begin(), scifi_planes.end(), std::back_inserter(sh_scifi_planes), [](
const snd::analysis_tools::ScifiPlane& p) { return p.HasShower(); });
140 std::copy_if(us_planes.begin(), us_planes.end(), std::back_inserter(sh_us_planes), [](
const snd::analysis_tools::USPlane& p) { return p.HasShower(); });
142 for (
auto &p: sh_scifi_planes) {
145 for (
auto &p: sh_us_planes) {
149 return std::make_pair(sh_scifi_planes, sh_us_planes);
152std::pair<double, double>
PCA(
const std::vector<double>& u,
const std::vector<double>& z)
155 assert(u.size() == z.size() && u.size() >= 2);
156 const size_t n_samples = u.size();
157 const int n_variables = 2;
160 double mean_u = 0.0, mean_z = 0.0;
161 for (
size_t i = 0; i < n_samples; ++i)
170 double cov_uu = 0.0, cov_zz = 0.0, cov_uz = 0.0;
171 for (
size_t i = 0; i < n_samples; ++i)
173 double du = u[i] - mean_u;
174 double dz = z[i] - mean_z;
180 const double denom = (n_samples > 1) ? (n_samples - 1.0) : 1.0;
186 TMatrixDSym cov_matrix(n_variables);
187 cov_matrix[0][0] = cov_uu;
188 cov_matrix[0][1] = cov_uz;
189 cov_matrix[1][0] = cov_uz;
190 cov_matrix[1][1] = cov_zz;
194 TMatrixDSymEigen eig_decomp(cov_matrix);
195 TVectorD evals = eig_decomp.GetEigenValues();
199 if (evals[0] < evals[1])
201 std::swap(evals[0], evals[1]);
206 return {evals[0], evals[1]};
211 std::vector<double> x, y, zx, zy;
212 for (
auto &p : scifi_planes) {
214 if (use_all_centroids ==
false) {
215 for (
auto &hit : p.GetHits()) {
225 auto centroid = p.GetCentroid();
227 if (!std::isnan(centroid.Z())) {
228 if (!std::isnan(centroid.X())) {
229 x.push_back(centroid.X());
230 zx.push_back(centroid.Z());
232 if (!std::isnan(centroid.Y())) {
233 y.push_back(centroid.Y());
234 zy.push_back(centroid.Z());
241 if (x.size() < 2 || y.size() < 2 || zx.size() < 2 || zy.size() < 2) {
244 double lambda1, lambda2;
245 std::tie(lambda1, lambda2) =
PCA(x, zx);
246 double anisotropy_xz = (lambda1 > 0) ? 1.0 - lambda2 / lambda1 : 0.0;
247 auto pca_result_yz =
PCA(y, zy);
248 std::tie(lambda1, lambda2) =
PCA(y, zy);
249 double anisotropy_yz = (lambda1 > 0) ? 1.0 - lambda2 / lambda1 : 0.0;
250 return {anisotropy_xz, anisotropy_yz};
255 std::vector<double> y, zy;
256 for (
auto &p : us_planes) {
258 if (use_all_centroids ==
false) {
259 for (
auto &hit : p.GetHits()) {
264 auto centroid = p.GetCentroid();
266 if (!(std::isnan(centroid.Z()) || std::isnan(centroid.Y()))) {
267 y.push_back(centroid.Y());
268 zy.push_back(centroid.Z());
274 if (y.size() < 2 || zy.size() < 2) {
277 double lambda1, lambda2;
278 std::tie(lambda1, lambda2) =
PCA(y, zy);
279 return (lambda1 > 0) ? 1.0 - lambda2 / lambda1 : 0.0;
int centroid_min_valid_station