SND@LHC Software
Loading...
Searching...
No Matches
snd::analysis_tools::ScifiPlane Class Reference

#include <sndScifiPlane.h>

Collaboration diagram for snd::analysis_tools::ScifiPlane:

Classes

struct  ScifiHit
 
struct  xy_pair
 

Public Member Functions

 ScifiPlane (std::vector< sndScifiHit * > snd_hits, const Configuration &configuration, Scifi *scifi_geometry, int station)
 
const int GetStation () const
 
const std::vector< ScifiHitGetHits () const
 
const ROOT::Math::XYZPoint GetCentroid () const
 
const ROOT::Math::XYZPoint GetCentroidError () const
 
const xy_pair< double > GetTotQdc (bool only_positive=false) const
 
const xy_pair< double > GetTotEnergy (bool only_positive=false) const
 
const xy_pair< int > GetNHits () const
 
const ROOT::Math::XYZPoint GetCluster (int max_gap) const
 
void FindCentroid ()
 
bool HasShower () const
 
void TimeFilter (double min_timestamp, double max_timestamp)
 
xy_pair< double > GetPointQdc (const ROOT::Math::XYZPoint &point, double radius) const
 

Private Attributes

std::vector< ScifiHithits_
 
Configuration configuration_
 
ROOT::Math::XYZPoint centroid_
 
ROOT::Math::XYZPoint centroid_error_
 
int station_
 

Detailed Description

Definition at line 13 of file sndScifiPlane.h.

Constructor & Destructor Documentation

◆ ScifiPlane()

snd::analysis_tools::ScifiPlane::ScifiPlane ( std::vector< sndScifiHit * >  snd_hits,
const Configuration configuration,
Scifi scifi_geometry,
int  station 
)

Definition at line 15 of file sndScifiPlane.cxx.

15 : configuration_(configuration), centroid_(std::nan(""), std::nan(""), std::nan("")), centroid_error_(std::nan(""), std::nan(""), std::nan("")), station_(station)
16{
17 for ( auto snd_hit : snd_hits)
18 {
19 if (!snd_hit->isValid()) continue;
20 ScifiHit hit;
21 hit.channel_index = 512 * snd_hit->GetMat() + 128 * snd_hit->GetSiPM() + snd_hit->GetSiPMChan();
22 int detectorID = snd_hit->GetDetectorID();
24 hit.timestamp = snd_hit->GetTime(0) / ShipUnit::snd_TDC2ns; // timestamp is in clock cycles
25 }
26 else {
27 hit.timestamp = (scifi_geometry->GetCorrectedTime(detectorID, snd_hit->GetTime(0)*ShipUnit::snd_TDC2ns, 0) / ShipUnit::snd_TDC2ns); // timestamp is in clock cycles
28 }
29 hit.qdc = snd_hit->GetSignal(0);
30 hit.is_x = snd_hit->isVertical();
31
32 TVector3 A, B;
33 scifi_geometry->GetSiPMPosition(detectorID, A, B);
34 hit.z = A.Z();
35 if (hit.is_x)
36 {
37 hit.x = A.X();
38 hit.y = std::nan("");
39 }
40 else
41 {
42 hit.x = std::nan("");
43 hit.y = A.Y();
44 }
45 hits_.push_back(hit);
46 }
47}
void GetSiPMPosition(Int_t SiPMChan, TVector3 &A, TVector3 &B)
Definition Scifi.cxx:727
Double_t GetCorrectedTime(Int_t fDetectorID, Double_t rawTime, Double_t L)
Definition Scifi.cxx:614
ROOT::Math::XYZPoint centroid_error_
std::vector< ScifiHit > hits_
ROOT::Math::XYZPoint centroid_

Member Function Documentation

◆ FindCentroid()

void snd::analysis_tools::ScifiPlane::FindCentroid ( )

Definition at line 228 of file sndScifiPlane.cxx.

