SND@LHC Software
Loading...
Searching...
No Matches
sndSciFiTools.cxx
Go to the documentation of this file.
1#include "sndSciFiTools.h"
2
3#include <numeric>
4#include <algorithm>
5
6#include "TH1F.h"
7#include "FairLogger.h"
8#include "TClonesArray.h"
9#include "sndScifiHit.h"
10#include "ROOT/TSeq.hxx"
11#include "Scifi.h"
12
13void snd::analysis_tools::getSciFiHitsPerStation(const TClonesArray *digiHits, std::vector<int> &horizontal_hits,
14 std::vector<int> &vertical_hits)
15{
16
17 // Clear hits per plane vectors
18 std::fill(horizontal_hits.begin(), horizontal_hits.end(), 0);
19 std::fill(vertical_hits.begin(), vertical_hits.end(), 0);
20
21 // Add valid hits to hits per plane vectors
22 sndScifiHit *hit;
23 TIter hitIterator(digiHits);
24
25 while (hit = dynamic_cast<sndScifiHit *>(hitIterator.Next())) {
26 if (hit->isValid()) {
27 int station = hit->GetStation();
28 if (hit->isVertical()) {
29 vertical_hits[station - 1]++;
30 } else {
31 horizontal_hits[station - 1]++;
32 }
33 }
34 }
35}
36
37int snd::analysis_tools::getTotalSciFiHits(std::vector<int> &horizontal_hits, std::vector<int> &vertical_hits)
38{
39 return std::accumulate(horizontal_hits.begin(), horizontal_hits.end(),
40 std::accumulate(vertical_hits.begin(), vertical_hits.end(), 0));
41}
42
43int snd::analysis_tools::getTotalSciFiHits(const TClonesArray *digiHits)
44{
45 std::vector<int> horizontal_hits = std::vector<int>(5);
46 std::vector<int> vertical_hits = std::vector<int>(5);
47
48 getSciFiHitsPerStation(digiHits, horizontal_hits, vertical_hits);
49
50 return getTotalSciFiHits(horizontal_hits, vertical_hits);
51}
52
53std::vector<float>
54snd::analysis_tools::getFractionalHitsPerScifiPlane(std::vector<int> &horizontal_hits, std::vector<int> &vertical_hits)
55{
56
57 int total_hits = getTotalSciFiHits(horizontal_hits, vertical_hits);
58
59 std::vector<float> fractional_hits_per_station = std::vector<float>(horizontal_hits.size());
60
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; });
64
65 return fractional_hits_per_station;
66}
67
68std::vector<float> snd::analysis_tools::getFractionalHitsPerScifiPlane(const TClonesArray *digiHits)
69{
70 std::vector<int> horizontal_hits = std::vector<int>(5);
71 std::vector<int> vertical_hits = std::vector<int>(5);
72
73 getSciFiHitsPerStation(digiHits, horizontal_hits, vertical_hits);
74
75 return getFractionalHitsPerScifiPlane(horizontal_hits, vertical_hits);
76}
77
78int snd::analysis_tools::findScifiStation(std::vector<int> &horizontal_hits, std::vector<int> &vertical_hits,
79 float threshold)
80{
81
82 std::vector<float> frac = getFractionalHitsPerScifiPlane(horizontal_hits, vertical_hits);
83
84 std::vector<float> frac_sum = std::vector<float>(frac.size());
85
86 std::partial_sum(frac.begin(), frac.end(), frac_sum.begin());
87
88 std::vector<float>::iterator station =
89 std::find_if(frac_sum.begin(), frac_sum.end(), [&threshold](const auto &f) { return f > threshold; });
90
91 return station - frac_sum.begin() + 1;
92}
93
94int snd::analysis_tools::findScifiStation(const TClonesArray *digiHits, float threshold)
95{
96 std::vector<int> horizontal_hits = std::vector<int>(5);
97 std::vector<int> vertical_hits = std::vector<int>(5);
98
99 getSciFiHitsPerStation(digiHits, horizontal_hits, vertical_hits);
100
101 return findScifiStation(horizontal_hits, vertical_hits, threshold);
102}
103
104// Auxiliar function to check whether hits are valid or not and whether they are within the same
105// station and orientation as the reference hit we are comparing it to
106bool validateHit(sndScifiHit *aHit, int ref_station, bool ref_orientation)
107{
108
109 if (!(aHit->isValid())) {
110 return false;
111 }
112 if (aHit->GetStation() != ref_station) {
113 return false;
114 }
115 if (aHit->isVertical() != ref_orientation) {
116 return false;
117 }
118
119 return true;
120}
121
122// Getting the max for the ScifiHits timing distribution in order to select hits within \pm 3ns
123// min_x and max_x should be given in ns
124// The code automatically filters for hits within the same station and orientation as the first hit
125float snd::analysis_tools::peakScifiTiming(const TClonesArray &digiHits, int bins, float min_x, float max_x, bool isMC)
126{
127
128 if (digiHits.GetEntries() <= 0) {
129 LOG(warning) << "digiHits has no valid SciFi Hits and as such no maximum for the timing distribution.";
130 return -1.;
131 }
132
133 TH1F ScifiTiming("Timing", "Scifi Timing", bins, min_x, max_x);
134
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.;
139 if (!isMC) {
140 timeConversion = 1E9 / (ShipUnit::snd_freq / ShipUnit::hertz);
141 }
142
143 for (auto *p : digiHits) {
144 auto *hit = dynamic_cast<sndScifiHit *>(p);
145 if (!validateHit(hit, refStation, refOrientation)) {
146 continue;
147 }
148 hitTime = hit->GetTime() * timeConversion;
149 if (hitTime < min_x || hitTime > max_x) {
150 continue;
151 }
152 ScifiTiming.Fill(hitTime);
153 hitTime = -1.0;
154 }
155
156 float peakTiming = (ScifiTiming.GetMaximumBin() - 0.5) * (max_x - min_x) / bins + min_x;
157
158 return peakTiming;
159}
160
161// Getting all the Scifi hits for a specific station and orientation
162std::unique_ptr<TClonesArray>
163snd::analysis_tools::getScifiHits(const TClonesArray &digiHits, int station, bool orientation)
164{
165
166 auto selectedHits = std::make_unique<TClonesArray>("sndScifiHit");
167
168 int i = 0;
169 for (auto *p : digiHits) {
170 auto *hit = dynamic_cast<sndScifiHit *>(p);
171 if (!validateHit(hit, station, orientation)) {
172 continue;
173 }
174 new ((*selectedHits)[i++]) sndScifiHit(*hit);
175 }
176
177 return selectedHits;
178}
179
180// Getting all the Scifi hits for a specific station and orientation, taking into account a filter
181// of \pm range around the peak of the timing distribution for said Scifi plane
182// selection_parameters is the number of bins for the histogram, min_x, max_x and time window for
183// the Scifi hits in ns
184// make_selection == true allows you to first perform a selection of the relevant hits, and only
185// afterwards apply the filter. This is recomended for when the selection has not been made
186// previously
187std::unique_ptr<TClonesArray> snd::analysis_tools::selectScifiHits(const TClonesArray &digiHits, int station,
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,
191 bool isMC)
192{
193
194 if (bins_x < 1) {
195 LOG(FATAL) << "bins_x in selection_parameters cannot be <1. Consider using the default value of 52 instead.";
196 }
197 if (min_x > max_x) {
198 LOG(warning) << "In selection_parameters min_x > max_x. Values will be swapped.";
199 float aux_float = min_x;
200 min_x = max_x;
201 max_x = aux_float;
202 }
203 if (min_x < 0.0) {
204 LOG(warning) << "In selection_parameters min_x < 0.0. Consider using the default value of 0.0.";
205 }
206 if (max_x < 0.0) {
207 LOG(FATAL) << "In selection_parameters max_x < 0.0. Consider using the default value of 26.0.";
208 }
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.";
211 }
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.";
214 }
215
216 auto filteredHits = std::make_unique<TClonesArray>("sndScifiHit", digiHits.GetEntries());
217
218 float peakTiming = -1.0;
219
220 float timeConversion = 1.;
221 if (!isMC) {
222 timeConversion = 1E9 / (ShipUnit::snd_freq / ShipUnit::hertz);
223 }
224
225 if (make_selection) {
226
227 auto selectedHits = getScifiHits(digiHits, station, orientation);
228
229 peakTiming = peakScifiTiming(*selectedHits, bins_x, min_x, max_x, isMC);
230
231 int i = 0;
232 for (auto *p : *selectedHits) {
233 auto *hit = dynamic_cast<sndScifiHit *>(p);
234 if (!validateHit(hit, station, orientation)) {
235 continue;
236 }
237 if ((peakTiming - time_lower_range > hit->GetTime() * timeConversion) ||
238 (hit->GetTime() * timeConversion > peakTiming + time_upper_range)) {
239 continue;
240 }
241 new ((*filteredHits)[i++]) sndScifiHit(*hit);
242 }
243
244 } else {
245 // Does not create selectedHits and just uses digiHits (not unique_ptr)
246
247 peakTiming = peakScifiTiming(digiHits, bins_x, min_x, max_x, isMC);
248
249 int i = 0;
250 for (auto *p : digiHits) {
251 auto *hit = dynamic_cast<sndScifiHit *>(p);
252 if (!validateHit(hit, station, orientation)) {
253 continue;
254 }
255 if ((peakTiming - time_lower_range > hit->GetTime() * timeConversion) ||
256 (hit->GetTime() * timeConversion > peakTiming + time_upper_range)) {
257 continue;
258 }
259 new ((*filteredHits)[i++]) sndScifiHit(*hit);
260 }
261 }
262
263 return filteredHits;
264}
265
266// Takes a map with 4 or 5 arguments as an input {"bins_x", "min_x", "max_x", "time_lower_range",
267// "time_upper_range"}
268// User may foreit "time_upper_range" and function will assume a symmetric time interval
269std::unique_ptr<TClonesArray>
270snd::analysis_tools::selectScifiHits(const TClonesArray &digiHits, int station, bool orientation,
271 const std::map<std::string, float> &selection_parameters, bool make_selection,
272 bool isMC)
273{
274
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)}}";
283 }
284
285 float time_upper_range = -1.;
286
287 if (selection_parameters.find("time_upper_range") == selection_parameters.end()) {
288 time_upper_range = selection_parameters.at("time_lower_range");
289 } else {
290 time_upper_range = selection_parameters.at("time_upper_range");
291 }
292
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,
296 isMC);
297}
298
299std::unique_ptr<TClonesArray>
300snd::analysis_tools::filterScifiHits(const TClonesArray &digiHits,
301 const std::map<std::string, float> &selection_parameters, int method,
302 std::string setup, bool isMC)
303{
304 TClonesArray supportArray("sndScifiHit", 0);
305 auto filteredHits = std::make_unique<TClonesArray>("sndScifiHit", digiHits.GetEntries());
306 int filteredHitsIndex = 0;
307 int ScifiStations = 5;
308 if (setup == "H8") {
309 ScifiStations = 4;
310 } else {
311 LOG(info) << "\"TI18\" setup will be used by default, please provide \"H8\" for the Testbeam setup.";
312 }
313
314 sndScifiHit *hit;
315 TIter hitIterator(&supportArray);
316
317 if (method == 0) {
318
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)}}";
327 }
328
329 // This is overwriting the previous arrays with the newest one
330 for (auto station : ROOT::MakeSeq(1, ScifiStations + 1)) {
331 for (auto orientation : {false, true}) {
332
333 auto supportArray = selectScifiHits(digiHits, station, orientation, selection_parameters, true, isMC);
334 for (auto *p : *supportArray) {
335 auto *hit = dynamic_cast<sndScifiHit *>(p);
336 if (hit->isValid()) {
337 new ((*filteredHits)[filteredHitsIndex++]) sndScifiHit(*hit);
338 }
339 }
340 }
341 }
342 } else {
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}.";
347 }
348 return filteredHits;
349}
350
351std::unique_ptr<TClonesArray>
352snd::analysis_tools::filterScifiHits(const TClonesArray &digiHits, int method, std::string setup, bool isMC)
353{
354
355 std::map<std::string, float> selection_parameters;
356
357 if (method == 0) {
358
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);
364
365 } else {
366 LOG(FATAL) << "Please use method=0. No other methods implemented so far.";
367 }
368
369 return filterScifiHits(digiHits, selection_parameters, method, setup, isMC);
370}
371
372// Caculate the number of the SiPM channel in the whole station by inputing its number in the
373// sndScifiHit->GetChannelID() format
375{
376
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;
383
384 return referenceChannel;
385}
386
387int snd::analysis_tools::densityScifi(int reference_SiPM, const TClonesArray &digiHits, int radius, int min_hit_density,
388 bool min_check)
389{
390
391 int hit_density = 0;
392
393 bool orientation = false;
394 if (int(reference_SiPM / 100000) % 10 == 1) {
395 orientation = true;
396 }
397 int ref_station = reference_SiPM / 1000000;
398 int referenceChannel = calculateSiPMNumber(reference_SiPM);
399
400 for (auto *p : digiHits) {
401 auto *hit = dynamic_cast<sndScifiHit *>(p);
402 if (!validateHit(hit, ref_station, orientation)) {
403 continue;
404 }
405 int hitChannel = calculateSiPMNumber(hit->GetChannelID());
406 if (radius == -1) {
407 hit_density++;
408 } else {
409 if (hitChannel > referenceChannel + radius) {
410 break;
411 }
412 if (abs(referenceChannel - hitChannel) <= radius) {
413 hit_density++;
414 }
415 }
416
417 if (min_check && (hit_density >= min_hit_density)) {
418 break;
419 }
420 }
421
422 return hit_density;
423}
424
425// Perform a density check for a specific station and orientation (dafault is horizontal)
426bool snd::analysis_tools::densityCheck(const TClonesArray &digiHits, int radius, int min_hit_density, int station,
427 bool orientation)
428{
429
430 if (digiHits.GetEntries() <= 0) {
431 return false;
432 }
433
434 if (radius <= 0) {
435 LOG(FATAL) << "Radius<=0. Please provide a radius bigger than 0.";
436 return false;
437 }
438
439 if (min_hit_density < 0) {
440 LOG(FATAL) << "Min_hit_density < 0. Please provide a min_hit_density >= 0.";
441 return false;
442 }
443
444 if (min_hit_density > 2 * radius) {
445 LOG(warning) << "Warning! Radius of density check does not allow for the required minimum density!";
446 return false;
447 }
448
449 // Creating a vector that stores the fired SiPM channels (should already be ordered but we sort
450 // afterwards to make sure)
451 std::vector<int> fired_channels{};
452
453 // Only fill the set with hits from the same station and with the same orientation as given in
454 // argument (false==horizontal and true==vertical)
455 for (auto *p : digiHits) {
456 auto *hit = dynamic_cast<sndScifiHit *>(p);
457 if (!validateHit(hit, station, orientation)) {
458 continue;
459 }
460 fired_channels.push_back(calculateSiPMNumber(hit->GetChannelID()));
461 }
462
463 int n_fired_channels = fired_channels.size();
464
465 if (n_fired_channels < min_hit_density) {
466 return false;
467 }
468
469 // Looping over the ordered hits, checking whether within an interval of "min_hit_density" the
470 // difference between the channel IDs is smaller than "radius". If so, then we have the required
471 // density. Else, we check the next combination until we meet the criterion, or end the loop,
472 // returning false
473 std::sort(fired_channels.begin(), fired_channels.end());
474 for (int i = 0; i < n_fired_channels - min_hit_density; i++) {
475
476 if (fired_channels[i + min_hit_density - 1] - fired_channels[i] <= radius * 2) {
477 return true;
478 }
479 }
480 return false;
481}
482
483// Retrieve the target block where the shower starts
484// Method 0 checks for a minimum number of hits in a specific range (2*radius) in a station to
485// consider that a shower as started before said station. User must provide a map
486//"selection_parameters" with at least 2 elements "radius" and "min_hit_density"
487// In order to only require 1 orientation to pass the criterion, "selection_parameters" may also
488// include "orientation", which can be 0. and 1. for the horizontal and vertical orientations respec.
489int snd::analysis_tools::showerInteractionWall(const TClonesArray &digiHits,
490 const std::map<std::string, float> &selection_parameters, int method,
491 std::string setup)
492{
493
494 int totalScifiStations = 5;
495 if (setup == "H8") {
496 totalScifiStations = 4;
497 } else {
498 LOG(info) << "\"TI18\" setup will be used by default, please provide \"H8\" for the Testbeam setup.";
499 }
500
501 // There is always 1 more Scifi Station than a target block. As such, showerStart == totalScifiStations
502 // means that the shower did not start developing in the target, before the last Scifi Station
503 int showerStart = totalScifiStations;
504
505 if (method == 0) {
506
507 if ((selection_parameters.find("radius") == selection_parameters.end()) ||
508 (selection_parameters.find("min_hit_density") == selection_parameters.end())) {
509 LOG(FATAL)
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}}.";
512 }
513
514 for (int scifiStation = 1; scifiStation <= totalScifiStations; scifiStation++) {
515
516 // For each ScifiStation we check whether we see clusters with the desired parameters
517 // By default, we require passing the check on both the horizontal and vertical mats
518 // In case selection_parameters["orientation"] was provided, we set the NOT CHOSEN orientation
519 // as true by default, so as to only need to pass the chosen orientation check
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;
525 }
526 if (int(selection_parameters.at("orientation")) == 1) {
527 horizontalCheck = true;
528 }
529 }
530 horizontalCheck = (densityCheck(digiHits, int(selection_parameters.at("radius")),
531 int(selection_parameters.at("min_hit_density")), scifiStation, false) ||
532 horizontalCheck);
533 verticalCheck = (densityCheck(digiHits, int(selection_parameters.at("radius")),
534 int(selection_parameters.at("min_hit_density")), scifiStation, true) ||
535 verticalCheck);
536 if ((horizontalCheck) && (verticalCheck)) {
537 showerStart = scifiStation - 1;
538 return showerStart;
539 }
540 }
541 }
542
543 return showerStart;
544}
545
546int snd::analysis_tools::showerInteractionWall(const TClonesArray &digiHits, int method, std::string setup)
547{
548
549 if (method != 0) {
550 LOG(FATAL) << "Please use method=0. No other methods implemented so far.";
551 }
552
553 std::map<std::string, float> selection_parameters = {{"radius", 64.}, {"min_hit_density", 36.}};
554
555 return showerInteractionWall(digiHits, selection_parameters, method, setup);
556}
557
558double computeMean(const std::vector<double>& values)
559{
560 double sum = std::accumulate(values.begin(), values.end(), 0.0);
561 double mean = sum / values.size();
562 return mean;
563}
564
565std::pair<double, double>
566snd::analysis_tools::findCentreOfGravityPerStation(const TClonesArray* digiHits, int station, Scifi* ScifiDet)
567{
568 if (!digiHits) {
569 LOG(ERROR) << "Error: digiHits is null in findCentreOfGravityPerStation";
570 }
571 std::vector<double> x_positions;
572 std::vector<double> y_positions;
573 TVector3 A, B;
574 for (auto* obj : *digiHits) {
575 auto* hit = dynamic_cast<sndScifiHit*>(obj);
576 if (!hit || !hit->isValid()) {
577 continue;
578 }
579 if (hit->GetStation() != station) {
580 continue;
581 }
582 ScifiDet->GetSiPMPosition(hit->GetDetectorID(), A, B);
583 if (hit->isVertical()) {
584 x_positions.push_back((A.X() + B.X()) * 0.5);
585 }
586 else {
587 y_positions.push_back((A.Y() + B.Y()) * 0.5);
588 }
589 }
590 if (x_positions.empty()) {
591 LOG(ERROR) << "Error: No hits enter.";
592 }
593 double meanX = computeMean(x_positions);
594 if (y_positions.empty()) {
595 LOG(ERROR) << "Error: No hits enter.";
596 }
597 double meanY = computeMean(y_positions);
598 return {meanX, meanY};
599}
Definition Scifi.h:20
void GetSiPMPosition(Int_t SiPMChan, TVector3 &A, TVector3 &B)
Definition Scifi.cxx:727
Float_t GetTime(Int_t nChannel=0)
Definition SndlhcHit.cxx:32
Int_t GetStation()
Definition sndScifiHit.h:31
bool isValid() const
Definition sndScifiHit.h:30
bool isVertical()
Definition sndScifiHit.h:32
int calculateSiPMNumber(int reference_SiPM)
std::unique_ptr< TClonesArray > selectScifiHits(const TClonesArray &digiHits, int station, bool orientation, int bins_x=52, float min_x=0.0, float max_x=26.0, float time_lower_range=1E9/(2 *ShipUnit::snd_freq), float time_upper_range=1.2E9/(ShipUnit::snd_freq/ShipUnit::hertz), bool make_selection=true, bool isMC=false)
int findScifiStation(std::vector< int > &horizontal_hits, std::vector< int > &vertical_hits, float threshold)
float peakScifiTiming(const TClonesArray &digiHits, int bins, float min_x, float max_x, bool isMC=false)
int showerInteractionWall(const TClonesArray &digiHits, const std::map< std::string, float > &selection_parameters, int method=0, std::string setup="TI18")
void getSciFiHitsPerStation(const TClonesArray *digiHits, std::vector< int > &horizontal_hits, std::vector< int > &vertical_hits)
std::unique_ptr< TClonesArray > filterScifiHits(const TClonesArray &digiHits, const std::map< std::string, float > &selection_parameters, int method=0, std::string setup="TI18", bool isMC=false)
std::unique_ptr< TClonesArray > getScifiHits(const TClonesArray &digiHits, int station, bool orientation)
int densityScifi(int reference_SiPM, const TClonesArray &digiHits, int radius, int min_hit_density, bool min_check)
std::pair< double, double > findCentreOfGravityPerStation(const TClonesArray *digiHits, int station, Scifi *ScifiDet)
bool densityCheck(const TClonesArray &digiHits, int radius=64, int min_hit_density=36, int station=1, bool orientation=false)
std::vector< float > getFractionalHitsPerScifiPlane(std::vector< int > &horizontal_hits, std::vector< int > &vertical_hits)
int getTotalSciFiHits(std::vector< int > &horizontal_hits, std::vector< int > &vertical_hits)
bool validateHit(sndScifiHit *aHit, int ref_station, bool ref_orientation)
double computeMean(const std::vector< double > &values)