Skip to content
Snippets Groups Projects
Select Git revision
  • e162122e2a57b82cb0b9b96263d24a682ecdbab9
  • master default protected
  • use_flight_altitude
  • distribute
4 results

geos_nav.py

Blame
  • user avatar
    tomrink authored
    bfe53e76
    History
    geos_nav.py 5.31 KiB
    import numpy as np
    
    
    DEG_TO_RAD = np.pi/180.0;
    RAD_TO_DEG = 180.0/np.pi;
    r_pol = 6356.5838  # km
    r_eq = 6378.1690  # km
    
    # AHI -------------------------------
    # h = 42164.0  # barycentric height, km
    # sub_lon = 140.7
    # sub_lon *= DEG_TO_RAD
    # scan_geom = 'GEOS'
    # signs modified from static nav file to work with ABI FGF code
    # CFAC = 5.588799E-05
    # LFAC = -5.588799E-05
    # COFF = -0.1537199
    # LOFF = 0.1537199
    
    # computed from static nav file (lon, lat) grid
    # Note 0-based to the pixel center
    # CFAC = 5.58924125e-05
    # LFAC = -5.58810490e-05
    # COFF = -1.53678977e-01
    # LOFF = 1.53644345e-01
    
    # GOES ------------------------------
    h = 42164.16 # barycentric height, km
    scan_geom = 'GOES'
    # GOES-17 sub_lon = -137.0
    sub_lon = -75.0
    sub_lon *= DEG_TO_RAD
    
    # official for FD
    CFAC = 5.6E-05
    LFAC = -5.6E-05
    COFF = -0.151844
    LOFF = 0.151844
    
    # official for CONUS
    #CFAC = 5.6E-05
    #COFF = -0.101332
    #LFAC = -5.6E-05
    #LOFF = 0.128212
    
    # computed for CLAVRx FD
    #CFAC = 5.60016368e-05
    #LFAC = -5.59941969e-05
    #COFF = -1.51780260e-01
    #LOFF = 1.51773560e-01
    
    # 65536 = 2^16
    
    
    class GEOSNavigation:
        def __init__(self, sub_lon=-75.0, barycentric_height=42164.16, scan_geom='GOES', CFAC=5.6E-05, LFAC=-5.6E-05, COFF=-0.151844, LOFF=0.151844, num_elems=5424, num_lines=5424):
            self.sub_lon = sub_lon * DEG_TO_RAD
            self.h = barycentric_height
            self.scan_geom = scan_geom
            self.CFAC = CFAC
            self.LFAC = LFAC
            self.COFF = COFF
            self.LOFF = LOFF
            self.num_lines = num_lines
            self.num_elems = num_elems
    
        def earth_to_sat(self, geographic_lon, geographic_lat):
    
            geographic_lon *= DEG_TO_RAD
            geographic_lat *= DEG_TO_RAD
    
            geocentric_lat = np.arctan(((r_pol*r_pol)/(r_eq*r_eq))*np.tan(geographic_lat))
    
            r_earth = r_pol / np.sqrt(1.0 - ((r_eq * r_eq - r_pol * r_pol) / (r_eq * r_eq)) * np.cos(geocentric_lat) * np.cos(geocentric_lat))
    
            r_1 = self.h - r_earth * np.cos(geocentric_lat) * np.cos(geographic_lon - self.sub_lon)
            r_2 = -r_earth * np.cos(geocentric_lat) * np.sin(geographic_lon - self.sub_lon)
            r_3 = r_earth * np.sin(geocentric_lat)
    
            if r_1 > self.h:
                return np.nan, np.nan
    
            if self.scan_geom == 'GEOS':
                lamda_sat = np.arctan(-r_2/r_1)
                theta_sat = np.arcsin(r_3/np.sqrt(r_1*r_1 + r_2*r_2 + r_3*r_3))
            elif self.scan_geom == 'GOES':
                lamda_sat = np.arcsin(-r_2/np.sqrt(r_1*r_1 + r_2*r_2 + r_3*r_3))
                theta_sat = np.arctan(r_3/r_1)
    
            return lamda_sat, theta_sat
    
        def earth_to_sat_s(self, geographic_lon, geographic_lat):
    
            geographic_lon = geographic_lon * DEG_TO_RAD
            geographic_lat = geographic_lat * DEG_TO_RAD
    
            geocentric_lat = np.arctan(((r_pol*r_pol)/(r_eq*r_eq))*np.tan(geographic_lat))
    
            r_earth = r_pol / np.sqrt(1.0 - ((r_eq * r_eq - r_pol * r_pol) / (r_eq * r_eq)) * (np.cos(geocentric_lat))**2)
    
            r_1 = self.h - r_earth * np.cos(geocentric_lat) * np.cos(geographic_lon - self.sub_lon)
            r_2 = -r_earth * np.cos(geocentric_lat) * np.sin(geographic_lon - self.sub_lon)
            r_3 = r_earth * np.sin(geocentric_lat)
    
            if self.scan_geom == 'GEOS':
                lamda_sat = np.arctan(-r_2/r_1)
                theta_sat = np.arcsin(r_3/np.sqrt(r_1*r_1 + r_2*r_2 + r_3*r_3))
            elif self.scan_geom == 'GOES':
                lamda_sat = np.arcsin(-r_2/np.sqrt(r_1*r_1 + r_2*r_2 + r_3*r_3))
                theta_sat = np.arctan(r_3/r_1)
    
            np.where(r_1 > self.h, lamda_sat == np.nan, lamda_sat)
            np.where(r_1 > self.h, theta_sat == np.nan, theta_sat)
    
            return lamda_sat, theta_sat
    
        def sat_to_lc(self, lamda, theta):
            # c = COFF + np.rint(lamda * (1/np.power(2, 16)) * CFAC)
            # l = LOFF + np.rint(theta * (1/np.power(2, 16)) * LFAC)
    
            # (float(2 ** 16) * (float(lc) - off)) / float(fac) * DEG_TO_RAD
    
            cc = (lamda - self.COFF) / self.CFAC
            ll = (theta - self.LOFF) / self.LFAC
    
            cc = np.floor(cc + 0.5)
            ll = np.floor(ll + 0.5)
    
            cc = cc.astype(np.int32)
            ll = ll.astype(np.int32)
    
            return cc, ll
    
        def earth_to_lc(self, lon, lat):
            lamda, theta = self.earth_to_sat(lon, lat)
            if np.isnan(lamda):
                return None, None
            cc, ll = self.sat_to_lc(lamda, theta)
            return cc, ll
    
        def earth_to_lc_s(self, lons, lats):
            lamda, theta = self.earth_to_sat_s(lons, lats)
            cc, ll = self.sat_to_lc(lamda, theta)
            np.where(np.isnan(cc), cc == -1, cc)
            np.where(np.isnan(ll), ll == -1, ll)
            return cc, ll
    
        def earth_to_indexs(self, lons, lats, len_x):
            num = lons.shape[0]
            idxs = []
            for i in range(num):
                cc, ll = self.earth_to_lc(lons[i], lats[i])
                if cc is None:
                    idxs.append(-1)
                else:
                    idx = ll * len_x + cc
                    idxs.append(idx)
            idxs = np.array(idxs)
    
            return idxs
    
        def check_inside(self, lon, lat):
            return True
    
    
    def get_navigation(satellite='GOES16', domain='FD'):
        nav = None
        if satellite == 'GOES16':
            if domain == 'FD':
                nav = GEOSNavigation()
            elif domain == 'CONUS':
                pass
        elif satellite == 'GOES17':
            if domain == 'FD':
                nav = GEOSNavigation(sub_lon=-137.0)
            elif domain == 'CONUS':
                pass
    
        return nav