ShowerSizeFunction.cc
Go to the documentation of this file.
1 #include "ShowerSizeFunction.h"
3 #include "Utilities.h"
4 
5 #include <utl/AugerUnits.h>
6 #include <utl/Point.h>
7 #include <utl/EquationSolver.h>
8 #include <utl/Math.h>
9 #include <utl/AugerException.h>
10 
11 #include <tls/MuonProfile.h>
12 #include <tls/VTankResponse.h>
13 #include <tls/EMComponent.h>
14 
15 #include <limits>
16 
17 using namespace SdHorizontalReconstructionNS;
18 using namespace utl;
19 using namespace tls;
20 using namespace std;
21 
23  const StationList& list,
24  const SilentStationList& slist,
25  const AxisData& ad,
26  const ExternalGeometryData& gd)
27  : fType(eFull), fConfig(config), fList(list), fSList(slist), fExt(gd)
28 {
30  if (ad.fCov[eTheta] > 1e-8 && ad.fCov[ePhi] > 1e-8)
31  {
33  if (ad.fCov[eDistance] > 1e-8)
35  }
36 
37  for (size_t i = 0; i < fUseAxisCovariance; ++i)
38  {
39  fAxisPar[i] = ad.fPar[i];
40  for (size_t j = 0; j < fUseAxisCovariance; ++j)
41  fAxisInvCov[i][j] = ad.fCov(i, j);
42  }
43 
44  if (fUseAxisCovariance)
45  {
46  try {
47  InvertMatrix(fUseAxisCovariance, fAxisInvCov);
48  for (size_t i = 0; i < fUseAxisCovariance; ++i)
49  if (fAxisInvCov[i][i] <= 0) throw utl::DoesNotComputeException();
50  }
51  catch(const utl::DoesNotComputeException& e)
52  {
53  fUseAxisCovariance = 0;
54  }
55  }
56 }
57 
58 
59 double
60 ShowerSizeFunction::operator()(const std::vector<double>& pars)
61  const
62 {
63  for (size_t i = 0; i < 6; ++i)
64  if (std::isnan(pars[i]))
66 
67  const double n19 = pars[0];
68  const double coreX = pars[1]*km;
69  const double coreY = pars[2]*km;
70  const double theta0 = pars[3];
71  const double phi0 = pars[4];
72  const double distance0 = pars[5]*km;
73 
74  Point core, origin;
75  fConfig.GetShowerAxis(core, origin, coreX, coreY, theta0, phi0, distance0);
76 
77  double result = 0;
78 
79  const Vector axis = origin - core;
80 
81  const double theta = axis.GetTheta(fConfig.fBaryCS);
82  const double phi = axis.GetPhi(fConfig.fBaryCS);
83 
84  // station did trigger
85  for (StationList::const_iterator
86  sIt = fList.begin(),
87  sEnd = fList.end();
88  sIt != sEnd; ++sIt)
89  {
90  if (sIt->fRejected) continue;
91 
92  if (sIt->fSaturated)
93  {
94  if (sIt->fRecoveryErr > 0)
95  { // recovered station: assume Gaussian fluctuations and include recovery error
96  double mean, sigma;
97  Predict(mean, sigma, sIt->fPos, origin, n19, core, sIt->fRecoveryErr);
98  const double z = (sIt->fSignal - mean)/sigma;
99  result += 0.5*z*z;
100  }
101  else
102  { // non-recovered saturated station
103  if (fType == eFull)
104  {
105  // measured signal is lower limit to unknown actual signal
106  double xProj, yProj, rho, sTheta;
107  fConfig.LocalCoordinates(xProj, yProj, rho, sTheta, sIt->fPos, origin, core);
108  const double nMu =
109  n19 * fConfig.fMuonProfile->NMuon(xProj, yProj, theta, phi, 10*EeV);
110  const double ratioSEmSMu =
111  fConfig.fEMComponent->SignalRatio(xProj, yProj, n19, theta, phi);
112 
113  const double signalMu = sIt->fSignal/(1.0+ratioSEmSMu);
114  const double prob =
115  fConfig.fTankResponse->PoissonConvolvedCDF(signalMu, sTheta, rho, nMu, true);
116  result -= log(prob);
117  }
118  else
119  {
120  // use saturated signal as measured signal, assign huge error
121  double mean, sigma;
122  Predict(mean, sigma, sIt->fPos, origin, n19, core);
123  const double z = (sIt->fSignal - mean)/mean;
124  result += 0.5*z*z;
125  }
126  }
127  } // is saturated
128  else
129  { // non-saturated regular station with signal
130  if (fType == eFull)
131  {
133  (sIt->fSignal < fConfig.fSilentSignalThreshold))
134  {
135  // treat stations below assumed trigger threshold as non-triggering stations
136  double xProj, yProj, rho, sTheta;
137  fConfig.LocalCoordinates(xProj, yProj, rho, sTheta, sIt->fPos, origin, core);
138  const double nMu =
139  n19 * fConfig.fMuonProfile->NMuon(xProj, yProj, theta, phi, 10*EeV);
140  const double ratioSEmSMu =
141  fConfig.fEMComponent->SignalRatio(xProj, yProj, n19, theta, phi);
142  const double sThrMu = fConfig.fSilentSignalThreshold/(1.0+ratioSEmSMu);
143  const double prob =
144  fConfig.fTankResponse->PoissonConvolvedCDF(sThrMu, sTheta, rho, nMu, false);
145  result -= log(prob);
146  }
147  else
148  {
149  // probability of observing measured signal
150  double xProj, yProj, rho, sTheta;
151  fConfig.LocalCoordinates(xProj, yProj, rho, sTheta, sIt->fPos, origin, core);
152  const double nMu =
153  n19 * fConfig.fMuonProfile->NMuon(xProj, yProj, theta, phi, 10*EeV);
154  const double ratioSEmSMu =
155  fConfig.fEMComponent->SignalRatio(xProj, yProj, n19, theta, phi);
156 
157  const double signalMu = sIt->fSignal/(1.0+ratioSEmSMu);
158  const double prob =
159  fConfig.fTankResponse->PoissonConvolvedPDF(signalMu, sTheta, rho, nMu);
160  result -= log(prob);
161  }
162  }
163  else
164  {
165  // assume Gaussian fluctuations
166  double mean, sigma;
167  Predict(mean, sigma, sIt->fPos, origin, n19, core);
168  const double z = (sIt->fSignal - mean)/sigma;
169  result += 0.5*z*z;
170  }
171  } // regular station
172  } // loop over candidate stations
173 
174  // station did not trigger
175  for (SilentStationList::const_iterator
176  sIt = fSList.begin(),
177  sEnd = fSList.end();
178  sIt != sEnd; ++sIt)
179  {
180  if (fType == eFull)
181  {
182  // probability of nMu to produce a signal below the T2 trigger threshold
183  double xProj, yProj, rho, sTheta;
184  fConfig.LocalCoordinates(xProj, yProj, rho, sTheta, sIt->fPos, origin, core);
185  const double nMu =
186  n19 * fConfig.fMuonProfile->NMuon(xProj, yProj, theta, phi, 10*EeV);
187  const double ratioSEmSMu =
188  fConfig.fEMComponent->SignalRatio(xProj, yProj, n19, theta, phi);
189  const double sThrMu = fConfig.fSilentSignalThreshold/(1.0+ratioSEmSMu);
190  // probability of nMu to produce a signal below the T2 trigger threshold
191  const double prob =
192  fConfig.fTankResponse->PoissonConvolvedCDF(sThrMu, sTheta, rho, nMu, false);
193  result -= log(prob);
194  }
195  else
196  {
197  // assume Gaussian fluctuations, treat as if measured signal was zero
198  double mean, sigma;
199  Predict(mean, sigma, sIt->fPos, origin, n19, core);
200  const double z = mean/sigma;
201  result += 0.5*z*z;
202  }
203  } // loop over zero signal stations
204 
205  // axis may vary within its uncertainty
206  if (fUseAxisCovariance)
207  {
208  const double delta[3] = {
209  theta0 - fAxisPar[0],
210  phi0 - fAxisPar[1],
211  distance0 - fAxisPar[2]
212  };
213 
214  for (size_t i = 0; i < fUseAxisCovariance; ++i)
215  for (size_t j = 0; j < fUseAxisCovariance; ++j)
216  result += 0.5 * delta[i] * fAxisInvCov[i][j] * delta[j];
217  }
218 
219  // core and axis may vary within its external uncertainty
220  {
221  double delta[4];
222  delta[eCoreXExt] = coreX - fExt.fPar[eCoreXExt];
223  delta[eCoreYExt] = coreY - fExt.fPar[eCoreYExt];
224  delta[eThetaExt] = theta0 - fExt.fPar[eThetaExt];
225  delta[ePhiExt] = phi0 - fExt.fPar[ePhiExt];
226 
227  for (size_t i = 0; i < 4; ++i)
228  for (size_t j = 0; j < 4; ++j)
229  result += 0.5 * delta[i] * fExt.fInvCov[i][j] * delta[j];
230  }
231 
232  return result;
233 }
234 
235 
236 void
237 ShowerSizeFunction::Predict(double& meanSignal, double& sigmaSignal,
238  const Point& station,
239  const Point& origin,
240  const double n19,
241  const Point& core,
242  const double recoveryErr)
243  const
244 {
245  double xProj, yProj, rho, sTheta;
246  fConfig.LocalCoordinates(xProj, yProj, rho, sTheta, station, origin, core);
247 
248  const Vector axis = origin - core;
249 
250  const double theta = axis.GetTheta(fConfig.fBaryCS);
251  const double phi = axis.GetPhi(fConfig.fBaryCS);
252 
253  const double nMu =
254  n19 * fConfig.fMuonProfile->NMuon(xProj, yProj, theta, phi, 10*EeV);
255 
256  const double ratioSEmSMu =
257  fConfig.fEMComponent->SignalRatio(xProj, yProj, n19, theta, phi);
258 
259  fConfig.fTankResponse->PoissonConvolvedMeanAndStDev(meanSignal, sigmaSignal,
260  sTheta, rho, nMu);
261 
262  meanSignal *= (1 + ratioSEmSMu);
263  sigmaSignal *= (1 + ratioSEmSMu);
264  if (recoveryErr > 0)
265  sigmaSignal = sqrt(Sqr(sigmaSignal) + Sqr(recoveryErr));
266 }
double PoissonConvolvedCDF(const double sThreshold, const double theta, const double r, const double muons, const bool complement) const
constexpr T Sqr(const T &x)
Point object.
Definition: Point.h:32
double GetPhi(const CoordinateSystemPtr &coordinateSystem) const
azimuth (phi) angle in spherical and cylindrical coordinates
Definition: BasicVector.h:254
double GetTheta(const CoordinateSystemPtr &coordinateSystem) const
zenith (theta) angle in spherical coordinates
Definition: BasicVector.h:248
const double EeV
Definition: GalacticUnits.h:34
void Predict(double &meanSignal, double &sigmaSignal, const utl::Point &station, const utl::Point &origin, const double n19, const utl::Point &core, const double recoveryErr=0) const
void LocalCoordinates(double &xProjected, double &yProjected, double &rho, double &theta, const utl::Point &pos, const utl::Point &origin, const utl::Point &core) const
ShowerSizeFunction(const SdHorizontalReconstruction &config, const StationList &list, const SilentStationList &slist, const AxisData &ad, const ExternalGeometryData &gd)
#define max(a, b)
void InvertMatrix(const size_t n, AMatrix &a)
Invert A in place with Gauss-Jordan elimination and full pivoting.
const Data result[]
const double km
double operator()(const std::vector< double > &pars) const
void PoissonConvolvedMeanAndStDev(double &mean, double &stDev, const double theta, const double r, const double muons) const
Mean and standard deviation of signal, given an average number of muons (Poisson convolved).
void GetShowerAxis(utl::Point &core, utl::Point &origin, const double coreX, const double coreY, const double theta, const double phi, const double distance) const
std::vector< StationData > StationList
Definition: FitInterface.h:80
Base class for inconsistency/illogicality exceptions.
std::vector< SilentStationData > SilentStationList
Definition: FitInterface.h:79
Vector object.
Definition: Vector.h:30
double PoissonConvolvedPDF(const double signal, const double theta, const double r, const double muons) const
PDF of signal, given an average number of muons (Poisson convolved).
const SdHorizontalReconstruction & fConfig

, generated on Tue Sep 26 2023.