SdTopDownSignalSelector.cc
Go to the documentation of this file.
2 
3 #include <algorithm>
4 
5 #include <utl/ErrorLogger.h>
6 #include <utl/Branch.h>
7 #include <utl/Accumulator.h>
8 
9 #include <fwk/CentralConfig.h>
10 #include <fwk/LocalCoordinateSystem.h>
11 
12 #include <evt/Event.h>
13 #include <evt/ShowerRecData.h>
14 #include <evt/ShowerSRecData.h>
15 
16 #include <sevt/StationTriggerData.h>
17 #include <sevt/EventTrigger.h>
18 #include <sevt/SortCriteria.h>
19 
20 #include <sdet/SDetector.h>
21 
22 #include <TCdasUtil.h>
23 
24 using namespace std;
25 using namespace sevt;
26 using namespace utl;
27 using namespace fwk;
28 
29 
30 static bool bFirstIteration;
31 
32 
34 
35  Point SdTopDownSignalSelectorUGR::fBarycenter;
36  TimeStamp SdTopDownSignalSelectorUGR::fBaryTime;
37 
38 
40  fSEvent(0),
41  fVerbose(0),
42  fRejectNonT4Events(false),
43  fU(0.),
44  fV(0.),
45  fXCore(0.),
46  fYCore(0.),
47  fZCore(0.),
48  fTCore(0.),
49  fNMinStations(3),
50  fNMaxRemovedStations(4)
51  { }
52 
53 
56  {
57  // Initialize your module here. This method
58  INFO("SdTopDownSignalSelectorUGR::Init: INFO:");
59 
60  Branch topB =
61  CentralConfig::GetInstance()->GetTopBranch("SdTopDownSignalSelectorUGR");
62 
63  topB.GetChild("Verbose").GetData(fVerbose);
64  fVerbose = (fVerbose < 0) ? 0 : fVerbose;
65 
66  topB.GetChild("SignalThreshold").GetData(fSignalThreshold);
67 
68  topB.GetChild("Nmin").GetData(fMinSlots);
69  if (fMinSlots < 1) {
70  cerr << "WARNING! You specified a non valid Nmin (" << fMinSlots << "). Should be at least 1. Setting it to default (10 Slots)" << endl;
71  fMinSlots = 10;
72  }
73 
74  topB.GetChild("Smin").GetData(fMinSignal);
75  if (fMinSignal <= 0) {
76  cerr << "WARNING! You specified a non valid Smin (" << fMinSignal << "). Should be bigger than 0. Setting it to default (1 VEMs)" << endl;
77  fMinSignal = 1;
78  }
79 
80  topB.GetChild("N0").GetData(fMingap);
81  if (fMingap < 0) {
82  cerr << "WARNING! You specified a negative N0 (" << fMingap << "). Setting it to 0 slots." << endl;
83  fMingap = 0;
84  }
85 
86  topB.GetChild("RejectionProcedure").GetData(fRejectionProcedure);
87 
88  topB.GetChild("MinStationSignal").GetData(fMinStSignal);
89  if (fMinStSignal < 0) {
90  cerr << "WARNING! You specified a non valid MinStationSignal (" << fMinStSignal << "). Should be at least 0. Setting it to 0." << endl;
91  fMinStSignal = 0;
92  }
93 
94  topB.GetChild("MinNumberOfStationForSignalCut").GetData(fMinNumberStSignalCut);
95  if (fMinNumberStSignalCut < 0) {
96  cerr << "WARNING! You specified a non valid MinNumberOfStationForSignalCut (" << fMinNumberStSignalCut << "). Should be at least 0. Setting it to 0." << endl;
98  }
99 
100  topB.GetChild("AnodeSignalFactor").GetData(fLowFactor);
101  if (fLowFactor <= 0) {
102  cerr << "WARNING! You specified a non valid AnodeSignalFactor (" << fLowFactor << "). Should be bigger than 0. Setting it to 1." << endl;
103  fLowFactor = 1;
104  }
105 
106  // Get Top Down Parameters
107  // Pre Segment identification
108  topB.GetChild("PreSignalThreshold").GetData(fPreSignalThreshold);
109 
110  topB.GetChild("PreNmin").GetData(fPreMinSlots);
111  if (fPreMinSlots < 1) {
112  cerr << "WARNING! You specified a non valid Nmin (" << fPreMinSlots << "). Should be at least 1. Setting it to default (3 Slots)" << endl;
113  fPreMinSlots = 3;
114  }
115 
116  topB.GetChild("PreN0").GetData(fPreMingap);
117  if (fPreMingap < 0) {
118  cerr << "WARNING! You specified a non valid GAP (" << fPreMingap << "). Should be at least 0. Setting it to default (3 Slots)" << endl;
119  fPreMingap = 3;
120  }
121 
122  topB.GetChild("PreSmin").GetData(fPreMinSignal);
123  if (fPreMinSignal <= 0) {
124  cerr << "WARNING! You specified a non valid PreSmin (" << fPreMinSignal << "). Should be bigger than 0. Setting it to default (0.8 VEMs)" << endl;
125  fPreMinSignal = 0.8;
126  }
127 
128  // Top Down Parameters
129  topB.GetChild("RejectNonT4Events").GetData(fRejectNonT4Events);
130  topB.GetChild("MinNumberStations").GetData(fNMinStations);
131  topB.GetChild("MaxNumberStations").GetData(fNMaxStations);
132  topB.GetChild("MaxRejectedSignals").GetData(fNMaxRemovedStations);
133  topB.GetChild("BaryPower").GetData(kBaryPower);
134  topB.GetChild("TimeResidualTolerance").GetData(kTolRes);
135  topB.GetChild("MTimeResidualTolerance").GetData(kTolResM);
136  topB.GetChild("IsolatedDistance1").GetData(kIsoDist1);
137  topB.GetChild("IsolatedDistance2").GetData(kIsoDist2);
138  topB.GetChild("Curv0").GetData(kCurv0);
139  topB.GetChild("AreaMin").GetData(kAreaMin);
140  topB.GetChild("AreaMax").GetData(kAreaMax);
141  topB.GetChild("Ana3RatMin").GetData(kAna3RatMin);
142  topB.GetChild("DistMax").GetData(kDistMax);
143  topB.GetChild("IsoTime1").GetData(kIsoTime1);
144  topB.GetChild("IsoTime2").GetData(kIsoTime2);
145 
146  // Get SdCalibrator Parameters
147 
148  Branch topCB =
149  CentralConfig::GetInstance()->GetTopBranch("SdCalibrator");
150  if (topCB) {
151  topCB.GetChild("riseTimeFractions").GetData(fRiseTimeFractions);
152  topCB.GetChild("fallTimeFractions").GetData(fFallTimeFractions);
153  if (fRiseTimeFractions.first < 0 || fRiseTimeFractions.first > 1 ||
154  fRiseTimeFractions.second < 0 || fRiseTimeFractions.second > 1 ||
155  fFallTimeFractions.first < 0 || fFallTimeFractions.first > 1 ||
156  fFallTimeFractions.second < 0 || fFallTimeFractions.second > 1) {
157 
158  ERROR("Rise/fall time fractions must be within [0, 1]");
159  return eFailure;
160  }
161 
162  if (fRiseTimeFractions.first >= fRiseTimeFractions.second ||
163  fFallTimeFractions.first >= fFallTimeFractions.second ||
164  fRiseTimeFractions.first >= fFallTimeFractions.second) {
165 
166  ERROR("Rise/fall time definition is not in the ascending order");
167  return eFailure;
168  }
169  } else {
170  WARNING("Rise/Fall Time Fractions can not be readed. Did you use the SdTraceCalibratorOG?\n Using default values");
171  fRiseTimeFractions.first = 0.1;
172  fRiseTimeFractions.second = 0.5;
173  fFallTimeFractions.first = 0.5;
174  fFallTimeFractions.second = 0.9;
175  }
176 
177  if (fVerbose) {
178  cout << " Accidental Signal Rejector parameters: (See GAP 2005-074)\n"
179  "\t Verbosity: " << fVerbose << "\n"
180  "\t Signal Threshold: " << fSignalThreshold << "\n"
181  "\t Min Slots (Nmin): " << fMinSlots << "\n"
182  "\t Min. Signal (Smin): " << fMinSignal << "\n"
183  "\t Min. GAP (N0): " << fMingap << "\n"
184  "\tRejection Procedure: " << fRejectionProcedure << "\n"
185  "\tAnode Signal factor: " << fLowFactor << endl;
186 
187  if (fMinStSignal)
188  cout << "\t Reject St. below: " << fMinStSignal << " VEMs\n"
189  "\t Min. St. Sig. Cut: " << fMinNumberStSignalCut << endl;
190 
191  if (fRejectionProcedure == 4)
192  cout << "\t PreSignalThreshold: " << fPreSignalThreshold << " VEMs\n"
193  "\t Pre Nmin: " << fPreMinSlots << "\n"
194  "\t Pre N0: " << fPreMingap << "\n"
195  "\t Pre Smin: " << fPreMinSignal << "\n"
196  "\t Reject non T4 evt.: " << fRejectNonT4Events << "\n"
197  "\t Min. number St.: " << fNMinStations << "\n"
198  "\t Max. number St.: " << fNMaxStations << "\n"
199  "\t Max Rejected Sig.: " << fNMaxRemovedStations << "\n"
200  "\t Bary Power: " << kBaryPower << "\n"
201  "\t Time Residual Tol.: " << kTolRes << "\n"
202  "\t M. Time Res. Tol.: " << kTolResM << "\n"
203  "\t Isolated Dist. 1: " << kIsoDist1 << "\n"
204  "\t Isolated Dist. 2: " << kIsoDist2 << "\n"
205  "\t Curvature 0: " << kCurv0 << "\n"
206  "\t Area Min.: " << kAreaMin << "\n"
207  "\t Area Max.: " << kAreaMax << "\n"
208  "\t Ana. 3 Rat. Min.: " << kAna3RatMin << "\n"
209  "\t Dist. Max.: " << kDistMax << "\n"
210  "\t Isolated Time 1: " << kIsoTime1 << "\n"
211  "\t Isolated Time 2: " << kIsoTime2 << endl;
212  cout << endl;
213  }
214 
215  return eSuccess;
216  }
217 
218 
220  SdTopDownSignalSelectorUGR::Run(evt::Event& event)
221  {
222  INFO("SdTopDownSignalSelectorUGR::Run");
223 
224  if (!event.HasSEvent()) {
225  INFO("Event has not SEvent");
226  return eContinueLoop;
227  }
228 
229  fSEvent = &event.GetSEvent();
230 
231  if (fRejectionProcedure == 4.) { // Do we really need this? The SdEventSelector should do this.
232  cout << " Removing non grid stations." << endl;
233  RemoveEA();
234  RemoveDoublets();
236  fAllSegments.clear();
237  }
238 
239  // Sort by Increasing signal. important for cut station with low signal.
241 
242  if (fVerbose > 2) {
243  cout << " Sorted Stations by signal:" << endl;
245  sIt != fSEvent->CandidateStationsEnd(); ++sIt)
246  cout << " St: " << sIt->GetId() << "\t Signal: " << sIt->GetRecData().GetTotalSignal() << " VEMs" << endl;
247  }
248 
249  int candidateStations = 0;
250 
251  if (fVerbose)
252  cout << " Station pre-processing... " << endl;
253 
255  sIt != fSEvent->CandidateStationsEnd(); ++sIt) {
256 
257  // Safety filters for accidental uses of the module before the SdCalibrator
258  // It should never happens in Candidate Stations
259 
260  if (!sIt->HasTriggerData()) {
261  if (fVerbose)
262  cout << " St: " << sIt->GetId() << " -> Skipped. No Trigger Data." << endl;
263  sIt->SetRejected(sevt::StationConstants::eNoTrigger);
264  continue;
265  }
266  const StationTriggerData& trig = sIt->GetTriggerData();
267  if (trig.GetErrorCode()) {
268  if (fVerbose)
269  cout << " St: " << sIt->GetId() << " -> Skipped. Error by code:" << trig.GetErrorCode() << endl;
270  sIt->SetRejected(sevt::StationConstants::eErrorCode);
271  continue;
272  }
273  if (trig.IsRandom()) {
274  if (fVerbose)
275  cout << " St: " << sIt->GetId() << " -> Skipped. Random Trigger." << endl;
276  sIt->SetRejected(sevt::StationConstants::eRandom);
277  continue;
278  }
279  if (!sIt->HasCalibData()) {
280  if (fVerbose)
281  cout << " St: " << sIt->GetId() << " -> Skipped. No Calib Data." << endl;
282  sIt->SetRejected(sevt::StationConstants::eNoCalibData);
283  continue;
284  }
285  // exclude FADCs with Patrick's data
286  if (sIt->GetCalibData().GetVersion() > 32000) {
287  if (fVerbose)
288  cout << " St: " << sIt->GetId() << " -> Skipped. Calib vervison > 32000." << endl;
289  sIt->SetRejected(sevt::StationConstants::eBadCalib);
290  continue;
291  }
292  if (!sIt->HasGPSData()) {
293  if (fVerbose)
294  cout << " St: " << sIt->GetId() << " -> Skipped. No GPS Data." << endl;
295  sIt->SetRejected(sevt::StationConstants::eNoGPSData);
296  continue;
297  }
298  if (!sIt->HasVEMTrace()) {
299  if (fVerbose)
300  cout << " St: " << sIt->GetId() << " -> Skipped. No VEM signal." << endl;
301  sIt->SetRejected(sevt::StationConstants::eNoRecData);
302  continue;
303  }
304  ++candidateStations;
305  }
306 
307  if (fVerbose > 1)
308  cout << " Event with " << candidateStations << " candidate stations" << endl;
309 
310  // trivial selection
311  if (fRejectionProcedure == 4 && fRejectNonT4Events && candidateStations < fNMinStations) {
312  INFO("Event was not selected.");
313  return eContinueLoop;
314  }
315 
316  if (fVerbose)
317  cout << " Station processing... " << endl;
318 
319  // Iterate over candidate stations
321  sIt != fSEvent->CandidateStationsEnd(); ++sIt) {
322 
323  if (fVerbose)
324  cout << "\n Processing station: " << sIt->GetId() << endl;
325 
326  if (sIt->GetRecData().GetTotalSignal() < fMinStSignal && candidateStations > fMinNumberStSignalCut) {
327  if (fVerbose)
328  cout << " Rejected. Signal " << sIt->GetRecData().GetTotalSignal() << " VEMs below the minimun " << fMinStSignal << " VEMs" << endl;
329  sIt->SetRejected(sevt::StationConstants::eRandom);
330  --candidateStations;
331  continue;
332  }
333 
334  if (fRejectionProcedure != 4 || candidateStations >= fNMaxStations) {
335  // Search for different segments
336  GeoSegmentCollection segments(FoundSegments(*sIt));
337 
338  if (segments.size() < 1) { // Delete station
339  sIt->SetRejected(sevt::StationConstants::eRandom);
340  if (fVerbose)
341  cout << " Station " << sIt->GetId() << " rejected. No valid segments. Flagged as random." << endl;
342  --candidateStations;
343  continue;
344  }
345  SelectMainSegment(segments);
346 
347  // Set New station values
348  const int start = segments[0].fStart;
349  const int stop = segments[0].fStop + 1;
350  if (fVerbose)
351  cout << " Selected Segment [StartBin, StopBin): [" << start << " , " << stop << ")" << endl;
352  if (fRejectionProcedure == 4) {
353  fAllSegments.push_back(segments[0]);
354  if (fVerbose)
355  cout << " Segment Stored for Top Down selection " << endl;
356  }
357  if (!sIt->HasRecData())
358  sIt->MakeRecData();
359  UpdateStationValues(*sIt, start, stop);
360  } else {
361  GeoSegmentCollection BasicSegments(FoundBasicSegments(*sIt));
362  for (unsigned int seg = 0; seg < BasicSegments.size(); ++seg)
363  fAllSegments.push_back(BasicSegments[seg]);
364  }
365 
366  } // Station iterator
367 
368 
369  if (fRejectionProcedure == 4.) {
370 
371  if (fVerbose)
372  cout << " Using Top Down signal selector...";
373  if (fVerbose > 2) {
374  cout << " ...for the segments:\n"
375  " (StId, Start, Stop, Time, Signal)" << endl;
376  for (unsigned int seg = 0; seg < fAllSegments.size(); ++seg)
377  cout << " (" << fAllSegments[seg].fStEvt->GetId() << " , "
378  << fAllSegments[seg].fStart << " , "
379  << fAllSegments[seg].fStop << " , "
380  << fAllSegments[seg].fStartTime.GetGPSNanoSecond() << " , "
381  << fAllSegments[seg].fSignal << endl;
382  }
383  if (fVerbose)
384  cout << endl;
385 
386  // trivial selection
387  if (fRejectNonT4Events && candidateStations < fNMinStations) {
388  INFO("Event was not selected.");
389  return eContinueLoop;
390  }
391 
392  const bool isFD = fSEvent->GetTrigger().IsFD();
393  const bool isSdT4 = Select(); // Top Down procedure here!!.
394 
395  if (!event.HasRecShower())
396  event.MakeRecShower();
397  if (!event.GetRecShower().HasSRecShower())
398  event.GetRecShower().MakeSRecShower();
399 
400  evt::ShowerSRecData& shSRec = event.GetRecShower().GetSRecShower();
401  shSRec.SetT4Trigger((isFD * evt::ShowerSRecData::eT4_FD) |
402  (isSdT4 * evt::ShowerSRecData::eT4_4C1));
403 
404  if (isSdT4) {
405  EstimateCore();
406  const Vector axis(-fU, -fV, cos(EstimatedZenith("rad")), LocalCoordinateSystem::Create(fBarycenter));
407  shSRec.SetAxis(axis);
408 
409  // shSRec.SetAngleErrors(axis.GetCoordinates(fgLocalCS),
410  // Vector::Triple(fit->sigmaU2, fit->sigmaUV, fit->sigmaV2));
411 
412  shSRec.SetCurvature(0, 0);
413  shSRec.SetBarycenter(fBarycenter);
415  shSRec.SetCoreTime(fBaryTime + TimeInterval(fT0), 0); //kSpeedOfLight),
416  // TimeInterval(sqrt(fit->sigmact02)));
417 
418  // double timeMean3d;
419  // double timeSpread3d;
420  // double chi2;
421  // CalculateTimeResidual3D(axis, fT0/kSpeedOfLight, timeMean3d, timeSpread3d, chi2);
422 
423  // shSRec.SetTimeResidualMean(timeMean3d);
424  // shSRec.SetTimeResidualSpread(timeSpread3d);
425  // const int angleNDOF = nStations - 3;
426  // shSRec.SetAngleChi2(chi2, angleNDOF);
427 
428  // shSRec.SetLDFRecStage(fit->stage);
429  }
430 
431  if (fRejectNonT4Events && !isSdT4) {
432  INFO("Event was not selected.");
433  return eContinueLoop;
434  }
435  }
436 
437  return eSuccess;
438  }
439 
440 
442  SdTopDownSignalSelectorUGR::Finish()
443  {
444  // Put any termination or cleanup code here.
445  // This method is called once at the end of the run.
446 
447  INFO("SdTopDownSignalSelectorUGR::Finish");
448 
449  return eSuccess;
450  }
451 
452 
453  // ==============================================
454  // driving function
455  // ==============================================
456 
457  bool
458  SdTopDownSignalSelectorUGR::Select()
459  {
460  sort(fAllSegments.begin(), fAllSegments.end(), ByIncreasingSignal());
461 
462  const int ns = fAllSegments.size();
463 
465 
466  if (fVerbose > 4)
467  cout << " Debuged info: Number of segments: " << ns << "\n"
468  " Minimun of stations: " << fNMinStations << "\n"
469  " MaxRemoved Stations: " << fNMaxRemovedStations << "\n"
470  " Index k: " << k << endl;
471 
472  if (PatternRecovering()) {
473  UpdateStations();
474  if (fVerbose > 0)
475  cout << " Event Accepted with all stations. Theta ~ "
476  << EstimatedZenith("deg") << " deg." << endl;
477  return true;
478  }
479 
480  // "top down" selection
481  bFirstIteration = true;
482  for (int i = 1; i <= k; ++i) {
483  fIndexes.clear();
484  fIndexes.resize(i);
485  fIndexes[i - 1] = ns;
486  if (fVerbose > 1) {
487  cout << " Select: Trying with " << i << " less stations over " << ns << endl;
488  for (int ik = 0; ik < i; ++ik)
489  cout << " Select: fIndexes[" << ik << "] = " << fIndexes[ik] << endl;
490  }
491  if (TryRemovingStations(i)) {
492  UpdateStations();
493 
494  if (fVerbose > 2) {
495  cout << " Selected segments:\n"
496  " (StId, Start, Stop, Time, Signal)" << endl;
497  for (unsigned int seg = 0; seg < fAllSegments.size(); ++seg) {
498  if (!fAllSegments[seg].fCandidate)
499  continue;
500  cout << " (" << fAllSegments[seg].fStEvt->GetId() << " , "
501  << fAllSegments[seg].fStart << " , "
502  << fAllSegments[seg].fStop << " , "
503  << fAllSegments[seg].fStartTime.GetGPSNanoSecond() << " , "
504  << fAllSegments[seg].fSignal << endl;
505  }
506  }
507 
508  if (fVerbose > 0) {
509  cout << " Event accepted with " << i << " rejected. Theta ~ "
510  << EstimatedZenith("deg") << " deg." << endl;
511  }
512  return true;
513  }
514  }
515 
516  bFirstIteration = false;
517  for (int i = 1; i <= k; ++i) {
518  fIndexes.clear();
519  fIndexes.resize(i);
520  fIndexes[i - 1] = ns;
521  if (fVerbose > 1) {
522  cout << " Select: Trying with " << i << " less stations over " << ns << endl;
523  for (int ik = 0; ik < i; ++ik)
524  cout << " Select: fIndexes[" << ik << "] = " << fIndexes[ik] << endl;
525  }
526  if (TryRemovingStations(i)) {
527  UpdateStations();
528 
529  if (fVerbose > 2) {
530  cout << " Selected segments:\n"
531  " (StId, Start, Stop, Time, Signal)" << endl;
532  for (unsigned int seg = 0; seg < fAllSegments.size(); ++seg) {
533  if (!fAllSegments[seg].fCandidate)
534  continue;
535  cout << " (" << fAllSegments[seg].fStEvt->GetId() << " , "
536  << fAllSegments[seg].fStart << " , "
537  << fAllSegments[seg].fStop << " , "
538  << fAllSegments[seg].fStartTime.GetGPSNanoSecond() << " , "
539  << fAllSegments[seg].fSignal << endl;
540  }
541  }
542 
543  if (fVerbose > 0) {
544  cout << " Event accepted with " << i << " rejected. Theta ~ "
545  << EstimatedZenith("deg") << " deg." << endl;
546  }
547  return true;
548  }
549  }
550 
551  return false;
552  }
553 
554 
555  void
556  SdTopDownSignalSelectorUGR::RemoveEA()
557  {
559  sIt != fSEvent->CandidateStationsEnd(); ++sIt) {
560  if (sIt->GetId() < 100)
562  }
563  }
564 
565 
566  // This one actually removes all off-grid stations (in-fill, triplets, doublets),
567  // not only doublets. If we want to remove only doublets we need to change IsInGrid
568  // by the corresponding one
569  void
570  SdTopDownSignalSelectorUGR::RemoveDoublets()
571  {
572  const sdet::SDetector& sdetector = det::Detector::GetInstance().GetSDetector();
573 
575  sIt != fSEvent->CandidateStationsEnd(); ++sIt) {
576  const sdet::Station& station = sdetector.GetStation(*sIt);
577  if (!station.IsInGrid())
578  sIt->SetRejected(sevt::StationConstants::eOffGrid);
579  }
580  }
581 
582 
583  void
584  SdTopDownSignalSelectorUGR::RemoveIsolatedStations()
585  {
586  const sdet::SDetector& sdetector = det::Detector::GetInstance().GetSDetector();
587 
589  sIt_1 != fSEvent->CandidateStationsEnd(); ++sIt_1) {
590  const utl::Point fStPoint1 = sdetector.GetStation(*sIt_1).GetPosition();
591  int n1 = 0;
592  int n2 = 0;
593  const TimeStamp t1 = sIt_1->GetRecData().GetSignalStartTime();
594 
596  sIt_2 != fSEvent->CandidateStationsEnd(); ++sIt_2) {
597  if (sIt_1->GetId() == sIt_2->GetId())
598  continue;
599 
600  const utl::Point fStPoint2 = sdetector.GetStation(*sIt_2).GetPosition();
601  const double d = (fStPoint1 - fStPoint2).GetMag();
602  const TimeStamp t2 = sIt_2->GetRecData().GetSignalStartTime();
603  const double dt = fabs((t1 - t2).GetInterval());
604 
605  if (d < kIsoDist1 && dt < kIsoTime1)
606  ++n1;
607  if (d < kIsoDist2 && dt < kIsoTime2)
608  ++n2;
609  }
610 
611  if (n1 == 0)
612  sIt_1->SetRejected(sevt::StationConstants::eLonely);
613 
614  if (n1 && n2 < 2)
615  sIt_1->SetRejected(sevt::StationConstants::eLonely);
616  }
617  }
618 
619 
620  // ==============================================
621  // selection algorithm
622  // ==============================================
623 
624  bool
625  SdTopDownSignalSelectorUGR::PatternRecovering()
626  {
627  unsigned int ns = 0;
628  for (unsigned int is = 0; is < fAllSegments.size(); ++is)
629  if (fAllSegments[is].fCandidate)
630  ++ns;
631 
632  if (ns == 3) {
633  if (fNMinStations == 3)
634  return Recover3Stations(); // Note that 3 segments could not imply 3 stations
635  else
636  return false;
637  }
638  if (!EstimateCore())
639  return false;
640  fIsLastTimingIteration = false;
641  if (!IsGoodTimeConfig(eNone))
642  return false;
643  if (!IsGoodSpaceConfig())
644  return false;
645  fIsLastTimingIteration = true;
647  return false;
648  if (IsAligned())
649  return false;
650  return true;
651  }
652 
653 
654  bool
655  SdTopDownSignalSelectorUGR::TryRemovingStations(const int n)
656  {
657  if (n < 2) {
658  for (unsigned int is = 0; is < fIndexes[0]; ++is) {
659  fAllSegments[is].fCandidate = false;
660  if (PatternRecovering())
661  return true;
662  fAllSegments[is].fCandidate = true;
663  }
664  } else {
665  for (unsigned int is = n - 1; is < fIndexes[n - 1]; ++is) {
666  fAllSegments[is].fCandidate = false;
667  fIndexes[n - 2] = is;
668  if (TryRemovingStations(n - 1))
669  return true;
670  fAllSegments[is].fCandidate = true;
671  }
672  }
673  return false;
674  }
675 
676 
677  bool
678  SdTopDownSignalSelectorUGR::EstimateCore()
679  {
680  const CoordinateSystemPtr siteCS =
681  det::Detector::GetInstance().GetSiteCoordinateSystem();
682  const sdet::SDetector& sdetector = det::Detector::GetInstance().GetSDetector();
683 
684  Vector barySum(0, 0, 0, siteCS);
685  TimeInterval timeSum = 0;
686 
687  // the absolute points in time and space
688  const Point siteOrigin(0, 0, 0, siteCS);
689  const TimeStamp& eventTime = fSEvent->GetTrigger().GetTime();
690 
691  if (fVerbose > 2)
692  cout << " Estimating core..." << endl;
693 
694  const unsigned int size = fAllSegments.size();
695  double sumw = 0;
696  for (unsigned int is = 0; is < size; ++is) {
697  if (!fAllSegments[is].fCandidate)
698  continue;
699  const sevt::Station& station = *fAllSegments[is].fStEvt;
700 
701  const double weight = exp(kBaryPower * log(fAllSegments[is].fSignal));
702  barySum += weight * (sdetector.GetStation(station).GetPosition() - siteOrigin);
703  timeSum += weight *
704  (fAllSegments[is].fStartTime - eventTime).GetInterval();
705 
706  sumw += weight;
707  }
708  if (sumw == 0) {
709  if (fVerbose > 2)
710  cout << " ...FAILED." << endl;
711  return false;
712  }
713  barySum /= sumw;
714  fBarycenter = siteOrigin + barySum;
715  fBaryTime = eventTime + timeSum;
716 
717  timeSum /= sumw;
718 
719  fTCore = timeSum.GetInterval();
720  fXCore = barySum.GetX(siteCS);
721  fYCore = barySum.GetY(siteCS);
722  fZCore = barySum.GetZ(siteCS);
723 
724  if (fVerbose > 2)
725  cout << " ... Core(X,Y,Z,t): ("
726  << fXCore << " , "
727  << fYCore << " , "
728  << fZCore << " , "
729  << fTCore << ")" << endl;
730 
731  return true;
732  }
733 
734 
735  double
736  SdTopDownSignalSelectorUGR::CorrectTimeAltitude(const int is)
737  {
738  const CoordinateSystemPtr siteCS =
739  det::Detector::GetInstance().GetSiteCoordinateSystem();
740  const double costh = sqrt(max(0., 1 - fU * fU - fV * fV));
741  return costh * (fAllSegments[is].fStDet->GetPosition().GetZ(siteCS) - fZCore) / kSpeedOfLight;
742  }
743 
744 
745  double
746  SdTopDownSignalSelectorUGR::CorrectTimeAltitudeCurv(const int is)
747  {
748  // this is not used right now and probably shouldn't be used (HD)
749  const CoordinateSystemPtr siteCS =
750  det::Detector::GetInstance().GetSiteCoordinateSystem();
751  const double costh = sqrt(max(0., 1 - fU * fU - fV * fV));
752  const double dx = fAllSegments[is].fStDet->GetPosition().GetX(siteCS);
753  const double dy = fAllSegments[is].fStDet->GetPosition().GetY(siteCS);
754  const double d2 = dx * dx + dy * dy - pow(fU * dx + fV * dy, 2);
755  // WARNING: model of the curvature seems too simple (HD)
756  const double curv = kCurv0 * costh;
757  return (costh * (fAllSegments[is].fStDet->GetPosition().GetZ(siteCS) - fZCore) - curv * d2 / 2.) / kSpeedOfLight;
758  }
759 
760 
761  bool
762  SdTopDownSignalSelectorUGR::IsGoodTimeConfig(const TimeCorrectionType correctionType)
763  {
764  const CoordinateSystemPtr siteCS =
765  det::Detector::GetInstance().GetSiteCoordinateSystem();
766  unsigned int ns = 0;
767 
768  if (fVerbose > 2)
769  cout << " Checking for Good Time Configuration. Correction Type: " << correctionType << " ..." << endl;
770 
771  // const TimeStamp& eventTime = fSEvent->GetTrigger().GetTime();
772  const unsigned int size = fAllSegments.size();
773  double sumw = 0;
774  double sumx = 0;
775  double sumy = 0;
776  double sumx2 = 0;
777  double sumy2 = 0;
778  double sumxy = 0;
779  double sumt = 0;
780  double sumxt = 0;
781  double sumyt = 0;
782  for (unsigned int is = 0; is < size; ++is) {
783  if (!fAllSegments[is].fCandidate)
784  continue;
785 
786  const double dx = fAllSegments[is].fStDet->GetPosition().GetX(siteCS) - fXCore;
787  const double dy = fAllSegments[is].fStDet->GetPosition().GetY(siteCS) - fYCore;
788 
789  double dt;
790  if (correctionType == SdTopDownSignalSelectorUGR::eAltitude)
791  dt = CorrectTimeAltitude(is);
792  else if (correctionType == SdTopDownSignalSelectorUGR::eAltitudeCurved)
794  else if (correctionType == SdTopDownSignalSelectorUGR::eNone)
795  dt = 0;
796  else {
797  dt = 0;
798  INFO("Timing Correction Type not recognized. No correction done.");
799  }
800  dt += (fBaryTime - fAllSegments[is].fStartTime).GetInterval();
801  const double wgt = 1;
802  sumw += wgt;
803  sumx += wgt * dx;
804  sumy += wgt * dy;
805  sumx2 += wgt * dx * dx;
806  sumy2 += wgt * dy * dy;
807  sumxy += wgt * dx * dy;
808  sumt += wgt * dt;
809  sumxt += wgt * dt * dx;
810  sumyt += wgt * dt * dy;
811  ++ns;
812  }
813 
814  const double rxx = sumw * sumy2 - sumy * sumy;
815  const double ryy = sumw * sumx2 - sumx * sumx;
816  const double rxy = sumx * sumy - sumw * sumxy;
817  const double rx = sumxy * sumy - sumx * sumy2;
818  const double ry = sumxy * sumx - sumy * sumx2;
819  const double rr = sumx2 * sumy2 - sumxy * sumxy;
820  const double deter = sumx2 * rxx + sumxy * rxy + sumx * rx;
821 
822  if (deter == 0 || std::isnan(deter))
823  return false;
824  fU = (rxx * sumxt + rxy * sumyt + rx * sumt) / deter;
825  fV = (rxy * sumxt + ryy * sumyt + ry * sumt) / deter;
826  fT0 = (rx * sumxt + ry * sumyt + rr * sumt) / deter;
827  fU *= -kSpeedOfLight;
828  fV *= -kSpeedOfLight;
829 
831  return true;
832  if (fU * fU + fV * fV > 1)
833  return false;
834 
835  if (ns == 3)
836  return true;
837 
838  double sumdt2 = 0;
839  const double costh = sqrt(max(0., 1 - fU * fU - fV * fV));
840 
841  if (fVerbose > 3)
842  cout << " Weight sum: " << sumw
843  << "\t Residual Max: " << (ns - 2)*kTolResM* max(costh, 0.2) << endl;
844 
845  fResiduals.clear();
846  for (unsigned int is = 0; is < size; ++is) {
847  if (!fAllSegments[is].fCandidate || !fAllSegments[is].fStEvt->HasRecData())
848  continue; // trying patterns...
849  const double dx = fAllSegments[is].fStDet->GetPosition().GetX(siteCS) - fXCore;
850  const double dy = fAllSegments[is].fStDet->GetPosition().GetY(siteCS) - fYCore;
851  const double dt =
852  (fBaryTime - fAllSegments[is].fStartTime).GetInterval() - (fT0 - fU * dx / kSpeedOfLight - fV * dy / kSpeedOfLight);
853  sumdt2 += dt * dt;
854 
855  if (fVerbose > 3)
856  cout << " St: " << fAllSegments[is].fStEvt->GetId()
857  << "\tResidual: " << dt << " fabs: " << fabs(dt) << "\tLimit: " << (ns - 2)*kTolResM* max(costh, 0.2) << " --> ";
858 
859  if (fabs(dt) > (ns - 2)*kTolResM * max(costh, 0.2)) {
860  if (fVerbose > 3)
861  cout << " Pattern REJECTED." << endl;
862  return false;
863  }
864 
865  if (fVerbose > 3)
866  cout << " Segment ACCEPTED." << endl;
867  fAllSegments[is].fTimeResidual = dt;
868  fResiduals.push_back(dt);
869  }
870 
871  if (sqrt(sumdt2 / (ns - 3)) > (ns - 2)*kTolRes * max(costh, 0.2)) {
872  if (fVerbose > 3)
873  cout << " Mean RMS: " << sqrt(sumdt2 / (ns - 3)) << "\tMaxValue: " << (ns - 2)*kTolRes* max(costh, 0.2) << " --> REJECTED " << endl;
874  return false;
875  }
876 
877  const double sin2th = fU * fU + fV * fV;
878  if (sin2th >= 1 && bFirstIteration) {
879  if (fVerbose > 3)
880  cout << " REJECTED (firstIt && sin2th>1.)" << endl;
881  return false;
882  }
883  if (sin2th >= 1) {
884  fU /= sqrt(sin2th);
885  fV /= sqrt(sin2th);
886  }
887 
888  return true;
889  }
890 
891 
892  bool
893  SdTopDownSignalSelectorUGR::IsGoodSpaceConfig()
894  {
895  const CoordinateSystemPtr siteCS =
896  det::Detector::GetInstance().GetSiteCoordinateSystem();
897  const unsigned int ns = fAllSegments.size();
898  const double dist2_max_proj = pow(1300., 2) * (ns - 2);
899 
900  if (fVerbose > 2)
901  cout << " Checking Space Configuration..." << endl;
902 
903  if (fVerbose > 3)
904  cout << " Maximum Proj. Dist squared: " << dist2_max_proj << endl;
905 
906  for (int i = ns - 1; i >= 0; --i) {
907  if (!fAllSegments[i].fCandidate)
908  continue;
909  const double dx = fAllSegments[i].fStDet->GetPosition().GetX(siteCS) - fXCore;
910  const double dy = fAllSegments[i].fStDet->GetPosition().GetY(siteCS) - fYCore;
911  const double dist2 = pow(dx, 2) + pow(dy, 2) - pow(fU * dx + fV * dy, 2);
912  if (fVerbose > 3)
913  cout << " St: " << fAllSegments[i].fStEvt->GetId()
914  << "\tDist square: " << dist2 << " --> ";
915 
916  if (dist2 > dist2_max_proj) {
917  if (fVerbose > 3)
918  cout << " Pattern REJECTED." << endl;
919  return false;
920  }
921  if (fVerbose > 3)
922  cout << " St. ACCEPTED." << endl;
923  }
924  return true;
925  }
926 
927 
928  bool
929  SdTopDownSignalSelectorUGR::IsAligned()
930  {
931  const CoordinateSystemPtr siteCS =
932  det::Detector::GetInstance().GetSiteCoordinateSystem();
933  const unsigned int ns = fAllSegments.size();
934  double xmean = 0;
935  double ymean = 0;
936  for (unsigned int is = 0; is < ns; ++is) {
937  if (!fAllSegments[is].fCandidate)
938  continue;
939  xmean += fAllSegments[is].fStDet->GetPosition().GetX(siteCS);
940  ymean += fAllSegments[is].fStDet->GetPosition().GetY(siteCS);
941  }
942  xmean /= ns;
943  ymean /= ns;
944  vector<double> dx(ns);
945  vector<double> dy(ns);
946  for (unsigned int is = 0; is < ns; ++is) {
947  if (!fAllSegments[is].fCandidate)
948  continue;
949  dx[is] = fAllSegments[is].fStDet->GetPosition().GetX(siteCS) - xmean;
950  dy[is] = fAllSegments[is].fStDet->GetPosition().GetY(siteCS) - ymean;
951  }
952  double ixx = 0;
953  double ixy = 0;
954  double iyy = 0;
955  for (unsigned int is = 0; is < ns; ++is) {
956  if (!fAllSegments[is].fCandidate)
957  continue;
958  ixx += dx[is] * dx[is];
959  iyy += dy[is] * dy[is];
960  ixy += dx[is] * dy[is];
961  }
962  double zeta = 0.5 * atan2(2 * ixy, ixx - iyy);
963  vector<double> lg(ns);
964  vector<double> tr(ns);
965  for (unsigned int is = 0; is < ns; ++is) {
966  if (!fAllSegments[is].fCandidate)
967  continue;
968  lg[is] = dx[is] * cos(zeta) + dy[is] * sin(zeta);
969  tr[is] = dx[is] * sin(zeta) - dy[is] * cos(zeta);
970  }
971  double longi = 0;
972  double trans = 0;
973  for (unsigned int is = 0; is < ns; ++is) {
974  if (!fAllSegments[is].fCandidate)
975  continue;
976  longi += lg[is] * lg[is];
977  trans += tr[is] * tr[is];
978  }
979  longi = sqrt(longi);
980  trans = sqrt(trans);
981  if (longi < 300)
982  return true;
983 
984  if (trans < 300)
985  return true;
986 
987  return false;
988  }
989 
990 
991  double
992  SdTopDownSignalSelectorUGR::EstimatedZenith(const string& s)
993  {
994  if (s == "deg")
995  return asin(sqrt(fU * fU + fV * fV)) / degree;
996  return asin(sqrt(fU * fU + fV * fV));
997  }
998 
999 
1000  double
1001  SdTopDownSignalSelectorUGR::EstimatedAzimuth(const string& s)
1002  {
1003  if (s == "deg")
1004  return atan2(fV, fU) / degree;
1005  return atan2(fV, fU);
1006  }
1007 
1008 
1009  bool
1010  SdTopDownSignalSelectorUGR::Recover3Stations()
1011  {
1012  const CoordinateSystemPtr siteCS =
1013  det::Detector::GetInstance().GetSiteCoordinateSystem();
1014  const sdet::SDetector& sdetector = det::Detector::GetInstance().GetSDetector();
1015 
1016  int index[3];
1017  const unsigned int ns = fAllSegments.size();
1018  for (unsigned int i = 0, j = 0; i < ns; ++i) {
1019  if (!fAllSegments[i].fCandidate)
1020  continue;
1021 
1022  index[j] = i;
1023  ++j;
1024  }
1025 
1026  // area and maximal distance
1027  const double st1X = sdetector.GetStation(*fAllSegments[index[0]].fStEvt).GetPosition().GetX(siteCS);
1028  const double st1Y = sdetector.GetStation(*fAllSegments[index[0]].fStEvt).GetPosition().GetY(siteCS);
1029  const double st2X = sdetector.GetStation(*fAllSegments[index[1]].fStEvt).GetPosition().GetX(siteCS);
1030  const double st2Y = sdetector.GetStation(*fAllSegments[index[1]].fStEvt).GetPosition().GetY(siteCS);
1031  const double st3X = sdetector.GetStation(*fAllSegments[index[2]].fStEvt).GetPosition().GetX(siteCS);
1032  const double st3Y = sdetector.GetStation(*fAllSegments[index[2]].fStEvt).GetPosition().GetY(siteCS);
1033  const double deter =
1034  st1X * st2Y - st1Y * st2X +
1035  st2X * st3Y - st2Y * st3X +
1036  st3X * st1Y - st3Y * st1X;
1037  double dist2 = pow(st1X - st2X, 2) + pow(st1Y - st2Y, 2);
1038  dist2 = max(dist2, pow(st2X - st3X, 2) + pow(st2Y - st3Y, 2));
1039  dist2 = max(dist2, pow(st3X - st1X, 2) + pow(st3Y - st1Y, 2));
1040 
1041  // geometrical extension : cut on area of the triangle
1042  if (fabs(deter / 2) > kAreaMax || fabs(deter / 2) < kAreaMin)
1043  return false;
1044  // cut on distance between stations
1045  if (dist2 > pow(kDistMax, 2))
1046  return false;
1047  //--- computation of direction
1048 
1049  const double dt1 = (fAllSegments[index[1]].fStartTime -
1050  fAllSegments[index[0]].fStartTime).GetInterval();
1051  const double dt2 = (fAllSegments[index[2]].fStartTime -
1052  fAllSegments[index[0]].fStartTime).GetInterval();
1053 
1054  fU = kSpeedOfLight * ((st1Y - st3Y) * dt1 - (st1Y - st2Y) * dt2) / deter;
1055  fV = kSpeedOfLight * ((st3X - st1X) * dt1 - (st2X - st1X) * dt2) / deter;
1056 
1057  EstimateCore();
1058 
1059  fIsLastTimingIteration = false;
1061  return false;
1062 
1063  // fIsLastTimingIteration=true; if (!TopDownIsGoodTimeConfig(2)) return false;
1064  const double sin2th = fU * fU + fV * fV;
1065  if (sin2th > 1) {
1066  return false; // no SINTHMAX condition...
1067  }
1068  return true;
1069  }
1070 
1071 
1073  // Segment Identification
1075 
1077  SdTopDownSignalSelectorUGR::FoundSegments(sevt::Station& st)
1078  {
1079  // For station detector
1080  const sdet::Station& dStation =
1081  det::Detector::GetInstance().GetSDetector().GetStation(st);
1082 
1083  // For start time of the signal
1084  const double fadcBinSize = dStation.GetFADCBinSize();
1085  const StationGPSData& gpsData = st.GetGPSData();
1086  const TimeStamp gpsTime(gpsData.GetSecond(), gpsData.GetCorrectedNanosecond());
1087  const TimeStamp traceTime =
1088  gpsTime - TimeInterval(dStation.GetFADCTraceLength() * fadcBinSize);
1089 
1090  GeoSegmentCollection segments;
1091 
1092  const utl::TraceD& vemChargeTrace = GetVEMChargeTrace(st);
1093  const utl::TraceD& vemPeakTrace = st.GetVEMTrace();
1094 
1095  //sevt::Station::Signal subsegment(0,0,0,0);
1096  GeoSegment subsegment(0, 0, 0, 0., 0., 0., traceTime, &st, &dStation, true);
1097 
1098  double lowFactor = 1;
1099  if (st.IsHighGainSaturation()) {
1100  lowFactor *= fLowFactor;
1101  if (fVerbose)
1102  cout << " Station with High gain trace saturated. Using factor " << lowFactor << " for signal threshold." << endl;
1103  }
1104 
1105  if (fVerbose > 2)
1106  cout << "\n\t\t Scaning for segments..." << endl;
1107 
1108  // Uncomment next lines scan only betwen start signal bin and stop signal bin.
1109  // sevt::StationRecData & stRec = st.GetRecData();
1110  // for(int bin=stRec.GetSignalStartSlot(); bin<=stRec.GetSignalEndSlot(); ++bin ){
1111 
1112  // Search for elemental subsegments
1113  for (utl::TraceD::SizeType bin = vemChargeTrace.GetStart(); bin < vemChargeTrace.GetStop(); ++bin) {
1114  if (fVerbose > 4)
1115  cout << "\t\t\t Bin: " << bin
1116  << "\t Value: " << vemPeakTrace[bin]
1117  << " VEM Peak\t Value: " << vemChargeTrace[bin] << " VEM Charge" << endl;
1118  if (vemChargeTrace[bin] < (fSignalThreshold * lowFactor) && subsegment.fBinsOverThresh == 0)
1119  continue;
1120  else if (vemChargeTrace[bin] < (fSignalThreshold * lowFactor) && subsegment.fBinsOverThresh != 0) {
1121  if (fVerbose > 2)
1122  cout << "\t\t Adding new subsegment (start, stop, charge, bins): ("
1123  << subsegment.fStart << " , "
1124  << subsegment.fStop << " , "
1125  << subsegment.fCharge << " , "
1126  << subsegment.fAoP << " , "
1127  << subsegment.fBinsOverThresh << ")" << endl;
1128 
1129  // if((subsegment.fBinsOverThresh>=fMinSlots) && (subsegment.fCharge>=fMinSignal))
1130  segments.push_back(subsegment); // Store one segment
1131  // Init subsegment
1132  subsegment.fBinsOverThresh = 0;
1133  subsegment.fCharge = 0;
1134  subsegment.fAoP = 0;
1135  subsegment.fSignal = 0;
1136  subsegment.fStart = 0;
1137  subsegment.fStop = 0;
1138  subsegment.fStartTime = 0;
1139  } else if (vemChargeTrace[bin] >= (fSignalThreshold * lowFactor) && subsegment.fBinsOverThresh == 0) {
1140  subsegment.fStart = bin;
1141  subsegment.fStop = bin;
1142  subsegment.fCharge += vemChargeTrace[bin];
1143  subsegment.fSignal += vemPeakTrace[bin];
1144  ++subsegment.fBinsOverThresh;
1145  subsegment.fStartTime = traceTime + TimeInterval((bin - 0.5) * fadcBinSize);
1146  if (fVerbose >= 4)
1147  cout << "\t\t\t New segment starting: "
1148  << subsegment.fStart << " , "
1149  << subsegment.fStop << " , "
1150  << subsegment.fCharge << " , "
1151  << subsegment.fBinsOverThresh << endl;
1152  } else if (vemChargeTrace[bin] >= (fSignalThreshold * lowFactor) && subsegment.fBinsOverThresh != 0) {
1153  subsegment.fStop = bin;
1154  subsegment.fCharge += vemChargeTrace[bin];
1155  ++subsegment.fBinsOverThresh;
1156  subsegment.fSignal += vemPeakTrace[bin];
1157  if (fVerbose >= 4)
1158  cout << "\t\t\t Updating segment: "
1159  << subsegment.fStart << " , "
1160  << subsegment.fStop << " , "
1161  << subsegment.fCharge << " , "
1162  << subsegment.fBinsOverThresh << endl;
1163  }
1164  }
1165 
1166  if (segments.size() <= 1)
1167  return segments; // Only one segment or no segments
1168 
1169  if (fVerbose > 2)
1170  cout << "\n\t\t Merging subsegments..." << endl;
1171  if (fVerbose > 3)
1172  cout << "\t\t\t(Start, Stop, Charge, BinsOverThreshold)" << endl;
1173 
1174  // Merge subsegments into segments
1175  for (unsigned int seg = 0; seg < segments.size() - 1; ++seg) {
1176  //if (seg == segments.size()-2) break;
1177  if ((segments[seg].fStop + fMingap + segments[seg].fBinsOverThresh) > segments[seg + 1].fStart) { // Merge next segment
1178  if (fVerbose > 3)
1179  cout << "\t\t\t Merging: ("
1180  << segments[seg].fStart << " , "
1181  << segments[seg].fStop << " , "
1182  << segments[seg].fCharge << " , "
1183  << segments[seg].fBinsOverThresh << ") + ("
1184  << segments[seg + 1].fStart << " , "
1185  << segments[seg + 1].fStop << " , "
1186  << segments[seg + 1].fCharge << " , "
1187  << segments[seg + 1].fBinsOverThresh << ") = (";
1188 
1189  segments[seg].fStop = segments[seg + 1].fStop;
1190  segments[seg].fBinsOverThresh += segments[seg + 1].fBinsOverThresh;
1191  segments[seg].fCharge += segments[seg + 1].fCharge;
1192  segments[seg].fSignal += segments[seg + 1].fSignal;
1193 
1194  if (fVerbose > 3)
1195  cout << segments[seg].fStart << " , "
1196  << segments[seg].fStop << " , "
1197  << segments[seg].fCharge << " , "
1198  << segments[seg].fBinsOverThresh << ")" << endl;
1199 
1200  segments.erase(segments.begin() + seg + 1);
1201  --seg;
1202  }
1203  }
1204 
1205  if (fVerbose > 2)
1206  cout << "\n\t\t Deleting segments below threshold... " << endl;
1207  if (fVerbose > 3)
1208  cout << "\t\t\t(Start, Stop, Charge, BinsOverThreshold)" << endl;
1209  // Check for acceptable segments
1210  for (unsigned int seg = 0; seg < segments.size(); ++seg) {
1211  if (segments[seg].fBinsOverThresh >= fMinSlots && segments[seg].fCharge > fMinSignal) { // Good segment
1212  // Compute AoP
1213  double peak = 0;
1214  for (int bin = segments[seg].fStart; bin <= segments[seg].fStop; ++bin)
1215  peak = vemPeakTrace[bin] > peak ? vemPeakTrace[bin] : peak;
1216  segments[seg].fAoP = segments[seg].fCharge / peak;
1217  continue;
1218  }
1219 
1220  if (fVerbose > 3)
1221  cout << "\t\t\t Deleting segment: ("
1222  << segments[seg].fStart << " , "
1223  << segments[seg].fStop << " , "
1224  << segments[seg].fCharge << " , "
1225  << segments[seg].fBinsOverThresh << ")" << endl;
1226 
1227  segments.erase(segments.begin() + seg);
1228  --seg;
1229  }
1230 
1231  if (fVerbose > 1) {
1232  cout << "\n\t Selected segments: (Start, Stop, VEMCharge, AoP, VEMPeakSignal, BinsOverTh, SignalStartTime)" << endl;
1233  for (unsigned int seg = 0; seg < segments.size(); ++seg) {
1234  cout << "\t\t ("
1235  << segments[seg].fStart << " , "
1236  << segments[seg].fStop << " , "
1237  << segments[seg].fCharge << " , "
1238  << segments[seg].fAoP << " , "
1239  << segments[seg].fSignal << " , "
1240  << segments[seg].fBinsOverThresh << " , "
1241  << segments[seg].fStartTime.GetGPSNanoSecond() << ")" << endl;
1242  }
1243  }
1244 
1245  return segments;
1246  }
1247 
1248 
1249  bool
1251  const
1252  {
1253  return i.fCharge < j.fCharge;
1254  }
1255 
1256 
1257  bool
1259  const
1260  {
1261  cout << " Segment i: " << i.fCharge << " " << i.fCandidate << endl
1262  << " Segment j: " << j.fCharge << " " << j.fCandidate << endl
1263  << endl;
1264  if (!j.fCandidate)
1265  return true; //
1266  else if (!i.fCandidate)
1267  return false;
1268  else
1269  return i.fCharge > j.fCharge;
1270  }
1271 
1272 
1273  bool
1275  const
1276  {
1277  return i.fCharge * i.fBinsOverThresh > j.fCharge * j.fBinsOverThresh;
1278  }
1279 
1280 
1281  bool
1283  const
1284  {
1285  return i.fAoP > j.fAoP;
1286  }
1287 
1288 
1289  bool
1291  const
1292  {
1293  return i.fAoP * i.fBinsOverThresh > j.fAoP * j.fBinsOverThresh;
1294  }
1295 
1296 
1297  bool
1298  SdTopDownSignalSelectorUGR::SelectMainSegment(GeoSegmentCollection& segments)
1299  {
1300  // For the moment we select the segment with biggest signal.
1301  // sort(segments.begin(), segments.end(), ByDecreasingSignal());
1302  if (fVerbose > 1)
1303  cout << "\n Sorted segments by ";
1304 
1305  switch (fRejectionProcedure) {
1306  case 0:
1307  cout << "Signal";
1308  sort(segments.begin(), segments.end(), ByDecreasingSignal());
1309  break;
1310  case 1:
1311  cout << "Signal quality";
1312  sort(segments.begin(), segments.end(), ByDecreasingSignalQ());
1313  break;
1314  case 2:
1315  cout << "AoP";
1316  sort(segments.begin(), segments.end(), ByDecreasingAoP());
1317  break;
1318  case 3:
1319  cout << "AoP quality";
1320  sort(segments.begin(), segments.end(), ByDecreasingAoPQ());
1321  break;
1322  case 4:
1323  cout << "Signal quality (default for Top Down)";
1324  sort(segments.begin(), segments.end(), ByDecreasingSignalQ());
1325  break;
1326  default :
1327  cout << " Unrecognized Rejection Procedure. Setting to default: Signal Quality";
1328  fRejectionProcedure = 1;
1329  sort(segments.begin(), segments.end(), ByDecreasingSignalQ());
1330  break;
1331  }
1332 
1333  if (fVerbose > 1) {
1334  cout << ": " << endl;
1335  for (unsigned int seg = 0; seg < segments.size(); ++seg) {
1336  cout << "\t ("
1337  << segments[seg].fStart << " , "
1338  << segments[seg].fStop << " , "
1339  << segments[seg].fCharge << " , "
1340  << segments[seg].fAoP << " , "
1341  << segments[seg].fBinsOverThresh << ")" << endl;
1342  }
1343  }
1344  return true;
1345  }
1346 
1347 
1348  void
1349  SdTopDownSignalSelectorUGR::UpdateStations()
1350  {
1351  // For various segments in the same station, reject the ones with bigger Time Residual
1352  if (fVerbose > 2) {
1353  cout << " Will check duplicity of stations for the candidates out of the following segments\n"
1354  "\t (StId, Start, Stop, Charge, AoP, Cand, BinsOverThreshold, TimeResidual)" << endl;
1355  for (unsigned int i = 0; i < fAllSegments.size(); ++i) {
1356  cout << "\t ("
1357  << fAllSegments[i].fStEvt->GetId() << " , "
1358  << fAllSegments[i].fStart << " , "
1359  << fAllSegments[i].fStop << " , "
1360  << fAllSegments[i].fCharge << " , "
1361  << fAllSegments[i].fAoP << " , "
1362  << fAllSegments[i].fCandidate << " , "
1363  << fAllSegments[i].fBinsOverThresh << " , "
1364  << fAllSegments[i].fTimeResidual << ")" << endl;
1365  }
1366  }
1367 
1368  for (unsigned int i = 0; i < fAllSegments.size(); ++i) {
1369  if (!fAllSegments[i].fCandidate)
1370  continue;
1371  for (unsigned int j = i + 1; j < fAllSegments.size(); ++j) {
1372  if (!fAllSegments[j].fCandidate)
1373  continue;
1374  if (fAllSegments[i].fStEvt->GetId() == fAllSegments[j].fStEvt->GetId()) {
1375  if (abs(fAllSegments[i].fTimeResidual) < abs(fAllSegments[j].fTimeResidual)) {
1376  if (fVerbose > 2)
1377  cout << " Duplicate segment with bigger residual time rejected. Station " << fAllSegments[j].fStEvt->GetId() << endl;
1378  fAllSegments[j].fCandidate = false;
1379  } else {
1380  if (fVerbose > 2)
1381  cout << " Duplicate segment with bigger residual time rejected. Station " << fAllSegments[i].fStEvt->GetId() << endl;
1382  fAllSegments[i].fCandidate = false;
1383  }
1384  }
1385  }
1386  }
1387 
1388  // Update Stations
1389  if (fVerbose > 2) {
1390  cout << " Duplicate candidate segments checked and cleared (only one candidate per station)\n"
1391  "\t (StId, Start, Stop, Charge, AoP, Cand, BinsOverThreshold, TimeResidual)" << endl;
1392  for (unsigned int i = 0; i < fAllSegments.size(); ++i) {
1393  cout << "\t ("
1394  << fAllSegments[i].fStEvt->GetId() << " , "
1395  << fAllSegments[i].fStart << " , "
1396  << fAllSegments[i].fStop << " , "
1397  << fAllSegments[i].fCharge << " , "
1398  << fAllSegments[i].fAoP << " , "
1399  << fAllSegments[i].fCandidate << " , "
1400  << fAllSegments[i].fBinsOverThresh << " , "
1401  << fAllSegments[i].fTimeResidual << ")" << endl;
1402  }
1403  }
1404 
1405  // First we flag each rejected segment and delete it from the list.
1406  GeoSegmentCollection rejectedSegments;
1407  for (unsigned int seg = 0; seg < fAllSegments.size(); ++seg) {
1408  if (fAllSegments[seg].fCandidate)
1409  continue;
1410  UpdateStationValues(*fAllSegments[seg].fStEvt, fAllSegments[seg].fStart, fAllSegments[seg].fStop);
1411  //~ fAllSegments[seg].fStEvt->SetRejected(sevt::StationConstants::eOutOfTime);
1412  rejectedSegments.push_back(fAllSegments[seg]);
1413  fAllSegments.erase(fAllSegments.begin() + seg);
1414  --seg;
1415  }
1416  // Finally, if the rejected candidate's station doesn't have a candidate segment at all, we set the station to rejected.
1417  for (unsigned int r = 0; r < rejectedSegments.size(); ++r) {
1418  bool rejectCurrSt = true;
1419  for (unsigned int seg = 0; seg < fAllSegments.size() && rejectCurrSt; ++seg) {
1420  if (rejectedSegments[r].fStEvt == fAllSegments[seg].fStEvt)
1421  rejectCurrSt = false;
1422  }
1423  if (rejectCurrSt)
1424  rejectedSegments[r].fStEvt->SetRejected(sevt::StationConstants::eOutOfTime);
1425  }
1426 
1427  if (fVerbose > 2) {
1428  cout << " Duplicate segments deleted. Final segments to update\n"
1429  "\t (StId, Start, Stop, Charge, AoP, Cand, BinsOverThreshold, TimeResidual)" << endl;
1430  for (unsigned int i = 0; i < fAllSegments.size(); ++i) {
1431  cout << "\t ("
1432  << fAllSegments[i].fStEvt->GetId() << " , "
1433  << fAllSegments[i].fStart << " , "
1434  << fAllSegments[i].fStop << " , "
1435  << fAllSegments[i].fCharge << " , "
1436  << fAllSegments[i].fAoP << " , "
1437  << fAllSegments[i].fCandidate << " , "
1438  << fAllSegments[i].fBinsOverThresh << " , "
1439  << fAllSegments[i].fTimeResidual << ")" << endl;
1440  }
1441  }
1442 
1443  // Now we update the segments with the final criteria for a segment definition and update the station values.
1444  for (unsigned int seg = 0; seg < fAllSegments.size(); ++seg) {
1445  if (!fAllSegments[seg].fCandidate)
1446  continue;
1447  UpdateSegmentValues(seg);
1448  UpdateStationValues(*fAllSegments[seg].fStEvt, fAllSegments[seg].fStart, fAllSegments[seg].fStop);
1449  fAllSegments[seg].fStEvt->SetCandidate();
1450  }
1451 
1452  if (fVerbose > 2) {
1453  cout << " updated segments:\n"
1454  "\t (StId, Start, Stop, Charge, AoP, Cand, BinsOverThreshold, TimeResidual)" << endl;
1455  for (unsigned int i = 0; i < fAllSegments.size(); ++i) {
1456  cout << "\t ("
1457  << fAllSegments[i].fStEvt->GetId() << " , "
1458  << fAllSegments[i].fStart << " , "
1459  << fAllSegments[i].fStop << " , "
1460  << fAllSegments[i].fCharge << " , "
1461  << fAllSegments[i].fAoP << " , "
1462  << fAllSegments[i].fCandidate << " , "
1463  << fAllSegments[i].fBinsOverThresh << " , "
1464  << fAllSegments[i].fTimeResidual << ")" << endl;
1465  }
1466  }
1467  }
1468 
1469 
1470  bool
1471  SdTopDownSignalSelectorUGR::UpdateStationValues(sevt::Station& st, const int start, const int stop)
1472  {
1473  sevt::StationRecData& stRec = st.GetRecData();
1474  stRec.SetSignalStartSlot(start);
1475  stRec.SetSignalEndSlot(stop);
1476 
1477  {
1478  const TraceD& vemTrace = st.GetVEMTrace();
1479  double peak = 0;
1480  for (int i = start; i < stop; ++i) {
1481  const double val = vemTrace[i];
1482  if (val > peak)
1483  peak = val;
1484  }
1485  stRec.SetPeakAmplitude(peak);
1486  }
1487 
1488  const sdet::Station& dStation =
1489  det::Detector::GetInstance().GetSDetector().GetStation(st);
1490 
1491  // bool highGainSaturation = false;
1492  // bool lowGainSaturation = false;
1493  int nPMTs = 0;
1494  double totalCharge = 0;
1499  for (Station::PMTIterator pmtIt = st.PMTsBegin();
1500  pmtIt != st.PMTsEnd(); ++pmtIt) {
1501  if (pmtIt->HasCalibData() && pmtIt->GetCalibData().IsTubeOk()) {
1502  PMTRecData& pmtRec = pmtIt->GetRecData();
1503  // if (pmtRec.GetFADCSaturatedBins(PMTConstants::eHighGain)) // set but not used
1504  // highGainSaturation = true;
1505  // if (pmtRec.GetFADCSaturatedBins(PMTConstants::eLowGain))
1506  // set but not used
1507  // lowGainSaturation = true;
1508  const TraceD& vemTrace = pmtRec.GetVEMTrace();
1509  double charge = 0;
1510  for (int i = start; i < stop; ++i)
1511  charge += vemTrace[i];
1512  ComputeShapeRiseFallPeak(pmtRec, dStation.GetFADCBinSize(), start, start, stop, charge);
1513  charge *= pmtRec.GetVEMPeak() / pmtRec.GetVEMCharge();
1514  pmtRec.SetTotalCharge(charge);
1515  totalCharge += charge;
1516  shapeStat(pmtRec.GetShapeParameter());
1517  riseStat(pmtRec.GetRiseTime());
1518  fallStat(pmtRec.GetFallTime());
1519  t50Stat(pmtRec.GetT50());
1520  const double peak = pmtRec.GetPeakAmplitude();
1521  if (peak)
1522  pmtRec.SetAreaOverPeak(charge / peak);
1523  ++nPMTs;
1524  }
1525  }
1526  totalCharge /= nPMTs;
1527 
1528  // this is done on the pmt vem traces due to individual pmt vem peak/charge values
1529  stRec.SetTotalSignal(totalCharge);
1530  // if (totalCharge <= 0)
1531  // return false;
1532 
1533  const StationGPSData& gpsData = st.GetGPSData();
1534 
1535  // timing of the trace END
1536  const TimeStamp gpsTime(gpsData.GetSecond(), gpsData.GetCorrectedNanosecond());
1537 
1538  const double fadcBinSize = dStation.GetFADCBinSize();
1539 
1540  // timing of the trace BEGINNING
1541  const TimeStamp traceTime = gpsTime -
1542  TimeInterval(dStation.GetFADCTraceLength() * fadcBinSize);
1543  st.SetTraceStartTime(traceTime);
1544 
1545  // timing of the SIGNAL START
1546  const TimeStamp signalTime = traceTime +
1547  TimeInterval((start - 0.5) * fadcBinSize);
1548  stRec.SetSignalStartTime(signalTime);
1549 
1550  return true;
1551  }
1552 
1553 
1554  // Copy paste from SdCalibratorOG
1555  // set rise/fall time for PMT trace and return shape parameter
1556  void
1557  SdTopDownSignalSelectorUGR::ComputeShapeRiseFallPeak(PMTRecData& pmtRec,
1558  const double binSize,
1559  const unsigned int startBin,
1560  const unsigned int startIntegration,
1561  const unsigned int endIntegration,
1562  const double traceIntegral)
1563  const
1564  {
1565  // sorry for not using the nice TraceAlgorithms, but all this values can
1566  // be calculated in single trace pass
1567 
1568  if (traceIntegral <= 0)
1569  return;
1570 
1571  const double riseStartSentry = fRiseTimeFractions.first * traceIntegral;
1572  const double riseEndSentry = fRiseTimeFractions.second * traceIntegral;
1573  const double fallStartSentry = fFallTimeFractions.first * traceIntegral;
1574  const double fallEndSentry = fFallTimeFractions.second * traceIntegral;
1575  const double binTiming = binSize;
1576  const unsigned int shapeSentry =
1577  startIntegration + (unsigned int)(600 * nanosecond / binTiming);
1578  const double t50Sentry = 0.5 * traceIntegral;
1579  double riseStartBin = 0;
1580  double riseEndBin = 0;
1581  double fallStartBin = 0;
1582  double fallEndBin = 0;
1583  double t50Bin = 0;
1584  double sumEarly = 0;
1585 
1586  double peakAmplitude = 0;
1587  double runningSum = 0;
1588  double oldSum = 0;
1589 
1590  const TraceD& trace = pmtRec.GetVEMTrace();
1591 
1592  for (unsigned int i = startIntegration; i < endIntegration; ++i) {
1593 
1594  const double binValue = trace[i];
1595  runningSum += binValue;
1596 
1597  if (peakAmplitude < binValue)
1598  peakAmplitude = binValue;
1599 
1600  if (!sumEarly && i >= shapeSentry)
1601  sumEarly = oldSum;
1602 
1603  if (!riseStartBin && runningSum > riseStartSentry)
1604  riseStartBin = i - (runningSum - riseStartSentry) / (runningSum - oldSum);
1605 
1606  if (!riseEndBin && runningSum > riseEndSentry)
1607  riseEndBin = i - (runningSum - riseEndSentry) / (runningSum - oldSum);
1608 
1609  if (!fallStartBin && runningSum > fallStartSentry)
1610  fallStartBin = i - (runningSum - fallStartSentry) / (runningSum - oldSum);
1611 
1612  if (!fallEndBin && runningSum > fallEndSentry)
1613  fallEndBin = i - (runningSum - fallEndSentry) / (runningSum - oldSum);
1614 
1615  if (!t50Bin && runningSum > t50Sentry)
1616  t50Bin = i - (runningSum - t50Sentry) / (runningSum - oldSum);
1617 
1618  oldSum = runningSum;
1619 
1620  }
1621 
1622  pmtRec.SetPeakAmplitude(peakAmplitude);
1623  pmtRec.SetRiseTime(binTiming * (riseEndBin - riseStartBin), 0);
1624  pmtRec.SetFallTime(binTiming * (fallEndBin - fallStartBin), 0);
1625  pmtRec.SetT50(binTiming * (t50Bin - startBin));
1626  const double sumLate = runningSum - sumEarly;
1627  if (shapeSentry < endIntegration && sumLate > 0)
1628  pmtRec.SetShapeParameter(sumEarly / sumLate);
1629  }
1630 
1631 
1632  TraceD
1633  SdTopDownSignalSelectorUGR::GetVEMChargeTrace(const sevt::Station& station)
1634  const
1635  {
1636 
1637  const sdet::Station& dStation =
1638  det::Detector::GetInstance().GetSDetector().GetStation(station);
1639 
1640  vector<const PMT*> validPMTs;
1641 
1642  TraceD vemTrace(dStation.GetFADCTraceLength(), dStation.GetFADCBinSize(),
1644 
1645  const int traceLength = vemTrace.GetSize();
1646  for (int i = 0; i < traceLength; ++i)
1647  vemTrace[i] = 0;
1648 
1649  for (Station::ConstPMTIterator pmtIt = station.PMTsBegin();
1650  pmtIt != station.PMTsEnd(); ++pmtIt)
1651  if (pmtIt->HasCalibData() && pmtIt->GetCalibData().IsTubeOk() &&
1652  pmtIt->HasRecData() && pmtIt->GetRecData().HasVEMTrace())
1653  validPMTs.push_back(&(*pmtIt));
1654 
1655  if (!validPMTs.empty()) {
1656  const int nPMTs = validPMTs.size();
1657  for (vector<const PMT*>::const_iterator pmtIt = validPMTs.begin();
1658  pmtIt != validPMTs.end(); ++pmtIt) {
1659  const PMTRecData& pmtRec = (*pmtIt)->GetRecData();
1660  const TraceD& pmtTrace = pmtRec.GetVEMTrace();
1661  const double peakChargeFactor = pmtRec.GetVEMPeak() / pmtRec.GetVEMCharge();
1662  for (int i = 0; i < traceLength; ++i)
1663  vemTrace[i] += (pmtTrace[i] * peakChargeFactor) / nPMTs;
1664  }
1665  }
1666 
1667  return vemTrace;
1668  }
1669 
1670 
1672  SdTopDownSignalSelectorUGR::FoundBasicSegments(sevt::Station& st)
1673  {
1674  // For station detector
1675  const sdet::Station& dStation =
1676  det::Detector::GetInstance().GetSDetector().GetStation(st);
1677 
1678  // For start time of the signal
1679  const double fadcBinSize = dStation.GetFADCBinSize();
1680  const StationGPSData& gpsData = st.GetGPSData();
1681  const TimeStamp gpsTime(gpsData.GetSecond(), gpsData.GetCorrectedNanosecond());
1682  const TimeStamp traceTime = gpsTime -
1683  TimeInterval(dStation.GetFADCTraceLength() * fadcBinSize);
1684 
1685  GeoSegmentCollection segments;
1686 
1687  const utl::TraceD& vemChargeTrace = GetVEMChargeTrace(st);
1688  const utl::TraceD& vemPeakTrace = st.GetVEMTrace();
1689 
1690  //sevt::Station::Signal subsegment(0,0,0,0);
1691  GeoSegment subsegment(0, 0, 0, 0., 0., 0., traceTime, &st, &dStation, true);
1692 
1693  double lowFactor = 1;
1694  if (st.IsHighGainSaturation()) {
1695  lowFactor *= fLowFactor;
1696  if (fVerbose)
1697  cout << " Station with High gain trace saturated. Using factor " << lowFactor << " for signal threshold." << endl;
1698  }
1699 
1700  if (fVerbose > 2)
1701  cout << "\n\t\t Scaning for segments..." << endl;
1702 
1703  // Search for elemental subsegments
1704  for (utl::TraceD::SizeType bin = vemChargeTrace.GetStart(); bin < vemChargeTrace.GetStop(); ++bin) {
1705  if (fVerbose > 4)
1706  cout << "\t\t\t Bin: " << bin
1707  << "\t Value: " << vemPeakTrace[bin]
1708  << " VEM Peak\t Value: " << vemChargeTrace[bin] << " VEM Charge" << endl;
1709  if (vemChargeTrace[bin] < fPreSignalThreshold * lowFactor && subsegment.fBinsOverThresh == 0)
1710  continue;
1711  else if (vemChargeTrace[bin] < fPreSignalThreshold * lowFactor && subsegment.fBinsOverThresh != 0) {
1712  if (fVerbose > 2)
1713  cout << "\t\t Adding new subsegment (start, stop, charge, bins): ("
1714  << subsegment.fStart << " , "
1715  << subsegment.fStop << " , "
1716  << subsegment.fCharge << " , "
1717  << subsegment.fAoP << " , "
1718  << subsegment.fBinsOverThresh << ")" << endl;
1719 
1720  // if((subsegment.fBinsOverThresh>=fMinSlots) && (subsegment.fCharge>=fMinSignal))
1721  segments.push_back(subsegment); // Store one segment
1722  // Init subsegment
1723  subsegment.fBinsOverThresh = 0;
1724  subsegment.fCharge = 0;
1725  subsegment.fAoP = 0;
1726  subsegment.fSignal = 0;
1727  subsegment.fStart = 0;
1728  subsegment.fStop = 0;
1729  subsegment.fStartTime = 0;
1730  } else if (vemChargeTrace[bin] >= fPreSignalThreshold * lowFactor && subsegment.fBinsOverThresh == 0) {
1731  subsegment.fStart = bin;
1732  subsegment.fStop = bin;
1733  subsegment.fCharge += vemChargeTrace[bin];
1734  subsegment.fSignal += vemPeakTrace[bin];
1735  ++subsegment.fBinsOverThresh;
1736  subsegment.fStartTime = traceTime + TimeInterval((bin - 0.5) * fadcBinSize);
1737  if (fVerbose >= 4)
1738  cout << "\t\t\t New segment starting: "
1739  << subsegment.fStart << " , "
1740  << subsegment.fStop << " , "
1741  << subsegment.fCharge << " , "
1742  << subsegment.fBinsOverThresh << endl;
1743  } else if (vemChargeTrace[bin] >= fPreSignalThreshold * lowFactor && subsegment.fBinsOverThresh != 0) {
1744  subsegment.fStop = bin;
1745  subsegment.fCharge += vemChargeTrace[bin];
1746  ++subsegment.fBinsOverThresh;
1747  subsegment.fSignal += vemPeakTrace[bin];
1748  if (fVerbose >= 4)
1749  cout << "\t\t\t Updating segment: "
1750  << subsegment.fStart << " , "
1751  << subsegment.fStop << " , "
1752  << subsegment.fCharge << " , "
1753  << subsegment.fBinsOverThresh << endl;
1754  }
1755  }
1756 
1757  if (segments.size() <= 1)
1758  return segments; // Only one segment or no segments
1759 
1760  if (fVerbose > 2)
1761  cout << "\n\t\t Merging subsegments..." << endl;
1762  if (fVerbose > 3)
1763  cout << "\t\t\t(Start, Stop, Charge, BinsOverThreshold)" << endl;
1764 
1765  // Merge subsegments into segments
1766  for (unsigned int seg = 0; seg < segments.size() - 1; ++seg) {
1767  // if(seg==(segments.size()-2)) break;
1768  if ((segments[seg].fStop + fPreMingap + segments[seg].fBinsOverThresh) > segments[seg + 1].fStart) { // Merge next segment
1769  if (fVerbose > 3)
1770  cout << "\t\t\t Merging: ("
1771  << segments[seg].fStart << " , "
1772  << segments[seg].fStop << " , "
1773  << segments[seg].fCharge << " , "
1774  << segments[seg].fBinsOverThresh << ") + ("
1775  << segments[seg + 1].fStart << " , "
1776  << segments[seg + 1].fStop << " , "
1777  << segments[seg + 1].fCharge << " , "
1778  << segments[seg + 1].fBinsOverThresh << ") = (";
1779 
1780  segments[seg].fStop = segments[seg + 1].fStop;
1781  segments[seg].fBinsOverThresh += segments[seg + 1].fBinsOverThresh;
1782  segments[seg].fCharge += segments[seg + 1].fCharge;
1783  segments[seg].fSignal += segments[seg + 1].fSignal;
1784 
1785  if (fVerbose > 3)
1786  cout << segments[seg].fStart << " , "
1787  << segments[seg].fStop << " , "
1788  << segments[seg].fCharge << " , "
1789  << segments[seg].fBinsOverThresh << ")" << endl;
1790 
1791  segments.erase(segments.begin() + seg + 1);
1792  --seg;
1793  }
1794  }
1795 
1796  if (fVerbose > 2)
1797  cout << "\n\t\t Deleting Pre segments below threshold... " << endl;
1798  if (fVerbose > 3)
1799  cout << "\t\t\t(Start, Stop, Charge, BinsOverThreshold)" << endl;
1800  // Check for acceptable segments
1801  for (unsigned int seg = 0; seg < segments.size(); ++seg) {
1802  if (segments[seg].fBinsOverThresh >= fPreMinSlots && segments[seg].fCharge > fPreMinSignal) { // Good segment
1803  // Compute AoP
1804  double peak = 0;
1805  for (int bin = segments[seg].fStart; bin <= segments[seg].fStop; ++bin)
1806  peak = vemPeakTrace[bin] > peak ? vemPeakTrace[bin] : peak;
1807  segments[seg].fAoP = segments[seg].fCharge / peak;
1808  continue;
1809  }
1810 
1811  if (fVerbose > 3)
1812  cout << "\t\t\t Deleting segment: ("
1813  << segments[seg].fStart << " , "
1814  << segments[seg].fStop << " , "
1815  << segments[seg].fCharge << " , "
1816  << segments[seg].fBinsOverThresh << ")" << endl;
1817 
1818  segments.erase(segments.begin() + seg);
1819  --seg;
1820  }
1821 
1822  if (fVerbose > 1) {
1823  cout << "\n\t Selected segments: (Start, Stop, VEMCharge, AoP, VEMPeakSignal, BinsOverTh, SignalStartTime)" << endl;
1824  for (unsigned int seg = 0; seg < segments.size(); ++seg) {
1825  cout << "\t\t ("
1826  << segments[seg].fStart << " , "
1827  << segments[seg].fStop << " , "
1828  << segments[seg].fCharge << " , "
1829  << segments[seg].fAoP << " , "
1830  << segments[seg].fSignal << " , "
1831  << segments[seg].fBinsOverThresh << " , "
1832  << segments[seg].fStartTime.GetGPSNanoSecond() << ")" << endl;
1833  }
1834  }
1835 
1836  return segments;
1837  }
1838 
1839 
1840  void
1841  SdTopDownSignalSelectorUGR::UpdateSegmentValues(const int seg)
1842  {
1843  sevt::Station& st = *(fAllSegments[seg].fStEvt);
1844 
1845  if (fVerbose > 2)
1846  cout << "\n\t\t Updating segment for station: " << st.GetId()
1847  << "\n\t\t (Start, Stop): (" << fAllSegments[seg].fStart
1848  << " , " << fAllSegments[seg].fStop << endl;
1849 
1850  GeoSegmentCollection segments;
1851 
1852  const utl::TraceD& vemChargeTrace = GetVEMChargeTrace(st);
1853  utl::TraceD& vemPeakTrace = st.GetVEMTrace();
1854 
1855  //sevt::Station::Signal subsegment(0,0,0,0);
1856  GeoSegment subsegment(0, 0, 0, 0., 0., 0., 0, NULL, NULL, true);
1857 
1858  double lowFactor = 1;
1859  if (st.IsHighGainSaturation()) {
1860  if (fVerbose)
1861  cout << " Station with High gain trace saturated. Using factor " << lowFactor << " for signal threshold." << endl;
1862  lowFactor *= fLowFactor;
1863  }
1864 
1865  if (fVerbose > 2)
1866  cout << "\n\t\t Scaning for segments..." << endl;
1867 
1868  // Search for elemental subsegments
1869  for (utl::TraceD::SizeType bin = fAllSegments[seg].fStop; bin < vemChargeTrace.GetStop(); ++bin) {
1870 
1871  if ((fAllSegments[seg].fStop + fMingap + fAllSegments[seg].fBinsOverThresh) < int(bin) &&
1872  !segments.size() && !subsegment.fStart) {
1873  if (fVerbose > 2)
1874  cout << "\t\tNo more segments found " << endl;
1875  return;
1876  }
1877 
1878  if (fVerbose > 4)
1879  cout << "\t\t\t Bin: " << bin
1880  << "\t Value: " << vemPeakTrace[bin]
1881  << " VEM Peak\t Value: " << vemChargeTrace[bin] << " VEM Charge" << endl;
1882  if (vemChargeTrace[bin] < fSignalThreshold * lowFactor && subsegment.fBinsOverThresh == 0)
1883  continue;
1884  else if (vemChargeTrace[bin] < fSignalThreshold * lowFactor && subsegment.fBinsOverThresh != 0) {
1885  if (fVerbose > 2)
1886  cout << "\t\t Adding new subsegment (start, stop, charge, bins): ("
1887  << subsegment.fStart << " , "
1888  << subsegment.fStop << " , "
1889  << subsegment.fCharge << " , "
1890  << subsegment.fAoP << " , "
1891  << subsegment.fBinsOverThresh << ")" << endl;
1892 
1893  segments.push_back(subsegment); // Store one segment
1894  // Init subsegment
1895  subsegment.fBinsOverThresh = 0;
1896  subsegment.fCharge = 0;
1897  subsegment.fAoP = 0;
1898  subsegment.fSignal = 0;
1899  subsegment.fStart = 0;
1900  subsegment.fStop = 0;
1901  subsegment.fStartTime = 0;
1902  } else if (vemChargeTrace[bin] >= fSignalThreshold * lowFactor && subsegment.fBinsOverThresh == 0) {
1903  subsegment.fStart = bin;
1904  subsegment.fStop = bin;
1905  subsegment.fCharge += vemChargeTrace[bin];
1906  subsegment.fSignal += vemPeakTrace[bin];
1907  ++subsegment.fBinsOverThresh;
1908 
1909  //If first subsegment founded is far enought return
1910  if ((fAllSegments[seg].fStop + fMingap + fAllSegments[seg].fBinsOverThresh) < int(bin)) {
1911  if (fVerbose > 2)
1912  cout << "\t\tNo more segments found " << endl;
1913  return;
1914  }
1915 
1916  if (fVerbose >= 4)
1917  cout << "\t\t\t New segment starting: "
1918  << subsegment.fStart << " , "
1919  << subsegment.fStop << " , "
1920  << subsegment.fCharge << " , "
1921  << subsegment.fBinsOverThresh << endl;
1922  } else if (vemChargeTrace[bin] >= fSignalThreshold * lowFactor && subsegment.fBinsOverThresh != 0) {
1923  subsegment.fStop = bin;
1924  subsegment.fCharge += vemChargeTrace[bin];
1925  ++subsegment.fBinsOverThresh;
1926  subsegment.fSignal += vemPeakTrace[bin];
1927  if (fVerbose >= 4)
1928  cout << "\t\t\t Updating segment: "
1929  << subsegment.fStart << " , "
1930  << subsegment.fStop << " , "
1931  << subsegment.fCharge << " , "
1932  << subsegment.fBinsOverThresh << endl;
1933  }
1934  }
1935 
1936  // Merge subsegments into segments
1937  for (unsigned int i = 0; i < segments.size(); ++i) {
1938  if ((fAllSegments[seg].fStop + fMingap + fAllSegments[seg].fBinsOverThresh) > segments[i].fStart) { // Merge next segment
1939  if (fVerbose > 3)
1940  cout << "\t\t\t Merging: ("
1941  << fAllSegments[seg].fStart << " , "
1942  << fAllSegments[seg].fStop << " , "
1943  << fAllSegments[seg].fCharge << " , "
1944  << fAllSegments[seg].fBinsOverThresh << ") + ("
1945  << segments[i].fStart << " , "
1946  << segments[i].fStop << " , "
1947  << segments[i].fCharge << " , "
1948  << segments[i].fBinsOverThresh << ") = (";
1949 
1950  fAllSegments[seg].fStop = segments[i].fStop;
1951  fAllSegments[seg].fBinsOverThresh += segments[i].fBinsOverThresh;
1952  fAllSegments[seg].fCharge += segments[i].fCharge;
1953  fAllSegments[seg].fSignal += segments[i].fSignal;
1954 
1955  if (fVerbose > 3)
1956  cout << fAllSegments[seg].fStart << " , "
1957  << fAllSegments[seg].fStop << " , "
1958  << fAllSegments[seg].fCharge << " , "
1959  << fAllSegments[seg].fBinsOverThresh << ")" << endl;
1960  }
1961  }
1962 
1963  // Recompute AoP
1964  {
1965  double peak = 0;
1966  for (int bin = fAllSegments[seg].fStart; bin <= fAllSegments[seg].fStop; ++bin)
1967  peak = vemPeakTrace[bin] > peak ? vemPeakTrace[bin] : peak;
1968  fAllSegments[seg].fAoP = fAllSegments[seg].fCharge / peak;
1969  }
1970 
1971  if (fVerbose > 3)
1972  cout << "\t\t\t Merging done! " << endl;
1973  }
1974 
1975 }
double GetVEMCharge() const
Definition: PMTRecData.h:130
Branch GetTopBranch() const
Definition: Branch.cc:63
Class to access station level reconstructed data.
static bool bFirstIteration
void SetCurvature(const double curvature, const double error)
gaussian curvature = 1 / Rc
utl::TraceD & GetVEMTrace(const StationConstants::SignalComponent source=StationConstants::eTotal)
Traces calibrated in VEM Peak.
Definition: PMTRecData.h:46
void SetTotalSignal(const double signal, const double sErr=0)
Total integrated signal in VEM unit, averaged over pmts.
int GetId() const
Get the station Id.
const double degree
Point object.
Definition: Point.h:32
std::vector< GeoSegment > GeoSegmentCollection
void SetBarycenter(const utl::Point &bary)
Detector description interface for Station-related data.
Report success to RunController.
Definition: VModule.h:62
void SetSignalStartSlot(const unsigned int slot)
Start time of the signal in time slots from beginning of trace.
bool operator()(const GeoSegment &i, const GeoSegment &j) const
double GetRiseTime() const
Average rise time from the PMTs.
Definition: PMTRecData.h:97
SizeType fStart
Definition: Trace.h:224
Interface class to access to the SD Reconstruction of a Shower.
SizeType GetStop() const
Get valid data stop bin.
Definition: Trace.h:148
bool HasRecShower() const
PMTIterator PMTsBegin(const sdet::PMTConstants::PMTType type=sdet::PMTConstants::eWaterCherenkovLarge)
begin PMT iterator for read/write
void SetShapeParameter(const double shape)
Definition: PMTRecData.h:207
void SetAreaOverPeak(const double areaOverPeak)
Definition: PMTRecData.h:201
Skip remaining modules in the current loop and continue with next iteration of the loop...
Definition: VModule.h:68
double GetFallTime() const
Average fall time from the PMTs.
Definition: PMTRecData.h:103
ShowerRecData & GetRecShower()
void SetPeakAmplitude(const double peak)
Amplitude of signal Peak in VEM-Peak unit,averaged over pmts.
bool is(const double a, const double b)
Definition: testlib.cc:113
EventTrigger & GetTrigger()
Get the object with central trigger data, throw if n.a.
Definition: SEvent.h:148
unsigned int GetSecond() const
Get end of traces raw time.
void SetFallTime(const double fallTime, const double rms)
Definition: PMTRecData.h:177
sevt::StationRecData & GetRecData()
Get station level reconstructed data.
#define INFO(message)
Macro for logging informational messages.
Definition: ErrorLogger.h:161
bool IsInGrid(const SDetectorConstants::GridIndex index=SDetectorConstants::eStandard) const
Tells whether the station is in the regular triangular grid.
void SetTraceStartTime(const utl::TimeStamp &Time)
Set absolute start time of the VEM trace.
boost::filter_iterator< CandidateStationFilter, StationIterator > CandidateStationIterator
Iterator over candidate stations.
Definition: SEvent.h:68
void Init()
Initialise the registry.
Branch GetChild(const std::string &childName) const
Get child of this Branch by child name.
Definition: Branch.cc:211
double pow(const double x, const unsigned int i)
bool IsHighGainSaturation() const
void SortStations(const OrderingCriterion ord) const
Sort the list of stations by the criterion specified in an OrderingCriterion object.
Definition: SEvent.h:172
A TimeStamp holds GPS second and nanosecond for some event.
Definition: TimeStamp.h:110
utl::TraceD & GetVEMTrace(const StationConstants::SignalComponent source=StationConstants::eTotal)
signal trace calibrated in [VEM charge]
utl::Point GetPosition() const
Tank position.
Criterion to sort stations by increasing signal.
Definition: SortCriteria.h:25
CandidateStationIterator CandidateStationsBegin()
Definition: SEvent.h:72
void SetPeakAmplitude(const double peak)
Definition: PMTRecData.h:206
boost::shared_ptr< const CoordinateTransformer > CoordinateSystemPtr
Shared pointer for coordinate systems.
#define max(a, b)
Class representing a document branch.
Definition: Branch.h:107
class to hold data at Station level
constexpr double s
Definition: AugerUnits.h:163
class to hold reconstructed data at PMT level
Definition: PMTRecData.h:38
double GetX(const CoordinateSystemPtr &coordinateSystem) const
Definition: BasicVector.h:206
std::vector< double >::size_type SizeType
Definition: Trace.h:58
const double ns
constexpr double nanosecond
Definition: AugerUnits.h:143
double abs(const SVector< n, T > &v)
void SetAxis(const utl::Vector &axis)
bool operator()(const GeoSegment &i, const GeoSegment &j) const
bool IsGoodTimeConfig(const TimeCorrectionType correctionType)
PMTIterator PMTsEnd(const sdet::PMTConstants::PMTType type=sdet::PMTConstants::eWaterCherenkovLarge)
end PMT iterator for read/write
utl::TraceD GetVEMChargeTrace(const sevt::Station &st) const
unsigned int GetCorrectedNanosecond() const
Get corrected trigger nanosecond.
sevt::StationGPSData & GetGPSData()
Get GPS data for the station.
double GetShapeParameter() const
Definition: PMTRecData.h:141
SizeType GetSize() const
Definition: Trace.h:156
#define WARNING(message)
Macro for logging warning messages.
Definition: ErrorLogger.h:163
void GetData(bool &b) const
Overloads of the GetData member template function.
Definition: Branch.cc:644
a second level trigger
Definition: XbT2.h:8
void SetCoreTime(const utl::TimeStamp &coreTime, const utl::TimeInterval &coreTimeErr)
void SetTotalCharge(const double totalCharge, const double chErr=0)
Definition: PMTRecData.h:203
bool operator()(const GeoSegment &i, const GeoSegment &j) const
std::vector< GeoSegment > FoundSegments(sevt::Station &st)
void ComputeShapeRiseFallPeak(sevt::PMTRecData &pmtRecData, const double binSize, const unsigned int startBin, const unsigned int startIntegration, const unsigned int endIntegration, const double traceIntegral) const
void SetSignalStartTime(const utl::TimeStamp time)
Start time of the signal.
bool operator()(const GeoSegment &i, const GeoSegment &j) const
double GetY(const CoordinateSystemPtr &coordinateSystem) const
Definition: BasicVector.h:209
constexpr double kSpeedOfLight
A TimeInterval is used to represent time elapsed between two events.
Definition: TimeInterval.h:43
utl::TimeStamp GetTime() const
Get time of the trigger.
ResultFlag
Flag returned by module methods to the RunController.
Definition: VModule.h:60
bool UpdateStationValues(sevt::Station &st, const int start, const int stop)
double GetFADCBinSize() const
Station Trigger Data description
SizeType GetStart() const
Get valid data start bin.
Definition: Trace.h:142
Vector object.
Definition: Vector.h:30
Detector description interface for SDetector-related data.
Definition: SDetector.h:42
void SetT50(const double t50)
Definition: PMTRecData.h:183
Report failure to RunController, causing RunController to terminate execution.
Definition: VModule.h:64
void SetCorePosition(const utl::Point &core)
unsigned int GetFADCTraceLength() const
CandidateStationIterator CandidateStationsEnd()
Definition: SEvent.h:74
double GetT50() const
Definition: PMTRecData.h:110
void SetT4Trigger(const int t4)
void SetRiseTime(const double riseTime, const double rms)
Definition: PMTRecData.h:172
const Station & GetStation(const int stationId) const
Get station by Station Id.
Definition: SDetector.cc:192
double GetPeakAmplitude() const
Peak Amplitude.
Definition: PMTRecData.h:140
#define ERROR(message)
Macro for logging error messages.
Definition: ErrorLogger.h:165
std::vector< GeoSegment > FoundBasicSegments(sevt::Station &st)
double GetVEMPeak() const
Definition: PMTRecData.h:119
bool HasSRecShower() const
bool HasSEvent() const
bool operator()(const GeoSegment &i, const GeoSegment &j) const
void SetSignalEndSlot(const unsigned int slot)
End time of the signal in time slots from beginning of trace.

, generated on Tue Sep 26 2023.