예제 #1
0
파일: itu676.py 프로젝트: yzl-china/ITU-Rpy
    def zenit_water_vapour_attenuation(self, lat, lon, p, f, V_t=None, h=None):
        f_ref = 20.6  # [GHz]
        p_ref = 815  # [hPa]

        if h is None:
            h = topographic_altitude(lat, lon).value

        if V_t is None:
            V_t = total_water_vapour_content(lat, lon, p, h).value

        rho_ref = V_t / 3.67
        t_ref = 14 * np.log(0.22 * V_t / 3.67) + 3  # [Celsius]

        a = (0.2048 * np.exp(-((f - 22.43) / 3.097)**2) +
             0.2236 * np.exp(-((f - 183.5) / 4.096)**2) +
             0.2073 * np.exp(-((f - 325) / 3.651)**2) - 0.113)

        b = 8.741e4 * np.exp(-0.587 * f) + 312.2 * f**(-2.38) + 0.723
        h = np.minimum(h, 4)

        gammaw_approx_vect = np.vectorize(self.gammaw_approx)

        Aw_term1 = (0.0176 * V_t *
                    gammaw_approx_vect(f, p_ref, rho_ref, t_ref + 273.15) /
                    gammaw_approx_vect(f_ref, p_ref, rho_ref, t_ref + 273.15))

        return np.where(f < 20, Aw_term1, Aw_term1 * (a * h**b + 1))
예제 #2
0
    def rain_attenuation_probability(self,
                                     lat,
                                     lon,
                                     el,
                                     hs=None,
                                     Ls=None,
                                     P0=None):

        Re = 8500
        if hs is None:
            hs = topographic_altitude(lat, lon).to(u.km).value

        # Step 1: Estimate the probability of rain, at the earth station either
        # from Recommendation ITU-R P.837 or from local measured rainfall
        # rate data
        if P0 is None:
            P0 = rainfall_probability(lat, lon).\
                to(u.dimensionless_unscaled).value

        # Step 2: Calculate the parameter alpha using the inverse of the
        # Q-function alpha = Q^{-1}(P0)  -> Q(alpha) = P0
        alpha = stats.norm.ppf(1 - P0)

        # Step 3: Calculate the spatial correlation function, rho:
        hr = rain_height(lat, lon).value

        if Ls is None:
            Ls = np.where(
                el >= 5,
                (hr - hs) / (np.sin(np.deg2rad(el))),  # Eq. 1
                2 * (hr - hs) / (((np.sin(np.deg2rad(el)))**2 + 2 *
                                  (hr - hs) / Re)**0.5 +
                                 (np.sin(np.deg2rad(el)))))  # Eq. 2

        d = Ls * np.cos(np.deg2rad(el))
        rho = 0.59 * np.exp(-abs(d) / 31) + 0.41 * np.exp(-abs(d) / 800)

        # Step 4: Calculate the complementary bivariate normal distribution
        biva_fcn = np.vectorize(__CDF_bivariate_normal__)
        c_B = biva_fcn(alpha, alpha, rho)

        # Step 5: Calculate the probability of rain attenuation on the slant
        # path:
        P = 1 - (1 - P0) * ((c_B - P0**2) / (P0 * (1 - P0)))**P0
        return P
