PURIFY
Next-generation radio interferometric imaging
Enumerations | Functions
purify::operators Namespace Reference

Enumerations

enum class  fftw_plan { estimate , measure }
 enum for fftw plans More...
 

Functions

template<class T >
std::tuple< sopt::OperatorFunction< T >, sopt::OperatorFunction< T > > init_on_the_fly_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 t_uint Ju, const t_int total_samples)
 on the fly application of the degridding operator using presampling More...
 
template<class T , class... ARGS>
std::tuple< sopt::OperatorFunction< T >, sopt::OperatorFunction< T > > init_gridding_matrix_2d (ARGS &&...args)
 constructs lambdas that apply degridding matrix with adjoint More...
 
template<class T >
std::tuple< sopt::OperatorFunction< T >, sopt::OperatorFunction< T > > init_zero_padding_2d (const Image< typename T::Scalar > &S, const t_real &oversample_ratio)
 Construsts zero padding operator. More...
 
template<class T >
sopt::OperatorFunction< T > init_normalise (const t_real &op_norm)
 
template<class T >
std::tuple< sopt::OperatorFunction< T >, sopt::OperatorFunction< T > > init_weights_ (const Vector< t_complex > &weights)
 Construsts zero padding operator. More...
 
template<class T >
std::tuple< sopt::OperatorFunction< T >, sopt::OperatorFunction< T > > init_FFT_2d (const t_uint &imsizey_, const t_uint &imsizex_, const t_real &oversample_factor_, const fftw_plan fftw_plan_flag_=fftw_plan::measure)
 Construsts FFT operator. More...
 
template<class T >
std::tuple< sopt::OperatorFunction< T >, sopt::OperatorFunction< T > > base_padding_and_FFT_2d (const std::function< t_real(t_real)> &ftkernelu, const std::function< t_real(t_real)> &ftkernelv, const t_uint &imsizey, const t_uint &imsizex, const t_real &oversample_ratio=2, const fftw_plan &ft_plan=fftw_plan::measure, const t_real &w_mean=0, const t_real &cellx=1, const t_real &celly=1)
 
template<class T >
std::tuple< sopt::OperatorFunction< T >, sopt::OperatorFunction< T > > base_degrid_operator_2d (const Vector< t_real > &u, const Vector< t_real > &v, const Vector< t_real > &w, const Vector< t_complex > &weights, const t_uint &imsizey, const t_uint &imsizex, const t_real &oversample_ratio=2, const kernels::kernel kernel=kernels::kernel::kb, const t_uint Ju=4, const t_uint Jv=4, const fftw_plan &ft_plan=fftw_plan::measure, const bool w_stacking=false, const t_real &cellx=1, const t_real &celly=1, const bool on_the_fly=true)
 
template<class T >
std::tuple< sopt::OperatorFunction< T >, sopt::OperatorFunction< T > > base_padding_and_FFT_2d (const std::function< t_real(t_real)> &ftkerneluv, const t_uint imsizey, const t_uint imsizex, const t_real oversample_ratio, const fftw_plan ft_plan, const t_real w_mean, const t_real cellx, const t_real celly)
 
template<class T >
std::tuple< sopt::OperatorFunction< T >, sopt::OperatorFunction< T > > base_degrid_operator_2d (const Vector< t_real > &u, const Vector< t_real > &v, const Vector< t_real > &w, const Vector< t_complex > &weights, const t_uint &imsizey, const t_uint &imsizex, const t_real oversample_ratio, const kernels::kernel kernel, const t_uint Ju, const t_uint Jw, const fftw_plan ft_plan, const bool w_stacking, const t_real cellx, const t_real celly, const t_real absolute_error, const t_real relative_error, const dde_type dde)
 

Enumeration Type Documentation

◆ fftw_plan

enum for fftw plans

Enumerator
estimate 
measure 

Definition at line 389 of file operators.h.

Function Documentation

◆ base_degrid_operator_2d() [1/2]

template<class T >
std::tuple<sopt::OperatorFunction<T>, sopt::OperatorFunction<T> > purify::operators::base_degrid_operator_2d ( const Vector< t_real > &  u,
const Vector< t_real > &  v,
const Vector< t_real > &  w,
const Vector< t_complex > &  weights,
const t_uint &  imsizey,
const t_uint &  imsizex,
const t_real &  oversample_ratio = 2,
const kernels::kernel  kernel = kernels::kernel::kb,
const t_uint  Ju = 4,
const t_uint  Jv = 4,
const fftw_plan ft_plan = fftw_plan::measure,
const bool  w_stacking = false,
const t_real &  cellx = 1,
const t_real &  celly = 1,
const bool  on_the_fly = true 
)

