8#include "TClonesArray.h"
10#include "ROOT/TSeq.hxx"
13#include "ROOT/RRangeCast.hxx"
16 std::vector<int> &vertical_hits)
20 std::fill(horizontal_hits.begin(), horizontal_hits.end(), 0);
21 std::fill(vertical_hits.begin(), vertical_hits.end(), 0);
25 TIter hitIterator(digiHits);
27 while (hit =
dynamic_cast<sndScifiHit *
>(hitIterator.Next())) {
31 vertical_hits[station - 1]++;
33 horizontal_hits[station - 1]++;
41 return std::accumulate(horizontal_hits.begin(), horizontal_hits.end(),
42 std::accumulate(vertical_hits.begin(), vertical_hits.end(), 0));
47 std::vector<int> horizontal_hits = std::vector<int>(5);
48 std::vector<int> vertical_hits = std::vector<int>(5);
61 std::vector<float> fractional_hits_per_station = std::vector<float>(horizontal_hits.size());
63 std::transform(horizontal_hits.begin(), horizontal_hits.end(), vertical_hits.begin(),
64 fractional_hits_per_station.begin(),
65 [&total_hits](
const auto &hor,
const auto &ver) { return ((float)hor + ver) / total_hits; });
67 return fractional_hits_per_station;
72 std::vector<int> horizontal_hits = std::vector<int>(5);
73 std::vector<int> vertical_hits = std::vector<int>(5);
86 std::vector<float> frac_sum = std::vector<float>(frac.size());
88 std::partial_sum(frac.begin(), frac.end(), frac_sum.begin());
90 std::vector<float>::iterator station =
91 std::find_if(frac_sum.begin(), frac_sum.end(), [&threshold](
const auto &f) { return f > threshold; });
93 return station - frac_sum.begin() + 1;
98 std::vector<int> horizontal_hits = std::vector<int>(5);
99 std::vector<int> vertical_hits = std::vector<int>(5);
130 if (digiHits.GetEntries() <= 0) {
131 LOG(warning) <<
"digiHits has no valid SciFi Hits and as such no maximum for the timing distribution.";
135 TH1F ScifiTiming(
"Timing",
"Scifi Timing", bins, min_x, max_x);
137 Scifi *ScifiDet =
dynamic_cast<Scifi*
> (gROOT->GetListOfGlobals()->FindObject(
"Scifi") );
138 auto* hit =
static_cast<sndScifiHit*
>(digiHits[0]);
140 bool refOrientation = hit->isVertical();
141 float hitTime = -1.0;
142 float timeConversion = 1.;
144 timeConversion = 1E9 / (ShipUnit::snd_freq / ShipUnit::hertz);
147 for (
auto *p : digiHits) {
149 if (!
validateHit(hit, refStation, refOrientation)) {
152 hitTime = hit->
GetTime() * timeConversion;
154 int id_hit = hit ->GetDetectorID();
157 if (hitTime < min_x || hitTime > max_x) {
160 ScifiTiming.Fill(hitTime);
164 float peakTiming = (ScifiTiming.GetMaximumBin() - 0.5) * (max_x - min_x) / bins + min_x;
170std::unique_ptr<TClonesArray>
174 auto selectedHits = std::make_unique<TClonesArray>(
"sndScifiHit");
177 for (
auto *p : digiHits) {
196 bool orientation,
int bins_x,
float min_x,
197 float max_x,
float time_lower_range,
198 float time_upper_range,
bool make_selection,
203 LOG(FATAL) <<
"bins_x in selection_parameters cannot be <1. Consider using the default value of 52 instead.";
206 LOG(warning) <<
"In selection_parameters min_x > max_x. Values will be swapped.";
207 float aux_float = min_x;
212 LOG(warning) <<
"In selection_parameters min_x < 0.0. Consider using the default value of 0.0.";
215 LOG(FATAL) <<
"In selection_parameters max_x < 0.0. Consider using the default value of 26.0.";
217 if (time_lower_range <= 0.0) {
218 LOG(FATAL) <<
"In selection_parameters time_lower_range <= 0.0. Value should always be positive, in ns.";
220 if (time_upper_range <= 0.0) {
221 LOG(FATAL) <<
"In selection_parameters time_upper_range <= 0.0. Value should always be positive, in ns.";
224 auto filteredHits = std::make_unique<TClonesArray>(
"sndScifiHit", digiHits.GetEntries());
226 float peakTiming = -1.0;
228 float timeConversion = 1.;
230 timeConversion = 1E9 / (ShipUnit::snd_freq / ShipUnit::hertz);
233 if (make_selection) {
235 auto selectedHits =
getScifiHits(digiHits, station, orientation);
237 peakTiming =
peakScifiTiming(*selectedHits, bins_x, min_x, max_x, isMC);
240 for (
auto *p : *selectedHits) {
245 if ((peakTiming - time_lower_range > hit->GetTime() * timeConversion) ||
246 (hit->GetTime() * timeConversion > peakTiming + time_upper_range)) {
258 for (
auto *p : digiHits) {
263 if ((peakTiming - time_lower_range > hit->GetTime() * timeConversion) ||
264 (hit->GetTime() * timeConversion > peakTiming + time_upper_range)) {
277std::unique_ptr<TClonesArray>
279 const std::map<std::string, float> &selection_parameters,
bool make_selection,
283 if ((selection_parameters.find(
"bins_x") == selection_parameters.end()) ||
284 (selection_parameters.find(
"min_x") == selection_parameters.end()) ||
285 (selection_parameters.find(
"max_x") == selection_parameters.end()) ||
286 (selection_parameters.find(
"time_lower_range") == selection_parameters.end())) {
287 LOG(FATAL) <<
"In order to use method 0 please provide the correct selection_parameters. Consider the default = "
288 "{{\"bins_x\", 52.}, {\"min_x\", 0.}, {\"max_x\", 26.}, {\"time_lower_range\", "
289 "1E9/(2*ShipUnit::snd_freq/ShipUnit::hertz))}, {\"time_upper_range\", "
290 "2E9/(ShipUnit::snd_freq/ShipUnit::hertz)}}";
293 float time_upper_range = -1.;
295 if (selection_parameters.find(
"time_upper_range") == selection_parameters.end()) {
296 time_upper_range = selection_parameters.at(
"time_lower_range");
298 time_upper_range = selection_parameters.at(
"time_upper_range");
301 return selectScifiHits(digiHits, station, orientation,
int(selection_parameters.at(
"bins_x")),
302 selection_parameters.at(
"min_x"), selection_parameters.at(
"max_x"),
303 selection_parameters.at(
"time_lower_range"), time_upper_range, make_selection,
307std::unique_ptr<TClonesArray>
309 const std::map<std::string, float> &selection_parameters,
int method,
310 std::string setup,
bool isMC)
312 TClonesArray supportArray(
"sndScifiHit", 0);
313 auto filteredHits = std::make_unique<TClonesArray>(
"sndScifiHit", digiHits.GetEntries());
314 int filteredHitsIndex = 0;
315 int ScifiStations = 5;
319 LOG(info) <<
"\"TI18\" setup will be used by default, please provide \"H8\" for the Testbeam setup.";
323 TIter hitIterator(&supportArray);
327 if ((selection_parameters.find(
"bins_x") == selection_parameters.end()) ||
328 (selection_parameters.find(
"min_x") == selection_parameters.end()) ||
329 (selection_parameters.find(
"max_x") == selection_parameters.end()) ||
330 (selection_parameters.find(
"time_lower_range") == selection_parameters.end())) {
331 LOG(FATAL) <<
"In order to use method 0 please provide the correct selection_parameters. Consider the default "
332 "= {{\"bins_x\", 52.}, {\"min_x\", 0.}, {\"max_x\", 26.}, {\"time_lower_range\", "
333 "1E9/(2*ShipUnit::snd_freq/ShipUnit::hertz)}, {\"time_upper_range\", "
334 "1.2E9/(ShipUnit::snd_freq/ShipUnit::hertz)}}";
338 for (
auto station : ROOT::MakeSeq(1, ScifiStations + 1)) {
339 for (
auto orientation : {
false,
true}) {
341 auto supportArray =
selectScifiHits(digiHits, station, orientation, selection_parameters,
true, isMC);
342 for (
auto *p : *supportArray) {
345 new ((*filteredHits)[filteredHitsIndex++])
sndScifiHit(*hit);
351 LOG(error) <<
"Please provide a valid time filter method from:";
352 LOG(error) <<
"(0): Events within \\mp time_lower_range time_upper_range of the peak of the time distribution "
353 "for Scifi Hits within each station and orientation";
354 LOG(FATAL) <<
"selection_parameters = {bins_x, min_x, max_x, time_lower_range, time_upper_range}.";
359std::unique_ptr<TClonesArray>
363 std::map<std::string, float> selection_parameters;
367 selection_parameters[
"bins_x"] = 52.0;
368 selection_parameters[
"min_x"] = 0.0;
369 selection_parameters[
"max_x"] = 26.0;
370 selection_parameters[
"time_lower_range"] = 1E9 / (2 * ShipUnit::snd_freq / ShipUnit::hertz);
371 selection_parameters[
"time_upper_range"] = 1.2E9 / (ShipUnit::snd_freq / ShipUnit::hertz);
374 LOG(FATAL) <<
"Please use method=0. No other methods implemented so far.";
377 return filterScifiHits(digiHits, selection_parameters, method, setup, isMC);
385 int ref_matAux = reference_SiPM % 100000;
386 int ref_mat = ref_matAux / 10000;
387 int ref_arrayAux = reference_SiPM % 10000;
388 int ref_array = ref_arrayAux / 1000;
389 int ref_channel = reference_SiPM % 1000;
390 int referenceChannel = ref_mat * 4 * 128 + ref_array * 128 + ref_channel;
392 return referenceChannel;
401 bool orientation =
false;
402 if (
int(reference_SiPM / 100000) % 10 == 1) {
405 int ref_station = reference_SiPM / 1000000;
408 for (
auto *p : digiHits) {
417 if (hitChannel > referenceChannel + radius) {
420 if (abs(referenceChannel - hitChannel) <= radius) {
425 if (min_check && (hit_density >= min_hit_density)) {
438 if (digiHits.GetEntries() <= 0) {
443 LOG(FATAL) <<
"Radius<=0. Please provide a radius bigger than 0.";
447 if (min_hit_density < 0) {
448 LOG(FATAL) <<
"Min_hit_density < 0. Please provide a min_hit_density >= 0.";
452 if (min_hit_density > 2 * radius) {
453 LOG(warning) <<
"Warning! Radius of density check does not allow for the required minimum density!";
459 std::vector<int> fired_channels{};
463 for (
auto *p : digiHits) {
471 int n_fired_channels = fired_channels.size();
473 if (n_fired_channels < min_hit_density) {
481 std::sort(fired_channels.begin(), fired_channels.end());
482 for (
int i = 0; i < n_fired_channels - min_hit_density; i++) {
484 if (fired_channels[i + min_hit_density - 1] - fired_channels[i] <= radius * 2) {
498 const std::map<std::string, float> &selection_parameters,
int method,
502 int totalScifiStations = 5;
504 totalScifiStations = 4;
506 LOG(info) <<
"\"TI18\" setup will be used by default, please provide \"H8\" for the Testbeam setup.";
511 int showerStart = totalScifiStations;
515 if ((selection_parameters.find(
"radius") == selection_parameters.end()) ||
516 (selection_parameters.find(
"min_hit_density") == selection_parameters.end())) {
518 <<
"Argument of select_parameters is incorrect. Please provide a map with the arguments \"radius\" and "
519 "\"min_hit_density\". Consider using the default values of {{\"radius\",64}, {\"min_hit_density\",36}}.";
522 for (
int scifiStation = 1; scifiStation <= totalScifiStations; scifiStation++) {
528 bool horizontalCheck =
false;
529 bool verticalCheck =
false;
530 if (selection_parameters.find(
"orientation") != selection_parameters.end()) {
531 if (
int(selection_parameters.at(
"orientation")) == 0) {
532 verticalCheck =
true;
534 if (
int(selection_parameters.at(
"orientation")) == 1) {
535 horizontalCheck =
true;
538 horizontalCheck = (
densityCheck(digiHits,
int(selection_parameters.at(
"radius")),
539 int(selection_parameters.at(
"min_hit_density")), scifiStation,
false) ||
541 verticalCheck = (
densityCheck(digiHits,
int(selection_parameters.at(
"radius")),
542 int(selection_parameters.at(
"min_hit_density")), scifiStation,
true) ||
544 if ((horizontalCheck) && (verticalCheck)) {
545 showerStart = scifiStation - 1;
558 LOG(FATAL) <<
"Please use method=0. No other methods implemented so far.";
561 std::map<std::string, float> selection_parameters = {{
"radius", 64.}, {
"min_hit_density", 36.}};
568 double sum = std::accumulate(values.begin(), values.end(), 0.0);
569 double mean = sum / values.size();
573std::pair<double, double>
577 LOG(ERROR) <<
"Error: digiHits is null in findCentreOfGravityPerStation";
582 if (x_positions.empty()) {
583 LOG(ERROR) <<
"Error: No hits enter.";
586 if (y_positions.empty()) {
587 LOG(ERROR) <<
"Error: No hits enter.";
590 return {meanX, meanY};
605 LOG(ERROR) <<
"Error: digiHits is null";
607 std::vector<double> x_positions;
608 std::vector<double> y_positions;
611 for (
auto* hit : ROOT::RRangeCast<sndScifiHit*, false, decltype(*digiHits)>(*digiHits)) {
612 if (!hit || !hit->isValid()) {
615 if (hit->GetStation() != station) {
619 if (hit->isVertical()) {
620 x_positions.push_back((A.X() + B.X()) * 0.5);
623 y_positions.push_back((A.Y() + B.Y()) * 0.5);
626 if (x_positions.empty()) {
627 LOG(ERROR) <<
"Error: No hits enter.";
629 if (y_positions.empty()) {
630 LOG(ERROR) <<
"Error: No hits enter.";
632 return {x_positions, y_positions};
648 if (hit_position.empty()) {
649 LOG(INFO) <<
"Warning: The hit position vector is empty." << std::endl;
653 int n_hits = hit_position.size();
655 std::vector<double> weights;
658 std::sort(hit_position.begin(), hit_position.end());
666 for (
int i = 0; i < n_hits; i++) {
667 double specific_hit = hit_position[i];
671 while (right_ptr < n_hits && hit_position[right_ptr] <= specific_hit + width) {
677 while (left_ptr < n_hits && hit_position[left_ptr] < specific_hit - width) {
684 double count_in_window = right_ptr - left_ptr;
691 double neighbour_no_of_hits = count_in_window - 1;
694 if (neighbour_no_of_hits < 0) {
695 neighbour_no_of_hits = 0;
698 weights.push_back(neighbour_no_of_hits);
702 double sum_weights = std::accumulate(weights.begin(), weights.end(), 0.0);
717 std::vector<double> hit_position_x = hit_position_vec.first;
718 std::vector<double> hit_position_y = hit_position_vec.second;
720 if (hit_position_x.size()==0 && hit_position_y.size()==0) {
721 LOG(INFO)<<
"Warning: The hit position vector is empty." << std::endl;
728 return {sum_weights_x, sum_weights_y};
void GetSiPMPosition(Int_t SiPMChan, TVector3 &A, TVector3 &B)
Double_t GetCorrectedTime(Int_t fDetectorID, Double_t rawTime, Double_t L)
Float_t GetTime(Int_t nChannel=0)