예제 #3
0
    def rain_attenuation(self,
                         lat,
                         lon,
                         f,
                         el,
                         hs=None,
                         p=0.01,
                         R001=None,
                         tau=45,
                         Ls=None):

        if p < 0.001 or p > 5:
            warnings.warn(
                RuntimeWarning('The method to compute the rain attenuation in '
                               'recommendation ITU-P 618-12 is only valid for '
                               'unavailability values between 0.001 and 5'))

        Re = 8500  # Efective radius of the Earth (8500 km)

        if hs is None:
            hs = topographic_altitude(lat, lon).to(u.km).value

        # Step 1: Compute the rain height (hr) based on ITU - R P.839
        hr = rain_height(lat, lon).value

        # Step 2: Compute the slant path length
        if Ls is None:
            Ls = np.where(
                el >= 5,
                (hr - hs) / (np.sin(np.deg2rad(el))),  # Eq. 1
                2 * (hr - hs) / (((np.sin(np.deg2rad(el)))**2 + 2 *
                                  (hr - hs) / Re)**0.5 +
                                 (np.sin(np.deg2rad(el)))))  # Eq. 2

        # Step 3: Calculate the horizontal projection, LG, of the
        # slant-path length
        Lg = np.abs(Ls * np.cos(np.deg2rad(el)))

        # Obtain the raingall rate, exceeded for 0.01% of an average year,
        # if not provided, as described in ITU-R P.837.
        if R001 is None:
            R001 = rainfall_rate(lat, lon, 0.01).to(u.mm / u.hr).value

        # Step 5: Obtain the specific attenuation gammar using the frequency
        # dependent coefficients as given in ITU-R P.838
        gammar = rain_specific_attenuation(R001, f, el,
                                           tau).to(u.dB / u.km).value

        # Step 6: Calculate the horizontal reduction factor, r0.01,
        # for 0.01% of the time:
        r001 = 1. / (1 + 0.78 * np.sqrt(Lg * gammar / f) - 0.38 *
                     (1 - np.exp(-2 * Lg)))

        # Step 7: Calculate the vertical adjustment factor, v0.01,
        # for 0.01% of the time:
        eta = np.rad2deg(np.arctan2(hr - hs, Lg * r001))

        Lr = np.where(eta > el, Lg * r001 / np.cos(np.deg2rad(el)),
                      (hr - hs) / np.sin(np.deg2rad(el)))

        xi = np.where(np.abs(lat) < 36, 36 - np.abs(lat), 0)

        v001 = 1. / (
            1 + np.sqrt(np.sin(np.deg2rad(el))) *
            (31 *
             (1 - np.exp(-(el /
                           (1 + xi)))) * np.sqrt(Lr * gammar) / f**2 - 0.45))

        # Step 8: calculate the effective path length:
        Le = Lr * v001  # (km)

        # Step 9: The predicted attenuation exceeded for 0.01% of an average
        # year
        A001 = gammar * Le  # (dB)

        # Step 10: The estimated attenuation to be exceeded for other
        # percentages of an average year
        if p >= 1:
            beta = np.zeros_like(A001)
        else:
            beta = np.where(
                np.abs(lat) > 36, np.zeros_like(A001),
                np.where((np.abs(lat) < 36) & (el > 25),
                         -0.005 * (np.abs(lat) - 36),
                         -0.005 * (np.abs(lat) - 36) + 1.8 -
                         4.25 * np.sin(np.deg2rad(el))))

        A = A001 * (p / 0.01)**(
            -(0.655 + 0.033 * np.log(p) - 0.045 * np.log(A001) - beta *
              (1 - p) * np.sin(np.deg2rad(el))))

        return A
예제 #4
0
    def total_attenuation_synthesis(self,
                                    lat,
                                    lon,
                                    f,
                                    el,
                                    p,
                                    D,
                                    Ns,
                                    Ts=1,
                                    hs=None,
                                    tau=45,
                                    eta=0.65,
                                    rho=None,
                                    H=None,
                                    P=None,
                                    hL=1000,
                                    return_contributions=False):
        t_disc = int(5e6)
        # Step A Correlation coefficients:
        C_RC = 1
        C_CV = 0.8

        # Step B Scintillation polynomials
        def a_Fade(p):
            return -0.061 * np.log10(p)**3 + 0.072 * \
                np.log10(p)**2 - 1.71 * np.log10(p) + 3

        def a_Enhanc(p):
            return -0.0597 * np.log10(p)**3 - 0.0835 * \
                np.log10(p)**2 - 1.258 * np.log10(p) + 2.672

        # Step C1-C3:
        n_R = np.random.normal(0, 1, int((Ns * Ts + t_disc)))
        n_L0 = np.random.normal(0, 1, int((Ns * Ts + t_disc)))
        n_V0 = np.random.normal(0, 1, int((Ns * Ts + t_disc)))

        # Step C4-C5:
        n_L = C_RC * n_R + np.sqrt(1 - C_RC**2) * n_L0
        n_V = C_CV * n_L + np.sqrt(1 - C_CV**2) * n_V0

        # Step C6: Compute the rain attenuation time series
        if hs is None:
            hs = topographic_altitude(lat, lon)
        Ar = self.rain_attenuation_synthesis(lat,
                                             lon,
                                             f,
                                             el,
                                             hs,
                                             Ns,
                                             Ts=1,
                                             tau=tau,
                                             n=n_R)
        Ar = Ar[t_disc:]

        # Step C7: Compute the cloud integrated liquid water content time
        # series
        L = self.cloud_liquid_water_synthesis(lat, lon, Ns, Ts=1, n=n_L)
        L = L[t_disc:]
        Ac = L * \
            specific_attenuation_coefficients(f, T=0) / np.sin(np.deg2rad(el))
        Ac = Ac.flatten()

        # Step C9: Identify time stamps where A_R > 0 L > 1
        idx = np.where(np.logical_and(Ar > 0, L > 1))[0]
        idx_no = np.where(np.logical_not(np.logical_and(Ar > 0, L > 1)))[0]

        # Step C10: Discard the previous values of Ac and re-compute them by
        # linear interpolation vs. time starting from the non-discarded cloud
        # attenuations values
        Ac[idx] = np.interp(idx, idx_no, Ac[idx_no])

        # Step C11: Compute the integrated water vapour content time series
        V = self.integrated_water_vapour_synthesis(lat, lon, Ns, Ts=1, n=n_V)
        V = V[t_disc:]

        # Step C12: Convert the integrated water vapour content time series
        # V into water vapour attenuation time series AV(kTs)
        Av = zenit_water_vapour_attenuation(lat, lon, p, f, V_t=V).value

        # Step C13: Compute the mean annual temperature Tm for the location of
        # interest using experimental values if available.
        Tm = surface_mean_temperature(lat, lon).value

        # Step C14: Convert the mean annual temperature Tm into mean annual
        # oxygen attenuation AO following the method recommended in
        # Recommendation ITU-R P.676.
        if P is None:
            P = standard_pressure(hs).value

        if rho is None:
            rho = standard_water_vapour_density(hs).value

        e = Tm * rho / 216.7
        go = gamma0_exact(f, P, rho, Tm).value
        ho, _ = slant_inclined_path_equivalent_height(f, P + e).value
        Ao = ho * go * np.ones_like(Ar)

        # Step C15: Synthesize unit variance scintillation time series
        sci_0 = self.scintillation_attenuation_synthesis(Ns * Ts, Ts=1)

        # Step C16: Compute the correction coefficient time series Cx(kTs) in
        # order to distinguish between scintillation fades and enhancements:
        Q_sci = 100 * stats.norm.sf(sci_0)
        C_x = np.where(sci_0 > 0, a_Fade(Q_sci) / a_Enhanc(Q_sci), 1)

        # Step C17: Transform the integrated water vapour content time series
        # V(kTs) into the Gamma distributed time series Z(kTs) as follows:
        kappa, lambd = self.integrated_water_vapour_coefficients(lat, lon)
        Z = stats.gamma.ppf(1 - np.exp(-(V / lambd)**kappa), 10, 0.1)

        # Step C18: Compute the scintillation standard deviation σ following
        # the method recommended in Recommendation ITU-R P.618.
        sigma = scintillation_attenuation_sigma(lat, lon, f, el, p, D, eta, Tm,
                                                H, P, hL).value

        # Step C19: Compute the scintillation time series sci:
        As = np.where(Ar > 1, sigma * sci_0 * C_x * Z * Ar**(5 / 12),
                      sigma * sci_0 * C_x * Z)

        # Step C20: Compute total tropospheric attenuation time series A(kTs)
        # as follows:
        A = Ar + Ac + Av + Ao + As

        if return_contributions:
            return (Ao + Av)[::Ts], Ac[::Ts], Ar[::Ts], As[::Ts], A[::Ts]
        else:
            return A[::Ts]