Definition at line 490 of file operators.h.

496  {
497  std::function<t_real(t_real)> kernelu, kernelv, ftkernelu, ftkernelv;
498  std::tie(kernelu, kernelv, ftkernelu, ftkernelv) =
499  purify::create_kernels(kernel, Ju, Jv, imsizey, imsizex, oversample_ratio);
500  sopt::OperatorFunction<T> directFZ, indirectFZ;
501  t_real const w_mean = w_stacking ? w.array().mean() : 0.;
502  std::tie(directFZ, indirectFZ) = base_padding_and_FFT_2d<T>(
503  ftkernelu, ftkernelv, imsizey, imsizex, oversample_ratio, ft_plan, w_mean, cellx, celly);
504  sopt::OperatorFunction<T> directG, indirectG;
505  PURIFY_MEDIUM_LOG("FoV (width, height): {} deg x {} deg", imsizex * cellx / (60. * 60.),
506  imsizey * celly / (60. * 60.));
507  PURIFY_LOW_LOG("Constructing Weighting and Gridding Operators: WG");
508  PURIFY_MEDIUM_LOG("Number of visibilities: {}", u.size());
509  PURIFY_MEDIUM_LOG("Mean, w: {}, +/- {}", w_mean, (w.maxCoeff() - w.minCoeff()) * 0.5);
510  std::tie(directG, indirectG) =
511  (on_the_fly)
512  ? purify::operators::init_on_the_fly_gridding_matrix_2d<T>(
513  u, v, weights, imsizey, imsizex, oversample_ratio, kernelu, Ju, 4e5)
514  : purify::operators::init_gridding_matrix_2d<T>(
515  u, v, weights, imsizey, imsizex, oversample_ratio, kernelv, kernelu, Ju, Jv);
516  auto direct = sopt::chained_operators<T>(directG, directFZ);
517  auto indirect = sopt::chained_operators<T>(indirectFZ, indirectG);
518  PURIFY_LOW_LOG("Finished consturction of Φ.");
519  return std::make_tuple(direct, indirect);
520 }
#define PURIFY_LOW_LOG(...)
Low priority message.
Definition: logging.h:207
#define PURIFY_MEDIUM_LOG(...)
Medium priority message.
Definition: logging.h:205
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
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)
std::tuple< std::function< t_real(t_real)>, std::function< t_real(t_real)>, std::function< t_real(t_real)>, std::function< t_real(t_real)> > create_kernels(const kernels::kernel kernel_name_, const t_uint Ju_, const t_uint Jv_, const t_real imsizey_, const t_real imsizex_, const t_real oversample_ratio)
Definition: kernels.cc:249

References purify::create_kernels(), PURIFY_LOW_LOG, PURIFY_MEDIUM_LOG, operators_test::u, operators_test::v, and purify::utilities::w_stacking().

◆ base_degrid_operator_2d() [2/2]

template<class T >
std::tuple<sopt::OperatorFunction<T>, sopt::OperatorFunction<T> > purify::operators::base_degrid_operator_2d ( const Vector< t_real > &  u,
const Vector< t_real > &  v,
const Vector< t_real > &  w,
const Vector< t_complex > &  weights,
const t_uint &  imsizey,
const t_uint &  imsizex,
const t_real  oversample_ratio,
const kernels::kernel  kernel,
const t_uint  Ju,
const t_uint  Jw,
const fftw_plan  ft_plan,
const bool  w_stacking,
const t_real  cellx,
const t_real  celly,
const t_real  absolute_error,
const t_real  relative_error,
const dde_type  dde 
)

Definition at line 60 of file wproj_operators.h.

