コード例 #1
0
def main(lst, lst_vza, lai, csp, fgv, ar, mi, nsr, li, mask, soil_roughness,
         alpha_pt, atmospheric_measurement_height, green_vegetation_emissivity,
         soil_emissivity, save_component_fluxes, save_component_temperature,
         save_aerodynamic_parameters, output_file):

    # Read the required data
    lst = su.read_snappy_product(lst, 'sharpened_LST')[0].astype(np.float32)
    vza = su.read_snappy_product(lst_vza,
                                 'sat_zenith_tn')[0].astype(np.float32)
    lai, geo_coding = su.read_snappy_product(lai, 'lai')
    lai = lai.astype(np.float32)
    lad = su.read_snappy_product(
        csp, 'veg_inclination_distribution')[0].astype(np.float32)
    frac_cover = su.read_snappy_product(csp, 'veg_fractional_cover')[0].astype(
        np.float32)
    h_w_ratio = su.read_snappy_product(
        csp, 'veg_height_width_ratio')[0].astype(np.float32)
    leaf_width = su.read_snappy_product(csp,
                                        'veg_leaf_width')[0].astype(np.float32)
    veg_height = su.read_snappy_product(csp,
                                        'veg_height')[0].astype(np.float32)
    landcover_band = su.read_snappy_product(
        csp, 'igbp_classification')[0].astype(np.float32)
    frac_green = su.read_snappy_product(fgv,
                                        'frac_green')[0].astype(np.float32)
    z_0M = su.read_snappy_product(ar, 'roughness_length')[0].astype(np.float32)
    d_0 = su.read_snappy_product(ar, 'zero_plane_displacement')[0].astype(
        np.float32)
    ta = su.read_snappy_product(mi, 'air_temperature')[0].astype(np.float32)
    u = su.read_snappy_product(mi, 'wind_speed')[0].astype(np.float32)
    ea = su.read_snappy_product(mi, 'vapour_pressure')[0].astype(np.float32)
    p = su.read_snappy_product(mi, 'air_pressure')[0].astype(np.float32)
    shortwave_rad_c = su.read_snappy_product(
        nsr, 'net_shortwave_radiation_canopy')[0].astype(np.float32)
    shortwave_rad_s = su.read_snappy_product(
        nsr, 'net_shortwave_radiation_soil')[0].astype(np.float32)
    longwave_irrad = su.read_snappy_product(
        li, 'longwave_irradiance')[0].astype(np.float32)
    mask = su.read_snappy_product(mask, 'mask')[0].astype(np.float32)

    # Model outputs
    t_s = np.full(lai.shape, np.nan, np.float32)
    t_c = np.full(lai.shape, np.nan, np.float32)
    t_ac = np.full(lai.shape, np.nan, np.float32)
    h_s = np.full(lai.shape, np.nan, np.float32)
    h_c = np.full(lai.shape, np.nan, np.float32)
    le_s = np.full(lai.shape, np.nan, np.float32)
    le_c = np.full(lai.shape, np.nan, np.float32)
    g = np.full(lai.shape, np.nan, np.float32)
    ln_s = np.full(lai.shape, np.nan, np.float32)
    ln_c = np.full(lai.shape, np.nan, np.float32)
    r_s = np.full(lai.shape, np.nan, np.float32)
    r_x = np.full(lai.shape, np.nan, np.float32)
    r_a = np.full(lai.shape, np.nan, np.float32)
    u_friction = np.full(lai.shape, np.nan, np.float32)
    mol = np.full(lai.shape, np.nan, np.float32)
    n_iterations = np.full(lai.shape, np.nan, np.float32)
    flag = np.full(lai.shape, 255)

    # ======================================
    # First process bare soil cases
    i = np.logical_and(lai <= 0, mask == 1)
    t_s[i] = lst[i]

    # Calculate soil fluxes
    [
        flag[i], ln_s[i], le_s[i], h_s[i], g[i], r_a[i], u_friction[i], mol[i],
        n_iterations[i]
    ] = TSEB.OSEB(lst[i],
                  ta[i],
                  u[i],
                  ea[i],
                  p[i],
                  shortwave_rad_s[i],
                  longwave_irrad[i],
                  soil_emissivity,
                  z_0M[i],
                  d_0[i],
                  atmospheric_measurement_height,
                  atmospheric_measurement_height,
                  calcG_params=[[1], 0.35])

    # Set canopy fluxes to 0
    ln_c[i] = 0.0
    le_c[i] = 0.0
    h_c[i] = 0.0

    # ======================================
    # Then process vegetated cases
    i = np.logical_and(lai > 0, mask == 1)
    # Emissivity of canopy containing green and non-green elements.
    emissivity_veg = green_vegetation_emissivity * frac_green[i] + 0.91 * (
        1 - frac_green[i])

    # Caculate component fluxes
    [
        flag[i], t_s[i], t_c[i], t_ac[i], ln_s[i], ln_c[i], le_c[i], h_c[i],
        le_s[i], h_s[i], g[i], r_s[i], r_x[i], r_a[i], u_friction[i], mol[i],
        n_iterations[i]
    ] = TSEB.TSEB_PT(lst[i],
                     vza[i],
                     ta[i],
                     u[i],
                     ea[i],
                     p[i],
                     shortwave_rad_c[i],
                     shortwave_rad_s[i],
                     longwave_irrad[i],
                     lai[i],
                     veg_height[i],
                     emissivity_veg,
                     soil_emissivity,
                     z_0M[i],
                     d_0[i],
                     atmospheric_measurement_height,
                     atmospheric_measurement_height,
                     f_c=frac_cover[i],
                     f_g=frac_green[i],
                     w_C=h_w_ratio[i],
                     leaf_width=leaf_width[i],
                     z0_soil=soil_roughness,
                     alpha_PT=alpha_pt,
                     x_LAD=lad[i],
                     calcG_params=[[1], 0.35],
                     resistance_form=[0, {}])

    # Calculate the bulk fluxes
    le = le_c + le_s
    h = h_c + h_s
    r_ns = shortwave_rad_c + shortwave_rad_s
    r_nl = ln_c + ln_s
    r_n = r_ns + r_nl

    band_data = [{
        'band_name': 'sensible_heat_flux',
        'band_data': h
    }, {
        'band_name': 'latent_heat_flux',
        'band_data': le
    }, {
        'band_name': 'ground_heat_flux',
        'band_data': g
    }, {
        'band_name': 'net_radiation',
        'band_data': r_n
    }, {
        'band_name': 'quality_flag',
        'band_data': flag
    }]

    if save_component_fluxes:
        band_data.extend([{
            'band_name': 'sensible_heat_flux_canopy',
            'band_data': h_c
        }, {
            'band_name': 'sensible_heat_flux_soil',
            'band_data': h_s
        }, {
            'band_name': 'latent_heat_flux_canopy',
            'band_data': le_c
        }, {
            'band_name': 'latent_heat_flux_soil',
            'band_data': le_s
        }, {
            'band_name': 'net_longwave_radiation_canopy',
            'band_data': ln_c
        }, {
            'band_name': 'net_longwave_radiation_soil',
            'band_data': ln_s
        }])
    if save_component_temperature:
        band_data.extend([{
            'band_name': 'temperature_canopy',
            'band_data': t_c
        }, {
            'band_name': 'temperature_soil',
            'band_data': t_s
        }, {
            'band_name': 'temperature_canopy_air',
            'band_data': t_ac
        }])
    if save_aerodynamic_parameters:
        band_data.extend([{
            'band_name': 'resistance_surface',
            'band_data': r_a
        }, {
            'band_name': 'resistance_canopy',
            'band_data': r_x
        }, {
            'band_name': 'resistance_soil',
            'band_data': r_s
        }, {
            'band_name': 'friction_velocity',
            'band_data': u_friction
        }, {
            'band_name': 'monin_obukhov_length',
            'band_data': mol
        }])

    su.write_snappy_product(output_file, band_data, 'turbulentFluxes',
                            geo_coding)