예제 #5
0
파일: itu836.py 프로젝트: yzl-china/ITU-Rpy
def __total_water_vapour_content_836_4_5__(self, lat, lon, p, alt=None):
    """
    """
    lat_f = lat.flatten()
    lon_f = lon.flatten()

    available_p = np.array([0.1, 0.2, 0.3, 0.5, 1, 2, 3, 5, 10,
                            20, 30, 50, 60, 70, 80, 90, 95, 99])

    if p in available_p:
        p_below = p_above = p
        pExact = True
    else:
        pExact = False
        idx = available_p.searchsorted(p, side='right') - 1
        idx = np.clip(idx, 0, len(available_p) - 1)

        p_below = available_p[idx]
        idx = np.clip(idx + 1, 0, len(available_p) - 1)
        p_above = available_p[idx]

    R = -(lat_f - 90) // 1.125
    C = lon_f // 1.125

    lats = np.array([90 - R * 1.125, 90 - (R + 1) * 1.125,
                     90 - R * 1.125, 90 - (R + 1) * 1.125])

    lons = np.mod(np.array([C * 1.125, C * 1.125,
                            (C + 1) * 1.125, (C + 1) * 1.125]), 360)

    r = - (lat_f - 90) / 1.125
    c = lon_f / 1.125

    V_a = self.V(lats, lons, p_above)
    VSCH_a = self.VSCH(lats, lons, p_above)
    altitude_res = topographic_altitude(lats,
                                        lons).value.reshape(lats.shape)
    if alt is None:
        alt = altitude_res
    else:
        alt = alt.flatten()

    V_a = V_a * np.exp(-(alt - altitude_res) * 1.0 / (VSCH_a))

    V_a = (V_a[0, :] * ((R + 1 - r) * (C + 1 - c)) +
           V_a[1, :] * ((r - R) * (C + 1 - c)) +
           V_a[2, :] * ((R + 1 - r) * (c - C)) +
           V_a[3, :] * ((r - R) * (c - C)))

    if not pExact:
        V_b = self.V(lats, lons, p_below)
        VSCH_b = self.VSCH(lats, lons, p_below)

        V_b = V_b * np.exp(-(alt - altitude_res) * 1.0 / (VSCH_b))
        V_b = (V_b[0, :] * ((R + 1 - r) * (C + 1 - c)) +
               V_b[1, :] * ((r - R) * (C + 1 - c)) +
               V_b[2, :] * ((R + 1 - r) * (c - C)) +
               V_b[3, :] * ((r - R) * (c - C)))

    if not pExact:
        V = V_b + (V_a - V_b) * (np.log(p) - np.log(p_below)) / \
                                (np.log(p_above) - np.log(p_below))
        return V.reshape(lat.shape)
    else:
        return V_a.reshape(lat.shape)