targets.py 14.7 KB
#from math import pi, sin, cos, fmod, tan, atan, fabs, atan2, asin, acos, sqrt
import doctest


try:
    from .dates import Date
except:
    from dates import Date

try:
    from .angles import Angle
except:
    from angles import Angle

try:
    from .coords import Coords
except:
    from coords import Coords

try:
    from .mechanics import Mechanics
except:
    from mechanics import Mechanics

try:
    from .guitastrotools import GuitastroTools
except:
    from guitastrotools import GuitastroTools

# ========================================================
# ========================================================
# === TARGETS
# ========================================================
# ========================================================

class Target(Mechanics, GuitastroTools):
    """ Class to compute planets for astronomy
    """
# ========================================================
# === attributs
# ========================================================

    # analytical fit methods
    _TYPE_UNKNOWN = 0
    _TYPE_PLANET = 1
    _TYPE_STAR = 2
    _TYPE_COORD_RADEC = 3
    _TYPE_COORD_HADEC = 4
    _TYPE_COORD_ALTAZ = 5

    _target_input = dict()
    _target_type = _TYPE_UNKNOWN

# ========================================================
# === internal methods : Generals
# ========================================================

    def _init_target(self,*args,**kwargs):
        """ Object initialization

        :param planet_name: A string (cf. help(PLanet))
        :type planet_name: string

        skyobj= {'planet':'Sun'}
        target.define(skyobj)
        or
        name = 'Sun'
        target.define(planet=name)

        """
        #print("1.*args={}".format(args))
        #print("1.**kwargs={}".format(kwargs))
        if (len(kwargs)==0):
            if (len(args)==0):
                dics = {'planet':'Sun'}
                self._define_resolver(*args,**dics)
        else:
            self._define_resolver(*args,**kwargs)
        return

    def _define_resolver(self,*args,**kwargs):
        """ Resolve the definition of the target

        :param **kwargs: keys:values of parameter
        :type **kwargs: dict
        """
        #print("2.*args={}".format(args))
        #print("2.**kwargs={}".format(kwargs))
        # ========= ?
        if (len(kwargs)==0):
            if (len(args)==0):
                return self._target_type, self._target_input
            elif (args[0]=="?"):
                res = "Dictionary keys: "
                res += "planet, ra, dec, equinox, epoch, mura, mudec, plx"
                return res
            else:
                kwargs = args[0]
        #print("3.*args={}".format(args))
        #print("3.**kwargs={}".format(kwargs))
        # ========= change keys into upper strings
        self._target_type = self._TYPE_UNKNOWN
        self._target_input = dict()
        dics = dict()
        for k,v in kwargs.items():
            ku = str(k).upper()
            if (type(v) is str):
                v = v.strip()
            dic = { ku : v }
            dics.update(dic)
        #print("dics={}".format(dics))
        # ========= name
        xxx_names = ['NAME'] ; # string of the name
        for xxx_name in xxx_names:
            if dics.get(xxx_name,'None')!='None':
                dic = { 'NAME' : dics[xxx_name] }
                self._target_input.update(dic)
                break
        # ========= search for a planet
        if dics.get('STAR','None')!='None':
            star_name = (dics['STAR']).strip()
            sn = (star_name).upper()
            if (sn == "SUN"):
                self._target_type = self._TYPE_PLANET
                dic = { 'PLANET' : sn }
                self._target_input.update(dic)
            else:
                self._target_type = self._TYPE_STAR
                dic = { 'STAR' : sn }
                self._target_input.update(dic)
        if (self._target_type != self._TYPE_UNKNOWN):
            return self._target_type
        # ========= search for a planet
        planet_names = {'SUN':'Sun', 'MER':'Mercury', 'VEN':'Venus', 'MAR':'Mars', 'JUP':'Jupiter', 'SAT':'Saturn', 'URA':'Uranus', 'NEP':'Neptune', 'PLU':'Pluto', 'MOO':'Moon', 'ELP':'ELP-Moon'}
        if dics.get('PLANET','None')!='None':
            planet_name = (dics['PLANET']).strip()
            if len(planet_name)>=3:
                p = (planet_name[0:3]).upper()
                if (p in planet_names):
                    self._target_type = self._TYPE_PLANET
                    dic = { 'PLANET' : planet_names[p] }
                    self._target_input.update(dic)
        if (self._target_type != self._TYPE_UNKNOWN):
            return self._target_type
        # ========= search for coords ra,dec
        dic0s = dict()
        ra_names = ['RA','R.A','R.A.','RIGHT ASCENSION']
        for ra_name in ra_names:
            if dics.get(ra_name,'None')!='None':
                dic = { 'RA' : dics[ra_name] }
                dic0s.update(dic)
                break
        dec_names = ['DEC','DEC.','DECL.','DECLINATION']
        for dec_name in dec_names:
            if dics.get(dec_name,'None')!='None':
                dic = { 'DEC' : dics[dec_name] }
                dic0s.update(dic)
                break
        equ_names = ['EQUINOX','EQU']
        for equ_name in equ_names:
            if dics.get(equ_name,'None')!='None':
                dic = { 'EQUINOX' : dics[equ_name] }
                dic0s.update(dic)
                break
        epo_names = ['EPOCH','EP','EPO']
        for epo_name in epo_names:
            if dics.get(epo_name,'None')!='None':
                dic = { 'EPOCH' : dics[epo_name] }
                dic0s.update(dic)
                break
        xxx_names = ['MURA','MU RA','MU R.A','MU R.A.'] ; # mas/yr
        for xxx_name in xxx_names:
            if dics.get(xxx_name,'None')!='None':
                dic = { 'MURA' : dics[xxx_name] }
                dic0s.update(dic)
                break
        xxx_names = ['MUDEC','MU DEC','MU DEC.','MU DECL.'] ; # mas/yr
        for xxx_name in xxx_names:
            if dics.get(xxx_name,'None')!='None':
                dic = { 'MUDEC' : dics[xxx_name] }
                dic0s.update(dic)
                break
        xxx_names = ['PLX','PARALLAX','PI'] ; # mas
        for xxx_name in xxx_names:
            if dics.get(xxx_name,'None')!='None':
                dic = { 'PLX' : dics[xxx_name] }
                dic0s.update(dic)
                break
        if (dic0s.get('RA','None')!='None') and (dic0s.get('DEC','None')!='None'):
            self._target_type = self._TYPE_COORD_RADEC
            if (dic0s.get('EQUINOX','None')=='None'):
                dic = { 'EQUINOX' : 'J2000' }
                dic0s.update(dic)
            if (dic0s.get('EPOCH','None')=='None'):
                dic = { 'EPOCH' : 'J2000' }
                dic0s.update(dic)
            if (dic0s.get('MURA','None')=='None'):
                dic = { 'MURA' : 0 }
                dic0s.update(dic)
            if (dic0s.get('MUDEC','None')=='None'):
                dic = { 'MUDEC' : 0 }
                dic0s.update(dic)
            if (dic0s.get('PLX','None')=='None'):
                dic = { 'PLX' : 0 }
                dic0s.update(dic)
            self._target_input.update(dic0s)
        if (self._target_type != self._TYPE_UNKNOWN):
            return self._target_type
        # ========= coords ha,dec
        dic0s = dict()
        xxx_names = ['HA','H.A','H.A.','HOUR ANGLE']
        for xxx_name in xxx_names:
            if dics.get(xxx_name,'None')!='None':
                dic = { 'HA' : dics[xxx_name] }
                dic0s.update(dic)
                break
        dec_names = ['DEC','DEC.','DECL.','DECLINATION']
        for dec_name in dec_names:
            if dics.get(dec_name,'None')!='None':
                dic = { 'DEC' : dics[dec_name] }
                dic0s.update(dic)
                break
        if (dic0s.get('HA','None')!='None') and (dic0s.get('DEC','None')!='None'):
            self._target_type = self._TYPE_COORD_HADEC
            self._target_input.update(dic0s)
        if (self._target_type != self._TYPE_UNKNOWN):
            return self._target_type
        # ========= coords alt, az
        dic0s = dict()
        xxx_names = ['AZ','AZIMUT','AZIMUTH','AZIMUTAL']
        for xxx_name in xxx_names:
            if dics.get(xxx_name,'None')!='None':
                dic = { 'AZ' : dics[xxx_name] }
                dic0s.update(dic)
                break
        xxx_names = ['ELEV','ELEVATION','ELEV.','ALTITUDE','ALT','ALT.']
        for xxx_name in xxx_names:
            if dics.get(xxx_name,'None')!='None':
                dic = { 'ELEV' : dics[xxx_name] }
                dic0s.update(dic)
                break
        if (dic0s.get('AZ','None')!='None') and (dic0s.get('ELEV','None')!='None'):
            self._target_type = self._TYPE_COORD_ALTAZ
            self._target_input.update(dic0s)
        if (self._target_type != self._TYPE_UNKNOWN):
            return self._target_type
        # ================================================
        #print("self._target_type={}".format(self._target_type))
        #print("self._target_input={}".format(self._target_input))
        # ================================================
        return self._target_type, self._target_input

