5 #include <utl/Vector.h>
6 #include <utl/CoordinateSystemPtr.h>
7 #include <utl/Transformation.h>
8 #include <utl/TimeInterval.h>
9 #include <utl/AugerUnits.h>
10 #include <utl/PhysicalConstants.h>
11 #include <utl/TabulatedFunctionErrors.h>
13 #include <fevt/FEvent.h>
15 #include <fevt/EyeRecData.h>
16 #include <fevt/EyeHeader.h>
17 #include <fevt/Pixel.h>
19 #include <fevt/Telescope.h>
20 #include <fevt/TelescopeRecData.h>
22 #include <det/Detector.h>
23 #include <fdet/FDetector.h>
26 #include <fwk/LocalCoordinateSystem.h>
27 #include <fwk/CentralConfig.h>
33 #include "../../General/RecDataWriterNG/ConversionUtil.h"
37 #define PCGF_DEBUGLOG(x) { cerr << "DEBUGLOG " << x << endl;}
44 namespace FdProfileConstrainedGeometryFit {
54 (apLightOption==
"eExternal") ? eExternal :
55 (apLightOption ==
"eInternal") ? eInternal : eCallForEach;
69 "\t apLightMethod is " << apLightOption <<
"\n"
70 "\t checkUnderground is " << (fCheckUnderground?
"on":
"off") <<
"\n"
71 "\t prescan is " << (fPrescan?
"on":
"off") <<
"\n"
72 "\t scanOnly is " << (fScanOnly?
"on":
"off") <<
"\n"
73 "\t scanStep: " << fScanStep/
degree <<
" deg\n"
74 "\t scanStart: " << fScanStart/
degree <<
" deg\n"
75 "\t scanStop: " << fScanStop/
degree <<
" deg\n"
76 "\t delZeroLightFlux is " << (fDelZeroFlux?
"on":
"off") <<
"\n"
77 "\t useLightFlux is " << (fUseLightFlux?
"on":
"off") <<
"\n"
78 "\t TimeFitModel is " << (fRealAtm?
"RealisticAtm":
"VacuumAtm") <<
"\n"
79 "\t TimeFitDeexcitation is " << (fDeex?
"on":
"off") <<
"\n";
82 if (fApLightMethod == eCallForEach) {
83 fApertureLightFinder.Init();
84 }
else if (fApLightMethod == eInternal) {
91 fProfileFit.SetUseLightFlux(fUseLightFlux);
97 PCGFitter::Underground(
const double chi0,
const Eye &eye)
99 if (!fCheckUnderground)
107 const double chii = pixRec.
GetChi_i();
109 if (sin(chi0 - chii) < 0) {
119 PCGFitter::operator()(
const vector<double>& par)
121 const double chi0 = par[0];
125 const double chi2 = CombinedChi2(chi0, rp, t0,
PCGFData::eFit,
true);
131 PCGFitter::CombinedChi2(
const double chi0,
double &rp,
double &t0,
135 const Eye& eye = *fEye;
139 chi0reg(chi0, chi2timing, rp, t0);
142 cout <<
"Chi0: " << chi0/
degree <<
"\t"
143 "Rp: " << rp/
m <<
"\t"
144 "T0: " << t0/
ns <<
"\t "
145 "Chi^2_t: " << chi2timing <<
"\n";
148 if (Underground(chi0, eye))
149 return numeric_limits<double>::infinity();
152 Eye& eyeCopy = CopyEye(eye, eventCopy);
154 FillParams(eyeCopy, chi0, rp, t0);
155 if (!AdjustGeometry(eyeCopy)) {
157 return numeric_limits<double>::infinity();
160 if (fApLightMethod == eCallForEach) {
161 const bool haveLight =
164 return numeric_limits<double>::infinity();
170 vector<double> phX, phXerr, phY, phYerr;
171 vector<double> bgX, bgXerr, bgY, bgYerr;
172 for (
unsigned int i = 0; i < photonTrace.
GetNPoints(); ++i) {
173 if ((photonTrace.
GetY(i)-photonTrace.
GetYErr(i)) > 0.) {
174 phX.push_back(photonTrace.
GetX(i));
175 phXerr.push_back(photonTrace.
GetXErr(i));
176 phY.push_back(photonTrace.
GetY(i));
177 phYerr.push_back(photonTrace.
GetYErr(i));
178 bgX.push_back(bgTrace.
GetX(i));
179 bgXerr.push_back(bgTrace.
GetXErr(i));
180 bgY.push_back(bgTrace.
GetY(i));
181 bgYerr.push_back(bgTrace.
GetYErr(i));
186 for (
unsigned int i = 0; i < phX.size(); ++i) {
187 photonTrace.
PushBack(phX[i], phXerr[i], phY[i], phYerr[i]);
188 bgTrace.
PushBack(bgX[i], bgXerr[i], bgY[i], bgYerr[i]);
195 if (!telIter->HasRecData())
continue;
200 vector<double> phX, phXerr, phY, phYerr;
201 vector<double> bgX, bgXerr, bgY, bgYerr;
202 for (
unsigned int i = 0; i < photonTrace.
GetNPoints(); ++i) {
203 if (photonTrace.
GetY(i)-photonTrace.
GetYErr(i) > 0.) {
204 phX.push_back(photonTrace.
GetX(i));
205 phXerr.push_back(photonTrace.
GetXErr(i));
206 phY.push_back(photonTrace.
GetY(i));
207 phYerr.push_back(photonTrace.
GetYErr(i));
208 bgX.push_back(bgTrace.
GetX(i));
209 bgXerr.push_back(bgTrace.
GetXErr(i));
210 bgY.push_back(bgTrace.
GetY(i));
211 bgYerr.push_back(bgTrace.
GetYErr(i));
216 for (
unsigned int i = 0; i < phX.size(); ++i) {
217 photonTrace.
PushBack(phX[i], phXerr[i], phY[i], phYerr[i]);
218 bgTrace.
PushBack(bgX[i], bgXerr[i], bgY[i], bgYerr[i]);
224 const double chi2profile = fProfileFit(eyeCopy);
225 const double constraint1 = fProfileFit.GetShapeConstraint1Chi2();
226 const double constraint2 = fProfileFit.GetShapeConstraint2Chi2();
227 const double constraint3 = fProfileFit.GetShapeConstraint3Chi2();
229 cout <<
"Chi^2_prof: " << chi2profile <<
", including constraints 1/2/3: " << constraint1 <<
"/" << constraint2 <<
"/" << constraint3 <<
'\n';
231 map<string, double> mapchi2;
232 mapchi2[
"time"] = chi2timing;
233 mapchi2[
"prof"] = chi2profile-constraint1-constraint2-constraint3;
234 mapchi2[
"constraint1"] = constraint1;
235 mapchi2[
"constraint2"] = constraint2;
236 mapchi2[
"constraint3"] = constraint3;
237 map<string, double> mapNDof;
238 mapNDof[
"time"] = chi0reg.
GetNDof();
239 mapNDof[
"prof"] = fProfileFit.GetNDof();
240 mapNDof[
"constraint1"] = 1;
241 mapNDof[
"constraint2"] = 1;
242 mapNDof[
"constraint3"] = 1;
243 fPCGFData.push_back(
PCGFData(chi0, rp, t0, status, mapchi2, mapNDof));
245 return chi2profile+chi2timing;
255 fProfileFit.SetFitterPars();
262 const double t0 = eyeRecData.
GetTZero();
264 const double rp = eyeRecData.
GetRp();
266 map<string, double> mapchi2;
268 map<string, double> mapNDof;
276 fPCGFData.push_back(
PCGFData(chi0, rp, t0, PCGFData::ePreFit, mapchi2, mapNDof));
289 fChi0Regression = &chi0reg;
292 Eye& eyeCopy1 = CopyEye(eye, eventCopy1);
294 if (fApLightMethod == eInternal) {
295 fApLight.SetStripMode(
true);
298 fProfileFit.UnSetFitterPars();
304 double from = fScanStart;
305 double to = fScanStop;
306 if ((fPrescan && !Prescan(fScanStep, from, to)) || !ScanChi0(eye, fScanStep, from, to)) {
307 fProfileFit.UnSetFitterPars();
313 chi0Par.
fValue = startchi0;
314 chi0Par.
fStep = 0.5*fScanStep;
319 double chi0 = startchi0;
320 double chi0Err = fScanStep;
322 double chi2timing = 0;
329 Eye& eyeCopy2 = CopyEye(eye, eventCopy2);
331 if (fApLightMethod == eInternal) {
332 chi0reg(chi0, chi2timing, rp, t0);
333 FillParams(eyeCopy2, chi0, rp, t0);
334 if (!AdjustGeometry(eyeCopy2)) {
335 fProfileFit.UnSetFitterPars();
338 fApLight.SetStripMode(
false);
341 fProfileFit.UnSetFitterPars();
350 ERROR (
"MIGRAD failed.");
351 fProfileFit.UnSetFitterPars();
355 const auto result = min.GetParameterAndError(0);
360 if (!ScanChi0(eye, 0.1*fScanStep, startchi0 - 3*fScanStep, startchi0 + 3*fScanStep)) {
361 fProfileFit.UnSetFitterPars();
368 if (std::isnan(chi0Err) || chi0Err > 90*
degree || chi0 < 5*degree || chi0 > 175*
degree) {
369 cerr <<
"FIT RESULT:\n\tchi0 = (" << chi0 / degree
370 <<
" +/- " << chi0Err / degree <<
") degree\n";
371 ERROR (
"Fit result not regarded sane.");
372 fProfileFit.UnSetFitterPars();
376 chi0reg(chi0, chi2timing, rp, rpErr, t0, t0Err);
379 info <<
"FIT RESULT:\n\tchi0 = (" << chi0 / degree
380 <<
" +/- " << chi0Err / degree <<
") degree\n"
381 <<
"\trp = ( " << rp /
km
382 <<
" +/- " << rpErr/
km <<
" ) km\n"
387 FillParams(eye, chi0, chi0Err, rp, rpErr, t0, t0Err);
392 CombinedChi2(chi0, rp, t0, PCGFData::eFinal,
true);
395 eyeRecWrite.
SetPCGF(fPCGFData);
398 fProfileFit.UnSetFitterPars();
405 PCGFitter::Prescan(
const double step,
double& from,
double& to)
408 const double bigstep = 4*step;
409 const double inf = numeric_limits<double>::infinity();
413 for ( ; ; from += bigstep) {
415 PCGF_DEBUGLOG(
"Pescan failed leave: All profile fits failed.");
419 if (CombinedChi2(from, rp, t0, PCGFData::eScan,
true) < inf) {
426 for ( ; ; to -= bigstep) {
428 PCGF_DEBUGLOG(
"Pescan failed leave: All profile fits failed backwards. This should not happen.");
432 if (CombinedChi2(to, rp, t0, PCGFData::eScan,
true) < inf) {
437 PCGF_DEBUGLOG(
"Prescan: chi^2 finite for chi0 from : "<< from <<
"\t to: " << to);
447 PCGFitter::ScanChi0(
Eye &eye,
const double step,
double from,
double to)
449 const double inf = numeric_limits<double>::infinity();
458 vector<double> chi0s;
459 vector<double> chi2s;
463 for (
double chi0 = from; chi0 <= to; chi0 += step) {
466 double chi2 = CombinedChi2(chi0, rp, t0, PCGFData::eScan,
true);
468 chi0s.push_back(chi0);
469 chi2s.push_back(chi2);
474 int min_i = TMath::LocMin(chi2s.size(), &chi2s[0]);
476 PCGF_DEBUGLOG(
"ScanChi0: min i:" << min_i <<
"\t size: " << chi2s.size());
479 if (!(chi2s[min_i] < inf)) {
480 PCGF_DEBUGLOG(
"ScanChi0 failed leave: All profile fits failed.");
500 while (chi2s[min_i] < tooMuch) {
501 vector<double> chi2s_trial(chi2s);
502 chi2s_trial[min_i] = tooMuch;
503 int min_i_trial1 = TMath::LocMin(chi2s_trial.size(), &chi2s_trial[0]);
504 chi2s_trial[min_i_trial1] = tooMuch;
505 int min_i_trial2 = TMath::LocMin(chi2s_trial.size(), &chi2s_trial[0]);
506 chi2s_trial[min_i_trial2] = tooMuch;
507 if (chi2s_trial[min_i-1] == tooMuch && chi2s_trial[min_i+1] == tooMuch) {
510 chi2s[min_i] = tooMuch;
511 min_i = TMath::LocMin(chi2s.size(), &chi2s[0]);
514 if (!(chi2s[min_i] < tooMuch)) {
528 double xmin = chi0s[min_i];
529 double ymin = chi2s[min_i];
536 for (
unsigned int i = 1; i < 5; ++i) {
538 unsigned int k = min_i + i;
539 if ((j > 0) && std::isfinite(chi2s[j]) && (chi2s[j] < tooMuch)) {
540 x.push_back(
std::abs(chi0s[j] - xmin));
541 y.push_back(((chi2s[j] - ymin) > 0) ?
sqrt(chi2s[j] - ymin) : 0.);
544 if (k < chi0s.size() && std::isfinite(chi2s[k]) && chi2s[k] < tooMuch) {
545 x.push_back(
abs(chi0s[k] - xmin));
546 y.push_back(((chi2s[k] - ymin) > 0) ?
sqrt(chi2s[k] - ymin) : 0.);
554 double chi0err = (b != 0) ? (1./b) : 90*
degree;
559 cout <<
"calculating result geometry\n";
566 cout <<
"chi0: " << chi0s[min_i]/
degree <<
" deg "
567 "rp: " << rps[min_i] /
meter <<
" m "
591 PCGFitter::FillParams(
Eye& eyeCopy,
592 const double chi0,
const double chi0Err,
593 const double rp,
const double rpErr,
594 const double t0,
const double t0Err)
600 eyeReco.
SetRp(rp, rpErr );
604 telIt != eyeCopy.
TelescopesEnd(ComponentSelector::eHasData); ++telIt) {
605 if (!telIt->HasRecData())
606 telIt->MakeRecData();
610 telRecData.
SetRp(rp,rpErr);
618 PCGFitter::FillParams(
Eye& eyeCopy,
629 PCGFitter::AdjustGeometry(
Eye& eyeCopy)
634 const double t0 = eyeRecData.
GetTZero();
636 const double rp = eyeRecData.
GetRp();
639 det::Detector::GetInstance().GetFDetector().GetEye(eyeCopy);
642 const double sdpPhi = eyeRecData.
GetSDP().
GetPhi(eyeCS);
644 const Vector sdp =
Vector(1, sdpTheta, sdpPhi, eyeCS, Vector::kSpherical);
645 const Vector vertical(0,0,1, eyeCS);
648 const Transformation rot = Transformation::Rotation(-chi0, sdp, eyeCS);
650 const double coreDistance = rp / sin(chi0);
651 const Vector coreEyeVec = coreDistance * horizontalInSDP;
653 const Point core = eyepos + coreEyeVec;
AxialVector Cross(const Vector &l, const Vector &r)
unsigned int GetId() const
unsigned int GetNPoints() const
void SetChiZero(const double chiZero, const double error)
bool HasLightFlux(const FdConstants::LightSource source=FdConstants::eTotal) const
Check that light profile for source /par source is present.
double GetPhi(const CoordinateSystemPtr &coordinateSystem) const
azimuth (phi) angle in spherical and cylindrical coordinates
Report success to RunController.
fevt::EyeHeader & GetHeader()
Header for this Eye Event.
Fluorescence Detector Eye Event.
void SetPCGF(const std::vector< PCGFData > &pcgf)
double GetTheta(const CoordinateSystemPtr &coordinateSystem) const
zenith (theta) angle in spherical coordinates
double GetChiZero() const
unsigned int GetNDof() const
void SetRealAtm(bool realAtm, bool deex)
void SetCorePosition(const utl::Point &core)
unsigned int GetTimeFitNDof() const
void SetTimeFitCorrelations(double rRpT0, double rRpChi0, double rChi0T0)
#define INFO(message)
Macro for logging informational messages.
void MakeEye(const unsigned int eyeId, const ComponentSelector::Status status=ComponentSelector::eHasData)
void SetRp(const double rp, const double error)
void Init()
Initialise the registry.
Detector description interface for Eye-related data.
Branch GetChild(const std::string &childName) const
Get child of this Branch by child name.
int Migrad(const int n=500)
double GetChiZeroError() const
boost::indirect_iterator< ConstInternalPixelIterator, const Pixel & > ConstPixelIterator
Const iterator over pixels used in reconstruction.
Exception for reporting variable out of valid range.
boost::shared_ptr< const CoordinateTransformer > CoordinateSystemPtr
Shared pointer for coordinate systems.
utl::TabulatedFunctionErrors & GetLightFlux(const FdConstants::LightSource source=fevt::FdConstants::eTotal)
Light flux at diaphragm, photons/m^2 versus time in ns.
Class representing a document branch.
const double & GetYErr(const unsigned int idx) const
void SetCoreTime(const utl::TimeStamp &coreTime, const utl::TimeInterval &coreTimeErr)
utl::CoordinateSystemPtr GetEyeCoordinateSystem() const
Returns the Eye Coordinate system.
TelescopeIterator TelescopesEnd()
first available tel of status eHasData (DEPRECATED)
bool HasLightFlux(const FdConstants::LightSource source=FdConstants::eTotal) const
Check that light profile for source /par source is present.
void SetAxis(const utl::Vector &axis)
double abs(const SVector< n, T > &v)
evt::ShowerFRecData & GetFRecShower()
Reconstructed shower info for this eye.
void SetChiZero(const double chiZero, const double error)
Telescope-specific shower reconstruction data.
boost::filter_iterator< ComponentSelector, AllTelescopeIterator > TelescopeIterator
selective Telescope iterators
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.
const double & GetXErr(const unsigned int idx) const
Eye-specific shower reconstruction data.
AxialVector Normalized(const AxialVector &v)
Eye & GetEye(const unsigned int eyeId, const ComponentSelector::Status status=ComponentSelector::eHasData)
return Eye by id
TelescopeIterator TelescopesBegin()
first available tel of status eHasData (DEPRECATED)
const double & GetY(const unsigned int idx) const
const utl::AxialVector & GetSDP() const
double GetTimeFitChiSquare() const
fevt::FEvent & GetFEvent()
A TimeInterval is used to represent time elapsed between two events.
void SetTZero(const double tzero, const double error)
static CentralConfig * GetInstance()
Use this the first time you get an instance of central configuration.
void SetTimeFitChiSquare(const double tfitChi2, const unsigned int ndof)
PixelIterator TimeFitPixelsEnd()
constexpr double kilometer
const double & GetX(const unsigned int idx) const
Interface class to access to Fluorescence reconstruction of a Shower.
void SetRp(const double rp, const double error)
void SetUseLightFlux(bool use=true)
void SetTZero(const double tzero, const double error)
utl::TabulatedFunctionErrors & GetLightFlux(const FdConstants::LightSource source=fevt::FdConstants::eTotal)
Light flux at diaphragm, photons/m^2 versus time in ns.
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.
static Policy::type Create(const utl::Point &theOrigin)
Create the standard local coordinate system for a Point.
PixelIterator TimeFitPixelsBegin()
#define ERROR(message)
Macro for logging error messages.
constexpr double microsecond
const utl::Point & GetCorePosition() const
Shower core as reconstructed by the FD or FD eye.
Fluorescence Detector Pixel Reconstructed Data.
const std::string & GetMessage() const
Retrieve the message from the exception.
utl::Point GetPosition() const
Eye position.
utl::Branch GetTopBranch(const std::string &id)
Get top branch for moduleConfigLink with given id (XML files)
fevt::EyeRecData & GetRecData()
Reconstructed data for this eye.
const utl::Vector & GetAxis() const
Shower Axis as reconstructed by the FD or FD eye.