PURIFY
Next-generation radio interferometric imaging
setup_utils.cc
Go to the documentation of this file.
1 #include "purify/setup_utils.h"
2 #include <sopt/differentiable_func.h>
3 #include <sopt/l1_non_diff_function.h>
4 #include <sopt/l2_differentiable_func.h>
5 #include <sopt/non_differentiable_func.h>
6 
7 #ifdef PURIFY_ONNXRT
8 #include <sopt/onnx_differentiable_func.h>
9 #endif
10 
11 #include <sopt/power_method.h>
12 #include <sopt/real_indicator.h>
13 
14 #ifdef PURIFY_ONNXRT
15 #include <sopt/tf_non_diff_function.h>
16 #endif
17 
18 using namespace purify;
19 
21  const factory::distributed_wavelet_operator &wop_algo) {
22  std::vector<std::tuple<std::string, t_uint>> sara;
23  for (size_t i = 0; i < params.wavelet_basis().size(); i++)
24  sara.push_back(std::make_tuple(params.wavelet_basis().at(i), params.wavelet_levels()));
25  t_uint sara_size = 0;
26 #ifdef PURIFY_MPI
27  {
28  auto const world = sopt::mpi::Communicator::World();
29  if (params.mpiAlgorithm() == factory::algo_distribution::mpi_random_updates)
30  sara = sopt::wavelets::distribute_sara(sara, world);
31  }
32 #endif
33  auto const wavelets_transform = factory::wavelet_operator_factory<Vector<t_complex>>(
34  wop_algo, sara, params.height(), params.width(), sara_size);
35  return {wavelets_transform, sara_size};
36 }
37 
43  bool using_mpi = false;
44  if (params.mpiAlgorithm() != factory::algo_distribution::serial) {
45 #ifndef PURIFY_MPI
46  throw std::runtime_error("Compile with MPI if you want to use MPI algorithm");
47 #endif
48  mop_algo = (not params.gpu())
51  if (params.mpi_all_to_all())
52  mop_algo = (not params.gpu())
56  if (params.mpiAlgorithm() == factory::algo_distribution::mpi_random_updates) {
57  mop_algo = (not params.gpu()) ? factory::distributed_measurement_operator::serial
60  }
61  using_mpi = true;
62  }
63  return {mop_algo, wop_algo, using_mpi};
64 }
65 
68  const factory::distributed_wavelet_operator wop_algo, const bool using_mpi) {
69  utilities::vis_params uv_data;
70  bool w_term = params.w_term();
71  t_real sigma;
72  std::vector<t_int> image_index = std::vector<t_int>();
73  std::vector<t_real> w_stacks = std::vector<t_real>();
74 
75  Vector<t_complex> measurement_op_eigen_vector =
76  Vector<t_complex>::Ones(params.width() * params.height());
77  // read eigen vector for power method
78  if (params.eigenvector_real() != "" and params.eigenvector_imag() != "") {
79  t_int rows;
80  t_int cols;
81  t_int pols;
82  t_int chans;
83  Vector<t_real> temp_real;
84  Vector<t_real> temp_imag;
85  pfitsio::read3d(params.eigenvector_real(), temp_real, rows, cols, chans, pols);
86  if (rows != params.height() or cols != params.width() or chans != 1 or pols != 1)
87  throw std::runtime_error("Image of measurement operator eigenvector is wrong size.");
88  pfitsio::read3d(params.eigenvector_imag(), temp_imag, rows, cols, chans, pols);
89  if (rows != params.height() or cols != params.width() or chans != 1 or pols != 1)
90  throw std::runtime_error("Image of measurement operator eigenvector is wrong size.");
91  measurement_op_eigen_vector.real() = temp_real;
92  measurement_op_eigen_vector.imag() = temp_imag;
93  }
94  if (params.source() == purify::utilities::vis_source::measurements) {
95  PURIFY_HIGH_LOG("Input visibilities are from files:");
96  for (size_t i = 0; i < params.measurements().size(); i++)
97  PURIFY_HIGH_LOG("{}", params.measurements()[i]);
98  sigma = params.measurements_sigma();
99 #ifdef PURIFY_MPI
100  if (using_mpi) {
101  auto const world = sopt::mpi::Communicator::World();
102  uv_data = read_measurements::read_measurements(params.measurements(), world,
104  params.measurements_units());
105  const t_real norm =
106  std::sqrt(world.all_sum_all(
107  (uv_data.weights.real().array() * uv_data.weights.real().array()).sum()) /
108  world.all_sum_all(uv_data.size()));
109  // normalise weights
110  uv_data.weights = uv_data.weights / norm;
111  // using no weights for now
112  // uv_data.weights = Vector<t_complex>::Ones(uv_data.size());
113  } else
114 #endif
115  {
116  uv_data = read_measurements::read_measurements(params.measurements(), w_term, stokes::I,
117  params.measurements_units());
118  const t_real norm = std::sqrt(
119  (uv_data.weights.real().array() * uv_data.weights.real().array()).sum() / uv_data.size());
120  // normalising weights
121  uv_data.weights = uv_data.weights / norm;
122  // using no weights for now
123  // uv_data.weights = Vector<t_complex>::Ones(uv_data.size());
124  }
125  if (params.conjugate_w()) uv_data = utilities::conjugate_w(uv_data);
126 #ifdef PURIFY_MPI
127  if (params.mpi_wstacking() and
130  auto const world = sopt::mpi::Communicator::World();
131  const auto cost = [](t_real x) -> t_real { return std::abs(x * x); };
132  const t_real du =
133  widefield::pixel_to_lambda(params.cellsizex(), params.width(), params.oversampling());
134  std::tie(uv_data, image_index, w_stacks) = utilities::w_stacking_with_all_to_all(
135  uv_data, du, params.Jx(), params.Jw(), world, params.kmeans_iters(), 0, cost);
136  } else if (params.mpi_wstacking()) {
137  auto const world = sopt::mpi::Communicator::World();
138  const auto cost = [](t_real x) -> t_real { return std::abs(x * x); };
139  uv_data = utilities::w_stacking(uv_data, world, params.kmeans_iters(), cost);
140  }
141 #endif
142  } else if (params.source() == purify::utilities::vis_source::simulation) {
143  PURIFY_HIGH_LOG("Input visibilities will be generated for random coverage.");
144  // TODO: move this to function (in utilities.h?)
145  auto image = pfitsio::read2d(params.skymodel());
146  if (params.height() != image.rows() || params.width() != image.cols())
147  throw std::runtime_error("Input image size (" + std::to_string(image.cols()) + "x" +
148  std::to_string(image.rows()) + ") is not equal to the input one (" +
149  std::to_string(params.width()) + "x" +
150  std::to_string(params.height()) + ").");
151  t_int const number_of_pixels = image.size();
152  t_int const number_of_vis = params.number_of_measurements();
153  t_real const sigma_m = constant::pi / 4;
154  const t_real rms_w = params.w_rms(); // lambda
155  if (params.measurements().at(0) == "") {
156  uv_data = utilities::random_sample_density(number_of_vis, 0, sigma_m, rms_w);
158  uv_data.weights = Vector<t_complex>::Ones(uv_data.size());
159  } else {
160 #ifdef PURIFY_MPI
161  if (using_mpi) {
162  auto const world = sopt::mpi::Communicator::World();
163  uv_data = read_measurements::read_measurements(params.measurements(), world,
165  params.measurements_units());
166  } else
167 #endif
168  uv_data = read_measurements::read_measurements(params.measurements(), w_term, stokes::I,
169  params.measurements_units());
170  uv_data.weights = Vector<t_complex>::Ones(uv_data.weights.size());
171  }
172  if (params.conjugate_w()) uv_data = utilities::conjugate_w(uv_data);
173 #ifdef PURIFY_MPI
174  if (params.mpi_wstacking() and
177  auto const world = sopt::mpi::Communicator::World();
178  const auto cost = [](t_real x) -> t_real { return std::abs(x * x); };
179  const t_real du =
180  widefield::pixel_to_lambda(params.cellsizex(), params.width(), params.oversampling());
181  std::tie(uv_data, image_index, w_stacks) = utilities::w_stacking_with_all_to_all(
182  uv_data, du, params.Jx(), params.Jw(), world, params.kmeans_iters(), 0, cost);
183  } else if (params.mpi_wstacking()) {
184  auto const world = sopt::mpi::Communicator::World();
185  const auto cost = [](t_real x) -> t_real { return std::abs(x * x); };
186  uv_data = utilities::w_stacking(uv_data, world, params.kmeans_iters(), cost);
187  }
188 #endif
189  std::shared_ptr<sopt::LinearTransform<Vector<t_complex>>> sky_measurements;
192  sky_measurements =
193  (not params.wprojection())
194  ? factory::measurement_operator_factory<Vector<t_complex>>(
195  mop_algo, uv_data, params.height(), params.width(), params.cellsizey(),
196  params.cellsizex(), params.oversampling(),
197  kernels::kernel_from_string.at(params.kernel()), params.sim_J(), params.sim_J(),
198  params.mpi_wstacking())
199  : factory::measurement_operator_factory<Vector<t_complex>>(
200  mop_algo, uv_data, params.height(), params.width(), params.cellsizey(),
201  params.cellsizex(), params.oversampling(),
202  kernels::kernel_from_string.at(params.kernel()), params.sim_J(), params.Jw(),
203  params.mpi_wstacking(), 1e-6, 1e-6, dde_type::wkernel_radial);
204  else
205  sky_measurements =
206  (not params.wprojection())
208  mop_algo, image_index, w_stacks, uv_data, params.height(), params.width(),
209  params.cellsizey(), params.cellsizex(), params.oversampling(),
210  kernels::kernel_from_string.at(params.kernel()), params.sim_J(), params.sim_J(),
211  params.mpi_wstacking())
213  mop_algo, image_index, w_stacks, uv_data, params.height(), params.width(),
214  params.cellsizey(), params.cellsizex(), params.oversampling(),
215  kernels::kernel_from_string.at(params.kernel()), params.sim_J(), params.Jw(),
216  params.mpi_wstacking(), 1e-6, 1e-6, dde_type::wkernel_radial);
217  uv_data.vis =
218  ((*sky_measurements) * Vector<t_complex>::Map(image.data(), image.size())).eval().array();
219  sigma = utilities::SNR_to_standard_deviation(uv_data.vis, params.signal_to_noise());
220  uv_data.vis = utilities::add_noise(uv_data.vis, 0., sigma);
221  }
222  t_real ideal_cell_x = widefield::estimate_cell_size(uv_data.u.cwiseAbs().maxCoeff(),
223  params.width(), params.oversampling());
224  t_real ideal_cell_y = widefield::estimate_cell_size(uv_data.v.cwiseAbs().maxCoeff(),
225  params.height(), params.oversampling());
226 #ifdef PURIFY_MPI
227  if (using_mpi) {
228  auto const comm = sopt::mpi::Communicator::World();
229  ideal_cell_x = widefield::estimate_cell_size(
230  comm.all_reduce<t_real>(uv_data.u.cwiseAbs().maxCoeff(), MPI_MAX), params.width(),
231  params.oversampling());
232  ideal_cell_y = widefield::estimate_cell_size(
233  comm.all_reduce<t_real>(uv_data.v.cwiseAbs().maxCoeff(), MPI_MAX), params.height(),
234  params.oversampling());
235  }
236 #endif
238  "Using cell size {}\" x {}\", recommended from the uv coverage and field of view is "
239  "{}\"x{}\".",
240  params.cellsizey(), params.cellsizex(), ideal_cell_y, ideal_cell_x);
241  PURIFY_HIGH_LOG("The equivalent miriad cell size is: {}\" x {}\"",
242  widefield::equivalent_miriad_cell_size(params.cellsizex(), params.width(),
243  params.oversampling()),
244  widefield::equivalent_miriad_cell_size(params.cellsizey(), params.height(),
245  params.oversampling()));
246 
247  return {uv_data, sigma, measurement_op_eigen_vector, image_index, w_stacks};
248 }
249 
250 std::shared_ptr<sopt::LinearTransform<Vector<t_complex>>> createMeasurementOperator(
251  const YamlParser &params, const factory::distributed_measurement_operator mop_algo,
252  const factory::distributed_wavelet_operator wop_algo, const bool using_mpi,
253  const std::vector<t_int> &image_index, const std::vector<t_real> &w_stacks,
254  const utilities::vis_params &uv_data, Vector<t_complex> &measurement_op_eigen_vector) {
255  std::shared_ptr<sopt::LinearTransform<Vector<t_complex>>> measurements_transform;
258  measurements_transform =
259  (not params.wprojection())
260  ? factory::measurement_operator_factory<Vector<t_complex>>(
261  mop_algo, uv_data, params.height(), params.width(), params.cellsizey(),
262  params.cellsizex(), params.oversampling(),
263  kernels::kernel_from_string.at(params.kernel()), params.Jy(), params.Jx(),
264  params.mpi_wstacking())
265  : factory::measurement_operator_factory<Vector<t_complex>>(
266  mop_algo, uv_data, params.height(), params.width(), params.cellsizey(),
267  params.cellsizex(), params.oversampling(),
268  kernels::kernel_from_string.at(params.kernel()), params.Jy(), params.Jw(),
269  params.mpi_wstacking(), 1e-6, 1e-6, dde_type::wkernel_radial);
270  else
271  measurements_transform =
272  (not params.wprojection())
274  mop_algo, image_index, w_stacks, uv_data, params.height(), params.width(),
275  params.cellsizey(), params.cellsizex(), params.oversampling(),
276  kernels::kernel_from_string.at(params.kernel()), params.Jy(), params.Jx(),
277  params.mpi_wstacking())
279  mop_algo, image_index, w_stacks, uv_data, params.height(), params.width(),
280  params.cellsizey(), params.cellsizex(), params.oversampling(),
281  kernels::kernel_from_string.at(params.kernel()), params.Jy(), params.Jw(),
282  params.mpi_wstacking(), 1e-6, 1e-6, dde_type::wkernel_radial);
283  t_real operator_norm = 1.;
284 #ifdef PURIFY_MPI
285  if (using_mpi) {
286  auto const comm = sopt::mpi::Communicator::World();
287  auto power_method_result =
288  (params.mpiAlgorithm() != factory::algo_distribution::mpi_random_updates)
289  ? sopt::algorithm::power_method<Vector<t_complex>>(
290  *measurements_transform, params.powMethod_iter(), params.powMethod_tolerance(),
291  comm.broadcast(measurement_op_eigen_vector).eval())
292  : sopt::algorithm::all_sum_all_power_method<Vector<t_complex>>(
293  comm, *measurements_transform, params.powMethod_iter(),
294  params.powMethod_tolerance(), comm.broadcast(measurement_op_eigen_vector).eval());
295  measurement_op_eigen_vector = std::get<1>(power_method_result);
296  operator_norm = std::get<0>(power_method_result);
297  measurements_transform->set_norm(operator_norm);
298  } else
299 #endif
300  {
301  auto power_method_result = sopt::algorithm::power_method<Vector<t_complex>>(
302  *measurements_transform, params.powMethod_iter(), params.powMethod_tolerance(),
303  measurement_op_eigen_vector);
304  measurement_op_eigen_vector = std::get<1>(power_method_result);
305  operator_norm = std::get<0>(power_method_result);
306  measurements_transform->set_norm(operator_norm);
307  }
308 
309  return measurements_transform;
310 }
311 
312 void setupCostFunctions(const YamlParser &params, std::unique_ptr<DifferentiableFunc<t_complex>> &f,
313  std::unique_ptr<NonDifferentiableFunc<t_complex>> &g, t_real sigma,
314  sopt::LinearTransform<Vector<t_complex>> &Phi) {
315  switch (params.diffFuncType()) {
317  f = std::make_unique<sopt::L2DifferentiableFunc<t_complex>>(sigma, Phi);
318  break;
320 #ifdef PURIFY_ONNXRT
321  f = std::make_unique<sopt::ONNXDifferentiableFunc<t_complex>>(
322  params.CRR_function_model_path(), params.CRR_gradient_model_path(), sigma, params.CRR_mu(),
323  params.CRR_lambda(), Phi);
324 #else
325  throw std::runtime_error(
326  "To use the CRR you must compile with ONNX runtime turned on. (-Donnxrt=on)");
327 #endif
328  break;
329  }
330 
331  switch (params.nondiffFuncType()) {
333  g = std::make_unique<sopt::algorithm::L1GProximal<t_complex>>();
334  break;
336 #ifdef PURIFY_ONNXRT
337  g = std::make_unique<sopt::algorithm::TFGProximal<t_complex>>(params.model_path());
338  break;
339 #else
340  throw std::runtime_error(
341  "To use the Denoiser you must compile with ONNX runtime turned on. (-Donnxrt=on)");
342 #endif
343 
345  g = std::make_unique<sopt::algorithm::RealIndicator<t_complex>>();
346  break;
347  }
348 }
349 
351  if (params.mpiAlgorithm() != factory::algo_distribution::serial) {
352 #ifdef PURIFY_MPI
353  auto const world = sopt::mpi::Communicator::World();
354  if (world.is_root())
355 #else
356  throw std::runtime_error("Compile with MPI if you want to use MPI algorithm");
357 #endif
358  params.writeOutput();
359  } else {
360  params.writeOutput();
361  }
362 }
363 
364 Headers genHeaders(const YamlParser &params, const utilities::vis_params &uv_data) {
365  const pfitsio::header_params update_header_sol =
366  pfitsio::header_params(params.output_path() + "/sol_update.fits", "Jy/Pixel", 1, uv_data.ra,
367  uv_data.dec, params.measurements_polarization(), params.cellsizex(),
368  params.cellsizey(), uv_data.average_frequency, 0, 0, false, 0, 0, 0);
369  const pfitsio::header_params update_header_res =
370  pfitsio::header_params(params.output_path() + "/res_update.fits", "Jy/Beam", 1, uv_data.ra,
371  uv_data.dec, params.measurements_polarization(), params.cellsizex(),
372  params.cellsizey(), uv_data.average_frequency, 0, 0, false, 0, 0, 0);
374  "", "Jy/Pixel", 1, uv_data.ra, uv_data.dec, params.measurements_polarization(),
375  params.cellsizex(), params.cellsizey(), uv_data.average_frequency, 0, 0, false, 0, 0, 0);
376 
377  return {update_header_sol, update_header_res, def_header};
378 }
379 
381  const Vector<t_complex> &measurement_op_eigen_vector) {
382  if (params.mpiAlgorithm() != factory::algo_distribution::serial) {
383 #ifdef PURIFY_MPI
384  auto const world = sopt::mpi::Communicator::World();
385  if (world.is_root())
386 #else
387  throw std::runtime_error("Compile with MPI if you want to use MPI algorithm");
388 #endif
389  {
390  pfitsio::write2d(measurement_op_eigen_vector.real(), params.height(), params.width(),
391  params.output_path() + "/eigenvector_real.fits", "pix", true);
392  pfitsio::write2d(measurement_op_eigen_vector.imag(), params.height(), params.width(),
393  params.output_path() + "/eigenvector_imag.fits", "pix", true);
394  }
395  } else {
396  pfitsio::write2d(measurement_op_eigen_vector.real(), params.height(), params.width(),
397  params.output_path() + "/eigenvector_real.fits", "pix", true);
398  pfitsio::write2d(measurement_op_eigen_vector.imag(), params.height(), params.width(),
399  params.output_path() + "/eigenvector_imag.fits", "pix", true);
400  }
401 }
402 
403 void savePSF(
404  const YamlParser &params, const pfitsio::header_params &def_header,
405  const std::shared_ptr<sopt::LinearTransform<Vector<t_complex>>> &measurements_transform,
406  const utilities::vis_params &uv_data, const t_real flux_scale, const t_real sigma,
407  const t_real beam_units) {
408  pfitsio::header_params psf_header = def_header;
409  psf_header.fits_name = params.output_path() + "/psf.fits";
410  psf_header.pix_units = "Jy/Pixel";
411  const Vector<t_complex> psf = measurements_transform->adjoint() * (uv_data.weights / flux_scale);
412  const Image<t_real> psf_image =
413  Image<t_complex>::Map(psf.data(), params.height(), params.width()).real();
415  "Peak of PSF: {} (used to convert between Jy/Pixel and Jy/BEAM)",
416  psf_image(static_cast<t_int>(params.width() * 0.5 + params.height() * 0.5 * params.width())));
417  if (params.mpiAlgorithm() != factory::algo_distribution::serial) {
418 #ifdef PURIFY_MPI
419  auto const world = sopt::mpi::Communicator::World();
421  "Expected image domain residual RMS is {} jy/beam",
422  sigma * params.epsilonScaling() * measurements_transform->norm() /
423  (std::sqrt(params.width() * params.height()) * world.all_sum_all(uv_data.size())));
424  if (world.is_root())
425 #else
426  throw std::runtime_error("Compile with MPI if you want to use MPI algorithm");
427 #endif
428  pfitsio::write2d(psf_image, psf_header, true);
429  } else {
430  PURIFY_LOW_LOG("Expected image domain residual RMS is {} jy/beam",
431  sigma * params.epsilonScaling() * measurements_transform->norm() /
432  (std::sqrt(params.width() * params.height()) * uv_data.size()));
433  pfitsio::write2d(psf_image, psf_header, true);
434  }
436  "Theoretical calculation for peak PSF: {} (used to convert between Jy/Pixel and Jy/BEAM)",
437  beam_units);
438  PURIFY_HIGH_LOG("Effective sigma is {} Jy", sigma * params.epsilonScaling());
439 }
440 
442  const YamlParser &params, const pfitsio::header_params &def_header,
443  const std::shared_ptr<sopt::LinearTransform<Vector<t_complex>>> &measurements_transform,
444  const utilities::vis_params &uv_data, const t_real beam_units) {
445  pfitsio::header_params dirty_header = def_header;
446  dirty_header.fits_name = params.output_path() + "/dirty.fits";
447  dirty_header.pix_units = "Jy/Beam";
448  const Vector<t_complex> dimage = measurements_transform->adjoint() * uv_data.vis;
449  const Image<t_real> dirty_image =
450  Image<t_complex>::Map(dimage.data(), params.height(), params.width()).real();
451  if (params.mpiAlgorithm() != factory::algo_distribution::serial) {
452 #ifdef PURIFY_MPI
453  auto const world = sopt::mpi::Communicator::World();
454  if (world.is_root())
455 #else
456  throw std::runtime_error("Compile with MPI if you want to use MPI algorithm");
457 #endif
458  pfitsio::write2d(dirty_image / beam_units, dirty_header, true);
459  } else {
460  pfitsio::write2d(dirty_image / beam_units, dirty_header, true);
461  }
462 }
std::string output_path() const
Definition: yaml-parser.h:152
#define PURIFY_LOW_LOG(...)
Low priority message.
Definition: logging.h:207
#define PURIFY_HIGH_LOG(...)
High priority message.
Definition: logging.h:203
const t_real pi
mathematical constant
Definition: types.h:70
distributed_measurement_operator
determine type of distribute for mpi measurement operator
std::shared_ptr< sopt::LinearTransform< T > > measurement_operator_factory(const distributed_measurement_operator distribute, ARGS &&...args)
distributed measurement operator factory
std::shared_ptr< sopt::LinearTransform< T > > all_to_all_measurement_operator_factory(const distributed_measurement_operator distribute, const std::vector< t_int > &image_stacks, const std::vector< t_real > &w_stacks, ARGS &&...args)
distributed measurement operator factory
const std::map< std::string, kernel > kernel_from_string
Definition: kernels.h:16
void write2d(const Image< t_real > &eigen_image, const pfitsio::header_params &header, const bool &overwrite)
Write image to fits file.
Definition: pfitsio.cc:30
Image< t_complex > read2d(const std::string &fits_name)
Read image from fits file.
Definition: pfitsio.cc:109
std::vector< Image< t_complex > > read3d(const std::string &fits_name)
Read cube from fits file.
Definition: pfitsio.cc:95
utilities::vis_params read_measurements(const std::string &name, const bool w_term, const stokes pol, const utilities::vis_units units)
read in single measurement file
utilities::vis_params w_stacking(utilities::vis_params const &params, sopt::mpi::Communicator const &comm, const t_int iters, const std::function< t_real(t_real)> &cost, const t_real k_means_rel_diff)
t_real SNR_to_standard_deviation(const Vector< t_complex > &y0, const t_real &SNR)
Converts SNR to RMS noise.
Definition: utilities.cc:101
Vector< t_complex > add_noise(const Vector< t_complex > &y0, const t_complex &mean, const t_real &standard_deviation)
Add guassian noise to vector.
Definition: utilities.cc:113
utilities::vis_params conjugate_w(const utilities::vis_params &uv_vis)
reflects visibilities into the w >= 0 domain
std::tuple< utilities::vis_params, std::vector< t_int >, std::vector< t_real > > w_stacking_with_all_to_all(utilities::vis_params const &params, const t_real du, const t_int min_support, const t_int max_support, sopt::mpi::Communicator const &comm, const t_int iters, const t_real fill_relaxation, const std::function< t_real(t_real)> &cost, const t_real k_means_rel_diff)
utilities::vis_params random_sample_density(const t_int vis_num, const t_real mean, const t_real standard_deviation, const t_real rms_w)
Generates a random visibility coverage.
t_real equivalent_miriad_cell_size(const t_real cell, const t_uint imsize, const t_real oversample_ratio)
for a given purify cell size in arcsec provide the equivalent miriad cell size in arcsec
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
t_real estimate_cell_size(const t_real max_u, const t_uint imsize, const t_real oversample_ratio)
return cell size from the bandwidth
void saveMeasurementEigenVector(const YamlParser &params, const Vector< t_complex > &measurement_op_eigen_vector)
Definition: setup_utils.cc:380
void saveDirtyImage(const YamlParser &params, const pfitsio::header_params &def_header, const std::shared_ptr< sopt::LinearTransform< Vector< t_complex >>> &measurements_transform, const utilities::vis_params &uv_data, const t_real beam_units)
Definition: setup_utils.cc:441
void savePSF(const YamlParser &params, const pfitsio::header_params &def_header, const std::shared_ptr< sopt::LinearTransform< Vector< t_complex >>> &measurements_transform, const utilities::vis_params &uv_data, const t_real flux_scale, const t_real sigma, const t_real beam_units)
Definition: setup_utils.cc:403
std::shared_ptr< sopt::LinearTransform< Vector< t_complex > > > createMeasurementOperator(const YamlParser &params, const factory::distributed_measurement_operator mop_algo, const factory::distributed_wavelet_operator wop_algo, const bool using_mpi, const std::vector< t_int > &image_index, const std::vector< t_real > &w_stacks, const utilities::vis_params &uv_data, Vector< t_complex > &measurement_op_eigen_vector)
Definition: setup_utils.cc:250
waveletInfo createWaveletOperator(YamlParser &params, const factory::distributed_wavelet_operator &wop_algo)
Definition: setup_utils.cc:20
OperatorsInfo selectOperators(YamlParser &params)
Definition: setup_utils.cc:38
void initOutDirectoryWithConfig(YamlParser &params)
Definition: setup_utils.cc:350
Headers genHeaders(const YamlParser &params, const utilities::vis_params &uv_data)
Definition: setup_utils.cc:364
inputData getInputData(const YamlParser &params, const factory::distributed_measurement_operator mop_algo, const factory::distributed_wavelet_operator wop_algo, const bool using_mpi)
Definition: setup_utils.cc:66
void setupCostFunctions(const YamlParser &params, std::unique_ptr< DifferentiableFunc< t_complex >> &f, std::unique_ptr< NonDifferentiableFunc< t_complex >> &g, t_real sigma, sopt::LinearTransform< Vector< t_complex >> &Phi)
Definition: setup_utils.cc:312
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