229{
230 centroid_.SetXYZ(0, 0, 0);
231 double tot_qdc_x{0}, sum_qdc2_x{0.0};
232 double tot_qdc_y{0}, sum_qdc2_y{0.0};
233 std::vector<ScifiHit> cleaned_hits = hits_;
234
235 cleaned_hits.erase(std::remove_if(cleaned_hits.begin(), cleaned_hits.end(),
236 [&](auto &hit)
237 { return hit.qdc <= 0; }),
238 cleaned_hits.end());
239 int counts_x = std::count_if(cleaned_hits.begin(), cleaned_hits.end(), [](auto &hit)
240 { return hit.is_x; });
241 int counts_y = static_cast<int>(cleaned_hits.size())-counts_x;
243 centroid_ = ROOT::Math::XYZPoint(std::nan(""), std::nan(""), std::nan(""));
244 return;
245 }
246
247 for (auto &hit : cleaned_hits)
248 {
249 if (hit.qdc > 0)
250 {
251 if (hit.is_x)
252 {
253 centroid_.SetX(centroid_.X() + hit.x * hit.qdc);
254 tot_qdc_x += hit.qdc;
255 sum_qdc2_x += hit.qdc*hit.qdc;
256 }
257 else
258 {
259 centroid_.SetY(centroid_.Y() + hit.y * hit.qdc);
260 tot_qdc_y += hit.qdc;
261 sum_qdc2_y += hit.qdc*hit.qdc;
262 }
263
264 centroid_.SetZ(centroid_.Z() + hit.z * hit.qdc);
265 }
266 }
267 centroid_ = ROOT::Math::XYZPoint((tot_qdc_x > 0) ? centroid_.X() / tot_qdc_x : std::nan(""), (tot_qdc_y > 0) ? centroid_.Y() / tot_qdc_y : std::nan(""), (tot_qdc_x+tot_qdc_y > 0) ? centroid_.Z() / (tot_qdc_x+tot_qdc_y) : std::nan(""));
268 auto qdc_x_error_scaler = sqrt(sum_qdc2_x)/tot_qdc_x;
269 auto qdc_y_error_scaler = sqrt(sum_qdc2_y)/tot_qdc_y;
270 auto qdc_z_error_scaler = sqrt(sum_qdc2_x+sum_qdc2_y)/(tot_qdc_x+tot_qdc_y);
271 centroid_error_ = ROOT::Math::XYZPoint(configuration_.scifi_centroid_error_x*qdc_x_error_scaler,
272 configuration_.scifi_centroid_error_y*qdc_y_error_scaler,
273 configuration_.scifi_centroid_error_z*qdc_z_error_scaler);
274}

◆ GetCentroid()

const ROOT::Math::XYZPoint snd::analysis_tools::ScifiPlane::GetCentroid ( ) const
inline

Definition at line 39 of file sndScifiPlane.h.

39{ return centroid_; }

◆ GetCentroidError()

const ROOT::Math::XYZPoint snd::analysis_tools::ScifiPlane::GetCentroidError ( ) const
inline

Definition at line 40 of file sndScifiPlane.h.

40{ return centroid_error_; }

◆ GetCluster()

const ROOT::Math::XYZPoint snd::analysis_tools::ScifiPlane::GetCluster ( int  max_gap) const

Definition at line 112 of file sndScifiPlane.cxx.