# ========================================================
# === internal methods :
# ========================================================


# ========================================================
# === target methods
# ========================================================

    def get(self):
        return self._target_type, self._target_input

    def ephem(self, date_utc, siteobs, outputs="", options=""):

        if (self._target_type == self._TYPE_UNKNOWN):
            raise Exception
            return ""

        # === PLANETS
        if (self._target_type == self._TYPE_PLANET):
            planet_name = self._target_input['PLANET']
            # --- get outputs
            if (outputs==""):
                outputs = ['ra','dec','equinox']
            # --- get options
            astrometric = 1
            equinox = Date("J2000").jd()
            if isinstance(options, dict):
                # --- change keys into upper strings
                self._target_type = self._TYPE_UNKNOWN
                self._target_input = dict()
                dics = dict()
                for k,v in options.items():
                    ku = str(k).upper()
                    if (type(v) is str):
                        v = v.strip()
                    dic = { ku : v }
                    dics.update(dic)
                # --- possible options are astrometric and equinox
                if dics.get('ASTROMETRIC','None')!='None':
                    astrometric = int(options['ASTROMETRIC'])
                if dics.get('EQUINOX','None')!='None':
                    equinox = Date(options['EQUINOX']).jd()
            # --- ephemeris for the given equinox
            longmpc, rhocosphip, rhosinphip = siteobs.lrr
            results = self._mc_ephem_planet(planet_name, date_utc, longmpc, rhocosphip, rhosinphip, astrometric, equinox, outputs)
        # === COORD_RADEC
        if (self._target_type == self._TYPE_COORD_RADEC):
            longmpc, rhocosphip, rhosinphip = siteobs.lrr
            tk = siteobs.temperature
            ppa = siteobs.pressure
            hump = siteobs.humidity
            lnm = 550 ; # lambda (nm)
            ra=0; dec=0; equinox=Date("J2000").jd(); epoch=Date("J2000").jd(); mura=0; mudec=0; plx=0
            ra = self._target_input['RA']
            ra = Angle(ra).deg()
            dec = self._target_input['DEC']
            dec = Angle(dec).deg()
            #print("-10. ra={} dec={}".format(ra,dec))
            equinox= Date(self._target_input['EQUINOX']).jd()
            epoch= Date(self._target_input['EPOCH']).jd()
            mura = self._target_input['MURA']; # mas/yr
            mudec = self._target_input['MUDEC']; # mas/yr
            plx = self._target_input['PLX']; # mas
            results = self._mc_radec2app(date_utc, longmpc, rhocosphip, rhosinphip, ra, dec, equinox, epoch, mura, mudec, plx,  tk,ppa,hump,lnm, outputs)
        return results

    def define(self, *args, **kwargs):
        return self._define_resolver(*args, **kwargs)