65  {
66  sopt::OperatorFunction<T> directFZ, indirectFZ;
67  sopt::OperatorFunction<T> directG, indirectG;
68  t_real const w_mean = w_stacking ? w.array().mean() : 0;
69  switch (dde) {
70  case (dde_type::wkernel_radial): {
71  auto const kerneluvs = purify::create_radial_ftkernel(kernel, Ju, oversample_ratio);
72  std::tie(directFZ, indirectFZ) = base_padding_and_FFT_2d<T>(
73  std::get<0>(kerneluvs), imsizey, imsizex, oversample_ratio, ft_plan, w_mean, cellx, celly);
74  PURIFY_MEDIUM_LOG("FoV (width, height): {} deg x {} deg", imsizex * cellx / (60. * 60.),
75  imsizey * celly / (60. * 60.));
76  PURIFY_LOW_LOG("Constructing Weighting and Gridding Operators: WG");
77  PURIFY_MEDIUM_LOG("Number of visibilities: {}", u.size());
78  PURIFY_MEDIUM_LOG("Mean, w: {}, +/- {}", w.array().mean(), (w.maxCoeff() - w.minCoeff()) * 0.5);
79  std::tie(directG, indirectG) = purify::operators::init_gridding_matrix_2d<T>(
80  u, v, w.array() - w_mean, weights, imsizey, imsizex, oversample_ratio,
81  std::get<0>(kerneluvs), std::get<1>(kerneluvs), Ju, Jw, cellx, celly, absolute_error,
82  relative_error, dde);
83  break;
84  }
85  case (dde_type::wkernel_2d): {
86  std::function<t_real(t_real)> kernelu, kernelv, ftkernelu, ftkernelv;
87  std::tie(kernelu, kernelv, ftkernelu, ftkernelv) =
88  purify::create_kernels(kernel, Ju, Ju, imsizey, imsizex, oversample_ratio);
89  std::tie(directFZ, indirectFZ) = base_padding_and_FFT_2d<T>(
90  ftkernelu, ftkernelv, imsizey, imsizex, oversample_ratio, ft_plan, w_mean, cellx, celly);
91  PURIFY_MEDIUM_LOG("FoV (width, height): {} deg x {} deg", imsizex * cellx / (60. * 60.),
92  imsizey * celly / (60. * 60.));
93  PURIFY_LOW_LOG("Constructing Weighting and Gridding Operators: WG");
94  PURIFY_MEDIUM_LOG("Number of visibilities: {}", u.size());
95  PURIFY_MEDIUM_LOG("Mean, w: {}, +/- {}", w.array().mean(), (w.maxCoeff() - w.minCoeff()) * 0.5);
96  auto const kerneluvs = purify::create_radial_ftkernel(kernel, Ju, oversample_ratio);
97  std::tie(directG, indirectG) = purify::operators::init_gridding_matrix_2d<T>(
98  u, v, w.array() - w_mean, weights, imsizey, imsizex, oversample_ratio,
99  std::get<0>(kerneluvs), std::get<1>(kerneluvs), Ju, Jw, cellx, celly, absolute_error,
100  relative_error, dde);
101  break;
102  }
103  default:
104  throw std::runtime_error("DDE is not recognised.");
105  }
106  auto direct = sopt::chained_operators<T>(directG, directFZ);
107  auto indirect = sopt::chained_operators<T>(indirectFZ, indirectG);
108  PURIFY_LOW_LOG("Finished consturction of Φ.");
109  return std::make_tuple(direct, indirect);
110 }
std::tuple< std::function< t_real(t_real)>, std::function< t_real(t_real)> > create_radial_ftkernel(const kernels::kernel kernel_name_, const t_uint Ju_, const t_real oversample_ratio)
Definition: kernels.cc:347

References purify::create_kernels(), purify::create_radial_ftkernel(), PURIFY_LOW_LOG, PURIFY_MEDIUM_LOG, operators_test::u, operators_test::v, purify::utilities::w_stacking(), purify::wkernel_2d, and purify::wkernel_radial.

◆ base_padding_and_FFT_2d() [1/2]

template<class T >
std::tuple<sopt::OperatorFunction<T>, sopt::OperatorFunction<T> > purify::operators::base_padding_and_FFT_2d ( const std::function< t_real(t_real)> &  ftkernelu,
const std::function< t_real(t_real)> &  ftkernelv,
const t_uint &  imsizey,
const t_uint &  imsizex,
const t_real &  oversample_ratio = 2,
const fftw_plan ft_plan = fftw_plan::measure,
const t_real &  w_mean = 0,
const t_real &  cellx = 1,
const t_real &  celly = 1 
)

Definition at line 453 of file operators.h.

