targets.py 14.2 KB
#from math import pi, sin, cos, fmod, tan, atan, fabs, atan2, asin, acos, sqrt
import doctest
from celme.angles import Angle
from celme.dates import Date
from celme.coords import Coords
from celme.mechanics import Mechanics
#from celme.site import Site

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

class Target(Mechanics):
    """ 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, site, 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 = site.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 = site.lrr
            tk = site.temperature
            ppa = site.pressure
            hump = site.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
# ========================================================

    
# ========================================================
# === debug methods
# ========================================================
    
    def infos(self, action) -> None:
        """ To get informations about this class
        
        :param action: A command to run a debug action (see examples).
        :type action: string
        
        :Example:
            
        Target().infos("doctest")
        Target().infos("doc_methods")
        Target().infos("internal_attributes")
        Target().infos("public_methods")        
        """
        if (action == "doc_methods"):
            publics = [x for x in dir(self) if x[0]!="_"]
            for public in publics:
                varname = "{}".format(public)
                if (callable(getattr(self,varname))==True):
                    print("\n{:=^40}".format(" method "+varname+" "))
                    t = "Target()."+varname+".__doc__"
                    tt =eval(t)
                    print(tt)
        if (action == "doctest"):
            if __name__ == "__main__":
                print("\n{:~^40}".format("doctest"))
                doctest.testmod(verbose=False)
        if (action == "internal_attributes"):
            internals = [x for x in dir(self) if x[0]=="_" and x[1]!="_"]
            for internal in internals:
                varname = "{}".format(internal)
                #if (hasattr(self,varname)==True):
                if (callable(getattr(self,varname))==False):
                    print(varname + "=" + str(getattr(self,varname)))
        if (action == "public_methods"):
            publics = [x for x in dir(self) if x[0]!="_"]
            for public in publics:
                varname = "{}".format(public)
                if (callable(getattr(self,varname))==True):
                    print(varname)

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