SdMonteCarloPropagator.cc
Go to the documentation of this file.
1 
9 #include <cmath>
10 #include <iostream>
11 #include <iomanip>
12 
13 #include <Eigen/Core>
14 #include <Eigen/LU>
15 #include <Eigen/Cholesky>
16 
17 #include <time.h>
18 
19 #include <evt/Event.h>
20 #include <sevt/SEvent.h>
21 #include <sevt/Header.h>
22 #include <evt/ShowerRecData.h>
23 #include <evt/ShowerSRecData.h>
24 #include <fwk/VModule.h>
25 #include <fwk/CentralConfig.h>
26 #include <utl/ErrorLogger.h>
27 #include <utl/Is.h>
28 
29 // #include <fwk/RandomEngineRegistry.h>
30 #include <fwk/LocalCoordinateSystem.h>
31 #include <utl/CoordinateSystemPtr.h>
32 // #include <CLHEP/Random/RandGauss.h>
33 // #include <CLHEP/Random/Randomize.h>
34 
35 #include <boost/random.hpp>
36 #include <boost/random/normal_distribution.hpp>
37 
38 #include "SdMonteCarloPropagator.h"
39 
40 using namespace sevt;
41 using namespace evt;
42 using namespace std;
43 using namespace utl;
44 using namespace fwk;
45 using namespace std;
46 using namespace Eigen;
47 
48 #define OUT(x) if ((x) <= fInfoLevel) cerr << " "
49 
50 
51 namespace SdMonteCarloPropagatorKVI {
52 
53  // typedef CLHEP::RandGauss RandGauss;
54 
55 
57  eBeta = 0,
58  eGamma = 1,
59  eXCore = 2,
60  eYCore = 3,
63  eUv = 6,
64  eVv = 7,
65  eCoreTime = 8, // Last!
66  };
67 
68 
69  const int kNumParameters = eCoreTime + 1;
70 
71 
72  typedef Matrix<double, kNumParameters, kNumParameters> MatrixmNxNd;
73  typedef Matrix<double, kNumParameters, 1> VectorNd;
74  typedef Transpositions<kNumParameters, kNumParameters, int> TranspositionmNxNd;
75 
76 
79  {
80  auto topB = CentralConfig::GetInstance()->GetTopBranch("SdMonteCarloPropagator");
81 
82  topB.GetChild("infoLevel").GetData(fInfoLevel);
83  topB.GetChild("randomSeed").GetData(fRandomSeed);
84  // fRandomEngine = &RandomEngineRegistry::GetInstance().Get(RandomEngineRegistry::eDetector);
85 
86  return eSuccess;
87  }
88 
89 
90  const int trillion = 1000000000; // Workaround for nanoseconds
91 
93 
94 
96  SdMonteCarloPropagator::Run(evt::Event& event)
97  {
98  INFO("SdMonteCarloPropagator::Run()");
99 
100  // if the old event was stored then replace the event with the old event
101  // this should happen on every second call of the SdMonteCarloPropagator
102  if (originalEvent) {
103  OUT(1) << "Restoring the original event." << endl;
104  event = *originalEvent;
105  delete originalEvent;
106  originalEvent = nullptr;
107  return eSuccess;
108  }
109 
110  // Change the event ids in order to keep track of the original and the varied parameters
111  int sEventId = event.GetSEvent().GetHeader().GetId();
112  auto eventId = event.GetHeader().GetId();
113  bool finishEarly = false;
114  if (Is("_original").NotIn(eventId) && Is("_varied").NotIn(eventId)) {
115  eventId += string("_original");
116  finishEarly = true;
117  } else {
118  const auto originalStart = eventId.find("_original");
119  unsigned int newNum = 0;
120  if (originalStart == string::npos) {
121  newNum = atoi(eventId.substr(eventId.length()-4).c_str()) + 1;
122  sEventId += 1;
123  } else {
124  eventId = eventId.substr(0, originalStart) + "_varied0000";
125  sEventId *= 100;
126  }
127  eventId = eventId.substr(0, eventId.length()-4);
128  ostringstream numOut;
129  numOut << eventId << setfill('0') << setw(4) << newNum;
130  eventId = numOut.str();
131  }
132  event.GetHeader().SetId(eventId);
133  event.GetSEvent().GetHeader().SetId(sEventId);
134  ShowerSRecData& recShower = event.GetRecShower().GetSRecShower();
135 
136  // Saving the old event
137  originalEvent = new evt::Event(event);
138 
139  if (finishEarly) {
140  // Do nothing but re-seed and return in order to keep the original parameters as well
141  if (fRandomSeed) {
142  OUT(2) << "Seeding the random generator with " << sEventId*fRandomSeed << endl;
143  fRandgen.seed(sEventId*fRandomSeed);
144  }
145  return eSuccess;
146  }
147 
148  // Not sure about how to use the random engine.
149  // Can't get the wrapped registry stuff to work if I want to
150  // have the option to seed it.
151  // CLHEP::HepRandomEngine &randomEngine = fRandomEngine->GetEngine();
152  // if (fRandomSeed) {
153  // randomEngine.setSeed(sEventId*fRandomSeed, 0);
154  // }
155  // Instead I will use the Mersenne twister from boost (for now)
156 
157  MatrixmNxNd covarianceMatrix; // Will contain the variances and covariances
158 
159  // Setting all elements to zero
160  for (int i = 0; i < kNumParameters; ++i) {
161  for (int j = 0; j < kNumParameters; ++j) {
162  covarianceMatrix(i, j) = 0;
163  }
164  }
165 
166  VectorNd origParameters; // Will store the originally reconstructed primary shower parameters
167  VectorNd variedParameters; // Will store the varied primary shower parameters
168  VectorNd randomShiftInParameters; // Will contain random gaussian values
169 
170  const CoordinateSystemPtr gBaryCS = LocalCoordinateSystem::Create(recShower.GetBarycenter());
171 
172  if (!recShower.HasParameter(eShowerAxisX) and !recShower.HasParameter(eShowerAxisY)) {
173  WARNING("There is no shower axis available! Sorry, I can't proceed with this event...");
174  return eBreakLoop;
175  }
176 
177  // Store original primary parameters into a vector
178  origParameters(eBeta) = recShower.GetBeta();
179  origParameters(eGamma) = recShower.GetGamma();
180  const auto& core = recShower.GetCorePosition();
181  origParameters(eXCore) = core.GetX(gBaryCS);
182  origParameters(eYCore) = core.GetY(gBaryCS);
183  origParameters(eCurvature) = recShower.GetCurvature();
184  origParameters(eShowerSize) = recShower.GetShowerSize();
185  origParameters(eUv) = recShower.GetParameter(eShowerAxisX);
186  origParameters(eVv) = recShower.GetParameter(eShowerAxisY);
187  // It is wrong that the time is stored in a non-floating point data-type. We'll try to work around this.
188  origParameters(eCoreTime) = recShower.GetCoreTime().GetGPSNanoSecond();
189  const unsigned coreTimeSeconds = recShower.GetCoreTime().GetGPSSecond();
190 
191  // Storing variances into the covariance matrix
192  covarianceMatrix(eBeta, eBeta) = Sqr(recShower.GetBetaError());
193  covarianceMatrix(eGamma, eGamma) = Sqr(recShower.GetGammaError());
194  const auto& coreError = recShower.GetCoreError();
195  covarianceMatrix(eXCore, eXCore) = Sqr(coreError.GetX(gBaryCS));
196  covarianceMatrix(eYCore, eYCore) = Sqr(coreError.GetY(gBaryCS));
197  covarianceMatrix(eCurvature, eCurvature) = Sqr(recShower.GetCurvatureError());
198  covarianceMatrix(eShowerSize, eShowerSize) = Sqr(recShower.GetShowerSizeError());
199  // The new ParameterStorage class does not use a coordinate system.
200  covarianceMatrix(eUv, eUv) = recShower.GetParameterCovariance(eShowerAxisX, eShowerAxisX);
201  covarianceMatrix(eVv, eVv) = recShower.GetParameterCovariance(eShowerAxisY, eShowerAxisY);
202  // Workaround for core time, converting from int to float
203  covarianceMatrix(eCoreTime, eCoreTime) = Sqr(recShower.GetCoreTimeError().GetInterval()/ns);
204 
205  // Storing covariances into the covariance matrix is done below
206  // N.B. Not all covariances are implemented. E.g. the covariances between the core time and the core
207  // position are not available). This is wrong. Future versions of offline should contain all relevant
208  // covariances and this module should implement these as well.
209 
210  // The core error is stored in a datatype that is coordinate system free
211  const double xCoreErr = recShower.GetCoreError().GetX(gBaryCS);
212  const double yCoreErr = recShower.GetCoreError().GetY(gBaryCS);
213  // The correlation of the error however is stored with an implicit coordinate system.
214  // This is not in accordance with the 'philosophy' of OffLine
215  // Carefull! Implicit assumption that the coordinate system is gBaryCS!!!!!
216  const double xyCoreCov = recShower.GetCorrelationXY() * xCoreErr * yCoreErr;
217  // The same comments hold here for the covariances between U and V, these are stored with the implicit gBaryCS in mind!
218  // Carefull! Implicit assumption that the coordinate system is gBaryCS!!!!!
219  const double uvCov = recShower.GetParameterCovariance(eShowerAxisX, eShowerAxisY);
220  covarianceMatrix(eUv, eVv) = covarianceMatrix(eVv, eUv) = uvCov;
221  covarianceMatrix(eXCore, eYCore) = covarianceMatrix(eYCore, eXCore) = xyCoreCov;
222 
223  OUT(2) << "Testing errorpropagator " << sEventId << endl;
224  OUT(2) << "Original parameters:" << endl;
225  OUT(2) << origParameters << endl;
226  OUT(2) << "Covariance matrix:" << endl;
227  OUT(2) << covarianceMatrix << endl;
228 
229  Eigen::LDLT<MatrixmNxNd> ldlt(covarianceMatrix);
230  // Testing wether the covariance matrix is positive semidefinite
231  // The isPositive() function is a bit misleading, isNonNegative() would have been better (or simply isPositiveSemiDefinite())
232  if (!ldlt.isPositive()) {
233  ERROR("Covariance matrix not positive (semi)definite! "
234  "You are the weakest link, good bye! "
235  "(by the way this should definitely not be happening. "
236  "Beter make sure that the SD reconstruction is ok...)");
237  return eBreakLoop;
238  }
239 
240  // The variables below will have to satisfy
241  // covarianceMatrix == P^T L D L^T P (see eigen3 documentation on LDLT decomposition)
242  MatrixmNxNd cML(ldlt.matrixL()); // lower triangular matrix L
243  TranspositionmNxNd cMP(ldlt.transpositionsP()); // permutation matrix P
244  VectorNd cMD(ldlt.vectorD()); // diagonal matrix D (represented as a vector)
245 
246  // Calculating the conventional square roots of the diagonals and putting them into a real matrix
247  MatrixmNxNd cMDSqrt;
248  cMDSqrt.setZero();
249  for (int i = 0; i < kNumParameters; ++i)
250  cMDSqrt(i, i) = sqrt(cMD(i));
251 
252  // Calculating the 'square root' of the covariance matrix
253  MatrixmNxNd covarianceMatrixSqrt = cMP.transpose() * cML * cMDSqrt;
254 
255  // Testing wether covarianceMatrix == covarianceMatrixSqrt * covarianceMatrixSqrt.transpose()
256  OUT(2) << "Testing wether the 'square root' of the covariance matrix is correctly computed... " << endl;
257  if (!(covarianceMatrixSqrt * covarianceMatrixSqrt.transpose()).isApprox(covarianceMatrix, 1e-12) ) {
258  ERROR("The test for the sanity of the covariance matrix failed! This should not be happening.");
259  return eBreakLoop;
260  }
261 
262  VectorNd randomGaussianValues; // Will contain random gaussian values with mu=0 and sigma=1
263  for (int i = 0; i < kNumParameters; ++i)
264  randomGaussianValues(i) = fRandomGenerator();
265 
266  randomShiftInParameters = covarianceMatrixSqrt * randomGaussianValues;
267  variedParameters = origParameters + randomShiftInParameters;
268 
269  // Put the varied data back into the shower parameters...
270  recShower.SetBeta(variedParameters(eBeta), recShower.GetBetaError()); // beta Is stored into varied data structure
271  recShower.SetGamma(variedParameters(eGamma), recShower.GetGammaError()); // gamma Is stored into varied data structure
272  const double variedXCore = variedParameters(eXCore); // put XCore in separate variable
273  const double variedYCore = variedParameters(eYCore); // put YCore in separate variable
274  const double variedZcore = core.GetZ(gBaryCS); // store unaltered ZCore in separate variable
275  recShower.SetCorePosition(utl::Point(variedXCore, variedYCore, variedZcore, gBaryCS)); // core position is stored into varied data structure
276  recShower.SetCurvature(variedParameters(eCurvature), recShower.GetCurvatureError()); // curvature is stored into varied data structure
277  recShower.SetShowerSize(variedParameters(eShowerSize), recShower.GetShowerSizeError()); // ShowerSize is stored into varied data structure
278  recShower.SetParameter(eShowerAxisX, variedParameters(eShowerAxisX)); // U is stored into varied data structure
279  recShower.SetParameter(eShowerAxisY, variedParameters(eShowerAxisY)); // V is stored into varied data structure
280  // Originally the next lines were a workaround for faulty implemented nanoseconds in the core time
281  // Now that the nanoseconds have become floats we have to see wether this teeds to be removed or changed.
282  unsigned int variedSeconds = coreTimeSeconds;
283  unsigned int variedNanoSeconds = trillion + variedParameters(eCoreTime);
284  variedSeconds += variedNanoSeconds/trillion - 1;
285  variedNanoSeconds %= trillion;
286  const TimeStamp variedCoreTime(variedSeconds, variedNanoSeconds);
287  recShower.SetCoreTime(variedCoreTime, recShower.GetCoreTimeError()); // CoreTime is stored into varied data structure
288 
289  // Secondary shower parameters
290  // Re-calculate the varied axis based on U and V and the gBaryCS
291  const double axisU = variedParameters(eUv);
292  const double axisV = variedParameters(eVv);
293  const double axisW = sqrt(1 - Sqr(axisU) - Sqr(axisV));
294  recShower.SetAxis(utl::Vector(axisU, axisV, axisW, gBaryCS));
295 
296  // Re-calculate the energy based on the energy calculation of the LDFFinderKG::EnergyConversion::GetEnergy()
297  // The beautiful modularity of offline does not allow access to this function itself. Here we are forced to
298  // copy the relevant features of this function into this line. If the error calculation in this GetEnergy() function
299  // changes then this line below may give inconsistent results.
300  const double energyError = recShower.GetEnergyError();
301  recShower.SetEnergy(recShower.GetEnergy() * variedParameters(eShowerSize) / origParameters(eShowerSize), energyError);
302 
303  OUT(3) << "Varied parameters:\n" << variedParameters << endl;
304  OUT(1) << "Finished varying parametrs for EventID " << eventId << ", SEventID " << sEventId << endl;
305 
306  return eSuccess;
307  }
308 
309 }
Matrix< double, kNumParameters, 1 > VectorNd
double GetCorrelationXY() const
void SetCurvature(const double curvature, const double error)
gaussian curvature = 1 / Rc
double GetCurvatureError() const
void SetShowerSize(const double value, const double error)
constexpr T Sqr(const T &x)
Point object.
Definition: Point.h:32
Transpositions< kNumParameters, kNumParameters, int > TranspositionmNxNd
double GetCurvature() const
gaussian curvature = 1 / Rc
void SetBeta(const double beta, const double error)
IsProxy< T > Is(const T &x)
Definition: Is.h:46
Interface class to access to the SD Reconstruction of a Shower.
double GetBetaError() const
double GetParameterCovariance(const Parameter q1, const Parameter q2) const
const utl::Vector & GetCoreError() const
#define INFO(message)
Macro for logging informational messages.
Definition: ErrorLogger.h:161
double GetShowerSize() const
void Init()
Initialise the registry.
double GetEnergyError() const
A TimeStamp holds GPS second and nanosecond for some event.
Definition: TimeStamp.h:110
utl::CoordinateSystemPtr gBaryCS
double GetBeta() const
Matrix< double, kNumParameters, kNumParameters > MatrixmNxNd
boost::shared_ptr< const CoordinateTransformer > CoordinateSystemPtr
Shared pointer for coordinate systems.
double GetParameter(const Parameter q) const
void SetParameter(const Parameter q, const double param, const bool lock=true)
double GetX(const CoordinateSystemPtr &coordinateSystem) const
Definition: BasicVector.h:206
const double ns
const utl::TimeStamp & GetCoreTime() const
time when shower front passes through the core point
void SetAxis(const utl::Vector &axis)
const utl::Point & GetBarycenter() const
#define WARNING(message)
Macro for logging warning messages.
Definition: ErrorLogger.h:163
void SetCoreTime(const utl::TimeStamp &coreTime, const utl::TimeInterval &coreTimeErr)
double GetEnergy() const
double GetInterval() const
Get the time interval as a double (in Auger base units)
Definition: TimeInterval.h:69
#define OUT(x)
double GetY(const CoordinateSystemPtr &coordinateSystem) const
Definition: BasicVector.h:209
const utl::TimeInterval & GetCoreTimeError() const
double GetGammaError() const
bool HasParameter(const Parameter q) const
ResultFlag
Flag returned by module methods to the RunController.
Definition: VModule.h:60
unsigned long GetGPSSecond() const
GPS second.
Definition: TimeStamp.h:124
double GetGPSNanoSecond() const
GPS nanosecond.
Definition: TimeStamp.h:127
Vector object.
Definition: Vector.h:30
double GetShowerSizeError() const
const utl::Point & GetCorePosition() const
void SetCorePosition(const utl::Point &core)
void SetGamma(const double gamma, const double error)
void SetEnergy(const double energy, const double error)
#define ERROR(message)
Macro for logging error messages.
Definition: ErrorLogger.h:165
double GetGamma() const

, generated on Tue Sep 26 2023.