Source code for ska.sdp.msadd.antenna

"""
This module deals with the storage, construction and writing of Antenna Tables. THere is an internal memory structure.
Essentially an array of dictionaries that hold the antenna information.

"""

from os import path
import json
import urllib.request

from casacore import tables
from astropy.coordinates import EarthLocation

import logging

logger = logging.getLogger(__name__)


[docs]class AntennaTable(object): """ simple class that updates the antenna table using either a JSON object or another table from a reference MS The same class can deal with multiple reference options - in order of preference: It first checks if local MS reference table is given. Then it checks whether a remote file location is given. Finally it checks for a local json file. """ def __init__(self, input_table_name: str = None, json_file_location=None): """ :param str input_table_name: The name of the input (reference) antenna table :param str json_file_location: pull the json file from the gitlab location """ self.antenna_table = [] try: if input_table_name: self.load_table_from_ms(input_table_name) elif json_file_location: if path.exists(json_file_location): with open(json_file_location) as f: self.load_table_from_json(json.load(f)) else: urlData = json_file_location # thanks to Stack Overflow for this ... webURL = urllib.request.urlopen(urlData) data = webURL.read() encoding = webURL.info().get_content_charset('utf-8') self.load_table_from_json(json.loads(data.decode(encoding))) else: logger.error("Antenna table not provided") raise BaseException except (BaseException) as err: raise
[docs] def load_table_from_json(self, data): """ Create an internal array of antenna dictionaries using the JSON format as input :param dict data: Dictionary structure as generated by json.loads - the assumption is that this remains in order """ for antenna in data['antennas']: self.antenna_table.append(antenna)
[docs] def load_table_from_ms(self, input_table_name): """ If the input table name exists - set the input table load the values into a dictionary :param str input_table_name: The actual ANTENNA table in a measurement set """ if path.exists(input_table_name): table = tables.table(input_table_name) else: raise FileExistsError name = table.col("NAME") pos = table.col('POSITION') diam = table.col("DISH_DIAMETER") for row in range(table.nrows()): antenna = {"name": name[row], "dish_diameter": diam[row], "x": pos[row][0], "y": pos[row][1], "z": pos[row][2]} self.antenna_table.append(antenna)
[docs] def get_antenna_pos(self, index): """ Returns the XYZ antenna position as held in the internal representation of the antenna table :param int index: The antenna index as listed in the relevant row of the MAIN table :return position: The XYZ position geocentric of the antenna :rtype: [x, y, z] """ # FIXME: THis assumes that the geoid is WGS84 it should pick this up from the layout assert index < len(self.antenna_table) if 'x' in self.antenna_table[index]: x = self.antenna_table[index].get('x') y = self.antenna_table[index].get('y') z = self.antenna_table[index].get('z') elif 'lat' in self.antenna_table[index]: lat = self.antenna_table[index].get('lat') lon = self.antenna_table[index].get('long') if 'height' in self.antenna_table[index]: height = self.antenna_table[index].get('height') else: height = 0.0 location = EarthLocation.from_geodetic(lat=lat,lon=lon,height=height,ellipsoid='WGS84') (x,y,z) = location.to_geocentric() return [x, y, z]