CDASToOfflineEventConverter.cc
Go to the documentation of this file.
1 
10 #include <io/CDASToOfflineEventConverter.h>
11 
12 #include <det/Detector.h>
13 #include <sdet/SDetector.h>
14 #include <sdet/Station.h>
15 #include <sdet/PMT.h>
16 #include <sdet/PMTConstants.h>
17 
18 #include <evt/Event.h>
19 #include <evt/ShowerRecData.h>
20 #include <evt/ShowerSRecData.h>
21 #include <evt/ShowerFRecData.h>
22 #include <evt/VGaisserHillasParameter.h>
23 #include <evt/GaisserHillas2Parameter.h>
24 
25 #include <sevt/EventTrigger.h>
26 #include <sevt/Header.h>
27 #include <sevt/SEvent.h>
28 #include <sevt/Station.h>
29 #include <sevt/StationCalibData.h>
30 #include <sevt/StationRecData.h>
31 #include <sevt/StationGPSData.h>
32 #include <sevt/StationTriggerData.h>
33 #include <sevt/PMT.h>
34 #include <sevt/PMTCalibData.h>
35 #include <sevt/PMTRecData.h>
36 #include <sevt/Meteo.h>
37 
38 #include <fwk/LocalCoordinateSystem.h>
39 #include <fwk/CoordinateSystemRegistry.h>
40 
41 #include <utl/Math.h>
42 #include <utl/MathConstants.h>
43 #include <utl/CoordinateSystemPtr.h>
44 #include <utl/Point.h>
45 #include <utl/AugerCoordinateSystem.h>
46 #include <utl/ErrorLogger.h>
47 #include <utl/TimeStamp.h>
48 #include <utl/UTCDateTime.h>
49 #include <utl/Trace.h>
50 #include <utl/TraceAlgorithm.h>
51 #include <utl/UTMPoint.h>
52 #include <utl/String.h>
53 #include <utl/Test.h>
54 #include <utl/Is.h>
55 
56 // CDAS Classes
57 #include <IoSdData.h>
58 #include <Ec.h>
59 #include <Es.h>
60 #include <Er.h>
61 #include <MdEvent.h>
62 
63 // Offline
64 #include <mdet/MDetector.h>
65 #include <mdet/Counter.h>
66 #include <mdet/Module.h>
67 #include <mdet/FrontEnd.h>
68 
69 #include <mevt/MEvent.h>
70 #include <mevt/Counter.h>
71 #include <mevt/Module.h>
72 #include <mevt/Channel.h>
73 
74 #include <rdet/RDetector.h>
75 #include <rdet/Station.h>
76 #include <rdet/Channel.h>
77 
78 #include <revt/REvent.h>
79 #include <revt/Station.h>
80 #include <revt/Channel.h>
81 #include <revt/Header.h>
82 #include <revt/StationTriggerData.h>
83 #include <revt/StationGPSData.h>
84 #include <revt/EventTrigger.h>
85 #include <revt/StationHeader.h>
86 #include <revt/StationConstants.h>
87 
88 #include <iostream>
89 #include <iomanip>
90 #include <string>
91 #include <vector>
92 
93 using namespace evt;
94 using namespace sevt;
95 using namespace fwk;
96 using namespace utl;
97 using namespace io;
98 using namespace std;
99 
100 
101 //#define DEBUGRAW(x) cout << x
102 #define DEBUGRAW(x)
103 //#define DEBUGEC(x) cout << x
104 #define DEBUGEC(x)
105 //#define DEBUGES(x) cout << x
106 #define DEBUGES(x)
107 //#define DEBUGER(x) cout << x
108 #define DEBUGER(x)
109 
110 
111 namespace io {
112 
113  template<typename T1, typename T2>
114  void
115  ConditionalCopy(const T1& src,
116  T2* const dst, const unsigned int dstSize,
117  const string& what)
118  {
119  static bool beenHere = false;
120  const unsigned int srcSize = src.size();
121  if (!beenHere && srcSize != dstSize) {
122  ostringstream warn;
123  warn << what << " size mismatch: source " << srcSize << ", "
124  "destination " << dstSize << '.';
125  WARNING(warn);
126  beenHere = true;
127  }
128  const unsigned int n = min(srcSize, dstSize);
129  unsigned int i;
130  for (i = 0; i < n; ++i)
131  dst[i] = src[i];
132  for (; i < dstSize; ++i)
133  dst[i] = 0;
134  }
135 
136 
137  bool
138  HasRDetectorConfig(const bool printMsg = false)
139  {
140  const auto& managerRRegister = det::Detector::GetInstance().GetRManagerRegister();
141 
142  // no RManager registered
143  if (managerRRegister.ManagersBegin() == managerRRegister.ManagersEnd()) {
144  if (printMsg)
145  INFO("No RDetector is configured. No read-in of RD data possible!");
146  return false;
147  }
148  return true;
149  }
150 
151 
152  bool
153  HasMDetectorConfig(const bool printMsg = false)
154  {
155  const auto& managerMRegister = det::Detector::GetInstance().GetMManagerRegister();
156 
157  // no MManager registered
158  if (managerMRegister.ManagersBegin() == managerMRegister.ManagersEnd()) {
159  if (printMsg)
160  INFO("No MDetector is configured. No read-in of UMD data possible!");
161  return false;
162  }
163  return true;
164  }
165 
166 }
167 
168 
169 namespace sdet {
170 
171  class Unlock {
172  public:
173  Unlock(const sdet::Station& station) : fStation(station) { }
174  void UpdateElectronics(const bool isUUB) const { fStation.UpdateElectronics(isUUB); }
175  void MakeScintillator() const { fStation.MakeScintillator(); }
176  void RemoveScintillator() const { fStation.RemoveScintillator(); }
177  void MakeSmallPMT() const { fStation.MakeSmallPMT(); }
178  void RemoveSmallPMT() const { fStation.RemoveSmallPMT(); }
179  private:
181  };
182 
183 }
184 
185 
186 namespace evt {
187 
189 
190  void
191  operator<<(Event& event, const IoSdEvent& rawEvent)
192  {
193  ConvertIoSdToEvent(event, rawEvent);
194  }
195 
196 
197  inline
198  bool
199  HasError(const IoSdStation& station)
200  {
201  return station.Error & 0xff;
202  }
203 
204 
205  static const std::set<int> gCycloneStations({600, 610, 620, 627, 630, 648});
206  static const std::set<int> gCycloneYears({2007, 2008, 2009});
207 
208 
209  void
210  ConvertIoSdToEvent(evt::Event& oEvent, const IoSdEvent& rEvent)
211  {
212  DEBUGRAW(" PullEventRaw - IoSdEvent " << endl);
213 
214  if (!oEvent.HasSEvent())
215  oEvent.MakeSEvent();
216 
217  auto& oSEvent = oEvent.GetSEvent();
218 
219  if (!oSEvent.HasTrigger())
220  oSEvent.MakeTrigger();
221 
222  oSEvent.SetNErrorZeroStations(rEvent.NumberOfErrorZeroStation);
223 
224  // sevt header
225  auto& osHeader = oSEvent.GetHeader();
226  osHeader.SetId(rEvent.Id);
227 
228  const auto& rTrigger = rEvent.Trigger;
229  const TimeStamp currentTime(rTrigger.Second, rTrigger.MicroSecond * 1000);
230  osHeader.SetTime(currentTime);
231 
232  // evt header
233  auto& oHeader = oEvent.GetHeader();
234  oHeader.SetTime(currentTime);
235 
236  {
237  ostringstream idos;
238  if (!oHeader.GetId().empty())
239  idos << oHeader.GetId() << "__";
240  idos << "sd_" << rEvent.Id;
241  const auto& id = idos.str();
242  oHeader.SetId(id);
243  INFO(id);
244  }
245 
246  // trigger
247  auto& oTrigger = oSEvent.GetTrigger();
248 
249  oTrigger.SetId(rTrigger.Id);
250  oTrigger.SetPreviousId(rTrigger.PreviousId);
251  oTrigger.SetTime(currentTime);
252  oTrigger.SetSender(rTrigger.Sender);
253  oTrigger.SetAlgorithm(rTrigger.Algo);
254  oTrigger.SetSDPAngle(rTrigger.SDPAngle);
255 
256  const auto& detector = det::Detector::GetInstance();
257  const auto& rDetector = detector.GetRDetector();
258 
259  /*
260  With the AugerPrime Upgrade, radio traces are part of the "normal" Sd data stream.
261  To save ordinary (Sd) people from configuring the RDetector every time radio data is present,
262  it is required that the RDetector is configured (in the first place) (therefore it is an intentional act)!
263  To ensure that the AugerPrime Radio Detector is configured an not AERA,
264  we require "AddStationListFromSManager" to be true. However in case of a simulated shower, this should not be done!
265  When using the Offline file format with a radio simulation the REvent was here initialized unintentionally.
266  */
267  const bool readInRdData =
268  HasRDetectorConfig() && rDetector.AddStationListFromSManager() && !oEvent.HasSimShower();
269 
270  if (readInRdData) {
271  if (!oEvent.HasREvent())
272  oEvent.MakeREvent();
273 
274  auto& rdEvent = oEvent.GetREvent();
275  auto& rdHeader = rdEvent.GetHeader();
276 
277  if (!rdEvent.HasTrigger())
278  rdEvent.MakeTrigger();
279  rdEvent.GetTrigger().SetSDTrigger(true); // always true for RD data
280 
281  // TH: for now: Radio Event ID and time is only set to SD values if there is not already an AERA event ID
282  if (!rdHeader.GetId()) {
283  rdHeader.SetId(rEvent.Id);
284  rdHeader.SetTime(currentTime);
285  }
286  }
287 
288  // meteo information from CDAS >= v5r0
289  if (!oSEvent.HasMeteo())
290  oSEvent.MakeMeteo();
291 
292  if (rEvent.MeteoFlag) {
293 
294  const auto& rMeteo = rEvent.meteo();
295 
296  auto& oMeteo = oSEvent.GetMeteo();
297  float pressures[kIoSd::N_WEATHER_STATIONS];
298  float dailyPressures[kIoSd::N_WEATHER_STATIONS];
299 
300  for (unsigned int k = 0; k < kIoSd::N_WEATHER_STATIONS; ++k) {
301  pressures[k] = rMeteo.Pressure[k]*hPa;
302  dailyPressures[k] = rMeteo.DayPressure[k]*hPa;
303  }
304 
305  oMeteo.SetPressures(pressures, kIoSd::N_WEATHER_STATIONS);
306  oMeteo.SetTemperatures(rMeteo.Temperature, kIoSd::N_WEATHER_STATIONS);
307  oMeteo.SetHumidities(rMeteo.Humidity, kIoSd::N_WEATHER_STATIONS);
308  oMeteo.SetDayPressures(dailyPressures, kIoSd::N_WEATHER_STATIONS);
309  oMeteo.SetDayTemperatures(rMeteo.DayTemperature, kIoSd::N_WEATHER_STATIONS);
310  oMeteo.SetDayHumidities(rMeteo.DayHumidity, kIoSd::N_WEATHER_STATIONS);
311 
312  }
313 
314  const auto& rStations = rEvent.Stations;
315 
316  set<int> zeroErrorStations;
317  for (const auto& s : rStations) {
318  // UUB sends bit 8 set when error = 0, use only lowest 8 bits:
319  if (!HasError(s))
320  zeroErrorStations.emplace(s.Id);
321  }
322 
323  const auto& sDetector = detector.GetSDetector();
324  set<int> missingDStations;
325 
326  set<int> copiedStations;
327  ostringstream discardedStations;
328  for (const auto& rStation : rStations) {
329 
330  const int id = rStation.Id;
331 
332  if (Is(id).In(copiedStations) ||
333  (Is(id).In(zeroErrorStations) && HasError(rStation))) {
334  // id already copied or this is not the zero-error station
335  discardedStations << ' ' << id << '(' << rStation.Error << ')';
336  continue;
337  }
338 
339  try {
340  sDetector.GetStation(id);
342  missingDStations.insert(id);
343  continue;
344  }
345  auto& dStation = sDetector.GetStation(id);
346 
347  copiedStations.emplace(id);
348 
349  /*
350  When a mismatch occurs between what hardware exists
351  in the SDetector Station and what is seen in CDAS station,
352  the SDetector Station is updated to reflect that which is
353  seen in the CDAS station. This must be done before the
354  SEvent Station is created as the SEvent Station constructor
355  creates hardware which just mirrors what exists in the
356  SDetector Station. Note that stations with a T3 error
357  status of eNoError (i.e. 0 (256) for UBs (UUBs)) have the
358  IsUUB member of the IoSdStation class correctly set, whereas
359  those with a T3 error status of eT3NotFound (i.e. 2) do not.
360  Thus, the hardware defined in the SDetector is only
361  overwritten if the IoSdStation T3 error is 0 or 256 (meaning
362  the station had a trigger and sent data to CDAS).
363  */
364  const bool isUUB = rStation.IsUUB;
365  const int hasSSD = const_cast<IoSdStation&>(rStation).HasSSD();
366  const bool noError = !HasError(rStation);
367 
368  if (noError) {
369 
370  if (dStation.IsUUB() != isUUB)
371  sdet::Unlock(dStation).UpdateElectronics(isUUB);
372 
373  /*
374  At present, EA UUB stations will return 0 for
375  HasSSD() whether they have an SSD or not since
376  HasSSD() just checks if one of large WCD PMT classes
377  is filled with SSD E-Kit information. As such,
378  we need to check both for a masked WCD PMT (used for SSD)
379  or a dedicated SSD PMT.
380 
381  When reading in WCD+SSD UB simulations, the CDASToOffline
382  converter will RemoveScintillator even if the SSD was
383  simulated as in the IoSdStation in CDAS, HasSSD() will
384  return false. It returns false because the TubeMask doesn't
385  reflect the SSD PPA setup (where one WCD PMT is not okay as
386  it is being used for the SSD PMT). Unless we want to
387  task one PMT as not okay in WCD+SSD UB simulations and
388  update the TubeMask in IoSdStation accordingly when
389  streaming the Offline event to a raw CDAS event, I don't
390  see a way the !oEvent.HasSimShower() check below. Once the
391  IoSdStation class in CDAS has another way of checking if an
392  SSD exists (other than the HasSSD() function, which also
393  returns 0 when UUB stations have an SSD), this can be
394  revisted.
395  */
396  if (hasSSD || isUUB) {
397  if (!dStation.HasScintillator())
398  sdet::Unlock(dStation).MakeScintillator();
399  } else if (dStation.HasScintillator() && !oEvent.HasSimShower())
400  sdet::Unlock(dStation).RemoveScintillator();
401 
402  // For now, a small PMT is only (and always) created if a station has a UUB
403  if (isUUB) {
404  if (!dStation.HasSmallPMT())
405  sdet::Unlock(dStation).MakeSmallPMT();
406  } else if (dStation.HasSmallPMT())
407  sdet::Unlock(dStation).RemoveSmallPMT();
408 
409  }
410 
411  if (!oSEvent.HasStation(id))
412  oSEvent.MakeStation(id);
413  auto& oStation = oSEvent.GetStation(id);
414  /*
415  - IsUUB flag is only available for cdas-version >= v5r6
416  - UFadc (get FADC traces for UUB stations) only available for cdas-version >= v5r8
417  - Calibration info (Base3, Offset3, Shape3 ...) available for cdas-version >= v5r9
418  - Latest updates were done in cdas release v6r0p1.
419  code for the upgrade will not compile for old cdas versions.
420  */
421 
422  // T2 Trigger
423  if (!oStation.HasTriggerData())
424  oStation.MakeTriggerData();
425 
426  auto& oStationTrigger = oStation.GetTriggerData();
427  oStationTrigger.SetErrorCode(rStation.Error);
428 
429  const auto& rStationTrigger = rStation.Trigger;
430  oStationTrigger.SetWindowMicroSecond(rStationTrigger.Window);
431  oStationTrigger.SetOffsetMicroSecond(rStationTrigger.Offset);
432  if (!isUUB)
433  oStationTrigger.SetPLDTrigger(rStationTrigger.Type);
434  else {
435  /* DV 2021-02-27: in cdas for UUB they do
436  IoSdT2Trigger.Type1 = pld & 0xff00ff;
437  IoSdT2Trigger.Type2 = (pld & 0xff00ff00) >> 8;
438  here we are trying to undo this so that the lower 16 bits are
439  the same as for UB */
440  const StationTriggerData::PLDType pld =
441  StationTriggerData::PLDType(rStationTrigger.Type1) |
442  (StationTriggerData::PLDType(rStationTrigger.Type2) << 8);
443  oStationTrigger.SetPLDTrigger(pld);
444  }
445 
446  // T2Life info
447  if (rStation.T2Life > -1 && rStation.T2Life120 > -1)
448  oStation.SetT2Life(bool(rStation.T2Life) + bool(rStation.T2Life120));
449  else
450  oStation.SetT2Life(2); // info not available, assume alive
451 
452  // Upgrade Trigger Parameter Information (UUB only)
453  /*if (isUUB) {
454  const IoUSdTrigParam* const rUTrigParam = rStation.UTrigParam;
455  if (rUTrigParam) {
456  // Placeholder
457  DEBUGRAW("IoUSdTrigParam exists");
458  }
459  }*/
460 
461  // GPS
462  const auto* const rGPS = rStation.Gps;
463 
464  if (rGPS) {
465  DEBUGRAW(" has-GPS " << flush);
466 
467  if (!oStation.HasGPSData())
468  oStation.MakeGPSData();
469 
470  auto& oGPS = oStation.GetGPSData();
471 
472  oGPS.SetSecond(rGPS->Second);
473  oGPS.SetTick(rGPS->Tick);
474  oGPS.SetCurrent100(rGPS->Current100);
475  oGPS.SetNext100(rGPS->Next100);
476  oGPS.SetCurrent40(rGPS->Current40);
477  oGPS.SetNext40(rGPS->Next40);
478  oGPS.SetPreviousST(rGPS->PreviousST);
479  oGPS.SetCurrentST(rGPS->CurrentST);
480  oGPS.SetNextST(rGPS->NextST);
481  oGPS.SetOffset(rGPS->Offset);
482  //oGPS.SetTickFall() is set below
483  }
484 
485  /*
486  Stations with Cyclone FE boards running Zbigniew Szadkowski's firmware:
487  In years {2007, 2008, 2009} the stations with IDs {600, 610, 620, 627, 630, 648}
488  were sending some telemetry data in the last 8 bins of the PMT traces. For
489  these we have to set the IsCyclone status so that the calibration can avoid it.
490  */
491  if (!isUUB &&
492  Is(id).In(gCycloneStations) &&
493  Is(UTCDateTime(currentTime).GetYear()).In(gCycloneYears))
494  oStation.SetIsCyclone();
495 
496  // Calibration
497  const auto* const rCalib = rStation.Calib;
498 
499  if (rCalib) {
500 
501  DEBUGRAW(" has-Calib ("
502  << "v" << rCalib->Version << ")"
503  << flush);
504 
505  if (!oStation.HasCalibData())
506  oStation.MakeCalibData();
507  auto& oStationCalib = oStation.GetCalibData();
508 
509  const auto& calibVersion = rCalib->Version;
510  oStationCalib.SetVersion(calibVersion);
511 
512  if (rGPS && calibVersion > 12)
513  oStation.GetGPSData().SetTickFall(rGPS->TickFall);
514  else
515  // this is just to get false from (Tick == TickFall)
516  oStation.GetGPSData().SetTickFall(rGPS->Tick ? 0 : 1);
517 
518  if (rGPS) {
519  ApplyTimeCorrection(oStation.GetGPSData());
520  //oStation.GetGPSData().SetCorrectedNanosecond(rGPS->NanoSecond);
521  }
522 
523  oStationCalib.SetStartSecond(rCalib->StartSecond);
524  oStationCalib.SetEndSecond(rCalib->EndSecond);
525  oStationCalib.SetNT1(rCalib->NbT1);
526  oStationCalib.SetNT2(rCalib->NbT2);
527  oStationCalib.SetNTot(rCalib->NbTOT);
528 
529  const unsigned int tubeMask = rCalib->TubeMask;
530  int nTubesOK = 0;
531 
532  for (auto& oPMT : oStation.PMTsRange(sdet::PMTConstants::eAnyType)) {
533 
534  /*
535  Comment on the loops over all PMTs and converting data from CDAS PMTs to Offline PMTs:
536 
537  CDAS iterates over PMTs with id = 0, 1, 2
538  Offline iterates over PMTs with id = 1, 2, 3
539  - In case of isUUB stations, 5 PMTs are created by the Offline station
540  i.e. eWaterCherenkovSmall (id = 4) and eScintillator (id = 5)
541  - In case of hasSSD stations (SSD connected to UB through kit box), 4 PMTs
542  are created (3 eWaterCherenkovLarge + eScintillator). The flag hasSSD returns
543  the id of the WCD PMT channel which is now used by the Scintillator PMT. Data
544  of this PMT is accessed in CDAS by hasSSD-1, therefore we need to explicitly
545  tell Offline which is the CDAS-PMT id that corresponds to eScintillator.
546 
547  The loop over PMTConstants::eAnyType with the logic below
548  should handle all these situations.
549  */
550 
551  int i = oPMT.GetId() - 1;
552  if (hasSSD) {
553  if (oPMT.GetType() == sdet::PMTConstants::eScintillator)
554  i = hasSSD - 1;
555  else if (i == hasSSD - 1)
556  continue;
557  }
558 
559  if (!oPMT.HasCalibData())
560  oPMT.MakeCalibData();
561 
562  auto& oPMTCalib = oPMT.GetCalibData();
563  // UUB information still missing in CDAS (v6r0)
564  if (tubeMask & (1u << i)) {
565  ++nTubesOK;
566  oPMTCalib.SetIsTubeOk(true);
567  oPMTCalib.SetIsLowGainOk(true);
568  }
569 
570  /*
571  For calibration version < 262, the UUB PMTs are all set as "not ok" in CDAS.
572  In order to use data from these PMTs, here we overwrite this flag. This implies
573  that for a calibration version < 262, there could be some UUB PMTs that are
574  disfunctional but have IsTubeOk set to true.
575  */
576  if (isUUB && calibVersion < 262) {
577  ++nTubesOK;
578  oPMTCalib.SetIsTubeOk(true);
579  oPMTCalib.SetIsLowGainOk(true);
580  ostringstream warn;
581  warn << "station " << oStation.GetId() << " has calibration version " << calibVersion << "; "
582  "PMT id " << oPMT.GetId() << " had flag IsTubeOK overwritten with \"true\"";
583  WARNING(warn);
584  }
585 
586  /*
587  22-06-2022: For calibration versions 262 to 268, the SSD PMTs are set as "not ok" in CDAS.
588  Here we also overwrite this flag for such PMTs so that we can analyse their data.
589  Again this implies that, for the mentioned calibration versions, there could be some SSD PMTs
590  that are disfunctional having their IsTubeOk as true.
591  */
592  if (isUUB &&
593  oPMT.GetType() == sdet::PMTConstants::eScintillator &&
594  262 <= calibVersion && calibVersion <= 268) {
595  ++nTubesOK;
596  oPMTCalib.SetIsTubeOk(true);
597  oPMTCalib.SetIsLowGainOk(true);
598  ostringstream warn;
599  warn << "station " << oStation.GetId() << " has calibration version " << calibVersion << "; "
600  "SSD PMT flag IsTubeOK was overwritten with \"true\"";
601  WARNING(warn);
602  } else if (isUUB && oPMT.GetType() == sdet::PMTConstants::eScintillator) {
603  ostringstream warn;
604  warn << "station " << oStation.GetId() << " has calibration version " << calibVersion << "; "
605  "if SSD PMT trace is absent, its IsTubeOK flag is possibly set to \"false\" by CDAS";
606  WARNING(warn);
607  }
608 
609  /*
610  2023-04-13: Here we assign nominal values for MIP Peak and charge.
611  Since there is no data member for the raw SSD calibration data
612  in IoSdCalib (see next comment too), we need to do it before the
613  next "continue" statement.
614  */
615  auto& dPmt = dStation.GetPMT(oPMT.GetId());
616  if (oPMT.GetType() == sdet::PMTConstants::eScintillator) {
617  oPMTCalib.SetGainRatio(dPmt.GetGainRatio(), 0);
618  oPMTCalib.SetOnlinePeak(dPmt.GetNominalVEMPeak());
619  oPMTCalib.SetOnlineCharge(dPmt.GetNominalVEMCharge());
620  }
621 
622  /*
623  January 17, 2020: arrays housing PMT-specific calibration information
624  in the IoSdCalib class are of length kIoSd::NPMT (which = 3). Data
625  members to house sPMT and SSD PMT related calibration data have
626  not yet been been implemented. Therefore, for now, we continue
627  after the data for the large WCD PMTs has been read in.
628  */
629  if (i >= int(kIoSd::NPMT))
630  continue;
631 
632  // PMT calibration
633  oPMTCalib.SetNumberTDA(rCalib->NbTDA[i]);
634  oPMTCalib.SetEvolution(rCalib->Evolution[i]);
635  oPMTCalib.SetRate(rCalib->Rate[i]);
636 
637  // The ordering of baseline data in the Base and SigmaBase
638  // arrays differs between UB and UUB.
639  if (isUUB) {
640  oPMTCalib.SetBaseline(rCalib->Base[2*i+1], rCalib->SigmaBase[i], sdet::PMTConstants::eHighGain);
641  oPMTCalib.SetBaseline(rCalib->Base[2*i], rCalib->SigmaBase[2*i], sdet::PMTConstants::eLowGain);
642  } else {
643  oPMTCalib.SetBaseline(rCalib->Base[i], rCalib->SigmaBase[i], sdet::PMTConstants::eHighGain);
644  oPMTCalib.SetBaseline(rCalib->Base[i+3], rCalib->SigmaBase[i+3], sdet::PMTConstants::eLowGain);
645  }
646 
647  /*
648  For the early calibration versions of UUB, the online gain ratio, VEM peak
649  and charge may be zero or hold some meaningless value. When this happens,
650  we override these values with their nominal ones to avoid crashes.
651  */
652  if (rCalib->DA[i] > 0)
653  oPMTCalib.SetGainRatio(rCalib->DA[i], rCalib->SigmaDA[i]);
654  else
655  oPMTCalib.SetGainRatio(dPmt.GetGainRatio(), 0);
656  oPMTCalib.SetOnlinePeak(
657  (rCalib->VemPeak[i] > 0) ? rCalib->VemPeak[i] : dPmt.GetNominalVEMPeak()
658  );
659  oPMTCalib.SetOnlineCharge(
660  (rCalib->VemCharge[i] > 0) ? rCalib->VemCharge[i] : dPmt.GetNominalVEMCharge()
661  );
662 
663  /*
664  For PPA stations, the SSD PMT has its IsTubeOK flag always set to false.
665  To analyse data from these stations, we override this flag to true.
666  This implies the possibility that a dysfunctional PPA SSD PMT end up with a true
667  flag for IsTubeOK.
668  Their online values for MIP peak and charge coming from CDAS are meaninless,
669  therefore we set them to nominal values
670  */
671  if (!isUUB && oPMT.GetType() == sdet::PMTConstants::eScintillator) {
672  oPMTCalib.SetIsTubeOk(true);
673  oPMTCalib.SetIsLowGainOk(true);
674  oPMTCalib.SetOnlinePeak(dPmt.GetNominalVEMPeak());
675  oPMTCalib.SetOnlineCharge(dPmt.GetNominalVEMCharge());
676 
677  ostringstream warn;
678  warn << "PPA station " << oStation.GetId() << " had its SSD PMT "
679  "flag IsTubeOK overridden with \"true\" and its online MIP peak and charge "
680  "set to nominal values " << oPMTCalib.GetOnlinePeak() << " adc and "
681  << oPMTCalib.GetOnlineCharge() << " adct, respectively";
682  WARNING(warn);
683  }
684 
685  // remove zeroing when IoSdCalib empty ctor is fixed in CDAS
686  // as of CDAS v3r4 this has not been fixed, yet, if ever...
687  if (calibVersion > 12) {
688  oPMTCalib.SetHighGainDelay(rCalib->DADt[i], rCalib->SigmaDADt[i]);
689  oPMTCalib.SetHighGainDelayChi2(rCalib->DAChi2[i]);
690  } else {
691  oPMTCalib.SetHighGainDelay(0, 0);
692  oPMTCalib.SetHighGainDelayChi2(0);
693  }
694 
695  } // i loop PMTs
696  oStationCalib.SetNTubesOk(nTubesOK);
697  } // if station has calib
698 
699  // PMT quality
700  const IoSdPMQuality* const rPMQuality = rStation.pmquality();
701  if (rPMQuality) {
702  const auto& version = rPMQuality->Version;
703  const auto& tube = rPMQuality->TubeMask;
704  const auto& anode = rPMQuality->AnodeMask;
705  const auto& raining = rPMQuality->RainingMask;
706 
707  for (auto& oPMT : oStation.PMTsRange(sdet::PMTConstants::eAnyType)) {
708  int i = oPMT.GetId() - 1;
709  if (hasSSD) {
710  if (oPMT.GetType() == sdet::PMTConstants::eScintillator)
711  i = hasSSD - 1;
712  else if (i == hasSSD - 1)
713  continue;
714  }
715  if (!oPMT.HasQuality())
716  oPMT.MakeQuality();
717  auto& oPMTQuality = oPMT.GetQuality();
718  oPMTQuality.SetVersion(version);
719  const auto pmtMask = 1 << i;
720  oPMTQuality.SetIsTubeOk(tube & pmtMask);
721  oPMTQuality.SetHasAnode(anode & pmtMask);
722  oPMTQuality.SetIsRaining(~raining & pmtMask);
723  }
724  }
725 
726  // Muon histograms
727  const IoSdHisto* const rHisto = rStation.Histo;
728 
729  if (rHisto) {
730 
731  DEBUGRAW(" has-Histo " << flush);
732 
733  if (!oStation.HasCalibData())
734  oStation.MakeCalibData();
735 
736  auto& oStationCalib = oStation.GetCalibData();
737 
738  const int calibVersion = oStationCalib.GetVersion();
739  if (calibVersion > 8) {
740 
741  vector<int> mch(rHisto->Charge[3], rHisto->Charge[3] + 600);
742  oStationCalib.SetMuonChargeHisto(mch, rHisto->Offset[9]);
743 
744  // NB_HISTO_CALIB comes from IoSdData.h
745  // this has gone into corresponding PMTCalibData
746  /*vector<int> offset(rHisto->Offset, rHisto->Offset + kIoSd::NB_HISTO_CALIB);
747  oStationCalib.SetOffsetHisto(offset);*/
748 
749  for (auto& oPMT : oStation.PMTsRange(sdet::PMTConstants::eAnyType)) {
750 
751  int i = oPMT.GetId() - 1;
752  if (hasSSD) {
753  if (oPMT.GetType() == sdet::PMTConstants::eScintillator)
754  i = hasSSD - 1;
755  else if (i == hasSSD - 1)
756  continue;
757  }
758 
759  if (!oPMT.HasCalibData())
760  oPMT.MakeCalibData();
761  auto& oPMTCalib = oPMT.GetCalibData();
762 
763  if (oPMT.GetType() == sdet::PMTConstants::eWaterCherenkovSmall)
764  continue; // skip small pmt until update in CDAS
765 
766  if (isUUB) {
767  if (oPMT.GetType() == sdet::PMTConstants::eWaterCherenkovLarge) {
768  const vector<int> base(rHisto->Base[i], rHisto->Base[i] + 20);
769  oPMTCalib.SetMuonBaseHisto(base, rHisto->Offset[i]);
770 
771  const vector<int> shape(rHisto->UShape[i], rHisto->UShape[i] + 70);
772  oPMTCalib.SetMuonShapeHisto(shape);
773 
774  const vector<int> peak(rHisto->Peak[i], rHisto->Peak[i] + 150);
775  oPMTCalib.SetMuonPeakHisto(peak, rHisto->Offset[i+3]);
776 
777  const vector<int> charge(rHisto->Charge[i], rHisto->Charge[i] + 600);
778  oPMTCalib.SetMuonChargeHisto(charge, rHisto->Offset[i+6]);
779 
780  // different treatment for ssd pmt in CDAS
781  } else if (oPMT.GetType() == sdet::PMTConstants::eScintillator) {
782  const vector<int> base(rHisto->Base3, rHisto->Base3 + 20);
783  oPMTCalib.SetMuonBaseHisto(base, rHisto->Offset3[0]);
784 
785  const vector<int> shape(rHisto->UShape[3], rHisto->UShape[3] + 70);
786  oPMTCalib.SetMuonShapeHisto(shape);
787 
788  const vector<int> peak(rHisto->Peak3, rHisto->Peak3 + 150);
789  oPMTCalib.SetMuonPeakHisto(peak, rHisto->Offset3[1]);
790 
791  const vector<int> charge(rHisto->Charge[3], rHisto->Charge[3] + 600);
792  oPMTCalib.SetMuonChargeHisto(charge, rHisto->Offset3[2]);
793  }
794  } else {
795  const vector<int> base(rHisto->Base[i], rHisto->Base[i] + 20);
796  oPMTCalib.SetMuonBaseHisto(base, rHisto->Offset[i]);
797 
798  const unsigned int shapeN = (calibVersion == 13) ? 19 : 20;
799  const vector<int> shape(rHisto->Shape[i], rHisto->Shape[i] + shapeN);
800  oPMTCalib.SetMuonShapeHisto(shape);
801 
802  const vector<int> peak(rHisto->Peak[i], rHisto->Peak[i] + 150);
803  oPMTCalib.SetMuonPeakHisto(peak, rHisto->Offset[i+3]);
804 
805  const vector<int> charge(rHisto->Charge[i], rHisto->Charge[i] + 600);
806  oPMTCalib.SetMuonChargeHisto(charge, rHisto->Offset[i+6]);
807  }
808  }
809  }
810  }
811 
812  // FADC traces
813  if (!isUUB) {
814  const IoSdFadc* const rFADC = rStation.Fadc;
815 
816  if (rFADC) {
817 
818  DEBUGRAW(" has-FADC " << flush);
819 
820  for (auto& oPMT : oStation.PMTsRange(sdet::PMTConstants::eAnyType)) {
821  // PMTs always exist (otherwise something is seriously wrong)
822  int i = oPMT.GetId() - 1;
823  if (hasSSD) {
824  if (oPMT.GetType() == sdet::PMTConstants::eScintillator)
825  i = hasSSD - 1;
826  else if (i == hasSSD - 1)
827  continue;
828  }
829  const auto& trace = rFADC->Trace[i];
830  // FADC traces
831  if (!oPMT.HasFADCTrace()) {
832  oPMT.MakeFADCTrace();
833  oPMT.GetFADCTrace(sdet::PMTConstants::eHighGain).Adopt(trace[IoSdEvent::eHigh], kIoSd::MAXSAMPLE);
834  oPMT.GetFADCTrace(sdet::PMTConstants::eLowGain).Adopt(trace[IoSdEvent::eLow], kIoSd::MAXSAMPLE);
835  }
836  }
837  DEBUGRAW(endl);
838 
839  }
840  } else {
841  // different method to get FADC traces for the UUB
842  if (rStation.UFadc) {
843  const int nGain = 2;
844  const int nSample = rStation.UFadc->NSample;
845  DEBUGRAW(" upgraded station has-FADC " << flush);
846  for (auto& oPMT : oStation.PMTsRange(sdet::PMTConstants::eAnyType)) {
847  int i = oPMT.GetId() - 1;
848  if (!oPMT.HasFADCTrace())
849  oPMT.MakeFADCTrace();
850  for (int j = 0; j < nGain; ++j) {
851  unsigned short trace[nSample];
852  for (int k = 0; k < nSample; ++k) {
853  trace[k] = rStation.UFadc->GetValue(i, j, k);
854  }
855  oPMT.GetFADCTrace(
857  ).Adopt(trace, nSample);
858  }
859  }
860  /*
861  * For now revt::Station and rdet::Station are only and always created if
862  * a station has a valid radio trace.
863  * To check the existence of the radio traces in UUB stations
864  * the lenght of the buffer memory of all the FADC is used.
865  * If the CDAS developsers will introduce a new specific function for this
866  * the following line has to be changed accordingly
867  */
868  if (readInRdData && rStation.UFadc->Traces.size() > 20480) {
869 
870  // data parity check
871  const int nSample = rStation.UFadc->NSample;
872  unsigned int totalParity = 0;
873  for (int i = 0; i < nSample; ++i) {
874  totalParity += rStation.UFadc->GetValueParity(5, 0, i);
875  totalParity += rStation.UFadc->GetValueParity(5, 1, i);
876  }
877  const bool parityOkay = (totalParity == 4096);
878 
879  auto& rdEvent = oEvent.GetREvent();
880 
881  // Id of Rd station
882  const unsigned int rdId = rDetector.GetRdSdStationIdLink() + id;
883 
884  // make revt::Station
885  if (!rdEvent.HasStation(rdId))
886  rdEvent.MakeStation(rdId);
887 
888  auto& rdStation = rdEvent.GetStation(rdId);
889  if (!rdStation.HasTriggerData())
890  rdStation.MakeTriggerData();
891 
892  if (!rdStation.HasGPSData())
893  rdStation.MakeGPSData();
894 
895  // start-time is set at the beginning of the SD trace
896  auto& gps = rdStation.GetGPSData();
897  gps.SetSecond(rGPS->Second);
898  gps.SetCorrectedNanosecond(oStation.GetGPSData().GetCorrectedNanosecond());
899 
900  const utl::TimeStamp ts(gps.GetSecond(), gps.GetCorrectedNanosecond());
901 
902  const double fadcBinSize = dStation.GetFADCBinSize();
903 
904  const auto& rdetStation = rDetector.GetStation(rdStation);
905 
906  /*
907  - GetRdValue/GetValueParity only available for cdas-version >= v6r2p1.
908  - code for the Rd upgrade will not compile for older cdas versions.
909  - Rd iterates over Channel with id = 0, 1. Ch0 EW-aligned antenna, Ch1 NS-aligned antenna.
910  */
911  for (int chId = 0; chId < rdetStation.GetNChannels(); ++chId) {
912  auto& chan = rdStation.GetChannel(chId);
913  chan.SetActive();
914  auto& trace = chan.GetChannelADCTimeSeries();
915 
916  const auto& rdetChannel = rdetStation.GetChannel(chId);
917  const double samplingfreq = rdetChannel.GetSamplingFrequency();
918  trace.SetBinning(1 / samplingfreq);
919 
920  unsigned int parityChannel = 0;
921  for (int i = 0; i < nSample; ++i) {
922  const double val = rStation.UFadc->GetValueRd(5, chId, i);
923  trace.PushBack(val);
924  parityChannel += rStation.UFadc->GetValueParity(5, chId, i);
925  }
926  chan.SetParity(parityChannel);
927  }
928  const TimeStamp traceTime = ts - TimeInterval(nSample * fadcBinSize);
929  rdStation.SetRawTraceStartTime(traceTime);
930 
931  if (!parityOkay) {
932  rdStation.SetExcludedReason(revt::eParityError);
933  ostringstream err;
934  err << "Wrong parity count for traces of RD station " << rdId
935  << ". Excluded it from reconstruction.";
936  ERROR(err);
937  }
938  }
939  DEBUGRAW(endl);
940  }
941  }
942  }
943 
944  {
945  const auto dis = discardedStations.str();
946  if (!dis.empty()) {
947  discardedStations.str("");
948  discardedStations << "Discarded duplicated stations:" << dis;
949  INFO(discardedStations);
950  }
951  }
952 
953  if (!missingDStations.empty()) {
954  ostringstream warn;
955  warn << "Station" << String::Plural(missingDStations) << ' '
956  << String::OfSortedIds(missingDStations)
957  << " missing from the SD detector description, not including.";
958  WARNING(warn);
959  }
960 
961  oTrigger.SetNStations(copiedStations.size());
962 
963  DEBUGRAW(" PullEventRaw - IoSdEvent (END) " << endl);
964  }
965 
966 
967  // Push an evt::Event to CDAS IoSdEvent
968  void
969  operator>>(const Event& theEvent, IoSdEvent& rawSEvent)
970  {
971  ConvertEventToIoSd(theEvent, rawSEvent);
972  }
973 
974 
975  void
976  ConvertEventToIoSd(const evt::Event& theEvent, IoSdEvent& rawSEvent)
977  {
978  DEBUGRAW(" PushEventRaw - IoSdEvent " << endl);
979 
980  if (!theEvent.HasSEvent()) {
981  ERROR("Non-existent evt::SEvent class object.");
982  return;
983  }
984 
985  const SEvent& sEvent = theEvent.GetSEvent();
986 
987  if (!sEvent.HasTrigger()) {
988  ERROR("Non-existent central trigger in event.");
989  return;
990  }
991 
992  rawSEvent.NumberOfErrorZeroStation = sEvent.GetNErrorZeroStations();
993 
994  const sevt::Header& header = sEvent.GetHeader();
995  rawSEvent.Id = header.GetId();
996 
997  const sevt::EventTrigger& trigger = sEvent.GetTrigger();
998  IoSdT3Trigger& reTrigger = rawSEvent.Trigger;
999 
1000  reTrigger.Id = trigger.GetId();
1001  reTrigger.PreviousId = trigger.GetPreviousId();
1002  reTrigger.Second = trigger.GetTime().GetGPSSecond();
1003  reTrigger.MicroSecond = trigger.GetTime().GetGPSNanoSecond() / 1000;
1004  reTrigger.Sender = trigger.GetSender();
1005  reTrigger.Algo = trigger.GetAlgorithm();
1006  reTrigger.SDPAngle = trigger.GetSDPAngle();
1007  reTrigger.NumberOfStation = trigger.GetNStations();
1008 
1009  // Loop over the triggered stations in the event
1010 
1011  const ReferenceEllipsoid& e = ReferenceEllipsoid::GetWGS84();
1012 
1013  const sdet::SDetector& theSDetector = det::Detector::GetInstance().GetSDetector();
1014 
1015  const SEvent::ConstStationIterator stationsEnd = sEvent.StationsEnd();
1016  for (SEvent::ConstStationIterator csIt = sEvent.StationsBegin();
1017  csIt != stationsEnd; ++csIt) {
1018 
1019  const int sdId = csIt->GetId();
1020  const bool isUUB = csIt->IsUUB();
1021 
1022  IoSdStation rawStation;
1023  rawStation.Id = sdId;
1024  rawStation.IsUUB = isUUB;
1025 
1026  try {
1027 
1028  rawStation.Name = theSDetector.GetStation(csIt->GetId()).GetName();
1029  const UTMPoint pos =
1030  UTMPoint(theSDetector.GetStation(csIt->GetId()).GetPosition(), e);
1031 
1032  boost::tie(rawStation.Northing, rawStation.Easting, rawStation.Altitude) =
1033  pos.GetCoordinates3();
1034 
1035  } catch (NonExistentComponentException&) {
1036 
1037  // TODO: where should we take this info from?
1038 
1039  DEBUGRAW(" raw-station: " << setw(4) << rawStation.Id
1040  << " is not available in Offline. ... " << endl);
1041 
1042  //continue;
1043 
1044  rawStation.Name = "unkown by Offline";
1045  rawStation.Northing = 0;
1046  rawStation.Easting = 0;
1047  rawStation.Altitude = 0;
1048 
1049  }
1050 
1051  DEBUGRAW(" raw-station: " << setw(4) << rawStation.Id
1052  << " " << setw (20) << left << rawStation.Name);
1053 
1054  if (csIt->HasTriggerData()) {
1055 
1056  DEBUGRAW(" has-trig-data " << flush);
1057 
1058  const StationTriggerData& localTrigger = csIt->GetTriggerData();
1059 
1060  IoSdT2Trigger& rTrigger = rawStation.Trigger;
1061 
1062  rTrigger.Type = localTrigger.GetPLDTrigger();
1063  rTrigger.Offset = localTrigger.GetOffsetMicroSecond();
1064  rTrigger.Window = localTrigger.GetWindowMicroSecond();
1065  rTrigger.Name = localTrigger.GetAlgorithmName();
1066  rawStation.Error = localTrigger.GetErrorCode();
1067 
1068  DEBUGRAW(" Ecode " << rawStation.Error << flush);
1069 
1070  if (localTrigger.GetErrorCode() == 0) {
1071 
1072  IoSdFadc* const rfadc = rawStation.Fadc = new IoSdFadc;
1073 
1074  rfadc->NSample = theSDetector.GetStation(csIt->GetId()).GetFADCTraceLength();
1075 
1076  for (unsigned int i = 0; i < 3; ++i) {
1077 
1078  const PMT& pmt = csIt->GetPMT(i+1);
1079 
1080  if (pmt.HasFADCTrace()) {
1081 
1082  {
1083  Short_t* const rTraceHigh = rfadc->Trace[i][IoSdEvent::eHigh];
1084  const TraceI& traceHigh = pmt.GetFADCTrace(sdet::PMTConstants::eHighGain);
1085  const TraceI::ConstIterator traceHighEnd = traceHigh.End();
1086  unsigned int j = 0;
1087  for (TraceI::ConstIterator hIt = traceHigh.Begin();
1088  hIt != traceHighEnd && j < kIoSd::MAXSAMPLE; ++hIt, ++j)
1089  rTraceHigh[j] = Short_t(*hIt);
1090  }
1091  {
1092  Short_t* const rTraceLow = rfadc->Trace[i][IoSdEvent::eLow];
1093  const TraceI& traceLow = pmt.GetFADCTrace(sdet::PMTConstants::eLowGain);
1094  const TraceI::ConstIterator traceLowEnd = traceLow.End();
1095  unsigned int j = 0;
1096  for (TraceI::ConstIterator lIt = traceLow.Begin();
1097  lIt != traceLowEnd && j < kIoSd::MAXSAMPLE; ++lIt, ++j)
1098  rTraceLow[j] = Short_t(*lIt);
1099  }
1100 
1101  } // has FADC trace
1102 
1103  } // loop 3 PMTs
1104 
1105  } // if Error code == 0
1106 
1107  if (csIt->HasGPSData()) {
1108 
1109  DEBUGRAW(" has-gps-data " << flush);
1110 
1111  IoSdGps* const rgps = rawStation.Gps = new IoSdGps;
1112 
1113  const StationGPSData& gps = csIt->GetGPSData();
1114 
1115  rgps->Second = gps.GetSecond();
1116  rgps->Tick = gps.GetTick();
1117  rgps->Offset = gps.GetOffset();
1118  rgps->Current100 = gps.GetCurrent100();
1119  rgps->Next100 = gps.GetNext100();
1120  rgps->Current40 = gps.GetCurrent40();
1121  rgps->Next40 = gps.GetNext40();
1122  rgps->PreviousST = gps.GetPreviousST();
1123  rgps->CurrentST = gps.GetCurrentST();
1124  rgps->NextST = gps.GetNextST();
1125  rgps->NanoSecond = gps.GetCorrectedNanosecond();
1126  // let us assume the TickFall is correct inside offline
1127  rgps->TickFall = gps.GetTickFall();
1128 
1129  }
1130 
1131  if (csIt->HasCalibData()) {
1132 
1133  DEBUGRAW(" has-cal-data " << flush);
1134 
1135  // Station calibration data
1136 
1137  IoSdCalib* const rcalib = rawStation.Calib = new IoSdCalib;
1138 
1139  const StationCalibData& calib = csIt->GetCalibData();
1140 
1141  rcalib->Version = calib.GetVersion();
1142  rcalib->StartSecond = calib.GetStartSecond();
1143  rcalib->EndSecond = calib.GetEndSecond();
1144  rcalib->NbT1 = calib.GetNT1();
1145  rcalib->NbT2 = calib.GetNT2();
1146  rcalib->NbTOT = calib.GetNTot();
1147  rcalib->TubeMask = 0;
1148 
1149  for (unsigned int i = 0; i < kIoSd::NPMT; ++i) {
1150 
1151  // PMTs always exist (otherwise something is seriously wrong)
1152  const PMT& pmt = csIt->GetPMT(i+1);
1153 
1154  if (pmt.HasCalibData()) {
1155 
1156  const auto& pmtCalib = pmt.GetCalibData();
1157 
1158  if (pmtCalib.IsTubeOk())
1159  rcalib->TubeMask |= (1U << i);
1160 
1161  rcalib->NbTDA[i] = UShort_t(pmtCalib.GetNumberTDA());
1162  rcalib->Evolution[i] = pmtCalib.GetEvolution();
1163  rcalib->Rate[i] = pmtCalib.GetRate();
1164  rcalib->VemCharge[i] = pmtCalib.GetOnlineCharge();
1165  rcalib->VemPeak[i] = pmtCalib.GetOnlinePeak();
1166  rcalib->Base[i] = pmtCalib.GetBaseline();
1167  rcalib->Base[i+3] = pmtCalib.GetBaseline(sdet::PMTConstants::eLowGain);
1168  rcalib->SigmaBase[i] = pmtCalib.GetBaselineRMS();
1169  rcalib->SigmaBase[i+3] = pmtCalib.GetBaselineRMS(sdet::PMTConstants::eLowGain);
1170  rcalib->DA[i] = pmtCalib.GetGainRatio();
1171  rcalib->SigmaDA[i] = pmtCalib.GetGainRatioRMS();
1172 
1173  if (calib.GetVersion() > 12) {
1174  rcalib->DADt[i] = pmtCalib.GetHighGainDelay();
1175  rcalib->SigmaDADt[i] = pmtCalib.GetHighGainDelayRMS();
1176  rcalib->DAChi2[i] = pmtCalib.GetHighGainDelayChi2();
1177  } else {
1178  // this is for the broken IoSd ctor
1179  rcalib->DADt[i] = 0;
1180  rcalib->SigmaDADt[i] = 0;
1181  rcalib->DAChi2[i] = 0;
1182  }
1183 
1184  // non-persitent data member
1185  rcalib->TubeOk[i] = bool(rawStation.calib()->TubeMask & (1U << i));
1186 
1187  }
1188 
1189  }
1190 
1191  // non-persitent data member
1192  rcalib->NTubesOk = rcalib->TubeOk[0] + rcalib->TubeOk[1] + rcalib->TubeOk[2];
1193 
1194  // Muon histograms
1195 
1196  if (calib.GetVersion() > 8) {
1197 
1198  IoSdHisto* const rhisto = rawStation.Histo = new IoSdHisto;
1199 
1200  const vector<int>& mch = calib.GetMuonChargeHisto();
1201  ConditionalCopy(mch, rhisto->Charge[3], 600,
1202  "Muon charge (sum)");
1203  rhisto->Offset[9] = calib.GetMuonChargeHistoOffset();
1204 
1205  // this is set from PMTCalibData now
1206  /*const vector<int>& offset = calib.GetOffsetHisto();
1207  ConditionalCopy(offset, rhisto->Offset, kIoSd::NB_HISTO_CALIB,
1208  "Offset histogram");*/
1209 
1210  for (unsigned int i = 0; i < kIoSd::NPMT; ++i) {
1211 
1212  const PMT& pmt = csIt->GetPMT(i+1);
1213 
1214  if (pmt.HasCalibData()) {
1215 
1216  const PMTCalibData& pmtCalib = pmt.GetCalibData();
1217 
1218  const vector<int>& base = pmtCalib.GetMuonBaseHisto();
1219  ConditionalCopy(base, rhisto->Base[i], 20, "Muon base histogram");
1220  rhisto->Offset[i] = pmtCalib.GetMuonBaseHistoOffset();
1221 
1222  const vector<int>& shape = pmtCalib.GetMuonShapeHisto();
1223  ConditionalCopy(shape, rhisto->Shape[i], kIoSd::SINGLE_MUON_SIZE, "Muon shape histogram");
1224 
1225  const vector<int>& peak = pmtCalib.GetMuonPeakHisto();
1226  ConditionalCopy(peak, rhisto->Peak[i], 150, "Muon peak histogram");
1227  rhisto->Offset[i+3] = pmtCalib.GetMuonPeakHistoOffset();
1228 
1229  const vector<int>& mch = pmtCalib.GetMuonChargeHisto();
1230  ConditionalCopy(mch, rhisto->Charge[i], 600, "Muon charge histogram");
1231  rhisto->Offset[i+6] = pmtCalib.GetMuonChargeHistoOffset();
1232 
1233  }
1234 
1235  }
1236 
1237  if (isUUB) {
1238 
1239  const PMT& pmt = csIt->GetScintillatorPMT();
1240 
1241  if (pmt.HasCalibData()) {
1242 
1243  const PMTCalibData& pmtCalib = pmt.GetCalibData();
1244 
1245  const vector<int>& base = pmtCalib.GetMuonBaseHisto();
1246  ConditionalCopy(base, rhisto->Base3, 20, "Muon base histogram");
1247  rhisto->Offset3[0] = pmtCalib.GetMuonBaseHistoOffset();
1248 
1249  const vector<int>& shape = pmtCalib.GetMuonShapeHisto();
1250  ConditionalCopy(shape, rhisto->UShape[3], 70, "Muon shape histogram");
1251 
1252  const vector<int>& peak = pmtCalib.GetMuonPeakHisto();
1253  ConditionalCopy(peak, rhisto->Peak3, 150, "Muon peak histogram");
1254  rhisto->Offset3[1] = pmtCalib.GetMuonPeakHistoOffset();
1255 
1256  const vector<int>& mch = pmtCalib.GetMuonChargeHisto();
1257  ConditionalCopy(mch, rhisto->Charge[3], 600, "Muon charge histogram");
1258  rhisto->Offset3[2] = pmtCalib.GetMuonChargeHistoOffset();
1259 
1260  }
1261  }
1262 
1263  } // if version
1264 
1265  } // if has calib
1266 
1267  rawSEvent.Stations.push_back(rawStation);
1268 
1269  } // if has trigger data
1270 
1271  DEBUGRAW(endl);
1272 
1273  } // end station loop
1274 
1275  DEBUGRAW(" PushEventRaw - IoSdEvent (DONE)" << endl);
1276  }
1277 
1278 
1280 
1281  void
1282  operator>>(const Event& event, TEcEvent& ec)
1283  {
1284  DEBUGEC(" PushEventEc - TEcEvent" << endl);
1285 
1286  // first do the IoSd part
1287  event >> (IoSdEvent&)ec;
1288  ConvertEventToEc(event, ec);
1289  }
1290 
1291 
1292  void
1293  ConvertEventToEc(const evt::Event& theEvent, TEcEvent& theEc)
1294  {
1295  if (!theEvent.HasSEvent()) {
1296  ERROR ("Non-existent evt::SEvent class object.");
1297  return;
1298  }
1299 
1300  const SEvent& theSEvent = theEvent.GetSEvent();
1301 
1302  // set reference point: PampaAmarilla
1303  // all CDAS coordinates are relative to it
1304  CoordinateSystemPtr pampaCS = CoordinateSystemRegistry::Get("PampaAmarilla");
1305 
1306  const ReferenceEllipsoid& wgs84 = ReferenceEllipsoid::Get(ReferenceEllipsoid::eWGS84);
1307 
1308  const Point refPoint(0,0,0, pampaCS);
1309  const UTMPoint refPointUTM(refPoint, wgs84);
1310  const CoordinateSystemPtr refCS = LocalCoordinateSystem::Create(refPoint);
1311  theEc.fRefNorthing = refPointUTM.GetNorthing();
1312  theEc.fRefEasting = refPointUTM.GetEasting();
1313 
1314  DEBUGEC(" Reference Point: northing " << theEc.fRefNorthing
1315  << " easting " << theEc.fRefEasting << endl);
1316 
1317  // do the stations loop
1318  const SEvent::ConstStationIterator stationsEnd = theSEvent.StationsEnd();
1319  for (SEvent::ConstStationIterator csIt = theSEvent.StationsBegin();
1320  csIt != stationsEnd; ++csIt) {
1321 
1322  const unsigned int stationID = csIt->GetId();
1323 
1324  const sdet::Station& dStation =
1325  det::Detector::GetInstance().GetSDetector().GetStation(stationID);
1326 
1327  DEBUGEC(" cal-station: " << setw(4) << stationID);
1328 
1329  vector<IoSdStation>& rStations = theEc.Stations;
1330  // find the the raw station event from IoSdData
1331  vector<IoSdStation>::const_iterator iRawStation = rStations.begin();
1332  for ( ; iRawStation != rStations.end(); ++iRawStation)
1333  if (iRawStation->Id == stationID)
1334  break;
1335 
1336  if (iRawStation == rStations.end()) {
1337  ostringstream err;
1338  err << "Raw station " << stationID << " not found in raw event!"
1339  " DPA->CDAS conversion not possible!";
1340  ERROR(err);
1341  return; // -> TODO exception? Howto handle?
1342  }
1343 
1344  if (!csIt->HasCalibData() || !csIt->HasRecData()) {
1345 
1346  // also push silent/bad stations!
1347  // iRawStation.Error != 0 (not-calibrated)
1348  if (!iRawStation->Error) {
1349  ostringstream warn;
1350  warn << "Raw station " << stationID << " has error-code "
1351  << iRawStation->Error << " but is not calibrated!"
1352  " (HasCalibData: " << csIt->HasCalibData() << ")"
1353  " (HasRecData: " << csIt->HasRecData() << ')'
1354  << endl;
1355  WARNING (warn);
1356  }
1357  theEc.fCalibStations.push_back(*iRawStation);
1358 
1359  DEBUGEC("NO-cal-data. SKIP" << endl);
1360 
1361  continue;
1362  }
1363 
1364  // the DPA cal and rec station
1365  const auto& stationCalib = csIt->GetCalibData();
1366  const auto& stationRec = csIt->GetRecData();
1367 
1368  // create the cdas calibrated station
1369  TCalibStation cdasCal(*iRawStation);
1370 
1371  DEBUGEC("pos: north " << cdasCal.Northing/m
1372  << " east " << cdasCal.Easting/m
1373  << " alti " << cdasCal.Altitude/m << endl);
1374 
1375  // first fill the trivial stuff
1376  // station position
1377  const UTMPoint stationPosUTM(cdasCal.Northing,
1378  cdasCal.Easting,
1379  cdasCal.Altitude,
1380  19, 'H', wgs84);
1381 
1382  const Point stationPos = stationPosUTM.GetPoint();
1383 
1384  cdasCal.fRefSecond = theEc.Trigger.Second; // redundant info
1385  cdasCal.fX = stationPos.GetX(refCS)/m;
1386  cdasCal.fY = stationPos.GetY(refCS)/m;
1387  cdasCal.fZ = stationPos.GetZ(refCS)/m;
1388  const ReferenceEllipsoid::Triple latLonH =
1389  wgs84.PointToLatitudeLongitudeHeight(stationPos);
1390  cdasCal.fLatitude = latLonH.get<0>()/deg;
1391  cdasCal.fLongitude = latLonH.get<1>()/deg;
1392 
1393  int nSaturatedPMTs = 0;
1394  for (unsigned int iPMT = 0; iPMT < kIoSd::NPMT; ++iPMT) {
1395 
1396  if (!csIt->HasPMT(iPMT+1)) {
1397  ostringstream err;
1398  err << "Raw station " << stationID << " has no PMT #" << iPMT+1 << "!"
1399  " CDAS event might be currupted!";
1400  ERROR(err);
1401  continue; // -> skip (TODO exception? its a real problem)
1402  }
1403 
1404  const PMT& pmt = csIt->GetPMT(iPMT+1);
1405  if (!pmt.HasCalibData() || !pmt.HasRecData()) {
1406  ostringstream err;
1407  err << "Raw station " << stationID << " PMT #" << iPMT+1
1408  << " has no calib/rec data!" ;
1409  ERROR(err);
1410  continue; // -> skip (TODO exception? its a real problem)
1411  }
1412 
1413  const PMTCalibData& pmtCal = pmt.GetCalibData();
1414  const PMTRecData& pmtRec = pmt.GetRecData();
1415 
1416  TCalibSdPmt& pmti = cdasCal.fPmt[iPMT];
1417 
1418  const int saturationValue = dStation.GetSaturationValue();
1419 
1420  int nBinsSaturatedHighGain = 0;
1421  int nBinsSaturatedLowGain = 0;
1422 
1423  if (pmtRec.HasVEMTrace()) { // get PMT total vem trace
1424 
1425  const TraceD& vemTrace = pmtRec.GetVEMTrace();
1426  const TraceI& lowTrace = pmt.GetFADCTrace(sdet::PMTConstants::eLowGain);
1427  const TraceI& highTrace = pmt.GetFADCTrace(sdet::PMTConstants::eHighGain);
1428  const unsigned int vemTraceSize = vemTrace.GetSize();
1429 
1430  for (unsigned int iTraceBin = 0; iTraceBin < kIoSd::MAXSAMPLE; ++iTraceBin) {
1431 
1432  pmti.fTrace[iTraceBin] = (iTraceBin < vemTraceSize) ? vemTrace[iTraceBin] : 0;
1433 
1434  if (lowTrace[iTraceBin] >= int(saturationValue))
1435  ++nBinsSaturatedLowGain;
1436 
1437  if (highTrace[iTraceBin] >= int(saturationValue))
1438  ++nBinsSaturatedHighGain;
1439 
1440  }
1441 
1442  // now fill the PMT's trace info
1443  // TODO: make PMT integration start/stop bin available
1444  const int start = stationRec.GetSignalStartSlot();
1445  const int end = stationRec.GetSignalEndSlot();
1446  pmti.fT90 = TraceAlgorithm::TimeAtRelativeSignalX(vemTrace, start, end, 90)/ns;
1447  pmti.fT70 = TraceAlgorithm::TimeAtRelativeSignalX(vemTrace, start, end, 70)/ns;
1448  pmti.fT50 = TraceAlgorithm::TimeAtRelativeSignalX(vemTrace, start, end, 50)/ns;
1449  pmti.fT10 = TraceAlgorithm::TimeAtRelativeSignalX(vemTrace, start, end, 10)/ns;
1450  pmti.fSigInVEM = pmtRec.GetTotalCharge();
1451  pmti.fPeakInVEM = pmtRec.GetPeakAmplitude();
1452  pmti.fStartIntegration = start;
1453  pmti.fEndIntegration = end;
1454 
1455  } // pmt has vem trace
1456 
1457  // no of saturated channels
1458  pmti.fHighGainSat = nBinsSaturatedHighGain;
1459  pmti.fLowGainSat = nBinsSaturatedLowGain;
1460 
1461  // 0: no cal, 1: rough, 2: online, 3: histo, 4: extra water info
1462  pmti.fCalibratedState = 3; // TODO, non existing in DPA
1463  //pmti.fCalibratedState = 0;
1464 
1465  // from online cal
1466  pmti.fVemPeak = pmtCal.GetOnlinePeak();
1467  // from online cal or histos (best available)
1468  pmti.fVemCharge = pmtCal.GetOnlineCharge();
1469 
1470  // from offline calibration (FADC)
1471  pmti.fBaseline[IoSdEvent::eLow] = pmtCal.GetBaseline(sdet::PMTConstants::eLowGain);
1472  pmti.fBaselineSigma[IoSdEvent::eLow] = pmtCal.GetBaselineRMS(sdet::PMTConstants::eLowGain);
1473  pmti.fBaseline[IoSdEvent::eHigh] = pmtCal.GetBaseline(sdet::PMTConstants::eHighGain);
1474  pmti.fBaselineSigma[IoSdEvent::eHigh] = pmtCal.GetBaselineRMS(sdet::PMTConstants::eHighGain);
1475 
1476  // PMT
1477  pmti.fPmtBaselineSigma = 0; // TODO, non existing in DPA
1478  //TraceAlgorithm::Mean(rawtrace, fFirstMeanSlot, fLastMeanSlot);
1479 
1480  pmti.fDA = pmtCal.GetGainRatio();
1481 
1482  /* USED FOR WATER LEVEL STUDIES, SKIPPED NOW (CDAS XB experimental)
1483  pmti.fPulseSlope = ;
1484  pmti.fHistSlope = ;
1485  pmti.fChi = ; */
1486 
1487  } // end loop PMTs
1488 
1489  // now fill the station's trace info
1490  if (csIt->HasVEMTrace()) {
1491 
1492  const int start = stationRec.GetSignalStartSlot();
1493  const int end = stationRec.GetSignalEndSlot();
1494  const TraceD& vemTrace = csIt->GetVEMTrace();
1495 
1496  cdasCal.fT90 = TraceAlgorithm::TimeAtRelativeSignalX(vemTrace, start, end, 90)/ns;
1497  cdasCal.fT70 = TraceAlgorithm::TimeAtRelativeSignalX(vemTrace, start, end, 70)/ns;
1498  cdasCal.fT50 = TraceAlgorithm::TimeAtRelativeSignalX(vemTrace, start, end, 50)/ns;
1499  cdasCal.fT10 = TraceAlgorithm::TimeAtRelativeSignalX(vemTrace, start, end, 10)/ns;
1500 
1501  cdasCal.fSigInVEM = stationRec.GetTotalSignal();
1502  cdasCal.fPeakInVEM = stationRec.GetPeakAmplitude();
1503 
1504  cdasCal.fStartIntegration = start;
1505  cdasCal.fEndIntegration = end;
1506 
1507  }
1508 
1509  /* NOT YET USED (experimental)
1510  TSignal signal;
1511  signal.fPMT = ;//pmtID;
1512  signal.fStart = ;
1513  signal.fEnd = ;
1514  signal.fSignal = ;
1515  signal.fPeak = ;
1516  signal.fNoise = ;
1517  cdasCal.fSignals.push_back(signal);
1518  cdasCal.fCasuals.push_back(signal); */
1519 
1520  // rest of the TCalibStation
1521 
1522  cdasCal.fPmTStatus = stationCalib.GetNTubesOk(); // good PMTs in tank
1523  cdasCal.fSat = nSaturatedPMTs; // # of low gain saturated pmts
1524 
1525  // redundant
1526  cdasCal.fStartBin = cdasCal.fStartIntegration;
1527 
1528  cdasCal.fSeveralSignals = 0; // NOT USED YET (CDAS experimental)
1529 
1530  /* THIS IS USED FOR RECONSTRUCTION, NOT FILLED HERE: PLACEHOLDERS (see TErEvent)
1531  cdasCal.fDist = ;
1532  cdasCal.fDcore = ;
1533  cdasCal.fCosZeta = ;
1534  cdasCal.fDt = ;
1535  cdasCal.fdt = ;
1536  cdasCal.fWgt = ; */
1537 
1538  theEc.fCalibStations.push_back(cdasCal);
1539 
1540  } // end loop calibrated stations
1541 
1542  theEc.fNCalibStations = theEc.fCalibStations.size();
1543 
1544  DEBUGEC(" PushEventEc - TEcEvent (DONE) " << endl);
1545  }
1546 
1547 
1548  // convert CDAS/Ec to evt::Event
1549  void
1550  operator<<(Event& event, const TEcEvent& ec)
1551  {
1552  DEBUGEC(" PullEventEc - TEcEvent " << endl);
1553 
1554  // first fill the IoSd part
1555  event << (IoSdEvent&)ec;
1556  ConvertEcToEvent(event, ec);
1557  }
1558 
1559 
1560  void
1561  ConvertEcToEvent(evt::Event& event, const TEcEvent& ec)
1562  {
1563  auto& oSEvent = event.GetSEvent();
1564 
1565  // set reference point: PampaAmarilla
1566  const auto& wgs84 = ReferenceEllipsoid::Get(ReferenceEllipsoid::eWGS84);
1567  const auto& pampaCS = CoordinateSystemRegistry::Get("PampaAmarilla");
1568  const Point refPoint(0,0,0, pampaCS);
1569  const double refHeight = wgs84.PointToLatitudeLongitudeHeight(refPoint).get<2>();
1570  const UTMPoint cdasRefPointUTM(ec.fRefNorthing, ec.fRefEasting, refHeight, 19, 'H', wgs84);
1571 
1572  const auto& cdasRefCS = LocalCoordinateSystem::Create(cdasRefPointUTM);
1573 
1574  DEBUGEC(" Reference Point: north/east/alt " << ec.fRefNorthing << '/'
1575  << ec.fRefEasting << '/' << refHeight << endl);
1576 
1577  bool firstMsg = true;
1578 
1579  for (auto iCDASCalStation = ec.fCalibStations.begin(); iCDASCalStation != ec.fCalibStations.end(); ++iCDASCalStation) {
1580 
1581  const unsigned int stationID = iCDASCalStation->id();
1582  const int errorCode = iCDASCalStation->Error && 0xff;
1583 
1584  if (!oSEvent.HasStation(stationID)) {
1585  ostringstream err;
1586  err << "Missing station " << stationID << " in event!";
1587  ERROR(err);
1588  continue;
1589  }
1590 
1591  auto& oStation = oSEvent.GetStation(stationID);
1592 
1593  // skip station (its a non-good/uncalibratable station)
1594  if (errorCode == 2 && iCDASCalStation->Trigger.Window) {
1595  oStation.SetSilent();
1596  continue;
1597  }
1598 
1599  if (!oStation.HasCalibData())
1600  oStation.MakeCalibData();
1601 
1602  auto& oStationCalib = oStation.GetCalibData();
1603 
1604  if (!oStation.HasGPSData()) {
1605  ERROR("Raw station with signal, but without GPS data !");
1606  oStation.MakeGPSData();
1607  }
1608  auto& gpsData = oStation.GetGPSData();
1609 
1610  if (oStation.HasRecData() && firstMsg) {
1611  ERROR ("The SEvent should be completely cleared before refilling!");
1612  firstMsg = false;
1613  } else
1614  oStation.MakeRecData();
1615 
1616  auto& oStationRec = oStation.GetRecData();
1617 
1618  DEBUGEC("cal-station: " << setw(4) << stationID);
1619 
1620  const auto& sDetector = det::Detector::GetInstance().GetSDetector();
1621 
1622  const unsigned int fadcTraceLength = sDetector.GetStation(stationID).GetFADCTraceLength();
1623 
1624  const double fadcBinSize = sDetector.GetStation(stationID).GetFADCBinSize();
1625 
1626  for (unsigned int iPMT = 0; iPMT < kIoSd::NPMT; ++iPMT) {
1627 
1628  if (!oStation.HasPMT(iPMT+1)) {
1629  ostringstream err;
1630  err << "PMT " << iPMT+1 << " missing in station " << stationID << "!";
1631  ERROR(err);
1632  continue;
1633  }
1634  auto& oPMT = oStation.GetPMT(iPMT+1);
1635 
1636  if (!oPMT.HasRecData())
1637  oPMT.MakeRecData();
1638  auto& oPMTRec = oPMT.GetRecData();
1639 
1640  if (!oPMTRec.HasVEMTrace())
1641  oPMTRec.MakeVEMTrace();
1642  auto& oPMTRecTrace = oPMTRec.GetVEMTrace();
1643 
1644  const auto& pmt = iCDASCalStation->fPmt[iPMT];
1645 
1646  // copy the trace
1647  oPMTRecTrace = TraceD(fadcTraceLength, fadcBinSize);
1648 
1649  for (unsigned int iTraceBin = 0; iTraceBin < kIoSd::MAXSAMPLE; ++iTraceBin) {
1650  if (iTraceBin < fadcTraceLength)
1651  oPMTRecTrace[iTraceBin] = pmt.fTrace[iTraceBin];
1652  else
1653  ERROR("Trace out of bounds!");
1654  }
1655 
1656  // now fill the PMT's trace info
1657  oPMTRec.SetT50(pmt.T50()*ns);
1658 
1659  // not available (identical to station start/end slot)
1660  //oPMTRec.SetSignalStartSlot(pmt.fStartIntegration)
1661  //oPMTRec.SetSignalEndSlot(pmt.fEndIntegration);
1662  oPMTRec.SetTotalCharge(pmt.fSigInVEM);
1663  oPMTRec.SetPeakAmplitude(pmt.fPeakInVEM);
1664 
1665  // number of saturated channels -> not supported ?
1666  // just a flag for high/low gain saturation
1667  oStation.SetHighGainSaturation(pmt.fHighGainSat);
1668  oStation.SetLowGainSaturation(pmt.fLowGainSat);
1669 
1670  // 0: no cal, 1: rough, 2: online, 3: histo, 4: extra water info
1671  //pmt.fCalibratedState = 3; // TODO !!!!!! missing in DPA event.
1672  //pmt.fCalibratedState = 0;
1673 
1674  /* USED FOR WATER LEVEL STUDIES, SKIPPED NOW (CDAS experimental)
1675  pmt.fPulseSlope = ;
1676  pmt.fHistSlope = ;
1677  pmt.fChi = ; */
1678 
1679  } // end loop PMTs
1680 
1681  // copy the total station trace
1682  TraceD sumTrace(fadcTraceLength, fadcBinSize);
1683 
1684  for (unsigned int iTraceBin = 0; iTraceBin < kIoSd::MAXSAMPLE; ++iTraceBin) {
1685  if (iTraceBin < fadcTraceLength) {
1686  sumTrace[iTraceBin] =
1687  iCDASCalStation->fPmt[0].fTrace[iTraceBin] +
1688  iCDASCalStation->fPmt[1].fTrace[iTraceBin] +
1689  iCDASCalStation->fPmt[2].fTrace[iTraceBin];
1690  } else
1691  ERROR("Trace out of bounds!");
1692  }
1693 
1694  if (!oStation.HasVEMTrace())
1695  oStation.MakeVEMTrace();
1696  oStation.GetVEMTrace() = sumTrace;
1697 
1698  // timing of the trace END
1699  const TimeStamp gpsTime(gpsData.GetSecond(), gpsData.GetCorrectedNanosecond());
1700 
1701  DEBUGEC("bin: " << iCDASCalStation->fStartIntegration
1702  << " sec " << gpsTime.GetGPSSecond()
1703  << " nsec " << gpsTime.GetNanoSecond() << flush);
1704 
1705  // timing of the trace BEGINNING
1706  const TimeStamp traceTime = gpsTime - TimeInterval(fadcTraceLength * fadcBinSize);
1707 
1708  oStation.SetTraceStartTime(traceTime);
1709 
1710  const TimeStamp signalTime = traceTime +
1711  TimeInterval((iCDASCalStation->fStartIntegration - 0.5) * fadcBinSize);
1712 
1713  oStationRec.SetSignalStartTime(signalTime);
1714 
1715  // now fill the station's trace info
1716  oStationRec.SetSignalStartSlot(iCDASCalStation->fStartIntegration);
1717  oStationRec.SetSignalEndSlot(iCDASCalStation->fEndIntegration);
1718 
1719  oStationRec.SetT50(iCDASCalStation->T50()*ns, 0.);
1720  oStationRec.SetTotalSignal(iCDASCalStation->fSigInVEM);
1721  oStationRec.SetPeakAmplitude(iCDASCalStation->fPeakInVEM);
1722 
1723  oStationCalib.SetNTubesOk(iCDASCalStation->fPmTStatus);
1724 
1725  // redundant: iCDASCalStation->fStartBin
1726 
1727  DEBUGEC("signal " << iCDASCalStation->fSigInVEM
1728  << " peak " << iCDASCalStation->fPeakInVEM
1729  << " t50 " << iCDASCalStation->T50()*ns
1730  << " start " << iCDASCalStation->fStartIntegration
1731  << " end " << iCDASCalStation->fEndIntegration
1732  << flush);
1733 
1734  /* NOT YET USED (experimental)
1735  TSignal signal;
1736  signal.fPMT = ;//pmtID;
1737  signal.fStart = ;
1738  signal.fEnd = ;
1739  signal.fSignal = ;
1740  signal.fPeak = ;
1741  signal.fNoise = ;
1742  cdasCal.fSignals.push_back (signal);
1743  cdasCal.fCasuals.push_back (signal); */
1744 
1745  DEBUGEC(endl);
1746 
1747  } // end loop calibrated stations
1748 
1749  DEBUGEC(" PullEventEc - TEcEvent (END) " << endl);
1750  }
1751 
1752 
1754  void
1755  operator>>(const Event& event, TEsEvent& es)
1756  {
1757  DEBUGES(" PushEventEs - TEsEvent " << endl);
1758 
1759  // first do the Ec part
1760  event >> (TEcEvent&)es;
1761  ConvertEventToEs(event, es);
1762  }
1763 
1764 
1765  void
1766  ConvertEventToEs(const evt::Event& event, TEsEvent& es)
1767  {
1768  if (!event.HasSEvent()) {
1769  ERROR ("Non-existent evt::SEvent class object.");
1770  return;
1771  }
1772  const auto& oSEvent = event.GetSEvent();
1773 
1774  auto& calStations = es.fCalibStations;
1775  auto& randomStations = es.fRandomStations;
1776  auto& selectedStations = es.fSelectedStations;
1777  auto& silentStations = es.fSilentStations;
1778  auto& badStations = es.fBadStations;
1779 
1780  for (auto osIt = oSEvent.StationsBegin(), end = oSEvent.StationsEnd(); osIt != end; ++osIt) {
1781 
1782  const unsigned int stationID = osIt->GetId();
1783 
1784  DEBUGES("sel-station: " << setw(4) << stationID);
1785 
1786  // get the corresponding TCalibStation
1787  auto csIt = calStations.begin();
1788  for ( ; csIt != calStations.end(); ++csIt)
1789  if (csIt->Id == stationID)
1790  break;
1791 
1792  if (csIt == calStations.end()) {
1793  ostringstream err;
1794  err << "Raw station " << stationID << " "
1795  "not found in cdas event (accidental)! "
1796  "DPA->CDAS conversion may not be possible!";
1797  ERROR(err);
1798  } else {
1799  if (osIt->IsRejected()) {
1800  randomStations.push_back(&(*csIt));
1801  DEBUGES(" accidental" << endl);
1802  } else if (osIt->IsCandidate()) {
1803  selectedStations.push_back(&(*csIt));
1804  DEBUGES(" candidate" << endl);
1805  } else if (osIt->IsSilent()) {
1806  silentStations.push_back(&(*csIt));
1807  DEBUGES(" silent" << endl);
1808  } else {
1809  // if we reach to this point, the station must be bad!
1810  badStations.push_back(&(*csIt));
1811  DEBUGES(" bad" << endl);
1812  }
1813  }
1814 
1815  } // end station loop
1816 
1817  // mark the seed triangle
1818  if (!event.HasRecShower() || !event.GetRecShower().HasSRecShower()) {
1819  ERROR("No Seed triangle available!");
1820  return; // exception ?
1821  }
1822 
1823  const auto& showerRec = event.GetRecShower();
1824  const auto& showerSRec = showerRec.GetSRecShower();
1825  const auto& seed = showerSRec.GetReconstructionSeed();
1826 
1827  DEBUGES("Mark SEED stations: ");
1828 
1829  for (auto seedIt = seed.begin(); seedIt != seed.end(); ++seedIt) {
1830 
1831  // get the corresponding TCalibStation
1832  auto sIt = calStations.begin();
1833  for ( ; sIt != calStations.end(); ++sIt)
1834  if (int(sIt->Id) == *seedIt)
1835  break;
1836 
1837  if (sIt == calStations.end()) {
1838  ostringstream err;
1839  err << "Calib station " << *seedIt
1840  << " not found in cdas event!"
1841  " DPA->CDAS conversion not possible!";
1842  ERROR(err);
1843  continue;
1844  }
1845 
1846  sIt->Trigger.Type |= 0x400; // set bit20
1847 
1848  DEBUGES(" " << *seedIt);
1849 
1850  } // end loop seed-stations
1851 
1852  DEBUGES(endl);
1853 
1854  /* No SEED IN CDAS ES YET, just internal stuff (experimental)
1855  TSeed cdasSeed(theEs);
1856  cdasSeed.fStations.push_back(&(*iCalStation));
1857  } // enf of the seed id loop
1858  cdasSeed.fValid = true;
1859  cdasSeed.fVem = 00000;
1860  cdasSeed.fTot = 00000;
1861  cdasSeed.fNbCompat = 00000; */
1862 
1863  // set reference point: PampaAmarilla
1864  const auto& cdasRefCS = CoordinateSystemRegistry::Get("PampaAmarilla");
1865 
1866  // fill the estimated shower reconstruction
1867  const auto& axis = showerSRec.GetSeedAxis();
1868  const auto& core = showerSRec.GetSeedBarycenter();
1869 
1870  auto& estimated = es.fEstimated;
1871 
1872  estimated.fGPSSecond = es.Trigger.Second; // more redundancy
1873  estimated.fU = sin(axis.GetTheta(cdasRefCS)) * cos(axis.GetPhi(cdasRefCS));
1874  estimated.fV = sin(axis.GetTheta(cdasRefCS)) * sin(axis.GetPhi(cdasRefCS));
1875  estimated.fXCore = core.GetX(cdasRefCS)/m;
1876  estimated.fYCore = core.GetY(cdasRefCS)/m;
1877  estimated.fZCore = core.GetZ(cdasRefCS)/m; // not used in CDAS ...
1878 
1879  DEBUGES(" PushEventEs - TEsEvent (END) " << endl);
1880  }
1881 
1882 
1884  void
1885  operator<<(Event& event, const TEsEvent& es)
1886  {
1887  DEBUGES("PullEventEs - TEsEvent" << endl);
1888 
1889  event << (TEcEvent&)es;
1890  ConvertEsToEvent(event, es);
1891  }
1892 
1893 
1894  void
1895  ConvertEsToEvent(evt::Event& event, const TEsEvent& es)
1896  {
1897  auto& oSEvent = event.GetSEvent();
1898 
1899  /* tp
1900  // remove lonely stations
1901  theEs.RemoveLonelyStations();
1902  // end tp */
1903 
1904  vector<int> seed;
1905 
1906  // set candidates
1907  const auto& selectedStations = es.fSelectedStations;
1908  for (auto sIt = selectedStations.begin(); sIt != selectedStations.end(); ++sIt) {
1909 
1910  const auto* const cStat = *sIt;
1911  const unsigned int sId = cStat->id();
1912 
1913  DEBUGES("sel-station: " << setw (4) << sId);
1914 
1915  // check for beeing part of seed triangle
1916  if (cStat->Trigger.Type & 0x400) {
1917  seed.push_back(sId);
1918  DEBUGES(" seed" << flush);
1919  }
1920 
1921  if (!oSEvent.HasStation(sId)) {
1922  ERROR("SelectedStations: Can't use Event Selection with DPA Event not completely set.");
1923  } else {
1924  oSEvent.GetStation(sId).SetCandidate();
1925  DEBUGES(" candidate" << endl);
1926  }
1927 
1928  }
1929 
1930  // set accidental (fRandomStations in Es)
1931  for (const auto rs : es.fRandomStations) {
1932 
1933  const unsigned int sId = rs->id();
1934 
1935  DEBUGES("sel-station: " << setw (4) << sId);
1936 
1937  if (!oSEvent.HasStation(sId)) {
1938  ERROR("RandomStations: Can't use Event Selection with DPA Event not completely set.");
1939  } else {
1940  oSEvent.GetStation(sId).SetRejected(StationConstants::eRandom);
1941  DEBUGES(" accidental" << endl);
1942  }
1943 
1944  }
1945 
1946  // set accidental (fBadStations in Es)
1947  for (const auto bs : es.fBadStations) {
1948 
1949  const unsigned int sId = bs->id();
1950 
1951  DEBUGES("sel-station: " << setw (4) << sId << " bad" << endl);
1952 
1953  if (oSEvent.HasStation(sId))
1954  oSEvent.GetStation(sId).SetSilent();
1955 
1956  }
1957 
1958  // set silent
1959  for (const auto ss : es.fSilentStations) {
1960 
1961  const unsigned int sId = ss->id();
1962 
1963  DEBUGES("sel-station: " << setw(4) << sId);
1964 
1965  if (!oSEvent.HasStation(sId)) {
1966  ERROR("SilentStations: Can't use Event Selection with DPA Event not completely set.");
1967  } else {
1968  oSEvent.GetStation(sId).SetSilent();
1969 
1970  DEBUGES(" silent" << endl);
1971  }
1972 
1973  }
1974 
1975  if (!event.HasRecShower())
1976  event.MakeRecShower();
1977 
1978  auto& showerRec = event.GetRecShower();
1979 
1980  if (!showerRec.HasSRecShower())
1981  showerRec.MakeSRecShower();
1982 
1983  auto& srecData = showerRec.GetSRecShower();
1984 
1985  if (seed.size() != 3U)
1986  WARNING("Seed size != 3.");
1987  srecData.SetReconstructionSeed(seed);
1988 
1989  srecData.SetT4Trigger(const_cast<TEsEvent&>(es).IsT4());
1990  srecData.SetT5Trigger(const_cast<TEsEvent&>(es).IsT5());
1991 
1992  // set reference point: PampaAmarilla
1993  const auto& cdasRefCS = CoordinateSystemRegistry::Get("PampaAmarilla");
1994 
1995  const auto& estimated = es.fEstimated;
1996 
1997  const double u = estimated.fU; // sintheta*cosphi
1998  const double v = estimated.fV; // sintheta*sinphi
1999  const double w = sqrt(1 - Sqr(u) - Sqr(v));
2000 
2001  const Point core(estimated.fXCore*m,
2002  estimated.fYCore*m,
2003  estimated.fZCore*m, cdasRefCS);
2004  const Vector axis(u, v, w, cdasRefCS);
2005 
2006  srecData.SetSeedAxis(axis);
2007  srecData.SetSeedBarycenter(core);
2008 
2009  DEBUGES("PullEventEs - TEsEvent (END) " << endl);
2010  }
2011 
2012 
2014 
2015  void
2016  operator>>(const Event& event, TErEvent& er)
2017  {
2018  DEBUGER(" PushEventEr - TErEvent " << endl);
2019 
2020  // first do the Es part
2021  event >> (TEsEvent&)er;
2022  ConvertEventToEr(event, er);
2023  }
2024 
2025 
2026  void
2027  ConvertEventToEr(const evt::Event& theEvent, TErEvent& theEr)
2028  {
2029  if (!theEvent.HasRecShower() || !theEvent.GetRecShower().HasSRecShower())
2030  return;
2031 
2032  const auto& siteCS = CoordinateSystemRegistry::Get("PampaAmarilla");
2033 
2034  /* if (!theEvent.HasSEvent()) {
2035  ERROR("Non-existent evt::SEvent class object.");
2036  return;
2037  }
2038  const sevt::SEvent& oSEvent = theEvent.GetSEvent(); */
2039 
2040  const auto& showerRec = theEvent.GetRecShower();
2041  const auto& showerSRec = showerRec.GetSRecShower();
2042 
2043  // now fill the TShowerParams part
2044  const auto& time = showerSRec.GetCoreTime();
2045 
2046  TShowerParams& cRec = theEr.fRec;
2047 
2048  cRec.fT0 = time.GetGPSNanoSecond();
2049  cRec.fGPSSecond = time.GetGPSSecond();
2050 
2051  const auto& core = showerSRec.GetCorePosition();
2052  const auto& axis = showerSRec.GetAxis();
2053  const auto& localCS = LocalCoordinateSystem::Create(core);
2054 
2055  cRec.fU = axis.GetX(localCS);
2056  cRec.fV = axis.GetY(localCS);
2057 
2058  cRec.fXCore = core.GetX(siteCS)/m;
2059  cRec.fYCore = core.GetY(siteCS)/m;
2060  cRec.fZCore = core.GetZ(siteCS)/m;
2061 
2062  cRec.fSRef = showerSRec.GetShowerSize();
2063  switch (showerSRec.GetShowerSizeType()) {
2065  cRec.fRefDist = 1000;
2066  break;
2067  case ShowerSRecData::eS450:
2068  cRec.fRefDist = 450;
2069  break;
2070  default:
2071  ostringstream msg;
2072  msg << "Could not determine the reference distance for shower size."
2073  "ShowerSizeType = " << showerSRec.GetShowerSizeType();
2074  WARNING(msg);
2075  // I don't really know what to do in this situation, but ...
2076  cRec.fRefDist = 0;
2077  }
2078 
2079  double xMax = 0;
2080  double xMaxError = 0;
2081  if (showerRec.HasFRecShower() &&
2082  showerRec.GetFRecShower().HasGHParameters()) {
2083  const VGaisserHillasParameter& gh = showerRec.GetFRecShower().GetGHParameters();
2084  xMax = gh.GetXMax();
2085  xMaxError = gh.GetXMaxError();
2086  }
2087 
2088  cRec.fXmax = xMax/(g/cm2);
2089 
2090  const double curv = showerSRec.GetCurvature()*m;
2091  cRec.fR = (curv ? 1/curv : 0);
2092 
2093  // Last fit information
2094  cRec.fChi2 = showerSRec.GetLDFChi2();
2095  cRec.frChi2 = showerSRec.GetLDFChi2()/showerSRec.GetLDFNdof();
2096  cRec.fddl = showerSRec.GetLDFNdof();
2097 
2098  // Relating to the ldf
2099  cRec.fBeta = showerSRec.GetBeta();
2100  cRec.fGamma = showerSRec.GetGamma();
2101 
2102  // Energy
2103  cRec.fE = showerSRec.GetEnergy()/EeV;
2104  cRec.fdE = showerSRec.GetEnergyError()/EeV;
2105 
2106  // covariance matric
2107  for (int i = 0; i < 8; ++i)
2108  for (int j = 0; j < 8; ++j)
2109  cRec.fVarCov[i][j] = 0;
2110 
2111  const double theta = axis.GetTheta(localCS);
2112  const double sinTheta = sin(theta);
2113  const double cosTheta = cos(theta);
2114  const double phi = axis.GetPhi(localCS);
2115  const double sinPhi = sin(phi);
2116  const double cosPhi = cos(phi);
2117 
2118  cRec.fVarCov[0][0] = Sqr(showerSRec.GetCoreTimeError().GetNanoSecond()); // T0
2119  cRec.fVarCov[1][1] = Sqr(showerSRec.GetThetaError() * cosTheta * cosPhi) -
2120  Sqr(showerSRec.GetPhiError() * sinTheta * sinPhi); // u
2121  cRec.fVarCov[2][2] = Sqr(showerSRec.GetThetaError() * cosTheta * sinPhi) +
2122  Sqr(showerSRec.GetPhiError() * sinTheta * cosPhi); // v
2123  cRec.fVarCov[3][3] = Sqr(showerSRec.GetCoreError().GetX(localCS)/m); // x
2124  cRec.fVarCov[4][4] = Sqr(showerSRec.GetCoreError().GetY(localCS)/m); // y
2125  cRec.fVarCov[5][5] = Sqr(showerSRec.GetShowerSizeError()); //s1000
2126  cRec.fVarCov[6][6] = Sqr(xMaxError/(g/cm2)); // xmax
2127  cRec.fVarCov[7][7] = Sqr(showerSRec.GetCurvatureError()/m); //R
2128 
2129  DEBUGER("PushEventEr - TErEvent (END) " << endl);
2130  }
2131 
2132 
2134  void
2135  operator<<(Event& event, const TErEvent& er)
2136  {
2137  DEBUGER(" PullEventEr - TErEvent " << endl);
2138 
2139  event << (TEsEvent&)er;
2140  ConvertErToEvent(event, er);
2141  }
2142 
2143 
2144  void
2145  ConvertErToEvent(evt::Event& event, const TErEvent& er)
2146  {
2147  const auto& pampaCS = CoordinateSystemRegistry::Get("PampaAmarilla");
2148 
2149  if (!event.HasRecShower())
2150  event.MakeRecShower();
2151  auto& recData = event.GetRecShower();
2152 
2153  if (!recData.HasSRecShower())
2154  recData.MakeSRecShower();
2155  auto& srecData = recData.GetSRecShower();
2156 
2157  if (!recData.HasFRecShower())
2158  recData.MakeFRecShower();
2159  auto& frecData = recData.GetFRecShower();
2160 
2161  const auto& cRec = er.fRec;
2162 
2163  // get the errors out of the covariance matrix
2164  const double nsecError = sqrt(cRec.fVarCov[0][0])*ns;
2165  //const double uError = sqrt(cRec.fVarCov[1][1]);
2166  //const double vError = sqrt(cRec.fVarCov[2][2]);
2167  const double xError = sqrt(cRec.fVarCov[3][3])*m;
2168  const double yError = sqrt(cRec.fVarCov[4][4])*m;
2169  //const double s1000Error = sqrt(cRec.fVarCov[5][5]);
2170  const double xMaxError = sqrt(cRec.fVarCov[6][6])*g/cm2;
2171  const double rcError = sqrt(cRec.fVarCov[7][7])*m;
2172 
2174  gh2.SetXMax(cRec.fXmax*g/cm2, xMaxError);
2175  if (!frecData.HasGHParameters())
2176  frecData.MakeGHParameters(gh2);
2177  else
2178  frecData.GetGHParameters() = gh2;
2179 
2180  const TimeStamp coreTime =
2181  TimeStamp((unsigned int)(cRec.fGPSSecond),
2182  (unsigned int)(cRec.fT0));
2183  const TimeInterval coreTimeErr(nsecError*ns);
2184  srecData.SetCoreTime(coreTime, coreTimeErr);
2185 
2186  const Point core(cRec.fXCore*m,
2187  cRec.fYCore*m,
2188  cRec.fZCore*m, pampaCS);
2189  const Vector coreError(xError, yError, 0, pampaCS);
2190  const auto& localCS = LocalCoordinateSystem::Create(core);
2191 
2192  const double u = cRec.fU; // sintheta*cosphi
2193  const double v = cRec.fV; // sintheta*sinphi
2194  const double w = sqrt(1 - Sqr(u) - Sqr(v));
2195  const Vector axis(u,v,w, localCS);
2196 
2197  // TODO: do error propagation
2198  const double thetaError = 0;
2199  const double phiError = 0;
2200 
2201  srecData.SetAxis(axis);
2202  srecData.SetCorePosition(core);
2203  srecData.SetCoreError(coreError);
2204  srecData.SetThetaError(thetaError);
2205  srecData.SetPhiError(phiError);
2206 
2207  srecData.SetShowerSize(cRec.fSRef, cRec.dSRef());
2208  if (Test<CloseTo>(cRec.fRefDist, 450*m))
2209  srecData.SetShowerSizeType(ShowerSRecData::eS450);
2210  else if (Test<CloseTo>(cRec.fRefDist, 1000*m))
2211  srecData.SetShowerSizeType(ShowerSRecData::eS1000);
2212  else {
2213  ostringstream msg;
2214  msg << "Could not determine the ShowerSizeType "
2215  "CDAS fRefDist = " << cRec.fRefDist << endl;
2216  srecData.SetShowerSizeType(ShowerSRecData::eUndefined);
2217  }
2218 
2219  if (cRec.fR)
2220  srecData.SetCurvature(1/(cRec.fR*m), rcError);
2221  else
2222  srecData.SetCurvature(0, 0);
2223 
2224  // Last fit information
2225  srecData.SetLDFChi2(cRec.fChi2, cRec.fddl);
2226 
2227  // Relating to the ldf
2228  const double betaError = -1;
2229  const double gammaError = -1;
2230  srecData.SetBeta(cRec.fBeta, betaError);
2231  srecData.SetGamma(cRec.fGamma, gammaError);
2232 
2233  // Energy
2234  srecData.SetEnergy(cRec.fE*EeV, cRec.fdE*EeV);
2235 
2236  // Number of Stations used in LDF fit?
2237  srecData.SetNumberOfActiveStations(int(cRec.fddl));
2238 
2239  // This stuff will never be part of an 'official' CDAS realease, but it was
2240  // existing for some time in CDAS v4r4pxx
2241  if (!event.HasSEvent())
2242  event.MakeSEvent();
2243 
2244  auto& sevent = event.GetSEvent();
2245 
2246  // loop all stations and get StationRecData
2247  const auto& calibStations = er.fCalibStations;
2248  for (auto sIt = calibStations.begin(); sIt != calibStations.end(); ++sIt) {
2249 
2250  const unsigned int sId = sIt->id();
2251 
2252  if (!sevent.HasStation(sId)) {
2253  ostringstream err;
2254  err << "Missing station " << sId << " in event!";
2255  ERROR(err);
2256  continue;
2257  }
2258 
2259  auto& oStation = sevent.GetStation(sId);
2260 
2261  if (!oStation.HasRecData())
2262  oStation.MakeRecData();
2263 
2264  auto& oStationRec = oStation.GetRecData();
2265 
2266  oStationRec.SetSPDistance(sIt->fDist, 0);
2267  //cdasCal.fDcore = ; // not avail. in DPA
2268  //cdasCal.fCosZeta = ; // not clear
2269  oStationRec.SetResidual(sIt->fDt);
2270  oStationRec.SetLDFResidual(sIt->fDt);
2271  //cdasCal.fdt = ; // unclear
2272  //cdasCal.fWgt = ; // only internal use ?
2273 
2274  }
2275 
2276  DEBUGER("PullEventEr - TErEvent (END) " << endl);
2277  }
2278 
2279 
2280  //From CDAS to Offline
2281  void
2282  operator<<(evt::Event& event, const md::Event& rawEvent)
2283  {
2284  DEBUGRAW(" PullEventRaw - md::Event " << endl);
2285  ConvertIoMdToEvent(event, rawEvent);
2286  }
2287 
2288 
2289  void
2290  ConvertIoMdToEvent(evt::Event& oEvent, const md::Event& rEvent)
2291  {
2292  // if no MDetector is configured do nothing
2293  if (!HasMDetectorConfig(rEvent.HasCounters()))
2294  return;
2295 
2296  ostringstream msg;
2297 
2298  if (!oEvent.HasMEvent())
2299  oEvent.MakeMEvent();
2300 
2301  auto& omEvent = oEvent.GetMEvent();
2302  if (rEvent.HasCounters()) {
2303  msg.str("");
2304  msg << "Number of Counters: " << rEvent.CountersSize();
2305  INFO(msg);
2306  } else
2307  return;
2308 
2309  /* md trigger from real event (CDAS) */
2310  const auto& rTrigger = rEvent.GetTrigger();
2311  const unsigned int t3Sec = rTrigger.GetT3Sec();
2312  const unsigned int t3NanoSec = int(rTrigger.GetT3Mic() * 1000);
2313  const auto mdId = rTrigger.GetId();
2314  const auto t3algorithm = rTrigger.GetT3Algorithm();
2315 
2316  const TimeStamp mdT3GPS(t3Sec, t3NanoSec);
2317 
2318  /* mevt header (Offline) */
2319  auto& omHeader = omEvent.GetHeader();
2320  omHeader.SetId(mdId);
2321  omHeader.SetTime(mdT3GPS); // by construction, sould be identical to currentTime of SD
2322  /* mevt trigger (Offline) */
2323  auto& omTrigger = omHeader.GetTrigger();
2324  omTrigger.SetAlgorithm(t3algorithm);
2325 
2326  ostringstream idss;
2327  /* evt header (append md id to the end of the string) (Offline) */
2328  auto& oHeader = oEvent.GetHeader();
2329  if (!oHeader.GetId().empty())
2330  idss << oHeader.GetId() << "__";
2331  idss << "md_" << mdId;
2332 
2333  oHeader.SetTime(mdT3GPS);
2334  oHeader.SetId(idss.str());
2335 
2336  const auto& mDetector = det::Detector::GetInstance().GetMDetector();
2337 
2338  // Loop on CDAS data and creates/fill Offline structure
2339  for (auto cIt = rEvent.CountersBegin(), end = rEvent.CountersEnd(); cIt != end; ++cIt) {
2340 
2341  const auto& mdCter = **cIt;
2342  const int cId = mdCter.GetId();
2343  const unsigned int t3delay = mdCter.GetT3Delay(); // if -1 T3NotFound on-ground
2344  const size_t mdWindow = mdCter.GetWindow();
2345 
2346  int sdError = -2; // -2 No SD station, -1 No SD trigger data, otherwise has the same codification of SDError [from 0 to 7]
2347  int sdWindow = -1;
2348  // To check SD station error (not available in MEvent data)
2349  const auto& oSEvent = oEvent.GetSEvent();
2350  if (oSEvent.HasStation(cId)) {
2351  ++sdError;
2352  const auto& oStation = oSEvent.GetStation(cId);
2353  // T2 Trigger
2354  if (oStation.HasTriggerData()) {
2355  const auto& oStationTrigger = oStation.GetTriggerData();
2356  sdError = oStationTrigger.GetErrorCode();
2357  sdWindow = oStationTrigger.GetWindowMicroSecond();
2358  }
2359  }
2360 
2361  if (!omEvent.HasCounter(cId))
2362  omEvent.MakeCounter(cId);
2363 
2364  // retrieves mevt::Counter and mdet::Counter (Offline) just created
2365  auto& oCounter = omEvent.GetCounter(cId);
2366  const auto& mdetCounter = mDetector.GetCounter(cId);
2367 
2368  for (auto mIt = mdCter.ModulesBegin(), end = mdCter.ModulesEnd(); mIt != end; ++mIt) {
2369 
2370  const auto& mdMod = **mIt;
2371  const int mId = mdMod.GetId();
2372 
2373  if (!oCounter.HasModule(mId))
2374  oCounter.MakeModule(mId);
2375 
2376  // retrieve mevt::Module (Offline) just created
2377  auto& oModule = oCounter.GetModule(mId);
2378 
2379  // retrieve mdet::Module
2380  const auto& mdetModule = mdetCounter.GetModule(mId);
2381 
2382  msg.str("");
2383  msg << "Counter " << oCounter.GetId() << " module " << oModule.GetId() << " is ";
2384 
2385  std::ostringstream errorFlag;
2386  errorFlag << "SDError:" << sdError <<":SDWindow:"<< sdWindow << ":MDWindow:" << mdWindow;
2387 
2388  if (t3delay == (unsigned int)(-1)) {
2389 
2390  errorFlag << ":T3NotFound";
2391 
2392  if (sdError == 2 && sdWindow != 0) { // Silent station
2393  oModule.SetSilent();
2394  msg << "silent because \"" << errorFlag.str() << "\".";
2395  } else {
2396  oModule.SetRejected(errorFlag.str()); // T1-LTS pair not found in the on-ground (SBC) table, no request is broadcast to modules underground
2397  msg << "rejected because \"" << errorFlag.str() << "\".";
2398  }
2399  WARNING(msg);
2400  continue; // no more to do for this module
2401  } else if (!mdMod.HasT1()) { // and if T3NotFound
2402  errorFlag << ":T1NotFound";
2403  oModule.SetRejected(errorFlag.str()); // The LTS broadcasted to under-ground modules have not been found
2404  msg << "rejected because \"" << errorFlag.str() << "\".";
2405  WARNING(msg);
2406  continue; // no more to do for this module
2407  } else if (sdError != 0 && sdError != 256) {
2408  errorFlag << ":T1Found";
2409  oModule.SetRejected(errorFlag.str()); // Inconstistency between SD and MD: for SD this station maybe Silent or Bad, for MD the counter is candidate (plausible argument: different buffer length)
2410  msg << "rejected because \"" << errorFlag.str() << "\".";
2411  WARNING(msg);
2412  // continue because MD may have data to load :-(
2413  } else {
2414  msg << "candidate.";
2415  oModule.SetCandidate();
2416  }
2417 
2418  const auto mdmask = mdetModule.IsSiPM() ?
2419  mdetModule.GetFrontEndSiPM().GetMask() : mdetModule.GetFrontEnd().GetMask();
2420 
2421  const bitset<64> bit_mask = mdmask;
2422  oModule.SetChannelMask(bit_mask);
2423 
2424  const auto& dyn = (*mIt)->GetIntegrator();
2425  if (!dyn.empty()) {
2426  INFO("*** This module has dynode-integrated signal ***");
2427  if (!oModule.HasDynodeTrace())
2428  oModule.MakeDynodeTrace();
2429  auto& oDynodeTrace = oModule.GetDynodeTrace();
2430  oDynodeTrace.Assign(dyn.begin(), dyn.end());
2431  }
2432 
2433  const auto& integratorA = (*mIt)->GetIntegratorA();
2434  if (!integratorA.empty()) {
2435  INFO("*** This module has dynode-integrated signal for SiPM electronics ***");
2436  if (!oModule.HasIntegratorATrace())
2437  oModule.MakeIntegratorATrace();
2438  auto& oIntegratorATrace = oModule.GetIntegratorATrace();
2439  oIntegratorATrace.Assign(integratorA.begin(), integratorA.end());
2440 
2441  if (!oModule.HasIntegratorBTrace())
2442  oModule.MakeIntegratorBTrace();
2443  auto& oIntegratorBTrace = oModule.GetIntegratorBTrace();
2444  const auto& integratorB = (*mIt)->GetIntegratorB();
2445  oIntegratorBTrace.Assign(integratorB.begin(), integratorB.end());
2446  }
2447 
2448  // Create all channels
2449  for (unsigned int bit = 0, chId = 1; bit < 64; ++bit, ++chId) {
2450 
2451  if (!oModule.HasChannel(chId))
2452  oModule.MakeChannel(chId);
2453 
2454  // retrieves mevt::Channel and mdet::Channel/FrontEnd (Offline) just created
2455  mevt::Channel& oChannel = oModule.GetChannel(chId);
2456  oChannel.SetMask(bit_mask[chId-1]); // set the channel mask
2457 
2458  if (!oChannel.HasTrace()) {
2459  oChannel.MakeTrace();
2460  //oChannel.GetTrace().SetBinning(sRate);
2461  oChannel.GetTrace().SetStart(0);
2462  oChannel.GetTrace().SetStop(0);
2463  }
2464 
2465  }
2466 
2467  const unsigned int numberOfSamples = mdetModule.IsSiPM() ?
2468  mdetModule.GetFrontEndSiPM().GetBufferLength() :
2469  mdetModule.GetFrontEnd().GetBufferLength();
2470  FillMdTraces(mdMod, oModule, numberOfSamples);
2471 
2472  } // end modules loop
2473  } // end counters loop
2474  }
2475 
2476 
2477  void
2478  FillMdTraces(const md::Module& mdMod, mevt::Module& oModule, unsigned int numberOfSamples)
2479  {
2480  // Fill time bins of all traces
2481  auto rawsigIt = mdMod.RawSignalBegin();
2482  for (unsigned int nTimeBin = 0; nTimeBin < numberOfSamples; ++nTimeBin) {
2483 
2484  if (rawsigIt != mdMod.RawSignalEnd() && nTimeBin == (*rawsigIt)->GetTimeBin()) { // fill traces with data
2485 
2486  const bitset<64> bc = (*rawsigIt)->GetSample();
2487 
2488  ostringstream msg;
2489  msg << setw(10) << setfill(' ')
2490  << nTimeBin << ' '
2491  << bc << " "
2492  " ==> (" << bc.count() << ")\n";
2493  DEBUGLOG(msg);
2494 
2495  //Now fill samples on corresponding channels for this time bin
2496  for (unsigned int bit = 0, chId = 1, n = bc.size(); bit < n; ++bit, ++chId) {
2497 
2498  /* retrieves mevt::Channel and mdet::Channel/FrontEnd (Offline) just created */
2499  auto& oChannel = oModule.GetChannel(chId);
2500  auto& trace = oChannel.GetTrace();
2501 
2502  //first "1" of this channel
2503  if (!trace.GetStart() && bc[bit])
2504  trace.SetStart(nTimeBin);
2505 
2506  //last "1" of this channel
2507  if (bc[bit])
2508  trace.SetStop(nTimeBin);
2509 
2510  /* Signal in MD is a boolean trace of 0s and 1s */
2511  trace.PushBack(bool(bc[bit])); // Load the time sample in channel number chId
2512 
2513  }
2514 
2515  ++rawsigIt; // move to the next RawSignal record
2516 
2517  } else {
2518 
2519  // fill traces with zeros
2520  for (unsigned int bit = 0, chId = 1; bit < 64; ++bit, ++chId) {
2521  /* Signal in MD is a boolean trace */
2522  auto& oChannel = oModule.GetChannel(chId);
2523  auto& trace = oChannel.GetTrace();
2524  trace.PushBack(false);
2525  }
2526 
2527  }
2528 
2529  }
2530  }
2531 
2532 
2533  // From Offline to CDAS
2534  void
2535  operator>>(const evt::Event& event, md::Event& rawEvent)
2536  {
2537  ConvertEventToIoMd(event, rawEvent);
2538  }
2539 
2540 
2541  void
2542  ConvertEventToIoMd(const evt::Event& /*event*/, md::Event& /*rawEvent*/)
2543  {
2544  // do nothing
2545  }
2546 
2547 } // namespace evt
2548 
2549 
2550 namespace io {
2551 
2552  // -----------------------------------------------------
2553  // TAKE CARE: copied from SdCalibrator
2554  void
2556  {
2557  //StationGPSData& gpsData = oStation.GetGPSData();
2558 
2559  // NEW : TAP 26/04/2003 -> From CDAS v1r2 : taking into account Offsets...
2560  // Warning, part of the field is used for the tick offset:
2561  // GPS Offset = 0.01*(short)(gps->Offset & 0xffff)
2562  // Tick Offset = (short)(gps->Offset>>16)
2563  // New: taking into account 100ns jumps
2564  // From Moulin Rouge and Dia Noche we found that the TickFall-Tick
2565  // can be 0, 9, 10, 11 or a big number. The big number could be
2566  // understood if it is the trigger of another event. It was found
2567  // that if the dt is 0, there is a 100ns jump in the event, and not
2568  // in any other case, including big values. Hence this empiric
2569  // correction
2570  //
2571  // This is the code from IoSd v1r2 :
2572  // gps->NanoSecond =
2573  // (unsigned int)((gps->Tick*(1000000000.0 + gps->NextST - gps->CurrentST)
2574  // /gps->Next100) + gps->CurrentST + 0.01*(short)(gps->Offset & 0xffff))
2575  // -100*(gps->TickFall==gps->Tick);
2576 
2577  const unsigned int tick = gpsData.GetTick();
2578  const int currentST = gpsData.GetCurrentST();
2579  const int next100 = gpsData.GetNext100();
2580  const int nextST = gpsData.GetNextST();
2581 
2582  const unsigned int tickFall = gpsData.GetTickFall();
2583  const int offset = gpsData.GetOffset();
2584 
2585  const unsigned int nanosecond =
2586  (unsigned int)((tick * (1e9 + nextST - currentST) / next100) + currentST +
2587  0.01 * short(offset & 0xffff)) - 100 * (tickFall == tick);
2588 
2589  gpsData.SetCorrectedNanosecond(nanosecond);
2590  }
2591 
2592 }
void operator>>(const Event &theEvent, IoSdEvent &rawSEvent)
void SetStop(const SizeType stop)
Set valid data stop bin.
Definition: Trace.h:151
int GetEvolution() const
Definition: PMTCalibData.h:76
StationIterator StationsEnd()
End of all stations.
Definition: SEvent.h:59
utl::TraceD & GetVEMTrace(const StationConstants::SignalComponent source=StationConstants::eTotal)
Traces calibrated in VEM Peak.
Definition: PMTRecData.h:46
double GetTotalCharge() const
Total charge.
Definition: PMTRecData.h:137
#define DEBUGES(x)
bool HasRecData() const
Check for existenc of PMT reconstructed data object.
Definition: SEvent/PMT.h:53
constexpr T Sqr(const T &x)
Point object.
Definition: Point.h:32
mevt::MEvent & GetMEvent()
class to hold data at PMT level
Definition: SEvent/PMT.h:28
void SetMask(bool mask)
double GetBaselineRMS(const sdet::PMTConstants::PMTGain gain=sdet::PMTConstants::eHighGain) const
Definition: PMTCalibData.h:44
static const std::set< int > gCycloneYears({2007, 2008, 2009})
IsProxy< T > Is(const T &x)
Definition: Is.h:46
bool HasMEvent() const
Detector description interface for Station-related data.
evt::Header & GetHeader()
PMTCalibData & GetCalibData()
Get object containing PMT calibration data.
Definition: SEvent/PMT.h:56
void ConvertEsToEvent(evt::Event &event, const TEsEvent &es)
bool HasRecShower() const
void SetTime(const utl::TimeStamp &t)
Definition: Event/Header.h:38
Interface class to access to the SD part of an event.
Definition: SEvent.h:39
const std::vector< int > & GetMuonChargeHisto() const
histogram of the sum of muon charges (not really used anywhere)
void ConvertIoSdToEvent(evt::Event &oEvent, const IoSdEvent &rEvent)
Class to hold and convert a point in geodetic coordinates.
Definition: UTMPoint.h:40
int GetMuonPeakHistoOffset() const
x-axis offset of the muon peak histogram
Definition: PMTCalibData.h:66
unsigned int GetNT1() const
number of T1 received during calibration
PMTRecData & GetRecData()
Get object containing PMT reconstructed data.
Definition: SEvent/PMT.h:48
#define DEBUGER(x)
ShowerRecData & GetRecShower()
bool HasCalibData() const
Check for existence of PMT calibration data object.
Definition: SEvent/PMT.h:61
const std::vector< int > & GetMuonChargeHisto() const
Muon charge histogram.
Definition: PMTCalibData.h:69
bool HasSimShower() const
unsigned int GetId() const
Get Id of the trigger.
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 ConvertEventToEc(const evt::Event &theEvent, TEcEvent &theEc)
void SetXMax(const double xMax, const double error)
#define INFO(message)
Macro for logging informational messages.
Definition: ErrorLogger.h:161
const std::vector< int > & GetMuonPeakHisto() const
Muon peak histogram.
Definition: PMTCalibData.h:64
int GetId() const
Definition: SEvent/Header.h:20
unsigned int GetNT2() const
number of T2 received during calibration
void UpdateElectronics(const bool isUUB) const
revt::REvent & GetREvent()
Base class for exceptions trying to access non-existing components.
Header file holding the SD Event Trigger class definition.
Definition: SEvent/Header.h:16
bool HasMDetectorConfig(const bool printMsg=false)
utl::TraceB & GetTrace()
const std::string & GetAlgorithmName() const
#define DEBUGEC(x)
bool HasREvent() const
const double EeV
Definition: GalacticUnits.h:34
const std::vector< int > & GetMuonShapeHisto() const
Average shape of a muon.
Definition: PMTCalibData.h:74
unsigned int GetPreviousId() const
Get Id of the FD trigger that contains data for this event.
double GetNorthing() const
Get the northing.
Definition: UTMPoint.h:206
void ApplyTimeCorrection(StationGPSData &gpsData)
const std::vector< int > & GetMuonBaseHisto() const
Muon base histogram.
Definition: PMTCalibData.h:59
void FillMdTraces(const md::Module &mdMod, mevt::Module &oModule, unsigned int numberOfSamples)
ShowerSRecData & GetSRecShower()
#define U
std::vector< int >::const_iterator ConstIterator
Definition: Trace.h:60
Trace< double > TraceD
Definition: Trace-fwd.h:26
A TimeStamp holds GPS second and nanosecond for some event.
Definition: TimeStamp.h:110
constexpr double deg
Definition: AugerUnits.h:140
Iterator Begin()
Definition: Trace.h:75
const char * Plural(const T n)
Definition: String.h:104
unsigned int GetTick() const
boost::shared_ptr< const CoordinateTransformer > CoordinateSystemPtr
Shared pointer for coordinate systems.
bool HasFADCTrace(const StationConstants::SignalComponent source=StationConstants::eTotal) const
Check if a FADC trace exists. Trace source may be specified.
Definition: SEvent/PMT.h:83
void ConvertEventToIoMd(const evt::Event &, md::Event &)
int GetMuonChargeHistoOffset() const
x axis offset of the combined charge histogram
constexpr double s
Definition: AugerUnits.h:163
Reference ellipsoids for UTM transformations.
Module level event data.
Definition: MEvent/Module.h:41
class to hold reconstructed data at PMT level
Definition: PMTRecData.h:38
void operator<<(Event &event, const IoSdEvent &rawEvent)
grabs the data of an IoSdEvent and stores it in evt::Event
int GetOffset() const
Get GPS offset compared to a reference.
double GetX(const CoordinateSystemPtr &coordinateSystem) const
Definition: BasicVector.h:206
unsigned int GetSaturationValue() const
const double ns
Interface class to access the Event Trigger (T3)
constexpr double nanosecond
Definition: AugerUnits.h:143
const utl::TimeStamp & GetCoreTime() const
time when shower front passes through the core point
#define DEBUGLOG(message)
Macro for logging debugging messages.
Definition: ErrorLogger.h:157
void ConditionalCopy(const T1 &src, T2 *const dst, const unsigned int dstSize, const string &what)
void ConvertEventToEs(const evt::Event &event, TEsEvent &es)
Online Calibration data.
Definition: PMTCalibData.h:27
Header & GetHeader()
access to REvent Header
Definition: REvent.h:239
void SetStart(const SizeType start)
Set valid data start bin.
Definition: Trace.h:145
#define DEBUGRAW(x)
bool HasTrigger() const
check whether the central trigger object exists
Definition: SEvent.h:153
void MakeTrigger()
Create the central trigger object.
Definition: SEvent.cc:102
Triple PointToLatitudeLongitudeHeight(const Point &thePoint) const
Convert Point to Lat/Long/Height.
Channel & GetChannel(const int cId)
Definition: MEvent/Module.h:95
double GetEasting() const
Get the easting.
Definition: UTMPoint.h:209
void ConvertErToEvent(evt::Event &event, const TErEvent &er)
void ConvertEventToIoSd(const evt::Event &theEvent, IoSdEvent &rawSEvent)
Station Calibration data
unsigned int GetNTot() const
total number of triggers recevied during calibration
unsigned int GetCorrectedNanosecond() const
Get corrected trigger nanosecond.
constexpr double g
Definition: AugerUnits.h:200
boost::tuple< double, double, double > Triple
Coordinate triple.
int GetNErrorZeroStations() const
Get number of error zero stations (mapped over from IoSdEvent)
Definition: SEvent.h:131
SizeType GetSize() const
Definition: Trace.h:156
#define WARNING(message)
Macro for logging warning messages.
Definition: ErrorLogger.h:163
Gaisser Hillas with 4 parameters.
utl::TraceI & GetFADCTrace(const sdet::PMTConstants::PMTGain gain=sdet::PMTConstants::eHighGain, const StationConstants::SignalComponent source=StationConstants::eTotal)
Definition: SEvent/PMT.h:72
Station & GetStation(const int stationId)
retrieve station by id throw utl::NonExistentComponentException if n.a.
Definition: SEvent.h:116
double GetBaseline(const sdet::PMTConstants::PMTGain gain=sdet::PMTConstants::eHighGain) const
Definition: PMTCalibData.h:41
void RemoveScintillator() const
unsigned int GetNStations() const
Get number of stations in the trigger.
const std::string & GetId() const
Get the event identifier.
Definition: Event/Header.h:31
double GetY(const CoordinateSystemPtr &coordinateSystem) const
Definition: BasicVector.h:209
constexpr double hPa
Definition: AugerUnits.h:218
boost::tuple< double, double, double > GetCoordinates3() const
Get norting, easting, and height.
Definition: UTMPoint.h:224
unsigned int GetStartSecond() const
GPS second of start of calibration.
A TimeInterval is used to represent time elapsed between two events.
Definition: TimeInterval.h:43
utl::TimeStamp GetTime() const
Get time of the trigger.
unsigned long GetGPSSecond() const
GPS second.
Definition: TimeStamp.h:124
Unlock(const sdet::Station &station)
double GetGPSNanoSecond() const
GPS nanosecond.
Definition: TimeStamp.h:127
unsigned int GetEndSecond() const
GPS second of end of calibration.
int GetMuonBaseHistoOffset() const
x-axis offset of the muon base histogram
Definition: PMTCalibData.h:61
Station Trigger Data description
StationIterator StationsBegin()
Beginning of all stations.
Definition: SEvent.h:57
bool HasRDetectorConfig(const bool printMsg=false)
Channel level event data.
void SetId(const int id)
Definition: REvent/Header.h:28
Interface class for access to the Gaisser-Hillas parameters.
Vector object.
Definition: Vector.h:30
Detector description interface for SDetector-related data.
Definition: SDetector.h:42
void SetCorrectedNanosecond(const unsigned int ns)
Set corrected trigger nanosecond.
int GetVersion() const
version of the onboard calibration
sevt::Header & GetHeader()
Definition: SEvent.h:155
bool HasError(const IoSdStation &station)
std::string GetAlgorithm() const
Get algorithm of the trigger.
void ConvertEventToEr(const evt::Event &theEvent, TErEvent &theEr)
utl::CoordinateSystemPtr Get(const std::string &id)
Get a well-known Coordinate System.
int GetMuonChargeHistoOffset() const
x-axis offset of the muon charge histogram
Definition: PMTCalibData.h:71
sevt::StationTriggerData & GetTriggerData()
Get Trigger data for the station.
const sdet::Station & fStation
string OfSortedIds(vector< int > ids)
Definition: String.cc:65
double GetOnlineCharge() const
Online estimate of VEM_charge [adc*time_bin].
Definition: PMTCalibData.h:39
static const std::set< int > gCycloneStations({600, 610, 620, 627, 630, 648})
double GetZ(const CoordinateSystemPtr &coordinateSystem) const
Definition: BasicVector.h:212
bool HasTrace() const
const Station & GetStation(const int stationId) const
Get station by Station Id.
Definition: SDetector.cc:192
void PushBack(const T &value)
Insert a single value at the end.
Definition: Trace.h:119
double GetPeakAmplitude() const
Peak Amplitude.
Definition: PMTRecData.h:140
bool HasVEMTrace(const StationConstants::SignalComponent source=StationConstants::eTotal) const
Definition: PMTRecData.h:55
Iterator End()
Definition: Trace.h:76
boost::indirect_iterator< InternalConstStationIterator, const Station & > ConstStationIterator
Definition: SEvent.h:54
Point GetPoint(const CoordinateSystemPtr &theCS=CoordinateSystemPtr()) const
Get a cartesian point from an UTMPoint.
Definition: UTMPoint.cc:45
#define ERROR(message)
Macro for logging error messages.
Definition: ErrorLogger.h:165
constexpr double m
Definition: AugerUnits.h:121
double GetOnlinePeak() const
Online estimate of VEM_peak [adc].
Definition: PMTCalibData.h:36
void ConvertIoMdToEvent(evt::Event &oEvent, const md::Event &rEvent)
void MakeStation(const int stationId)
make a station with specifying Id, throw if invalid stationId
Definition: REvent.cc:94
unsigned int GetTickFall() const
bool HasSRecShower() const
sevt::SEvent & GetSEvent()
std::string GetSender() const
Get sender of the trigger.
bool HasSEvent() const
void ConvertEcToEvent(evt::Event &event, const TEcEvent &ec)
double GetSDPAngle() const
Get SDPAngle of the trigger.
double GetGainRatio() const
Definition: PMTCalibData.h:47
constexpr double cm2
Definition: AugerUnits.h:118

, generated on Tue Sep 26 2023.