113{
114 std::vector<double> pos_x(configuration_.scifi_n_channels_per_plane, std::nan(""));
115 std::vector<double> pos_y(configuration_.scifi_n_channels_per_plane, std::nan(""));
116
117 for (auto &hit : hits_)
118 {
119 if (hit.qdc > 0)
120 {
121 if (hit.is_x)
122 {
123 pos_x[hit.channel_index] = hit.x;
124 }
125 else
126 {
127 pos_y[hit.channel_index] = hit.y;
128 }
129 }
130 }
131
132 auto largest_cluster = [&](const std::vector<double> &positions)
133 {
134 int n = static_cast<int>(positions.size());
135
136 int best_start = -1, best_end = -1, best_size = 0;
137 int start = -1, gap_count = 0, size = 0;
138
139 // Find the largest cluster
140 for (int i = 0; i < n; ++i)
141 {
142 if (!std::isnan(positions[i]))
143 {
144 if (start == -1)
145 start = i; // Start a new cluster
146 size++;
147 gap_count = 0; // Reset consecutive gap counter
148 }
149 else
150 {
151 gap_count++;
152 if (gap_count > max_gap)
153 { // Too many consecutive gaps, finalize previous cluster
154 if (size > best_size)
155 {
156 best_start = start;
157 best_end = i - gap_count; // End before the excessive gaps
158 best_size = size;
159 }
160 // Reset for a new potential cluster
161 start = -1;
162 gap_count = 0;
163 size = 0;
164 }
165 else
166 {
167 size++; // Gaps within max_gap still count in cluster size
168 }
169 }
170 }
171
172 // Check last cluster
173 if (size > best_size)
174 {
175 best_start = start;
176 best_end = n - 1;
177 best_size = size;
178 }
179
180 // Compute the average of non-gap values in the best cluster
181 if (best_start == -1 || best_end == -1)
182 return std::nan(""); // No valid cluster found
183
184 double sum = 0.0;
185 int count = 0;
186 for (int i = best_start; i <= best_end; ++i)
187 {
188 if (!std::isnan(positions[i]))
189 {
190 sum += positions[i];
191 count++;
192 }
193 }
194
195 return (count > 0) ? sum / count : std::nan("");
196 };
197
198 double cluster_x = largest_cluster(pos_x);
199 double cluster_y = largest_cluster(pos_y);
200 if (!(std::isnan(cluster_x) || std::isnan(cluster_y))) {
201 return ROOT::Math::XYZPoint(cluster_x, cluster_y, hits_[0].z);
202 }
203 return ROOT::Math::XYZPoint(std::nan(""), std::nan(""), std::nan(""));
204}
int i
Definition ShipAna.py:86

◆ GetHits()

const std::vector< ScifiHit > snd::analysis_tools::ScifiPlane::GetHits ( ) const
inline

Definition at line 38 of file sndScifiPlane.h.

38{ return hits_; }

◆ GetNHits()

const snd::analysis_tools::ScifiPlane::xy_pair< int > snd::analysis_tools::ScifiPlane::GetNHits ( ) const

Definition at line 49 of file sndScifiPlane.cxx.

50{
51 xy_pair<int> counts{0, 0};
52 counts.x = std::count_if(hits_.begin(), hits_.end(), [](auto &hit)
53 { return hit.is_x; });
54 counts.y = static_cast<int>(hits_.size()) - counts.x;
55
56 return counts;
57}

◆ GetPointQdc()

snd::analysis_tools::ScifiPlane::xy_pair< double > snd::analysis_tools::ScifiPlane::GetPointQdc ( const ROOT::Math::XYZPoint &  point,
double  radius 
) const

Definition at line 214 of file sndScifiPlane.cxx.

215{
216 xy_pair<double> qdc{0.0, 0.0};
217 for (const auto &hit : hits_) {
218 if (hit.is_x && std::abs(hit.x - point.X()) <= radius) {
219 qdc.x += hit.qdc;
220 }
221 else if (!hit.is_x && std::abs(hit.y - point.Y()) <= radius) {
222 qdc.y += hit.qdc;
223 }
224 }
225 return qdc;
226}

◆ GetStation()

const int snd::analysis_tools::ScifiPlane::GetStation ( ) const
inline

Definition at line 37 of file sndScifiPlane.h.

37{ return station_; }

◆ GetTotEnergy()

const snd::analysis_tools::ScifiPlane::xy_pair< double > snd::analysis_tools::ScifiPlane::GetTotEnergy ( bool  only_positive = false) const

