8#include "TClonesArray.h"
10#include "ROOT/TSeq.hxx"
14 std::vector<int> &vertical_hits)
18 std::fill(horizontal_hits.begin(), horizontal_hits.end(), 0);
19 std::fill(vertical_hits.begin(), vertical_hits.end(), 0);
23 TIter hitIterator(digiHits);
25 while (hit =
dynamic_cast<sndScifiHit *
>(hitIterator.Next())) {
29 vertical_hits[station - 1]++;
31 horizontal_hits[station - 1]++;
39 return std::accumulate(horizontal_hits.begin(), horizontal_hits.end(),
40 std::accumulate(vertical_hits.begin(), vertical_hits.end(), 0));
45 std::vector<int> horizontal_hits = std::vector<int>(5);
46 std::vector<int> vertical_hits = std::vector<int>(5);
59 std::vector<float> fractional_hits_per_station = std::vector<float>(horizontal_hits.size());
61 std::transform(horizontal_hits.begin(), horizontal_hits.end(), vertical_hits.begin(),
62 fractional_hits_per_station.begin(),
63 [&total_hits](
const auto &hor,
const auto &ver) { return ((float)hor + ver) / total_hits; });
65 return fractional_hits_per_station;
70 std::vector<int> horizontal_hits = std::vector<int>(5);
71 std::vector<int> vertical_hits = std::vector<int>(5);
84 std::vector<float> frac_sum = std::vector<float>(frac.size());
86 std::partial_sum(frac.begin(), frac.end(), frac_sum.begin());
88 std::vector<float>::iterator station =
89 std::find_if(frac_sum.begin(), frac_sum.end(), [&threshold](
const auto &f) { return f > threshold; });
91 return station - frac_sum.begin() + 1;
96 std::vector<int> horizontal_hits = std::vector<int>(5);
97 std::vector<int> vertical_hits = std::vector<int>(5);
128 if (digiHits.GetEntries() <= 0) {
129 LOG(warning) <<
"digiHits has no valid SciFi Hits and as such no maximum for the timing distribution.";
133 TH1F ScifiTiming(
"Timing",
"Scifi Timing", bins, min_x, max_x);
135 int refStation = ((
sndScifiHit *)digiHits.At(0))->GetStation();
136 bool refOrientation = ((
sndScifiHit *)digiHits.At(0))->isVertical();
137 float hitTime = -1.0;
138 float timeConversion = 1.;
140 timeConversion = 1E9 / (ShipUnit::snd_freq / ShipUnit::hertz);
143 for (
auto *p : digiHits) {
145 if (!
validateHit(hit, refStation, refOrientation)) {
148 hitTime = hit->
GetTime() * timeConversion;
149 if (hitTime < min_x || hitTime > max_x) {
152 ScifiTiming.Fill(hitTime);
156 float peakTiming = (ScifiTiming.GetMaximumBin() - 0.5) * (max_x - min_x) / bins + min_x;
162std::unique_ptr<TClonesArray>
166 auto selectedHits = std::make_unique<TClonesArray>(
"sndScifiHit");
169 for (
auto *p : digiHits) {
188 bool orientation,
int bins_x,
float min_x,
189 float max_x,
float time_lower_range,
190 float time_upper_range,
bool make_selection,
195 LOG(FATAL) <<
"bins_x in selection_parameters cannot be <1. Consider using the default value of 52 instead.";
198 LOG(warning) <<
"In selection_parameters min_x > max_x. Values will be swapped.";
199 float aux_float = min_x;
204 LOG(warning) <<
"In selection_parameters min_x < 0.0. Consider using the default value of 0.0.";
207 LOG(FATAL) <<
"In selection_parameters max_x < 0.0. Consider using the default value of 26.0.";
209 if (time_lower_range <= 0.0) {
210 LOG(FATAL) <<
"In selection_parameters time_lower_range <= 0.0. Value should always be positive, in ns.";
212 if (time_upper_range <= 0.0) {
213 LOG(FATAL) <<
"In selection_parameters time_upper_range <= 0.0. Value should always be positive, in ns.";
216 auto filteredHits = std::make_unique<TClonesArray>(
"sndScifiHit", digiHits.GetEntries());
218 float peakTiming = -1.0;
220 float timeConversion = 1.;
222 timeConversion = 1E9 / (ShipUnit::snd_freq / ShipUnit::hertz);
225 if (make_selection) {
227 auto selectedHits =
getScifiHits(digiHits, station, orientation);
229 peakTiming =
peakScifiTiming(*selectedHits, bins_x, min_x, max_x, isMC);
232 for (
auto *p : *selectedHits) {
237 if ((peakTiming - time_lower_range > hit->GetTime() * timeConversion) ||
238 (hit->GetTime() * timeConversion > peakTiming + time_upper_range)) {
250 for (
auto *p : digiHits) {
255 if ((peakTiming - time_lower_range > hit->GetTime() * timeConversion) ||
256 (hit->GetTime() * timeConversion > peakTiming + time_upper_range)) {
269std::unique_ptr<TClonesArray>
271 const std::map<std::string, float> &selection_parameters,
bool make_selection,
275 if ((selection_parameters.find(
"bins_x") == selection_parameters.end()) ||
276 (selection_parameters.find(
"min_x") == selection_parameters.end()) ||
277 (selection_parameters.find(
"max_x") == selection_parameters.end()) ||
278 (selection_parameters.find(
"time_lower_range") == selection_parameters.end())) {
279 LOG(FATAL) <<
"In order to use method 0 please provide the correct selection_parameters. Consider the default = "
280 "{{\"bins_x\", 52.}, {\"min_x\", 0.}, {\"max_x\", 26.}, {\"time_lower_range\", "
281 "1E9/(2*ShipUnit::snd_freq/ShipUnit::hertz))}, {\"time_upper_range\", "
282 "2E9/(ShipUnit::snd_freq/ShipUnit::hertz)}}";
285 float time_upper_range = -1.;
287 if (selection_parameters.find(
"time_upper_range") == selection_parameters.end()) {
288 time_upper_range = selection_parameters.at(
"time_lower_range");
290 time_upper_range = selection_parameters.at(
"time_upper_range");
293 return selectScifiHits(digiHits, station, orientation,
int(selection_parameters.at(
"bins_x")),
294 selection_parameters.at(
"min_x"), selection_parameters.at(
"max_x"),
295 selection_parameters.at(
"time_lower_range"), time_upper_range, make_selection,
299std::unique_ptr<TClonesArray>
301 const std::map<std::string, float> &selection_parameters,
int method,
302 std::string setup,
bool isMC)
304 TClonesArray supportArray(
"sndScifiHit", 0);
305 auto filteredHits = std::make_unique<TClonesArray>(
"sndScifiHit", digiHits.GetEntries());
306 int filteredHitsIndex = 0;
307 int ScifiStations = 5;
311 LOG(info) <<
"\"TI18\" setup will be used by default, please provide \"H8\" for the Testbeam setup.";
315 TIter hitIterator(&supportArray);
319 if ((selection_parameters.find(
"bins_x") == selection_parameters.end()) ||
320 (selection_parameters.find(
"min_x") == selection_parameters.end()) ||
321 (selection_parameters.find(
"max_x") == selection_parameters.end()) ||
322 (selection_parameters.find(
"time_lower_range") == selection_parameters.end())) {
323 LOG(FATAL) <<
"In order to use method 0 please provide the correct selection_parameters. Consider the default "
324 "= {{\"bins_x\", 52.}, {\"min_x\", 0.}, {\"max_x\", 26.}, {\"time_lower_range\", "
325 "1E9/(2*ShipUnit::snd_freq/ShipUnit::hertz)}, {\"time_upper_range\", "
326 "1.2E9/(ShipUnit::snd_freq/ShipUnit::hertz)}}";
330 for (
auto station : ROOT::MakeSeq(1, ScifiStations + 1)) {
331 for (
auto orientation : {
false,
true}) {
333 auto supportArray =
selectScifiHits(digiHits, station, orientation, selection_parameters,
true, isMC);
334 for (
auto *p : *supportArray) {
337 new ((*filteredHits)[filteredHitsIndex++])
sndScifiHit(*hit);
343 LOG(error) <<
"Please provide a valid time filter method from:";
344 LOG(error) <<
"(0): Events within \\mp time_lower_range time_upper_range of the peak of the time distribution "
345 "for Scifi Hits within each station and orientation";
346 LOG(FATAL) <<
"selection_parameters = {bins_x, min_x, max_x, time_lower_range, time_upper_range}.";
351std::unique_ptr<TClonesArray>
355 std::map<std::string, float> selection_parameters;
359 selection_parameters[
"bins_x"] = 52.0;
360 selection_parameters[
"min_x"] = 0.0;
361 selection_parameters[
"max_x"] = 26.0;
362 selection_parameters[
"time_lower_range"] = 1E9 / (2 * ShipUnit::snd_freq / ShipUnit::hertz);
363 selection_parameters[
"time_upper_range"] = 1.2E9 / (ShipUnit::snd_freq / ShipUnit::hertz);
366 LOG(FATAL) <<
"Please use method=0. No other methods implemented so far.";
369 return filterScifiHits(digiHits, selection_parameters, method, setup, isMC);
377 int ref_matAux = reference_SiPM % 100000;
378 int ref_mat = ref_matAux / 10000;
379 int ref_arrayAux = reference_SiPM % 10000;
380 int ref_array = ref_arrayAux / 1000;
381 int ref_channel = reference_SiPM % 1000;
382 int referenceChannel = ref_mat * 4 * 128 + ref_array * 128 + ref_channel;
384 return referenceChannel;
393 bool orientation =
false;
394 if (
int(reference_SiPM / 100000) % 10 == 1) {
397 int ref_station = reference_SiPM / 1000000;
400 for (
auto *p : digiHits) {
409 if (hitChannel > referenceChannel + radius) {
412 if (abs(referenceChannel - hitChannel) <= radius) {
417 if (min_check && (hit_density >= min_hit_density)) {
430 if (digiHits.GetEntries() <= 0) {
435 LOG(FATAL) <<
"Radius<=0. Please provide a radius bigger than 0.";
439 if (min_hit_density < 0) {
440 LOG(FATAL) <<
"Min_hit_density < 0. Please provide a min_hit_density >= 0.";
444 if (min_hit_density > 2 * radius) {
445 LOG(warning) <<
"Warning! Radius of density check does not allow for the required minimum density!";
451 std::vector<int> fired_channels{};
455 for (
auto *p : digiHits) {
463 int n_fired_channels = fired_channels.size();
465 if (n_fired_channels < min_hit_density) {
473 std::sort(fired_channels.begin(), fired_channels.end());
474 for (
int i = 0; i < n_fired_channels - min_hit_density; i++) {
476 if (fired_channels[i + min_hit_density - 1] - fired_channels[i] <= radius * 2) {
490 const std::map<std::string, float> &selection_parameters,
int method,
494 int totalScifiStations = 5;
496 totalScifiStations = 4;
498 LOG(info) <<
"\"TI18\" setup will be used by default, please provide \"H8\" for the Testbeam setup.";
503 int showerStart = totalScifiStations;
507 if ((selection_parameters.find(
"radius") == selection_parameters.end()) ||
508 (selection_parameters.find(
"min_hit_density") == selection_parameters.end())) {
510 <<
"Argument of select_parameters is incorrect. Please provide a map with the arguments \"radius\" and "
511 "\"min_hit_density\". Consider using the default values of {{\"radius\",64}, {\"min_hit_density\",36}}.";
514 for (
int scifiStation = 1; scifiStation <= totalScifiStations; scifiStation++) {
520 bool horizontalCheck =
false;
521 bool verticalCheck =
false;
522 if (selection_parameters.find(
"orientation") != selection_parameters.end()) {
523 if (
int(selection_parameters.at(
"orientation")) == 0) {
524 verticalCheck =
true;
526 if (
int(selection_parameters.at(
"orientation")) == 1) {
527 horizontalCheck =
true;
530 horizontalCheck = (
densityCheck(digiHits,
int(selection_parameters.at(
"radius")),
531 int(selection_parameters.at(
"min_hit_density")), scifiStation,
false) ||
533 verticalCheck = (
densityCheck(digiHits,
int(selection_parameters.at(
"radius")),
534 int(selection_parameters.at(
"min_hit_density")), scifiStation,
true) ||
536 if ((horizontalCheck) && (verticalCheck)) {
537 showerStart = scifiStation - 1;
550 LOG(FATAL) <<
"Please use method=0. No other methods implemented so far.";
553 std::map<std::string, float> selection_parameters = {{
"radius", 64.}, {
"min_hit_density", 36.}};
560 double sum = std::accumulate(values.begin(), values.end(), 0.0);
561 double mean = sum / values.size();
565std::pair<double, double>
569 LOG(ERROR) <<
"Error: digiHits is null in findCentreOfGravityPerStation";
571 std::vector<double> x_positions;
572 std::vector<double> y_positions;
574 for (
auto* obj : *digiHits) {
576 if (!hit || !hit->isValid()) {
579 if (hit->GetStation() != station) {
583 if (hit->isVertical()) {
584 x_positions.push_back((A.X() + B.X()) * 0.5);
587 y_positions.push_back((A.Y() + B.Y()) * 0.5);
590 if (x_positions.empty()) {
591 LOG(ERROR) <<
"Error: No hits enter.";
594 if (y_positions.empty()) {
595 LOG(ERROR) <<
"Error: No hits enter.";
598 return {meanX, meanY};
void GetSiPMPosition(Int_t SiPMChan, TVector3 &A, TVector3 &B)
Float_t GetTime(Int_t nChannel=0)