1 #include <rdet/AntennaType.h>
2 #include <det/VManager.h>
3 #include <det/Detector.h>
5 #include <utl/AugerException.h>
17 std::map<std::string, AntennaPattern> AntennaType::fgAntennaPattern;
19 AntennaType::AntennaType(
const string& antennaType)
21 fAntennaType = antennaType;
26 AntennaType::BufferAntennaPattern()
28 if (fgAntennaPattern.find(fAntennaType) == fgAntennaPattern.end()) {
30 std::map<ResponseKey, VectorEffectiveLength> antennaResponse;
32 ostringstream message;
33 message <<
"Buffering Antenna Pattern for " << fAntennaType;
37 GetAntennaData(frequenciesS,
"frequency");
40 GetAntennaData(frequencies,
"frequency");
46 message <<
"buffering frequencies:";
47 for (std::vector<double>::iterator it = antennaPattern.
frequencies.begin();
61 GetAntennaData(vTheta,
"theta");
64 unsigned int nTheta = 0;
65 bool first_iteration =
true;
66 double theta_0 = vTheta.
Get().at(0);
67 for (
unsigned int i = 0; i < vTheta.
Get().size(); ++i) {
68 const double theta = vTheta.
Get().at(i);
69 if (first_iteration && theta == theta_0 && i) {
71 first_iteration =
false;
73 if (first_iteration) {
76 if (antennaPattern.
thetaAngles.at(i % nTheta) != theta) {
77 ERROR(
"error in importing zenith angles");
82 antennaPattern.
nTheta = nTheta;
85 message <<
"buffering theta angles:";
86 for (std::vector<double>::iterator it = antennaPattern.
thetaAngles.begin();
98 const int nTotal = vTheta.
Get().size();
99 antennaPattern.
nPhi = nTotal / nTheta;
100 if (antennaPattern.
nPhi * antennaPattern.
nTheta != nTotal) {
101 ERROR(
"error in determining number of azimuth samples");
105 message <<
"nPhi has been determined to " << antennaPattern.
nPhi
106 <<
"\t nTheta has been determined to " << antennaPattern.
nTheta;
111 GetAntennaData(vPhi,
"phi");
114 for (
int iPhi = 0; iPhi < antennaPattern.
nPhi; ++iPhi)
118 message <<
"buffering phi angles:";
119 for (std::vector<double>::iterator it = antennaPattern.
phiAngles.begin();
120 it != antennaPattern.
phiAngles.end(); ++it) {
123 message <<
" degree";
126 for (
unsigned int iFrequency = 0; iFrequency < frequenciesS.
Get().size(); ++iFrequency) {
131 GetAntennaData(sphereEAHTheta_amp,
"EAHTheta_amp", frequenciesS.
Get().at(iFrequency));
132 GetAntennaData(sphereEAHTheta_phase,
"EAHTheta_phase", frequenciesS.
Get().at(iFrequency));
133 GetAntennaData(sphereEAHPhi_amp,
"EAHPhi_amp", frequenciesS.
Get().at(iFrequency));
134 GetAntennaData(sphereEAHPhi_phase,
"EAHPhi_phase", frequenciesS.
Get().at(iFrequency));
136 for (
int iPhi = 0; iPhi < antennaPattern.
nPhi; ++iPhi) {
137 const double current_phi = antennaPattern.
phiAngles.at(iPhi);
141 for (
int iTheta = 0; iTheta < antennaPattern.
nTheta; ++iTheta) {
149 if (current_phi != vPhi.
Get().at(iPhi * antennaPattern.
nTheta + iTheta)) {
153 const float Phi_amp = sphereEAHPhi_amp.
Get().at(iPhi * antennaPattern.
nTheta + iTheta);
154 const float Phi_phase = sphereEAHPhi_phase.
Get().at(iPhi * antennaPattern.
nTheta + iTheta);
155 const float Theta_amp = sphereEAHTheta_amp.
Get().at(iPhi * antennaPattern.
nTheta + iTheta);
156 const float Theta_phase = sphereEAHTheta_phase.
Get().at(iPhi * antennaPattern.
nTheta + iTheta);
159 vel.
Phi = std::polar(Phi_amp, Phi_phase);
160 vel.
Theta = std::polar(Theta_amp, Theta_phase);
164 antennaResponse[key] = vel;
171 for (
unsigned int iFrequency = 0; iFrequency < frequenciesS.
Get().size(); ++iFrequency) {
172 const double integratedVEL =
173 CalculateIntegratedEffectiveAntennaHeight(antennaResponse, iFrequency, antennaPattern.
nTheta, antennaPattern.
nPhi);
181 fgAntennaPattern[fAntennaType] = antennaPattern;
183 message <<
"finished buffering antenna " << fAntennaType;
189 std::pair<std::complex<double>, std::complex<double>>
190 AntennaType::GetElectricFieldResponse(
const double theta,
const double phi,
const double freq,
const std::string& interpolationMode)
193 double matchedPhi = phi;
194 while (matchedPhi < 0)
195 matchedPhi += 360. *
degree;
196 while (matchedPhi >= 360. *
degree)
197 matchedPhi -= 360. *
degree;
199 if (interpolationMode ==
"Lookup") {
200 return GetElectricFieldResponse_lookup(theta, matchedPhi, freq);
201 }
else if (interpolationMode ==
"LinearInterpolation") {
202 return GetElectricFieldResponse_LinearInterpolation(theta, matchedPhi, freq);
204 ostringstream message;
205 message <<
"interpolation mode " << interpolationMode <<
" unknown";
211 std::pair<std::complex<double>, std::complex<double>>
214 return std::pair<std::complex<double>, std::complex<double>>(vel.
Theta, vel.
Phi);
219 AntennaType::InterpolateLinear(
const double x,
const double x_low,
const double x_up,
220 const double y_low,
const double y_up)
225 const double result = y_low + (y_up - y_low) * (x - x_low) / (x_up - x_low);
226 if (std::isnan(result)) {
228 msg <<
"linear interpolation results in NaN:\n"
229 "\tx = " << x <<
"\n"
230 "\tx_low = " << x_low <<
"\n"
231 "\tx_up = " << x_up <<
"\n"
232 "\ty_low = " << y_low <<
"\n"
233 "\ty_up = " << y_up <<
"\n"
234 "\tresult = " << result <<
'\n';
242 AntennaType::InterpolateLinear(
const float x,
const float x_low,
const float x_up,
243 const std::complex<float>& y_low,
const std::complex<float>& y_up)
248 const std::complex<float>
result = y_low + (y_up - y_low) * ((x - x_low) / (x_up - x_low));
252 msg <<
"linear interpolation results in NaN:\n"
253 "\tx = " << x <<
"\n"
254 "\tx_low = " << x_low <<
"\n"
255 "\tx_up = " << x_up <<
"\n"
256 "\ty_low = " << y_low <<
"\n"
257 "\ty_up = " << y_up <<
"\n"
258 "\tresult = " << result <<
'\n';
267 AntennaType::InterpolateLinear(
const double x,
const double x_low,
const double x_up,
270 const auto theta = InterpolateLinear(x, x_low, x_up, vel_low.
Theta, vel_up.
Theta);
271 const auto phi = InterpolateLinear(x, x_low, x_up, vel_low.
Phi, vel_up.
Phi);
276 std::pair<std::complex<double>, std::complex<double>>
277 AntennaType::GetElectricFieldResponse_lookup(
const double theta,
const double phi,
const double freq)
279 BufferAntennaPattern();
280 const double theta_lower_bound = fgAntennaPattern[fAntennaType].theta_lower_bound;
281 const double theta_upper_bound = fgAntennaPattern[fAntennaType].theta_upper_bound;
282 const double phi_lower_bound = fgAntennaPattern[fAntennaType].phi_lower_bound;
283 const double phi_upper_bound = fgAntennaPattern[fAntennaType].phi_upper_bound;
284 const double frequency_lower_bound = fgAntennaPattern[fAntennaType].frequency_lower_bound;
285 const double frequency_upper_bound = fgAntennaPattern[fAntennaType].frequency_upper_bound;
286 const int nTheta = fgAntennaPattern[fAntennaType].nTheta;
287 const int nPhi = fgAntennaPattern[fAntennaType].nPhi;
288 const int nFrequency = fgAntennaPattern[fAntennaType].nFrequency;
291 int(round((theta - theta_lower_bound) / (theta_upper_bound - theta_lower_bound) * (nTheta - 1)));
292 const int iPhi = int(round((phi - phi_lower_bound) / (phi_upper_bound - phi_lower_bound) * (nPhi - 1)));
293 const int iFrequency =
294 int(round( (freq - frequency_lower_bound) / (frequency_upper_bound - frequency_lower_bound) * (nFrequency - 1)));
300 return GetComplexRepresentationOfVectorEffectiveLength(vel);
304 std::pair<std::complex<double>, std::complex<double>>
305 AntennaType::GetElectricFieldResponse_LinearInterpolation(
const double theta,
const double phi,
const double freq)
307 BufferAntennaPattern();
309 const double theta_lower_bound = fgAntennaPattern[fAntennaType].theta_lower_bound;
310 const double theta_upper_bound = fgAntennaPattern[fAntennaType].theta_upper_bound;
311 const double phi_lower_bound = fgAntennaPattern[fAntennaType].phi_lower_bound;
312 const double phi_upper_bound = fgAntennaPattern[fAntennaType].phi_upper_bound;
313 const double frequency_lower_bound = fgAntennaPattern[fAntennaType].frequency_lower_bound;
314 const double frequency_upper_bound = fgAntennaPattern[fAntennaType].frequency_upper_bound;
316 if ((freq < frequency_lower_bound || freq > frequency_upper_bound) ||
317 (phi < phi_lower_bound || phi > phi_upper_bound) ||
318 (theta < theta_lower_bound || theta > theta_upper_bound)) {
322 <<
"deg) angle requested that is not contained in the antenna pattern, returning 0";
324 return std::pair<std::complex<double>, std::complex<double>>(std::complex<double>(0, 0),
325 std::complex<double>(0, 0));
328 const int nTheta = fgAntennaPattern[fAntennaType].nTheta;
329 const int nPhi = fgAntennaPattern[fAntennaType].nPhi;
330 const int nFrequency = fgAntennaPattern[fAntennaType].nFrequency;
331 const std::vector<double>& frequencies = fgAntennaPattern[fAntennaType].frequencies;
332 const std::vector<double>& thetaAngles = fgAntennaPattern[fAntennaType].thetaAngles;
333 const std::vector<double>& phiAngles = fgAntennaPattern[fAntennaType].phiAngles;
335 const int iTheta_lower =
336 int(floor((theta - theta_lower_bound) / (theta_upper_bound - theta_lower_bound) * (nTheta - 1)));
337 const double theta_lower = thetaAngles.at(iTheta_lower);
338 const int iTheta_upper =
339 int(ceil((theta - theta_lower_bound) / (theta_upper_bound - theta_lower_bound) * (nTheta - 1)));
340 const double theta_upper = thetaAngles.at(iTheta_upper);
341 const int iPhi_lower =
342 int(floor((phi - phi_lower_bound) / (phi_upper_bound - phi_lower_bound) * (nPhi - 1)));
343 const double phi_lower = phiAngles.at(iPhi_lower);
344 const int iPhi_upper =
345 int(ceil((phi - phi_lower_bound) / (phi_upper_bound - phi_lower_bound) * (nPhi - 1)));
346 const double phi_upper = phiAngles.at(iPhi_upper);
347 const int iFrequency_lower =
348 int(floor((freq - frequency_lower_bound) / (frequency_upper_bound - frequency_lower_bound) * (nFrequency - 1)));
349 const double frequency_lower = frequencies.at(iFrequency_lower);
350 const int iFrequency_upper =
351 int( ceil((freq - frequency_lower_bound) / (frequency_upper_bound - frequency_lower_bound) * (nFrequency - 1)));
352 const double frequency_upper = frequencies.at(iFrequency_upper);
353 const std::map<ResponseKey, VectorEffectiveLength>& antennaResponse =
354 fgAntennaPattern[fAntennaType].AntennaResponse;
360 phi, phi_lower, phi_upper,
361 antennaResponse.at(
ResponseKey(iFrequency_lower, iTheta_lower, iPhi_lower)),
362 antennaResponse.at(
ResponseKey(iFrequency_lower, iTheta_lower, iPhi_upper))
368 phi, phi_lower, phi_upper,
369 antennaResponse.at(
ResponseKey(iFrequency_lower, iTheta_upper, iPhi_lower)),
370 antennaResponse.at(
ResponseKey(iFrequency_lower, iTheta_upper, iPhi_upper))
374 InterpolateLinear(theta, theta_lower, theta_upper, vel_freq_low_theta_low, vel_freq_low_theta_up);
380 phi, phi_lower, phi_upper,
381 antennaResponse.at(
ResponseKey(iFrequency_upper, iTheta_lower, iPhi_lower)),
382 antennaResponse.at(
ResponseKey(iFrequency_upper, iTheta_lower, iPhi_upper))
388 phi, phi_lower, phi_upper,
389 antennaResponse.at(
ResponseKey(iFrequency_upper, iTheta_upper, iPhi_lower)),
390 antennaResponse.at(
ResponseKey(iFrequency_upper, iTheta_upper, iPhi_upper))
394 InterpolateLinear(theta, theta_lower, theta_upper, vel_freq_up_theta_low, vel_freq_up_theta_up);
397 InterpolateLinear(freq, frequency_lower, frequency_upper, vel_freq_low, vel_freq_up);
401 return GetComplexRepresentationOfVectorEffectiveLength(vel);
406 AntennaType::GetIntegratedEffectiveAntennaHeight(
const double freq)
408 BufferAntennaPattern();
409 const double frequency_lower_bound = fgAntennaPattern[fAntennaType].frequency_lower_bound;
410 const double frequency_upper_bound = fgAntennaPattern[fAntennaType].frequency_upper_bound;
412 if (freq < frequency_lower_bound || freq > frequency_upper_bound) {
419 const int nFrequency = fgAntennaPattern[fAntennaType].nFrequency;
420 const std::vector<double>& frequencies = fgAntennaPattern[fAntennaType].frequencies;
422 const int iFrequency_lower =
423 int(floor((freq - frequency_lower_bound) / (frequency_upper_bound - frequency_lower_bound) * (nFrequency - 1)));
424 const double frequency_lower = frequencies.at(iFrequency_lower);
425 const int iFrequency_upper =
426 int(ceil((freq - frequency_lower_bound) / (frequency_upper_bound - frequency_lower_bound) * (nFrequency - 1)));
427 const double frequency_upper = frequencies.at(iFrequency_upper);
434 return InterpolateLinear(freq, frequency_lower, frequency_upper,
435 fgAntennaPattern[fAntennaType].meanTransfer.at(iFrequency_lower),
436 fgAntennaPattern[fAntennaType].meanTransfer.at(iFrequency_upper));
441 AntennaType::CalculateIntegratedEffectiveAntennaHeight(
const std::map<ResponseKey, VectorEffectiveLength>& antennaResponse,
442 const int iFreq,
const int nTheta,
const int nPhi)
444 double integratedVEL = 0;
445 for (
int iTheta = 0; iTheta < nTheta; ++iTheta) {
446 for (
int iPhi = 0; iPhi < nPhi; ++iPhi) {
451 integratedVEL *= 2 * M_PI / (nTheta * nPhi *
sqrt(2));
452 return integratedVEL;
457 AntennaType::NotFoundAndExit(
const string& msg)
461 err <<
"Did not find requested component: " << msg;
std::complex< float > Theta
Base class for all exceptions used in the auger offline code.
std::map< ResponseKey, VectorEffectiveLength > AntennaResponse
#define INFO(message)
Macro for logging informational messages.
Wrapper class for initially unset data.
std::vector< double > meanTransfer
double abs(const SVector< n, T > &v)
#define WARNING(message)
Macro for logging warning messages.
std::vector< double > frequencies
double frequency_upper_bound
boost::tuple< int, int, int > ResponseKey
std::complex< float > Phi
std::vector< double > thetaAngles
std::vector< double > phiAngles
double frequency_lower_bound
#define ERROR(message)
Macro for logging error messages.