#!/usr/bin/env python
"""
Defines classes for holding beam maps and models for ASKAP
Copyright (C) CSIRO 2017
"""
import numpy as np
from aces.obsplan.config import ACESConfig
[docs]class BeamBase(object):
"""
A base class for holding and providing information about beams.
The subclasses in mind are BeamFormed and BeamSingleports.
:param int num_beams: number of beams
:param offsets_rect: rectangular offsets in l,m about antenna boresight
:type offsets_rect: :class:`numpy.ndarray` of dimension (num_beams, 2)
"""
def __init__(self, num_beams=0, offsets_rect=None):
# check valid inputs
self.numBeams = num_beams
if offsets_rect is None:
self.offsetsRect = np.zeros([0, 2])
else:
self.offsetsRect = offsets_rect
if self.numBeams != self.offsetsRect.shape[0]:
raise(ValueError, 'offsets_rect.shape[0] is {} but should equal num_beams which is {}'.format(
self.offsetsRect.shape[0], self.numBeams))
[docs] def get_num_beams(self):
return self.numBeams
[docs] def get_beam_offset(self, beam):
if beam >= self.numBeams:
raise RuntimeError("Illegal beam number requested {:d}".format(beam))
else:
return self.offsetsRect[beam]
[docs]def get_port_positions():
ports_per_pol = 94
irowa = range(6, 2, -1)
irowb = range(8, 0, -1)
irowc = range(9, -1, -1)
rowa = np.array(irowa) - 4.5
rowb = np.array(irowb) - 4.5
rowc = np.array(irowc) - 4.5
na, nb, nc = 4, 8, 10
p1x = na*[10] + nb*[9] + nc*[8] + nc*[7] + nc*[6] + nc*[5] + nc*[4] + nc*[3] + nc*[2] + nb*[1] + na*[0]
xgrid_x = np.concatenate((rowa, rowb,
rowc, rowc, rowc, rowc, rowc, rowc, rowc,
rowb, rowa))
xgrid_y = np.array(p1x) - 5.0
ygrid_x = -xgrid_y
ygrid_y = xgrid_x
num_beams_total = ports_per_pol * 2
xy0 = np.zeros([num_beams_total, 2])
xy0[:ports_per_pol, 0] = -xgrid_x
xy0[:ports_per_pol, 1] = +xgrid_y
xy0[ports_per_pol:, 0] = -ygrid_x
xy0[ports_per_pol:, 1] = +ygrid_y
ang = -3.0 * np.pi/4
c45, s45 = np.cos(ang), np.sin(ang)
posOnPAF = np.zeros([num_beams_total, 2])
posOnPAF[:, 0] = c45 * xy0[:, 0] - s45 * xy0[:, 1]
posOnPAF[:, 1] = s45 * xy0[:, 0] + c45 * xy0[:, 1]
return posOnPAF
[docs]class BeamSinglePorts(BeamBase):
"""
Provides beam information for single port beams
Mounting and geometry errors can be incorporated.
"""
def __init__(self, port_numbers):
"""
Geometry according to the JER green paper
Naming: lower-case x,y denotes which set of ports. Upper case X,Y denotes X,Y position on PAF
Changed 2017-Feb-02 to match view from rear, and orientation used in port gain quiver plots.
"""
pitch = 90.0
fl = 6000.0
plate_scale = 0.86/fl
pos_on_PAF = get_port_positions()
offsets_rect_all = pos_on_PAF * plate_scale*pitch
num_ports_total = offsets_rect_all.shape[0]
num_beams = len(port_numbers)
offsets_rect = np.array([offsets_rect_all[i-1] for i in range(1, num_ports_total+1) if i in port_numbers])
BeamBase.__init__(self, num_beams, offsets_rect)