REASFile.cc
Go to the documentation of this file.
1 
9 #include <evt/Event.h>
10 #include <evt/ShowerSimData.h>
11 #include <evt/SimRadioPulse.h>
12 #include <evt/RadioSimulation.h>
13 
14 #include <fwk/CoordinateSystemRegistry.h>
15 
16 #include <io/CorsikaUtilities.h>
17 #include <io/CorsikaShowerFile.h>
18 #include <io/REASFile.h>
19 #include <io/REASIOException.h>
20 
21 #include <utl/AugerUnits.h>
22 #include <utl/ErrorLogger.h>
23 #include <utl/PhysicalConstants.h>
24 #include <utl/TimeStamp.h>
25 #include <utl/CoordinateSystem.h>
26 #include <utl/Point.h>
27 #include <utl/ReferenceEllipsoid.h>
28 #include <utl/UTMPoint.h>
29 #include <utl/UTCDateTime.h>
30 #include <utl/System.h>
31 #include <utl/FileName.h>
32 
33 #include <det/Detector.h>
34 
35 #include <boost/lexical_cast.hpp>
36 
37 #include <cmath>
38 #include <cstdlib>
39 #include <dirent.h>
40 #include <iostream>
41 #include <iomanip>
42 #include <sstream>
43 #include <string>
44 #include <unistd.h>
45 
46 using namespace utl;
47 using namespace evt;
48 using namespace revt;
49 using std::string;
50 using std::stringstream;
51 using std::ostringstream;
52 using std::ifstream;
53 using std::vector;
54 
55 
56 namespace io {
57 
58  REASFile::~REASFile()
59  {
60  delete fReasin;
61  delete fCorsikaShowerFile;
62  }
63 
64 
65  REASFile::REASFile() :
66  fProcessId(getpid())
67  { }
68 
69 
70  REASFile::REASFile(const std::string& fileName, const Mode mode, utl::Branch* const b) :
71  VEventFile(fileName, mode),
72  fProcessId(getpid())
73  {
74  Open(fileName, mode, b);
75  }
76 
77 
78  void
79  REASFile::Open(const std::string& fileName, const Mode mode, utl::Branch* const /*b*/)
80  {
81  // make a copy of the file name, we might have to update it
82  std::string ourFileName = fileName;
83 
84  //std::cout << "filename: " << fileName << endl;
85 
86  // determine the host name
87  char tmpHostNameString[256];
88  gethostname(tmpHostNameString, 256);
89  fHostName = tmpHostNameString;
90 
91  if (fileName.size() < 7 ||
92  (fileName.substr(fileName.size() - 5, 5) != ".reas" &&
93  fileName.substr(fileName.size() - 7, 7) != ".tar.gz" &&
94  fileName.substr(fileName.size() - 8, 8) != ".tar.bz2")) {
95  ostringstream msg;
96  msg << "Cannot open file " << fileName
97  << " - file name does not end on .reas, .tar.gz or .tar.bz2";
98  ERROR(msg);
99  throw io::REASIOException(msg.str());
100  }
101 
102  if (mode != eRead) {
103  ostringstream msg;
104  msg << "Cannot open file " << fileName << " - REAS files are read-only";
105  ERROR(msg);
106  throw io::REASIOException(msg.str());
107  }
108 
109  //check if we try to read in a .tar.gz file; if so, uncompress it and update the file name accordingly
110  if ((fileName.substr(fileName.size() - 7, 7) == ".tar.gz") ||
111  (fileName.substr(fileName.size() - 8, 8) == ".tar.bz2")) {
112  stringstream directory;
113  directory << "./TempExtractionDir/" << fHostName << "_" << fProcessId;
114 
115  stringstream command;
116  command << "rm -rf " << directory.str();
117  System(command);
118 
119  ostringstream msg;
120  msg << "Extracting " << fileName << " to directory " << directory.str() << " ...";
121  INFO(msg);
122  command.str("");
123  command << "mkdir 2>/dev/null ./TempExtractionDir";
124  System(command);
125  command.str("");
126  command << "mkdir 2>/dev/null " << directory.str();
127  System(command);
128  command.str("");
129 
130  // set flag according to file extension
131  string flag = (fileName.substr(fileName.size() - 7, 7) == ".tar.gz") ? "xfz": "xfj";
132 
133  command << "tar " << flag << " " << fileName << " -C " << directory.str();
134  System(command);
135 
136  if (ParseForREASFile(directory.str(), ourFileName) != 1) {
137  string new_directory = directory.str() + "/" + BareFileName(BareFileName(fileName)); // *tar.gz
138  msg.str("");
139  msg << "Not exactly one .reas file found in " << directory.str() << "\n"
140  "\tLooking for .reas file in " << new_directory;
141  INFO(msg);
142 
143  if (ParseForREASFile(new_directory, ourFileName) != 1) {
144  msg.str("");
145  msg << "Not exactly one .reas file found in " << fileName;
146  ERROR(msg);
147  throw io::REASIOException(msg.str());
148  }
149  }
150  }
151 
152  fReasin = new ifstream(ourFileName.c_str());
153  if (!*fReasin) {
154  ostringstream msg;
155  msg << "Cannot open file " << ourFileName << " - ERROR";
156  ERROR(msg);
157  throw io::REASIOException(msg.str());
158  }
159 
160  ostringstream info;
161  info << "(Co)REAS simulation " << ourFileName << '\n';
162 
163  const string basename = ourFileName.substr(0, ourFileName.size() - 5); // strip of extension ".reas"
164  const size_t pathlength = ourFileName.find_last_of("/"); // find last slash
165  string pathname;
166  string simname;
167 
168  if (pathlength >= ourFileName.size()) {
169  pathname = "./";
170  simname = basename.substr(0, 9); // just the SIMxxxxxx part
171  } else {
172  pathname = ourFileName.substr(0, pathlength) + "/";
173  simname = basename.substr(pathname.size(), 9); // just the SIMxxxxxx part
174  }
175 
176  # warning Should refactor REASFile reader to use boost filesystem library.
177 
178  DIR* const dir = opendir(pathname.c_str());
179  struct dirent* dp;
180  string entryname;
181  fBinFileList.clear();
182 
183  while ((dp = readdir(dir))) {
184  entryname = dp->d_name;
185  if (entryname.substr(0, simname.size()) == simname &&
186  entryname.substr(entryname.size() - 5, 5) == ".bins") {
187  fBinFileList.push_back(entryname); // this is a bin-file belonging to this simulation, schedule for processing
188  info << " containing " << entryname << '\n';
189  }
190  }
191  INFO(info);
192  closedir(dir); // close the directory
193 
194  // save the current directory
195  const unsigned int bufsize = 1024;
196  char dirbuf[bufsize];
197  if (!getcwd(dirbuf, bufsize)) {
198  ostringstream msg;
199  msg << "Buffer too small for reading out path.";
200  ERROR(msg);
201  throw io::REASIOException(msg.str());
202  }
203  fOrigDirectory = string(dirbuf);
204 
205  // save the REAS directory
206  fReasDirectory = pathname;
207  }
208 
209 
210  void
212  {
213  fReasin->close();
214  if (fCorsikaShowerFile) {
216  delete fCorsikaShowerFile;
217  fCorsikaShowerFile = nullptr;
218  }
219 
220  // delete temporary extraction directory
221  stringstream command;
222  command << "rm -rf ./TempExtractionDir/" << fHostName << "_" << fProcessId;
223  System(command);
224  }
225 
226 
227  Status
229  {
230  // test if there are any more events in this file to read
231  if (fCurrentPosition >= (unsigned int)GetNEvents())
232  return eEOF;
233 
234  // std::cout << " dir " << fReasDirectory << std::endl;
235  int chdirerror = chdir(fReasDirectory.c_str());
236  if (chdirerror) {
237  ostringstream msg;
238  msg << "Unable to change to directory " << fReasDirectory;
239  ERROR(msg);
240  throw io::REASIOException(msg.str());
241  }
242 
243  INFO("Reading in (Co)REASFile");
245 
246  if (event.HasSimShower()) {
247  ERROR("Event not cleared - has SimShower. Cannot read REASFile.");
248  return eFail;
249  }
250 
251  // First: read the REAS input file with all settings. At this moment the SimShower does not yet exist, it will be created only afterwards.
252 
253  int observertype = 1; // default case (only case for REAS3) is antenna list
254  double corecoordinateeastinaugercs = 0;
255  double corecoordinatenorthinaugercs = 0;
256  double corecoordinateverticalinaugercs = 0;
257  double corecoordinateverticalinreassim = 0;
258  double corecoordinatenorthinreassim = 0;
259  double corecoordinatewestinreassim = 0;
260  double refractiveIndexAtSeaLevel = 0;
261 
262  std::string OfflineCoordinateSystem("Reference"); // per default the reference coordinate system is used (normally PampaAmarilla)
263  double magneticfielddeclination = 0;
264  //double corsikashowerazimuth = 0;
265  long selectedcorsikashower = 1;
266  string corsikafilepath;
267  string corsikaparamfile;
268  bool corsikaazimuth = true; // default case (only case for REAS3) is use of corsika azimuth also in REAS
269  bool newgeometryconversion = false; // old version means no explicit core position in .reas file
270  int eventnumber = -1;
271  int runnumber = -1;
272  unsigned int gpssecs = 0;
273  unsigned int gpsnanosecs = 0;
274  TimeStamp event_timestamp;
275  string event_timestamp_str;
276  double distanceofshowermax = -1;
277 
278  char lineBuf[1024];
279 
280  while (fReasin->getline(lineBuf, sizeof(lineBuf)/sizeof(*lineBuf))) {
281  string currLine(lineBuf);
282  if (currLine.substr(0, 1) == "#") // comment
283  continue;
284  unsigned int pos = currLine.find("=", 1); // search for "=" starting with second character
285  if (pos < currLine.size()) {
286  string type = currLine.substr(0, pos); // everything before the "="
287 
288  string value;
289  unsigned int pose = currLine.find(";", pos); // search for ";" starting with the position of the "=" found before
290  if (pose < currLine.size()) {
291  // comment found, only use part before the ";"
292  value = currLine.substr(pos + 1, pose - pos - 1); // only part before the ";"
293  } else
294  value = currLine.substr(pos + 1); // everything after the "="
295 
296  unsigned int tend = type.size();
297  stringstream ss;
298 
299  ss << value; // feed the value into the stringstream for conversion
300 
301  // now check for the individual types
302 
303  // will be read in from corsika input file directly
304  // if (type.find("PrimaryParticleEnergy") < tend) {
305  // ss >> primaryenergy;
306  // primaryenergy *= eV;
307  // shower.SetEnergy(primaryenergy);
308  // continue;
309  // }
310 
311  /*if (type.find("DepthOfShowerMaximum") < tend) {
312  ss >> xmax;
313  xmax *= g/cm2;
314  // where to write this to - if at all
315  continue;
316  }*/
317 
318  if (type.find("ShowerEvolutionShift") < tend) {
319  double shift = 0;
320  if (!(ss >> shift) || fabs(shift) > 1e-3) {
321  ostringstream msg;
322  msg << "REAS simulations with active ShowerEvolutionShift cannot (yet) be processed";
323  ERROR(msg);
324  throw io::REASIOException(msg.str());
325  }
326  }
327 
329  // if (type.find("ShowerZenithAngle") < tend) {
330  // if (!(ss >> showerzenith))
331  // throw io::REASIOException("ShowerZenithAngle parse failed");
332  // showerzenith *= deg;
333  // shower.SetZenith(showerzenith);
334  // continue;
335  // }
336  //
338  // if (type.find("ShowerAzimuthAngle") < tend) {
339  // if (!(ss >> showerazimuth))
340  // throw io::REASIOException("ShowerAzimuthAngle parse failed");
341  // showerazimuth *= deg;
342  // showerazimuth -= 90*deg; // convert from REAS to Auger
343  // // do not call shower.SetAzimuth() yet because it might have to be corrected for magnetic field declination first
344  // continue;
345  // }
346 
347  /*if (type.find("ElectricFieldStrength") < tend) {
348  ss >> dd;
349  rhs.ElectricFieldStrength(dd);
350  continue;
351  }*/
352 
353  if (type.find("ObserverType") < tend) {
354  if (!(ss >> observertype))
355  throw io::REASIOException("ObserverType parse failed");
356  continue;
357  }
358 
359  if (type.find("CoreCoordinateVertical") < tend) {
360  if (!(ss >> corecoordinateverticalinreassim))
361  throw io::REASIOException("CoreCoordinateVertical parse failed");
362  corecoordinateverticalinreassim *= cm;
363  continue;
364  }
365 
366  if (type.find("CoreCoordinateNorth") < tend) {
367  if (!(ss >> corecoordinatenorthinreassim))
368  throw io::REASIOException("CoreCoordinateNorth parse failed");
369  corecoordinatenorthinreassim *= cm;
370  continue;
371  }
372 
373  if (type.find("CoreCoordinateWest") < tend) {
374  if (!(ss >> corecoordinatewestinreassim))
375  throw io::REASIOException("CoreCoordinateWest parse failed");
376  corecoordinatewestinreassim *= cm;
377  continue;
378  }
379 
380  // Get refractive index at sea level (_not_ ground resp. observation level)
381  if (type.find("GroundLevelRefractiveIndex") < tend) {
382  if (!(ss >> refractiveIndexAtSeaLevel))
383  throw io::REASIOException("GroundLevelRefractiveIndex parse failed");
384  continue;
385  }
386 
387 
388 
389  /*if (type.find("AtmosphereModel") < tend) {
390  ss >> ll;
391  rhs.AtmosphereModel(ll);
392  continue;
393  }*/
394 
395  if (type.find("CorsikaFilePath") < tend)
396  {
397  if (!(ss >> corsikafilepath))
398  throw io::REASIOException("CorsikaFilePath parse failed");
399  continue;
400  }
401 
402  if (type.find("CorsikaParameterFile") < tend) {
403  if (!(ss >> corsikaparamfile))
404  throw io::REASIOException("CorsikaParameterFile parse failed");
405  //corsikaparamfile=corsikaparamfile.substr(0,corsikaparamfile.size()-4); // remove extension ".inp"
406  continue;
407  }
408 
409  /*if (type.find("CorsikaSlantOptionToggle") < tend) {
410  ss >> bb;
411  rhs.CorsikaSlantOptionToggle(bb);
412  continue;
413  }*/
414 
415  if (type.find("SelectedCorsikaShower") < tend) {
416  if (!(ss >> selectedcorsikashower))
417  throw io::REASIOException("SelectedCorsikaShower parse failed");
418  continue;
419  }
420 
421  if (type.find("RunNumber") < tend) {
422  if (!(ss >> runnumber))
423  throw io::REASIOException("RunNumber parse failed");
424  continue;
425  }
426 
427  if (type.find("EventNumber") < tend) {
428  if (!(ss >> eventnumber))
429  throw io::REASIOException("EventNumber parse failed");
430  continue;
431  }
432 
433  if (type.find("GPSSecs") < tend) {
434  if (!(ss >> gpssecs))
435  throw io::REASIOException("GPSSecs parse failed");
436  continue;
437  }
438 
439  if (type.find("EventTimeStamp") < tend) {
440  if (!(ss >> event_timestamp_str))
441  throw io::REASIOException("EventTimeStamp parse failed");
442  event_timestamp = boost::lexical_cast<UTCDateTime>(event_timestamp_str).GetTimeStamp();
443  continue;
444  }
445 
446  if (type.find("GPSNanoSecs") < tend) {
447  if (!(ss >> gpsnanosecs))
448  throw io::REASIOException("GPSNanoSecs parse failed");
449  continue;
450  }
451 
452  // will be read in from corsika input file directly
453  // if (type.find("PrimaryParticleType") < tend) {
454  // if (!(ss >> primaryparticletype))
455  // throw io::REASIOException("PrimaryParticleType parse failed");
456  // continue;
457  // }
458 
459  if (type.find("CoreEastingPampaAmarilla") < tend ||
460  type.find("CoreEastingOffline") < tend) {
461  if (!(ss >> corecoordinateeastinaugercs))
462  throw io::REASIOException("CoreEastingOffline parse failed");
463  corecoordinateeastinaugercs *= meter;
464  newgeometryconversion = true;
465  continue;
466  }
467 
468  if (type.find("CoreNorthingPampaAmarilla") < tend ||
469  type.find("CoreNorthingOffline") < tend) {
470  if (!(ss >> corecoordinatenorthinaugercs))
471  throw io::REASIOException("CoreNorthingPampaAmarilla/CoreNorthingOffline parse failed");
472  corecoordinatenorthinaugercs *= meter;
473  newgeometryconversion = true;
474  continue;
475  }
476 
477  if (type.find("CoreVerticalPampaAmarilla") < tend ||
478  type.find("CoreVerticalOffline") < tend) {
479  if (!(ss >> corecoordinateverticalinaugercs))
480  throw io::REASIOException("CoreVerticalPampaAmarilla/CoreVerticalOffline parse failed");
481  corecoordinateverticalinaugercs *= meter;
482  newgeometryconversion = true;
483  continue;
484  }
485 
486  if (type.find("OfflineCoordinateSystem") < tend) {
487  if (!(ss >> OfflineCoordinateSystem))
488  throw io::REASIOException("OfflineCoordinateSystem parse failed");
489  newgeometryconversion = true;
490  //std::cout << "DEBUG: Offline CS is \"" << OfflineCoordinateSystem << "\"" << std::endl;
491  continue;
492  }
493 
494  if (type.find("RotationAngleForMagfieldDeclination") < tend) {
495  if (!(ss >> magneticfielddeclination))
496  throw io::REASIOException("RotationAngleForMagfieldDeclination parse failed");
497  magneticfielddeclination *= degree;
498  newgeometryconversion = true;
499  continue;
500  }
501 
502  if (type.find("DistanceOfShowerMaximum") < tend) {
503  if (!(ss >> distanceofshowermax))
504  throw io::REASIOException("DistanceOfShowerMaximum parse failed");
505  distanceofshowermax *= cm;
506  continue;
507  }
508 
509  }
510  }
511 
512  // check for version of geometry conversion
513  if (newgeometryconversion) {
514  // check for consistency of local core position in new conversion
515  if (corecoordinatenorthinreassim || corecoordinatewestinreassim) {
516  const string msg =
517  "(Co)REAS local coordinate system has to be anchored at (0,0,z) "
518  "but the x and/or y coordinate is not 0";
519  ERROR(msg);
520  throw io::REASIOException(msg);
521  }
522  } else {
523  // old conversion, no longer supported
524  const string msg =
525  "You are trying to read in a .reas file with implicit core position. "
526  "This is no longer supported.\n"
527  "Please check out revision 19862 or older of REASFile.cc to read these files.";
528  ERROR(msg);
529  throw io::REASIOException(msg);
530  }
531 
532  // Second call the CorsikaShowerFile::Read function. This will initialize the SimShower and read all available data: geometry, longitudinal data, ground particles, etc.
533  // now use CORSIKA shower file reader to import shower geometry, longitudinal and, if available, particle file
534  // beware: REASFile reader currently has very inefficient strategy for importing CORSIKA files with multiple simulations
535  // explanation: calls of CorsikaShowerFile::Open() re-reads in particle file on each call
536 
537  // check if an open CorsikaShowerFile exists, if so close it
538  if (fCorsikaShowerFile) {
540  delete fCorsikaShowerFile;
541  fCorsikaShowerFile = nullptr;
542  }
543 
544  fCorsikaShowerFile = new CorsikaShowerFile(corsikafilepath+corsikaparamfile, eRead);
545  fCorsikaShowerFile->SetMagneticFieldDeclination(-magneticfielddeclination); // this is WEST=-EAST convention
546 
547  if (eSuccess == fCorsikaShowerFile->GotoPosition(selectedcorsikashower - 1)) { // is the CORSIKA position really counted from zero here or from one (as in REAS)?
548  if (eSuccess == fCorsikaShowerFile->Read(event)) { // read in particle file
549  if (!corsikaazimuth) {
550  const string msg = "REAS simulations with particle file must not have azimuth override set";
551  ERROR(msg);
552  throw io::REASIOException(msg);
553  }
554  #warning RU: the following check is logical not 100% identical to before
555  if (selectedcorsikashower != 1) {
556  const string msg =
557  "(Co)REAS simulations without particle file must not have "
558  "multiple CORSIKA simulations in one CORSIKA run";
559  ERROR(msg);
560  throw io::REASIOException(msg);
561  }
562  }
563  } else {
564  const string msg =
565  "(Co)REAS simulations could not initialize sim shower. No CORSIKA files found";
566  ERROR(msg);
567  throw io::REASIOException(msg);
568  }
569  // finished reading CORSIKA basic data
570  // now the SimShower is initialized
571 
572  ShowerSimData& shower = event.GetSimShower();
573 
574  shower.SetMagneticFieldDeclination(-magneticfielddeclination); // yes, since we want "WEST=-EAST" angle
575 
576  shower.SetShowerNumber(selectedcorsikashower); // from REAS
577  shower.SetDistanceOfShowerMaximum(distanceofshowermax); // from REAS
578 
579  if (shower.HasRadioSimulation()) {
580  //fixme TH: need proper error handling if radio simulation already present
581  WARNING ("Event not cleared - has RadioSimulation");
582  // what is the consequence of this? could lead to multiple antenna pulses for same positions!?
583  } else
584  shower.MakeRadioSimulation();
585 
586  RadioSimulation& radiosim = shower.GetRadioSimulation();
587 
588 
589  // set event number and time stamp of the radio simulation
590  radiosim.SetEventNumber(eventnumber);
591  radiosim.SetRunNumber(runnumber);
592  if (gpssecs || gpsnanosecs) {
593  if (!event_timestamp_str.empty()) {
594  const string msg = "EventTimeStamp found while GPS time was set up";
595  ERROR(msg);
596  throw io::REASIOException(msg);
597  }
598  radiosim.SetEventTime(TimeStamp(gpssecs, gpsnanosecs));
599  } else
600  radiosim.SetEventTime(event_timestamp);
601 
602  // set the event (not revent) id
603  ostringstream tmpout;
604  tmpout << "(Co)REAS_r" << runnumber << "_e" << eventnumber;
605  event.GetHeader().SetId(tmpout.str());
606 
607  utl::CoordinateSystemPtr cs = det::Detector::GetInstance().GetReferenceCoordinateSystem();
608  if (OfflineCoordinateSystem != "Reference")
609  cs = fwk::CoordinateSystemRegistry::Get(OfflineCoordinateSystem);
610 
611  ostringstream info;
612  if (observertype == 1) {
613  const utl::Point core(corecoordinateeastinaugercs, corecoordinatenorthinaugercs, corecoordinateverticalinaugercs, cs);
614  radiosim.SetCorePosition(core);
615  info.str("");
616  info << "setting core position to " << core.GetX(cs) << ", " << core.GetY(cs) << ", "
617  << core.GetZ(cs) << " in coordinate system: \"" << OfflineCoordinateSystem << "\"";
618  INFO(info);
619  } else {
620  const string msg = "Cannot process REAS simulations with ObserverType = 0";
621  ERROR(msg);
622  throw io::REASIOException(msg);
623  }
624 
625  radiosim.SetRefractiveIndexAtSeaLevel(refractiveIndexAtSeaLevel);
626 
627  for (vector<string>::const_iterator it = fBinFileList.begin(); it != fBinFileList.end(); ++it) {
628  ifstream binin(it->c_str());
629 
630  if (!binin) {
631  ostringstream msg;
632  msg << "Cannot open file " << *it << " - ERROR";
633  ERROR(msg);
634  throw io::REASIOException(msg.str());
635  }
636 
637  while (binin.getline(lineBuf, sizeof(lineBuf)/sizeof(*lineBuf))) {
638  string currLine(lineBuf);
639  if (currLine.substr(0, 1) == "#") // commentary line
640  continue;
641  stringstream ss(currLine);
642  string antfile;
643  double xdist = 0; // x is given as north relative to core in REAS .bins files
644  double ydist = 0; // y is given as west relative to core in REAS .bins files
645  double zpos = 0; // z is given absolute in REAS .bins files (yes, it's inconsistent ...)
646  if (!(ss >> antfile >> xdist >> ydist >> zpos))
647  throw io::REASIOException("antenna parse failed");
648  // derotate antenna coordinates according to magnetic field declination
649  double rotX = cos(-magneticfielddeclination)*xdist - sin(-magneticfielddeclination)*ydist;
650  double rotY = sin(-magneticfielddeclination)*xdist + cos(-magneticfielddeclination)*ydist;
651  rotX *= cm; // REAS distances are given in cm
652  rotY *= cm; // REAS distances are given in cm
653  zpos *= cm; // REAS distances are given in cm
654  SimRadioPulse currpulse;
655  currpulse.SetRelativeCoordinates(-rotY, rotX, zpos - corecoordinateverticalinreassim); // set as east, north, vertical
656  const string antname = BareFileName(antfile);
657  currpulse.SetAntennaName(antname);
658  // std::cout << "setting antenna position to " << -rotY << ", " << rotX << ", " << zpos << " -"
659  // << corecoordinateverticalinreassim << " = "
660  // << zpos - corecoordinateverticalinreassim << " in coordinate system "
661  // << OfflineCoordinateSystem << std::endl;
662  TraceV3D& currtimeseries = currpulse.GetEfieldTimeSeries();
663 
664  ifstream antin(antfile.c_str());
665  if (!antin) {
666  ostringstream msg;
667  msg << "Cannot open file " << antfile.c_str()
668  << " - ERROR";
669  ERROR(msg);
670  throw io::REASIOException(msg.str());
671  }
672 
673  bool first = true;
674  double timestamp = 0;
675  double efield[3];
676  double rotefield[3];
677  double finalefield[3];
678  string s1;
679  string s2;
680  string s3;
681  string s4;
682  stringstream ds;
683 
684  while (antin >> s1 >> s2 >> s3 >> s4) { // REAS: north, west, vertical
685  // check for NaN values which could occur for older versions of REAS3.11 and CoREAS
686  if (s2.find("nan") < s2.size() || s3.find("nan") < s3.size() || s4.find("nan") < s4.size()) {
687  const string msg = "File " + antfile + " contains NaN values. Aborting!";
688  ERROR(msg);
689  throw io::REASIOException(msg);
690  }
691  // put strings into stringstream and extract doubles
692  ds.clear();
693  ds << s1 << ' ' << s2 << ' ' << s3 << ' ' << s4;
694  if (!(ds >> timestamp >> efield[0] >> efield[1] >> efield[2]))
695  throw io::REASIOException("efield parse failed");
696 
697  if (first) {
698  currpulse.SetStartTime(timestamp * second);
699  first = false;
700  }
701 
702  const double conv = 2.99792458e10*micro*volt/meter; // conversion from cgs units to microVolt/meter
703  efield[0] *= conv;
704  efield[1] *= conv;
705  efield[2] *= conv;
706 
707  // derotate the electric field for the magnetic field declination
708  rotefield[0] = cos(-magneticfielddeclination)*efield[0] - sin(-magneticfielddeclination)*efield[1];
709  rotefield[1] = sin(-magneticfielddeclination)*efield[0] + cos(-magneticfielddeclination)*efield[1];
710  rotefield[2] = efield[2];
711 
712  // construct a vector according to east, north, vertical convention of Offline
713  finalefield[0] = -rotefield[1];
714  finalefield[1] = rotefield[0];
715  finalefield[2] = rotefield[2];
716 
717  currtimeseries.PushBack(Vector3D(finalefield));
718  }
719 
720  antin.close();
721  currpulse.SetBinning((timestamp*second - currpulse.GetStartTime()) / double(currtimeseries.GetSize() - 1));
722  radiosim.AddSimRadioPulse(currpulse);
723  }
724 
725  binin.close();
726  }
727 
728  chdirerror = chdir(fOrigDirectory.c_str()); // change back to original directory
729  if (chdirerror) {
730  ostringstream msg;
731  msg << "Unable to change to directory " << fOrigDirectory;
732  ERROR(msg);
733  throw io::REASIOException(msg.str());
734  }
735 
736  return eSuccess;
737  }
738 
739 
740  void
741  REASFile::Write(const evt::Event& /*event*/)
742  {
743  const string msg = "Cannot write to REASFile - read-only file";
744  ERROR(msg);
745  throw io::REASIOException(msg);
746  }
747 
748 
749  Status
750  REASFile::FindEvent(const unsigned int eventId)
751  {
752  // REAS shower don't have event ids
753  return GotoPosition(eventId);
754  }
755 
756 
757  Status
758  REASFile::GotoPosition(const unsigned int position)
759  {
760  if (position > (unsigned int)GetNEvents())
761  return eFail;
762  else {
763  //fCurrentPosition = position;
764  return eSuccess;
765  }
766  }
767 
768 
769  int
770  REASFile::ParseForREASFile(const string& directory, string& ourFileName)
771  {
772  // search for the .reas file in the extracted directory
773  int counter = 0;
774  DIR* const dir = opendir(directory.c_str()); // open the directory
775  if (!dir) // check for successful directory opening
776  return 0;
777 
778  struct dirent* dp;
779  string entryname;
780  while ((dp = readdir(dir))) {
781  entryname = dp->d_name;
782  if (entryname.size() > 5 &&
783  entryname.substr(entryname.size() - 5, 5) == ".reas" &&
784  entryname.substr(0, 2) != "._") {
785  ourFileName = directory + "/" + entryname;
786  ++counter;
787  }
788  }
789  closedir(dir); // close the directory
790 
791  return counter;
792  }
793 
794 
795  int
797  {
798  return 1; // there is currently one event in a REAS file (hard-coded)
799  /*if (fShowerTree)
800  return int(fShowerTree->GetEntries());
801  else {
802  string msg = "Cannot request number of events from NULL tree";
803  ERROR(msg);
804  throw REASIOException(msg);
805  }*/
806  }
807 
808 }
Status Read(evt::Event &event) override
read current event advance cursor by 1
void SetCorePosition(const utl::Point &core)
Set the core position of the RadioSimulation using an utl::Point.
void SetMagneticFieldDeclination(const double magneticFieldDeclination)
Set the declination of the Earth&#39;s magnetic field used in CORSIKA/REAS simulation.
Status FindEvent(const unsigned int eventId) override
seek Event id set cursor there
Definition: REASFile.cc:750
const double degree
Point object.
Definition: Point.h:32
std::string fReasDirectory
Definition: REASFile.h:59
void SetStartTime(const double starttime)
Definition: SimRadioPulse.h:41
void System(const char *const command, const bool throwOnError, const bool notify)
Definition: System.cc:10
void MakeRadioSimulation()
Make the RadioSimulation.
Data structure for simulated Radio pulses.
Definition: SimRadioPulse.h:29
Status GotoPosition(const unsigned int position) override
goto by position in the file
Definition: REASFile.cc:758
bool HasSimShower() const
Data structure for a radio simulation (including several SimRadioPulses)
std::string BareFileName(const fs::path &thePath)
Definition: FileName.cc:46
void SetBinning(const double samplingtime)
Definition: SimRadioPulse.h:36
Mode
Available open modes.
Definition: IoCodes.h:16
const double meter
Definition: GalacticUnits.h:29
#define INFO(message)
Macro for logging informational messages.
Definition: ErrorLogger.h:161
void SetRefractiveIndexAtSeaLevel(const double n)
bool HasRadioSimulation() const
Check initialization of the RadioSimulation.
utl::SVector< 3, double > Vector3D
Definition: Trace-fwd.h:32
unsigned long fProcessId
Definition: REASFile.h:61
void SetRunNumber(const int runnum)
Set the run number of the RadioSimulation.
unsigned int fCurrentPosition
Definition: REASFile.h:55
Status GotoPosition(const unsigned int position) override
goto by position in the file
A TimeStamp holds GPS second and nanosecond for some event.
Definition: TimeStamp.h:110
void SetEventNumber(const int eventnum)
Set the event number of the RadioSimulation.
Interface class to access Shower Simulated parameters.
Definition: ShowerSimData.h:49
boost::shared_ptr< const CoordinateTransformer > CoordinateSystemPtr
Shared pointer for coordinate systems.
Class representing a document branch.
Definition: Branch.h:107
Status
Return code for seek operation.
Definition: IoCodes.h:24
Status Read(evt::Event &event) override
read current event advance cursor by 1
Definition: REASFile.cc:228
void SetMagneticFieldDeclination(const double d)
double GetX(const CoordinateSystemPtr &coordinateSystem) const
Definition: BasicVector.h:206
void SetEventTime(const utl::TimeStamp &t)
Set the event time of the RadioSimulation.
void Close() override
Definition: REASFile.cc:211
RadioSimulation & GetRadioSimulation()
Get the radio simulation data.
int ParseForREASFile(const std::string &directory, std::string &ourFileName)
Definition: REASFile.cc:770
const double second
Definition: GalacticUnits.h:32
Base for exceptions in the REAS reader.
Read data from the output of CORSIKA.
std::string fOrigDirectory
Definition: REASFile.h:58
SizeType GetSize() const
Definition: Trace.h:156
int GetNEvents() override
Definition: REASFile.cc:796
#define WARNING(message)
Macro for logging warning messages.
Definition: ErrorLogger.h:163
void AddSimRadioPulse(const SimRadioPulse &rp)
Add a radio pulse to the RadioSimulation.
std::ifstream * fReasin
Definition: REASFile.h:57
double GetY(const CoordinateSystemPtr &coordinateSystem) const
Definition: BasicVector.h:209
void Open(const std::string &fileName, const Mode mode=eRead, utl::Branch *const b=nullptr) override
Definition: REASFile.cc:79
Template class for a FADC data or calibrated data container. Use the typedefs (TraceD, TraceI, etc.) defined in Trace-fwd.h.
Definition: Trace-fwd.h:19
void SetRelativeCoordinates(double northing, double easting, double height)
Definition: SimRadioPulse.h:56
void Write(const evt::Event &event) override
Definition: REASFile.cc:741
void SetShowerNumber(const int sid)
Definition: ShowerSimData.h:75
std::vector< std::string > fBinFileList
Definition: REASFile.h:56
constexpr double cm
Definition: AugerUnits.h:117
void SetDistanceOfShowerMaximum(const double parDistance)
Set the geometrical distance of the shower maximum from the core.
constexpr double micro
Definition: AugerUnits.h:65
utl::CoordinateSystemPtr Get(const std::string &id)
Get a well-known Coordinate System.
CorsikaShowerFile * fCorsikaShowerFile
Definition: REASFile.h:63
double GetZ(const CoordinateSystemPtr &coordinateSystem) const
Definition: BasicVector.h:212
void PushBack(const T &value)
Insert a single value at the end.
Definition: Trace.h:119
#define ERROR(message)
Macro for logging error messages.
Definition: ErrorLogger.h:165
const utl::TraceV3D & GetEfieldTimeSeries() const
Get the Trace of the simulated electric field.
Definition: SimRadioPulse.h:44
std::string fHostName
Definition: REASFile.h:60
const double volt
Definition: GalacticUnits.h:38
double GetStartTime() const
Get the timestamp of the first sample.
Definition: SimRadioPulse.h:39
void SetAntennaName(const std::string antname)
Set the name of simulated antenna.
Definition: SimRadioPulse.h:64

, generated on Tue Sep 26 2023.