RdAntennaStationToChannelConverter.cc
Go to the documentation of this file.
2 
3 #include <fwk/CentralConfig.h>
4 #include <fwk/LocalCoordinateSystem.h>
5 
6 #include <utl/TraceAlgorithm.h>
7 #include <utl/ErrorLogger.h>
8 #include <utl/Vector.h>
9 #include <utl/Point.h>
10 
11 #include <evt/Event.h>
12 #include <evt/ShowerSimData.h>
13 
14 #include <revt/REvent.h>
15 #include <revt/Station.h>
16 #include <revt/Channel.h>
17 
18 #include <det/Detector.h>
19 
20 #include <rdet/RDetector.h>
21 #include <rdet/Station.h>
22 #include <rdet/Channel.h>
23 
24 #include <atm/Atmosphere.h>
25 #include <atm/ProfileResult.h>
26 
27 using namespace utl;
28 using namespace fwk;
29 using namespace revt;
30 
31 
33 
36 {
37  Branch topBranch = CentralConfig::GetInstance()->GetTopBranch("RdAntennaStationToChannelConverter");
38  topBranch.GetChild("InfoLevel").GetData(fInfoLevel);
39  INFODebug("");
40 
41  topBranch.GetChild("InterpolationMode").GetData(fInterpolationMode);
42  std::string tmpstring = topBranch.GetChild("Direction").Get<std::string>();
43  fDirectionPerStation = tmpstring == "LineOfSightStationShowerMaximum";
44 
45  topBranch.GetChild("CalculateDistanceToXmaxOnTheFly").GetData(fCalculateDistanceToXmaxOnTheFly);
46 
47 
48  std::ostringstream info;
49  info << "\n\tInterplation mode : " << fInterpolationMode
50  << "\n\tDirection used : " << tmpstring << "\n ";
51  INFO(info);
52 
53  return eSuccess;
54 }
55 
56 
58 RdAntennaStationToChannelConverter::Run(evt::Event& event)
59 {
60  INFODebug("");
61 
62  // First some checks if simulation data is there:
63  if (!event.HasSimShower()) {
64  ERROR("Event has no simulated data.");
65  return eContinueLoop;
66  }
67  // is there also radio simulation data?:
68  evt::ShowerSimData& simShower = event.GetSimShower();
69  if (!simShower.HasRadioSimulation()) {
70  ERROR("SimShower has no radio simulation.");
71  return eContinueLoop;
72  }
73 
74  const CoordinateSystemPtr localCS = simShower.GetLocalCoordinateSystem();
75  const Vector simAxis = -simShower.GetDirection();
76  const double zenith = simAxis.GetTheta(localCS);
77  const double azimuth = simAxis.GetPhi(localCS);
78 
79  utl::Point posShowerMaximum;
80  if (fDirectionPerStation) {
81 
82  double distanceToXmax = -1;
83 
84  if (fCalculateDistanceToXmaxOnTheFly) {
85  const auto& gh = simShower.GetGHParameters();
86  const double xmaxMC = gh.GetXMax();
87 
88  // initiate atm + tables (which model is used is decieded in the config)
89  const atm::Atmosphere& theAtm = det::Detector::GetInstance().GetAtmosphere();
90  theAtm.InitSlantProfileModel(simShower.GetPosition(), simAxis, 5 * g / cm2);
91  const atm::ProfileResult& distanceFromDepth = theAtm.EvaluateDistanceVsSlantDepth();
92 
93  // distance to shower maximum, yep, the result is negative, convention thing...
94  distanceToXmax = abs(distanceFromDepth.Y(xmaxMC));
95  } else {
96  distanceToXmax = simShower.GetDistanceOfShowerMaximum();
97  if (distanceToXmax < 0) {
98  std::ostringstream err;
99  err << "Distance to shower maximum (as stored in the .reas file) is negative. "
100  "This might happens for mpi generated simulations. Using \"MCAxis\" in "
101  " the XML config does not need the distance to the shower maximum. Abort...";
102  ERROR(err);
103  throw utl::NonExistentComponentException(err.str());
104  }
105  }
106  posShowerMaximum = simShower.GetPosition() + simAxis * distanceToXmax;
107  }
108 
109  // has the radio simulation data been associated with the stations?:
110  if (!event.HasREvent()) {
111  ERROR("Event has simulated shower but no radio event. Use RdStationAssociator!");
112  return eContinueLoop;
113  }
114 
115  // We need it all: rEvent, rdet and the simulated data... fetch the rest:
116  REvent& rEvent = event.GetREvent();
117  const rdet::RDetector& rDetector = det::Detector::GetInstance().GetRDetector();
118 
119  // we need to loop over all stations and also over all channels of each station! Here is the loop
120  // over the stations which are included in the event.
121  for (REvent::StationIterator sIt = rEvent.StationsBegin(); sIt != rEvent.StationsEnd(); ++sIt) {
122 
123  double stationZenith = -1;
124  double stationAzimuth = -1;
125  if (fDirectionPerStation) {
126  const Point& posStation = rDetector.GetStation(*sIt).GetPosition();
127  const CoordinateSystemPtr stationCS = LocalCoordinateSystem::Create(posStation);
128  const Vector stationToShowerMaximum = posShowerMaximum - posStation;
129  stationZenith = stationToShowerMaximum.GetTheta(stationCS);
130  stationAzimuth = stationToShowerMaximum.GetPhi(stationCS);
131  } else {
132  stationZenith = zenith;
133  stationAzimuth = azimuth;
134  }
135 
136  if (fInfoLevel >= eInfoIntermediate) {
137  std::ostringstream info;
138  info << "Direction used for station " << sIt->GetId() << ": "
139  << "zenith = " << stationZenith / utl::deg << " deg"
140  << ", azimuth = " << stationZenith / utl::deg << " deg";
141  INFO(info);
142  }
143 
144  // for convenience, get a reference to the source station time series
145  const StationTimeSeries& efield = sIt->GetStationTimeSeries();
146 
147  // we will need to convert the station data to the shower coordinate system, for this we create a temporary FFTDataContainer
148  StationFFTDataContainer StationDataSCS;
149  // we have to configure the Nyquist zone of the temporary container correctly
150  StationDataSCS.SetNyquistZone(sIt->GetNyquistZone());
151 
152  // at each station there should be a three component electric field vector in cartesian coordinates
153  // this vector is now transfered into the shower base coordinate system with the antenna in the center.
154  // Here the simulated shower incoming direction is used which seems to be a pretty fair estimate:
155  StationTimeSeries& eFieldSCS = StationDataSCS.GetTimeSeries();
156  ConvertToShowerCS(efield, eFieldSCS, stationZenith, stationAzimuth);
157 
158  // Now we have the eField in SCS (Shower Coordinate System) in the time domain.
159  // However, we need the FFT of the three components.
160  StationFrequencySpectrum& eFieldSCSSpec = StationDataSCS.GetFrequencySpectrum();
161 
162  // now that we have all prepared on the station level, we have to loop the channels to apply the transfer
163  // function of the attached antenna. So loop the channels of the revent:
164  for (Station::ChannelIterator cIt = sIt->ChannelsBegin(); cIt != sIt->ChannelsEnd(); ++cIt) {
165  // Some preparation...
166  // ...from the rdetector we will need the corresponding detector channel:
167  const rdet::Channel& cDetChannel = rDetector.GetStation(*sIt).GetChannel(*cIt);
168 
169  // ...the calculated response will be saved as the channel frequency spectrum:
170  ChannelFrequencySpectrum& cChannelResponseSpectrum = cIt->GetChannelFrequencySpectrum();
171 
172  // clear the channel response spectrum in case there is already data there
173  cChannelResponseSpectrum.Clear();
174 
175  // set the meta data for the channel correctly, will be same as that of the original station data
176  cChannelResponseSpectrum.SetBinning(sIt->GetStationFrequencySpectrum().GetBinning());
177  cIt->SetNyquistZone(sIt->GetNyquistZone());
178 
179  const double designlowerfrequency = cDetChannel.GetDesignLowerFreq();
180  const double designupperfrequency = cDetChannel.GetDesignUpperFreq();
181 
182  // ...this is needed to avoid multiple interpolations at the same frequency (here for technical reason)
183  std::pair<std::complex<double>, std::complex<double>> cEffectiveAntennaHeight;
184 
185  // now we will loop over the efield spectrum and fold it with the transfer function:
186  for (StationFrequencySpectrum::SizeType i = 0; i < eFieldSCSSpec.GetSize(); ++i) {
187  // fetch the effective antenna height for the incoming direction and the frequency which belongs to the bin:
188 
189  const double frequency = StationDataSCS.GetFrequencyOfBin(i);
190  if (frequency >= designlowerfrequency && frequency <= designupperfrequency) {
191  cEffectiveAntennaHeight = cDetChannel.GetElectricFieldResponse(stationZenith, stationAzimuth,
192  StationDataSCS.GetFrequencyOfBin(i),
193  fInterpolationMode);
194 
195  // multiply the e_theta components of the effective heigths and the efield as well as the e_phi components and add them up
196  // this is then the antenna response at the corresponding frequency. So push it into the channel response spectrum:
197  cChannelResponseSpectrum.PushBack(
198  cEffectiveAntennaHeight.first * eFieldSCSSpec[i][0]
199  + cEffectiveAntennaHeight.second * eFieldSCSSpec[i][1]);
200  } else {
201  cChannelResponseSpectrum.PushBack(std::complex<double>(0., 0.));
202  }
203  }
204  }
205  }
206 
207  return eSuccess;
208 }
209 
210 
211 void
212 RdAntennaStationToChannelConverter::ConvertToShowerCS(const StationTimeSeries& eFieldXYZ,
213  StationTimeSeries& eFieldSCS,
214  double sZen, double sAzi)
215  const
216 {
217  eFieldSCS.Clear(); // delete data if there is already some
218  eFieldSCS.SetBinning(eFieldXYZ.GetBinning()); // have to set the binning correctly
219  for (StationTimeSeries::SizeType i = 0; i < eFieldXYZ.GetSize(); ++i) {
220  double tmpVector[3] = {
221  (cos(sZen) * cos(sAzi) * eFieldXYZ[i][0] + cos(sZen) * sin(sAzi) * eFieldXYZ[i][1]
222  - sin(sZen) * eFieldXYZ[i][2]), // e_theta
223  (-sin(sAzi) * eFieldXYZ[i][0] + cos(sAzi) * eFieldXYZ[i][1]), // e_phi
224  (sin(sZen) * cos(sAzi) * eFieldXYZ[i][0] + sin(sZen) * sin(sAzi) * eFieldXYZ[i][1]
225  + cos(sZen) * eFieldXYZ[i][2]) // e_r
226  };
227  eFieldSCS.PushBack(Vector3D(tmpVector));
228  }
229 }
230 
231 
233 RdAntennaStationToChannelConverter::Finish()
234 {
235  INFODebug("");
236  return eSuccess;
237 }
238 
239 }
Branch GetTopBranch() const
Definition: Branch.cc:63
utl::CoordinateSystemPtr GetLocalCoordinateSystem() const
Get the Auger coordinate system associated to the shower core position.
Top of the interface to Atmosphere information.
Point object.
Definition: Point.h:32
double GetPhi(const CoordinateSystemPtr &coordinateSystem) const
azimuth (phi) angle in spherical and cylindrical coordinates
Definition: BasicVector.h:254
void InitSlantProfileModel(const utl::Point &core, const utl::Vector &dir, const double deltaX) const
double GetDesignUpperFreq() const
Get design value of the freq-band.
const evt::VGaisserHillasParameter & GetGHParameters() const
Get the Gaisser-Hillas parameters of the shower.
Interface class to access to the Radio part of an event.
Definition: REvent.h:42
double GetTheta(const CoordinateSystemPtr &coordinateSystem) const
zenith (theta) angle in spherical coordinates
Definition: BasicVector.h:248
double GetDesignLowerFreq() const
Get design value of the freq-band.
bool HasSimShower() const
double GetBinning() const
size of one slot
Definition: Trace.h:138
const atm::ProfileResult & EvaluateDistanceVsSlantDepth() const
Table of distance as a function of slant depth.
#define INFO(message)
Macro for logging informational messages.
Definition: ErrorLogger.h:161
bool HasRadioSimulation() const
Check initialization of the RadioSimulation.
utl::SVector< 3, double > Vector3D
Definition: Trace-fwd.h:32
StationIterator StationsEnd()
Definition: REvent.h:130
StationIterator StationsBegin()
Definition: REvent.h:128
void Init()
Initialise the registry.
Base class for exceptions trying to access non-existing components.
Detector description interface for Channel-related data.
Branch GetChild(const std::string &childName) const
Get child of this Branch by child name.
Definition: Branch.cc:211
boost::filter_iterator< StationFilter, AllStationIterator > StationIterator
Iterator over all (non-exculded) stations.
Definition: REvent.h:125
bool HasREvent() const
double Y(const double x) const
Get the Y value (coordinate) for given X (ordinate)
Detector description interface for RDetector-related data.
Definition: RDetector.h:46
constexpr double deg
Definition: AugerUnits.h:140
Interface class to access Shower Simulated parameters.
Definition: ShowerSimData.h:49
T Get() const
Definition: Branch.h:271
boost::shared_ptr< const CoordinateTransformer > CoordinateSystemPtr
Shared pointer for coordinate systems.
Class representing a document branch.
Definition: Branch.h:107
double GetDistanceOfShowerMaximum() const
Get the geometrical distance of the shower maximum from the core.
const utl::Vector & GetDirection() const
Get the direction of the shower axis. This is the true direction of shower movement.
C< F > & GetFrequencySpectrum()
read out the frequency spectrum (write access)
std::vector< T >::size_type SizeType
Definition: Trace.h:58
Class describing the Atmospheric profile.
Definition: ProfileResult.h:25
double abs(const SVector< n, T > &v)
const utl::Point & GetPosition() const
Get the position of the shower core.
C< T > & GetTimeSeries()
read out the time series (write access)
void Clear()
Definition: Trace.h:158
constexpr double g
Definition: AugerUnits.h:200
SizeType GetSize() const
Definition: Trace.h:156
void GetData(bool &b) const
Overloads of the GetData member template function.
Definition: Branch.cc:644
#define INFODebug(y)
Definition: VModule.h:163
const Channel & GetChannel(const int id) const
Get specified Channel by id.
void SetBinning(const double binning)
Definition: Trace.h:139
Template class for a data container that offers and takes both time series and corresponding frequenc...
ResultFlag
Flag returned by module methods to the RunController.
Definition: VModule.h:60
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
Vector object.
Definition: Vector.h:30
void SetNyquistZone(const unsigned int zone)
set the Nyquist zone
utl::Point GetPosition() const
Tank position in Site Cartesian Coordinates.
std::pair< std::complex< double >, std::complex< double > > GetElectricFieldResponse(const double theta, const double phi, const double freq, std::string interpolationMode) const
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 Station & GetStation(const int stationId) const
Get station by Station Id.
Definition: RDetector.cc:141
constexpr double cm2
Definition: AugerUnits.h:118

, generated on Tue Sep 26 2023.