2 #include "purify/config.h"
15 if (names.size() == 1)
return output;
16 for (
int i = 1; i < names.size(); i++) output =
read_uvfits(names.at(i), output);
21 const bool flag,
const stokes pol) {
23 const bool w_term = not uv1.
w.isZero(0);
25 if (std::abs(uv1.
ra - uv2.ra) > 1e-6)
26 throw std::runtime_error(vis_name2 +
": wrong RA in pointing.");
27 if (std::abs(uv1.
dec - uv2.dec) > 1e-6)
28 throw std::runtime_error(vis_name2 +
": wrong DEC in pointing.");
31 uv.
u = Vector<t_real>::Zero(uv1.
size() + uv2.size());
32 uv.
v = Vector<t_real>::Zero(uv1.
size() + uv2.size());
33 uv.
w = Vector<t_real>::Zero(uv1.
size() + uv2.size());
34 uv.
vis = Vector<t_complex>::Zero(uv1.
size() + uv2.size());
35 uv.
weights = Vector<t_complex>::Zero(uv1.
size() + uv2.size());
36 uv.
u.segment(0, uv1.
size()) = uv1.
u;
37 uv.
v.segment(0, uv1.
size()) = uv1.
v;
38 uv.
w.segment(0, uv1.
size()) = uv1.
w;
41 uv.
u.segment(uv1.
size(), uv2.size()) = uv2.u;
42 uv.
v.segment(uv1.
size(), uv2.size()) = uv2.v;
43 uv.
w.segment(uv1.
size(), uv2.size()) = uv2.w;
44 uv.
vis.segment(uv1.
size(), uv2.size()) = uv2.vis;
45 uv.
weights.segment(uv1.
size(), uv2.size()) = uv2.weights;
58 std::shared_ptr<char> comment =
59 std::shared_ptr<char>(
new char[FLEN_CARD], [](
char *ptr) {
delete[] ptr; });
61 if (fits_open_file(&fptr, filename.c_str(), READONLY, &status))
62 throw std::runtime_error(
"Could not open file " + filename);
65 if (fits_movabs_hdu(fptr, 1, &hdutype, &status))
throw std::runtime_error(
"Error changing HDU.");
66 if (hdutype != IMAGE_HDU)
67 throw std::runtime_error(
"HDU 1 not expected type " + std::to_string(hdutype));
69 fits_read_key(fptr, TDOUBLE,
"CRVAL5", &ra, comment.get(), &status);
70 fits_read_key(fptr, TDOUBLE,
"CRVAL6", &dec, comment.get(), &status);
71 fits_read_key(fptr, TINT,
"GCOUNT", &baselines, comment.get(), &status);
72 fits_read_key(fptr, TINT,
"NAXIS", &naxes, comment.get(), &status);
73 fits_read_key(fptr, TINT,
"PCOUNT", &pcount, comment.get(), &status);
74 if (naxes == 0)
throw std::runtime_error(
"No axes in header... ");
75 if (pcount == 0)
throw std::runtime_error(
"No uvw or time coordinates in header... ");
77 std::vector<int> naxis(naxes, 0);
79 for (
int i = 1; i < naxes; i++) {
81 std::string key =
"NAXIS" + std::to_string(i + 1);
82 fits_read_key(fptr, TINT, key.c_str(), &n, comment.get(), &status);
87 const t_uint channels = naxis.at(3);
88 const t_uint pols = naxis.at(2);
89 const t_uint ifs = naxis.at(4);
90 const t_uint pointings_num = naxis.at(5);
98 "Purify currently assumes uvfits files are in XX YY XY YX format. Also will only read Stokes "
101 if (pointings_num > 1)
throw std::runtime_error(
"More than one pointing is not supported.");
102 if (ifs > 1)
throw std::runtime_error(
"More than one IF is not supported.");
108 const Vector<t_real> data =
read_uvfits_data(fptr, &status, naxis, baselines);
110 if (frequencies.size() != channels)
111 throw std::runtime_error(
"Number of frequencies doesn't match number of channels. " +
112 std::to_string(frequencies.size()) +
"!=" + std::to_string(channels));
115 Vector<t_complex> stokes_transform = Vector<t_complex>::Zero(2);
120 stokes_transform(0) = 1. / 2;
121 stokes_transform(1) = 1. / 2;
124 throw std::runtime_error(
"Polarisation not supported for reading uvfits.");
127 stokes_transform(0) = 1. / 2;
128 stokes_transform(1) = -1. / 2;
131 throw std::runtime_error(
"Polarisation not supported for reading uvfits.");
134 stokes_transform(0) = 1. / 2 * t_complex(0, -1);
135 stokes_transform(1) = 1. / 2 * t_complex(0, -1);
138 throw std::runtime_error(
"Polarisation not supported for reading uvfits.");
141 stokes_transform(0) = 1. / 2 * t_complex(0, -1);
142 stokes_transform(1) = -1. / 2 * t_complex(0, -1);
145 throw std::runtime_error(
"Polarisation not supported for reading uvfits.");
148 stokes_transform(0) = 1. / 2;
149 stokes_transform(1) = 1. / 2;
152 fits_close_file(fptr, &status);
154 fits_report_error(stderr, status);
155 throw std::runtime_error(
"Error reading fits file...");
158 data, coords, frequencies, pol_index1, pol_index2, pols, baselines, channels,
160 [flag](
const t_complex vis1,
const t_complex weight1,
const t_complex vis2,
161 const t_complex weight2) {
163 return (weight1.real() > 0.) and (weight2.real() > 0.) and (std::abs(vis1) > 1e-20) and
164 (std::abs(vis2) > 1e-20) and
165 (!std::isnan(vis1.real()) and !std::isnan(vis1.imag())) and
166 (!std::isnan(vis2.real()) and !std::isnan(vis2.imag()));
177 const Vector<t_complex> &stokes_transform,
178 const std::function<
bool(t_real, t_real, t_real, t_complex, t_complex, t_real, t_real, t_real,
179 t_complex, t_complex)> &filter) {
181 if (stokes_transform.size() != 2)
182 throw std::runtime_error(
"stokes transform is not the right size (!= 2).");
183 if (stokes_transform.isZero())
throw std::runtime_error(
"stokes transform not valid.");
185 throw std::runtime_error(
"Cannot apply filter to each data set, sizes do not match.");
186 for (
int i = 0; i < input.
size(); i++) {
187 if (filter(input.
u(i), input.
v(i), input.
w(i), input.
vis(i), input.
weights(i), input2.
u(i),
188 input2.
v(i), input2.
w(i), input2.
vis(i), input2.
weights(i))) {
189 if (std::abs(input.
u(i) - input2.
u(i)) > 1e-6)
190 throw std::runtime_error(
"baselines don't match for filter.");
191 if (std::abs(input.
v(i) - input2.
v(i)) > 1e-6)
192 throw std::runtime_error(
"baselines don't match for filter.");
193 if (std::abs(input.
w(i) - input2.
w(i)) > 1e-6)
194 throw std::runtime_error(
"baselines don't match for filter.");
199 PURIFY_LOW_LOG(
"Applying flags: Keeping {} out of {} data points.", size, input.
size());
201 Vector<t_real>::Zero(size), Vector<t_complex>::Zero(size),
202 Vector<t_complex>::Zero(size), input.
units, input.
ra, input.
dec,
204 output.
time = Vector<t_real>::Zero(size);
205 output.
baseline = Vector<t_uint>::Zero(size);
208 for (t_uint i = 0; i < input.
size(); i++)
209 if (filter(input.
u(i), input.
v(i), input.
w(i), input.
vis(i), input.
weights(i), input2.
u(i),
210 input2.
v(i), input2.
w(i), input2.
vis(i), input2.
weights(i))) {
211 output.
u(count) = input.
u(i);
212 output.
v(count) = input.
v(i);
213 output.
w(count) = input.
w(i);
214 output.
vis(count) = input.
vis(i) * stokes_transform(0) + input2.
vis(i) * stokes_transform(1);
215 output.
weights(count) = 1. / std::sqrt(1. / input.
weights(i) * stokes_transform(0) +
216 1. / input2.
weights(i) * stokes_transform(1));
226 const Vector<t_real> &data,
const Matrix<t_real> &coords,
const Vector<t_real> &frequencies,
227 const t_uint pol_index1,
const t_uint pol_index2,
const t_uint pols,
const t_uint baselines,
228 const t_uint channels,
const Vector<t_complex> stokes_transform,
229 const std::function<
bool(t_complex, t_complex, t_complex, t_complex)> &filter) {
231 for (t_uint
c = 0;
c < channels;
c++)
232 for (t_uint b = 0; b < baselines; b++) {
233 t_complex
const weight1 =
235 t_complex
const weight2 =
237 t_complex
const vis1 =
read_vis_from_data(data, pol_index1, pols,
c, channels, b, baselines);
238 t_complex
const vis2 =
read_vis_from_data(data, pol_index2, pols,
c, channels, b, baselines);
239 if (filter(vis1, weight1, vis2, weight2)) count++;
241 const t_uint stride = count;
243 uv_data.
u = Vector<t_real>::Zero(stride);
244 uv_data.
v = Vector<t_real>::Zero(stride);
245 uv_data.
w = Vector<t_real>::Zero(stride);
246 uv_data.
time = Vector<t_real>::Zero(stride);
247 uv_data.
baseline = Vector<t_uint>::Zero(stride);
248 uv_data.
vis = Vector<t_complex>::Zero(stride);
249 uv_data.
weights = Vector<t_complex>::Zero(stride);
251 if (pol_index1 >= pols)
throw std::runtime_error(
"Polarisation index out of bounds.");
252 if (pol_index2 >= pols)
throw std::runtime_error(
"Polarisation index out of bounds.");
253 PURIFY_LOW_LOG(
"Applying flags: Keeping {} out of {} data points.", stride, channels * baselines);
256 for (t_uint
c = 0;
c < channels;
c++)
257 for (t_uint b = 0; b < baselines; b++) {
258 t_complex
const weight1 =
260 t_complex
const weight2 =
262 t_complex
const vis1 =
read_vis_from_data(data, pol_index1, pols,
c, channels, b, baselines);
263 t_complex
const vis2 =
read_vis_from_data(data, pol_index2, pols,
c, channels, b, baselines);
265 if (filter(vis1, weight1, vis2, weight2)) {
266 uv_data.
vis(count) = uv_data.
vis(count) =
267 vis1 * stokes_transform(0) + vis2 * stokes_transform(1);
269 1. / std::sqrt(1. / weight1 * stokes_transform(0) + 1. / weight2 * stokes_transform(1));
270 uv_data.
u(count) = coords(0, b) * frequencies(
c);
271 uv_data.
v(count) = -coords(1, b) * frequencies(
c);
272 uv_data.
w(count) = coords(2, b) * frequencies(
c);
273 uv_data.
baseline(count) =
static_cast<t_uint
>(coords(3, b));
274 uv_data.
time(count) = coords(4, b);
278 assert(count == stride);
285 const Vector<t_real> &frequencies,
const t_uint pol_index1,
286 const t_uint pols,
const t_uint baselines,
287 const t_uint channels) {
288 const t_uint stride = channels * baselines;
290 uv_data.
u = Vector<t_real>::Zero(stride);
291 uv_data.
v = Vector<t_real>::Zero(stride);
292 uv_data.
w = Vector<t_real>::Zero(stride);
293 uv_data.
time = Vector<t_real>::Zero(stride);
294 uv_data.
baseline = Vector<t_uint>::Zero(stride);
295 uv_data.
vis = Vector<t_complex>::Zero(stride);
296 uv_data.
weights = Vector<t_complex>::Zero(stride);
297 if (pol_index1 >= pols)
throw std::runtime_error(
"Polarisation index out of bounds.");
300 for (t_uint
c = 0;
c < channels;
c++)
301 for (t_uint b = 0; b < baselines; b++) {
308 for (t_uint i = 0; i < frequencies.size(); i++) {
309 uv_data.
u.segment(i * baselines, baselines) = coords.row(0) * frequencies(i);
310 uv_data.
v.segment(i * baselines, baselines) = -coords.row(1) * frequencies(i);
311 uv_data.
w.segment(i * baselines, baselines) = coords.row(2) * frequencies(i);
312 uv_data.
baseline.segment(i * baselines, baselines) = coords.row(3).cast<t_uint>();
313 uv_data.
time.segment(i * baselines, baselines) = coords.row(4);
321 Vector<t_real> output;
326 void read_uvfits_freq(fitsfile *fptr,
int *status, Vector<t_real> &output,
const int &col) {
331 std::shared_ptr<char> comment =
332 std::shared_ptr<char>(
new char[FLEN_CARD], [](
char *ptr) {
delete[] ptr; });
333 std::string key =
"CRVAL" + std::to_string(col);
334 fits_read_key(fptr, TDOUBLE, key.c_str(), &cfreq, comment.get(), status);
335 key =
"CDELT" + std::to_string(col);
336 fits_read_key(fptr, TDOUBLE, key.c_str(), &dfreq, comment.get(), status);
337 key =
"CRPIX" + std::to_string(col);
338 fits_read_key(fptr, TINT, key.c_str(), &crpix, comment.get(), status);
339 key =
"NAXIS" + std::to_string(col);
340 fits_read_key(fptr, TINT, key.c_str(), &nfreq, comment.get(), status);
341 if (nfreq == 0)
throw std::runtime_error(
"Wrong number of channels read from header.");
342 output = Vector<t_real>::Zero(nfreq);
343 for (
int i = 0; i < output.size(); i++) output(i) = (i - nfreq * 0.5) * dfreq + cfreq;
346 Vector<t_real>
read_uvfits_data(fitsfile *fptr,
int *status,
const std::vector<int> &naxis,
347 const int &baselines) {
348 Vector<t_real> output;
354 const int &baselines, Vector<t_real> &output) {
356 for (
int i = 2; i < naxis.size(); i++) {
357 nelements *=
static_cast<long>(naxis.at(i));
359 if (nelements == 0)
throw std::runtime_error(
"Zero number of elements.");
360 output = Vector<t_real>::Zero(naxis.at(1) * nelements * baselines);
363 fits_read_col(fptr, TDOUBLE, 2, 1, 1,
static_cast<long>(output.size()), &nulval, output.data(),
369 Matrix<t_real> output;
375 const t_uint pols,
const t_uint chan,
const t_uint chans,
376 const t_uint baseline,
const t_uint baselines) {
377 const t_uint index = col + 3 * (pol + pols * (chan + chans * baseline));
382 const t_uint chan,
const t_uint chans,
const t_uint baseline,
383 const t_uint baselines) {
389 const t_uint chan,
const t_uint chans,
const t_uint baseline,
390 const t_uint baselines) {
391 return t_complex(
read_value_from_data(data, 2, pol, pols, chan, chans, baseline, baselines), 0);
395 Matrix<t_real> &output) {
396 output = Matrix<t_real>::Zero(pcount, groups);
400 for (
int i = 0; i < groups; i++)
401 fits_read_col(fptr, TDOUBLE, 1, 1 + i, 1, pcount, &nulval, output.col(i).data(), &anynul,
406 std::shared_ptr<char> card =
407 std::shared_ptr<char>(
new char[FLEN_CARD], [](
char *ptr) {
delete[] ptr; });
409 fits_get_hdrspace(fptr, &nkeys, NULL, status);
411 for (
int ii = 1; ii <= nkeys; ii++) {
412 fits_read_record(fptr, ii, card.get(), status);
413 std::printf(
"%s\n", card.get());
415 std::printf(
"END\n\n");
#define PURIFY_LOW_LOG(...)
Low priority message.
#define PURIFY_MEDIUM_LOG(...)
Medium priority message.
const t_real c
speed of light in vacuum
utilities::vis_params filter_and_combine(const utilities::vis_params &input, const utilities::vis_params &input2, const Vector< t_complex > &stokes_transform, const std::function< bool(t_real, t_real, t_real, t_complex, t_complex, t_real, t_real, t_real, t_complex, t_complex)> &filter)
Remove visibilities with zero weighting.
utilities::vis_params read_polarisation_with_flagging(const Vector< t_real > &data, const Matrix< t_real > &coords, const Vector< t_real > &frequencies, const t_uint pol_index1, const t_uint pol_index2, const t_uint pols, const t_uint baselines, const t_uint channels, const Vector< t_complex > stokes_transform, const std::function< bool(t_complex, t_complex, t_complex, t_complex)> &filter)
read polarisation with flaggging
t_real read_value_from_data(const Vector< t_real > &data, const t_uint col, const t_uint pol, const t_uint pols, const t_uint chan, const t_uint chans, const t_uint baseline, const t_uint baselines)
read value from data
t_complex read_weight_from_data(const Vector< t_real > &data, const t_uint pol, const t_uint pols, const t_uint chan, const t_uint chans, const t_uint baseline, const t_uint baselines)
return weight for given baseline
void read_fits_keys(fitsfile *fptr, int *status)
Read uvfits keys out.
Matrix< t_real > read_uvfits_coords(fitsfile *fptr, int *status, const int &groups, const int &pcount)
read coordinates from uvfits file
utilities::vis_params read_uvfits(const std::vector< std::string > &names, const bool flag, const stokes pol)
Read uvfits files from name of vector.
Vector< t_real > read_uvfits_freq(fitsfile *fptr, int *status, const int &col)
read frequencies for each channel
Vector< t_real > read_uvfits_data(fitsfile *fptr, int *status, const std::vector< int > &naxis, const int &baselines)
read data from uvfits file
utilities::vis_params read_polarisation(const Vector< t_real > &data, const Matrix< t_real > &coords, const Vector< t_real > &frequencies, const t_uint pol_index1, const t_uint pols, const t_uint baselines, const t_uint channels)
read polarisation data from uvfits data
t_complex read_vis_from_data(const Vector< t_real > &data, const t_uint pol, const t_uint pols, const t_uint chan, const t_uint chans, const t_uint baseline, const t_uint baselines)
return visibility for given baseline
Vector< t_uint > baseline
t_uint size() const
return number of measurements
Vector< t_complex > weights
Vector< t_real > frequencies