In [ ]:
import astropy.coordinates as ac
import astropy.units as au
import astropy.time as at
import numpy as np
import sys

class RadioArray(object):
    '''Handles the radio array object.'''
    def __init__(self,arrayFile = None,antennaPos=None,name = None,msFile=None,numAntennas=0,earthLocs=None,frequency=120e6):
        self.frequency = frequency#can be widebandwidth later
        self.Nantenna = 0
        if arrayFile is not None:
            self.arrayFile = arrayFile
            self.loadArrayFile(arrayFile)
        if antennaPos is not None:
            self.loadPosArray(antennaPos)
            
    def loadArrayFile(self,arrayFile):
        '''Loads a csv where each row is x,y,z in geocentric ITRS coords of the antennas'''
        
        try:
            types = np.dtype({'names':['X','Y','Z','diameter','station_label'],
                             'formats':[np.double,np.double,np.double,np.double,'S16']})
            d = np.genfromtxt(arrayFile,comments = '#',dtype=types)
            self.diameters = d['diameter']
            self.labels = d['station_label'].astype(str)
            self.locs = ac.SkyCoord(x=d['X']*au.m,y=d['Y']*au.m,z=d['Z']*au.m,frame='itrs')
            self.Nantenna = int(np.size(d['X']))
        except:
            d = np.genfromtxt(arrayFile,comments = '#',usecols=(0,1,2))
            self.locs = ac.SkyCoord(x=d[:,0]*au.m,y=d[:,1]*au.m,z=d[:,2]*au.m,frame='itrs')
            self.Nantenna = d.shape[0]
            self.labels = np.arange(self.Nantenna)
            self.diameters = None
        self.calcCenter()
        
    def getFov(self):
        '''get the field of view in radians'''
        return 4.*np.pi/180.
    
    def saveArrayFile(self,arrayFile):
        import time
        locs = self.locs.cartesian.xyz.to(au.m).value.transpose()
        f = open(arrayFile,'w')
        f.write('# Created on {0} by Joshua G. Albert\n'.format(time.strftime("%a %c",time.localtime())))
        f.write('# ITRS(m)\n')
        f.write('# X\tY\tZ\tdiameter\tlabels\n')
        i = 0
        while i < self.Nantenna:
            if self.diameters is not None:
                f.write('{0:1.9e}\t{1:1.9e}\t{2:1.9e}\t{3:1.4e}\t{4}'.format(locs[i,0],locs[i,1],locs[i,2],self.diameters[i],self.labels[i]))
            else:
                f.write('{0:1.9e}\t{1:1.9e}\t{2:1.9e}\t{3:d}\t{4}'.format(locs[i,0],locs[i,1],locs[i,2],-1,self.labels[i]))
            if i < self.Nantenna-1:
                f.write('\n')
            i += 1
        f.close()
        
    def loadPosArray(self,antennaPos):
        '''Load pos is shape (N,3), typically grabbed from a ms/ANTENNA table.
        Assumes it is in ITRS(m)'''
        self.locs = ac.SkyCoord(x=antennaPos[:,0]*au.m,y=antennaPos[:,1]*au.m,z=antennaPos[:,2]*au.m,frame='itrs')
        self.Nantenna = antennaPos.shape[0]
        self.calcCenter()

    def calcCenter(self):
        '''calculates the centroid of the array based on self.locs returns the ITRS of center'''
        center = np.mean(self.locs.cartesian.xyz,axis=1)
        self.center = ac.SkyCoord(x=center[0],y=center[1],z=center[2],frame='itrs')
        
        #n = self.center.itrs.earth_location.geocentric.to(au.m).value
        #self.n = n/np.sqrt(n[0]**2 + n[1]**2 + n[2]**2)
        return self.center
    
    def getCenter(self):
        '''Return the ITRS center of the array'''
        try:
            return self.center
        except:
            self.calcCenter()
            self.log("Center of array: {0}".format(self.center))
            return self.center
    
    def getAntennaIdx(self,name):
        '''Retrieve the index of the given name from labels.
        Returns None if no match.'''
        i = 0
        while i < self.Nantenna:
            if self.labels[i] == name:
                return i
            i += 1
        return None
    
    def getSunZenithAngle(self,time):
        '''Return the solar zenith angle in degrees at the given time.'''
        frame = ac.AltAz(location=self.getCenter().earth_location,obstime=time)
        sun = ac.get_sun(time).transform_to(frame)
        return 90. - sun.alt.deg
    
    def __repr__(self):
        return "Radio Array: {0:1.5e} MHz, Longitude {1:.2f} Latitude {2:.2f} Height {3:.2f}".format(self.frequency,*self.getCenter().earth_location.to_geodetic('WGS84'))

if __name__=='__main__':
    #from Logger import Logger
    #logger = Logger()
    radioArray = RadioArray(arrayFile='arrays/lofar.hba.antenna.cfg')
    print(radioArray.labels)