G/PCGFitter.cc
Go to the documentation of this file.
1 #define DEBUG 1
2 #include "PCGFitter.h"
3 
4 #include <utl/Point.h>
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>
12 
13 #include <fevt/FEvent.h>
14 #include <fevt/Eye.h>
15 #include <fevt/EyeRecData.h>
16 #include <fevt/EyeHeader.h>
17 #include <fevt/Pixel.h>
18 
19 #include <fevt/Telescope.h>
20 #include <fevt/TelescopeRecData.h>
21 
22 #include <det/Detector.h>
23 #include <fdet/FDetector.h>
24 #include <fdet/Eye.h>
25 #include <fdet/Pixel.h>
26 
27 #include <fwk/LocalCoordinateSystem.h>
28 #include <fwk/CentralConfig.h>
29 #include <TMath.h>
30 
31 #include "ChiZeroRegression.h"
32 #include "ProfileChi2.h"
33 
34 #include "../../General/RecDataWriterNG/ConversionUtil.h"
35 
36 #include <limits>
37 
38 #define PCGF_DEBUGLOG(x) { cerr << "DEBUGLOG " << x << endl;}
39 
40 
41 using namespace std;
42 using namespace fevt;
43 using namespace utl;
44 
45 namespace FdProfileConstrainedGeometryFitPG {
46 
47 void
49 {
50  Branch topBranch = fwk::CentralConfig::GetInstance()->GetTopBranch("FdProfileConstrainedGeometryFitPG");
51 
52  string apLightOption;
53  topBranch.GetChild("apLightMethod").GetData(apLightOption);
54  fApLightMethod = (apLightOption=="eExternal") ?
55  eExternal :
56  (apLightOption=="eInternal")?
57  eInternal : eCallForEach;
58 
59  topBranch.GetChild("checkUnderground").GetData(fCheckUnderground);
60  topBranch.GetChild("prescan").GetData(fPrescan);
61  topBranch.GetChild("scanOnly").GetData(fScanOnly);
62  topBranch.GetChild("scanStep").GetData(fScanStep);
63  topBranch.GetChild("scanStart").GetData(fScanStart);
64  topBranch.GetChild("scanStop").GetData(fScanStop);
65  topBranch.GetChild("useLightFlux").GetData(fUseLightFlux);
66  topBranch.GetChild("skipNegativeT0").GetData(fSkipNegativeT0);
67  topBranch.GetChild("delZeroLightFlux").GetData(fDelZeroFlux);
68  topBranch.GetChild("TimeFitModel").GetData(fRealAtm);
69  topBranch.GetChild("TimeFitDeexcitation").GetData(fDeex);
70  topBranch.GetChild("emissionPointCorrection").GetData(fEmissionPointCorrection);
71  ostringstream info;
72  info << "\n"
73  "\t apLightMethod is " << apLightOption << "\n"
74  "\t checkUnderground is " << (fCheckUnderground?"on":"off") << "\n"
75  "\t prescan is " << (fPrescan?"on":"off") << "\n"
76  "\t scanOnly is " << (fScanOnly?"on":"off") << "\n"
77  "\t scanStep: " << fScanStep/degree << " deg\n"
78  "\t scanStart: " << fScanStart/degree << " deg\n"
79  "\t scanStop: " << fScanStop/degree << " deg\n"
80  "\t delZeroLightFlux is " << (fDelZeroFlux?"on":"off") << "\n"
81  "\t useLightFlux is " << (fUseLightFlux?"on":"off") << "\n"
82  "\t skipNegativeT0 is " << (fSkipNegativeT0?"on":"off") << "\n"
83  "\t emissionPointCorrection is " << (fEmissionPointCorrection?"on":"off") << "\n"
84  "\t TimeFitModel is " << (fRealAtm?"RealisticAtm":"VacuumAtm") << "\n"
85  "\t TimeFitDeexcitation is " << (fDeex?"on":"off") << "\n";
86  INFO(info);
87 
88  fPrecise = false;
89  if (fApLightMethod == eCallForEach) {
90  fApertureLightFinder.Init();
91  fPrecise = true;
92  } else if (fApLightMethod == eInternal) {
93  fApLight.Init();
94  }
95 
96  fProfileFit.Init();
97 
98  fProfileFit.SetUseLightFlux(fUseLightFlux);
99 }
100 
101 
102 inline
103 bool
104 PCGFitter::Underground(const double chi0, const double rp, const Eye &eye)
105 {
106  if (!fCheckUnderground)
107  return false;
108 
109  const EyeRecData& eyeRec = eye.GetRecData();
110 
111  const fdet::FDetector& detFD = det::Detector::GetInstance().GetFDetector();
112 
113  const Point telPos = detFD.GetEye(eye.GetId()).GetTelescope(fTelId).GetPosition();
115  const Vector sdp = eye.GetTelescope(fTelId).GetRecData().GetSDP();
116  const Vector vertical(0,0,1, telCS);
117  const Vector horizontalInSDP = Normalized(Cross(sdp, vertical));
118 
119  const Transformation rot = Transformation::Rotation(-chi0, sdp, telCS);
120  Vector axis = Normalized(rot*horizontalInSDP);
121 
122  const double coreDistance = rp / sin(chi0);
123  const Vector coreTelVec = coreDistance * horizontalInSDP;
124  const Point core = telPos + coreTelVec;
125 
127  end = eyeRec.TimeFitPixelsEnd(); pix != end; ++pix) {
128 
129  int telId = pix->GetTelescopeId();
130  //if (telId == fTelId) {
131 
132  const fdet::Telescope& curTel = detFD.GetEye(eye.GetId()).GetTelescope(telId);
133  const Point curtelPos = curTel.GetPosition();
134  const CoordinateSystemPtr curtelCS = fwk::LocalCoordinateSystem::Create(curtelPos);
135 
136  const Point core_in_curtel = core-axis*core.GetZ(curtelCS)/cos(axis.GetTheta(curtelCS));
137 
138  const Vector curtel_to_core = core_in_curtel-curtelPos;
139  double chi0_in_curtel = Angle(curtel_to_core, axis);
140  if (axis.GetTheta(curtelCS) > kPi/2.) {
141  chi0_in_curtel = -(kPi-chi0_in_curtel);
142  }
143  const utl::AxialVector SDP_in_curtel = Normalized(Cross(axis, curtel_to_core));
144 
145  const Vector vertical_in_curtel(0,0,1, curtelCS);
146  const Vector horizontalInSDP_in_curtel = Normalized(Cross(SDP_in_curtel, vertical_in_curtel));
147 
148  const Vector pixelDirection = curTel.GetPixel(pix->GetId()).GetDirection();
149  const Vector pixelDirInSDP = pixelDirection - (SDP_in_curtel * pixelDirection)*SDP_in_curtel;
150  const double chii = Angle(pixelDirInSDP, horizontalInSDP_in_curtel);
151  //following is too simple! - eyeCopy does not make new fevt::Pixel and in RecData only pointers are stored, this makes mess
152  //const PixelRecData& pixRec = pix->GetRecData();
153  //const double chii = pixRec.GetChi_i();
154 
155  //cout << "chii " << chii << " pixel " << (*pix).GetId() << " tel "<<telId<<" eye "<<eye.GetId()<<"\n";
156  if (sin(chi0_in_curtel - chii) < 0) {
157  PCGF_DEBUGLOG("Under ground");
158  return true;
159  }
160  //}
161  }
162  return false;
163 }
164 
165 
166 double
167 PCGFitter::operator()(const vector<double>& par)
168 {
169  const double chi0 = par[0];
170 
171  double rp = 0;
172  double t0 = 0;
173  double rpErr = 0;
174  double t0Err = 0;
175  const double chi2 = CombinedChi2(chi0, rp, rpErr, t0, t0Err, PCGFData::eFit, true);
176  return chi2;
177 }
178 
179 
180 double
181 PCGFitter::CombinedChi2(const double chi0, double &rp, double &rpErr, double &t0, double &t0Err,
182  const fevt::PCGFData::EPCGFStatus status,
183  const bool verbose)
184 {
185  const Eye& eye = (*fEye);
186 
187  //horizontal shower with undefined core
188  if (fabs(chi0-180*deg) < 1e-4*deg || fabs(chi0+180*deg) < 1e-4*deg || fabs(chi0-0*deg) < 1e-4*deg || fabs(chi0-360*deg) < 1e-4*deg)
189  return numeric_limits<double>::infinity();
190 
191  double chi2timing; // rp, t0;
192  const ChiZeroRegression& chi0reg = *fChi0Regression;
193  chi0reg(chi0, chi2timing, rp, t0);
194 
195  if (fSkipNegativeT0 && (t0 < 0))
196  return numeric_limits<double>::infinity();
197 
198  if (verbose)
199  cout << "Chi0: " << chi0/degree << "\t"
200  "Rp: " << rp/m << "\t"
201  "T0: " << t0/ns << "\t "
202  "Chi^2_t: " << chi2timing << "\n";
203 
204  //Check after regression: fill rp, t0 correctly anyway; probably never needed ...
205  if (Underground(chi0, rp, eye))
206  return numeric_limits<double>::infinity();
207 
208  evt::Event eventCopy;
209  Eye& eyeCopy = CopyEye(eye, eventCopy);
210 
211  FillParams(eyeCopy, chi0, rp, t0);
212  if (!AdjustGeometry(eyeCopy)) {
213  //ERROR("could not adjust geometry");
214  return numeric_limits<double>::infinity();
215  }
216 
217  if (fApLightMethod == eCallForEach) {
218  const bool haveLight =
219  fApertureLightFinder.Run(eventCopy) == fwk::VModule::eSuccess && eyeCopy.GetRecData().HasLightFlux();
220  if (!haveLight)
221  return numeric_limits<double>::infinity();
222 
223  if (fDelZeroFlux) {
224  //VN remove all light flux bins comatible with zero
227  vector<double> phX, phXerr, phY, phYerr;
228  vector<double> bgX, bgXerr, bgY, bgYerr;
229  for (unsigned int i = 0; i < photonTrace.GetNPoints(); ++i) {
230  if ((photonTrace.GetY(i)-photonTrace.GetYErr(i)) > 0.) {
231  phX.push_back(photonTrace.GetX(i));
232  phXerr.push_back(photonTrace.GetXErr(i));
233  phY.push_back(photonTrace.GetY(i));
234  phYerr.push_back(photonTrace.GetYErr(i));
235  bgX.push_back(bgTrace.GetX(i));
236  bgXerr.push_back(bgTrace.GetXErr(i));
237  bgY.push_back(bgTrace.GetY(i));
238  bgYerr.push_back(bgTrace.GetYErr(i));
239  }
240  }
241  photonTrace.Clear();
242  bgTrace.Clear();
243  for (unsigned int i = 0; i < phX.size(); ++i) {
244  photonTrace.PushBack(phX[i], phXerr[i], phY[i], phYerr[i]);
245  bgTrace.PushBack(bgX[i], bgXerr[i], bgY[i], bgYerr[i]);
246  }
247 
248  for (fevt::Eye::TelescopeIterator telIter =
251  ++telIter) {
252  if (!telIter->HasRecData()) continue;
253  TelescopeRecData& telRecData = telIter->GetRecData();
254  if (!telRecData.HasLightFlux()) continue;
257  vector<double> phX, phXerr, phY, phYerr;
258  vector<double> bgX, bgXerr, bgY, bgYerr;
259  for (unsigned int i = 0; i < photonTrace.GetNPoints(); ++i) {
260  if (photonTrace.GetY(i)-photonTrace.GetYErr(i) > 0.) {
261  phX.push_back(photonTrace.GetX(i));
262  phXerr.push_back(photonTrace.GetXErr(i));
263  phY.push_back(photonTrace.GetY(i));
264  phYerr.push_back(photonTrace.GetYErr(i));
265  bgX.push_back(bgTrace.GetX(i));
266  bgXerr.push_back(bgTrace.GetXErr(i));
267  bgY.push_back(bgTrace.GetY(i));
268  bgYerr.push_back(bgTrace.GetYErr(i));
269  }
270  }
271  photonTrace.Clear();
272  bgTrace.Clear();
273  for (unsigned int i = 0; i < phX.size(); ++i) {
274  photonTrace.PushBack(phX[i], phXerr[i], phY[i], phYerr[i]);
275  bgTrace.PushBack(bgX[i], bgXerr[i], bgY[i], bgYerr[i]);
276  }
277  }
278  }
279  }
280 
281  evt::Event eventCopy2;
282  Eye& eyeCopy2 = CopyEye(eyeCopy, eventCopy2);
283  if (std::isfinite(fProfileFit(eyeCopy2, fPrecise))) {
284  double Xmax = eyeCopy2.GetRecData().GetFRecShower().GetGHParameters().GetXMax();
285  chi0reg(chi0, chi2timing, rp, rpErr, t0, t0Err, Xmax);
286 
287  FillParams(eyeCopy, chi0, rp, t0);
288  if (!AdjustGeometry(eyeCopy)) {
289  return numeric_limits<double>::infinity();
290  }
291  }
292 
293  const double chi2profile = fProfileFit(eyeCopy, fPrecise);
294  const double constraint1 = fProfileFit.GetShapeConstraint1Chi2();
295  const double constraint2 = fProfileFit.GetShapeConstraint2Chi2();
296  const double constraint3 = fProfileFit.GetShapeConstraint3Chi2();
297  if (verbose) {
298  cout << "Chi^2_prof: " << chi2profile << ", including constraints 1/2/3: " << constraint1 << "/" << constraint2 << "/" << constraint3 << '\n';
299  if (fEmissionPointCorrection)
300  cout << "Chi^2_time after emission point correction: " << chi2timing << '\n';
301  }
302 
303  map<string, double> mapchi2;
304  mapchi2["time"] = chi2timing;
305  mapchi2["prof"] = chi2profile-constraint1-constraint2-constraint3;//sqrt(pow(chi2profile,2) - pow(constraint1,2) - pow(constraint2,2) - pow(constraint3,2) );
306  mapchi2["constraint1"] = constraint1;
307  mapchi2["constraint2"] = constraint2;
308  mapchi2["constraint3"] = constraint3;
309  map<string, double> mapNDof;
310  mapNDof["time"] = chi0reg.GetNDof();
311  mapNDof["prof"] = fProfileFit.GetNDof();
312  mapNDof["constraint1"] = 1;
313  mapNDof["constraint2"] = 1;
314  mapNDof["constraint3"] = 1;
315  fPCGFData.push_back(PCGFData(chi0, rp, t0, status, mapchi2, mapNDof));
316 
317  return chi2profile+chi2timing;
318 }
319 
320 
321 bool
322 PCGFitter::Run(Eye &eye)
323 {
324  fEye = &eye;
325 
326  //VN to manage static fitter
327  fProfileFit.SetFitterPars();
328 
329  fPCGFData.clear();
330 
331  // keep initial value
332  {
333  const EyeRecData& eyeRecData = eye.GetRecData();
334  const double t0 = eyeRecData.GetTZero();
335  const double chi0 = eyeRecData.GetChiZero();
336  const double rp = eyeRecData.GetRp();
337 
338  map<string, double> mapchi2;
339  mapchi2["time"] = eyeRecData.GetTimeFitChiSquare();
340  map<string, double> mapNDof;
341  mapNDof["time"] = eyeRecData.GetTimeFitNDof();
342  // typically we have no profile fit at this stage...
343  /*
344  ShowerFRecData& recShower = eyeRecData.GetFRecShower();
345  mapchi2["prof"] = sqrt(recShower.GetGHParameters().GetChiSquare();
346  //recShower.GetGHParameters().GetNdof()) :
347  */
348  fPCGFData.push_back(PCGFData(chi0, rp, t0, PCGFData::ePreFit, mapchi2, mapNDof));
349  }
350 
351  ChiZeroRegression chi0reg(eye, fTelId);
352  if (fTelId == 0) {
353  return false;
354  }
355  chi0reg.SetUseLightFlux(fUseLightFlux);
356  chi0reg.SetRealAtm(fRealAtm, fDeex, fEmissionPointCorrection);
357  fChi0Regression = &chi0reg;
358 
359  // sim chi0 (for testing purposes)
360  /* double chi0, chi0Err, rp, rpErr, t0, t0Err, chi2timing;
361  chi0 = eye.GetTelescope(fTelId).GetRecData().GetChiZero();
362  chi0Err = 0.01*chi0;
363  CombinedChi2(chi0, rp, rpErr, t0, t0Err, PCGFData::eFit, true);
364  */
365 
366  evt::Event eventCopy1;
367  Eye& eyeCopy1 = CopyEye(eye, eventCopy1);
368 
369  if (fApLightMethod == eInternal) {
370  fApLight.SetStripMode(true);
371  const bool haveLight = fApLight.Run(eventCopy1) && eyeCopy1.GetRecData().HasLightFlux();
372  if (!haveLight) {
373  fProfileFit.UnSetFitterPars();
374  return false;
375  }
376  fEye = &eyeCopy1;
377  fPrecise = false;
378  }
379 
380  double from=fScanStart, to=fScanStop;
381  if ((fPrescan?(!Prescan(fScanStep, from, to)):false)
382  || !ScanChi0(eyeCopy1, fScanStep, from, to)) {
383  fProfileFit.UnSetFitterPars();
384  return false;
385  }
386  const double startchi0 = eyeCopy1.GetTelescope(fTelId).GetRecData().GetChiZero();
387  {
388  Minou::ParameterDef& chi0Par = GetParameterDefs()[0];
389  chi0Par.fValue = startchi0;
390  chi0Par.fStep = 0.5*fScanStep;
391  }
392 
393  // fChi0Regression = &chi0reg; //changed in scanchi0 -- this should be refactored
394 
395  double chi0 = startchi0;
396  double chi0Err = fScanStep;
397 
398  double rp = 0;
399  double rpErr = 0;
400  double t0 = 0;
401  double t0Err = 0;
402 
403  evt::Event eventCopy2;
404  Eye& eyeCopy2 = CopyEye(eye, eventCopy2);
405 
406  if (fApLightMethod == eInternal) {
407  CombinedChi2(chi0, rp, rpErr, t0, t0Err, PCGFData::eScan, false);
408  FillParams(eyeCopy2, chi0, rp, t0);
409  if (!AdjustGeometry(eyeCopy2)) {
410  fProfileFit.UnSetFitterPars();
411  return false;
412  }
413  fApLight.SetStripMode(false);
414  const bool haveLight = fApLight.Run(eventCopy2) && eyeCopy2.GetRecData().HasLightFlux();
415  if (!haveLight) {
416  fProfileFit.UnSetFitterPars();
417  return false;
418  }
419  fEye = &eyeCopy2;
420  fPrecise = true;
421  }
422 
423  if (!fScanOnly) {
424  Minou::Minimizer<PCGFitter> min(*this);
425  if (min.Migrad()) {
426  ERROR ("MIGRAD failed.");
427  fProfileFit.UnSetFitterPars();
428  return false;
429  }
430 
431  const auto result = min.GetParameterAndError(0);
432 
433  chi0 = result.first;
434  chi0Err = result.second;
435  } else {
436  if (!ScanChi0(eyeCopy2, fScanStep/10., startchi0-3*fScanStep, startchi0+3*fScanStep, 1)) {
437  fProfileFit.UnSetFitterPars();
438  return false;
439  }
440  chi0 = eyeCopy2.GetTelescope(fTelId).GetRecData().GetChiZero();
441  chi0Err = eyeCopy2.GetTelescope(fTelId).GetRecData().GetChiZeroError();
442  }
443 
444  if (std::isnan(chi0Err) || chi0Err > 180*degree /*||
445  chi0 < 5*degree || chi0 > 175*degree*/) {
446  cerr << "FIT RESULT:\n\tchi0 = (" << chi0 / degree
447  << " +/- " << chi0Err / degree << ") degree\n";
448  ERROR ("Fit result not regarded sane.");
449  fProfileFit.UnSetFitterPars();
450  return false;
451  }
452 
453  CombinedChi2(chi0, rp, rpErr, t0, t0Err, PCGFData::eFinal, true);
454 
455  ostringstream info;
456  info << "FIT RESULT:\n\tchi0 = (" << chi0 / degree
457  << " +/- " << chi0Err / degree << ") degree\n"
458  << "\trp = ( " << rp / km
459  << " +/- " << rpErr/km << " ) km\n"
460  << "\tt0 = ( " << t0 / microsecond
461  << " +/- " << t0Err / microsecond << " ) us";
462  INFO(info);
463 
464  FillParams(eye, chi0, chi0Err, rp, rpErr, t0, t0Err);
465  AdjustGeometry(eye);
466 
467  // fill the PCGF data
468  {
469  CombinedChi2(chi0, rp, rpErr, t0, t0Err, PCGFData::eFinal, true);
470 
471  EyeRecData& eyeRecWrite = eye.GetRecData();
472  eyeRecWrite.SetPCGF(fPCGFData);
473  }
474 
475  fProfileFit.UnSetFitterPars();
476 
477  return true;
478 }
479 
480 
481 bool
482 PCGFitter::Prescan(const double step, double &from, double &to){
483  //calling CombinedChi2, so fChi0Regression must be set
484  const double bigstep=4*step;
485  const double inf = numeric_limits<double>::infinity();
486 
487  double rp=0, t0=0, rpErr=0, t0Err=0;
488  for (;; from+=bigstep) {
489  if (from >= to) {
490  PCGF_DEBUGLOG("Pescan failed leave: All profile fits failed.");
491  return false;
492  }
493 
494  if (CombinedChi2(from, rp, rpErr, t0, t0Err, PCGFData::eScan, true) < inf) {
495  break;
496  }
497  }
498  //to be sure that we do not miss anything
499  from -= bigstep;
500 
501  for (;; to-=bigstep) {
502  if (from > to) {
503  PCGF_DEBUGLOG("Pescan failed leave: All profile fits failed backwards. This should not happen.");
504  return false;
505  }
506 
507  if (CombinedChi2(to, rp, rpErr, t0, t0Err, PCGFData::eScan, true) < inf) {
508  break;
509  }
510  }
511  to += bigstep;
512  PCGF_DEBUGLOG( "Prescan: chi^2 finite for chi0 from : "<< from << "\t to: " << to);
513  if (from >= to) {
514  return false;
515  }
516 
517  return true;
518 }
519 
520 bool
521 PCGFitter::ScanChi0(Eye &eye, const double step, double from, double to, int level)
522 {
523  const double inf = numeric_limits<double>::infinity();
524 
525  PCGF_DEBUGLOG("ScanChi0 enter");
526  //const EyeRecData& eyeRec = eye.GetRecData();
527  //ChiZeroRegression chi0reg(eyeRec);
528  //chi0reg.SetUseLightFlux(fUseLightFlux);
529  //fChi0Regression = &chi0reg;
530  //ChiZeroRegression &chi0reg = *fChi0Regression;
531 
532  vector<double> chi0s;
533  vector<double> chi2s;
534  vector<double> rps;
535  vector<double> t0s;
536 
537  for (double chi0 = from; chi0 <= to; chi0 += step) {
538  double rp = 0, rpErr = 0;
539  double t0 = 0, t0Err = 0;
540  double chi2 = CombinedChi2(chi0, rp, rpErr, t0, t0Err, PCGFData::eScan, true);
541 
542  chi0s.push_back(chi0);
543  chi2s.push_back(chi2);
544  rps.push_back(rp);
545  t0s.push_back(t0);
546  }
547 
548  unsigned int min_i = TMath::LocMin(chi2s.size(), &chi2s[0]);
549 
550  PCGF_DEBUGLOG( "ScanChi0: min i:" << min_i << "\t size: " << chi2s.size());
551  PCGF_DEBUGLOG( "ScanChi0: min chi2: " << chi2s[min_i]);
552 
553  if (!(chi2s[min_i] < inf)) {
554  PCGF_DEBUGLOG("ScanChi0 failed leave: All profile fits failed.");
555  return false;
556  }
557 
558  if (level > 0 && level < 10) { //we are in the second scan phase (do at most 10 re-scans)
559  //if we are at the scan range border, do another scan
560  if (min_i == 0) {
561  return ScanChi0(eye, fScanStep/10., chi0s[min_i]-3*fScanStep, chi0s[min_i]+4*fScanStep/10., level+1);
562  } else if (min_i == chi2s.size()-1) {
563  return ScanChi0(eye, fScanStep/10., chi0s[min_i]-4*fScanStep/10., chi0s[min_i]+3*fScanStep, level+1);
564  }
565  }
566 /* else if (level == 4 && (min_i == 0 || min_i == chi2s.size()-1)) {
567  PCGF_DEBUGLOG("ScanChi0 failed leave: No smooth minimum after 3 re-scans.");
568  return false;
569  }
570 */
571 
572  /*const double tooMuch = numeric_limits<double>::max(); //but not infinity! //TODO: ask Vladimir why
573  //VN : imagine example [..66,55,33,inf..] -> [..66,55,tooMuch,inf..] -> 55 is OK
574  // if tooMuch=inf :[..66,55,33,inf..] -> [..66,55,inf,inf..] -> [..66,inf,inf,inf..] etc.
575  while (!((min_i > 0) ? chi2s[min_i-1] : inf < inf &&
576  (min_i < chi2s.size()-1) ? chi2s[min_i+1] : inf < inf) &&
577  (chi2s[min_i] != tooMuch)) { //What about the margins? - VN : true, fixed
578  chi2s[min_i] = tooMuch;
579  min_i = TMath::LocMin(chi2s.size(), &chi2s[0]);
580  }
581  if (chi2s[min_i] == tooMuch) {
582  PCGF_DEBUGLOG("ScanChi0 failed leave: No smooth minimum.");
583  return false;
584  }*/
585 
586  //VN: different estimate of smooth minimum
587  const double tooMuch = numeric_limits<double>::max();
588  vector<double> chi2s_copy(chi2s);
589  chi2s_copy[0] = tooMuch;
590  chi2s_copy[chi2s_copy.size()-1] = tooMuch;
591  min_i = TMath::LocMin(chi2s_copy.size(), &chi2s_copy[0]);
592 
593  while (level>0 && chi2s_copy[min_i] < tooMuch) {
594  vector<double> chi2s_trial(chi2s_copy);
595  chi2s_trial[min_i] = tooMuch;
596  int min_i_trial1 = TMath::LocMin(chi2s_trial.size(), &chi2s_trial[0]);
597  chi2s_trial[min_i_trial1] = tooMuch;
598  int min_i_trial2 = TMath::LocMin(chi2s_trial.size(), &chi2s_trial[0]);
599  chi2s_trial[min_i_trial2] = tooMuch;
600  if ((chi2s_trial[min_i-1] == tooMuch) && (chi2s_trial[min_i+1] == tooMuch)) {
601  break;
602  } else {
603  chi2s_copy[min_i] = tooMuch;
604  min_i = TMath::LocMin(chi2s_copy.size(), &chi2s_copy[0]);
605  }
606  }
607 
608  if (!(chi2s_copy[min_i] < tooMuch)) {
609  PCGF_DEBUGLOG("ScanChi0 failed leave: No smooth minimum.");
610  return false;
611  }
612 
613  //estimate chi0 error
614  double xmin = chi0s[min_i];
615  double ymin = chi2s[min_i];
616  vector<double> x;
617  vector<double> y;
618  vector<double> yerr;
619  x.push_back(0.);
620  y.push_back(0.);
621  yerr.push_back(1.);
622  for (unsigned int i = 1; i < 5; ++i) {
623  int j = min_i-i;
624  unsigned int k = min_i+i;
625  if ((j > 0) && std::isfinite(chi2s[j]) && (chi2s[j] != tooMuch)) {
626  x.push_back(abs(chi0s[j]-xmin));
627  y.push_back(((chi2s[j]-ymin)>0.) ? sqrt(chi2s[j]-ymin) : 0.);
628  yerr.push_back(1.);
629  //cout<<x[x.size()-1] << y[y.size()-1]<<endl;
630  }
631  if ((k < chi0s.size()) && std::isfinite(chi2s[k]) && (chi2s[k] != tooMuch)) {
632  x.push_back(abs(chi0s[k]-xmin));
633  y.push_back(((chi2s[k]-ymin)>0.) ? sqrt(chi2s[k]-ymin) : 0.);
634  yerr.push_back(1.);
635  //cout<<x[x.size()-1] << y[y.size()-1]<<endl;
636  }
637  }
638  double a = 0.;
639  double b = 0.;
640  double chi2 = 0.;
641  otoa::LinearFit(x, y, yerr, a, b, chi2);
642  double chi0err = (b!=0) ? (1./b) : 90*deg;
643  //end of chi0 error estimation
644 
645  FillParams(eye, chi0s[min_i], chi0err, rps[min_i], 0.1*kilometer, t0s[min_i], 0.1*microsecond);
646 
647  cout << "calculating result geometry\n";
648  AdjustGeometry(eye);
649  {
650  const evt::ShowerFRecData& recShower = eye.GetRecData().GetFRecShower();
651  const Point& corePos = recShower.GetCorePosition();
653  const Vector& axis = recShower.GetAxis();
654  cout << "chi0: " << chi0s[min_i]/degree << " deg "
655  "rp: " << rps[min_i] / meter << " m "
656  " -> "
657  "theta: " << axis.GetTheta(coreCS)/degree << " deg "
658  "phi: " << axis.GetPhi(coreCS)/degree << " deg"
659  << endl;
660  }
661 
662  PCGF_DEBUGLOG("ScanChi0 sucessful leave");
663  return true;
664 }
665 
666 
667 Eye&
668 PCGFitter::CopyEye(const Eye& eye, evt::Event& eventCopy)
669  const
670 {
671  eventCopy.MakeFEvent();
672  eventCopy.GetFEvent().MakeEye(eye.GetId());
673  eventCopy.GetFEvent().GetEye(eye.GetId()) = eye;
674  return eventCopy.GetFEvent().GetEye(eye.GetId());
675 }
676 
677 
678 void
679 PCGFitter::FillParams(Eye& eyeCopy,
680  const double chi0, const double chi0Err,
681  const double rp, const double rpErr,
682  const double t0, const double t0Err)
683  const
684 {
685  if (eyeCopy.HasTelescope(fTelId)) {
686  fevt::Telescope& tel = eyeCopy.GetTelescope(fTelId);
687  if (!tel.HasRecData())
688  tel.MakeRecData();
689  fevt::TelescopeRecData& telRecData = tel.GetRecData();
690  telRecData.SetChiZero(chi0,chi0Err);
691  telRecData.SetTZero(t0,t0Err);
692  telRecData.SetRp(rp,rpErr);
693  telRecData.SetTimeFitChiSquare(0,1);
694  telRecData.SetTimeFitCorrelations(0,0,0);
695  }
696 }
697 
698 
699 void
700 PCGFitter::FillParams(Eye& eyeCopy,
701  const double chi0,
702  const double rp,
703  const double t0)
704  const
705 {
706  FillParams(eyeCopy, chi0, 0.5*degree, rp, 0.1*km, t0, 0.1*microsecond);
707 }
708 
709 
710 bool
711 PCGFitter::AdjustGeometry(Eye& eyeCopy)
712  const
713 {
714 
715  EyeRecData& eyeRecData = eyeCopy.GetRecData();
716  const fdet::FDetector& detFD = det::Detector::GetInstance().GetFDetector();
717  const fdet::Eye& detEye = detFD.GetEye(eyeCopy);
718  const Point eyePos = detEye.GetPosition();
719 
720  const utl::TimeStamp eyeStamp = eyeCopy.GetHeader().GetTimeStamp();
721 
722  if (!eyeCopy.HasTelescope(fTelId) || !eyeCopy.GetTelescope(fTelId).HasRecData()) {
723  return false;
724  }
725  TelescopeRecData& telRecData = eyeCopy.GetTelescope(fTelId).GetRecData();
726 
727  double t0 = telRecData.GetTZero();
728  const double chi0 = telRecData.GetChiZero();
729  const double rp = telRecData.GetRp();
730  const double t0Err = telRecData.GetTZeroError();
731  const double chi0Err = telRecData.GetChiZeroError();
732  const double rpErr = telRecData.GetRpError();
733 
734  const Point telPos = detEye.GetTelescope(fTelId).GetPosition();
736  const double sdpTheta = telRecData.GetSDP().GetTheta(telCS);
737  const double sdpPhi = telRecData.GetSDP().GetPhi(telCS);
738 
739  const Vector sdp = Vector(1, sdpTheta, sdpPhi, telCS, Vector::kSpherical);
740  const Vector vertical(0,0,1, telCS);
741  const Vector horizontalInSDP = Normalized(Cross(sdp, vertical));
742 
743  const Transformation rot = Transformation::Rotation(-chi0, sdp, telCS);
744  Vector axis = Normalized(rot*horizontalInSDP);
745 
746  const double coreDistance = rp / sin(chi0);
747  const Vector coreTelVec = coreDistance * horizontalInSDP;
748  const Point core = telPos + coreTelVec;
749  const Point P_in_tel = telPos + Normalized(Cross(sdp, axis))*rp;
750 
751  //VN: set telescope data to deal with HECO; also set eye data and recalculate chi_i
752  bool fillEye = true;
753  for (fdet::Eye::TelescopeIterator detTelIt = detEye.TelescopesBegin();
754  detTelIt != detEye.TelescopesEnd(); ++detTelIt)
755  {
756 
757  const int curtelId = detTelIt->GetId();
758 
759  const Point curtelPos = detTelIt->GetPosition();
760  const CoordinateSystemPtr curtelCS = fwk::LocalCoordinateSystem::Create(curtelPos);
761 
762  const Point core_in_curtel = core-axis*core.GetZ(curtelCS)/cos(axis.GetTheta(curtelCS));
763 
764  const Vector curtel_to_core = core_in_curtel-curtelPos;
765  double chi0_in_curtel = Angle(curtel_to_core, axis);
766  if (axis.GetTheta(curtelCS)>kPi/2.) {
767  chi0_in_curtel = -(kPi-chi0_in_curtel);
768  }
769  double rp_in_curtel = curtel_to_core.GetMag()*sin(chi0_in_curtel);
770  if (axis.GetTheta(curtelCS)>kPi/2.) {
771  rp_in_curtel *= -1.;
772  }
773  const utl::AxialVector SDP_in_curtel = Normalized(Cross(axis, curtel_to_core));
774  const Point P_in_curtel = curtelPos + Normalized(Cross(SDP_in_curtel, axis))*rp_in_curtel;
775  const Vector Pt_to_Pct = P_in_curtel - P_in_tel;
776  const double t0_in_curtel = t0 + ((Pt_to_Pct*axis > 0.) ? -1. : 1.)*Pt_to_Pct.GetMag()/kSpeedOfLight;
777 
778  if (eyeCopy.HasTelescope(curtelId)) {
779  fevt::Telescope& tel = eyeCopy.GetTelescope(curtelId);
780 
781  if (!tel.HasRecData())
782  tel.MakeRecData();
783 
784  fevt::TelescopeRecData& telRecData = tel.GetRecData();
785  telRecData.SetSDP(SDP_in_curtel);
786  telRecData.SetChiZero(chi0_in_curtel, chi0Err);
787  telRecData.SetTZero(t0_in_curtel, t0Err);
788  telRecData.SetRp(rp_in_curtel, rpErr);
789  telRecData.SetTimeFitChiSquare(0,1);
790  telRecData.SetTimeFitCorrelations(0,0,0);
791  }
792 
793  if (fillEye) {
794  //choose tel with the same position as eye (usually, more of them are available)
795  if ((curtelPos - eyePos).GetMag() < 1e-3) {
796  eyeRecData.SetChiZero(chi0_in_curtel, chi0Err);
797  eyeRecData.SetTZero(t0_in_curtel, t0Err);
798  eyeRecData.SetRp(rp_in_curtel, rpErr);
799  eyeRecData.SetSDP(SDP_in_curtel);
800 
801  evt::ShowerFRecData& frecShower = eyeRecData.GetFRecShower();
802  frecShower.SetAxis(axis);
803  frecShower.SetCorePosition(core_in_curtel);
804  try {
805  double tCore = t0_in_curtel;
806  tCore -= (rp_in_curtel / tan(chi0_in_curtel)) / kSpeedOfLight;
807  utl::TimeStamp timeAtCore = eyeStamp - TimeInterval(1000*100*ns) + TimeInterval(tCore);
808  frecShower.SetCoreTime(timeAtCore, 0); //, rp_in_tel, chi0_in_tel, t0_in_tel);
809  } catch (OutOfBoundException& e) {
810  ERROR(e.GetMessage());
811  return false;
812  }
813  fillEye = false;
814  }
815  }
816  }
817 
818  for (fevt::EyeRecData::PixelIterator pixelIter = eyeRecData.PulsedPixelsBegin();
819  pixelIter != eyeRecData.PulsedPixelsEnd(); ++pixelIter) {
820 
821  unsigned int telId = pixelIter->GetTelescopeId();
822 
823  fevt::TelescopeRecData& telRecData = eyeCopy.GetTelescope(telId).GetRecData();
824  const Point telPos = det::Detector::GetInstance().GetFDetector().GetEye(eyeCopy).GetTelescope(telId).GetPosition();
826  const double sdpTheta = telRecData.GetSDP().GetTheta(telCS);
827  const double sdpPhi = telRecData.GetSDP().GetPhi(telCS);
828 
829  const Vector sdp = Vector(1, sdpTheta, sdpPhi, telCS, Vector::kSpherical);
830  const Vector vertical(0,0,1, telCS);
831  const Vector horizontalInSDP = Normalized(Cross(sdp, vertical));
832 
833  const Vector pixelDirection = detFD.GetPixel(*pixelIter).GetDirection();
834  const Vector pixelDirInSDP = pixelDirection - (sdp * pixelDirection)*sdp;
835  const double pixelChi = Angle(pixelDirInSDP, horizontalInSDP);
836 
837  pixelIter->GetRecData().SetChi_i(pixelChi);
838  }
839 
840  return true;
841 }
842 
843 }
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
unsigned int GetId() const
Definition: FEvent/Eye.h:54
const utl::Vector & GetDirection() const
pointing direction of this pixel
bool HasRecData() const
unsigned int GetNPoints() const
void SetChiZero(const double chiZero, const double error)
Definition: EyeRecData.h:237
bool HasLightFlux(const FdConstants::LightSource source=FdConstants::eTotal) const
Check that light profile for source /par source is present.
Definition: EyeRecData.h:297
const double degree
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
Report success to RunController.
Definition: VModule.h:62
fevt::EyeHeader & GetHeader()
Header for this Eye Event.
Definition: FEvent/Eye.cc:180
Fluorescence Detector Eye Event.
Definition: FEvent/Eye.h:29
PixelIterator PulsedPixelsEnd()
Definition: EyeRecData.h:121
void SetPCGF(const std::vector< PCGFData > &pcgf)
Definition: EyeRecData.h:334
const Pixel & GetPixel(const fevt::Pixel &eventPixel) const
Get fdet::Pixel from fevt::Channel.
Definition: FDetector.cc:198
double GetRpError() const
double GetTheta(const CoordinateSystemPtr &coordinateSystem) const
zenith (theta) angle in spherical coordinates
Definition: BasicVector.h:248
double GetChiZero() const
Definition: EyeRecData.h:85
void SetCorePosition(const utl::Point &core)
unsigned int GetTimeFitNDof() const
Definition: EyeRecData.h:93
const double meter
Definition: GalacticUnits.h:29
void SetTimeFitCorrelations(double rRpT0, double rRpChi0, double rChi0T0)
#define INFO(message)
Macro for logging informational messages.
Definition: ErrorLogger.h:161
void MakeEye(const unsigned int eyeId, const ComponentSelector::Status status=ComponentSelector::eHasData)
Definition: FEvent.cc:115
void SetRp(const double rp, const double error)
Definition: EyeRecData.h:239
void Init()
Initialise the registry.
const Eye & GetEye(const unsigned int eyeId) const
Find eye by numerical Id.
Definition: FDetector.cc:68
Detector description interface for Eye-related data.
Definition: FDetector/Eye.h:45
Branch GetChild(const std::string &childName) const
Get child of this Branch by child name.
Definition: Branch.cc:211
fevt::TelescopeRecData & GetRecData()
Reconstructed data for this telescope.
PixelIterator PulsedPixelsBegin()
Definition: EyeRecData.h:119
int Migrad(const int n=500)
Definition: Minou.h:266
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
A TimeStamp holds GPS second and nanosecond for some event.
Definition: TimeStamp.h:110
boost::indirect_iterator< ConstInternalPixelIterator, const Pixel & > ConstPixelIterator
Const iterator over pixels used in reconstruction.
Definition: EyeRecData.h:117
Exception for reporting variable out of valid range.
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
void SetSDP(const utl::AxialVector &vec)
boost::shared_ptr< const CoordinateTransformer > CoordinateSystemPtr
Shared pointer for coordinate systems.
#define max(a, b)
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.
Definition: Branch.h:107
const double & GetYErr(const unsigned int idx) const
void SetCoreTime(const utl::TimeStamp &coreTime, const utl::TimeInterval &coreTimeErr)
const double ns
TelescopeIterator TelescopesEnd()
first available tel of status eHasData (DEPRECATED)
Definition: FEvent/Eye.cc:230
constexpr double kPi
Definition: MathConstants.h:24
bool HasLightFlux(const FdConstants::LightSource source=FdConstants::eTotal) const
Check that light profile for source /par source is present.
TelescopeIterator TelescopesBegin() const
Beginning of the collection of telescopes.
Definition: FDetector/Eye.h:79
void SetAxis(const utl::Vector &axis)
double abs(const SVector< n, T > &v)
const Data result[]
Active transformations of geometrical objects.
const Telescope & GetTelescope(const unsigned int telescopeId) const
Find Telescope by numerical Id.
evt::ShowerFRecData & GetFRecShower()
Reconstructed shower info for this eye.
Definition: EyeRecData.h:323
double GetChiZeroError() const
void SetChiZero(const double chiZero, const double error)
const double km
Telescope-specific shower reconstruction data.
boost::filter_iterator< ComponentSelector, AllTelescopeIterator > TelescopeIterator
selective Telescope iterators
Definition: FEvent/Eye.h:72
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.
Definition: Branch.cc:644
double GetTZero() const
const double & GetXErr(const unsigned int idx) const
Eye-specific shower reconstruction data.
Definition: EyeRecData.h:65
AxialVector Normalized(const AxialVector &v)
Definition: AxialVector.h:81
Eye & GetEye(const unsigned int eyeId, const ComponentSelector::Status status=ComponentSelector::eHasData)
return Eye by id
Definition: FEvent.cc:70
TelescopeIterator TelescopesBegin()
first available tel of status eHasData (DEPRECATED)
Definition: FEvent/Eye.cc:207
const double & GetY(const unsigned int idx) const
double GetTimeFitChiSquare() const
Definition: EyeRecData.h:92
boost::filter_iterator< TelIsCommissioned, InternalConstTelescopeIterator > TelescopeIterator
An iterator over telescopes.
Definition: FDetector/Eye.h:76
fevt::FEvent & GetFEvent()
#define PCGF_DEBUGLOG(x)
Definition: G/PCGFitter.cc:38
boost::indirect_iterator< InternalPixelIterator, fevt::Pixel & > PixelIterator
Iterator over pixels used in reconstruction.
Definition: EyeRecData.h:113
constexpr double kSpeedOfLight
Detector description interface for Telescope-related data.
A TimeInterval is used to represent time elapsed between two events.
Definition: TimeInterval.h:43
void SetTZero(const double tzero, const double error)
double GetRp() const
Definition: EyeRecData.h:87
utl::TimeStamp GetTimeStamp() const
Time of the Eye Event as tagged by FD-DAS (== eye trigger time plus pixel trace length) ...
Definition: EyeHeader.h:118
static CentralConfig * GetInstance()
Use this the first time you get an instance of central configuration.
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
void SetTimeFitChiSquare(const double tfitChi2, const unsigned int ndof)
PixelIterator TimeFitPixelsEnd()
Definition: EyeRecData.h:171
constexpr double kilometer
Definition: AugerUnits.h:93
Vector object.
Definition: Vector.h:30
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)
TelescopeIterator TelescopesEnd() const
End of the collection of telescopes.
Definition: FDetector/Eye.h:83
void SetSDP(const utl::AxialVector &vec)
Definition: EyeRecData.h:218
AxialVector object.
Definition: AxialVector.h:30
double GetTZero() const
Definition: EyeRecData.h:83
void SetTZero(const double tzero, const double error)
Definition: EyeRecData.h:235
Fluorescence Detector Telescope Event.
utl::TabulatedFunctionErrors & GetLightFlux(const FdConstants::LightSource source=fevt::FdConstants::eTotal)
Light flux at diaphragm, photons/m^2 versus time in ns.
Definition: EyeRecData.h:286
double GetZ(const CoordinateSystemPtr &coordinateSystem) const
Definition: BasicVector.h:212
double GetChiZero() const
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.
const utl::AxialVector & GetSDP() const
PixelIterator TimeFitPixelsBegin()
Definition: EyeRecData.h:167
#define ERROR(message)
Macro for logging error messages.
Definition: ErrorLogger.h:165
constexpr double m
Definition: AugerUnits.h:121
constexpr double microsecond
Definition: AugerUnits.h:147
const utl::Point & GetCorePosition() const
Shower core as reconstructed by the FD or FD eye.
double GetTZeroError() const
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.
Definition: FEvent/Eye.cc:130
const utl::Vector & GetAxis() const
Shower Axis as reconstructed by the FD or FD eye.

, generated on Tue Sep 26 2023.