SND@LHC Software
Loading...
Searching...
No Matches
sndShowerTools.cxx
Go to the documentation of this file.
1#include "sndShowerTools.h"
2
3#include <vector>
4#include <algorithm>
5#include <utility>
6
7#include "sndConfiguration.h"
8#include "sndScifiPlane.h"
9#include "sndUSPlane.h"
10#include "TMatrixD.h"
11#include "TVectorD.h"
12#include "TDecompChol.h"
13#include "Math/Vector3D.h"
14#include "Math/Point3D.h"
15
16int snd::analysis_tools::GetScifiShowerStart(const std::vector<snd::analysis_tools::ScifiPlane> &scifi_planes)
17{
18 // Assuming planes are ordered
19 for (const auto &p : scifi_planes)
20 {
21 if (p.HasShower())
22 {
23 return p.GetStation();
24 }
25 }
26 return -1;
27}
28
29int snd::analysis_tools::GetScifiShowerEnd(const std::vector<snd::analysis_tools::ScifiPlane> &scifi_planes)
30{
31 // Assuming planes are ordered
32 for (auto p = scifi_planes.rbegin(); p != scifi_planes.rend(); p++) {
33 if (p->HasShower())
34 {
35 return p->GetStation();
36 }
37 }
38 return -1;
39}
40
41int snd::analysis_tools::GetUSShowerStart(const std::vector<snd::analysis_tools::USPlane> &us_planes)
42{
43 // Assuming planes are ordered
44 for (const auto &p : us_planes)
45 {
46 if (p.HasShower())
47 {
48 return p.GetStation();
49 }
50 }
51 return -1;
52}
53
54int snd::analysis_tools::GetUSShowerEnd(const std::vector<snd::analysis_tools::USPlane> &us_planes)
55{
56 // Assuming planes are ordered
57 for (auto p = us_planes.rbegin(); p != us_planes.rend(); p++) {
58 if (p->HasShower())
59 {
60 return p->GetStation();
61 }
62 }
63 return -1;
64}
65
66std::pair<ROOT::Math::XYZPoint, ROOT::Math::XYZVector> snd::analysis_tools::GetShowerInterceptAndDirection(const snd::Configuration &configuration, const std::vector<snd::analysis_tools::ScifiPlane> &scifi_planes, const std::vector<snd::analysis_tools::USPlane> &us_planes)
67{
68 std::vector<double> positions_x;
69 std::vector<double> positions_y;
70 std::vector<double> positions_z;
71 std::vector<double> err_positions_x;
72 std::vector<double> err_positions_y;
73 std::vector<double> err_positions_z;
74
75 auto collect_centroids = [&](const auto &planes) {
76 for (const auto &p : planes) {
77 auto centroid = p.GetCentroid();
78 auto centroid_error = p.GetCentroidError();
79 // Check that centroid is valid
80 if (!(std::isnan(centroid.X()) || std::isnan(centroid.Y()) || std::isnan(centroid.Z()))) {
81 positions_x.push_back(centroid.X());
82 positions_y.push_back(centroid.Y());
83 positions_z.push_back(centroid.Z());
84 err_positions_x.push_back(centroid_error.X());
85 err_positions_y.push_back(centroid_error.Y());
86 err_positions_z.push_back(centroid_error.Z());
87 }
88 }
89 };
90
91 collect_centroids(scifi_planes);
92 collect_centroids(us_planes);
93
94 if (static_cast<int>(positions_z.size()) < configuration.centroid_min_valid_station) {
95 return std::make_pair(ROOT::Math::XYZPoint(std::nan(""), std::nan(""), std::nan("")), ROOT::Math::XYZVector(std::nan(""), std::nan(""), std::nan("")));
96 }
97
98 auto weighted_linear_fit = [](const std::vector<double> &z, const std::vector<double> &val, const std::vector<double> &err)
99 {
100 const int n_points = z.size();
101 const int n_variables = 2; // intercept + slope
102
103 // Wrap existing memory into TVectorD
104 TVectorD v_z;
105 v_z.Use(n_points, const_cast<double*>(z.data()));
106 TVectorD v_y;
107 v_y.Use(n_points, const_cast<double*>(val.data()));
108 TVectorD v_e;
109 v_e.Use(n_points, const_cast<double*>(err.data()));
110
111 TMatrixD matrix(n_points, n_variables);
112 TMatrixDColumn(matrix,0) = 1.0;
113 TMatrixDColumn(matrix,1) = v_z;
114
115 // Solve normal equations (weighted least squares)
116 TVectorD coeffs = NormalEqn(matrix, v_y, v_e);
117
118 return std::make_pair(coeffs[0], coeffs[1]); // (intercept, slope)
119 };
120
121 auto [intercept_x, slope_x] = weighted_linear_fit(positions_z, positions_x, err_positions_x);
122 auto [intercept_y, slope_y] = weighted_linear_fit(positions_z, positions_y, err_positions_y);
123
124 ROOT::Math::XYZPoint shower_intercept(intercept_x, intercept_y, 0.0);
125 ROOT::Math::XYZVector shower_direction(slope_x, slope_y, 1.0);
126
127 return std::make_pair(shower_intercept, shower_direction.Unit());
128}
129
130std::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)
131{
132 std::vector<snd::analysis_tools::ScifiPlane> sh_scifi_planes;
133 std::vector<snd::analysis_tools::USPlane> sh_us_planes;
134
135 // Filter showering Scifi planes
136 std::copy_if(scifi_planes.begin(), scifi_planes.end(), std::back_inserter(sh_scifi_planes), [](const snd::analysis_tools::ScifiPlane& p) { return p.HasShower(); });
137 // Filter showering US planes
138 std::copy_if(us_planes.begin(), us_planes.end(), std::back_inserter(sh_us_planes), [](const snd::analysis_tools::USPlane& p) { return p.HasShower(); });
139
140 for (auto &p: sh_scifi_planes) {
141 p.FindCentroid();
142 }
143 for (auto &p: sh_us_planes) {
144 p.FindCentroid();
145 }
146
147 return std::make_pair(sh_scifi_planes, sh_us_planes);
148}
149
std::pair< std::vector< ScifiPlane >, std::vector< USPlane > > GetShoweringPlanes(const std::vector< ScifiPlane > &scifi_planes, const std::vector< USPlane > &us_planes)
int GetUSShowerEnd(const std::vector< USPlane > &us_planes)
int GetScifiShowerStart(const std::vector< ScifiPlane > &scifi_planes)
int GetUSShowerStart(const std::vector< USPlane > &us_planes)
int GetScifiShowerEnd(const std::vector< ScifiPlane > &scifi_planes)
std::pair< ROOT::Math::XYZPoint, ROOT::Math::XYZVector > GetShowerInterceptAndDirection(const Configuration &configuration, const std::vector< ScifiPlane > &scifi_planes, const std::vector< USPlane > &us_planes)