Definition at line 287 of file sndScifiPlane.cxx.

288{
289 xy_pair<double> energy{0.0, 0.0};
290 auto qdc = GetTotQdc(only_positive);
291
294
295 return energy;
296}
const xy_pair< double > GetTotQdc(bool only_positive=false) const

◆ GetTotQdc()

const snd::analysis_tools::ScifiPlane::xy_pair< double > snd::analysis_tools::ScifiPlane::GetTotQdc ( bool  only_positive = false) const

Definition at line 276 of file sndScifiPlane.cxx.

277{
278 xy_pair<double> qdc_sum{0.0, 0.0};
279 qdc_sum.x = std::accumulate(hits_.begin(), hits_.end(), 0.0, [&](double current_sum, auto &hit)
280 { return (hit.is_x && (hit.qdc > 0 || !only_positive)) ? (current_sum + hit.qdc) : current_sum; });
281 qdc_sum.y = std::accumulate(hits_.begin(), hits_.end(), 0.0, [&](double current_sum, auto &hit)
282 { return (!hit.is_x && (hit.qdc > 0 || !only_positive)) ? (current_sum + hit.qdc) : current_sum; });
283
284 return qdc_sum;
285}

◆ HasShower()

bool snd::analysis_tools::ScifiPlane::HasShower ( ) const

Definition at line 59 of file sndScifiPlane.cxx.

60{
62 {
63 throw std::runtime_error{"min_hits > window_width"};
64 }
65
67 {
68 throw std::runtime_error{"window_width > n_channels_per_plane"};
69 }
70
71 xy_pair<std::vector<int>> is_hit;
74
75 for (auto &hit : hits_)
76 {
77 if (hit.channel_index < 0 ||
78 hit.channel_index >= configuration_.scifi_n_channels_per_plane)
79 {
80 throw std::out_of_range{"hit.channel_index out of range"};
81 }
82 (hit.is_x ? is_hit.x : is_hit.y)[hit.channel_index] = 1;
83 }
84
85 auto density = [&](const std::vector<int> &hit_arr)
86 {
87 int count{0};
88
89 // Initial count for the first window
90 for (int i{0}; i < configuration_.scifi_shower_window_width; ++i)
91 {
92 count += hit_arr[i];
93 }
94
96 return true;
97
98 // Slide the window across the array
100 {
101 count += hit_arr[i] - hit_arr[i - configuration_.scifi_shower_window_width];
103 return true;
104 }
105
106 return false;
107 };
108
109 return density(is_hit.x) && density(is_hit.y);
110}

◆ TimeFilter()

void snd::analysis_tools::ScifiPlane::TimeFilter ( double  min_timestamp,
double  max_timestamp 
)

Definition at line 206 of file sndScifiPlane.cxx.

207{
208 hits_.erase(std::remove_if(hits_.begin(), hits_.end(),
209 [&](auto &hit)
210 { return hit.timestamp < min_timestamp || hit.timestamp > max_timestamp; }),
211 hits_.end());
212}

Member Data Documentation

◆ centroid_

ROOT::Math::XYZPoint snd::analysis_tools::ScifiPlane::centroid_
private

Definition at line 56 of file sndScifiPlane.h.

◆ centroid_error_

ROOT::Math::XYZPoint snd::analysis_tools::ScifiPlane::centroid_error_
private

Definition at line 57 of file sndScifiPlane.h.

◆ configuration_

Configuration snd::analysis_tools::ScifiPlane::configuration_
private

Definition at line 55 of file sndScifiPlane.h.

◆ hits_

std::vector<ScifiHit> snd::analysis_tools::ScifiPlane::hits_
private

Definition at line 54 of file sndScifiPlane.h.

◆ station_

int snd::analysis_tools::ScifiPlane::station_
private

Definition at line 59 of file sndScifiPlane.h.


The documentation for this class was generated from the following files: