PURIFY
Next-generation radio interferometric imaging
Classes | Functions
setup_utils.h File Reference
#include "purify/types.h"
#include "purify/logging.h"
#include "purify/measurement_operator_factory.h"
#include "purify/pfitsio.h"
#include "purify/read_measurements.h"
#include "purify/wavelet_operator_factory.h"
#include "purify/yaml-parser.h"
#include <sopt/differentiable_func.h>
#include <sopt/non_differentiable_func.h>
+ Include dependency graph for setup_utils.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  waveletInfo
 
struct  OperatorsInfo
 
struct  inputData
 
struct  Headers
 

Functions

waveletInfo createWaveletOperator (YamlParser &params, const factory::distributed_wavelet_operator &wop_algo)
 
OperatorsInfo selectOperators (YamlParser &params)
 
inputData getInputData (const YamlParser &params, const factory::distributed_measurement_operator mop_algo, const factory::distributed_wavelet_operator wop_algo, const bool using_mpi)
 
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)
 
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)
 
void initOutDirectoryWithConfig (YamlParser &params)
 
Headers genHeaders (const YamlParser &params, const utilities::vis_params &uv_data)
 
void saveMeasurementEigenVector (const YamlParser &params, const Vector< t_complex > &measurement_op_eigen_vector)
 
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)
 
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)
 

Function Documentation

◆ createMeasurementOperator()

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 at line 250 of file setup_utils.cc.

254  {
255  std::shared_ptr<sopt::LinearTransform<Vector<t_complex>>> measurements_transform;
256  if (mop_algo != factory::distributed_measurement_operator::mpi_distribute_all_to_all and
257  mop_algo != factory::distributed_measurement_operator::gpu_mpi_distribute_all_to_all)
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 }
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

References purify::factory::all_to_all_measurement_operator_factory(), purify::factory::gpu_mpi_distribute_all_to_all, purify::kernels::kernel_from_string, purify::factory::measurement_operator_factory(), purify::factory::mpi_distribute_all_to_all, purify::factory::mpi_random_updates, and purify::wkernel_radial.

Referenced by main().

◆ createWaveletOperator()

waveletInfo createWaveletOperator ( YamlParser params,
const factory::distributed_wavelet_operator wop_algo 
)

Definition at line 20 of file setup_utils.cc.

21  {
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 }

References purify::factory::mpi_random_updates.

Referenced by main().

◆ genHeaders()

Headers genHeaders ( const YamlParser params,
const utilities::vis_params uv_data 
)

Definition at line 364 of file setup_utils.cc.

364  {
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 }
std::string output_path() const
Definition: yaml-parser.h:152

References purify::utilities::vis_params::average_frequency, purify::utilities::vis_params::dec, purify::YamlParser::output_path(), and purify::utilities::vis_params::ra.

Referenced by main().

◆ getInputData()

inputData getInputData ( const YamlParser params,
const factory::distributed_measurement_operator  mop_algo,
const factory::distributed_wavelet_operator  wop_algo,
const bool  using_mpi 
)

Definition at line 66 of file setup_utils.cc.

68  {
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,
103  distribute::plan::radial, w_term, stokes::I,
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
128  (mop_algo == factory::distributed_measurement_operator::mpi_distribute_all_to_all or
129  mop_algo == factory::distributed_measurement_operator::gpu_mpi_distribute_all_to_all)) {
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);
157  uv_data.units = utilities::vis_units::radians;
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,
164  distribute::plan::radial, w_term, stokes::I,
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
175  (mop_algo == factory::distributed_measurement_operator::mpi_distribute_all_to_all or
176  mop_algo == factory::distributed_measurement_operator::gpu_mpi_distribute_all_to_all)) {
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;
190  if (mop_algo != factory::distributed_measurement_operator::mpi_distribute_all_to_all and
191  mop_algo != factory::distributed_measurement_operator::gpu_mpi_distribute_all_to_all)
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 }
#define PURIFY_HIGH_LOG(...)
High priority message.
Definition: logging.h:203
const t_real pi
mathematical constant
Definition: types.h:70
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
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