457  {
458  sopt::OperatorFunction<T> directZ, indirectZ;
459  sopt::OperatorFunction<T> directFFT, indirectFFT;
460 
461  const Image<t_complex> S =
462  purify::details::init_correction2d(oversample_ratio, imsizey, imsizex, ftkernelu, ftkernelv,
463  w_mean, cellx, celly) *
464  std::sqrt(imsizex * imsizey) * oversample_ratio;
465  PURIFY_LOW_LOG("Building Measurement Operator: WGFZDB");
467  "Constructing Zero Padding "
468  "and Correction Operator: "
469  "ZDB");
470  PURIFY_MEDIUM_LOG("Image size (width, height): {} x {}", imsizex, imsizey);
471  PURIFY_MEDIUM_LOG("Oversampling Factor: {}", oversample_ratio);
472  std::tie(directZ, indirectZ) = purify::operators::init_zero_padding_2d<T>(S, oversample_ratio);
473  PURIFY_LOW_LOG("Constructing FFT operator: F");
474  switch (ft_plan) {
475  case fftw_plan::measure:
476  PURIFY_MEDIUM_LOG("Measuring Plans...");
477  break;
478  case fftw_plan::estimate:
479  PURIFY_MEDIUM_LOG("Estimating Plans...");
480  break;
481  }
482  std::tie(directFFT, indirectFFT) =
483  purify::operators::init_FFT_2d<T>(imsizey, imsizex, oversample_ratio, ft_plan);
484  auto direct = sopt::chained_operators<T>(directFFT, directZ);
485  auto indirect = sopt::chained_operators<T>(indirectZ, indirectFFT);
486  return std::make_tuple(direct, indirect);
487 }
Image< t_complex > init_correction2d(const t_real &oversample_ratio, const t_uint &imsizey_, const t_uint &imsizex_, const std::function< t_real(t_real)> ftkernelu, const std::function< t_real(t_real)> ftkernelv, const t_real &w_mean, const t_real &cellx, const t_real &celly)
Definition: operators.cc:47

References estimate, purify::details::init_correction2d(), measure, PURIFY_LOW_LOG, and PURIFY_MEDIUM_LOG.

◆ base_padding_and_FFT_2d() [2/2]

template<class T >
std::tuple<sopt::OperatorFunction<T>, sopt::OperatorFunction<T> > purify::operators::base_padding_and_FFT_2d ( const std::function< t_real(t_real)> &  ftkerneluv,
const t_uint  imsizey,
const t_uint  imsizex,
const t_real  oversample_ratio,
const fftw_plan  ft_plan,
const t_real  w_mean,
const t_real  cellx,
const t_real  celly 
)

Definition at line 25 of file wproj_operators.h.

28  {
29  sopt::OperatorFunction<T> directZ, indirectZ;
30  sopt::OperatorFunction<T> directFFT, indirectFFT;
31  const Image<t_complex> S =
32  purify::details::init_correction_radial_2d(oversample_ratio, imsizey, imsizex, ftkerneluv,
33  w_mean, cellx, celly) *
34  std::sqrt(imsizex * imsizey) * oversample_ratio;
35  PURIFY_LOW_LOG("Building Measurement Operator: WGFZDB");
37  "Constructing Zero Padding "
38  "and Correction Operator: "
39  "ZDB");
40  PURIFY_MEDIUM_LOG("Image size (width, height): {} x {}", imsizex, imsizey);
41  PURIFY_MEDIUM_LOG("Oversampling Factor: {}", oversample_ratio);
42  std::tie(directZ, indirectZ) = purify::operators::init_zero_padding_2d<T>(S, oversample_ratio);
43  PURIFY_LOW_LOG("Constructing FFT operator: F");
44  switch (ft_plan) {
45  case fftw_plan::measure:
46  PURIFY_MEDIUM_LOG("Measuring Plans...");
47  break;
48  case fftw_plan::estimate:
49  PURIFY_MEDIUM_LOG("Estimating Plans...");
50  break;
51  }
52  std::tie(directFFT, indirectFFT) =
53  purify::operators::init_FFT_2d<T>(imsizey, imsizex, oversample_ratio, ft_plan);
54  auto direct = sopt::chained_operators<T>(directFFT, directZ);
55  auto indirect = sopt::chained_operators<T>(indirectZ, indirectFFT);
56  return std::make_tuple(direct, indirect);
57 }
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)

References estimate, purify::details::init_correction_radial_2d(), measure, PURIFY_LOW_LOG, and PURIFY_MEDIUM_LOG.

◆ init_FFT_2d()

template<class T >
std::tuple<sopt::OperatorFunction<T>, sopt::OperatorFunction<T> > purify::operators::init_FFT_2d ( const t_uint &  imsizey_,
const t_uint &  imsizex_,
const t_real &  oversample_factor_,
const fftw_plan  fftw_plan_flag_ = fftw_plan::measure 
)

