15snd::analysis_tools::ScifiPlane::ScifiPlane(std::vector<sndScifiHit*> snd_hits,
Configuration configuration,
Scifi *scifi_geometry,
int station) : configuration_(configuration), centroid_(std::nan(
""), std::nan(
""), std::nan(
"")), centroid_error_(std::nan(
""), std::nan(
""), std::nan(
"")), station_(station)
17 for (
auto snd_hit : snd_hits)
20 hit.
channel_index = 512 * snd_hit->GetMat() + 128 * snd_hit->GetSiPM() + snd_hit->GetSiPMChan();
21 hit.
timestamp = (scifi_geometry->
GetCorrectedTime(snd_hit->GetDetectorID(), snd_hit->GetTime(0)*ShipUnit::snd_TDC2ns, 0) / ShipUnit::snd_TDC2ns);
22 hit.
qdc = snd_hit->GetSignal(0);
23 hit.
is_x = snd_hit->isVertical();
26 int detectorID = snd_hit->GetDetectorID();
55 if (configuration_.scifi_min_hits_in_window > configuration_.scifi_shower_window_width)
57 throw std::runtime_error{
"min_hits > window_width"};
60 if (configuration_.scifi_shower_window_width > configuration_.scifi_n_channels_per_plane)
62 throw std::runtime_error{
"window_width > n_channels_per_plane"};
66 is_hit.
x.resize(configuration_.scifi_n_channels_per_plane, 0);
67 is_hit.
y.resize(configuration_.scifi_n_channels_per_plane, 0);
69 for (
auto &hit : hits_)
71 if (hit.channel_index < 0 ||
72 hit.channel_index >= configuration_.scifi_n_channels_per_plane)
74 throw std::out_of_range{
"hit.channel_index out of range"};
76 (hit.is_x ? is_hit.
x : is_hit.
y)[hit.channel_index] = 1;
79 auto density = [&](
const std::vector<int> &hit_arr)
84 for (
int i{0}; i < configuration_.scifi_shower_window_width; ++i)
89 if (count >= configuration_.scifi_min_hits_in_window)
93 for (
int i = configuration_.scifi_shower_window_width; i < configuration_.scifi_n_channels_per_plane; ++i)
95 count += hit_arr[i] - hit_arr[i - configuration_.scifi_shower_window_width];
96 if (count >= configuration_.scifi_min_hits_in_window)
103 return density(is_hit.
x) && density(is_hit.
y);
108 std::vector<double> pos_x(configuration_.scifi_n_channels_per_plane, std::nan(
""));
109 std::vector<double> pos_y(configuration_.scifi_n_channels_per_plane, std::nan(
""));
111 for (
auto &hit : hits_)
117 pos_x[hit.channel_index] = hit.x;
121 pos_y[hit.channel_index] = hit.y;
126 auto largest_cluster = [&](
const std::vector<double> &positions)
128 int n =
static_cast<int>(positions.size());
130 int best_start = -1, best_end = -1, best_size = 0;
131 int start = -1, gap_count = 0, size = 0;
134 for (
int i = 0; i < n; ++i)
136 if (!std::isnan(positions[i]))
146 if (gap_count > max_gap)
148 if (size > best_size)
151 best_end = i - gap_count;
167 if (size > best_size)
175 if (best_start == -1 || best_end == -1)
180 for (
int i = best_start; i <= best_end; ++i)
182 if (!std::isnan(positions[i]))
189 return (count > 0) ? sum / count : std::nan(
"");
192 double cluster_x = largest_cluster(pos_x);
193 double cluster_y = largest_cluster(pos_y);
194 if (!(std::isnan(cluster_x) || std::isnan(cluster_y))) {
195 return ROOT::Math::XYZPoint(cluster_x, cluster_y, hits_[0].z);
197 return ROOT::Math::XYZPoint(std::nan(
""), std::nan(
""), std::nan(
""));
224 centroid_.SetXYZ(0, 0, 0);
227 std::vector<ScifiHit> cleaned_hits = hits_;
229 cleaned_hits.erase(std::remove_if(cleaned_hits.begin(), cleaned_hits.end(),
231 { return hit.qdc <= 0; }),
233 int counts_x = std::count_if(cleaned_hits.begin(), cleaned_hits.end(), [](
auto &hit)
234 { return hit.is_x; });
235 int counts_y =
static_cast<int>(cleaned_hits.size())-counts_x;
236 if (counts_x < configuration_.scifi_min_n_hits_for_centroid && counts_y < configuration_.scifi_min_n_hits_for_centroid ) {
237 centroid_ = ROOT::Math::XYZPoint(std::nan(
""), std::nan(
""), std::nan(
""));
241 for (
auto &hit : cleaned_hits)
247 centroid_.SetX(centroid_.X() + hit.x * hit.qdc);
248 tot_qdc_x += hit.qdc;
252 centroid_.SetY(centroid_.Y() + hit.y * hit.qdc);
253 tot_qdc_y += hit.qdc;
256 centroid_.SetZ(centroid_.Z() + hit.z * hit.qdc);
259 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(
""));
260 centroid_error_ = ROOT::Math::XYZPoint(configuration_.scifi_centroid_error_x, configuration_.scifi_centroid_error_y, configuration_.scifi_centroid_error_z);
266 qdc_sum.
x = std::accumulate(hits_.begin(), hits_.end(), 0.0, [&](
double current_sum,
auto &hit)
267 { return (hit.is_x && (hit.qdc > 0 || !only_positive)) ? (current_sum + hit.qdc) : current_sum; });
268 qdc_sum.y = std::accumulate(hits_.begin(), hits_.end(), 0.0, [&](
double current_sum,
auto &hit)
269 { return (!hit.is_x && (hit.qdc > 0 || !only_positive)) ? (current_sum + hit.qdc) : current_sum; });