Skip to content
Snippets Groups Projects
Select Git revision
  • f0147329418ccdd0c012699db8a1677d05f2ca50
  • 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

add_notifications.sql

Blame
  • Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    griddedresponse.cc 6.29 KiB
    #include "griddedresponse.h"
    #include "../common/fftresampler.h"
    
    #include "../telescope/telescope.h"
    
    #include <aocommon/matrix2x2.h>
    #include <aocommon/matrix4x4.h>
    #include <vector>
    #include <complex>
    #include <stdexcept>
    
    using aocommon::HMC4x4;
    using aocommon::MC2x2;
    using aocommon::MC4x4;
    using aocommon::UVector;
    using everybeam::common::FFTResampler;
    using everybeam::griddedresponse::GriddedResponse;
    
    void GriddedResponse::CalculateIntegratedResponse(
        double* buffer, double time, double frequency, size_t field_id,
        size_t undersampling_factor, const std::vector<double>& baseline_weights) {
      size_t nstations = telescope_->GetNrStations();
      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);
    
      // Copy coordinate members
      size_t width_original = width_, height_original = height_;
      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
      size_t npixels = width_ * height_;
      std::vector<HMC4x4> matrices(npixels, HMC4x4::Zero());
      MakeIntegratedSnapshot(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;
    }
    
    void GriddedResponse::CalculateIntegratedResponse(
        double* buffer, const std::vector<double>& time_array, double frequency,
        size_t field_id, size_t undersampling_factor,
        const std::vector<double>& baseline_weights) {
      size_t nstations = telescope_->GetNrStations();
      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
      double baseline_total_weight =
          std::accumulate(baseline_weights.begin(), baseline_weights.end(), 0);
    
      // Copy coordinate members
      size_t width_original = width_, height_original = height_;
      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
      size_t npixels = width_ * height_;
      std::vector<HMC4x4> matrices(npixels, HMC4x4::Zero());
    
      for (std::size_t tstep = 0; tstep != time_array.size(); ++tstep) {
        MakeIntegratedSnapshot(matrices, time_array[tstep], frequency, field_id,
                               baseline_weights.data() + tstep * nbaselines);
      }
    
      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;
    }
    
    void GriddedResponse::MakeIntegratedSnapshot(
        std::vector<HMC4x4>& matrices, double time, double frequency,
        size_t field_id, const double* baseline_weights_interval) {
      size_t nstations = telescope_->GetNrStations();
      UVector<std::complex<float>> buffer_undersampled(
          GetStationBufferSize(nstations));
      CalculateAllStations(buffer_undersampled.data(), time, frequency, field_id);
    
      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(
        double* buffer, int width_in, int height_in, int width_out, int height_out,
        const std::vector<aocommon::HMC4x4>& matrices) {
      // (FFT) resampling, run multi-threaded?
      FFTResampler resampler(width_in, height_in, width_out, height_out);
      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 output buffer
        UVector<float> hires_output(width_out * height_out);
        resampler.Resample(lowres_input.data(), hires_output.data());
        // Copy hires_output (float) to buffer (double), conversion is implicit in
        // std::copy
        std::copy(hires_output.begin(), hires_output.end(),
                  buffer + p * width_out * height_out);
      }
    }