Construsts FFT operator.

Definition at line 392 of file operators.h.

394  {
395  t_int const ftsizeu_ = std::floor(imsizex_ * oversample_factor_);
396  t_int const ftsizev_ = std::floor(imsizey_ * oversample_factor_);
397  t_int plan_flag = (FFTW_MEASURE | FFTW_PRESERVE_INPUT);
398  switch (fftw_plan_flag_) {
399  case (fftw_plan::measure):
400  plan_flag = (FFTW_MEASURE | FFTW_PRESERVE_INPUT);
401  break;
402  case (fftw_plan::estimate):
403  plan_flag = (FFTW_ESTIMATE | FFTW_PRESERVE_INPUT);
404  break;
405  }
406 
407 #ifdef PURIFY_OPENMP_FFTW
408  PURIFY_LOW_LOG("Using OpenMP threading with FFTW.");
409  fftw_init_threads();
410 #endif
411  Vector<typename T::Scalar> src = Vector<t_complex>::Zero(ftsizev_ * ftsizeu_);
412  Vector<typename T::Scalar> dst = Vector<t_complex>::Zero(ftsizev_ * ftsizeu_);
413  // creating plans
414  const auto del = [](fftw_plan_s *plan) { fftw_destroy_plan(plan); };
415  // fftw plan with threads needs to be used before each fftw_plan is created
416 #ifdef PURIFY_OPENMP_FFTW
417  fftw_plan_with_nthreads(omp_get_max_threads());
418 #endif
419  const std::shared_ptr<fftw_plan_s> m_plan_forward(
420  fftw_plan_dft_2d(ftsizev_, ftsizeu_, reinterpret_cast<fftw_complex *>(src.data()),
421  reinterpret_cast<fftw_complex *>(dst.data()), FFTW_FORWARD, plan_flag),
422  del);
423  // fftw plan with threads needs to be used before each fftw_plan is created
424 #ifdef PURIFY_OPENMP_FFTW
425  fftw_plan_with_nthreads(omp_get_max_threads());
426 #endif
427  const std::shared_ptr<fftw_plan_s> m_plan_inverse(
428  fftw_plan_dft_2d(ftsizev_, ftsizeu_, reinterpret_cast<fftw_complex *>(src.data()),
429  reinterpret_cast<fftw_complex *>(dst.data()), FFTW_BACKWARD, plan_flag),
430  del);
431  auto const direct = [m_plan_forward, ftsizeu_, ftsizev_](T &output, const T &input) {
432  assert(input.size() == ftsizev_ * ftsizeu_);
433  output = Matrix<typename T::Scalar>::Zero(input.rows(), input.cols());
434  fftw_execute_dft(
435  m_plan_forward.get(),
436  const_cast<fftw_complex *>(reinterpret_cast<const fftw_complex *>(input.data())),
437  reinterpret_cast<fftw_complex *>(output.data()));
438  output /= std::sqrt(output.size());
439  };
440  auto const indirect = [m_plan_inverse, ftsizeu_, ftsizev_](T &output, const T &input) {
441  assert(input.size() == ftsizev_ * ftsizeu_);
442  output = Matrix<typename T::Scalar>::Zero(input.rows(), input.cols());
443  fftw_execute_dft(
444  m_plan_inverse.get(),
445  const_cast<fftw_complex *>(reinterpret_cast<const fftw_complex *>(input.data())),
446  reinterpret_cast<fftw_complex *>(output.data()));
447  output /= std::sqrt(output.size());
448  };
449  return std::make_tuple(direct, indirect);
450 }

References estimate, measure, and PURIFY_LOW_LOG.

◆ init_gridding_matrix_2d()

template<class T , class... ARGS>
std::tuple<sopt::OperatorFunction<T>, sopt::OperatorFunction<T> > purify::operators::init_gridding_matrix_2d ( ARGS &&...  args)

constructs lambdas that apply degridding matrix with adjoint

Definition at line 312 of file operators.h.

