Skip to content
Snippets Groups Projects
Select Git revision
  • 9fdd214bffb8102bc17a3b270012de5c45a0fca1
  • master default protected
  • L2SS-1914-fix_job_dispatch
  • TMSS-3170
  • TMSS-3167
  • TMSS-3161
  • TMSS-3158-Front-End-Only-Allow-Changing-Again
  • TMSS-3133
  • TMSS-3319-Fix-Templates
  • test-fix-deploy
  • TMSS-3134
  • TMSS-2872
  • defer-state
  • add-custom-monitoring-points
  • TMSS-3101-Front-End-Only
  • TMSS-984-choices
  • SDC-1400-Front-End-Only
  • TMSS-3079-PII
  • TMSS-2936
  • check-for-max-244-subbands
  • TMSS-2927---Front-End-Only-PXII
  • Before-Remove-TMSS
  • LOFAR-Release-4_4_318 protected
  • LOFAR-Release-4_4_317 protected
  • LOFAR-Release-4_4_316 protected
  • LOFAR-Release-4_4_315 protected
  • LOFAR-Release-4_4_314 protected
  • LOFAR-Release-4_4_313 protected
  • LOFAR-Release-4_4_312 protected
  • LOFAR-Release-4_4_311 protected
  • LOFAR-Release-4_4_310 protected
  • LOFAR-Release-4_4_309 protected
  • LOFAR-Release-4_4_308 protected
  • LOFAR-Release-4_4_307 protected
  • LOFAR-Release-4_4_306 protected
  • LOFAR-Release-4_4_304 protected
  • LOFAR-Release-4_4_303 protected
  • LOFAR-Release-4_4_302 protected
  • LOFAR-Release-4_4_301 protected
  • LOFAR-Release-4_4_300 protected
  • LOFAR-Release-4_4_299 protected
41 results

__init__.py