コード例 #2
0
def dis_TSEB(flux_LR,
             scale,
             Tr_K,
             vza,
             T_A_K,
             u,
             ea,
             p,
             Sn_C,
             Sn_S,
             L_dn,
             LAI,
             h_C,
             emis_C,
             emis_S,
             z_0M,
             d_0,
             z_u,
             z_T,
             UseL=np.inf,
             leaf_width=0.1,
             z0_soil=0.01,
             alpha_PT=1.26,
             x_LAD=1,
             f_c=1.0,
             f_g=1.0,
             w_C=1.0,
             resistance_form=[0, {}],
             calcG_params=[[1], 0.35],
             massman_profile=[0, []],
             flux_LR_method='EF',
             correct_LST=True):
    '''Priestley-Taylor TSEB

    Calculates the Priestley Taylor TSEB fluxes using a single observation of
    composite radiometric temperature and using resistances in series.

    Parameters
    ----------
    Tr_K : float
        Radiometric composite temperature (Kelvin).
    vza : float
        View Zenith Angle (degrees).
    T_A_K : float
        Air temperature (Kelvin).
    u : float
        Wind speed above the canopy (m s-1).
    ea : float
        Water vapour pressure above the canopy (mb).
    p : float
        Atmospheric pressure (mb), use 1013 mb by default.
    Sn_C : float
        Canopy net shortwave radiation (W m-2).
    Sn_S : float
        Soil net shortwave radiation (W m-2).
    L_dn : float
        Downwelling longwave radiation (W m-2).
    LAI : float
        Effective Leaf Area Index (m2 m-2).
    h_C : float
        Canopy height (m).
    emis_C : float
        Leaf emissivity.
    emis_S : flaot
        Soil emissivity.
    z_0M : float
        Aerodynamic surface roughness length for momentum transfer (m).
    d_0 : float
        Zero-plane displacement height (m).
    z_u : float
        Height of measurement of windspeed (m).
    z_T : float
        Height of measurement of air temperature (m).
    UseL : float or None, optional
        Its value will be used to force the Moning-Obukhov stability length.
    leaf_width : float, optional
        average/effective leaf width (m).
    z0_soil : float, optional
        bare soil aerodynamic roughness length (m).
    alpha_PT : float, optional
        Priestley Taylor coeffient for canopy potential transpiration,
        use 1.26 by default.
    x_LAD : float, optional
        Campbell 1990 leaf inclination distribution function chi parameter.
    f_c : float, optional
        Fractional cover.
    f_g : float, optional
        Fraction of vegetation that is green.
    w_C : float, optional
        Canopy width to height ratio.
    resistance_form : int, optional
        Flag to determine which Resistances R_x, R_S model to use.

            * 0 [Default] Norman et al 1995 and Kustas et al 1999.
            * 1 : Choudhury and Monteith 1988.
            * 2 : McNaughton and Van der Hurk 1995.

    calcG_params : list[list,float or array], optional
        Method to calculate soil heat flux,parameters.

            * [1],G_ratio]: default, estimate G as a ratio of Rn_S, default Gratio=0.35.
            * [0],G_constant] : Use a constant G, usually use 0 to ignore the computation of G.
            * [[2,Amplitude,phase_shift,shape],time] : estimate G from Santanello and Friedl with G_param list of parameters (see :func:`~TSEB.calc_G_time_diff`).

    Returns
    -------
    flag : int
        Quality flag, see Appendix for description.
    T_S : float
        Soil temperature  (Kelvin).
    T_C : float
        Canopy temperature  (Kelvin).
    T_AC : float
        Air temperature at the canopy interface (Kelvin).
    L_nS : float
        Soil net longwave radiation (W m-2)
    L_nC : float
        Canopy net longwave radiation (W m-2)
    LE_C : float
        Canopy latent heat flux (W m-2).
    H_C : float
        Canopy sensible heat flux (W m-2).
    LE_S : float
        Soil latent heat flux (W m-2).
    H_S : float
        Soil sensible heat flux (W m-2).
    G : float
        Soil heat flux (W m-2).
    R_S : float
        Soil aerodynamic resistance to heat transport (s m-1).
    R_x : float
        Bulk canopy aerodynamic resistance to heat transport (s m-1).
    R_A : float
        Aerodynamic resistance to heat transport (s m-1).
    u_friction : float
        Friction velocity (m s-1).
    L : float
        Monin-Obuhkov length (m).
    n_iterations : int
        number of iterations until convergence of L.

    References
    ----------
    .. [Norman1995] J.M. Norman, W.P. Kustas, K.S. Humes, Source approach for estimating
        soil and vegetation energy fluxes in observations of directional radiometric
        surface temperature, Agricultural and Forest Meteorology, Volume 77, Issues 3-4,
        Pages 263-293,
        http://dx.doi.org/10.1016/0168-1923(95)02265-Y.
    .. [Kustas1999] William P Kustas, John M Norman, Evaluation of soil and vegetation heat
        flux predictions using a simple two-source model with radiometric temperatures for
        partial canopy cover, Agricultural and Forest Meteorology, Volume 94, Issue 1,
        Pages 13-29,
        http://dx.doi.org/10.1016/S0168-1923(99)00005-2.
    '''

    # Initialize HR output variables
    [
        flag, T_S, T_C, T_AC, Ln_S, Ln_C, LE_C, H_C, LE_S, H_S, G, R_S, R_x,
        R_A, u_friction, L, n_iterations
    ] = map(np.empty, 17 * [Tr_K.shape])

    [
        T_S[:], T_C[:], T_AC[:], Ln_S[:], Ln_C[:], LE_C[:], H_C[:], LE_S[:],
        H_S[:], G[:], R_S[:], R_x[:], R_A[:], u_friction[:], L[:]
    ] = 15 * [np.nan]

    n_iterations[:] = 0
    flag[:] = NO_VALID_FLAG

    gt_LR = scale[0]
    prj_LR = scale[1]
    gt_HR = scale[2]
    prj_HR = scale[3]

    # Create mask that masks high-res pixels where low-res constant ratio
    # does not exist or is invalid
    dims_LR = flux_LR.shape
    dims_HR = Tr_K.shape
    const_ratio = scale_with_gdalwarp(flux_LR, prj_LR, prj_HR, dims_HR, gt_LR,
                                      gt_HR, gdal.GRA_NearestNeighbour)
    mask = np.ones(const_ratio.shape, dtype=bool)
    mask[np.logical_or(np.isnan(const_ratio), Tr_K <= 0)] = False

    # Set the starting conditions for disaggregation.
    counter = np.ones(const_ratio.shape)
    counter[~mask] = np.nan
    T_offset = np.zeros(const_ratio.shape)
    T_offset[~mask] = np.nan
    Tr_K_modified = Tr_K.copy()
    T_A_K_modified = T_A_K.copy()

    const_ratio_diff = np.zeros(const_ratio.shape) + 1000
    const_ratio_HR = np.ones(const_ratio.shape) * np.nan

    print(
        'Forcing low resolution MO stability length as starting point in the iteration'
    )
    if isinstance(UseL, float):
        L = np.ones(Tr_K.shape) * UseL
    else:
        L = scale_with_gdalwarp(UseL, prj_LR, prj_HR, dims_HR, gt_LR, gt_HR,
                                gdal.GRA_NearestNeighbour)
    del UseL

    rho = TSEB.met.calc_rho(p, ea, T_A_K)  # Air density
    c_p = TSEB.met.calc_c_p(p, ea)  # Heat capacity of air

    #######################################################################
    # For all the pixels in the high res. TSEB
    # WHILE high-res contant ration != low-res constant ratio
    #   adjust Tair or LST for unmasked pixels
    #   run high-res TSBE for unmaksed pixels
    #   claculate high-res consant ratio
    #   mask pixels where ratios aggree
    while np.any(mask) and np.nanmax(counter) < DIS_TSEB_ITERATIONS:

        # Adjust LST or air temperature as required
        if correct_LST:
            Tr_K_modified[mask] = _adjust_temperature(Tr_K[mask],
                                                      T_offset[mask],
                                                      correct_LST,
                                                      flux_LR_method)
        else:
            T_A_K_modified[mask] = _adjust_temperature(T_A_K[mask],
                                                       T_offset[mask],
                                                       correct_LST,
                                                       flux_LR_method)

        # Run high-res TSEB on all unmasked pixels
        flag[mask] = VALID_FLAG

        # First process bare soil cases
        print('First process bare soil cases')
        i = np.array(np.logical_and(LAI == 0, mask))

        [
            flag[i], Ln_S[i], LE_S[i], H_S[i], G[i], R_A[i], u_friction[i],
            L[i], n_iterations[i]
        ] = TSEB.OSEB(Tr_K_modified[i],
                      T_A_K_modified[i],
                      u[i],
                      ea[i],
                      p[i],
                      Sn_S[i],
                      L_dn[i],
                      emis_S[i],
                      z_0M[i],
                      d_0[i],
                      z_u[i],
                      z_T[i],
                      calcG_params=[calcG_params[0], calcG_params[1][i]],
                      UseL=L[i])

        T_S[i] = Tr_K_modified[i]
        T_AC[i] = T_A_K_modified[i]
        # Set canopy fluxes to 0
        Sn_C[i] = 0.0
        Ln_C[i] = 0.0
        LE_C[i] = 0.0
        H_C[i] = 0.0

        # Then process vegetated pixels
        print('Then process vegetated pixels')
        i = np.array(np.logical_and(LAI > 0, mask))
        if resistance_form[0] == 0:
            resistance_flag = [
                resistance_form[0],
                {k: resistance_form[1][k][i]
                 for k in resistance_form[1]}
            ]

        else:
            resistance_flag = [resistance_form[0], {}]

        [
            flag[i], T_S[i], T_C[i], T_AC[i], Ln_S[i], Ln_C[i], LE_C[i],
            H_C[i], LE_S[i], H_S[i], G[i], R_S[i], R_x[i], R_A[i],
            u_friction[i], L[i], n_iterations[i]
        ] = TSEB.TSEB_PT(Tr_K_modified[i],
                         vza[i],
                         T_A_K_modified[i],
                         u[i],
                         ea[i],
                         p[i],
                         Sn_C[i],
                         Sn_S[i],
                         L_dn[i],
                         LAI[i],
                         h_C[i],
                         emis_C[i],
                         emis_S[i],
                         z_0M[i],
                         d_0[i],
                         z_u[i],
                         z_T[i],
                         leaf_width=leaf_width[i],
                         z0_soil=z0_soil[i],
                         alpha_PT=alpha_PT[i],
                         x_LAD=x_LAD[i],
                         f_c=f_c[i],
                         f_g=f_g[i],
                         w_C=w_C[i],
                         resistance_form=resistance_flag,
                         calcG_params=[calcG_params[0], calcG_params[1][i]],
                         UseL=L[i])

        LE_HR = LE_C + LE_S
        H_HR = H_C + H_S

        print('Recalculating MO stability length')
        L = TSEB.MO.calc_L(u_friction, T_A_K_modified, rho, c_p, H_HR, LE_HR)

        # Calcualte HR constant ratio
        valid = np.logical_and(mask, flag != NO_VALID_FLAG)
        if flux_LR_method == 'EF':
            # Calculate high-res Evaporative Fraction
            const_ratio_HR[valid] = LE_HR[valid] / (LE_HR[valid] + H_HR[valid])
        elif flux_LR_method == 'LE':
            # Calculate high-res Evaporative Fraction
            const_ratio_HR[valid] = LE_HR[valid]
        elif flux_LR_method == 'H':
            # Calculate high-res Evaporative Fraction
            const_ratio_HR[valid] = H_HR[valid]

        # Calculate average constant ratio for each LR pixel from all HR
        # pixels it contains
        print(
            'Calculating average constant ratio for each LR pixel using valid HR pixels'
        )
        const_ratio_LR = scale_with_gdalwarp(const_ratio_HR, prj_HR, prj_LR,
                                             dims_LR, gt_HR, gt_LR,
                                             gdal.GRA_Average)
        const_ratio_HR = scale_with_gdalwarp(const_ratio_LR, prj_LR, prj_HR,
                                             dims_HR, gt_LR, gt_HR,
                                             gdal.GRA_NearestNeighbour)
        const_ratio_HR[~mask] = np.nan

        # Mask the low-res pixels for which constant ratio of hig-res and
        # low-res runs agree.
        const_ratio_diff = const_ratio_HR - const_ratio
        const_ratio_diff[np.logical_or(np.isnan(const_ratio_HR),
                                       np.isnan(const_ratio))] = 0

        # Calculate temperature offset and ready-pixels mask
        if flux_LR_method == 'EF':
            mask = np.abs(const_ratio_diff) > 0.01
            step = np.clip(const_ratio_diff * 5, -1, 1)
        elif flux_LR_method == 'LE' or flux_LR_method == 'H':
            mask = np.abs(const_ratio_diff) > 5
            step = np.clip(const_ratio_diff * 0.01, -1, 1)
        counter[mask] += 1
        T_offset[mask] += step[mask]

        print('disTSEB iteration %s' % np.nanmax(counter))
        print('Recalculating over %s high resolution pixels' %
              np.size(Tr_K[mask]))

    ####################################################################
    # When constant ratios for all pixels match, smooth the resulting Ta adjustment
    # with a moving window size of 2x2 km and perform a final run of high-res model
    mask = np.ones(const_ratio.shape, dtype=bool)
    mask[np.isnan(const_ratio)] = False

    T_offset_orig = T_offset.copy()
    T_offset = moving_gaussian_filter(T_offset, int(2000 / float(gt_HR[1])))

    # Smooth MO length
    L = moving_gaussian_filter(L, int(2000 / float(gt_HR[1])))

    if correct_LST:
        Tr_K_modified = Tr_K.copy()
        Tr_K_modified[mask] = _adjust_temperature(Tr_K[mask], T_offset[mask],
                                                  correct_LST, flux_LR_method)
    else:
        T_A_K_modified = T_A_K.copy()
        T_A_K_modified[mask] = _adjust_temperature(T_A_K[mask], T_offset[mask],
                                                   correct_LST, flux_LR_method)

    flag[mask] = VALID_FLAG

    # Run high-res TSEB on all unmasked pixels
    TSEB.ITERATIONS = ITERATIONS_OUT
    print('Final run of TSEB at high resolution with adjusted temperature')

    # First process bare soil cases
    print('First process bare soil cases')
    i = np.array(np.logical_and(LAI == 0, mask))
    [
        flag[i], Ln_S[i], LE_S[i], H_S[i], G[i], R_A[i], u_friction[i], L[i],
        n_iterations[i]
    ] = TSEB.OSEB(Tr_K_modified[i],
                  T_A_K_modified[i],
                  u[i],
                  ea[i],
                  p[i],
                  Sn_S[i],
                  L_dn[i],
                  emis_S[i],
                  z_0M[i],
                  d_0[i],
                  z_u[i],
                  z_T[i],
                  calcG_params=[calcG_params[0], calcG_params[1][i]],
                  UseL=L[i])

    T_S[i] = Tr_K_modified[i]
    T_AC[i] = T_A_K_modified[i]
    # Set canopy fluxes to 0
    Sn_C[i] = 0.0
    Ln_C[i] = 0.0
    LE_C[i] = 0.0
    H_C[i] = 0.0

    # Then process vegetated pixels
    print('Then process vegetated pixels')
    i = np.array(np.logical_and(LAI > 0, mask))

    if resistance_form[0] == 0:
        resistance_flag = [
            resistance_form[0],
            {k: resistance_form[1][k][i]
             for k in resistance_form[1]}
        ]

    else:
        resistance_flag = [resistance_form[0], {}]

    [
        flag[i], T_S[i], T_C[i], T_AC[i], Ln_S[i], Ln_C[i], LE_C[i], H_C[i],
        LE_S[i], H_S[i], G[i], R_S[i], R_x[i], R_A[i], u_friction[i], L[i],
        n_iterations[i]
    ] = TSEB.TSEB_PT(Tr_K_modified[i],
                     vza[i],
                     T_A_K_modified[i],
                     u[i],
                     ea[i],
                     p[i],
                     Sn_C[i],
                     Sn_S[i],
                     L_dn[i],
                     LAI[i],
                     h_C[i],
                     emis_C[i],
                     emis_S[i],
                     z_0M[i],
                     d_0[i],
                     z_u[i],
                     z_T[i],
                     leaf_width=leaf_width[i],
                     z0_soil=z0_soil[i],
                     alpha_PT=alpha_PT[i],
                     x_LAD=x_LAD[i],
                     f_c=f_c[i],
                     f_g=f_g[i],
                     w_C=w_C[i],
                     resistance_form=resistance_flag,
                     calcG_params=[calcG_params[0], calcG_params[1][i]],
                     UseL=L[i])

    return [
        flag, T_S, T_C, T_AC, Ln_S, Ln_C, LE_C, H_C, LE_S, H_S, G, R_S, R_x,
        R_A, u_friction, L, n_iterations, T_offset, counter, T_offset_orig
    ]
