DP3
AntennaConfig.h
Go to the documentation of this file.
1 // Copyright (C) 2023 ASTRON (Netherlands Institute for Radio Astronomy)
2 // SPDX-License-Identifier: GPL-3.0-or-later
3 
7 
11 
12 #ifndef AARTFAACREADER_ANTENNACONFIG_H_
13 #define AARTFAACREADER_ANTENNACONFIG_H_
14 
15 #include <algorithm>
16 #include <array>
17 #include <cctype>
18 #include <fstream>
19 #include <locale>
20 #include <map>
21 #include <numeric>
22 #include <sstream>
23 #include <string>
24 #include <utility>
25 #include <vector>
26 
27 #include <base/RcuMode.h>
28 #include <casacore/measures/Measures/MPosition.h>
29 
30 namespace {
31 
32 // trim from start (in place)
33 void LTrim(std::string &s) {
34  s.erase(s.begin(), std::find_if(s.begin(), s.end(),
35  [](int ch) { return !std::isspace(ch); }));
36 }
37 
38 // trim from end (in place)
39 void RTrim(std::string &s) {
40  s.erase(std::find_if(s.rbegin(), s.rend(),
41  [](int ch) { return !std::isspace(ch); })
42  .base(),
43  s.end());
44 }
45 
46 // trim from both ends (in place)
47 void Trim(std::string &s) {
48  LTrim(s);
49  RTrim(s);
50 }
51 } // namespace
52 
54 
56  public:
57  explicit AntennaConfig(const char *filename) : file_(filename) {
58  ParseFile();
59  }
60 
61  std::vector<casacore::MPosition> GetLBAPositions() const {
62  return GetPositions("LBA");
63  }
64 
65  std::vector<casacore::MPosition> GetHBAPositions() const {
66  return GetPositions("HBA");
67  }
68 
69  std::array<double, 9> GetLBAAxes() const {
70  return GetAxes("LBA_ROTATION_MATRIX");
71  }
72 
73  std::array<double, 9> GetHBA0Axes() const {
74  return GetAxes("HBA0_ROTATION_MATRIX");
75  }
76 
77  std::array<double, 9> GetHBA1Axes() const {
78  return GetAxes("HBA1_ROTATION_MATRIX");
79  }
80 
81  std::array<double, 9> GetAxesFromMode(base::RcuMode mode) {
82  switch (mode.mode) {
87  return GetLBAAxes();
91  return GetHBA0Axes();
92  break;
93  default:
94  throw std::runtime_error("Wrong RCU mode");
95  }
96  }
97 
98  std::vector<casacore::MPosition> GetArrayFromMode(base::RcuMode mode) {
99  switch (mode.mode) {
104  return GetLBAPositions();
105  break;
109  return GetHBAPositions();
110  default:
111  throw std::runtime_error("Wrong RCU mode");
112  }
113  }
114 
115  private:
116  struct Array {
117  std::string name;
118  std::string band;
119  std::vector<double> data;
120  };
121 
122  void ParseFile() {
123  Next();
124  struct Array a;
125  while (ReadArray(a.name, a.band, a.data)) {
126  std::string key;
127  if (a.band.empty())
128  key = a.name;
129  else
130  key = a.band + "_" + a.name;
131  values_.insert(std::make_pair(key, a));
132  }
133  }
134  const std::vector<double> &GetArray(const std::string &name) const {
135  return values_.find(name)->second.data;
136  }
137  std::vector<casacore::MPosition> GetPositions(
138  const std::string &arrayName) const {
139  const std::vector<double> &arr = GetArray(arrayName);
140  std::vector<casacore::MPosition> position;
141  for (size_t index = 0; index < arr.size(); index += 6) {
142  position.emplace_back(casacore::MPosition{
143  casacore::MVPosition{arr[index], arr[index + 1], arr[index + 2]},
144  casacore::MPosition::ITRF});
145  }
146  return position;
147  }
148 
149  std::array<double, 9> GetAxes(const std::string &arrayName) const {
150  const std::vector<double> &arr = GetArray(arrayName);
151  if (arr.size() != 9)
152  throw std::runtime_error(
153  "The array for coordinate axes in the antenna "
154  "config file had an incorrect size");
155 
156  std::array<double, 9> axes;
157  for (size_t index = 0; index < 9; ++index) axes[index] = arr[index];
158  return axes;
159  }
160 
161  bool Next() {
162  if (line_.empty() || line_position_ >= line_.size()) {
163  do {
164  std::getline(file_, line_);
165  if (!file_) {
166  token_.clear();
167  line_.clear();
168  return false;
169  }
170  Trim(line_);
171  } while (line_.empty() || line_[0] == '#');
172  line_position_ = 0;
173  }
174  size_t pos = line_.find_first_of(" \t", line_position_);
175  if (pos == std::string::npos) {
176  token_ = line_.substr(line_position_);
177  line_.clear();
178  line_position_ = 0;
179  return true;
180  } else {
181  token_ = line_.substr(line_position_, pos - line_position_);
182  line_position_ = pos + 1;
183  while (line_position_ < line_.size() &&
184  (line_[line_position_] == ' ' || line_[line_position_] == '\t'))
185  ++line_position_;
186  Trim(token_);
187  if (token_.empty())
188  return Next();
189  else
190  return true;
191  }
192  }
193 
194  std::vector<int> ReadDimensions() {
195  std::vector<int> dimensions = {std::atoi(token_.c_str())};
196  do {
197  if (!Next())
198  throw std::runtime_error(
199  "Antenna config file has bad format: expected dimensions");
200  if (token_ == "x") {
201  if (!Next())
202  throw std::runtime_error(
203  "Antenna config file has bad format: "
204  "expected another dimension after x");
205  int dimension_value = std::atoi(token_.c_str());
206  dimensions.push_back(dimension_value);
207  } else if (token_ != "[") {
208  throw std::runtime_error("Antenna config file has bad format");
209  }
210  } while (token_ != "[");
211  return dimensions;
212  }
213 
214  const std::vector<double> ReadData(const std::vector<int> &dimensions) {
215  int count = std::accumulate(dimensions.begin(), dimensions.end(), 1,
216  [](int a, int b) { return a * b; });
217  std::vector<double> values(count);
218  for (int i = 0; i != count; ++i) {
219  if (!Next()) {
220  throw std::runtime_error("Missing numbers");
221  }
222  values[i] = std::atof(token_.c_str());
223  }
224  Next(); // move TO ']'
225  return values;
226  }
227 
228  bool ReadArray(std::string &name, std::string &band,
229  std::vector<double> &values) {
230  values.clear();
231  if (!std::isalpha(token_[0])) return false;
232  name = token_;
233  Next();
234 
235  if (std::isalpha(token_[0])) {
236  band = token_;
237  Next();
238  } else {
239  band.clear();
240  }
241 
242  std::vector<int> dimensions1 = ReadDimensions();
243  std::vector<double> data1 = ReadData(dimensions1);
244  if (Next() && token_[0] >= '0' && token_[0] <= '9') {
245  std::vector<int> dimensions2 = ReadDimensions();
246  std::vector<double> data2 = ReadData(dimensions2);
247  Next(); // skip ']'
248 
249  values = std::move(data2);
250  for (size_t i = 0; i != values.size(); ++i)
251  values[i] += data1[i % data1.size()];
252  } else {
253  values = std::move(data1);
254  }
255  return true;
256  }
257 
258  std::map<std::string, Array> values_;
259 
260  std::ifstream file_;
261  std::string line_;
262  size_t line_position_;
263  std::string token_;
264 };
265 } // namespace dp3::aartfaacreader
266 
267 #endif // AARTFAACREADER_ANTENNACONFIG_H_
Definition: AntennaConfig.h:55
std::vector< casacore::MPosition > GetHBAPositions() const
Definition: AntennaConfig.h:65
std::vector< casacore::MPosition > GetLBAPositions() const
Definition: AntennaConfig.h:61
std::array< double, 9 > GetAxesFromMode(base::RcuMode mode)
Definition: AntennaConfig.h:81
std::array< double, 9 > GetHBA0Axes() const
Definition: AntennaConfig.h:73
std::array< double, 9 > GetHBA1Axes() const
Definition: AntennaConfig.h:77
AntennaConfig(const char *filename)
Definition: AntennaConfig.h:57
std::array< double, 9 > GetLBAAxes() const
Definition: AntennaConfig.h:69
std::vector< casacore::MPosition > GetArrayFromMode(base::RcuMode mode)
Definition: AntennaConfig.h:98
Definition: RcuMode.h:24
@ LBAInner30_90
Definition: RcuMode.h:31
@ LBAOuter10_90
Definition: RcuMode.h:28
@ LBAInner10_90
Definition: RcuMode.h:30
@ HBA110_190
Definition: RcuMode.h:32
@ HBA170_230
Definition: RcuMode.h:33
@ LBAOuter30_90
Definition: RcuMode.h:29
@ HBA210_270
Definition: RcuMode.h:34
enum dp3::base::RcuMode::Mode mode
Definition: AntennaConfig.h:53