313  {
314  const std::shared_ptr<const Sparse<t_complex>> interpolation_matrix =
315  std::make_shared<const Sparse<t_complex>>(
316  details::init_gridding_matrix_2d(std::forward<ARGS>(args)...));
317  const std::shared_ptr<const Sparse<t_complex>> adjoint =
318  std::make_shared<const Sparse<t_complex>>(interpolation_matrix->adjoint());
319 
320  return std::make_tuple(
321  [=](T &output, const T &input) {
322  output = utilities::sparse_multiply_matrix(*interpolation_matrix, input);
323  },
324  [=](T &output, const T &input) {
325  output = utilities::sparse_multiply_matrix(*adjoint, input);
326  });
327 }
std::tuple< sopt::OperatorFunction< T >, sopt::OperatorFunction< T > > init_gridding_matrix_2d(ARGS &&...args)
constructs lambdas that apply degridding matrix with adjoint
Definition: operators.h:312
std::enable_if< std::is_same< typename T0::Scalar, typename T1::Scalar >::value and T0::IsRowMajor, Vector< typename T0::Scalar > >::type sparse_multiply_matrix(const Eigen::SparseMatrixBase< T0 > &M, const Eigen::MatrixBase< T1 > &x)
Parallel multiplication with a sparse matrix and vector.
Definition: utilities.h:67

References purify::details::init_gridding_matrix_2d(), and purify::utilities::sparse_multiply_matrix().

◆ init_normalise()

template<class T >
sopt::OperatorFunction<T> purify::operators::init_normalise ( const t_real &  op_norm)

Definition at line 368 of file operators.h.

368  {
369  if (not(op_norm > 0)) throw std::runtime_error("Operator norm is not greater than zero.");
370  return [=](T &output, const T &x) { output = x / op_norm; };
371 }

◆ init_on_the_fly_gridding_matrix_2d()

template<class T >
std::tuple<sopt::OperatorFunction<T>, sopt::OperatorFunction<T> > purify::operators::init_on_the_fly_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 t_uint  Ju,
const t_int  total_samples 
)

on the fly application of the degridding operator using presampling

Definition at line 21 of file fly_operators.h.