# ========================================================
# === get/set methods
# ========================================================

# ========================================================
# === special methods
# ========================================================

    def __init__(self,*args,**kwargs):
        """ Object initialization
        """
        self._init_target(*args,**kwargs)
		  # super().__init__()

# #####################################################################
# #####################################################################
# #####################################################################
# Main
# #####################################################################
# #####################################################################
# #####################################################################


if __name__ == "__main__":

    example = 1
    print("Example       = {}".format(example))

    # --- Import the module guitastro
    import os, sys
    path = os.path.join(os.path.dirname(__file__), '..')
    if path not in sys.path:
        sys.path.append(path)
    # --- guitastro imports
    modulename = 'guitastro'
    if modulename in dir():
        del guitastro
    if modulename not in dir():
        import guitastro
    # ---

    if example == 1:
        """
        Simple example to compute Sun coordinates
        """
        # First we compute RA, DEC coordinates of the Sun:
        date = guitastro.Date("now")
        siteobs = guitastro.Siteobs("GPS 0 E 49 200")
        name = "Sun"
        print(f"{name} at {date.iso()} in {siteobs.gps}")
        skyobj= {'planet':name}
        outputs = ['elev']
        target = guitastro.Target()
        target.define(skyobj)
        output0s = ['ra','dec']
        results = target.ephem(date, siteobs, output0s)
        for key, val in results.items():
            print(f"{key} = {val}")
        ra = results['RA']
        dec = results['DEC']
        # Second, we inject RA, DEC to compute local coordinates:
        skyobj= {'RA':ra , 'DEC':dec }
        target.define(skyobj)
        results = target.ephem(date,siteobs,outputs)
        for key, val in results.items():
            print(f"{key} = {val}")