References purify::utilities::add_noise(), purify::factory::all_to_all_measurement_operator_factory(), purify::utilities::conjugate_w(), purify::widefield::equivalent_miriad_cell_size(), purify::widefield::estimate_cell_size(), purify::factory::gpu_mpi_distribute_all_to_all, purify::I, purify::kernels::kernel_from_string, purify::factory::measurement_operator_factory(), purify::utilities::measurements, purify::factory::mpi_distribute_all_to_all, purify::constant::pi, purify::widefield::pixel_to_lambda(), PURIFY_HIGH_LOG, purify::distribute::radial, purify::utilities::radians, purify::utilities::random_sample_density(), purify::pfitsio::read2d(), purify::pfitsio::read3d(), purify::read_measurements::read_measurements(), purify::utilities::simulation, purify::utilities::vis_params::size(), purify::utilities::SNR_to_standard_deviation(), purify::utilities::vis_params::u, purify::utilities::vis_params::units, purify::utilities::vis_params::v, purify::utilities::vis_params::vis, purify::utilities::w_stacking(), purify::utilities::w_stacking_with_all_to_all(), purify::utilities::vis_params::weights, and purify::wkernel_radial.

Referenced by main().

◆ initOutDirectoryWithConfig()

void initOutDirectoryWithConfig ( YamlParser params)

Definition at line 350 of file setup_utils.cc.

350  {
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 }

References purify::factory::serial, and purify::YamlParser::writeOutput().

Referenced by main().

◆ saveDirtyImage()

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 at line 441 of file setup_utils.cc.

444  {
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 }
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

References purify::pfitsio::header_params::fits_name, purify::YamlParser::output_path(), purify::pfitsio::header_params::pix_units, purify::factory::serial, purify::utilities::vis_params::vis, and purify::pfitsio::write2d().

Referenced by main().

◆ saveMeasurementEigenVector()

void saveMeasurementEigenVector ( const YamlParser params,
const Vector< t_complex > &  measurement_op_eigen_vector 
)

Definition at line 380 of file setup_utils.cc.

381  {
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 }

References purify::YamlParser::output_path(), purify::factory::serial, and purify::pfitsio::write2d().

Referenced by main().

◆ savePSF()

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 at line 403 of file setup_utils.cc.

407  {
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 }
#define PURIFY_LOW_LOG(...)
Low priority message.
Definition: logging.h:207

References purify::pfitsio::header_params::fits_name, purify::YamlParser::output_path(), purify::pfitsio::header_params::pix_units, PURIFY_HIGH_LOG, PURIFY_LOW_LOG, purify::factory::serial, purify::utilities::vis_params::size(), purify::utilities::vis_params::weights, and purify::pfitsio::write2d().

Referenced by main().

◆ selectOperators()

OperatorsInfo selectOperators ( YamlParser params)

Definition at line 38 of file setup_utils.cc.

38  {
40  (not params.gpu()) ? factory::distributed_measurement_operator::serial
41  : factory::distributed_measurement_operator::gpu_serial;
42  factory::distributed_wavelet_operator wop_algo = factory::distributed_wavelet_operator::serial;
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())
49  ? factory::distributed_measurement_operator::mpi_distribute_image
50  : factory::distributed_measurement_operator::gpu_mpi_distribute_image;
51  if (params.mpi_all_to_all())
52  mop_algo = (not params.gpu())
53  ? factory::distributed_measurement_operator::mpi_distribute_all_to_all
54  : factory::distributed_measurement_operator::gpu_mpi_distribute_all_to_all;
55  wop_algo = factory::distributed_wavelet_operator::mpi_sara;
56  if (params.mpiAlgorithm() == factory::algo_distribution::mpi_random_updates) {
57  mop_algo = (not params.gpu()) ? factory::distributed_measurement_operator::serial
58  : factory::distributed_measurement_operator::serial;
59  wop_algo = factory::distributed_wavelet_operator::serial;
60  }
61  using_mpi = true;
62  }
63  return {mop_algo, wop_algo, using_mpi};
64 }
distributed_measurement_operator
determine type of distribute for mpi measurement operator

References purify::factory::gpu_mpi_distribute_all_to_all, purify::factory::gpu_mpi_distribute_image, purify::factory::gpu_serial, purify::factory::mpi_distribute_all_to_all, purify::factory::mpi_distribute_image, purify::factory::mpi_random_updates, purify::factory::mpi_sara, and purify::factory::serial.

Referenced by main().

◆ setupCostFunctions()

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 at line 312 of file setup_utils.cc.

314  {
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 }

References purify::Denoiser, purify::L1Norm, purify::L2Norm, purify::L2Norm_with_CRR, and purify::RealIndicator.

Referenced by main().