PURIFY
Next-generation radio interferometric imaging
wproj_operators.cc
Go to the documentation of this file.
2 #include "purify/operators.h"
5 
6 namespace purify {
7 
8 namespace details {
9 
10 Sparse<t_complex> init_gridding_matrix_2d(const Vector<t_real> &u, const Vector<t_real> &v,
11  const Vector<t_real> &w, const Vector<t_complex> &weights,
12  const t_uint imsizey_, const t_uint imsizex_,
13  const t_real oversample_ratio,
14  const std::function<t_real(t_real)> &ftkerneluv,
15  const std::function<t_real(t_real)> &kerneluv,
16  const t_uint Ju, const t_uint Jw, const t_real cellx,
17  const t_real celly, const t_real abs_error,
18  const t_real rel_error, const dde_type dde) {
19  const t_uint ftsizev_ = std::floor(imsizey_ * oversample_ratio);
20  const t_uint ftsizeu_ = std::floor(imsizex_ * oversample_ratio);
21  const t_real du = widefield::pixel_to_lambda(cellx, imsizex_, oversample_ratio);
22  const t_real dv = widefield::pixel_to_lambda(celly, imsizey_, oversample_ratio);
23  PURIFY_HIGH_LOG("du x du: {}, {}", du, dv);
24  if (std::abs(du - dv) > 1e-6)
25  throw std::runtime_error(
26  "Field of view along l and m is not the same, this assumption is required for "
27  "w-projection.");
28  const t_uint rows = u.size();
29  const t_uint cols = ftsizeu_ * ftsizev_;
30  if (u.size() != v.size())
31  throw std::runtime_error(
32  "Size of u and v vectors are not the same for creating gridding matrix.");
33  if (u.size() != w.size())
34  throw std::runtime_error(
35  "Size of u and w vectors are not the same for creating gridding matrix.");
36  if (u.size() != weights.size())
37  throw std::runtime_error(
38  "Size of u and w vectors are not the same for creating gridding matrix.");
39  if (Ju > Jw)
40  throw std::runtime_error(
41  "w kernel size must be at least the size of w=0 kernel, must have Ju <= Jw.");
42  // count gridding coefficients with variable support size
43  Vector<t_int> total_coeffs = Vector<t_int>::Zero(w.size());
44  for (int i = 0; i < w.size(); i++) {
45  const t_int Ju_max =
46  widefield::w_support(w(i), du, static_cast<t_int>(Ju), static_cast<t_int>(Jw));
47  total_coeffs(i) = Ju_max * Ju_max;
48  }
49  const t_real num_of_coeffs = total_coeffs.array().cast<t_real>().sum();
50  PURIFY_HIGH_LOG("Using {} rows (coefficients per a row {}), and memory of {} MegaBytes",
51  total_coeffs.size(), total_coeffs.array().cast<t_real>().mean(),
52  16. * num_of_coeffs / std::pow(10., 6));
53  Sparse<t_complex> interpolation_matrix(rows, cols);
54  try {
55  interpolation_matrix.reserve(total_coeffs);
56  } catch (std::bad_alloc e) {
57  throw std::runtime_error(
58  "Not enough memory for coefficients, choose upper limit on support size Jw.");
59  }
60 
61  const t_complex I(0., 1.);
62 
63  const t_uint max_evaluations = 1e8;
64  const t_real relative_error = rel_error;
65  const t_real absolute_error = abs_error;
66 
67  auto const ftkernel_radial = [&](const t_real l) -> t_real { return ftkerneluv(l); };
68 
69  t_int coeffs_done = 0;
70  t_uint total = 0;
71 
72 #pragma omp parallel for
73  for (t_int m = 0; m < rows; ++m) {
74  // w_projection convolution setup
75  const t_int Ju_max = widefield::w_support(w(m), du, Ju, Jw);
76  t_uint evaluations = 0;
77  const t_int kwu = std::floor(u(m) - Ju_max * 0.5);
78  const t_int kwv = std::floor(v(m) - Ju_max * 0.5);
79  const t_real w_val = w(m); //((0. < w(m)) ? 1: -1) * std::min(Ju_max * du, std::abs(w(m)));
80 
81  for (t_int ju = 1; ju < Ju_max + 1; ++ju) {
82  for (t_int jv = 1; jv < Ju_max + 1; ++jv) {
83  const t_uint q = utilities::mod(kwu + ju, ftsizeu_);
84  const t_uint p = utilities::mod(kwv + jv, ftsizev_);
85  const t_uint index = utilities::sub2ind(p, q, ftsizev_, ftsizeu_);
86  interpolation_matrix.insert(m, index) =
87  std::exp(-2 * constant::pi * I * ((kwu + ju) * 0.5 + (kwv + jv) * 0.5)) * weights(m) *
88  ((dde == dde_type::wkernel_radial)
90  (u(m) - (kwu + ju)), (v(m) - (kwv + jv)), w_val, du, oversample_ratio,
91  ftkernel_radial, max_evaluations, absolute_error, relative_error,
92  (du > 1.) ? integration::method::p : integration::method::h, evaluations)
94  (u(m) - (kwu + ju)), (v(m) - (kwv + jv)), w_val, du, dv, oversample_ratio,
95  ftkernel_radial, ftkernel_radial, max_evaluations, absolute_error,
96  relative_error, integration::method::h, evaluations));
97 #pragma omp critical(add_eval)
98  {
99  coeffs_done++;
100  if (num_of_coeffs > 100) {
101  if ((coeffs_done % (static_cast<t_int>(num_of_coeffs / 100)) == 0)) {
103  "w = {}, support = {}x{}, coeffs: {} of {}, {}%", w_val, Ju_max, Ju_max,
104  coeffs_done, num_of_coeffs,
105  static_cast<t_real>(coeffs_done) / static_cast<t_real>(num_of_coeffs) * 100.);
106  }
107  }
108  }
109  }
110  }
111  }
112  interpolation_matrix.makeCompressed();
113  return interpolation_matrix;
114 }
115 
116 Image<t_complex> init_correction_radial_2d(const t_real oversample_ratio, const t_uint imsizey_,
117  const t_uint imsizex_,
118  const std::function<t_real(t_real)> &ftkerneluv,
119  const t_real w_mean, const t_real cellx,
120  const t_real celly) {
121  const t_uint ftsizeu_ = std::floor(imsizex_ * oversample_ratio);
122  const t_uint ftsizev_ = std::floor(imsizey_ * oversample_ratio);
123  const t_uint x_start = std::floor(ftsizeu_ * 0.5 - imsizex_ * 0.5);
124  const t_uint y_start = std::floor(ftsizev_ * 0.5 - imsizey_ * 0.5);
125 
126  Image<t_complex> gridding_correction = Image<t_complex>::Zero(imsizey_, imsizex_);
127  for (int i = 0; i < gridding_correction.rows(); i++)
128  for (int j = 0; j < gridding_correction.cols(); j++)
129  gridding_correction(i, j) =
130  1. / ftkerneluv(std::sqrt(std::pow((y_start + i + 0.5) / ftsizev_ - 0.5, 2) +
131  std::pow((j + 0.5 + x_start) / ftsizeu_ - 0.5, 2)));
132 
133  return gridding_correction.array() *
134  widefield::generate_chirp(w_mean, cellx, celly, imsizex_, imsizey_).array() * imsizex_ *
135  imsizey_;
136 }
137 
138 } // namespace details
139 
140 } // namespace purify
#define PURIFY_LOW_LOG(...)
Low priority message.
Definition: logging.h:207
#define PURIFY_HIGH_LOG(...)
High priority message.
Definition: logging.h:203
const std::vector< t_real > u
data for u coordinate
Definition: operators.cc:18
const std::vector< t_real > v
data for v coordinate
Definition: operators.cc:20
const t_real pi
mathematical constant
Definition: types.h:70
Image< t_complex > init_correction_radial_2d(const t_real oversample_ratio, const t_uint imsizey_, const t_uint imsizex_, const std::function< t_real(t_real)> &ftkerneluv, const t_real w_mean, const t_real cellx, const t_real celly)
Sparse< t_complex > init_gridding_matrix_2d(const Vector< t_real > &u, const Vector< t_real > &v, const Vector< t_complex > &weights, const t_uint &imsizey_, const t_uint &imsizex_, const t_real &oversample_ratio, const std::function< t_real(t_real)> kernelu, const std::function< t_real(t_real)> kernelv, const t_uint Ju, const t_uint Jv)
Construct gridding matrix.
Definition: operators.cc:7
t_complex exact_w_projection_integration_1d(const t_real u, const t_real v, const t_real w, const t_real du, const t_real oversample_ratio, const std::function< t_complex(t_real)> &ftkerneluv, const t_uint &max_evaluations, const t_real &absolute_error, const t_real &relative_error, const integration::method method, t_uint &evaluations)
t_complex exact_w_projection_integration(const t_real u, const t_real v, const t_real w, const t_real du, const t_real dv, const t_real oversample_ratio, const std::function< t_complex(t_real)> &ftkernelu, const std::function< t_complex(t_real)> &ftkernelv, const t_uint &max_evaluations, const t_real &absolute_error, const t_real &relative_error, const integration::method method, t_uint &evaluations)
numerical integration of chirp and kernel in image domain
t_int sub2ind(const t_int &row, const t_int &col, const t_int &rows, const t_int &cols)
Converts from subscript to index for matrix.
Definition: utilities.cc:12
t_real mod(const t_real &x, const t_real &y)
Mod function modified to wrap circularly for negative numbers.
Definition: utilities.cc:41
t_int w_support(const t_real w, const t_real du, const t_int min, const t_int max)
estimate support size of w given u resolution du
t_real pixel_to_lambda(const t_real cell, const t_uint imsize, const t_real oversample_ratio)
return factors to convert between arcsecond pixel size image space and lambda for uv space
Matrix< t_complex > generate_chirp(const t_real w_rate, const t_real cell_x, const t_real cell_y, const t_uint x_size, const t_uint y_size)
Generates image of chirp.
dde_type
Types of DDEs in purify.
Definition: types.h:59
Eigen::SparseMatrix< T, Eigen::RowMajor, I > Sparse
A matrix of a given type.
Definition: types.h:40