RadioFileAERA.cc
Go to the documentation of this file.
1 #include <io/RadioFileAERA.h>
2 
3 #include <utl/ErrorLogger.h>
4 #include <utl/AugerException.h>
5 
6 #include <config.h>
7 
8 #include <evt/Event.h>
9 #include <evt/Header.h>
10 #include <revt/REvent.h>
11 #include <revt/Station.h>
12 #include <revt/Channel.h>
13 #include <revt/Header.h>
14 #include <revt/StationTriggerData.h>
15 #include <revt/StationGPSData.h>
16 #include <revt/EventTrigger.h>
17 #include <revt/StationHeader.h>
18 #include <utl/Trace.h>
19 #include <utl/TimeStamp.h>
20 #include <utl/UTCDateTime.h>
21 #include <utl/LeapSeconds.h>
22 
23 #include <det/Detector.h>
24 #include <rdet/RDetector.h>
25 #include <rdet/Station.h>
26 
27 #include <TKey.h>
28 #include <TFile.h>
29 #include <TTree.h>
30 
31 #include <cstddef>
32 #include <cstdlib>
33 #include <iostream>
34 #include <sstream>
35 
36 #include <aevread.h>
37 #include <AeraEvent.h>
38 #include <amsg.h>
39 #include <llog.h>
40 
41 using namespace std;
42 using namespace utl;
43 using namespace io;
44 using namespace evt;
45 using namespace revt;
46 using namespace aera;
47 
48 
49 RadioFileAERA::RadioFileAERA(const std::string& filename,
50  const Mode mode,
51  utl::Branch* const b)
52 {
53  Open(filename, mode, b);
54 }
55 
56 
57 void
58 RadioFileAERA::Open(const std::string& filename, const Mode /*mode*/, utl::Branch* const /*b*/)
59 {
60  if (fHasFileOpen)
61  Close();
62  setAevreadLoglevel(0); //aevread library will be silent
63  setAevreadBufferedRead(true);
64  if (openAeraEventFile(filename.c_str())) {
65  fHasFileOpen = true;
66  fCurrentEvent = 0;
67  } else {
68  const string msg = "Something wrong occured when opening " + filename;
69  throw utl::IOFailureException(msg);
70  }
71 }
72 
73 
74 void
75 RadioFileAERA::Close()
76 {
77  if (!fHasFileOpen)
78  return;
79  closeAeraEventFile();
80  fHasFileOpen = false;
81  fCurrentEvent = -1;
82 }
83 
84 
85 void
86 RadioFileAERA::Write(const evt::Event& /*event*/)
87 {
88  WARNING("RadioFileAERA::Write not implemented!");
89 }
90 
91 
92 Status
93 RadioFileAERA::Read(evt::Event& event)
94 {
95  AeraEvent* const aev = fIsFirstevent ? getFirstAeraEvent() : getNextAeraEvent();
96  fIsFirstevent = false;
97 
98  if (!aev) {
99  fIsFirstevent = true;
100  return eEOF;
101  }
102 
103  if (event.HasREvent())
104  WARNING("Event not cleared - has REvent");
105  else
106  event.MakeREvent();
107 
108  REvent& revent = event.GetREvent();
109  const int event_id = getAeraEventEventId();
110  const int run_id = getAeraEventRunId();
111  const int file_id = getAeraFileHeaderFileId();
112  //const int runningid = getAeraEventRunningEventId();
113  const int eventversion = getAeraEventEventVersion();
114  const int numberofstations = getAeraEventLsCount();
115  revent.GetHeader().SetId(event_id); // integer ID for REvent
116  revent.GetHeader().SetRunNumber(run_id);
117  revent.GetHeader().SetFileId(file_id);
118  //revent.GetHeader().SetEventNumber(runningid);
119  revent.GetHeader().SetEventVersion(eventversion);
120  revent.GetHeader().SetNumberOfStations(numberofstations);
121  ostringstream id;
122  id << "revt_"<< run_id<< "_" << event_id;
123  event.GetHeader().SetId(id.str()); // string ID for Event
124  unsigned int ts_s = getAeraEventGPSSeconds();
125  unsigned int ts_ns = getAeraEventNanoSeconds();
126  // fixme MM : For these 2 workaroungs a maximal runnumber has to be defined
127  if (ts_s < 65536) {
128  // Workaround for events with wrong timestamp
129  WARNING("Event skipped! TimeStamp was not filled correctly.");
130  return eSkipEvent;
131  }
132 
133  if (ts_s > 1293494416) {
134  //Workaround for unix timestamp bug with German data
135  //Assume that everydate > 1/1/2020 is UNIX based
136  // This workaround is done again around line 310
137  LeapSeconds ls;
138  unsigned long ts_s_gps = 0;
139  ls.ConvertUnixToGPS(time_t(ts_s),ts_s_gps);
140  ts_s = ts_s_gps;
141  }
142  utl::TimeStamp ts;
143  try {
144  ts.SetGPSTime(ts_s, ts_ns);
145  } catch (OutOfBoundException&) {
146  WARNING("Event skipped! TimeStamp was not filled correctly.");
147  return eSkipEvent;
148  }
149  det::Detector::GetInstance().Update(ts);
150  event.GetHeader().SetTime(ts);
151  revent.GetHeader().SetTime(ts);
152 
153  if (!getAeraEventFirstLsData()) {
154  WARNING("No Local station data found");
155  return eFail;
156  }
157 
158  if (revent.HasTrigger()) {
159  const string msg = "Warning overwrites Event Trigger information";
160  WARNING(msg);
161  } else
162  revent.MakeTrigger();
163 
164  if (getAeraEventIsSelfTriggered())
165  revent.GetTrigger().SetSelfTrigger(true);
166  if (getAeraEventIsExternalT3Trigger())
167  revent.GetTrigger().SetExternalTrigger(true);
168  if (getAeraEventIsExternalElTrigger())
169  revent.GetTrigger().SetExternalTrigger(true);
170  if (getAeraEventIsRandomTrigger())
171  revent.GetTrigger().SetPeriodicTrigger(true);
172  if (getAeraEventIsCalibTrigger())
173  revent.GetTrigger().SetCalibrationTrigger(true);
174 
175  revent.GetTrigger().SetBitPattern(getAeraEvbTriggerFlag());
176  for (int i = 0; i < getAeraEventLsCount(); ++i) { //LS station loop
177 
178  const int station_id = LSPOS(getAeraEvbLsId());
179 
180  if (!getAeraEvbChannelPresentCount()) {
181  if (!getAeraEventNextLsData())
182  break;
183  else
184  continue;
185  }
186 
187  ostringstream stationname;
188 
189  if (station_id > 200 && station_id < 210)
190  stationname << 'M' << (station_id - 200);
191  else
192  stationname << "AERA_" << station_id;
193  try {
194  if (revent.HasStation(stationname.str())) {
195  const string msg = "Warning overwrites station information";
196  WARNING(msg);
197  } else
198  revent.MakeStation(stationname.str());
199  revt::Station& station = revent.GetStationByName(stationname.str());
200  const rdet::Station& detstation =
201  det::Detector::GetInstance().GetRDetector().GetStation(station); //Get the RDetector::Station from revt::Station
202  if (station.HasTriggerData()) {
203  const string msg = "Overwriting station trigger information";
204  WARNING(msg);
205  } else
206  station.MakeTriggerData();
207  // fixme SJ: Station also sets event level trigger because this flag is often not set correctly in the data
208  if (getAeraEvbIsSelfTriggered() ||
209  (getAeraEvbHardwareIsDutch() && !getAeraEvbIsRandomTrigger() && !getAeraEvbIsCalibTrigger())) {
210  station.GetTriggerData().SetTriggerSource(StationTriggerData::eSelf);
211  revent.GetTrigger().SetSelfTrigger(true);
212  } else if (getAeraEvbIsExternalElTrigger())
213  station.GetTriggerData().SetTriggerSource(StationTriggerData::eExternal);
214  else if (getAeraEvbIsExternalT3Trigger()) {
215  station.GetTriggerData().SetTriggerSource(StationTriggerData::eExternal);
216  revent.GetTrigger().SetExternalTrigger(true);
217  // WorkAround for Periodic trigger
218  if ((run_id >= 100210 && run_id < 100220) && (ts_ns < 5e8+20) && (ts_ns > 5e8-20)) {
220  revent.GetTrigger().SetPeriodicTrigger(true);
221  revent.GetTrigger().SetExternalTrigger(false);
222  }
223  if (run_id >= 100220 && (ts_ns < 7 || ts_ns > 1e9-7)) {
225  revent.GetTrigger().SetPeriodicTrigger(true);
226  revent.GetTrigger().SetExternalTrigger(false);
227  }
228  } else if (getAeraEvbIsCalibTrigger())
229  station.GetTriggerData().SetTriggerSource(StationTriggerData::eCalib);
230  else if (getAeraEvbIsRandomTrigger())
232  station.GetTriggerData().SetOffset(getAeraEvbTriggerPos());
233  if (station.HasGPSData()) {
234  const string msg = "Warning overwrites station GPS information";
235  WARNING(msg);
236  } else
237  station.MakeGPSData();
238  StationGPSData& gps = station.GetGPSData();
239 
240  if (station.HasStationHeader()) {
241  const string msg ="Warning overwrites station header";
242  WARNING(msg);
243  } else
244  station.MakeStationHeader();
245  if (getAeraEvbHardwareIsDutch())
246  station.GetStationHeader().SetHardwareType(StationHeader::eNL);
247  else if (getAeraEvbHardwareIsFrench())
248  station.GetStationHeader().SetHardwareType(StationHeader::eFR);
249  else if (getAeraEvbHardwareIsGerman())
250  station.GetStationHeader().SetHardwareType(StationHeader::eDE);
251  else {
252  ostringstream msg;
253  msg << " Unknown Hardware type :: getAeraEvbHardwareType() = " << getAeraEvbHardwareType() << "\n"
254  " Event ID is << " << id.str() << " File is " << file_id << "\n"
255  " Skip to next event";
256  ERROR(msg);
257  continue;
258  }
259  station.GetStationHeader().SetHardwareVersion(getAeraEvbHardwareVersion());
260 
261  const double samplingfreq = double(getAeraEvbSamplingFreq()) * utl::megahertz;
262  ts_s = getAeraEvbGPSseconds();
263  // Same Workaround as before for at the station level !!!
264  if (ts_s > 1293494416) {
265  // Workaround for unix timestamp bug with German data
266  // Assume that everydate > 1/1/2020 is UNIX based
267  unsigned long ts_s_gps = 0;
268  LeapSeconds ls;
269  ls.ConvertUnixToGPS(time_t(ts_s), ts_s_gps);
270  ts_s = ts_s_gps;
271  }
272  utl::TimeStamp stationts;
273  try {
274  stationts.SetGPSTime(ts_s, getAeraEvbGPSnanoseconds());
275  gps.SetSecond(ts_s); // ? Why was ts_gps_s
276  gps.SetCorrectedNanosecond(getAeraEvbGPSnanoseconds()); // corrected from what ?
277  } catch (utl::OutOfBoundException&) {
278  WARNING("Event skipped! TimeStamp was not filled correctly.");
279  return eSkipEvent;
280  }
281  double pretrigtime = 0;
282  if (getAeraEvbHardwareIsDutch()) {
283  const char* const raw = (const char*)getAeraEvbInfoADCbuffer();
284  const UINT16 s = (raw[5] << 8) + (raw[6] & 0xff);
285  const UINT16 t = (raw[7] << 8) + (raw[8] & 0xff);
286  pretrigtime = (s + t) / samplingfreq;
287  } else
288  pretrigtime = double(getAeraEvbTriggerPos()) / samplingfreq;
289  const utl::TimeInterval pretrig = pretrigtime;
290  try {
291  station.SetRawTraceStartTime(stationts - pretrig);
292  } catch (utl::OutOfBoundException&) {
293  WARNING("Event skipped! TimeStamp was not filled correctly.");
294  return eSkipEvent;
295  }
296 
297  const int numberofsamples = getAeraEvbTracelength();
298 
299  UINT16 thresh = 0;
300  ostringstream info;
301  for (int ch_id = 1; ch_id <= detstation.GetNChannels(); ++ch_id) {
302  info.str("");
303  revt::Channel& chan = station.GetChannel(ch_id);
304  //If Channel is not present in data, it will be set as inactive;
305  if (!getAeraEvbChannelXPresent(ch_id)) {
306  if (!((ch_id == 3 || ch_id == 4) && getAeraEvbHardwareIsGerman())) {
307  // German data have no Channel 3/4 so this warning is not necessary
308  info.str("");
309  info << " Channel " << ch_id << " Not present in data\n Channel will be marked as non active";
310  INFO(info);
311  }
312  chan.SetNotActive();
313  continue;
314  }
315  //as dutch channels 3 & 4 are not filled with low gain data, they will be set as inactive
316  if ((ch_id == 3 || ch_id == 4) && getAeraEvbHardwareIsDutch()) {
317  chan.SetNotActive();
318  continue;
319  }
320  chan.SetActive();
322  if (getAeraEvbHardwareIsGerman()) {
323  thistrace.SetBinning(1. / samplingfreq);
324  int offset = 2048;
325  if (getAevreadVersion() > 10201)
326  offset = 0;
327 
328  INT16* const tmpseries = (INT16*)getAeraEvbChannelXData(ch_id); // Changed for DE data
329  if (!tmpseries) {
330  info.str("");
331  info << " Pointer to time serie is NULL for channel " << ch_id
332  << " Channel will be marked as not active ";
333  WARNING(info);
334  chan.SetNotActive();
335  continue;
336  }
337  for (int ii = 0; ii < numberofsamples; ++ii) {
338  thistrace.PushBack(tmpseries[ii] + offset); //Change for DE electroncic
339  }
340  free(tmpseries);
341  } else if (getAeraEvbHardwareIsDutch()) {
342  thistrace.SetBinning(1. / samplingfreq);
343  UINT16* const tmpseries = getAeraEvbChannelXData(ch_id); // Changed for DE data
344  if (!tmpseries) {
345  info.str("");
346  info << " Pointer to time serie is NULL for channel " << ch_id
347  << " Channel will be marked as not active ";
348  WARNING(info);
349  chan.SetNotActive();
350  continue;
351  }
352  for (int ii = 0; ii < numberofsamples; ++ii) {
353  thistrace.PushBack(tmpseries[ii]); //Change for DE electroncic
354  }
355  free(tmpseries);
356  } else {
357  info.str("");
358  info << "Electronic readout is not implemented, Electronic type is " << getAeraEvbHardwareType()
359  << " Channel is Set has inactive";
360  chan.SetNotActive();
361  WARNING(info);
362  }
363  chan.SetNyquistZone(1);
364  // fixme SJ: if statement is workaround to avoid needless output of aevread for DE data, should be fixed in next version
365  if (getAeraEvbHardwareIsDutch()) {
366  thresh = getAeraEvbSignalThresholdX(ch_id);
367  // 0xFFFF is the Error code returned by the library in case no threshold is found
368  if (thresh != 0xFFFF)
369  chan.SetSignalThreshold(thresh);
370  thresh = getAeraEvbNoiseThresholdX(ch_id);
371  if (thresh != 0xFFFF)
372  chan.SetNoiseThreshold(thresh);
373  }
374  }
376  ERROR(e.what());
377  if (!getAeraEventNextLsData())
378  break;
379  else
380  continue;
381  }
382 
383  if (i+1 < getAeraEventLsCount())
384  getAeraEventNextLsData();
385  }
386 
387  ++fCurrentEvent;
388  //freeEvbody();
389  return eSuccess;
390 }
391 
392 
393 Status
394 RadioFileAERA::FileStatus()
395 {
396  return fHasFileOpen ? eSuccess : eFail;
397 }
398 
399 
400 Status
401 RadioFileAERA::FindEvent(const unsigned int /*id*/)
402 {
403  WARNING("RadioFileAERA::FindEvent not implemented!");
404  return eEOF;
405 }
406 
407 
408 Status
409 RadioFileAERA::GotoPosition(const unsigned int /*position*/)
410 {
411  WARNING("RadioFileAERA::GotoPosition not implemented!");
412  return eEOF;
413 }
414 
415 
416 int
417 RadioFileAERA::GetNEvents()
418 {
419  WARNING("RadioFileAERA::GetNEvents not implemented!");
420  return 0;
421 }
bool HasTrigger() const
check whether the central trigger object exists
Definition: REvent.h:236
int raw
Definition: dump1090.h:270
void SetHardwareType(const HardwareType t)
Set type of hardware used (should be provided by the DAQ)
Definition: StationHeader.h:28
StationTriggerData & GetTriggerData()
Get Trigger data for the station.
Detector description interface for Station-related data.
bool HasTriggerData() const
Check whether trigger data object exists.
void SetPeriodicTrigger(const bool trig)
Set if Event comes from PERIODIC trigger.
void SetOffset(const int offset)
Set postTrigger time in bins.
Station & GetStationByName(const std::string &name)
retrieve station by name, throw utl::NonExistentComponentException if n.a.
Definition: REvent.h:194
Interface class to access to the Radio part of an event.
Definition: REvent.h:42
EventTrigger & GetTrigger()
Get the object with central trigger data, throw if n.a.
Definition: REvent.h:229
void SetCorrectedNanosecond(const unsigned int &ns)
Set corrected trigger nanosecond.
Mode
Available open modes.
Definition: IoCodes.h:16
void SetBitPattern(const uint16_t BitPattern)
Set the Trigger Bit Pattern.
#define INFO(message)
Macro for logging informational messages.
Definition: ErrorLogger.h:161
Base class for exceptions trying to access non-existing components.
bool HasREvent() const
void SetEventVersion(const int ver)
Definition: REvent/Header.h:33
void SetNoiseThreshold(const unsigned int thresh)
From DAQ.
A TimeStamp holds GPS second and nanosecond for some event.
Definition: TimeStamp.h:110
void SetCalibrationTrigger(const bool trig)
Set if Event comes from calibration trigger.
void SetTime(const utl::TimeStamp &time)
Version of the AERAEvent used by the DAQ software.
Definition: REvent/Header.h:27
Exception for reporting variable out of valid range.
void MakeGPSData()
Make GPS data object.
Base class to report exceptions in IO.
void MakeTriggerData()
Make trigger data object.
void SetExternalTrigger(const bool trig)
Set if Event was externally triggered.
void SetHardwareVersion(const int v)
Set version of hardware is used (should be provided by the DAQ)
Definition: StationHeader.h:31
void SetSelfTrigger(const bool trig)
Set if Event was selftriggered.
bool HasStationHeader() const
Check whether StationHeader exists.
Class representing a document branch.
Definition: Branch.h:107
Status
Return code for seek operation.
Definition: IoCodes.h:24
class to hold data at the radio Station level.
constexpr double s
Definition: AugerUnits.h:163
void SetRawTraceStartTime(const utl::TimeStamp &time)
Set absolute start time of the station-level trace as originally provided in raw data, for reconstructions use eTraceStartTime in StationRecData!
void SetGPSTime(const unsigned long sec, const double nsec=0)
Set GPS second and (optionally) nanosecond.
Definition: TimeStamp.h:120
void MakeStationHeader()
Make Station Header object.
void MakeTrigger()
Create the central trigger object.
Definition: REvent.cc:174
Header & GetHeader()
access to REvent Header
Definition: REvent.h:239
int GetNChannels() const
Number of channels in station.
constexpr double megahertz
Definition: AugerUnits.h:155
StationGPSData & GetGPSData()
Get GPS data for the station.
#define WARNING(message)
Macro for logging warning messages.
Definition: ErrorLogger.h:163
int aera
Definition: dump1090.h:272
void SetFileId(const int id)
Definition: REvent/Header.h:30
void SetBinning(const double binning)
Definition: Trace.h:139
Channel & GetChannel(const int pmtId)
Retrieve a Channel by Id.
void SetSecond(const unsigned int &sec)
Set end of traces raw time.
A TimeInterval is used to represent time elapsed between two events.
Definition: TimeInterval.h:43
void SetSignalThreshold(const unsigned int thresh)
void SetNumberOfStations(const int nstat)
Definition: REvent/Header.h:31
void SetId(const int id)
Definition: REvent/Header.h:28
ChannelADCTimeSeries & GetChannelADCTimeSeries()
Get Channel ADC trace (write access, only use this if you intend to change the data) ...
Class that holds the data associated to an individual radio channel.
void SetRunNumber(const int run)
Definition: REvent/Header.h:32
bool HasStation(const int stationId) const
Check whether station exists.
Definition: REvent.cc:132
StationHeader & GetStationHeader()
Get the Station Header.
char * filename
Definition: dump1090.h:266
void SetNyquistZone(const unsigned int zone)
Set the Nyquist zone.
void PushBack(const T &value)
Insert a single value at the end.
Definition: Trace.h:119
void SetNotActive()
#define ERROR(message)
Macro for logging error messages.
Definition: ErrorLogger.h:165
bool HasGPSData() const
Check whether GPS data object exists.
void MakeStation(const int stationId)
make a station with specifying Id, throw if invalid stationId
Definition: REvent.cc:94
void SetActive()
Active means that it is used in reconstruction. By default this is true after read-in, but can be deactivated later.
void SetTriggerSource(const TriggerSource TrigSource)
Set the Trigger Source of the station, i.e. if it triggered itself or was triggered by the central st...
void ConvertUnixToGPS(const time_t unixSecond, unsigned long &gpsSecond) const
Definition: LeapSeconds.cc:25
const char * what() const
std::exception will print this on crash

, generated on Tue Sep 26 2023.