PURIFY
Next-generation radio interferometric imaging
casacore.cc
Go to the documentation of this file.
1 #include "purify/casacore.h"
2 #include "purify/config.h"
3 #include "purify/types.h"
4 #include <sstream>
5 #include <casacore/casa/Arrays/IPosition.h>
6 #include <casacore/tables/TaQL/ExprNode.h>
7 #include "purify/logging.h"
8 
9 namespace purify {
10 namespace casa {
11 std::string const MeasurementSet::default_filter = "WHERE NOT ANY(FLAG)";
12 MeasurementSet &MeasurementSet::filename(std::string const &filename) {
13  clear();
14  filename_ = filename;
15  return *this;
16 }
17 
18 ::casacore::Table const &MeasurementSet::table(std::string const &name) const {
19  auto const tabname = name == "" ? filename() : filename() + "/" + name;
20  auto i_result = tables_->find(tabname);
21  if (i_result == tables_->end())
22  i_result = tables_->emplace(tabname, ::casacore::Table(tabname)).first;
23 
24  return i_result->second;
25 }
26 
27 std::size_t MeasurementSet::size() const {
28  if (table().nrow() == 0) return 0;
29  auto const column = array_column<::casacore::Double>("CHAN_FREQ", "SPECTRAL_WINDOW");
30  auto const orig = column.shape(0);
31  for (t_uint i(1); i < column.nrow(); ++i)
32  if (orig != column.shape(i))
33  throw std::runtime_error("Can only do rectangular measurement set for now");
34  return orig(0);
35 }
36 
37 MeasurementSet::const_iterator MeasurementSet::begin(std::string const &filter) const {
38  return const_iterator(0, *this, filter);
39 }
40 MeasurementSet::const_iterator MeasurementSet::end(std::string const &filter) const {
41  return const_iterator(size(), *this, filter);
42 }
44  return ChannelWrapper(i, *this, "");
45 }
46 
48  std::tuple<t_uint, std::string> const &i) const {
49  if (std::get<0>(i) >= size()) throw std::out_of_range("Not that many channels");
50  return ChannelWrapper(std::get<0>(i), *this, std::get<1>(i));
51 }
52 
53 std::string MeasurementSet::ChannelWrapper::filter() const {
54  std::ostringstream sstr;
55  sstr << "WHERE NOT any(FLAG[" << channel_ << ",])";
56  if (not filter_.empty()) sstr << "AND " << filter_;
57  return sstr.str();
58 }
59 std::string MeasurementSet::ChannelWrapper::index(std::string const &variable) const {
60  std::ostringstream sstr;
61  sstr << variable << "[" << channel_ << ",]";
62  return sstr.str();
63 }
64 
65 Vector<t_real> MeasurementSet::ChannelWrapper::joined_spectral_window(
66  std::string const &column) const {
67  auto const raw = raw_spectral_window(column);
68  auto const ids = ms_.column<::casacore::Int>("DATA_DESC_ID", filter());
69  auto const spids =
70  table_column<::casacore::Int>(ms_.table("DATA_DESCRIPTION"), "SPECTRAL_WINDOW_ID");
71  Vector<t_real> result(ids.size());
72  for (Eigen::DenseIndex i(0); i < ids.size(); ++i) {
73  assert(ids(i) < spids.size());
74  assert(spids(ids(i)) < raw.size());
75  result(i) = raw(spids(ids(i)));
76  }
77  return result;
78 }
79 
81  std::ostringstream sstr;
82  sstr << "USING STYLE PYTHON SELECT FLAG[" << channel_ << ",] as R FROM $1 WHERE NOT any(FLAG["
83  << channel_ << ",])";
84  if (not filter_.empty()) sstr << "AND " << filter_;
85  auto const taql_table = ::casacore::tableCommand(sstr.str(), ms_.table());
86  return taql_table.table().nrow() > 0;
87 }
88 
89 std::string MeasurementSet::ChannelWrapper::stokes(std::string const &pol,
90  std::string const &column) const {
91  std::ostringstream sstr;
92  sstr << "mscal.stokes(" << column << ", '" << pol << "')";
93  return sstr.str();
94 }
95 
96 Vector<t_real> MeasurementSet::ChannelWrapper::raw_spectral_window(std::string const &stuff) const {
97  std::ostringstream sstr;
98  sstr << stuff << "[" << channel_ << "]";
99  return table_column<t_real>(ms_.table("SPECTRAL_WINDOW"), sstr.str());
100 }
101 
103  std::string const &filter) const {
104  auto const field_ids_raw = column<::casacore::Int>("FIELD_ID", filter);
105  auto const source_ids_raw = table_column<::casacore::Int>(table("FIELD"), "SOURCE_ID");
106  std::set<::casacore::Int> source_ids;
107  for (Eigen::DenseIndex i(0); i < field_ids_raw.size(); ++i) {
108  assert(field_ids_raw(i) < source_ids_raw.size());
109  source_ids.insert(source_ids_raw(field_ids_raw(i)));
110  }
111  if (source_ids.size() == 0 and source_ids_raw.size() > 0) {
112  PURIFY_DEBUG(
113  "Could not find sources. Try different filter, no matching data in channel. "
114  "Currently using filter: " +
115  filter);
116  Vector<t_real> original(2);
117  original(0) = 0.;
118  original(1) = 0.;
119  return original;
120  } else if (source_ids_raw.size() == 0)
121  throw std::runtime_error("Could not find sources. Cannot determine direction");
122  auto const directions = table_column<::casacore::Double>(table("SOURCE"), "DIRECTION");
123  auto const original = directions.row(*source_ids.begin());
124  for (auto const other : source_ids)
125  if (not directions.row(other).isApprox(original, tolerance))
126  throw std::runtime_error("Found more than one direction");
127  return original;
128 }
129 
131  ++channel_;
132  wrapper_ = std::make_shared<value_type>(channel_, ms_, filter_);
133  return *this;
134 }
135 
137  operator++();
138  return const_iterator(channel_ - 1, ms_, filter_);
139 }
140 
142  if (not same_measurement_set(c))
143  throw std::runtime_error("Iterators are not over the same measurement set");
144  return channel_ == c.channel_;
145 }
146 
147 utilities::vis_params read_measurementset(std::string const &filename, const stokes polarization,
148  const std::vector<t_int> &channels_input,
149  std::string const &filter) {
150  auto const ms_file = purify::casa::MeasurementSet(filename);
151  return read_measurementset(ms_file, polarization, channels_input, filter);
152 };
154  const utilities::vis_params &uv1, const stokes pol,
155  const std::vector<t_int> &channels,
156  std::string const &filter) {
158  const auto uv2 = read_measurementset(filename, pol, channels, filter);
159  if (std::abs(uv1.ra - uv2.ra) > 1e-6)
160  throw std::runtime_error(filename + ": wrong RA in pointing.");
161  if (std::abs(uv1.dec - uv2.dec) > 1e-6)
162  throw std::runtime_error(filename + ": wrong DEC in pointing.");
163  uv.ra = uv1.ra;
164  uv.dec = uv1.dec;
165  uv.u = Vector<t_real>::Zero(uv1.size() + uv2.size());
166  uv.v = Vector<t_real>::Zero(uv1.size() + uv2.size());
167  uv.w = Vector<t_real>::Zero(uv1.size() + uv2.size());
168  uv.vis = Vector<t_complex>::Zero(uv1.size() + uv2.size());
169  uv.weights = Vector<t_complex>::Zero(uv1.size() + uv2.size());
170  uv.u.segment(0, uv1.size()) = uv1.u;
171  uv.v.segment(0, uv1.size()) = uv1.v;
172  uv.w.segment(0, uv1.size()) = uv1.w;
173  uv.vis.segment(0, uv1.size()) = uv1.vis;
174  uv.weights.segment(0, uv1.size()) = uv1.weights;
175  uv.u.segment(uv1.size(), uv2.size()) = uv2.u;
176  uv.v.segment(uv1.size(), uv2.size()) = uv2.v;
177  uv.w.segment(uv1.size(), uv2.size()) = uv2.w;
178  uv.vis.segment(uv1.size(), uv2.size()) = uv2.vis;
179  uv.weights.segment(uv1.size(), uv2.size()) = uv2.weights;
180  return uv;
181 }
182 utilities::vis_params read_measurementset(std::vector<std::string> const &filename,
183  const stokes pol, const std::vector<t_int> &channel,
184  std::string const &filter) {
185  utilities::vis_params output = read_measurementset(filename.at(0), pol, channel, filter);
186  if (filename.size() == 1) return output;
187  for (int i = 1; i < filename.size(); i++)
188  output = read_measurementset(filename.at(i), output, pol, channel, filter);
189  return output;
190 }
192  const std::vector<t_int> &channels_input,
193  std::string const &filter) {
194  utilities::vis_params uv_data;
195  t_uint rows = 0;
196  std::vector<t_int> channels = channels_input;
197  if (channels.empty()) {
198  PURIFY_LOW_LOG("All Channels = {}", ms_file.size());
199  Vector<t_int> temp_vector = Vector<t_int>::LinSpaced(ms_file.size(), 0, ms_file.size());
200  if (temp_vector.size() == 1) // fixing unwanted behavior of LinSpaced when ms_file.size() = 1
201  temp_vector(0) = 0;
202  channels = std::vector<t_int>(temp_vector.data(), temp_vector.data() + temp_vector.size());
203  }
204 
205  // counting number of rows
206  for (auto channel_number : channels) {
207  rows += ms_file[channel_number].size();
208  }
209 
210  PURIFY_LOW_LOG("Visibilities = {}", rows);
211  uv_data.u = Vector<t_real>::Zero(rows);
212  uv_data.v = Vector<t_real>::Zero(rows);
213  uv_data.w = Vector<t_real>::Zero(rows);
214  uv_data.vis = Vector<t_complex>::Zero(rows);
215  uv_data.weights = Vector<t_complex>::Zero(rows);
216  uv_data.ra =
217  ms_file[channels[0]].right_ascension(); // convert directions from radians to degrees
218  uv_data.dec = ms_file[channels[0]].declination();
219  // calculate average frequency
220  uv_data.average_frequency = average_frequency(ms_file, filter, channels);
221 
222  // add data to channel
223  t_uint row = 0;
224 
225  for (auto channel_number : channels) {
226  PURIFY_DEBUG("Adding channel {} to plane...", channel_number);
227  if (channel_number < ms_file.size()) {
228  auto const channel = ms_file[channel_number];
229  if (channel.size() > 0) {
230  if (uv_data.ra != channel.right_ascension() or uv_data.dec != channel.declination())
231  throw std::runtime_error("Channels contain multiple pointings.");
232  Vector<t_real> const frequencies = channel.frequencies();
233  uv_data.u.segment(row, channel.size()) = channel.lambda_u();
234  uv_data.v.segment(row, channel.size()) = -channel.lambda_v();
235  uv_data.w.segment(row, channel.size()) = channel.lambda_w();
236  t_real const the_casa_factor = 2;
237  switch (polarization) {
238  case stokes::I:
239  uv_data.vis.segment(row, channel.size()) = channel.I("DATA") * 0.5;
240  uv_data.weights.segment(row, channel.size()).real() =
242  the_casa_factor; // go for sigma rather than sigma_spectrum
243  break;
244  case stokes::Q:
245  uv_data.vis.segment(row, channel.size()) = channel.Q("DATA") * 0.5;
246  uv_data.weights.segment(row, channel.size()).real() =
248  the_casa_factor; // go for sigma rather than sigma_spectrum
249  break;
250  case stokes::U:
251  uv_data.vis.segment(row, channel.size()) = channel.U("DATA") * 0.5;
252  uv_data.weights.segment(row, channel.size()).real() =
254  the_casa_factor; // go for sigma rather than sigma_spectrum
255  break;
256  case stokes::V:
257  uv_data.vis.segment(row, channel.size()) = channel.V("DATA") * 0.5;
258  uv_data.weights.segment(row, channel.size()).real() =
260  the_casa_factor; // go for sigma rather than sigma_spectrum
261  break;
262  case stokes::LL:
263  uv_data.vis.segment(row, channel.size()) = channel.LL("DATA");
264  uv_data.weights.segment(row, channel.size()).real() = channel.wLL(
265  MeasurementSet::ChannelWrapper::Sigma::OVERALL); // go for sigma rather than
266  // sigma_spectrum
267  break;
268  case stokes::LR:
269  uv_data.vis.segment(row, channel.size()) = channel.LR("DATA");
270  uv_data.weights.segment(row, channel.size()).real() = channel.wRL(
271  MeasurementSet::ChannelWrapper::Sigma::OVERALL); // go for sigma rather than
272  // sigma_spectrum
273  break;
274  case stokes::RL:
275  uv_data.vis.segment(row, channel.size()) = channel.RL("DATA");
276  uv_data.weights.segment(row, channel.size()).real() = channel.wRL(
277  MeasurementSet::ChannelWrapper::Sigma::OVERALL); // go for sigma rather than
278  // sigma_spectrum
279  break;
280  case stokes::RR:
281  uv_data.vis.segment(row, channel.size()) = channel.RR("DATA");
282  uv_data.weights.segment(row, channel.size()).real() = channel.wRR(
283  MeasurementSet::ChannelWrapper::Sigma::OVERALL); // go for sigma rather than
284  // sigma_spectrum
285  break;
286  case stokes::XX:
287  uv_data.vis.segment(row, channel.size()) = channel.XX("DATA");
288  uv_data.weights.segment(row, channel.size()).real() = channel.wXX(
289  MeasurementSet::ChannelWrapper::Sigma::OVERALL); // go for sigma rather than
290  // sigma_spectrum
291  break;
292  case stokes::XY:
293  uv_data.vis.segment(row, channel.size()) = channel.XY("DATA");
294  uv_data.weights.segment(row, channel.size()).real() = channel.wXY(
295  MeasurementSet::ChannelWrapper::Sigma::OVERALL); // go for sigma rather than
296  // sigma_spectrum
297  break;
298  case stokes::YX:
299  uv_data.vis.segment(row, channel.size()) = channel.YX("DATA");
300  uv_data.weights.segment(row, channel.size()).real() = channel.wYX(
301  MeasurementSet::ChannelWrapper::Sigma::OVERALL); // go for sigma rather than
302  // sigma_spectrum
303  break;
304  case stokes::YY:
305  uv_data.vis.segment(row, channel.size()) = channel.YY("DATA");
306  uv_data.weights.segment(row, channel.size()).real() = channel.wYY(
307  MeasurementSet::ChannelWrapper::Sigma::OVERALL); // go for sigma rather than
308  // sigma_spectrum
309  break;
310  case stokes::P:
311  t_complex I(0., 1.);
312  uv_data.vis.segment(row, channel.size()) = channel.Q("DATA") + I * channel.U("DATA");
313  uv_data.weights.segment(row, channel.size()).real() =
318  .sqrt(); // go for sigma rather than
319  // sigma_spectrum
320  break;
321  }
322  row += channel.size();
323  }
324  }
325  }
326  // make consistent with vis file format exported from casa
327  uv_data.weights = 1. / uv_data.weights.array();
329  return uv_data;
330 }
331 
332 std::vector<utilities::vis_params> read_measurementset_channels(std::string const &filename,
333  const stokes pol,
334  const t_int &channel_width,
335  std::string const &filter) {
336  // Read and average the channels into a vector of vis_params
337  std::vector<utilities::vis_params> channels_vis;
338  auto const ms_file = purify::casa::MeasurementSet(filename);
339  t_int const total_channels = ms_file.size();
340  t_int const planes = (channel_width == 0) ? 1 : std::floor(total_channels / channel_width);
341  PURIFY_DEBUG("Number of planes {} ...", planes);
342  for (int i = 0; i < planes; i++) {
343  PURIFY_DEBUG("Reading plane {} ...", i);
344  t_int const end = std::min((i + 1) * channel_width, total_channels);
345  Vector<t_int> temp_block = Vector<t_int>::LinSpaced(channel_width, i * channel_width, end);
346  if (channel_width == 1 or total_channels == i) temp_block(0) = i;
347  auto const block = std::vector<t_int>(temp_block.data(), temp_block.data() + temp_block.size());
348  channels_vis.push_back(read_measurementset(ms_file, pol, block, filter));
349  }
350  return channels_vis;
351 };
352 
353 t_real average_frequency(const purify::casa::MeasurementSet &ms_file, std::string const &filter,
354  const std::vector<t_int> &channels) {
355  // calculate average frequency
356  t_real frequency_sum = 0;
357  t_real width_sum = 0.;
358  for (auto channel_number : channels) {
359  auto const channel = ms_file[channel_number];
360  auto const frequencies = channel.frequencies();
361  auto const width = channel.width();
362  frequency_sum += (frequencies.array() * width.array()).sum();
363  width_sum += width.sum();
364  }
365  return frequency_sum / width_sum / 1e6;
366 }
367 
369  if (ms_.table().nrow() == 0) return 0;
370  std::ostringstream sstr;
371  sstr << "USING STYLE PYTHON SELECT FLAG[" << channel_ << ",] as R FROM $1 WHERE NOT any(FLAG["
372  << channel_ << ",])";
373  if (not filter_.empty()) sstr << "AND " << filter_;
374  auto const taql_table = ::casacore::tableCommand(sstr.str(), ms_.table());
375  auto const vtable = taql_table.table();
376  return vtable.nrow();
377 }
378 
380  channel_ += n;
381  return *this;
382 }
383 
385  if (not same_measurement_set(c))
386  throw std::runtime_error("Iterators are not over the same measurement set");
387  return channel_ > c.channel_;
388 }
389 
391  if (not same_measurement_set(c))
392  throw std::runtime_error("Iterators are not over the same measurement set");
393  return channel_ >= c.channel_;
394 }
395 } // namespace casa
396 } // namespace purify
t_uint size() const
Number of rows in a channel.
Definition: casacore.cc:368
bool is_valid() const
Check if channel has any data.
Definition: casacore.cc:80
const_iterator & operator+=(difference_type n)
Definition: casacore.cc:379
bool operator>(const_iterator const &c) const
Definition: casacore.cc:384
bool operator>=(const_iterator const &c) const
Definition: casacore.cc:390
bool operator==(const_iterator const &c) const
Definition: casacore.cc:141
Interface around measurement sets.
Definition: casacore.h:27
Direction::Scalar right_ascension(t_real tolerance=1e-8, std::string const &filter="") const
Right ascention in radians.
Definition: casacore.h:86
std::string const & filename() const
Filename of the measurement set.
Definition: casacore.h:44
const_iterator end(std::string const &filter="") const
Iterates over channels.
Definition: casacore.cc:40
::casacore::Table const & table(std::string const &name="") const
Gets table or subtable.
Definition: casacore.cc:18
ChannelWrapper operator[](t_uint i) const
Returns wrapper over specific channel.
Definition: casacore.cc:43
Direction direction(t_real tolerance=1e-8, std::string const &filter="") const
Direction (RA, DEC) in radians.
Definition: casacore.cc:102
static std::string const default_filter
Default filter specifying which data to accept.
Definition: casacore.h:31
Eigen::Array< t_real, 2, 1 > Direction
Type for (RA, DEC) direction.
Definition: casacore.h:35
Direction::Scalar declination(t_real tolerance=1e-8, std::string const &filter="") const
Declination in radians.
Definition: casacore.h:90
void clear()
Clear memory.
Definition: casacore.h:64
const_iterator begin(std::string const &filter="") const
Iterates over channels.
Definition: casacore.cc:37
std::size_t size() const
Number of channels in the measurement set.
Definition: casacore.cc:27
Matrix< T > column(std::string const &column, std::string const &filter="") const
Data from a column.
Definition: casacore.h:68
#define PURIFY_LOW_LOG(...)
Low priority message.
Definition: logging.h:207
#define PURIFY_DEBUG(...)
\macro Output some debugging
Definition: logging.h:197
t_real average_frequency(const purify::casa::MeasurementSet &ms_file, std::string const &filter, const std::vector< t_int > &channels)
Return average frequency over channels.
Definition: casacore.cc:353
utilities::vis_params read_measurementset(std::string const &filename, const stokes polarization, const std::vector< t_int > &channels_input, std::string const &filter)
Read measurement set into vis_params structure.
Definition: casacore.cc:147
std::vector< utilities::vis_params > read_measurementset_channels(std::string const &filename, const stokes pol, const t_int &channel_width, std::string const &filter)
Read meassurement set into a vector of vis_params.
Definition: casacore.cc:332
const t_real c
speed of light in vacuum
Definition: types.h:72
stokes
Definition: types.h:44
Vector< t_complex > vis
Definition: uvw_utilities.h:22
t_uint size() const
return number of measurements
Definition: uvw_utilities.h:54
Vector< t_complex > weights
Definition: uvw_utilities.h:23