3 #include <fwk/CentralConfig.h>
4 #include <fwk/RunController.h>
6 #include <det/Detector.h>
8 #include <sdet/SDetector.h>
9 #include <sdet/Station.h>
11 #include <evt/Event.h>
12 #include <evt/ShowerRecData.h>
13 #include <evt/ShowerSRecData.h>
15 #include <sevt/SEvent.h>
16 #include <sevt/Header.h>
17 #include <sevt/EventTrigger.h>
18 #include <sevt/Station.h>
19 #include <sevt/StationTriggerData.h>
20 #include <sevt/StationSimData.h>
21 #include <sevt/StationRecData.h>
23 #include <sevt/PMTRecData.h>
24 #include <sevt/PMTCalibData.h>
25 #include <sevt/IsLightning.h>
27 #include <utl/Vector.h>
28 #include <utl/AxialVector.h>
29 #include <utl/GeometryUtilities.h>
30 #include <utl/PhysicalConstants.h>
31 #include <utl/ErrorLogger.h>
32 #include <utl/String.h>
33 #include <utl/Reader.h>
34 #include <utl/TabularStream.h>
38 #include <boost/range/iterator_range.hpp>
47 using namespace SdEventSelectorOG;
48 using boost::make_iterator_range;
53 namespace SdEventSelectorOG {
73 template<
typename Iterator>
95 return (r[0] < x && x < r[1]);
107 Chi2(
int& ,
double*
const ,
double& value,
108 double*
const par,
const int )
110 const double& phi = par[0];
112 const double u = cos(phi);
113 const double v = sin(phi);
128 auto& shRec =
event.GetRecShower();
129 if (!shRec.HasSRecShower())
130 shRec.MakeSRecShower();
131 return shRec.GetSRecShower();
136 MakeInfo(
const vector<int>& ids,
const string& message)
153 fLightCompatibilityTolerance);
161 vector<int> ssElectronicsType;
162 vector<int> ssOffGrid;
164 vector<int> ssLightning;
165 vector<int> ssNoRecData;
170 for (
auto&
s : sEvent.StationsRange()) {
171 const int sId =
s.GetId();
172 const auto& dStation = det::Detector::GetInstance().GetSDetector().GetStation(
s);
174 if (fRejectUBStations && !
s.IsUUB()) {
175 ssElectronicsType.push_back(sId);
179 if (fRejectUUBStations &&
s.IsUUB()) {
180 ssElectronicsType.push_back(sId);
185 ssOffGrid.push_back(sId);
189 if (dStation.IsDense()) {
190 ssDense.push_back(sId);
194 if (
s.IsCandidate()) {
205 ssLightning.push_back(sId);
206 switch (fRejectLightning) {
213 WARNING(
"Lightning detected, whole event rejected.");
219 if (!
s.HasRecData()) {
220 ssNoRecData.push_back(sId);
224 const auto& sTrig =
s.GetTriggerData();
225 const bool thtot = sTrig.IsThresholdOrTimeOverThreshold();
228 const bool totd = sTrig.IsTimeOverThresholdDeconvoluted();
229 const bool silenceTotd = fSilenceTOTdStations && totd;
230 const bool mops = sTrig.IsMultiplicityOfPositiveSteps();
231 const bool silenceMops = fSilenceMoPSStations && mops;
232 if ((fSilenceTOTdStations && silenceMops) || (silenceTotd && !mops) || (silenceMops && !totd)) {
236 ssTOTd.push_back(sId);
238 ssMoPS.push_back(sId);
247 MakeInfo(ssOffGrid,
"rejected as off-grid.");
248 MakeInfo(ssDense,
"rejected as dense.");
249 MakeInfo(ssLightning, fRejectLightning ?
"rejected as potential lightning." :
"NOT rejected as lightning.");
250 MakeInfo(ssElectronicsType,
"rejected due to electronics type");
251 MakeInfo(ssNoRecData,
"without RecData rejected.");
252 MakeInfo(ssTOTd,
"set silent because only TOTd.");
253 MakeInfo(ssMoPS,
"set silent because only MoPS.");
265 const bool is3TOTMix,
273 trig << (trig.str().length() ?
"+" :
"") <<
"3TOT";
275 trig << (trig.str().length() ?
"+" :
"") <<
"3TOTd";
277 trig << (trig.str().length() ?
"+" :
"") <<
"3MoPS";
278 if (!is3TOT && !is3TOTd && !is3MoPS && is3TOTMix)
279 trig << (trig.str().length() ?
"+" :
"") <<
"3TOTMix";
281 trig << (trig.str().length() ?
"+" :
"") <<
"4C1";
293 topB.
GetChild(
"MinNumberOfStationsAtBeginning").
GetData(fMinNumberOfStationsAtBeginning);
295 topB.GetChild(
"EnableBottomUpSelection").GetData(fEnableBottomUpSelection);
297 topB.GetChild(
"EnableT4Trigger").GetData(fEnableT4Trigger);
299 topB.GetChild(
"RejectNonT4Events").GetData(fRejectNonT4Events);
301 topB.GetChild(
"EnableT5Trigger").GetData(fEnableT5Trigger);
303 topB.GetChild(
"MinNumberOfActiveStations").GetData(fMinNumberOfActiveStations);
305 topB.GetChild(
"RejectNonT5Events").GetData(fRejectNonT5Events);
307 topB.GetChild(
"RejectLightning").GetData(fRejectLightning);
308 switch (fRejectLightning) {
310 INFO(
"NOT rejecting stations with potential lightning signal.");
313 INFO(
"Rejecting individual stations with lightning signal.");
316 INFO(
"Rejecting whole event when lightning detected.");
319 topB.GetChild(
"RejectUBStations").GetData(fRejectUBStations);
320 topB.GetChild(
"RejectUUBStations").GetData(fRejectUUBStations);
322 if (fRejectUBStations && fRejectUUBStations) {
323 ERROR(
"Both UB and UUB stations configured for rejection. "
324 "At least one type of electronics must remain selected.");
329 const bool bad = topB.GetChild(
"EnableSdExcludedPeriods").Get<
bool>();
334 topB.GetChild(
"RejectBadPeriods").GetData(fRejectBadPeriods);
336 if (fRejectBadPeriods)
337 INFO(
"Events in bad periods are rejected.");
339 INFO(
"Events in bad periods are tagged.");
343 for (
auto periodB = excludedB.GetFirstChild();
344 periodB; periodB = periodB.GetNextSibling()) {
346 const int id = boost::lexical_cast<
int>(att.find(
"id")->second);
352 if (fBadPeriods.begin() == fBadPeriods.end())
353 WARNING(
"No excluded periods found.");
355 sort(fBadPeriods.begin(), fBadPeriods.end());
357 auto bPrevious = fBadPeriods.begin();
358 const auto bEnd = fBadPeriods.end();
359 if (bPrevious != bEnd) {
360 auto bIt = bPrevious;
361 for (++bIt; bIt != bEnd; ++bIt) {
362 if (bPrevious->HasCommonTime(*bIt)) {
364 err <<
"Excluded period "
365 "id=" << bPrevious->GetId() <<
" "
366 "[" << bPrevious->GetStartTime() <<
" | " << bPrevious->GetStopTime() <<
"] "
367 "is in conflict with period "
368 "id=" << bIt->GetId() <<
" "
369 "[" << bIt->GetStartTime() <<
" | " << bIt->GetStopTime() <<
"].";
380 topB.GetChild(
"GridType").GetData(fGridType);
383 INFO(
"Selecting stations from 1500 m array.");
386 INFO(
"Selecting stations from 750 m array.");
389 INFO(
"Selecting stations from 433 m array.");
392 ERROR(
"Unknown GridType!");
396 topB.GetChild(
"LightCompatibilityTolerance").GetData(fLightCompatibilityTolerance);
397 topB.GetChild(
"FirstCrownDistanceRange").GetData(fFirstCrownDistanceRange);
398 topB.GetChild(
"SkewMaximumDistance").GetData(fSkewMaximumDistance);
399 topB.GetChild(
"SeedPlaneFrontTimeResidualRangeToT").GetData(fSeedPlaneFrontTimeResidualRangeToT);
400 topB.GetChild(
"SeedPlaneFrontTimeResidualRangeToTd").GetData(fSeedPlaneFrontTimeResidualRangeToTd);
401 topB.GetChild(
"SeedPlaneFrontTimeResidualRangeMoPS").GetData(fSeedPlaneFrontTimeResidualRangeMoPS);
402 topB.GetChild(
"SeedPlaneFrontTimeResidualRangeTh2").GetData(fSeedPlaneFrontTimeResidualRangeTh2);
403 topB.GetChild(
"SeedPlaneFrontTimeResidualRangeTh1").GetData(fSeedPlaneFrontTimeResidualRangeTh1);
404 topB.GetChild(
"LonelyIfNoneInDistance").GetData(fLonelyIfNoneInDistance);
405 topB.GetChild(
"LonelyIfOneInDistance").GetData(fLonelyIfOneInDistance);
407 topB.GetChild(
"SilenceTOTdStations").GetData(fSilenceTOTdStations);
408 if (fSilenceTOTdStations)
409 INFO(
"Silencing stations with ToTd-only trigger.");
411 topB.GetChild(
"SilenceMoPSStations").GetData(fSilenceMoPSStations);
412 if (fSilenceMoPSStations)
413 INFO(
"Silencing stations with MoPS-only trigger.");
415 const auto silenceNewB = topB.GetChild(
"SilenceTOTdMoPSTriggersBeforeDate");
416 if (silenceNewB.GetChild(
"Enabled").Get<
bool>()) {
417 silenceNewB.GetChild(
"Date").GetData(fSilenceTOTdMoPSDate);
419 info <<
"Will silence stations with ToTd or MoPS only trigger before the date " << fSilenceTOTdMoPSDate;
430 auto& namedCounters = RunController::GetInstance().GetRunData().GetNamedCounters();
433 ++namedCounters[
"SdEventSelector/NoSdEvent"];
434 return eContinueLoop;
437 auto& sEvent =
event.GetSEvent();
440 const auto nStations = StationSelection(sEvent);
441 if (nStations < fMinNumberOfStationsAtBeginning) {
443 info <<
"Not enough stations (" << nStations <<
" < " << fMinNumberOfStationsAtBeginning <<
")!";
445 ++namedCounters[
"SdEventSelector/NotEnoughStations"];
446 return eContinueLoop;
449 fCandidateStations.clear();
450 f3TOTCandidateStations.clear();
451 f3TOTdCandidateStations.clear();
452 f3MoPSCandidateStations.clear();
453 f3TOTMixCandidateStations.clear();
454 f4C1CandidateStations.clear();
455 fSeedStations.clear();
457 const bool isFD = sEvent.GetTrigger().IsFD();
460 ++namedCounters[
"SdEventSelector/FdTrigger"];
462 const auto& eventTime = sEvent.GetHeader().GetTime();
463 if (fSilenceTOTdMoPSDate) {
464 if (eventTime < fSilenceTOTdMoPSDate) {
465 fSilenceTOTdStations =
true;
466 fSilenceMoPSStations =
true;
468 fSilenceTOTdStations =
false;
469 fSilenceMoPSStations =
false;
474 shSRec.SetIsTOTdMoPSSilent(fSilenceTOTdStations && fSilenceMoPSStations);
476 const auto& sDet = det::Detector::GetInstance().GetSDetector();
479 for (
auto&
s : sEvent.CandidateStationsRange()) {
480 const auto& sTrig =
s.GetTriggerData();
481 const auto& ds = sDet.GetStation(
s);
483 fCandidateStations.push_back(sp);
484 if (sTrig.IsT2() || isFD) {
485 f4C1CandidateStations.push_back(sp);
486 if (sTrig.IsTimeOverThreshold())
487 f3TOTCandidateStations.push_back(sp);
488 if (sTrig.IsTimeOverThresholdDeconvoluted() && !fSilenceTOTdStations)
489 f3TOTdCandidateStations.push_back(sp);
490 if (sTrig.IsMultiplicityOfPositiveSteps() && !fSilenceMoPSStations)
491 f3MoPSCandidateStations.push_back(sp);
492 if (sTrig.IsTimeOverThreshold() ||
493 (sTrig.IsTimeOverThresholdDeconvoluted() && !fSilenceTOTdStations) ||
494 (sTrig.IsMultiplicityOfPositiveSteps() && !fSilenceMoPSStations))
495 f3TOTMixCandidateStations.push_back(sp);
499 const bool is3TOT = IsSEvent3TOT(f3TOTCandidateStations);
500 const bool is3TOTd = IsSEvent3TOT(f3TOTdCandidateStations);
501 const bool is3MoPS = IsSEvent3TOT(f3MoPSCandidateStations);
502 const bool is3TOTMix = IsSEvent3TOT(f3TOTMixCandidateStations);
505 ++namedCounters[
"SdEventSelector/3TOT"];
507 ++namedCounters[
"SdEventSelector/3TOTd"];
509 ++namedCounters[
"SdEventSelector/3MoPS"];
511 ++namedCounters[
"SdEventSelector/3TOTMix"];
513 if (fEnableBottomUpSelection && !BottomUpSelection(is3TOTMix, event)) {
514 INFO(
"Bottom-up-selection failed!");
515 ++namedCounters[
"SdEventSelector/BottomUpSelectionFailed"];
516 return eContinueLoop;
521 while (RejectLonelyStations())
524 ++namedCounters[
"SdEventSelector/LonelyStationEvents"];
529 int t4TriggerPattern = 0;
530 if (fEnableT4Trigger) {
532 const bool is4C1 = IsSEvent4C1();
533 const bool isT4 = is3TOTMix || is4C1;
536 <<
GetT4TriggerName(isT4, isFD, is3TOT, is3TOTd, is3MoPS, is3TOTMix, is4C1);
539 ++namedCounters[
"SdEventSelector/4C1"];
541 ++namedCounters[
"SdEventSelector/T4"];
543 if (fRejectNonT4Events && !isT4) {
545 return eContinueLoop;
549 (isFD * ShowerSRecData::eT4_FD) |
550 (is3TOT * ShowerSRecData::eT4_3TOT) |
551 (is3TOTd * ShowerSRecData::eT4_3TOTd) |
552 (is3MoPS * ShowerSRecData::eT4_3MoPS) |
553 (is3TOTMix * ShowerSRecData::eT4_3TOTMix) |
554 (is4C1 * ShowerSRecData::eT4_4C1);
556 shSRec.SetT4Trigger(t4TriggerPattern);
557 shSRec.SetReconstructionSeed(fSeedStations);
561 if (fEnableT5Trigger) {
563 fCandidateStations.clear();
565 for (
auto&
s : sEvent.CandidateStationsRange()) {
566 const auto& ds = sDet.GetStation(
s);
567 fCandidateStations.emplace_back(&
s, &ds);
570 const auto t5Stations = CalculateT5Trigger(sEvent);
571 const unsigned int hottestStation = t5Stations.first;
572 const int nActive = t5Stations.second.size();
573 const bool t5 = (hottestStation && nActive >= fMinNumberOfActiveStations);
576 vector<int> t5NeighborsUUB;
577 for (
const auto sid : t5Stations.second) {
578 const bool isUUB = sDet.GetStation(sid).IsUUB();
580 t5NeighborsUUB.push_back(sid);
583 info << (info.str().length() ?
"; " :
"")
584 <<
"T5 = " << t5 <<
", "
586 "stations = " << hottestStation <<
"(hottest)";
587 for (
const auto id : t5Stations.second) {
588 const auto&
s = sEvent.GetStation(
id);
589 info <<
' ' <<
id <<
'('
590 << (
s.IsCandidate() ?
601 ++namedCounters[
"SdEventSelector/T5"];
603 if (fRejectNonT5Events && !t5) {
605 return eContinueLoop;
608 shSRec.SetT5Trigger(t5*ShowerSRecData::eT5_Prior);
609 shSRec.SetT5HottestStation(hottestStation);
610 shSRec.SetT5PriorActiveNeighbors(t5Stations.second);
611 shSRec.SetT5PriorActiveUUBNeighbors(t5NeighborsUUB);
615 const int id = GetBadPeriod(eventTime);
617 event.GetRecShower().GetSRecShower().SetBadPeriodId(
id);
618 ++namedCounters[
"SdEventSelector/BadPeriodEvents"];
619 info <<
"; Bad period id=" << id;
621 if (fRejectBadPeriods)
622 return eContinueLoop;
625 if (!info.str().empty())
628 ++namedCounters[
"SdEventSelector/SelectedEvent"];
635 SdEventSelector::Finish()
645 if (fBadPeriods.empty())
650 lower_bound(fBadPeriods.begin(), fBadPeriods.end(),
TimeRange(time, time));
652 if (
low == fBadPeriods.begin())
657 return low->IsInRange(time) ?
low->GetId() : 0;
670 if (candidateStations.size() < 3)
673 const auto spBegin = candidateStations.begin();
674 for (
auto spIt = spBegin, spEnd = candidateStations.end(); spIt != spEnd; ++spIt) {
676 const auto& si = *spIt->first;
677 const auto& dsi = *spIt->second;
679 for (
auto spJt = spBegin; spJt != spEnd; ++spJt) {
683 const auto& sj = *spJt->first;
684 const auto& dsj = *spJt->second;
687 const double distij =
Distance(dsi, dsj);
688 if (distij < fFirstCrownDistanceRange[0] || distij > fFirstCrownDistanceRange[1] ||
689 distij < CTimeDifferenceMargin(si, sj))
692 for (
auto spKt = spBegin; spKt != spEnd; ++spKt) {
693 if (spKt == spJt || spKt == spIt)
696 const auto& sk = *spKt->first;
697 const auto& dsk = *spKt->second;
700 const double distik =
Distance(dsi, dsk);
701 if (distik < fFirstCrownDistanceRange[0] || distik > fFirstCrownDistanceRange[1] ||
702 distik < CTimeDifferenceMargin(si, sk))
706 const double distjk =
Distance(dsj, dsk);
707 if (distjk < fFirstCrownDistanceRange[0] || distjk > fSkewMaximumDistance ||
708 distjk < CTimeDifferenceMargin(sj, sk))
726 SdEventSelector::IsSEvent4C1()
729 if (f4C1CandidateStations.size() < 4)
732 const auto spBegin = f4C1CandidateStations.begin();
733 for(
auto spIt = spBegin, spEnd = f4C1CandidateStations.end(); spIt != spEnd; ++spIt) {
735 const auto& si = *spIt->first;
736 const auto& dsi = *spIt->second;
738 for (
auto spJt = spBegin; spJt != spEnd; ++spJt) {
742 const auto& sj = *spJt->first;
743 const auto& dsj = *spJt->second;
746 const double distij =
Distance(dsi, dsj);
747 if (distij < fFirstCrownDistanceRange[0] || distij > fFirstCrownDistanceRange[1] ||
748 distij < CTimeDifferenceMargin(si, sj))
751 for (
auto spKt =
Next(spJt); spKt != spEnd; ++spKt) {
755 const auto& sk = *spKt->first;
756 const auto& dsk = *spKt->second;
759 const double distik =
Distance(dsi, dsk);
760 if (distik < fFirstCrownDistanceRange[0] || distik > fFirstCrownDistanceRange[1] ||
761 distik < CTimeDifferenceMargin(si, sk))
764 if (
Distance(dsj, dsk) < CTimeDifferenceMargin(sj, sk))
767 for (
auto spLt =
Next(spKt); spLt != spEnd; ++spLt) {
771 const auto& sl = *spLt->first;
772 const auto& dsl =*spLt->second;
775 const double distil =
Distance(dsi, dsl);
776 if (distil < fFirstCrownDistanceRange[0] || distil > fFirstCrownDistanceRange[1] ||
777 distil < CTimeDifferenceMargin(si, sl))
780 if (
Distance(dsj, dsl) < CTimeDifferenceMargin(sj, sl))
783 if (
Distance(dsk, dsl) < CTimeDifferenceMargin(sk, sl))
797 pair<int, vector<int>>
798 SdEventSelector::CalculateT5Trigger(
const SEvent& sEvent)
801 const Station* maxStation =
nullptr;
803 double maxSignal = 0;
804 for (
const auto&
s : sEvent.CandidateStationsRange()) {
805 const double signal =
s.GetRecData().GetTotalSignal();
806 if (maxSignal < signal) {
813 INFO(
"No station with maximal signal found");
814 return make_pair(0
U, vector<int>());
818 const auto& sDet = det::Detector::GetInstance().GetSDetector();
819 const auto maxPos = sDet.GetStation(*maxStation).GetPosition();
823 pair<unsigned int, vector<int>> ret;
824 ret.first = maxStation->
GetId();
825 auto& functioningNeighbors = ret.second;
826 unsigned int nCandidates = 0;
827 unsigned int nSilent = 0;
828 unsigned int nRejected = 0;
829 for (
const auto&
s : sEvent.StationsRange()) {
830 if (!
s.IsRejected() || !(
s.GetRejectionStatus() & badBits)) {
831 const auto& pos = sDet.GetStation(
s).GetPosition();
832 const double dist =
Distance(maxPos, pos);
833 if (fFirstCrownDistanceRange[0] < dist && dist < fFirstCrownDistanceRange[1]) {
834 functioningNeighbors.push_back(
s.GetId());
835 nCandidates +=
s.IsCandidate();
836 nSilent +=
s.IsSilent();
837 nRejected +=
s.IsRejected();
842 if (
int(functioningNeighbors.size()) < fMinNumberOfActiveStations) {
844 info <<
"Only " << functioningNeighbors.size() <<
" "
845 "(out of " << fMinNumberOfActiveStations <<
") "
846 "functioning neighbors for max-signal station "
847 << maxStation->
GetId() <<
" found "
848 "(candidates: " << nCandidates <<
", "
849 "silent: " << nSilent <<
", "
850 "rejected: " << nRejected <<
").";
859 SdEventSelector::BottomUpSelection(
const bool is3TOTMix,
Event& event)
863 set<StationPair> all4C1Stations;
865 if (!is3TOTMix && f4C1CandidateStations.size() >= 4) {
868 const auto spBegin = f4C1CandidateStations.begin();
869 for (
auto spIt = spBegin, spEnd = f4C1CandidateStations.end(); spIt != spEnd; ++spIt) {
871 const auto& si = *spIt->first;
872 const auto& dsi = *spIt->second;
874 for (
auto spJt = spBegin; spJt != spEnd; ++spJt) {
878 const auto& sj = *spJt->first;
879 const auto& dsj = *spJt->second;
882 const double distij =
Distance(dsi, dsj);
883 if (distij < fFirstCrownDistanceRange[0] || distij > fFirstCrownDistanceRange[1] ||
884 distij < CTimeDifferenceMargin(si, sj))
887 for (
auto spKt =
Next(spJt); spKt != spEnd; ++spKt) {
891 const auto& sk = *spKt->first;
892 const auto& dsk = *spKt->second;
895 const double distik =
Distance(dsi, dsk);
896 if (distik < fFirstCrownDistanceRange[0] || distik > fFirstCrownDistanceRange[1] ||
897 distik < CTimeDifferenceMargin(si, sk))
900 if (
Distance(dsj, dsk) < CTimeDifferenceMargin(sj, sk))
903 for (
auto spLt =
Next(spKt); spLt != spEnd; ++spLt) {
907 const auto& sl = *spLt->first;
908 const auto& dsl =*spLt->second;
911 const double distil =
Distance(dsi, dsl);
912 if (distil < fFirstCrownDistanceRange[0] || distil > fFirstCrownDistanceRange[1] ||
913 distil < CTimeDifferenceMargin(si, sl))
916 if (
Distance(dsj, dsl) < CTimeDifferenceMargin(sj, sl))
919 if (
Distance(dsk, dsl) < CTimeDifferenceMargin(sk, sl))
922 all4C1Stations.insert(*spIt);
923 all4C1Stations.insert(*spJt);
924 all4C1Stations.insert(*spKt);
925 all4C1Stations.insert(*spLt);
933 fSeedStations.clear();
936 for (
const auto& sp : all4C1Stations) {
937 const auto e = f3TOTMixCandidateStations.end();
938 if (find(f3TOTMixCandidateStations.begin(), e, sp) == e)
939 f3TOTMixCandidateStations.push_back(sp);
942 if (f3TOTMixCandidateStations.size() < 3) {
943 INFO(
"No seed found.");
947 double maxSignalSum = 0;
951 const auto spBegin = f3TOTMixCandidateStations.begin();
952 for (
auto spIt = spBegin, spEnd = f3TOTMixCandidateStations.end(); spIt != spEnd; ++spIt) {
954 const auto& si = *spIt->first;
955 const auto& dsi = *spIt->second;
957 for (
auto spJt = spBegin; spJt != spEnd; ++spJt) {
962 const auto& sj = *spJt->first;
963 const auto& dsj = *spJt->second;
965 const double distij =
Distance(dsi, dsj);
968 if (distij < fFirstCrownDistanceRange[0] || distij > fFirstCrownDistanceRange[1] ||
969 distij < CTimeDifferenceMargin(si, sj))
972 for (
auto spKt = spBegin; spKt != spEnd; ++spKt) {
974 if (spKt == spIt || spKt == spJt)
977 const auto& sk = *spKt->first;
978 const auto& dsk = *spKt->second;
980 const double distik =
Distance(dsi, dsk);
983 if (distik < fFirstCrownDistanceRange[0] || distik > fFirstCrownDistanceRange[1] ||
984 distik < CTimeDifferenceMargin(si, sk))
987 const double distjk =
Distance(dsj, dsk);
989 if (distjk < fFirstCrownDistanceRange[0] || distjk > fSkewMaximumDistance ||
990 distjk < CTimeDifferenceMargin(sj, sk))
993 const double sigi = si.GetRecData().GetTotalSignal();
994 const double sigj = sj.GetRecData().GetTotalSignal();
995 const double sigk = sk.GetRecData().GetTotalSignal();
996 const double signalSum = sigi + sigj + sigk;
998 if (signalSum > maxSignalSum) {
999 maxSignalSum = signalSum;
1028 if (!seed[0].first) {
1030 INFO(
"No seed found.");
1035 fSeedStations.resize(3);
1036 for (
int i = 0; i < 3; ++i)
1037 fSeedStations[i] = seed[i].first->GetId();
1039 const auto& s1 = *seed[0].first;
1040 const auto& t1 = s1.GetRecData().GetSignalStartTime();
1041 const auto& x1 = seed[0].second->GetPosition();
1043 const auto& s2 = *seed[1].first;
1045 kSpeedOfLight*(t1 - s2.GetRecData().GetSignalStartTime()).GetInterval();
1046 const auto x21 = seed[1].second->GetPosition() - x1;
1048 const auto& s3 = *seed[2].first;
1050 kSpeedOfLight*(t1 - s3.GetRecData().GetSignalStartTime()).GetInterval();
1051 const auto x31 = seed[2].second->GetPosition() - x1;
1053 const double sx21 = x21.GetMag();
1054 const auto vi = x21 / sx21;
1055 const double taui = ct12/sx21;
1056 const double sx31 = x31.GetMag();
1057 const auto vj = x31 / sx31;
1058 const double tauj = ct13/sx31;
1059 const double ij = vi*vj;
1060 const double d = 1 - ij*ij;
1061 const double gamma2 = (1 - (taui*taui - 2*ij*taui*tauj + tauj*tauj)/d)/d;
1063 const auto& siteCS = det::Detector::GetInstance().GetSiteCoordinateSystem();
1069 const double alpha = (taui - tauj*ij) / d;
1070 const double beta = (tauj - taui*ij) / d;
1071 const double gamma =
sqrt(gamma2);
1074 if (vk.
GetZ(siteCS) < 0)
1076 axis = alpha*vi + beta*vj + gamma*vk;
1081 INFO(
"Unphysical seed, trying minimization.");
1087 minuit.mnexcm(
"SET PRINTOUT", argList, 1, errFlag);
1088 minuit.mnexcm(
"SET NOWARNINGS", argList, 0, errFlag);
1089 minuit.SetPrintLevel(-1);
1095 const double jk = vj * vk;
1101 minuit.mnexcm(
"SET ERRORDEF", argList, 1, errFlag);
1103 const double phi0 = atan2(tauj*jk, taui + tauj*ij);
1104 minuit.mnparm(0,
"phi", phi0, 0.5, 0, 0, errFlag);
1107 minuit.mnexcm(
"MINIMIZE", argList, 1, errFlag);
1109 minuit.mnexcm(
"MINOS", argList, 0, errFlag);
1116 minuit.GetParameter(0, phi, phiErr);
1118 const double u = cos(phi);
1119 const double v = sin(phi);
1120 axis = u * vi + v * vk;
1125 info <<
"Seed theta = " << axis.
GetTheta(siteCS)/
degree <<
" deg, "
1126 "phi = " << axis.
GetPhi(siteCS)/
degree <<
" deg (site)";
1131 ssRec.SetSeedAxis(axis);
1132 ssRec.SetSeedBarycenter(x1 + (1/3.)*(x21 + x31));
1134 map<int, double> rejected;
1135 for (
auto spIt = fCandidateStations.begin(); spIt != fCandidateStations.end(); ) {
1136 auto&
s = *spIt->first;
1137 const double delay =
1138 (
s.GetRecData().GetSignalStartTime() - t1).GetInterval() +
1141 s.SetBottomUpResidual(delay);
1144 const auto& sTrig =
s.GetTriggerData();
1145 if ((sTrig.IsTimeOverThreshold() &&
IsInRange(delay, fSeedPlaneFrontTimeResidualRangeToT)) ||
1146 (sTrig.IsTimeOverThresholdDeconvoluted() &&
IsInRange(delay, fSeedPlaneFrontTimeResidualRangeToTd)) ||
1147 (sTrig.IsMultiplicityOfPositiveSteps() &&
IsInRange(delay, fSeedPlaneFrontTimeResidualRangeMoPS)) ||
1148 (sTrig.IsT2Threshold() &&
IsInRange(delay, fSeedPlaneFrontTimeResidualRangeTh2)) ||
1149 (sTrig.IsT1Threshold() &&
IsInRange(delay, fSeedPlaneFrontTimeResidualRangeTh1)))
1153 rejected[
s.GetId()] =
delay;
1154 f3TOTMixCandidateStations.remove(*spIt);
1155 f4C1CandidateStations.remove(*spIt);
1156 spIt = fCandidateStations.erase(spIt);
1160 if (!rejected.empty()) {
1163 <<
" not compatible with seed reconstruction:\n";
1167 for (
const auto& r : rejected)
1181 SdEventSelector::RejectLonelyStations()
1183 vector<int> ssLonely;
1185 for (
auto spIt = fCandidateStations.begin(); spIt != fCandidateStations.end(); ) {
1186 const auto& dsi = *spIt->second;
1187 int closeNeighbors = 0;
1188 int remoteNeighbors = 0;
1189 for (
auto spJt = fCandidateStations.begin(); spJt != fCandidateStations.end(); ++spJt) {
1192 const double distij =
Distance(dsi, *spJt->second);
1193 if (distij < fLonelyIfNoneInDistance)
1195 if (distij < fLonelyIfOneInDistance)
1198 if (!closeNeighbors || remoteNeighbors <= 1) {
1199 auto&
s = *spIt->first;
1200 ssLonely.push_back(
s.GetId());
1202 f3TOTMixCandidateStations.remove(*spIt);
1203 f4C1CandidateStations.remove(*spIt);
1204 spIt = fCandidateStations.erase(spIt);
1209 if (!ssLonely.empty()) {
AxialVector Cross(const Vector &l, const Vector &r)
int GetId() const
Get the station Id.
constexpr T Sqr(const T &x)
double GetPhi(const CoordinateSystemPtr &coordinateSystem) const
azimuth (phi) angle in spherical and cylindrical coordinates
Detector description interface for Station-related data.
Time interval defined by two TimeStamps.
ShowerSRecData & GetSRecShower(evt::Event &event)
Interface class to access to the SD Reconstruction of a Shower.
Iterator Next(Iterator it)
bool HasRecShower() const
Interface class to access to the SD part of an event.
double GetTheta(const CoordinateSystemPtr &coordinateSystem) const
zenith (theta) angle in spherical coordinates
sevt::StationRecData & GetRecData()
Get station level reconstructed data.
#define INFO(message)
Macro for logging informational messages.
void Init()
Initialise the registry.
Branch GetChild(const std::string &childName) const
Get child of this Branch by child name.
void Chi2(int &, double *const , double &value, double *const par, const int)
std::list< StationPair > StationPairList
A TimeStamp holds GPS second and nanosecond for some event.
string GetT4TriggerName(const bool isT4, const bool isFD, const bool is3TOT, const bool is3TOTd, const bool is3MoPS, const bool is3TOTMix, const bool is4C1)
utl::Point GetPosition() const
Tank position.
const char * Plural(const T n)
AttributeMap GetAttributes() const
Get a map<string, string> containing all the attributes of this Branch.
class to hold data at Station level
std::string AsBinary(const T &number, const int maxBits=8 *sizeof(T), const char separator= ' ', const int stride=4)
converts integer-type numbers into a string of binary representation
utl::TimeStamp GetSignalStartTime() const
Start time of the signal.
constexpr double nanosecond
double abs(const SVector< n, T > &v)
class to format data in tabular form
#define WARNING(message)
Macro for logging warning messages.
void GetData(bool &b) const
Overloads of the GetData member template function.
AxialVector Normalized(const AxialVector &v)
double Distance(const Point &p, const sdet::Station &s)
constexpr double kSpeedOfLight
void MakeInfo(const vector< int > &ids, const string &message)
ResultFlag
Flag returned by module methods to the RunController.
static CentralConfig * GetInstance()
Use this the first time you get an instance of central configuration.
bool IsInRange(const double x, const vector< double > &r)
std::pair< sevt::Station *, const sdet::Station * > StationPair
string OfSortedIds(vector< int > ids)
bool IsLightning(const Station &station)
double GetZ(const CoordinateSystemPtr &coordinateSystem) const
#define ERROR(message)
Macro for logging error messages.
utl::Branch GetTopBranch(const std::string &id)
Get top branch for moduleConfigLink with given id (XML files)