24  {
25  const t_uint ftsizev_ = std::floor(imsizey_ * oversample_ratio);
26  const t_uint ftsizeu_ = std::floor(imsizex_ * oversample_ratio);
27  const t_uint rows = u.size();
28  const t_uint cols = ftsizeu_ * ftsizev_;
29  if (u.size() != v.size())
30  throw std::runtime_error(
31  "Size of u and v vectors are not the same for creating gridding matrix.");
32 
33  const std::shared_ptr<Vector<t_real>> u_ptr = std::make_shared<Vector<t_real>>(u);
34  const std::shared_ptr<Vector<t_real>> v_ptr = std::make_shared<Vector<t_real>>(v);
35  const std::shared_ptr<Vector<t_complex>> weights_ptr =
36  std::make_shared<Vector<t_complex>>(weights);
37  const t_complex I(0, 1);
38  const t_int ju_max = std::min(Ju, ftsizeu_);
39  const t_int jv_max = std::min(Ju, ftsizev_);
40  const auto samples = kernels::kernel_samples(
41  total_samples, [&](const t_real x) { return kernelu(x * ju_max * 0.5); });
42  std::set<t_int> nonZeros_set;
43  for (t_int m = 0; m < rows; ++m) {
44  t_complex result = 0;
45  const t_real u_val = (*u_ptr)(m);
46  const t_real v_val = (*v_ptr)(m);
47  const t_real k_u = std::floor(u_val - ju_max * 0.5);
48  const t_real k_v = std::floor(v_val - jv_max * 0.5);
49  for (t_int jv = 1; jv < jv_max + 1; ++jv) {
50  const t_uint p = utilities::mod(k_v + jv, ftsizev_);
51  const t_real c_0 =
52  static_cast<t_int>(std::floor(2 * std::abs(v_val - (k_v + jv)) * total_samples / jv_max));
53  for (t_int ju = 1; ju < ju_max + 1; ++ju) {
54  const t_uint q = utilities::mod(k_u + ju, ftsizeu_);
55  const t_int i_0 = static_cast<t_int>(
56  std::floor(2 * std::abs(u_val - (k_u + ju)) * total_samples / ju_max));
57  const t_uint index = utilities::sub2ind(p, q, ftsizev_, ftsizeu_);
58  nonZeros_set.insert(index);
59  }
60  }
61  }
62 
63  std::vector<t_int> nonZeros_vec(nonZeros_set.begin(), nonZeros_set.end());
64  std::sort(nonZeros_vec.data(), nonZeros_vec.data() + nonZeros_vec.size());
65  SparseVector<t_int> mapping(ftsizev_ * ftsizeu_);
66  mapping.reserve(nonZeros_vec.size());
67  for (t_int index = 0; index < nonZeros_vec.size(); index++)
68  mapping.coeffRef(nonZeros_vec[index]) = index;
69  PURIFY_LOW_LOG("Non Zero grid locations: {} ", mapping.nonZeros());
70 
71  const auto degrid = [rows, ju_max, jv_max, I, u_ptr, v_ptr, weights_ptr, samples, total_samples,
72  ftsizeu_, ftsizev_](T &output, const T &input) {
73  output = T::Zero(u_ptr->size());
74  assert(input.size() == ftsizeu_ * ftsizev_);
75 #ifdef PURIFY_OPENMP
76 #pragma omp parallel for
77 #endif
78  for (t_int m = 0; m < rows; ++m) {
79  t_complex result = 0;
80  const t_real u_val = (*u_ptr)(m);
81  const t_real v_val = (*v_ptr)(m);
82  const t_real k_u = std::floor(u_val - ju_max * 0.5);
83  const t_real k_v = std::floor(v_val - jv_max * 0.5);
84  for (t_int jv = 1; jv < jv_max + 1; ++jv) {
85  const t_uint p = utilities::mod(k_v + jv, ftsizev_);
86  const t_real c_0 = static_cast<t_int>(
87  std::floor(2 * std::abs(v_val - (k_v + jv)) * total_samples / jv_max));
88  assert(c_0 >= 0);
89  assert(c_0 < total_samples);
90  const t_real kernelv_val = samples[c_0] * (1. - (2 * (p % 2)));
91  for (t_int ju = 1; ju < ju_max + 1; ++ju) {
92  const t_uint q = utilities::mod(k_u + ju, ftsizeu_);
93  const t_int i_0 = static_cast<t_int>(
94  std::floor(2 * std::abs(u_val - (k_u + ju)) * total_samples / ju_max));
95  assert(i_0 >= 0);
96  assert(i_0 < total_samples);
97  const t_real kernelu_val = samples[i_0] * (1. - (2 * (q % 2)));
98  const t_uint index = utilities::sub2ind(p, q, ftsizev_, ftsizeu_);
99  const t_real sign = kernelu_val * kernelv_val;
100  result += input(index) * sign;
101  }
102  }
103  output(m) = result;
104  }
105  output.array() *= (*weights_ptr).array();
106  };
107 
108  const auto grid = [rows, ju_max, jv_max, I, u_ptr, v_ptr, weights_ptr, samples, total_samples,
109  ftsizeu_, ftsizev_, mapping, nonZeros_vec](T &output, const T &input) {
110  const t_int N = ftsizeu_ * ftsizev_;
111  output = T::Zero(N);
112 #ifdef PURIFY_OPENMP
113  t_int const max_threads = omp_get_max_threads();
114 #else
115  t_int const max_threads = 1;
116 #endif
117  T output_compressed = T::Zero(nonZeros_vec.size() * max_threads);
118  assert(output.size() == N);
119 #ifdef PURIFY_OPENMP
120 #pragma omp parallel for
121 #endif
122  for (t_int m = 0; m < rows; ++m) {
123  t_complex result = 0;
124 #ifdef PURIFY_OPENMP
125  const t_int shift = omp_get_thread_num() * nonZeros_vec.size();
126 #else
127  const t_int shift = 0;
128 #endif
129  const t_real u_val = (*u_ptr)(m);
130  const t_real v_val = (*v_ptr)(m);
131  const t_real k_u = std::floor(u_val - ju_max * 0.5);
132  const t_real k_v = std::floor(v_val - jv_max * 0.5);
133  const t_complex vis = input(m) * std::conj((*weights_ptr)(m));
134  for (t_int jv = 1; jv < jv_max + 1; ++jv) {
135  const t_uint p = utilities::mod(k_v + jv, ftsizev_);
136  const t_real c_0 = static_cast<t_int>(
137  std::floor(2 * std::abs(v_val - (k_v + jv)) * total_samples / jv_max));
138  assert(c_0 >= 0);
139  assert(c_0 < total_samples);
140  const t_real kernelv_val = samples[c_0] * (1. - (2 * (p % 2)));
141  for (t_int ju = 1; ju < ju_max + 1; ++ju) {
142  const t_uint q = utilities::mod(k_u + ju, ftsizeu_);
143  const t_int i_0 = static_cast<t_int>(
144  std::floor(2 * std::abs(u_val - (k_u + ju)) * total_samples / ju_max));
145  assert(i_0 >= 0);
146  assert(i_0 < total_samples);
147  const t_real kernelu_val = samples[i_0] * (1. - (2 * (q % 2)));
148  const t_int index = utilities::sub2ind(p, q, ftsizev_, ftsizeu_);
149  const t_complex result = kernelu_val * kernelv_val * vis;
150  output_compressed(mapping.coeff(index) + shift) += result;
151  }
152  }
153  }
154  for (t_int m = 1; m < max_threads; m++) {
155  const t_int loop_shift = m * nonZeros_vec.size();
156  output_compressed.segment(0, nonZeros_vec.size()) +=
157  output_compressed.segment(loop_shift, nonZeros_vec.size());
158  }
159  for (t_int index = 0; index < nonZeros_vec.size(); index++)
160  output(nonZeros_vec[index]) += output_compressed(index);
161  };
162  return std::make_tuple(degrid, grid);
163 }
std::vector< t_real > kernel_samples(const t_int total_samples, const std::function< t_real(t_real)> kernelu)
Calculates samples of a kernel.
Definition: kernels.cc:144
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