コード例 #3
0
ファイル: PyTSEB.py プロジェクト: Nojuman/pyTSEB
    def run_TSEB(self, in_data, mask=None):

        print("Processing...")

        if mask is None:
            mask = np.ones(in_data['LAI'].shape)

        # Create the output dictionary
        out_data = dict()
        for field in self._get_output_structure():
            out_data[field] = np.zeros(in_data['LAI'].shape) + np.NaN

        # Esimate diffuse and direct irradiance
        difvis, difnir, fvis, fnir = rad.calc_difuse_ratio(in_data['S_dn'],
                                                           in_data['SZA'],
                                                           press=in_data['p'])
        out_data['fvis'] = fvis
        out_data['fnir'] = fnir
        out_data['Skyl'] = difvis * fvis + difnir * fnir
        out_data['S_dn_dir'] = in_data['S_dn'] * (1.0 - out_data['Skyl'])
        out_data['S_dn_dif'] = in_data['S_dn'] * out_data['Skyl']

        #======================================
        # First process bare soil cases

        noVegPixels = in_data['LAI'] <= 0
        noVegPixels = np.logical_or.reduce(
            (in_data['f_c'] <= 0.01, in_data['LAI'] <= 0,
             np.isnan(in_data['LAI'])))
        #in_data['LAI'][noVegPixels] = 0
        #in_data['f_c'][noVegPixels] = 0
        i = np.array(np.logical_and(noVegPixels, mask == 1))

        # Calculate roughness
        out_data['z_0M'][i] = in_data['z0_soil'][i]
        out_data['d_0'][i] = 5 * out_data['z_0M'][i]

        # Net shortwave radition for bare soil
        spectraGrdOSEB = out_data['fvis']  * \
            in_data['rho_vis_S'] + out_data['fnir'] * in_data['rho_nir_S']
        out_data['Sn_S1'][i] = (1. - spectraGrdOSEB[i]) * \
            (out_data['S_dn_dir'][i] + out_data['S_dn_dif'][i])

        # Other fluxes for bare soil
        if self.model_type == 'DTD':
            T_S_K = in_data['T_R1'][i]
            T0_K = (in_data['T_R0'][i], in_data['T_A0'][i])
        elif self.model_type == 'TSEB_PT':
            T_S_K = in_data['T_R1'][i]
            T0_K = []
        else:
            T_S_K = in_data['T_S'][i]
            T0_K = []
        [
            out_data['flag'][i], out_data['Ln_S1'][i], out_data['LE_S1'][i],
            out_data['H_S1'][i], out_data['G1'][i], out_data['R_A1'][i],
            out_data['u_friction'][i], out_data['L'][i],
            out_data['n_iterations'][i]
        ] = TSEB.OSEB(T_S_K,
                      in_data['T_A1'][i],
                      in_data['u'][i],
                      in_data['ea'][i],
                      in_data['p'][i],
                      out_data['Sn_S1'][i],
                      in_data['L_dn'][i],
                      in_data['emis_S'][i],
                      out_data['z_0M'][i],
                      out_data['d_0'][i],
                      in_data['z_u'][i],
                      in_data['z_T'][i],
                      calcG_params=[self.G_form[0], self.G_form[1][i]],
                      T0_K=T0_K)

        # Set canopy fluxes to 0
        out_data['Sn_C1'][i] = 0.0
        out_data['Ln_C1'][i] = 0.0
        out_data['LE_C1'][i] = 0.0
        out_data['H_C1'][i] = 0.0

        #======================================
        # Then process vegetated cases

        i = np.array(np.logical_and(~noVegPixels, mask == 1))

        # Calculate roughness
        out_data['z_0M'][i], out_data['d_0'][i] = \
            res.calc_roughness(in_data['LAI'][i],
                               in_data['h_C'][i],
                               w_C = in_data['w_C'][i],
                               landcover = in_data['landcover'][i],
                               f_c = in_data['f_c'][i])

        # Net shortwave radiation for vegetation
        F = np.zeros(in_data['LAI'].shape)
        F[i] = in_data['LAI'][i] / in_data['f_c'][i]
        # Clumping index
        omega0, Omega = np.zeros(in_data['LAI'].shape), np.zeros(
            in_data['LAI'].shape)
        omega0[i] = CI.calc_omega0_Kustas(in_data['LAI'][i],
                                          in_data['f_c'][i],
                                          x_LAD=in_data['x_LAD'][i],
                                          isLAIeff=True)
        if self.p['calc_row'][0] == 0:  # randomly placed canopies
            Omega[i] = CI.calc_omega_Kustas(omega0[i],
                                            in_data['SZA'][i],
                                            w_C=in_data['w_C'][i])
        else:
            Omega[i] = CI.calc_omega_Kustas(omega0[i],
                                            in_data['SZA'][i],
                                            w_C=in_data['w_C'][i])
        LAI_eff = F * Omega
        [out_data['Sn_C1'][i], out_data['Sn_S1'][i]
         ] = rad.calc_Sn_Campbell(in_data['LAI'][i],
                                  in_data['SZA'][i],
                                  out_data['S_dn_dir'][i],
                                  out_data['S_dn_dif'][i],
                                  out_data['fvis'][i],
                                  out_data['fnir'][i],
                                  in_data['rho_vis_C'][i],
                                  in_data['tau_vis_C'][i],
                                  in_data['rho_nir_C'][i],
                                  in_data['tau_nir_C'][i],
                                  in_data['rho_vis_S'][i],
                                  in_data['rho_nir_S'][i],
                                  x_LAD=in_data['x_LAD'][i],
                                  LAI_eff=LAI_eff[i])

        # Model settings
        calcG_params = [self.G_form[0], self.G_form[1][i]]
        resistance_form = [
            self.resistance_form,
            {k: self.res_params[k][i]
             for k in self.res_params}
        ]

        # Other fluxes for vegetation
        if self.model_type == 'DTD':
            [out_data['flag'][i], out_data['T_S1'][i], out_data['T_C1'][i],
             out_data['T_AC1'][i], out_data['Ln_S1'][i], out_data['Ln_C1'][i],
             out_data['LE_C1'][i], out_data['H_C1'][i], out_data['LE_S1'][i],
             out_data['H_S1'][i], out_data['G1'][i], out_data['R_S1'][i],
             out_data['R_x1'][i], out_data['R_A1'][i], out_data['u_friction'][i],
             out_data['L'][i], out_data['Ri'], out_data['n_iterations'][i]] = \
                     TSEB.DTD(in_data['T_R0'][i],
                              in_data['T_R1'][i],
                              in_data['VZA'][i],
                              in_data['T_A0'][i],
                              in_data['T_A1'][i],
                              in_data['u'][i],
                              in_data['ea'][i],
                              in_data['p'][i],
                              out_data['Sn_C1'][i],
                              out_data['Sn_S1'][i],
                              in_data['L_dn'][i],
                              in_data['LAI'][i],
                              in_data['h_C'][i],
                              in_data['emis_C'][i],
                              in_data['emis_S'][i],
                              out_data['z_0M'][i],
                              out_data['d_0'][i],
                              in_data['z_u'][i],
                              in_data['z_T'][i],
                              f_c=in_data['f_c'][i],
                              w_C=in_data['w_C'][i],
                              f_g=in_data['f_g'][i],
                              leaf_width=in_data['leaf_width'][i],
                              z0_soil=in_data['z0_soil'][i],
                              alpha_PT=in_data['alpha_PT'][i],
                              x_LAD=in_data['x_LAD'][i],
                              calcG_params=calcG_params,
                              resistance_form=resistance_form)

        elif self.model_type == 'TSEB_PT':
            [out_data['flag'][i], out_data['T_S1'][i], out_data['T_C1'][i],
             out_data['T_AC1'][i], out_data['Ln_S1'][i], out_data['Ln_C1'][i],
             out_data['LE_C1'][i], out_data['H_C1'][i], out_data['LE_S1'][i],
             out_data['H_S1'][i], out_data['G1'][i], out_data['R_S1'][i],
             out_data['R_x1'][i], out_data['R_A1'][i], out_data['u_friction'][i],
             out_data['L'][i], out_data['n_iterations'][i]] = \
                     TSEB.TSEB_PT(in_data['T_R1'][i],
                                  in_data['VZA'][i],
                                  in_data['T_A1'][i],
                                  in_data['u'][i],
                                  in_data['ea'][i],
                                  in_data['p'][i],
                                  out_data['Sn_C1'][i],
                                  out_data['Sn_S1'][i],
                                  in_data['L_dn'][i],
                                  in_data['LAI'][i],
                                  in_data['h_C'][i],
                                  in_data['emis_C'][i],
                                  in_data['emis_S'][i],
                                  out_data['z_0M'][i],
                                  out_data['d_0'][i],
                                  in_data['z_u'][i],
                                  in_data['z_T'][i],
                                  f_c=in_data['f_c'][i],
                                  f_g=in_data['f_g'][i],
                                  w_C=in_data['w_C'][i],
                                  leaf_width=in_data['leaf_width'][i],
                                  z0_soil=in_data['z0_soil'][i],
                                  alpha_PT=in_data['alpha_PT'][i],
                                  x_LAD=in_data['x_LAD'][i],
                                  calcG_params=calcG_params,
                                  resistance_form=resistance_form)

        elif self.model_type == 'TSEB_2T':
            # Run TSEB with the component temperatures T_S and T_C
            [out_data['flag'][i], out_data['T_AC1'][i], out_data['Ln_S1'][i],
             out_data['Ln_C1'][i], out_data['LE_C1'][i], out_data['H_C1'][i],
             out_data['LE_S1'][i], out_data['H_S1'][i], out_data['G1'][i],
             out_data['R_S1'][i], out_data['R_x1'][i], out_data['R_A1'][i],
             out_data['u_friction'][i], out_data['L'][i], out_data['n_iterations'][i]] = \
                     TSEB.TSEB_2T(in_data['T_C'][i],
                                  in_data['T_S'][i],
                                  in_data['T_A1'][i],
                                  in_data['u'][i],
                                  in_data['ea'][i],
                                  in_data['p'][i],
                                  out_data['Sn_C1'][i],
                                  out_data['Sn_S1'][i],
                                  in_data['L_dn'][i],
                                  in_data['LAI'][i],
                                  in_data['h_C'][i],
                                  in_data['emis_C'][i],
                                  in_data['emis_S'][i],
                                  out_data['z_0M'][i],
                                  out_data['d_0'][i],
                                  in_data['z_u'][i],
                                  in_data['z_T'][i],
                                  f_c=in_data['f_c'][i],
                                  f_g=in_data['f_g'][i],
                                  w_C=in_data['w_C'][i],
                                  leaf_width=in_data['leaf_width'][i],
                                  z0_soil=in_data['z0_soil'][i],
                                  alpha_PT=in_data['alpha_PT'][i],
                                  x_LAD=in_data['x_LAD'][i],
                                  calcG_params=calcG_params,
                                  resistance_form=resistance_form)

        # Calculate the bulk fluxes
        out_data['LE1'] = out_data['LE_C1'] + out_data['LE_S1']
        out_data['LE_partition'] = out_data['LE_C1'] / out_data['LE1']
        out_data['H1'] = out_data['H_C1'] + out_data['H_S1']
        out_data['R_ns1'] = out_data['Sn_C1'] + out_data['Sn_S1']
        out_data['R_nl1'] = out_data['Ln_C1'] + out_data['Ln_S1']
        out_data['R_n1'] = out_data['R_ns1'] + out_data['R_nl1']
        out_data['delta_R_n1'] = out_data['Sn_C1'] + out_data['Ln_C1']

        print("Finished processing!")
        return out_data