Skip to content
Snippets Groups Projects
Select Git revision
  • 18a0350da92e0861d255828ab82798c306e18f6f
  • master default protected
  • zhang-master-patch-34807
  • add-single-element-interface
  • ast-919-readthedocs
  • ncp_fix
  • workaround-wsclean-issue-83
  • ast-645-add-beam-normalisation-mode-preapplied
  • ast-645-add-beam-normalisation-mode-jm
  • activate-oskar-pybindings
  • disable-element-beam-1
  • submodulesync
  • fix-eigen
  • ncp_check
  • random-fixes
  • lobes-se607-1
  • test-schaapcommon
  • just-testing
  • extend-add_beaminfo-script
  • extend-telescope-interface-to-support-dp3
  • lobes-investigation
  • v0.3.1
  • v0.3.0
  • v0.2.0
  • v0.1.3
  • v0.1.2
  • v0.1.1
  • v0.1.0
28 results

lofarreadutils.cc

Blame
  • Forked from ResearchAndDevelopment / EveryBeam
    462 commits behind the upstream repository.
    Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    lofarreadutils.cc 12.98 KiB
    // lofarreadutils.cc: Utility functions to read the meta data relevant for
    // simulating the beam from LOFAR observations stored in MS format.
    //
    // Copyright (C) 2013
    // ASTRON (Netherlands Institute for Radio Astronomy)
    // P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
    //
    // This file is part of the LOFAR software suite.
    // The LOFAR software suite is free software: you can redistribute it and/or
    // modify it under the terms of the GNU General Public License as published
    // by the Free Software Foundation, either version 3 of the License, or
    // (at your option) any later version.
    //
    // The LOFAR software suite is distributed in the hope that it will be useful,
    // but WITHOUT ANY WARRANTY; without even the implied warranty of
    // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    // GNU General Public License for more details.
    //
    // You should have received a copy of the GNU General Public License along
    // with the LOFAR software suite. If not, see <http://www.gnu.org/licenses/>.
    //
    // $Id$
    
    #include "lofarreadutils.h"
    #include "beamformeridenticalantennas.h"
    #include "common/mathutils.h"
    #include "common/casautils.h"
    
    #include <casacore/measures/Measures/MDirection.h>
    #include <casacore/measures/Measures/MPosition.h>
    #include <casacore/measures/Measures/MCDirection.h>
    #include <casacore/measures/Measures/MCPosition.h>
    #include <casacore/measures/Measures/MeasTable.h>
    #include <casacore/measures/Measures/MeasConvert.h>
    #include <casacore/measures/TableMeasures/ScalarMeasColumn.h>
    
    #include <cassert>
    #include <stdexcept>
    
    #include <casacore/ms/MeasurementSets/MSAntenna.h>
    #include <casacore/ms/MSSel/MSSelection.h>
    #include <casacore/ms/MSSel/MSAntennaParse.h>
    #include <casacore/ms/MeasurementSets/MSAntennaColumns.h>
    #include <casacore/ms/MeasurementSets/MSDataDescription.h>
    #include <casacore/ms/MeasurementSets/MSDataDescColumns.h>
    #include <casacore/ms/MeasurementSets/MSField.h>
    #include <casacore/ms/MeasurementSets/MSFieldColumns.h>
    #include <casacore/ms/MeasurementSets/MSObservation.h>
    #include <casacore/ms/MeasurementSets/MSObsColumns.h>
    #include <casacore/ms/MeasurementSets/MSPolarization.h>
    #include <casacore/ms/MeasurementSets/MSPolColumns.h>
    #include <casacore/ms/MeasurementSets/MSSpectralWindow.h>
    #include <casacore/ms/MeasurementSets/MSSpWindowColumns.h>
    
    namespace everybeam {
    
    constexpr Antenna::CoordinateSystem::Axes lofar_antenna_orientation = {
        {
            -std::sqrt(.5),
            -std::sqrt(.5),
            0.0,
        },
        {
            std::sqrt(.5),
            -std::sqrt(.5),
            0.0,
        },
        {0.0, 0.0, 1.0},
    };
    
    // constexpr Antenna::CoordinateSystem::Axes lofar_antenna_orientation = {
    //     {1.0, 0.0, 0.0,},
    //     {0.0, 1.0, 0.0,},
    //     {0.0, 0.0, 1.0},
    // };
    
    using namespace casacore;
    
    typedef std::array<vector3r_t, 16> TileConfig;
    
    // TODO: utility is not used at all
    bool HasSubTable(const Table &table, const string &name) {
      return table.keywordSet().isDefined(name);
    }
    
    TileConfig ReadTileConfig(const Table &table, unsigned int row) {
      ROArrayQuantColumn<Double> c_tile_offset(table, "TILE_ELEMENT_OFFSET", "m");
    
      // Read tile configuration for HBA antenna fields, assert validity of aips
      // offset.
      Matrix<Quantity> aips_offset = c_tile_offset(row);
    
      TileConfig config;
      assert(aips_offset.ncolumn() == config.size());
    
      for (unsigned int i = 0; i < config.size(); ++i) {
        config[i][0] = aips_offset(0, i).getValue();
        config[i][1] = aips_offset(1, i).getValue();
        config[i][2] = aips_offset(2, i).getValue();
      }
      return config;
    }
    
    void TransformToFieldCoordinates(TileConfig &config,
                                     const Antenna::CoordinateSystem::Axes &axes) {
      for (unsigned int i = 0; i < config.size(); ++i) {
        const vector3r_t position = config[i];
        config[i][0] = dot(position, axes.p);
        config[i][1] = dot(position, axes.q);
        config[i][2] = dot(position, axes.r);
      }
    }
    
    vector3r_t TransformToFieldCoordinates(
        const vector3r_t &position, const Antenna::CoordinateSystem::Axes &axes) {
      const vector3r_t result{dot(position, axes.p), dot(position, axes.q),
                              dot(position, axes.r)};
      return result;
    }
    
    // AntennaField::CoordinateSystem readCoordinateSystemAartfaac(
    //     const Table &table, unsigned int id)
    // {
    //     ROArrayQuantColumn<Double> c_position(table, "POSITION", "m");
    //
    //     // Read antenna field center (ITRF).
    //     Vector<Quantity> aips_position = c_position(id);
    //     assert(aips_position.size() == 3);
    //
    //     vector3r_t position = {{aips_position(0).getValue(),
    //         aips_position(1).getValue(), aips_position(2).getValue()}};
    //
    //     TableRecord keywordset = table.keywordSet();
    //     Matrix<double> aips_axes;
    //     keywordset.get("AARTFAAC_COORDINATE_AXES", aips_axes);
    //     assert(aips_axes.shape().isEqual(IPosition(2, 3, 3)));
    //
    //     vector3r_t p = {{aips_axes(0, 0), aips_axes(1, 0), aips_axes(2, 0)}};
    //     vector3r_t q = {{aips_axes(0, 1), aips_axes(1, 1), aips_axes(2, 1)}};
    //     vector3r_t r = {{aips_axes(0, 2), aips_axes(1, 2), aips_axes(2, 2)}};
    //
    //     AntennaField::CoordinateSystem system = {position, {p, q, r}};
    //
    //     return system;
    // }
    
    BeamFormer::Ptr MakeTile(unsigned int id, const vector3r_t &position,
                             const TileConfig &tile_config,
                             ElementResponse::Ptr element_response) {
      BeamFormer::Ptr tile =
          BeamFormer::Ptr(new BeamFormerIdenticalAntennas(position));
    
      for (unsigned int id = 0; id < tile_config.size(); id++) {
        vector3r_t antenna_position = tile_config[id];
    
        Antenna::CoordinateSystem antenna_coordinate_system;
        antenna_coordinate_system.origin = antenna_position;
        antenna_coordinate_system.axes = lofar_antenna_orientation;
    
        Antenna::Ptr antenna = Element::Ptr(
            new Element(antenna_coordinate_system, element_response, id));
        tile->AddAntenna(antenna);
      }
    
      return tile;
    }
    
    BeamFormer::Ptr ReadAntennaField(const Table &table, unsigned int id,
                                     ElementResponse::Ptr element_response) {
      Antenna::CoordinateSystem coordinate_system =
          common::ReadCoordinateSystem(table, id);
      //     std::cout << "coordinate_system: " << std::endl;
      //     std::cout << "  axes.p: " << coordinate_system.axes.p[0] << ", " <<
      //     coordinate_system.axes.p[1] << ", " << coordinate_system.axes.p[2] <<
      //     std::endl; std::cout << "  axes.q: " << coordinate_system.axes.q[0] <<
      //     ", " << coordinate_system.axes.q[1] << ", " <<
      //     coordinate_system.axes.q[2] << std::endl; std::cout << "  axes.r: " <<
      //     coordinate_system.axes.r[0] << ", " << coordinate_system.axes.r[1] <<
      //     ", " << coordinate_system.axes.r[2] << std::endl;
      BeamFormer::Ptr beam_former(
          new BeamFormerIdenticalAntennas(coordinate_system));
    
      ROScalarColumn<String> c_name(table, "NAME");
      ROArrayQuantColumn<Double> c_offset(table, "ELEMENT_OFFSET", "m");
      ROArrayColumn<Bool> c_flag(table, "ELEMENT_FLAG");
    
      const string &name = c_name(id);
    
      // Read element offsets and flags.
      Matrix<Quantity> aips_offset = c_offset(id);
      assert(aips_offset.shape().isEqual(IPosition(2, 3, aips_offset.ncolumn())));
    
      Matrix<Bool> aips_flag = c_flag(id);
      assert(aips_flag.shape().isEqual(IPosition(2, 2, aips_offset.ncolumn())));
    
      TileConfig tile_config;
      if (name != "LBA") tile_config = ReadTileConfig(table, id);
      TransformToFieldCoordinates(tile_config, coordinate_system.axes);
    
      for (size_t i = 0; i < aips_offset.ncolumn(); ++i) {
        vector3r_t antenna_position = {aips_offset(0, i).getValue(),
                                       aips_offset(1, i).getValue(),
                                       aips_offset(2, i).getValue()};
        antenna_position =
            TransformToFieldCoordinates(antenna_position, coordinate_system.axes);
        Antenna::Ptr antenna;
        Antenna::CoordinateSystem antenna_coordinate_system{
            antenna_position, lofar_antenna_orientation};
        if (name == "LBA") {
          antenna = Element::Ptr(
              new Element(antenna_coordinate_system, element_response, id));
        } else {
          // name is HBA, HBA0, HBA1
          antenna = MakeTile(id, antenna_position, tile_config, element_response);
        }
    
        antenna->enabled_[0] = !aips_flag(0, i);
        antenna->enabled_[1] = !aips_flag(1, i);
        beam_former->AddAntenna(antenna);
      }
      return beam_former;
    }
    
    BeamFormer::Ptr ReadAntennaFieldAartfaac(const Table &table,
                                             const string &ant_type,
                                             unsigned int id) {
      BeamFormer::Ptr field;
      //     AntennaField::CoordinateSystem system =
      //     readCoordinateSystemAartfaac(table, id);
      //
      //     if (ant_type == "LBA")
      //     {
      //         DualDipoleAntenna::Ptr model(new DualDipoleAntenna());
      //         field = AntennaField::Ptr(new AntennaFieldLBA(ant_type, system,
      //         model));
      //     }
      //     else // HBA
      //     {
      //          // TODO: implement this
      //          throw std::runtime_error("HBA for Aartfaac is not implemented
      //          yet.");
      //     }
      //
      //     // Add only one antenna to the field (no offset, always enabled)
      //     AntennaField::Antenna antenna;
      //     antenna.position[0] = 0.;
      //     antenna.position[1] = 0.;
      //     antenna.position[2] = 0.;
      //     antenna.enabled[0] = true;
      //     antenna.enabled[1] = true;
      //
      //     field->addAntenna(antenna);
    
      return field;
    }
    
    vector3r_t ReadStationPhaseReference(const Table &table, unsigned int id) {
      vector3r_t phase_reference = {0.0, 0.0, 0.0};
      const string columnName("LOFAR_PHASE_REFERENCE");
      if (common::HasColumn(table, columnName)) {
        ROScalarMeasColumn<MPosition> c_reference(table, columnName);
        MPosition mReference =
            MPosition::Convert(c_reference(id), MPosition::ITRF)();
        MVPosition mvReference = mReference.getValue();
        phase_reference = {mvReference(0), mvReference(1), mvReference(2)};
      }
      return phase_reference;
    }
    
    Station::Ptr ReadLofarStation(const MeasurementSet &ms, unsigned int id,
                                  const ElementResponseModel model) {
      ROMSAntennaColumns antenna(ms.antenna());
      assert(antenna.nrow() > id && !antenna.flagRow()(id));
    
      // Get station name.
      const string name(antenna.name()(id));
    
      // Get station position (ITRF).
      MPosition mPosition =
          MPosition::Convert(antenna.positionMeas()(id), MPosition::ITRF)();
      MVPosition mvPosition = mPosition.getValue();
      const vector3r_t position = {{mvPosition(0), mvPosition(1), mvPosition(2)}};
    
      // Create station.
      Station::Ptr station(new Station(name, position, model));
    
      // Read phase reference position (if available).
      station->SetPhaseReference(ReadStationPhaseReference(ms.antenna(), id));
    
      // Read antenna field information.
      ROScalarColumn<String> telescope_name_col(
          common::GetSubTable(ms, "OBSERVATION"), "TELESCOPE_NAME");
      string telescope_name = telescope_name_col(0);
    
      if (telescope_name == "LOFAR") {
        Table tab_field = common::GetSubTable(ms, "LOFAR_ANTENNA_FIELD");
        tab_field = tab_field(tab_field.col("ANTENNA_ID") == static_cast<Int>(id));
    
        // The Station will consist of a BeamFormer that combines the fields
        // coordinate system is ITRF
        // phase reference is station position
        auto beam_former = BeamFormer::Ptr(new BeamFormer(
            Antenna::IdentityCoordinateSystem, station->GetPhaseReference()));
    
        for (size_t i = 0; i < tab_field.nrow(); ++i) {
          beam_former->AddAntenna(
              ReadAntennaField(tab_field, i, station->GetElementResponse()));
        }
    
        // TODO
        // If There is only one field, the top level beamformer is not needed
        // and the station antenna can be set the the beamformer of the field
    
        station->SetAntenna(beam_former);
    
        size_t field_id = 0;
        size_t element_id = 0;
        Antenna::CoordinateSystem coordinate_system =
            common::ReadCoordinateSystem(tab_field, field_id);
        auto model = station->GetElementResponse();
        // TODO: rotate coordinate system for antenna
        auto element =
            Element::Ptr(new Element(coordinate_system, model, element_id));
        station->SetElement(element);
      } else if (telescope_name == "AARTFAAC") {
        ROScalarColumn<String> ant_type_col(common::GetSubTable(ms, "OBSERVATION"),
                                            "AARTFAAC_ANTENNA_TYPE");
        string ant_type = ant_type_col(0);
    
        Table tab_field = common::GetSubTable(ms, "ANTENNA");
        station->SetAntenna(ReadAntennaFieldAartfaac(tab_field, ant_type, id));
      }
    
      return station;
    }
    
    MDirection ReadTileBeamDirection(const casacore::MeasurementSet &ms) {
      MDirection tileBeamDir;
    
      Table fieldTable = common::GetSubTable(ms, "FIELD");
    
      if (fieldTable.nrow() != 1) {
        throw std::runtime_error(
            "MS has multiple fields, this does not work with the LOFAR beam "
            "library.");
      }
    
      if (common::HasColumn(fieldTable, "LOFAR_TILE_BEAM_DIR")) {
        ROArrayMeasColumn<MDirection> tileBeamCol(fieldTable,
                                                  "LOFAR_TILE_BEAM_DIR");
        tileBeamDir = *(tileBeamCol(0).data());
      } else {
        ROArrayMeasColumn<MDirection> tileBeamCol(fieldTable, "DELAY_DIR");
        tileBeamDir = *(tileBeamCol(0).data());
      }
    
      return tileBeamDir;
    }
    
    }  // namespace everybeam