Blame
  • Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    griddedresponse.cc 8.33 KiB
    // Copyright (C) 2020 ASTRON (Netherlands Institute for Radio Astronomy)
    // SPDX-License-Identifier: GPL-3.0-or-later
    
    #include "griddedresponse.h"
    #include "../common/fftresampler.h"
    
    #include "../telescope/telescope.h"
    
    #include <aocommon/uvector.h>
    #include <aocommon/matrix2x2.h>
    #include <aocommon/matrix4x4.h>
    #include <aocommon/hmatrix4x4.h>
    #include <vector>
    #include <complex>
    #include <stdexcept>
    
    using aocommon::HMC4x4;
    using aocommon::MC2x2;
    using aocommon::MC4x4;
    using aocommon::UVector;
    
    namespace everybeam {
    namespace griddedresponse {
    void GriddedResponse::IntegratedResponse(
        BeamMode beam_mode, float* buffer, double time, double frequency,
        size_t field_id, size_t undersampling_factor,
        const std::vector<double>& baseline_weights) {
      const size_t nstations = telescope_->GetNrStations();
      const size_t nbaselines = nstations * (nstations + 1) / 2;
      if (baseline_weights.size() != nbaselines) {
        throw std::runtime_error("baseline_weights vector has incorrect size.");
      }
      // Scaling factor
      double baseline_total_weight =
          std::accumulate(baseline_weights.begin(), baseline_weights.end(), 0.0);
    
      // Copy coordinate members
      const size_t width_original = width_;
      const size_t height_original = height_;
      const double dl_original = dl_;
      const double dm_original = dm_;
    
      if (!PerformUndersampling()) undersampling_factor = 1;
    
      width_ /= undersampling_factor;
      height_ /= undersampling_factor;
      dl_ *= (double(width_original) / double(width_));
      dm_ *= (double(width_original) / double(width_));
    
      // Init (Hermitian) Mueller matrix for every pixel in the coarse grid
      size_t npixels = width_ * height_;
      std::vector<HMC4x4> matrices(npixels, HMC4x4::Zero());
      MakeIntegratedSnapshot(beam_mode, matrices, time, frequency, field_id,
                             baseline_weights.data());
    
      for (HMC4x4& matrix : matrices) {
        matrix /= baseline_total_weight;
      }
    
      DoFFTResampling(buffer, width_, height_, width_original, height_original,
                      matrices);
    
      // Reset coordinate members to original values
      width_ = width_original;
      height_ = height_original;
      dl_ = dl_original;
      dm_ = dm_original;
    }
    
    std::vector<HMC4x4> GriddedResponse::UndersampledIntegratedResponse(
        BeamMode beam_mode, const std::vector<double>& time_array, double frequency,
        size_t field_id, size_t undersampling_factor,
        const std::vector<double>& baseline_weights) {
      const size_t nstations = telescope_->GetNrStations();
      const size_t nbaselines = nstations * (nstations + 1) / 2;
      if (baseline_weights.size() != time_array.size() * nbaselines) {
        throw std::runtime_error("baseline_weights vector has incorrect size.");
      }
    
      // Scaling factor
      const double baseline_total_weight =
          std::accumulate(baseline_weights.begin(), baseline_weights.end(), 0.0);
    
      // Copy coordinate members
      size_t width_original = width_, height_original = height_;
      const double dl_original = dl_, dm_original = dm_;
    
      width_ /= undersampling_factor;
      height_ /= undersampling_factor;
      dl_ *= (double(width_original) / double(width_));
      dm_ *= (double(width_original) / double(width_));
    
      // Init (Hermitian) Mueller matrix for every pixel in the coarse grid
      const size_t npixels = width_ * height_;
      std::vector<HMC4x4> matrices(npixels, HMC4x4::Zero());
    
      for (std::size_t tstep = 0; tstep != time_array.size(); ++tstep) {
        MakeIntegratedSnapshot(beam_mode, matrices, time_array[tstep], frequency,
                               field_id,
                               baseline_weights.data() + tstep * nbaselines);
      }
    
      for (HMC4x4& matrix : matrices) {
        matrix /= baseline_total_weight;
      }
    
      // Reset coordinate members to original values
      width_ = width_original;
      height_ = height_original;
      dl_ = dl_original;
      dm_ = dm_original;
    
      return matrices;
    }
    
    void GriddedResponse::IntegratedResponse(
        BeamMode beam_mode, float* destination,
        const std::vector<double>& time_array, double frequency, size_t field_id,
        size_t undersampling_factor, const std::vector<double>& baseline_weights) {
      const std::vector<HMC4x4> matrices =
          UndersampledIntegratedResponse(beam_mode, time_array, frequency, field_id,
                                         undersampling_factor, baseline_weights);
    
      const size_t undersampled_width = width_ / undersampling_factor;
      const size_t undersampled_height = height_ / undersampling_factor;
    
      DoFFTResampling(destination, undersampled_width, undersampled_height, width_,
                      height_, matrices);
    }
    
    void GriddedResponse::UpsampleResponse(
        float* destination, size_t element_index, size_t width, size_t height,
        const std::vector<aocommon::HMC4x4>& undersampled_beam,
        size_t undersampling_factor) {
      if (undersampling_factor != 1) {
        const size_t undersampled_width = width / undersampling_factor;
        const size_t undersampled_height = height / undersampling_factor;
    
        common::FFTResampler resampler(undersampled_width, undersampled_height,
                                       width, height);
        resampler.SetWindowFunction(aocommon::WindowFunction::RaisedHann, true);
        UVector<float> lowres_input(undersampled_width * undersampled_height);
    
        for (size_t i = 0; i != undersampled_width * undersampled_height; ++i) {
          lowres_input[i] = undersampled_beam[i].Data(element_index);
        }
        // Resample and write to the "element_index-th image" in the output buffer
        resampler.Resample(lowres_input.data(), destination);
      } else {
        for (size_t i = 0; i != width * height; ++i) {
          destination[i] = undersampled_beam[i].Data(element_index);
        }
      }
    }
    
    void GriddedResponse::MakeIntegratedSnapshot(
        BeamMode beam_mode, std::vector<HMC4x4>& matrices, double time,
        double frequency, size_t field_id,
        const double* baseline_weights_interval) {
      const size_t nstations = telescope_->GetNrStations();
      UVector<std::complex<float>> buffer_undersampled(
          GetStationBufferSize(nstations));
      ResponseAllStations(beam_mode, buffer_undersampled.data(), time, frequency,
                          field_id);
    
      const size_t npixels = width_ * height_;
      for (size_t y = 0; y != height_; ++y) {
        for (size_t x = 0; x != width_; ++x) {
          size_t index = 0;
          HMC4x4 gain = HMC4x4::Zero();
          for (size_t s1 = 0; s1 != nstations; ++s1) {
            size_t offset_s1 = (s1 * npixels + y * width_ + x) * 4;
            MC2x2 A(buffer_undersampled[offset_s1],
                    buffer_undersampled[offset_s1 + 1],
                    buffer_undersampled[offset_s1 + 2],
                    buffer_undersampled[offset_s1 + 3]);
            for (size_t s2 = s1; s2 != nstations; ++s2) {
              size_t offset_s2 = offset_s1 + (s2 - s1) * npixels * 4;
              MC2x2 B(buffer_undersampled[offset_s2],
                      buffer_undersampled[offset_s2 + 1],
                      buffer_undersampled[offset_s2 + 2],
                      buffer_undersampled[offset_s2 + 3]);
    
              // Compute Mueller matrix and apply vec trick, see
              // https://en.wikipedia.org/wiki/Kronecker_product#Matrix_equations
              MC4x4 baseline_mueller =
                  MC4x4::KroneckerProduct(B.HermTranspose().Transpose(), A) +
                  MC4x4::KroneckerProduct(A.HermTranspose().Transpose(), B);
    
              // Note: keep scalar factor in brackets to avoid a redundant
              // element-wise multiplication of the HMC4x4 matrix. Factor 0.5 is to
              // account for Kronecker delta additions.
              gain += HMC4x4(baseline_mueller) *
                      (0.5 * baseline_weights_interval[index]);
              ++index;
            }
          }
          matrices[y * width_ + x] += gain;
        }
      }
    }
    
    void GriddedResponse::DoFFTResampling(
        float* destination, int width_in, int height_in, int width_out,
        int height_out, const std::vector<aocommon::HMC4x4>& matrices) {
      // (FFT) resampling, run multi-threaded?
      common::FFTResampler resampler(width_in, height_in, width_out, height_out);
      resampler.SetWindowFunction(aocommon::WindowFunction::RaisedHann, true);
      UVector<float> lowres_input(width_in * height_in);
      // Loop over the "double"  representation of the HMC4x4 Hermitian matrix
      for (size_t p = 0; p != 16; ++p) {
        for (int i = 0; i != width_in * height_in; ++i) {
          lowres_input[i] = matrices[i].Data(p);
        }
        // Resample and write to the "p-th image" in the output buffer
        resampler.Resample(lowres_input.data(),
                           destination + p * width_out * height_out);
      }
    }
    }  // namespace griddedresponse
    }  // namespace everybeam