#-----------------------------------------------------------------------
# This script duplicates the task inter-sensitivity.f90 in pure Python
#-----------------------------------------------------------------------

import math

clight = 299792458.0  # [m/s] Light velocity
kbolt  = 1.3806504e-23  # [J/K] Boltzman
rad_per_sec = math.pi/(180*3600)

class Inter_Sensitivity:

  def __init__(self,freq,bandwidth,npol,tsys,decorrel,ontime,nant,anteff,beam):
    self.freq = freq            # [GHz]
    self.bandwidth = bandwidth  # [MHz]
    self.npol = npol            #
    self.tsys = tsys            # [K]
    self.decorrel = decorrel    #
    self.ontime = ontime        # [hrs]
    self.nant = nant            #
    self.anteff = anteff        #
    self.beam = beam            # [arcsec]
    self.velres = 1e-6*(clight*bandwidth/freq)  # [km/s]
    self.lambd = 1e-6*clight/freq               # [mm]

  def display_inputs(self):
    out  = [ "" ]
    out += [ " Interferometer Sensitivity" ]
    out += [ " --------------------------" ]
    out += [ "" ]
    out += [ " Frequency:                    %9.3f GHz"  % (self.freq,) ]
    out += [ " Wavelength:                   %9.3f mm"   % (self.lambd,) ]
    out += [ "" ]
    out += [ " Number of polarizations:      %5i"        % (self.npol,) ]
    out += [ " Frequency resolution:         %9.3f MHz"  % (self.bandwidth,) ]
    out += [ " Velocity resolution:          %9.3f km/s" % (self.velres,) ]
    out += [ "" ]
    out += [ " Tsys:                         %9.1f K"    % (self.tsys,) ]
    out += [ " Decorrelation coefficient:    %9.1f"      % (self.decorrel,) ]
    out += [ " On-source integration time:   %9.1f hrs"  % (self.ontime,) ]
    out += [ "" ]
    out += [ " Number of available antennas: %5i"        % (self.nant,) ]
    out += [ " Antenna efficiency:           %9.1f Jy/K" % (self.anteff,) ]
    out += [ " Beam:                         %3.1f x %3.1f arcsec" % (self.beam[0],self.beam[1]) ]
    out += [ "" ]
    #
    return out

  def compute(self):
    self.bandwidth = self.bandwidth*1e6      # [Hz]
    self.freq = self.freq*1e9                # [Hz]
    self.ontime = self.ontime*3600.          # [s]
    self.beam[0] = self.beam[0]*rad_per_sec  # [rad]
    self.beam[1] = self.beam[1]*rad_per_sec  # [rad]
    self.nbas = self.nant*(self.nant-1)      # number of baselines
    #
    # In point source sensitivity, everything except the beam counts while
    # sensitivity expressed in main beam temperature obviously needs the
    # beam information.
    self.rms = self.anteff*self.tsys/(self.decorrel*math.sqrt(self.bandwidth*self.ontime*self.nbas*self.npol))
    self.jyperk = 2.*(kbolt*1e32)*math.pi*self.beam[0]*self.beam[1]/4./math.log(2.0)/self.lambd**2
    self.jyperk = 1./self.jyperk
    self.Trms = self.jyperk*self.rms

  def display_outputs(self):
    out  = [ "" ]
    out += [ " Conversion factor:            %9.1f K[Tmb] per Jy/beam" % (self.jyperk,) ]
    #
    if ((self.rms < 1e-1) and (self.rms >= 1e-3)):
      out += [ " Point source sensitivity:     %9.1f mJy"     % (self.rms*1e3,) ]
    elif ((self.rms < 1e-3) and (self.rms >= 1e-6)):
      out += [ " Point source sensitivity:     %9.1f microJy" % (self.rms*1e6,) ]
    else:
      out += [ " Point source sensitivity:     %9.1f Jy"      % (self.rms,) ]
    #
    if ((self.Trms < 1e-1) and (self.Trms >= 1e-3)):
      out += [ " rms brightness temperature:   %9.1f mK[Tmb]"     % (self.Trms*1e3,) ]
    elif ((self.Trms < 1e-3) and (self.Trms >= 1e-6)):
      out += [ " rms brightness temperature:   %9.1f microK[Tmb]" % (self.Trms*1e6,) ]
    else:
      out += [ " rms brightness temperature:   %9.1f K[Tmb]"      % (self.Trms,) ]
    #
    out += [ "" ]
    out += [ " --------------------------" ]
    #
    return out

  def execute(self):
    out = self.display_inputs()
    self.compute()
    out += self.display_outputs()
    return out
