3 #include <evt/ShowerRecData.h>
4 #include <evt/ShowerSRecData.h>
5 #include <evt/ShowerScintillatorRecData.h>
7 #include <evt/ShowerFRecData.h>
8 #include <evt/ShowerSimData.h>
10 #include <sevt/SEvent.h>
11 #include <sevt/StationRecData.h>
12 #include <sevt/EventTrigger.h>
13 #include <sevt/Station.h>
14 #include <sevt/StationConstants.h>
15 #include <sevt/Scintillator.h>
16 #include <sevt/ScintillatorRecData.h>
18 #include <fevt/FEvent.h>
19 #include <fevt/Header.h>
21 #include <fevt/Telescope.h>
22 #include <fevt/EyeHeader.h>
23 #include <fevt/EyeRecData.h>
25 #include <det/Detector.h>
27 #include <sdet/SDetector.h>
28 #include <sdet/SDetectorConstants.h>
29 #include <sdet/Station.h>
30 #include <sdet/STimeVariance.h>
32 #include <fdet/FDetector.h>
34 #include <fdet/Telescope.h>
36 #include <fwk/LocalCoordinateSystem.h>
37 #include <fwk/CentralConfig.h>
38 #include <fwk/RunController.h>
40 #include <utl/CoordinateSystem.h>
41 #include <utl/PhysicalConstants.h>
42 #include <utl/ErrorLogger.h>
43 #include <utl/TabulatedFunctionErrors.h>
44 #include <utl/TimeStamp.h>
45 #include <utl/AxialVector.h>
47 #include <utl/Reader.h>
49 #include <utl/NumericalErrorPropagator.h>
51 #include <Minuit2/MnMinimize.h>
52 #include <Minuit2/MnHesse.h>
53 #include <Minuit2/FCNBase.h>
54 #include <Minuit2/FunctionMinimum.h>
55 #include <Minuit2/MnUserParameters.h>
56 #include <Minuit2/MnUserCovariance.h>
57 #include <Minuit2/MnPrint.h>
61 #include <boost/range/iterator_range.hpp>
64 using namespace ScintillatorLDFFinderKG;
72 using CLHEP::HepRotation;
74 #define OUT(x) if ((x) <= fInfoLevel) cerr
77 namespace ScintillatorLDFFinderKG {
86 const size_t npar = result.fPar.size();
87 for (
size_t i = 0; i <
npar; ++i) {
88 if (std::isnan(result.fPar[i]))
90 for (
size_t j = i; j <
npar; ++j)
91 if (std::isnan(result.fCov(i, j)))
106 << g.GetX(cs)/
meter <<
", "
107 << g.GetY(cs)/
meter <<
", "
108 << g.GetZ(cs)/
meter <<
") [m]";
111 << g.GetX(cs) <<
", "
112 << g.GetY(cs) <<
", "
113 << g.GetZ(cs) <<
')';
124 label <<
"S" << refdist/
meter;
125 if (refdist < 1000*
meter)
135 static const char*
const labels[] = {
"beta ",
"gamma",
"mu ",
"tau " };
136 return labels[iShape];
148 DeltaR(
const double wcdShowerSize,
const double cosTheta)
150 const double f0 = 112.71;
151 const double f1 = 30.85;
152 const double f2 = -58.08;
153 const double f3 = -12.43;
154 const double f4 = 10.28;
155 const double f5 = 11.96;
157 const double sinTheta2 = 1 - cosTheta * cosTheta;
159 const double a = f0 + f1 * sinTheta2;
160 const double b = f2 + f3 * sinTheta2;
161 const double c = f4 + f5 * sinTheta2;
163 const double deltaR = a + b * std::log10(wcdShowerSize)
164 + c * std::log10(wcdShowerSize)* std::log10(wcdShowerSize);
178 const ShowerSRecData& recShower =
event.GetRecShower().GetSRecShower();
181 <<
"***** Final reconstructed shower data *****\n"
182 " LDF stage = " <<
" --- " <<
"\n"
188 " LDF chi2 / ndof = " << scinRecShower.
GetLDFChi2() <<
" / " << scinRecShower.
GetLDFNdof() <<
"\n"
203 const string sigVariance = topB.
GetChild(
"signalVariance").
Get<
string>();
204 if (sigVariance ==
"eGAP2018_025")
206 else if (sigVariance ==
"eGAP2019_000")
209 ERROR(
"Unknown signal variance");
217 double ldfReferenceDistance;
220 vector<double> ldfParameters;
223 vector<double> ldfUncertaintyParameters;
224 topB.
GetChild(
"ldfUncertaintyParameters").
GetData(ldfUncertaintyParameters);
226 fLDFFitConfig.fLDF =
LDF(ldfType, ldfReferenceDistance,
227 ldfParameters, ldfUncertaintyParameters);
228 fLDFFitConfig.fLDFShapeTreatment.resize(fLDFFitConfig.fLDF.GetNShapeParameters(),
eFitted);
232 fLDFFitConfig.fFixCore = fFixedCore;
235 fLDFFitConfig.fCorePropagationEnabled = fCorePropagation;
237 string minimizationMethod;
239 fUseMaxLikelihood = (minimizationMethod ==
"MaxLike");
243 topB.
GetChild(
"maxBaryToCoreDistance").
GetData(fMaxBaryToCoreDistance);
244 if (fMaxBaryToCoreDistance <= 0) {
245 ERROR(
"<maxBaryToCoreDistance> must be > 0");
250 stage0B.
GetChild(
"minNumberOfStations").
GetData(fStage0.fMinNumberOfStations);
253 stage1B.
GetChild(
"minNumberOfStations").
GetData(fStage1.fMinNumberOfStations);
257 stage2B.
GetChild(
"minNumberRelaxBeta").
GetData(fStage2.fMinNumberRelaxBeta);
258 stage2B.
GetChild(
"minNumberRelaxGamma").
GetData(fStage2.fMinNumberRelaxGamma);
263 <<
" LDF type: " << fLDFFitConfig.fLDF.GetType() <<
"\n"
264 <<
" Core type: " << (fFixedCore ?
"Reconstructed" :
"Fitted") <<
"\n"
265 <<
" Core uncertainties: " << (fCorePropagation ?
"Propagated" :
"Not included") <<
"\n"
267 <<
" Minimization method: " << (fUseMaxLikelihood ?
"Maximum-Likelihood" :
"Chi2") <<
"\n";
279 if (!(event.
HasSEvent() &&
event.HasRecShower() &&
280 event.GetRecShower().HasSRecShower()))
281 return eContinueLoop;
283 const SEvent& sEvent =
event.GetSEvent();
285 const ShowerSRecData& showerRec =
event.GetRecShower().GetSRecShower();
287 if (!showerRec.
HasLDF()) {
289 <<
"No LDF found from SD reconstruction!\n";
290 return eContinueLoop;
308 <<
"Distance cut for SSDs = " <<
DistanceCut(wcdShowerSize, cosTheta) <<
" m\n";
316 if (station.IsCandidate() && station.HasScintillator() && station.GetScintillator().HasRecData()) {
319 const sdet::SDetector& sDetector = det::Detector::GetInstance().GetSDetector();
321 const double rho =
RPerp(showerAxis, pos - core);
325 if (station.GetScintillator().IsLowGainSaturation())
328 }
else if (station.IsSilent())
332 nStations -= (nDistant + nSaturated);
335 <<
"# candidate stations = " << nStations
336 <<
" (" << nSaturated <<
" saturated, " << nDistant <<
" distant), " << nSilent <<
" silent\n";
340 if (nStations < fStage0.fMinNumberOfStations) {
342 <<
"Not enough stations.\n";
343 return eContinueLoop;
346 fLDFFitConfig.deltaR =
DeltaR(wcdShowerSize,cosTheta);
359 vector<StationFitData> stationFitData = MakeStationFitData(sEvent, core, wcdShowerSize, showerAxis);
363 best.
fRecStage = ShowerSRecData::kLDFEstimate;
366 <<
" - LDF shape fixed\n";
368 FitLDFSimplified(best, config, showerAxis, stationFitData);
370 if (nStations < fStage1.fMinNumberOfStations) {
371 SetRecData(event, best);
372 OutputResults(event);
384 <<
"Stage " << result.
fRecStage <<
": fit "
386 <<
" - core and shape fixed \n";
388 if (!FitLDF(result, config, showerAxis, stationFitData)){
390 <<
"Fit of the LDF FAILED! \n";
391 return eContinueLoop;
404 (nStations < fStage2.fMinNumberRelaxBeta ||
407 (nStations < fStage2.fMinNumberRelaxGamma ||
413 <<
"Stage " << result.
fRecStage <<
": fit "
419 if (FitLDF(result, config, showerAxis, stationFitData)) {
420 const bool fixBeta = FixBeta(result, showerAxis, stationFitData);
421 const bool fixGamma = FixGamma(result, showerAxis, stationFitData);
424 result.
fRecStage = ShowerSRecData::kLDF +
434 if (FitLDF(result, config, showerAxis, stationFitData)) {
435 result.
fRecStage = ShowerSRecData::kLDF +
445 SetRecData(event, best);
446 OutputResults(event);
467 const vector<StationFitData>&
data)
470 size_t nStations = 0;
471 for (
const auto& station : data) {
472 if (!station.fSignal)
479 <<
"FixBeta = " <<
true
480 <<
": nStations = " << nStations <<
'\n';
484 int nStationsInRange = 0;
485 double maxDistance = 0;
489 double refDist(fLDFFitConfig.fLDF.GetReferenceDistance());
491 if (refDist == 1000*
meter) {
492 rRange[0] = 400*
meter;
493 rRange[1] = 1600*
meter;
494 leverArms[0] = 900*
meter;
495 leverArms[1] = 800*
meter;
496 leverArms[2] = 700*
meter;
497 }
else if (refDist == 450*
meter) {
498 rRange[0] = 180*
meter;
499 rRange[1] = 720*
meter;
500 leverArms[0] = 405*
meter;
501 leverArms[1] = 360*
meter;
502 leverArms[2] = 315*
meter;
503 }
else if (refDist == 250*
meter) {
504 rRange[0] = 100*
meter;
505 rRange[1] = 400*
meter;
506 leverArms[0] = 225*
meter;
507 leverArms[1] = 200*
meter;
508 leverArms[2] = 175*
meter;
514 for (
const auto& station : data) {
516 if (!station.fSignal)
519 const double r =
RPerp(showerAxis, station.fPos - core);
521 if (rRange[0] < r && r < rRange[1]) {
524 for (
const auto&
s : data) {
525 const double rr =
RPerp(showerAxis,
s.fPos - core);
527 if (rRange[0] < rr && rr < rRange[1]) {
528 const double distance = fabs(r - rr);
529 if (distance > maxDistance)
530 maxDistance = distance;
536 const bool fixBeta = !((nStationsInRange > 1 && maxDistance > leverArms[0]) ||
537 (nStationsInRange > 2 && maxDistance > leverArms[1]) ||
538 (nStationsInRange > 3 && maxDistance > leverArms[2]));
540 <<
"FixBeta = " << fixBeta <<
": "
541 "nStations (InRange) = " << nStations <<
" (" << nStationsInRange <<
"), "
542 "maxDistance = " << maxDistance/
meter <<
" [m]\n";
552 const vector<StationFitData>&
data)
555 size_t nStations = 0;
556 for (
const auto& station : data) {
557 if (!station.fSignal)
564 <<
"FixGamma = " <<
true <<
": nStations = " << nStations <<
'\n';
568 int nStationsInRange = 0;
569 double maxDistance = 0;
573 double refDist(fLDFFitConfig.fLDF.GetReferenceDistance());
575 if (refDist == 1000*
meter) {
576 rRange[0] = 1000*
meter;
577 rRange[1] = 2000*
meter;
578 leverArms[0] = 500*
meter;
579 leverArms[1] = 400*
meter;
580 leverArms[2] = 300*
meter;
581 }
else if (refDist == 450*
meter) {
582 rRange[0] = 450*
meter;
583 rRange[1] = 1500*
meter;
584 leverArms[0] = 250*
meter;
585 leverArms[1] = 200*
meter;
586 leverArms[2] = 150*
meter;
593 for (
const auto& station : data) {
594 if (!station.fSignal)
597 const double r =
RPerp(showerAxis, station.fPos - core);
599 if (rRange[0] < r && r < rRange[1]) {
603 for (
const auto&
s : data) {
605 const double rr =
RPerp(showerAxis,
s.fPos - core);
607 if (rRange[0] < rr && rr < rRange[1]) {
608 const double distance = fabs(r - rr);
609 if (distance > maxDistance)
610 maxDistance = distance;
616 const bool fixGamma = !((nStationsInRange > 1 && maxDistance > leverArms[0]) ||
617 (nStationsInRange > 2 && maxDistance > leverArms[1]) ||
618 (nStationsInRange > 3 && maxDistance > leverArms[2]));
620 <<
"FixGamma = " << fixGamma <<
": "
621 "nStations (InRange) = " << nStations <<
" (" << nStationsInRange <<
"), "
622 "maxDistance = " << maxDistance/
meter <<
" [m]\n";
645 const sdet::SDetector& sDetector = det::Detector::GetInstance().GetSDetector();
647 const LDF& ldf = fLDFFitConfig.fLDF;
655 SEvent& sEvent =
event.GetSEvent();
657 const double theta = axis.
GetTheta(coreCS);
658 const double phi = axis.
GetPhi(coreCS);
660 CoordinateSystem::RotationY(
662 CoordinateSystem::RotationZ(
669 Accumulator::MinMax<double> minMaxRho(1000*
kilometer, 0);
673 if (!station.HasRecData())
676 if (!station.HasScintillator())
685 const double x = sPos.
GetX(showerPlaneCS);
686 const double y = sPos.
GetY(showerPlaneCS);
687 const double rho =
sqrt(x*x + y*y);
689 if (station.IsCandidate())
694 const double funcval = showerSize * ldf(rho, ldfShapePars);
701 if (!scinRecShower.
HasLDF())
704 tabulatedLDF.
Clear();
707 const double x0 = log(1);
708 const double x1 = log(10000);
709 const int nLDFPoints = 20;
711 for (
int i = 0; i < nLDFPoints; ++i) {
712 const double z = double(i) / (nLDFPoints-1);
713 const double rho = exp((1-z)*x0 + z*x1);
714 const double funcval = showerSize * ldf(rho, ldfShapePars);
716 tabulatedLDF.
PushBack(rho, 0, funcval, sigma);
722 vector<double> ldfShapeParsErr;
723 for (
size_t i = 0, n = fLDFFitConfig.fLDF.GetNShapeParameters(); i < n; ++i)
724 ldfShapeParsErr.push_back(lres.
fCov.Std(eShapeParameters + i));
736 scinRecShower.
SetBeta(ldfShapePars[0], ldfShapeParsErr[0]);
738 if (ldfShapePars.size() > 1)
739 scinRecShower.
SetGamma(ldfShapePars[1], ldfShapeParsErr[1]);
751 vector<StationFitData>
755 vector<StationFitData> sFitData;
757 const sdet::SDetector& sDetector = det::Detector::GetInstance().GetSDetector();
769 if (!station.IsCandidate())
772 if (!station.HasScintillator())
775 if (!station.GetScintillator().HasRecData())
780 const double rho =
RPerp(showerAxis, pos - core);
795 current.
fId = station.GetId();
796 current.
fIsSaturated = station.GetScintillator().IsLowGainSaturation();
799 sFitData.push_back(current);
812 const vector<StationFitData>&
data)
821 const vector<double> shape = config.
fLDF.
ShapeModel(cosTheta, 10);
833 double rhoClosest = kRefDist;
834 double signalClosest = 1;
837 for (
const auto& station : data) {
839 if (!station.fSignal)
842 const double rho =
RPerp(showerAxis, station.fPos - core);
843 const double distance = fabs(rho - kRefDist);
845 if (distance < minDistance) {
846 minDistance = distance;
848 signalClosest = station.fSignal;
877 for (
const auto& station : data) {
878 const double s = station.fSignal;
883 const double rho =
RPerp(showerAxis, station.fPos - core);
884 const double f = config.
fLDF(rho, shape);
908 FitLDF(result, thisConfig, showerAxis, data);
916 const vector<StationFitData>&
data)
919 using namespace ROOT::Minuit2;
921 MnUserParameters pars;
923 pars.Add(
"showerSize", result.
fPar[0], 1.0);
924 pars.SetLowerLimit(
"showerSize", 0);
925 pars.Add(
"coreX", result.
fPar[1], 200*
meter);
926 pars.Add(
"coreY", result.
fPar[2], 200*
meter);
942 MnMinimize
m(fUseMaxLikelihood ?
943 static_cast<const FCNBase&>(likeFcn) :
944 static_cast<const FCNBase&>(chi2Fcn), pars, 1);
946 FunctionMinimum fmin =
m(10000);
948 if (fmin.IsAboveMaxEdm() || fmin.HasReachedCallLimit() || !fmin.IsValid()) {
950 <<
"\n**************** Minimize FAILED ****************\n"
952 <<
"**************** Minimize FAILED ****************\n\n";
958 msg <<
"Found minimum after " << fmin.NFcn() <<
" evaluations";
963 hesse(m.Fcnbase(), fmin, 10000);
965 if (!fmin.IsValid() || fmin.HesseFailed()) {
967 <<
"\n**************** Hesse FAILED ****************\n"
969 <<
"**************** Hesse FAILED ****************\n\n";
973 if (fInfoLevel >= eMinuit)
975 <<
"\n**************** Minuit Output ****************\n"
977 <<
"**************** Minuit Output ****************\n\n";
980 result.
fPar = fmin.UserParameters().Params();
982 const vector<double> modeledShape =
986 result.
fPar[3+i] = modeledShape[i];
988 const size_t nVar = pars.VariableParameters();
993 for (
size_t i = 0; i < nVar; ++i)
994 for (
size_t j = 0; j < nVar; ++j)
995 result.
fCov(m.ExtOfInt(i), m.ExtOfInt(j)) = fmin.UserCovariance()(i,j);
997 const double minValue = fmin.Fval();
998 if (fUseMaxLikelihood) {
1003 result.
fChi2 = minValue;
1007 for (
const auto& station : data)
1008 if (station.fSignal > 0)
1010 result.
fNdof -= nVar;
1012 const double reducedChi2 = (result.
fNdof > 0) ? result.
fChi2/result.
fNdof : 0;
1018 <<
" chi2 = " << result.
fChi2 <<
" / " << result.
fNdof <<
"\n"
1025 <<
" = " << result.
fPar[eShapeParameters + i] <<
" +/- " << result.
fCov.Std(eShapeParameters + i);
1026 OUT(eIntermediate) << endl;
1028 if (reducedChi2 > fMaxChi2) {
1030 <<
" Chi2/Ndof = " << reducedChi2 <<
" exceeds limit "
1031 << fMaxChi2 <<
'\n';
1035 const double d = (core - fBarycenter).GetMag();
1036 if (d > fMaxBaryToCoreDistance) {
1038 <<
" Distance to core " << d/
km <<
" [km] exceeds limit.\n";
string ToString(const G &g, const CoordinateSystemPtr cs, bool units=true)
StationIterator StationsEnd()
End of all stations.
double GetShowerSizeError() const
double GetPhi(const CoordinateSystemPtr &coordinateSystem) const
azimuth (phi) angle in spherical and cylindrical coordinates
void SetRecData(evt::Event &event, const LDFFitResult &lresult) const
void SetTotalSignal(const double s, const double sErr)
Interface class to access to the SD Reconstruction of a Shower.
Interface class to access to the SD part of an event.
const utl::TimeStamp & GetBarytime() const
std::vector< double > ShapeModel(const double cosTheta, const double showerSize) const
double GetTheta(const CoordinateSystemPtr &coordinateSystem) const
zenith (theta) angle in spherical coordinates
double GetCosTheta(const CoordinateSystemPtr &coordinateSystem) const
cos of zenith (theta) angle
bool HasScintillatorRecShower() const
const utl::CoordinateSystemPtr & GetBarycenterCoordinateSystem() const
origin = GetBarycenter(), z-axis = local vertical, x-axis = east
ScintillatorRecData & GetRecData()
Get object containing scintillator reconstructed data.
void SetShowerSize(const double value, const double error)
#define INFO(message)
Macro for logging informational messages.
void SetBeta(const double beta, const double error)
double GetShowerSize() const
Base class for exceptions trying to access non-existing components.
bool FitLDF(LDFFitResult &result, LDFFitConfig &config, const utl::Vector &showerAxis, const std::vector< StationFitData > &data) const
Branch GetChild(const std::string &childName) const
Get child of this Branch by child name.
fwk::VModule::ResultFlag Init()
Initialize: invoked at beginning of run (NOT beginning of event)
double RPerp(const utl::Vector &axis, const utl::Vector &station)
double DeltaR(const double wcdShowerSize, const double cosTheta)
utl::Point GetPosition() const
Tank position.
void SetGamma(const double gamma, const double error)
boost::shared_ptr< const CoordinateTransformer > CoordinateSystemPtr
Shared pointer for coordinate systems.
void SetLDFChi2(const double chi2, const double ndof)
Class representing a document branch.
double GetGammaError() const
bool HasRecData() const
Check for existence of scintillator reconstructed data object.
double GetLDFNdof() const
double GetX(const CoordinateSystemPtr &coordinateSystem) const
void SetLDFLikelihood(const double likelihood)
double GetBetaError() const
void OutputResults(const evt::Event &event) const
const utl::Point & GetBarycenter() const
bool HasNaN(const T &result)
const char * GetShapeLabel(const int iShape)
string GetShowerSizeLabel(const LDFFitConfig &config)
const utl::TabulatedFunctionErrors & GetLDF() const
ShowerScintillatorRecData & GetScintillatorRecShower()
const utl::Vector & GetAxis() const
double GetTotalSignal() const
void SetLDFRecStage(const double stage)
void PushBack(const double x, const double xErr, const double y, const double yErr)
void GetData(bool &b) const
Overloads of the GetData member template function.
double GetReferenceDistance() const
std::vector< ParameterTreatment > fLDFShapeTreatment
std::vector< double > GetLDFShapeParameters() const
void FitLDFSimplified(LDFFitResult &result, LDFFitConfig &config, const utl::Vector &showerAxis, const std::vector< StationFitData > &data) const
Early estimate of shower size.
double GetY(const CoordinateSystemPtr &coordinateSystem) const
class to hold data for station Scintillator
ResultFlag
Flag returned by module methods to the RunController.
utl::CoordinateSystemPtr gBaryCS
void SetLDFResidual(const double res)
utl::CovarianceMatrix fCov
double GetLDFChi2() const
double DistanceCut(const double showerSize, const double cosTheta)
StationIterator StationsBegin()
Beginning of all stations.
Class to access station scintillator reconstructed data.
constexpr double kilometer
void SetShowerSizeType(const ShowerSizeType type)
Detector description interface for SDetector-related data.
const utl::Point & GetCorePosition() const
Main configuration utility.
fwk::VModule::ResultFlag Finish()
Finish: invoked at end of the run (NOT end of the event)
Class to access shower scintillator reconstructed data.
bool FixBeta(const LDFFitResult &result, const utl::Vector &showerAxis, const std::vector< StationFitData > &data) const
double SignalUncertainty(const ESignalVarianceModel model, const double cosTheta, const double signal)
void MakeScintillatorRecShower()
fwk::VModule::ResultFlag Run(evt::Event &event)
Run: invoked once per event.
const Station & GetStation(const int stationId) const
Get station by Station Id.
unsigned int GetNShapeParameters() const
#define ERROR(message)
Macro for logging error messages.
double GetShowerSize() const
bool FixGamma(const LDFFitResult &result, const utl::Vector &showerAxis, const std::vector< StationFitData > &data) const
Criterion if gamma can be fitted analogue to beta must be checked/updated.
std::vector< StationFitData > MakeStationFitData(const sevt::SEvent &sEvent, const utl::Point core, const double showerSize, const utl::Vector &showerAxis) const
Init station data used by LDF fit.
utl::Point GetCore() const
std::vector< double > fPar
utl::Branch GetTopBranch(const std::string &id)
Get top branch for moduleConfigLink with given id (XML files)