G/ChiZeroRegression.cc
Go to the documentation of this file.
1 #include "ChiZeroRegression.h"
2 
3 #include <utl/Point.h>
4 #include <utl/Vector.h>
5 #include <utl/CoordinateSystemPtr.h>
6 #include <utl/Transformation.h>
7 #include <utl/UTMPoint.h>
8 #include <fwk/LocalCoordinateSystem.h>
9 
10 #include <utl/PhysicalConstants.h>
11 #include <utl/PhysicalFunctions.h>
12 #include <fevt/Pixel.h>
13 #include <fevt/PixelRecData.h>
14 #include <fevt/Telescope.h>
15 #include <fevt/TelescopeRecData.h>
16 //#include <fevt/EyeRecData.h>
17 
18 #include <det/Detector.h>
19 #include <fdet/FDetector.h>
20 #include <fdet/Eye.h>
21 #include <fdet/Telescope.h>
22 #include <fdet/Pixel.h>
23 #include <utl/CoordinateSystemPtr.h>
24 #include <fdet/FTimeFitModel.h>
25 #include <atm/Atmosphere.h>
26 #include <atm/InclinedAtmosphericProfile.h>
27 #include <atm/ProfileResult.h>
28 #include <utl/ReferenceEllipsoid.h>
29 #include <TMinuit.h>
30 #include <TMath.h>
31 
32 #include <limits>
33 
34 #include "../../General/RecDataWriterNG/ConversionUtil.h"
35 
36 namespace FdProfileConstrainedGeometryFitPG {
37 
40 double ChiZeroRegression::fXmax = 0;
43 std::vector<double> ChiZeroRegression::times;
44 std::vector<double> ChiZeroRegression::timeErrs;
45 std::vector<double> ChiZeroRegression::chii;
46 std::vector<int> ChiZeroRegression::tels;
47 std::vector<int> ChiZeroRegression::pixids;
49 
50 void
51 ChiZeroRegression::SetRealAtm(bool realAtm, bool deex, bool emissionPointCorrection) {
52  fRealAtm = realAtm;
53  fDeex = deex;
54  fdet::FTimeFitModel::GetInstance().SetModel((fRealAtm && fDeex) ? (fdet::FTimeFitModel::eRealisticAtm) :
56  fEmissionPointCorrection = emissionPointCorrection;
57 }
58 
59 unsigned int
61 {
62  using namespace fevt;
63 
64  const EyeRecData& eyeRec = eye.GetRecData();
65  const fdet::FDetector& detFD = det::Detector::GetInstance().GetFDetector();
66  const unsigned int lastTel = detFD.GetEye(eyeRec.GetEyeId()).GetLastTelescopeId();
67  std::vector<unsigned int> nPix(lastTel, 0);
68 
69  for (EyeRecData::ConstPixelIterator pix = eyeRec.TimeFitPixelsBegin(),
70  end = eyeRec.TimeFitPixelsEnd(); pix != end; ++pix) {
71  nPix[pix->GetTelescopeId()-1]++;
72  }
73  unsigned int maxPix = 0;
74  for (unsigned int i=0; i<nPix.size(); i++) {
75  if (nPix[i] > maxPix) {
76  fTelId = i+1;
77  maxPix = nPix[i];
78  }
79  }
80 
81  fEyeId = eyeRec.GetEyeId();
82 
83  chii.resize(0);
84  times.resize(0);
85  timeErrs.resize(0);
86  tels.resize(0);
87  pixids.resize(0);
88 
89  for (EyeRecData::ConstPixelIterator pix = eyeRec.TimeFitPixelsBegin(),
90  end = eyeRec.TimeFitPixelsEnd(); pix != end; ++pix) {
91  const PixelRecData& pixRec = pix->GetRecData();
92  chii.push_back(pixRec.GetChi_i());
93  times.push_back(pixRec.GetT_i().GetNanoSecond());
94  timeErrs.push_back(pixRec.GetT_iError().GetInterval());
95  tels.push_back(pix->GetTelescopeId());
96  pixids.push_back(pix->GetId());
97  }
98 
99  const utl::Point telPos = detFD.GetEye(fEyeId).GetTelescope(fTelId).GetPosition();
101  if (eye.HasTelescope(fTelId) && eye.GetTelescope(fTelId).HasRecData()) {
104  }
105 
106  return fTelId;
107 }
108 
109 void
111  double& chi2,
112  double& rp,
113  double& t0,
114  double Xmax)
115  const
116 {
117  std::vector<double> xs;//(chii.size());
118  std::vector<double> ys;
119  std::vector<double> yerrs;
120 
121  double rpErr = 0.;
122  double t0Err = 0.;
123  for (unsigned int i = 0, n = chii.size(); i < n; ++i) {
124  if (tels[i] == fTelId) {
125  xs.push_back(tan(0.5*(chi0 - chii[i])));
126  ys.push_back(times[i]);
127  yerrs.push_back(timeErrs[i]);
128  }
129  }
130 
131  if (!fUseLightFlux) {
132  otoa::LinearFit(xs, ys, yerrs, t0, rp, chi2);
133  } else {
134  LinearFitErrors(xs, ys, yerrs, t0, t0Err, rp, rpErr, chi2);
135  }
136 
137  rp *= utl::kSpeedOfLight;
138  rpErr *= utl::kSpeedOfLight;
139 
140  fXmax = Xmax;
141 // if (fRealAtm)
142  MinuitFitErrors(chi0, t0, t0Err, rp, rpErr, chi2);
143 }
144 
145 void
147  double& chi2,
148  double& rp, double &rpErr,
149  double& t0, double &t0Err,
150  double Xmax)
151  const
152 {
153  std::vector<double> xs;//(chii.size());
154  std::vector<double> ys;
155  std::vector<double> yerrs;
156 
157  for (unsigned int i = 0, n = chii.size(); i < n; ++i) {
158  if (tels[i] == fTelId) {
159  xs.push_back(tan(0.5*(chi0 - chii[i])));
160  ys.push_back(times[i]);
161  yerrs.push_back(timeErrs[i]);
162  }
163  }
164 
165  LinearFitErrors(xs, ys, yerrs, t0, t0Err, rp, rpErr, chi2);
166  rp *= utl::kSpeedOfLight;
167  rpErr *= utl::kSpeedOfLight;
168 
169  fXmax = Xmax;
170 // if (fRealAtm)
171  MinuitFitErrors(chi0, t0, t0Err, rp, rpErr, chi2);
172 }
173 
174 void
175 ChiZeroRegression::MinuitFitFunc(int& /*npar*/, double* /*gin*/, double& f, double* par, int /*iflag*/)
176 {
177  using namespace utl;
178 
179  const double dirErr = 0.35*deg;
180 
181  double& Chi0 = par[0];
182  double& T0 = par[1];
183  double& Rp = par[2];
184  fdet::FTimeFitModel& timeFitModel = fdet::FTimeFitModel::GetInstance();
185 
186  const fdet::FDetector& detFD = det::Detector::GetInstance().GetFDetector();
187 
188  const Point telPos = detFD.GetEye(fEyeId).GetTelescope(fTelId).GetPosition();
190  const Vector sdp = Vector(1, fsdpTheta, fsdpPhi, telCS, Vector::kSpherical);
191  const Vector vertical(0,0,1, telCS);
192  const Vector horizontalInSDP = Normalized(Cross(sdp, vertical));
193 
194  const Transformation rot = Transformation::Rotation(-Chi0, sdp, telCS);
195  Vector axis = Normalized(rot*horizontalInSDP);
196 
197  const double coreDistance = Rp / sin(Chi0);
198  const Vector coreTelVec = coreDistance * horizontalInSDP;
199  const Point core = telPos + coreTelVec;
200  const Point P_in_tel = telPos + Normalized(Cross(sdp, axis))*Rp;
201 
202  //correction for shower LDF
203  try {
204  const atm::Atmosphere& atmo = det::Detector::GetInstance().GetAtmosphere();
205  atmo.InitSlantProfileModel(core, axis, 10*g/cm2);
206  const atm::ProfileResult& tempProfile = atmo.EvaluateTemperatureVsHeight();
207  const atm::ProfileResult& pressureProfile = atmo.EvaluatePressureVsHeight();
208  const atm::ProfileResult& slantDepthProfile = atmo.EvaluateSlantDepthVsDistance();
209  const ReferenceEllipsoid& wgs84 = ReferenceEllipsoid::GetWGS84();
210 
211  double logLikeSum = 0.;
212  double logLikeSumSDP = 0.;
213  for (int i = 0, n = chii.size(); i < n; ++i) {
214 
215  const fdet::Telescope& curTel = detFD.GetEye(fEyeId).GetTelescope(tels[i]);
216  const Point curtelPos = curTel.GetPosition();
217  const CoordinateSystemPtr curtelCS = fwk::LocalCoordinateSystem::Create(curtelPos);
218 
219  const Point core_in_curtel = core-axis*core.GetZ(curtelCS)/cos(axis.GetTheta(curtelCS));
220 
221  const Vector curtel_to_core = core_in_curtel-curtelPos;
222  double chi0_in_curtel = Angle(curtel_to_core, axis);
223  if (axis.GetTheta(curtelCS) > kPi/2.) {
224  chi0_in_curtel = -(kPi-chi0_in_curtel);
225  }
226  double rp_in_curtel = curtel_to_core.GetMag()*sin(chi0_in_curtel);
227  if (axis.GetTheta(curtelCS) > kPi/2.) {
228  rp_in_curtel *= -1.;
229  }
230  const utl::AxialVector SDP_in_curtel = Normalized(Cross(axis, curtel_to_core));
231 
232  const Point P_in_curtel = curtelPos + Normalized(Cross(SDP_in_curtel, axis))*rp_in_curtel;
233  const Vector Pt_to_Pct = P_in_curtel - P_in_tel;
234  const double t0_in_curtel = T0 + ((Pt_to_Pct*axis > 0.) ? -1. : 1.)*Pt_to_Pct.GetMag()/kSpeedOfLight;
235 
236  const Vector vertical_in_curtel(0,0,1, curtelCS);
237  const Vector horizontalInSDP_in_curtel = Normalized(Cross(SDP_in_curtel, vertical_in_curtel));
238 
239  const Vector pixelDirection = curTel.GetPixel(pixids[i]).GetDirection();
240  const Vector pixelDirInSDP = pixelDirection - (SDP_in_curtel * pixelDirection)*SDP_in_curtel;
241  const double pixelChi = Angle(pixelDirInSDP, horizontalInSDP_in_curtel);
242 
243  const double angleWithSDP = abs(kPiOnTwo - Angle(SDP_in_curtel, pixelDirection));
244 
245  const Point PointOnShower = P_in_curtel+axis*rp_in_curtel/tan(chi0_in_curtel-pixelChi);
246  const double cosLocalZenith =
247  axis.GetCosTheta(fwk::LocalCoordinateSystem::Create(UTMPoint(PointOnShower, wgs84)));
248  const double height = wgs84.PointToLatitudeLongitudeHeight(PointOnShower).get<2>();
249  const double pressure = pressureProfile.Y(height);
250  const double temperature = tempProfile.Y(height);
251  const double rMoliere = MoliereRadius(temperature, pressure, cosLocalZenith);
252  const Vector core_to_PoS = PointOnShower-core;
253  const double age = ShowerAge(slantDepthProfile.Y( ((core_to_PoS*axis > 0.) ? -1. : 1.) * core_to_PoS.GetMag() ),fXmax);
254  // parameters based on 3D CHERENKOV CORSIKA simulations at low energies (10^15-10^17 eV)
255  const double rcorr = InverseGoraCDF(0.9, age)*0.2954;
256  const double rMcor = rMoliere*rcorr;
257  double t_corr = (-rMcor/kSpeedOfLight*tan((chi0_in_curtel-pixelChi)/2.))+5.923*m/kSpeedOfLight;
258 
259  double ti_exp = timeFitModel.GetTimeAtAperture(t0_in_curtel, rp_in_curtel, chi0_in_curtel, pixelChi,
260  SDP_in_curtel.GetTheta(curtelCS), fEyeId, tels[i]) + (fEmissionPointCorrection ? t_corr : 0.);
261  logLikeSum += (-0.5*(2*kPi) - log(timeErrs[i]) - 0.5*pow( (times[i] - ti_exp)/timeErrs[i] , 2));
262  //SDP part
263  logLikeSumSDP += (-0.5*(2*kPi) - log(dirErr) - 0.5*pow(angleWithSDP/dirErr, 2));
264  }
265  logLikeSum += logLikeSumSDP;//*chii.size();
266  if (logLikeSum != 0) {
267  f = -2.*logLikeSum;
268  } else {
269  f = std::numeric_limits<double>::infinity();
270  }
271 
272  } catch (const std::exception&) {
273  f = std::numeric_limits<double>::infinity();
274  return;
275  }
276 }
277 
278 void
280  double& T0, double& T0err,
281  double& Rp, double& Rperr,
282  double& chi2) const
283 {
284  const int npar = 3;
285  TMinuit theMinuit(npar);
286  theMinuit.SetPrintLevel(-1);
287  theMinuit.SetFCN(ChiZeroRegression::MinuitFitFunc);
288  double arglist[npar];
289  int ierflag=0;
290  arglist[0] = 1;
291  arglist[1] = 1;
292  theMinuit.mnexcm("SET ERR", arglist,1,ierflag);
293  if (ierflag) ERROR("Minuit SET ERR failed");
294  static double vstart[npar];
295  static double step[npar];
296  vstart[0] = Chi0;
297  vstart[1] = T0;
298  vstart[2] = Rp;
299  step[0] = 0;
300  step[1] = 10;
301  step[2] = 10;
302  theMinuit.mnparm(0, "Chi0", vstart[0], step[0], 0,0,ierflag);
303  theMinuit.FixParameter(0);
304  theMinuit.mnparm(1, "T0", vstart[1], step[1], vstart[1]-300, vstart[1]+300.,ierflag); //hardcoded boundaries, should be optional in the future?
305  theMinuit.mnparm(2, "Rp", vstart[2], step[2], vstart[2]-300., vstart[2]+300.,ierflag);
306  arglist[0] = 3000; //maxcalls
307  arglist[1] = 1; //tolerance
308  theMinuit.mnexcm("MIGRAD", arglist, 2, ierflag);
309  if (ierflag) {
310  ERROR("Minuit MIGRAD failed");
311  }
312  theMinuit.GetParameter(1, T0, T0err);
313  theMinuit.GetParameter(2, Rp, Rperr);
314  chi2 = theMinuit.fAmin;
315 }
316 
317 void
318 ChiZeroRegression::LinearFitErrors(const std::vector<double>& x,
319  const std::vector<double>& y,
320  const std::vector<double>& ey,
321  double& a0, double& a0err,
322  double& a1, double& a1err,
323  double& chi2) const
324 {
325  double sw = 0;
326  double sx = 0;
327  double sxx = 0;
328  double sy = 0;
329  double sxy = 0;
330  double syy = 0;
331 
332  for (unsigned int i = 0; i<x.size(); ++i) {
333  if (ey[i] > 0) {
334  const double wi = 1.0 / (ey[i]*ey[i]);
335  sw += wi;
336  sx += wi * x[i];
337  sxx += wi * x[i] * x[i];
338  sy += wi * y[i];
339  sxy += wi * x[i] * y[i];
340  syy += wi * y[i] * y[i];
341  }
342  }
343 
344  const double dinv = 1.0/(sw*sxx - sx*sx);
345 
346  a0 = (sxx*sy - sx * sxy) * dinv;
347  a1 = (-sx*sy + sw * sxy) * dinv;
348  a0err = sqrt (sxx * dinv);
349  a1err = sqrt (sw * dinv);
350 
351  if (!fUseLightFlux) {
352  chi2 = syy - a0*sy - a1*sxy;
353  } else {
354  double logLikeSum = 0; //differs only by constant from chi2, but put in
355  for (unsigned int i = 0; i<x.size(); ++i) {
356  logLikeSum += (-0.5*log(ey[i]*ey[i]) - 0.5*pow( (y[i]-(a0+a1*x[i]))/ey[i] , 2));
357  }
358  chi2 = -2.*logLikeSum;
359  }
360 }
361 
362 } //namespace
Telescope & GetTelescope(const unsigned int telescopeId, const ComponentSelector::Status status=ComponentSelector::eHasData)
Retrieve Telescope by Id, throw exception if not existent.
Definition: FEvent/Eye.cc:57
AxialVector Cross(const Vector &l, const Vector &r)
Definition: OperationsAV.h:25
const utl::Vector & GetDirection() const
pointing direction of this pixel
double GetChi_i() const
Definition: PixelRecData.h:117
bool HasRecData() const
Top of the interface to Atmosphere information.
double InverseGoraCDF(const double fraction, const double age)
Point object.
Definition: Point.h:32
double Angle(const double theta1, const double phi1, const double theta2, const double phi2)
double GetPhi(const CoordinateSystemPtr &coordinateSystem) const
azimuth (phi) angle in spherical and cylindrical coordinates
Definition: BasicVector.h:254
void InitSlantProfileModel(const utl::Point &core, const utl::Vector &dir, const double deltaX) const
Fluorescence Detector Eye Event.
Definition: FEvent/Eye.h:29
double GetTheta(const CoordinateSystemPtr &coordinateSystem) const
zenith (theta) angle in spherical coordinates
Definition: BasicVector.h:248
Class to hold and convert a point in geodetic coordinates.
Definition: UTMPoint.h:40
const atm::ProfileResult & EvaluatePressureVsHeight() const
Tabulated function giving Y=air pressure as a function of X=height.
void LinearFitErrors(const std::vector< double > &x, const std::vector< double > &y, const std::vector< double > &ey, double &a0, double &a0err, double &a1, double &a1err, double &chi2) const
const unsigned int npar
Definition: UnivRec.h:75
const Eye & GetEye(const unsigned int eyeId) const
Find eye by numerical Id.
Definition: FDetector.cc:68
fevt::TelescopeRecData & GetRecData()
Reconstructed data for this telescope.
double pow(const double x, const unsigned int i)
double GetMag() const
Definition: Vector.h:58
void SetRealAtm(bool realAtm, bool deex, bool emissionPointCorrection)
Detector description interface for FDetector-related data.
Definition: FDetector.h:44
double Y(const double x) const
Get the Y value (coordinate) for given X (ordinate)
boost::indirect_iterator< ConstInternalPixelIterator, const Pixel & > ConstPixelIterator
Const iterator over pixels used in reconstruction.
Definition: EyeRecData.h:117
const Pixel & GetPixel(const unsigned int pixelId) const
Get Pixel by id, throw utl::NonExistentComponentException if n.a.
constexpr double deg
Definition: AugerUnits.h:140
boost::shared_ptr< const CoordinateTransformer > CoordinateSystemPtr
Shared pointer for coordinate systems.
Reference ellipsoids for UTM transformations.
double MoliereRadius(double temperature, double pressure, const double cosTheta)
The Moliere Radius (2 radiation length above obs-level, GAP-1998-002)
Class describing the Atmospheric profile.
Definition: ProfileResult.h:25
utl::TimeInterval GetT_i() const
Definition: PixelRecData.h:124
constexpr double kPi
Definition: MathConstants.h:24
double abs(const SVector< n, T > &v)
Active transformations of geometrical objects.
Triple PointToLatitudeLongitudeHeight(const Point &thePoint) const
Convert Point to Lat/Long/Height.
constexpr double kPiOnTwo
Definition: MathConstants.h:25
constexpr double g
Definition: AugerUnits.h:200
Eye-specific shower reconstruction data.
Definition: EyeRecData.h:65
AxialVector Normalized(const AxialVector &v)
Definition: AxialVector.h:81
double GetInterval() const
Get the time interval as a double (in Auger base units)
Definition: TimeInterval.h:69
void MinuitFitErrors(const double Chi0, double &T0, double &T0err, double &Rp, double &Rperr, double &chi2) const
constexpr double kSpeedOfLight
Detector description interface for Telescope-related data.
double ShowerAge(const double slantDepth, const double showerMax)
General definition of shower age.
static void MinuitFitFunc(int &npar, double *gin, double &f, double *par, int iflag)
bool HasTelescope(const unsigned int telescopeId, const ComponentSelector::Status status=ComponentSelector::eHasData) const
Check if the telescope is in the event.
Definition: FEvent/Eye.cc:117
utl::Point GetPosition() const
Vector object.
Definition: Vector.h:30
utl::TimeInterval GetT_iError() const
Definition: PixelRecData.h:125
AxialVector object.
Definition: AxialVector.h:30
double GetZ(const CoordinateSystemPtr &coordinateSystem) const
Definition: BasicVector.h:212
void LinearFit(const vector< double > &x, const vector< double > &y, const vector< double > &ey, double &a0, double &a1, double &chi2)
Do a linear fit and return coefficients and chi2.
double GetNanoSecond() const
Get integer number of nanoseconds past seconds boundary.
Definition: TimeInterval.cc:25
static Policy::type Create(const utl::Point &theOrigin)
Create the standard local coordinate system for a Point.
const utl::AxialVector & GetSDP() const
const atm::ProfileResult & EvaluateSlantDepthVsDistance() const
#define ERROR(message)
Macro for logging error messages.
Definition: ErrorLogger.h:165
constexpr double m
Definition: AugerUnits.h:121
Fluorescence Detector Pixel Reconstructed Data.
Definition: PixelRecData.h:27
void operator()(const double chi0, double &chi2, double &rp, double &t0, double Xmax=600 *utl::g/utl::cm2) const
const atm::ProfileResult & EvaluateTemperatureVsHeight() const
Tabulated function giving Y=temperature as a function of X=height.
constexpr double cm2
Definition: AugerUnits.h:118
fevt::EyeRecData & GetRecData()
Reconstructed data for this eye.
Definition: FEvent/Eye.cc:130

, generated on Tue Sep 26 2023.