65 #include <fwk/CentralConfig.h>
67 #include <evt/Event.h>
68 #include <evt/ShowerRecData.h>
69 #include <evt/ShowerSRecData.h>
71 #include <sevt/SEvent.h>
72 #include <sevt/Header.h>
73 #include <sevt/Station.h>
74 #include <sevt/StationRecData.h>
75 #include <sevt/StationConstants.h>
77 #include <sevt/PMTRecData.h>
79 #include <det/Detector.h>
81 #include <utl/Reader.h>
82 #include <utl/AugerUnits.h>
83 #include <utl/ErrorLogger.h>
84 #include <utl/StringCompare.h>
85 #include <utl/Trace.h>
86 #include <utl/TraceAlgorithm.h>
91 #include <TVirtualFitter.h>
99 using namespace Risetime1000;
100 using std::ostringstream;
104 double Risetime1000LLL::fgRisetime = -1;
105 double Risetime1000LLL::fgRisetimeError = -1;
106 double Risetime1000LLL::fgRisetimeReducedChi2 = -1;
113 Risetime1000LLL::~Risetime1000LLL()
115 delete fgRisetimeResults;
116 fgRisetimeResults =
nullptr;
123 std::ostringstream info;
124 info <<
"Configuring the FADC Parameters module.\n"
125 "***************************************\n";
126 auto topB = CentralConfig::GetInstance()->GetTopBranch(
"Risetime1000");
129 auto recalculateRiseTimeB = topB.GetChild(
"RecalculateRisetime");
130 recalculateRiseTimeB.GetChild(
"Recalculate").GetData(fForceRiseTimeRecalculation);
131 recalculateRiseTimeB.GetChild(
"RiseTimeStartFraction").GetData(fRiseTimeStartFraction);
132 recalculateRiseTimeB.GetChild(
"RiseTimeStopFraction").GetData(fRiseTimeStopFraction);
133 if (fForceRiseTimeRecalculation) {
134 info <<
"Going to recalculate risetimes for stations.\n"
135 "Pulse RiseTime defined as:\n"
136 << fRiseTimeStartFraction*100 <<
"% to " << fRiseTimeStopFraction*100
137 <<
"% of total signal.\n";
139 info <<
"Using existing station risetimes (from SdCalibrator).\n";
144 info <<
"\nConfiguring the risetime fit routines.\n";
145 auto risetimeFitB = topB.GetChild(
"RisetimeFit");
146 risetimeFitB.GetChild(
"Fit").GetData(fDoRiseTimeFit);
147 if (fDoRiseTimeFit) {
148 info <<
"Fitting the risetime for the event is enabled.\n";
149 risetimeFitB.GetChild(
"MinimumSignal").GetData(fMinimumSignalForRiseTimeFit);
150 risetimeFitB.GetChild(
"MinimumDistance").GetData(fMinimumDistanceForRiseTimeFit);
151 risetimeFitB.GetChild(
"MaximumDistance").GetData(fMaximumDistanceForRiseTimeFit);
152 risetimeFitB.GetChild(
"RisetimeEvaluatedAt").GetData(fDistanceToInterpolateFitResult);
153 info <<
"\tMinimum Signal " << fMinimumSignalForRiseTimeFit <<
" VEM\n"
154 <<
"\tMinimum Distance " << fMinimumDistanceForRiseTimeFit/
m <<
" m\n"
155 <<
"\tMaximum Distance " << fMaximumDistanceForRiseTimeFit/
m <<
" m\n"
156 <<
"\tRisetime Distance " << fDistanceToInterpolateFitResult/
m <<
" m\n";
158 risetimeFitB.GetChild(
"IncludeSaturated").GetData(fIncludeSaturatedForRiseTimeFit);
159 if (fIncludeSaturatedForRiseTimeFit)
160 info <<
"\tIncluding saturated stations.\n";
162 info <<
"\tNot including saturated stations.\n";
164 risetimeFitB.GetChild(
"WeightAsFunctionDistance").GetData(fRTWeightingFunction);
165 info <<
"\tWeighting Function: " << fRTWeightingFunction <<
'\n';
167 info <<
"Fitting the risetime for the event is disabled.\n";
169 fRTWeights =
new TFormula(
"RiseTimeWeights", fRTWeightingFunction.c_str());
170 if (fRTWeights->IsZombie()) {
172 err <<
"Weight formula defined in Risetime1000LLL.xml contains an error!\n"
173 "Current formula is: weight=" << fRTWeightingFunction <<
"\n"
174 "This formula does not conform to the ROOT formula class guidelines.";
177 fRTWeights =
nullptr;
182 topB.GetChild(
"UseDLECorrectedTrace").GetData(fUseDLECorrectedTrace);
184 if (fUseDLECorrectedTrace)
189 info <<
"***************************************\n"
190 "FADC Parameters module initialized.";
200 std::ostringstream info;
203 fgRisetimeError = -1;
204 fgRisetimeReducedChi2 = -1;
205 delete fgRisetimeResults;
206 fgRisetimeResults =
nullptr;
207 fRejectedStations = 0;
210 info <<
"There is no SEvent";
215 if (event.
HasRecShower() &&
event.GetRecShower().HasSRecShower()) {
217 const auto& sRecShower =
event.GetRecShower().GetSRecShower();
219 const auto& baryCS = sRecShower.GetBarycenterCoordinateSystem();
220 const double sec = 1 / sRecShower.GetAxis().GetCosTheta(baryCS);
236 const double alpha = 96.73 + sec*(-282.40 + sec*(241.80 - sec*62.61));
237 const double gamma = -0.0009572 + sec*(0.002068 + sec*(-0.001362 + sec*0.0002861));
241 auto& sEvent =
event.GetSEvent();
243 for (
auto& currentStation : sEvent.StationsRange()) {
244 if (!currentStation.HasVEMTrace(fComponent) || !currentStation.HasRecData())
247 unsigned short rejectCode = 0;
250 auto& sRecData = currentStation.GetRecData();
251 double stationRisetime = sRecData.GetRiseTime();
253 if (fForceRiseTimeRecalculation || stationRisetime <= 0)
254 stationRisetime = RecalculateRiseTime(currentStation);
256 if (stationRisetime <= 0)
259 const double stationDistance = sRecData.GetSPDistance();
260 const double stationDistanceError = sRecData.GetSPDistanceError();
261 const double g = alpha + gamma *
Sqr(stationDistance);
264 const double zeta = sRecData.GetAzimuthShowerPlane();
265 stationRisetime -= g * std::cos(zeta);
266 const double signal =
267 fUseDLECorrectedTrace ? sRecData.GetTotalSignalCleaned() : sRecData.GetTotalSignal();
269 const double stationRisetimeError = fRTWeights->Eval(stationDistance/
m, sec, signal);
271 if (signal < fMinimumSignalForRiseTimeFit)
273 if (!currentStation.IsCandidate())
275 if (!fIncludeSaturatedForRiseTimeFit && currentStation.IsLowGainSaturation())
277 if (stationDistance < fMinimumDistanceForRiseTimeFit || stationDistance > fMaximumDistanceForRiseTimeFit)
284 currentStationRisetimeData->
fStationId = currentStation.GetId();
285 currentStationRisetimeData->fCorrRisetime = stationRisetime;
286 currentStationRisetimeData->fCorrRisetimeError = stationRisetimeError;
287 currentStationRisetimeData->fDistance = stationDistance;
288 currentStationRisetimeData->fDistanceError = stationDistanceError;
289 currentStationRisetimeData->fRejectCode = rejectCode;
291 #ifdef DEBUG_Risetime1000LLL
293 info <<
"Station Id: " << currentStationRisetimeData->fStationId <<
"\n"
294 "Risetime: " << currentStationRisetimeData->fCorrRisetime <<
"\n"
295 "Risetime Error: " << currentStationRisetimeData->fCorrRisetimeError <<
"\n"
296 "Distance: " << currentStationRisetimeData->fDistance <<
"\n"
297 "DistanceError: " << currentStationRisetimeData->fDistanceError <<
"\n"
298 "RejectCode: " << currentStationRisetimeData->fRejectCode;
302 fgRisetimeResults->fStationData.push_back(currentStationRisetimeData);
303 sRecData.SetCorrectedRiseTime(currentStationRisetimeData->fCorrRisetime,
304 currentStationRisetimeData->fCorrRisetimeError);
305 sRecData.SetRiseTimeRejectionCode(currentStationRisetimeData->fRejectCode);
308 info <<
"There is no surface reconstruction!\n"
309 "Need a core position and zenith angle before this module.";
314 if (fDoRiseTimeFit) {
318 info <<
"The RiseTime at " << fDistanceToInterpolateFitResult/
km
319 <<
" km is " << fgRisetime
320 <<
" +- " << fgRisetimeError
324 if (event.
HasRecShower() &&
event.GetRecShower().HasSRecShower()) {
325 auto& sRecData =
event.GetRecShower().GetSRecShower();
326 if (!sRecData.HasRiseTime1000())
327 sRecData.MakeRiseTime1000();
329 auto& risetime1000Data = sRecData.GetRiseTime1000();
330 risetime1000Data.SetRiseTime1000(fgRisetime, fgRisetimeError);
331 risetime1000Data.SetChi2Ndof(fgRisetimeResults->fRisetime1000Chi2,
332 fgRisetimeResults->fRisetime1000NDF);
333 risetime1000Data.SetAlphaBeta(fgRisetimeResults->fFitPar0,
334 fgRisetimeResults->fFitPar1);
335 risetime1000Data.SetXmax(fgRisetimeResults->fXmax,
336 fgRisetimeResults->fXmaxErrorUp,
337 fgRisetimeResults->fXmaxErrorDown);
358 Risetime1000LLL::FitEventRiseTime()
360 const unsigned int pointsInGraph = fgRisetimeResults->fStationData.size() - fRejectedStations;
364 if (pointsInGraph <= 2) {
365 INFO(
"Event risetime uncalculated due to an insuffiecent number of acceptable stations.");
369 vector<double> distances(pointsInGraph);
370 vector<double> distancesError(pointsInGraph);
371 vector<double> risetimes(pointsInGraph);
372 vector<double> risetimesError(pointsInGraph);
373 unsigned int point = 0;
375 for (
const auto s : fgRisetimeResults->fStationData) {
376 const auto& currentStation = *
s;
377 if (currentStation.fRejectCode)
380 distances[point] = currentStation.fDistance /
km;
381 distancesError[point] = currentStation.fDistanceError /
km;
382 risetimes[point] = currentStation.fCorrRisetime /
ns;
383 risetimesError[point] = currentStation.fCorrRisetimeError /
ns;
386 info <<
"Passed Cut: station " << currentStation.fStationId <<
", "
387 "distance " << distances[point] <<
" km, "
388 "risetime " << risetimes[point] <<
" ns";
395 info << pointsInGraph <<
" stations passed the cuts.";
398 TGraphErrors riseTimeGraph(pointsInGraph, &distances.front(), &risetimes.front(),
nullptr, &risetimesError.front());
399 riseTimeGraph.SetMarkerStyle(20);
400 riseTimeGraph.SetMarkerColor(2);
401 riseTimeGraph.SetLineColor(2);
402 riseTimeGraph.SetLineWidth(2);
403 TF1 risetimeFit(
"RisetimeFit",
"40+[0]*x+[1]*x*x",
404 fMinimumDistanceForRiseTimeFit/
km, fMaximumDistanceForRiseTimeFit/
km);
405 risetimeFit.SetParLimits(0, 0, 10000);
406 risetimeFit.SetParLimits(1, 0, 10000);
410 double risetime = -1;
411 double risetimeErr = -1;
412 double risetimeChi2 = -1;
413 double risetimeNDF = -1;
414 const int failed = riseTimeGraph.Fit(&risetimeFit,
"Q",
"", fMinimumDistanceForRiseTimeFit/
km, fMaximumDistanceForRiseTimeFit/
km);
416 risetime = risetimeFit.Eval(fDistanceToInterpolateFitResult/
km);
417 const auto fitter = TVirtualFitter::GetFitter();
418 const int nPar = fitter->GetNumberTotalParameters();
419 const TMatrixD covar(nPar, nPar, fitter->GetCovarianceMatrix());
421 const double rtcov = covar[0][1];
422 const double rtcov2 = covar[1][1];
423 const double rtcov1 = covar[0][0];
427 risetimeErr =
sqrt(rtcov2 + rtcov1 + 2*rtcov);
429 risetimeChi2 = risetimeFit.GetChisquare();
430 risetimeNDF = risetimeFit.GetNDF();
433 fgRisetime = risetime*
ns;
434 fgRisetimeError = risetimeErr*
ns;
435 fgRisetimeReducedChi2 = risetimeChi2 / risetimeNDF;
437 fgRisetimeResults->fFitPar0 = risetimeFit.GetParameter(0) *
m/
km;
438 fgRisetimeResults->fFitPar1 = risetimeFit.GetParameter(1) *
m/
km *
m/
km;
439 fgRisetimeResults->fRisetime1000 = risetime*
ns;
440 fgRisetimeResults->fRisetime1000Error = risetimeErr*
ns;
441 fgRisetimeResults->fRisetime1000Chi2 = risetimeChi2;
442 fgRisetimeResults->fRisetime1000NDF = risetimeNDF;
445 fgRisetimeResults->fXmax = -1;
446 fgRisetimeResults->fXmaxErrorUp = -1;
447 fgRisetimeResults->fXmaxErrorDown = -1;
458 const int stopBin = recData.GetSignalEndSlot();
459 if (startBin >= stopBin || startBin < 0 || startBin > 5000)
463 double totalRisetime = 0;
464 for (
const auto& currentPMT : station.PMTsRange()) {
465 if (!currentPMT.HasRecData() || !currentPMT.GetRecData().HasVEMTrace(fComponent))
469 const auto& pmtRec = currentPMT.GetRecData();
470 const auto& vemTrace = pmtRec.GetVEMTrace(fComponent);
471 const double risetimeStart =
472 TraceAlgorithm::TimeAtRelativeSignalX(vemTrace, startBin, stopBin, 100*fRiseTimeStartFraction);
473 const double risetimeStop =
474 TraceAlgorithm::TimeAtRelativeSignalX(vemTrace, startBin, stopBin, 100*fRiseTimeStopFraction);
476 const double diff = risetimeStop - risetimeStart;
477 totalRisetime += diff;
481 ERROR(
"Valid station, but no PMTRecData. Risetime recalculation failed!");
484 return totalRisetime / numPMTs;
constexpr T Sqr(const T &x)
total (shower and background)
bool HasRecShower() const
sevt::StationRecData & GetRecData()
Get station level reconstructed data.
#define INFO(message)
Macro for logging informational messages.
void Init()
Initialise the registry.
static const RiseTimeRejectionCode eNotCandidate
static const RiseTimeRejectionCode eLowSignal
class to hold data at Station level
static const RiseTimeRejectionCode eLowGainSaturated
unsigned int GetSignalStartSlot() const
Start time of the signal in time slots from beginning of trace.
signal after subtracting direct light (includes all particle sources).
ResultFlag
Flag returned by module methods to the RunController.
static const RiseTimeRejectionCode eNotInRing
#define ERROR(message)
Macro for logging error messages.