References purify::I, purify::kernels::kernel_samples(), purify::utilities::mod(), PURIFY_LOW_LOG, purify::utilities::sub2ind(), operators_test::u, and operators_test::v.

◆ init_weights_()

template<class T >
std::tuple<sopt::OperatorFunction<T>, sopt::OperatorFunction<T> > purify::operators::init_weights_ ( const Vector< t_complex > &  weights)

Construsts zero padding operator.

Definition at line 375 of file operators.h.

376  {
377  PURIFY_DEBUG("Calculating weights: W");
378  auto direct = [=](T &output, const T &x) {
379  assert(weights.size() == x.size());
380  output = weights.array() * x.array();
381  };
382  auto indirect = [=](T &output, const T &x) {
383  assert(weights.size() == x.size());
384  output = weights.conjugate().array() * x.array();
385  };
386  return std::make_tuple(direct, indirect);
387 }
#define PURIFY_DEBUG(...)
\macro Output some debugging
Definition: logging.h:197

References PURIFY_DEBUG.

◆ init_zero_padding_2d()

template<class T >
std::tuple<sopt::OperatorFunction<T>, sopt::OperatorFunction<T> > purify::operators::init_zero_padding_2d ( const Image< typename T::Scalar > &  S,
const t_real &  oversample_ratio 
)

Construsts zero padding operator.

Definition at line 331 of file operators.h.

332  {
333  const t_uint imsizex_ = S.cols();
334  const t_uint imsizey_ = S.rows();
335  const t_uint ftsizeu_ = std::floor(imsizex_ * oversample_ratio);
336  const t_uint ftsizev_ = std::floor(imsizey_ * oversample_ratio);
337  const t_uint x_start = std::floor(ftsizeu_ * 0.5 - imsizex_ * 0.5);
338  const t_uint y_start = std::floor(ftsizev_ * 0.5 - imsizey_ * 0.5);
339  auto direct = [=](T &output, const T &x) {
340  assert(x.size() == imsizex_ * imsizey_);
341  output = Vector<t_complex>::Zero(ftsizeu_ * ftsizev_);
342 #pragma omp parallel for collapse(2)
343  for (t_uint j = 0; j < imsizey_; j++) {
344  for (t_uint i = 0; i < imsizex_; i++) {
345  const t_uint input_index = utilities::sub2ind(j, i, imsizey_, imsizex_);
346  const t_uint output_index =
347  utilities::sub2ind(y_start + j, x_start + i, ftsizev_, ftsizeu_);
348  output(output_index) = S(j, i) * x(input_index);
349  }
350  }
351  };
352  auto indirect = [=](T &output, const T &x) {
353  assert(x.size() == ftsizeu_ * ftsizev_);
354  output = T::Zero(imsizey_ * imsizex_);
355 #pragma omp parallel for collapse(2)
356  for (t_uint j = 0; j < imsizey_; j++) {
357  for (t_uint i = 0; i < imsizex_; i++) {
358  const t_uint output_index = utilities::sub2ind(j, i, imsizey_, imsizex_);
359  const t_uint input_index = utilities::sub2ind(y_start + j, x_start + i, ftsizev_, ftsizeu_);
360  output(output_index) = std::conj(S(j, i)) * x(input_index);
361  }
362  }
363  };
364  return std::make_tuple(direct, indirect);
365 }

References purify::utilities::sub2ind().