Beispiel #1
0
def calc_longwave_irradiance(ea, t_a_k, p=1013.25, z_T=2.0, h_C=2.0):
    '''Longwave irradiance

    Estimates longwave atmospheric irradiance from clear sky.
    By default there is no lapse rate correction unless air temperature
    measurement height is considerably different than canopy height, (e.g. when
    using NWP gridded meteo data at blending height)

    Parameters
    ----------
    ea : float
        atmospheric vapour pressure (mb).
    t_a_k : float
        air temperature (K).
    p : float
        air pressure (mb)
    z_T: float
        air temperature measurement height (m), default 2 m.
    h_C: float
        canopy height (m), default 2 m,

    Returns
    -------
    L_dn : float
        Longwave atmospheric irradiance (W m-2) above the canopy
    '''

    lapse_rate = met.calc_lapse_rate_moist(t_a_k, ea, p)
    t_a_surface = t_a_k - lapse_rate * (h_C - z_T)
    emisAtm = calc_emiss_atm(ea, t_a_surface)
    L_dn = emisAtm * met.calc_stephan_boltzmann(t_a_surface)
    return np.asarray(L_dn)
Beispiel #2
0
def calc_longwave_irradiance(ea, T_A_K, p=1013.25, z_T=2.0):
    '''Longwave irradiance

    Estimates longwave atmospheric irradiance from clear sky.

    Parameters
    ----------
    ea : float
        atmospheric vapour pressure (mb).
    T_A_K : float
        air temperature (K).
    p : float
        air pressure (mb)
    z_T: float
        air temperature measurement height (m), default 2 m.

    Returns
    -------
    L_dn : float
        Longwave atmospheric irradiance (W m-2)
    '''

    lapse_rate = met.calc_lapse_rate_moist(T_A_K, ea, p)
    T_A_surface = T_A_K - z_T * lapse_rate
    emisAtm = calc_emiss_atm(ea, T_A_surface)
    L_dn = emisAtm * met.calc_stephan_boltzmann(T_A_surface)
    return np.asarray(L_dn)
Beispiel #3
0
def calc_air_temperature_blending_height(ta, ea, p, z_bh, z_ta=2.0):
    if type(ta) is np.ndarray:
        ta = ta.astype(np.float32)
    if type(ea) is np.ndarray:
        ea = ea.astype(np.float32)
    if type(p) is np.ndarray:
        p = p.astype(np.float32)
    if type(z_bh) is np.ndarray:
        z_bh = z_bh.astype(np.float32)
    if type(z_ta) is np.ndarray:
        z_ta = z_ta.astype(np.float32)
    lapse_rate = met.calc_lapse_rate_moist(ta, ea, p)
    ta_bh = ta - lapse_rate * (z_bh - z_ta)
    return ta_bh
Beispiel #4
0
VI = ndvi(SR.sel(band=4), SR.sel(band=3))

VI_MAX = 0.95

albedo = reflectance_to_albedo(SR.where(SR > 0), wb)

# Reduce potential ET based on vegetation density based on Allen et al. 2013
ET_r_f_cold = xar.ones_like(Tr_K) * 1.05
ET_bare_soil = xar.zeros_like(Tr_K)
ET_r_f_cold = xar.where(VI < VI_MAX, 1.05 / VI_MAX * VI,
                        ET_r_f_cold)  # Eq. 4 [Allen 2013]

ET_r_f_hot = VI * ET_r_f_cold + (1.0 - VI) * ET_bare_soil  # Eq. 5 [Allen 2013]

# Compute normalized temperatures by adiabatic correction
gamma_w = met.calc_lapse_rate_moist(Tr_K, ea, p)

Tr_datum = Tr_K + gamma_w * alt
Ta_datum = T_A_K + gamma_w * alt
#.data to convert DataArrays to dAsk Arrays since ,ap_overblocks not yet supported in xarray
cv_ndvi, _, _ = endmember_search.moving_cv_filter(VI.data, (11, 11))
_, _, std_lst = endmember_search.moving_cv_filter(Tr_datum.data, (11, 11))
cv_albedo, _, _ = endmember_search.moving_cv_filter(albedo.data, (11, 11))
del _
# couldn't get logical_and.reduce to work with mix of numpy and dask arrays in endmember_search,
# computation would hang and spin on one processor forever. converting all to numpy arrays
cold_pixel, hot_pixel = endmember_search.esa(np.asarray(VI),
                                             np.asarray(Tr_datum),
                                             cv_ndvi.compute(),
                                             std_lst.compute(),
                                             cv_albedo.compute())
Beispiel #5
0
def METRIC(Tr_K,
           T_A_K,
           u,
           ea,
           p,
           Sn,
           L_dn,
           emis,
           z_0M,
           d_0,
           z_u,
           z_T,
           cold_pixel,
           hot_pixel,
           LE_cold,
           LE_hot=0,
           use_METRIC_resistance=True,
           calcG_params=[[1], 0.35],
           UseL=False,
           UseDEM=False):
    '''Calulates bulk fluxes using METRIC model

    Parameters
    ----------
    Tr_K : float
        Radiometric composite temperature (Kelvin).
    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.
    S_n : float
        Solar irradiance (W m-2).
    L_dn : float
        Downwelling longwave radiation (W m-2)
    emis : float
        Surface 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).
    cold_pixel : tuple
        pixel coordinates (row, col) for the cold endmember
    hot_pixel : tuple
        pixel coordinates (row, col) for the hot endmember
    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`).
    UseL : Optional[float]
        If included, its value will be used to force the Moning-Obukhov stability length.

    Returns
    -------
    flag : int
        Quality flag, see Appendix for description.
    Ln : float
        Net longwave radiation (W m-2)
    LE : float
        Latent heat flux (W m-2).
    H : float
        Sensible heat flux (W m-2).
    G : float
        Soil heat flux (W m-2).
    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
    ----------

    '''

    # Convert input scalars to numpy arrays and check parameters size
    Tr_K = np.asarray(Tr_K)
    (T_A_K, u, ea, p, Sn, L_dn, emis, z_0M, d_0, z_u, z_T, LE_cold, LE_hot,
     calcG_array) = map(tseb._check_default_parameter_size, [
         T_A_K, u, ea, p, Sn, L_dn, emis, z_0M, d_0, z_u, z_T, LE_cold, LE_hot,
         calcG_params[1]
     ], [Tr_K] * 14)

    # Create the output variables
    [Ln, LE, H, G, R_A,
     iterations] = [np.zeros(Tr_K.shape) + np.NaN for i in range(6)]
    flag = np.zeros(Tr_K.shape, dtype=np.byte)
    # iteration of the Monin-Obukhov length
    if isinstance(UseL, bool):
        # Initially assume stable atmospheric conditions and set variables for
        L = np.zeros(Tr_K.shape) + np.inf
        max_iterations = ITERATIONS
    else:  # We force Monin-Obukhov lenght to the provided array/value
        L = np.ones(Tr_K.shape) * UseL
        max_iterations = 1  # No iteration

    if isinstance(UseDEM, bool):
        Tr_datum = np.asarray(Tr_K)
        Ta_datum = np.asarray(T_A_K)
    else:
        gamma_w = met.calc_lapse_rate_moist(T_A_K, ea, p)
        Tr_datum = Tr_K + gamma_w * UseDEM
        Ta_datum = T_A_K + gamma_w * UseDEM

    # Calculate the general parameters
    rho = met.calc_rho(p, ea, T_A_K)  # Air density
    c_p = met.calc_c_p(p, ea)  # Heat capacity of air
    rho_datum = met.calc_rho(p, ea, Ta_datum)  # Air density

    # Calc initial Monin Obukhov variables
    u_friction = MO.calc_u_star(u, z_u, L, d_0, z_0M)
    u_friction = np.maximum(u_friction_min, u_friction)

    z_0H = res.calc_z_0H(z_0M, kB=kB)

    # Calculate Net radiation
    Ln = emis * L_dn - emis * met.calc_stephan_boltzmann(Tr_K)
    Rn = np.asarray(Sn + Ln)

    # Compute Soil Heat Flux
    i = np.ones(Rn.shape, dtype=bool)
    G[i] = tseb.calc_G([calcG_params[0], calcG_array], Rn, i)

    # Get cold and hot variables
    Rn_endmembers = np.array([Rn[cold_pixel], Rn[hot_pixel]])
    G_endmembers = np.array([G[cold_pixel], G[hot_pixel]])
    LE_endmembers = np.array([LE_cold[cold_pixel], LE_hot[hot_pixel]])
    u_friction_endmembers = np.array(
        [u_friction[cold_pixel], u_friction[hot_pixel]])
    u_endmembers = np.array([u[cold_pixel], u[hot_pixel]])
    z_u_endmembers = np.array([z_u[cold_pixel], z_u[hot_pixel]])
    Ta_datum_endmembers = np.array([Ta_datum[cold_pixel], Ta_datum[hot_pixel]])
    z_T_endmembers = np.array([z_T[cold_pixel], z_T[hot_pixel]])
    rho_datum_endmembers = np.array(
        [rho_datum[cold_pixel], rho_datum[hot_pixel]])
    c_p_endmembers = np.array([c_p[cold_pixel], c_p[hot_pixel]])
    d_0_endmembers = np.array([d_0[cold_pixel], d_0[hot_pixel]])
    z_0M_endmembers = np.array([z_0M[cold_pixel], z_0M[hot_pixel]])
    z_0H_endmembers = np.array([z_0H[cold_pixel], z_0H[hot_pixel]])

    H_endmembers = calc_H_residual(Rn_endmembers,
                                   G_endmembers,
                                   LE=LE_endmembers)

    # ==============================================================================
    #     HOT and COLD PIXEL ITERATIONS FOR MONIN-OBUKHOV LENGTH TO CONVERGE
    # ==============================================================================
    # Initially assume stable atmospheric conditions and set variables for
    L_old = np.ones(2)
    L_diff = np.ones(2) * float('inf')
    for iteration in range(max_iterations):
        if np.all(L_diff < L_thres):
            break

        if isinstance(UseL, bool):
            # Recaulculate L and the difference between iterations
            L_endmembers = MO.calc_L(u_friction_endmembers,
                                     Ta_datum_endmembers, rho_datum_endmembers,
                                     c_p_endmembers, H_endmembers,
                                     LE_endmembers)

            L_diff = np.fabs(L_endmembers - L_old) / np.fabs(L_old)
            L_old = np.array(L_endmembers)
            L_old[np.fabs(L_old) == 0] = 1e-36

            u_friction_endmembers = MO.calc_u_star(u_endmembers,
                                                   z_u_endmembers,
                                                   L_endmembers,
                                                   d_0_endmembers,
                                                   z_0M_endmembers)

            u_friction_endmembers = np.maximum(u_friction_min,
                                               u_friction_endmembers)

    # Hot and Cold aerodynamic resistances
    if use_METRIC_resistance is True:
        R_A_params = {
            "z_T": np.array([2.0, 2.0]),
            "u_friction": u_friction_endmembers,
            "L": L_endmembers,
            "d_0": np.array([0.0, 0.0]),
            "z_0H": np.array([0.1, 0.1])
        }
    else:
        R_A_params = {
            "z_T": z_T_endmembers,
            "u_friction": u_friction_endmembers,
            "L": L_endmembers,
            "d_0": d_0_endmembers,
            "z_0H": z_0H_endmembers
        }

    R_A_endmembers, _, _ = tseb.calc_resistances(tseb.KUSTAS_NORMAN_1999,
                                                 {"R_A": R_A_params})

    # Calculate the temperature gradients
    dT_endmembers = calc_dT(H_endmembers, R_A_endmembers, rho_datum_endmembers,
                            c_p_endmembers)

    # dT constants
    # Note: the equations for a and b in the Allen 2007 paper (eq 50 and 51) appear to be wrong.
    dT_b = (dT_endmembers[1] - dT_endmembers[0]) / (Tr_datum[hot_pixel] -
                                                    Tr_datum[cold_pixel])
    dT_a = dT_endmembers[1] - dT_b * Tr_datum[hot_pixel]

    # Apply the constant to the whole image
    dT = dT_a + dT_b * Tr_datum  # Allen 2007 eq. 29

    # ==============================================================================
    #     ITERATIONS FOR MONIN-OBUKHOV LENGTH AND H TO CONVERGE
    # ==============================================================================
    # Initially assume stable atmospheric conditions and set variables for
    L_queue = deque([np.ones(dT.shape)], 6)
    L_converged = np.asarray(np.zeros(Tr_K.shape)).astype(bool)
    L_diff_max = np.inf
    i = np.ones(dT.shape, dtype=bool)
    start_time = time.time()
    loop_time = time.time()

    for n_iterations in range(max_iterations):

        iterations[i] = n_iterations
        if np.all(L_converged):
            break
        current_time = time.time()
        loop_duration = current_time - loop_time
        loop_time = current_time
        total_duration = loop_time - start_time
        print(
            "Iteration: %d, non-converged pixels: %d, max L diff: %f, total time: %f, loop time: %f"
            % (n_iterations, np.sum(~L_converged[i]), L_diff_max,
               total_duration, loop_duration))

        i = ~L_converged

        if use_METRIC_resistance is True:
            R_A_params = {
                "z_T": np.array([2.0, 2.0]),
                "u_friction": u_friction[i],
                "L": L[i],
                "d_0": np.array([0.0, 0.0]),
                "z_0H": np.array([0.1, 0.1])
            }
        else:
            R_A_params = {
                "z_T": z_T[i],
                "u_friction": u_friction[i],
                "L": L[i],
                "d_0": d_0[i],
                "z_0H": z_0H[i]
            }

            R_A[i], _, _ = tseb.calc_resistances(tseb.KUSTAS_NORMAN_1999,
                                                 {"R_A": R_A_params})

        H[i] = calc_H(dT[i], rho[i], c_p[i], R_A[i])
        LE[i] = Rn[i] - G[i] - H[i]

        if isinstance(UseL, bool):
            # Now L can be recalculated and the difference between iterations
            # derived
            L[i] = MO.calc_L(u_friction[i], T_A_K[i], rho[i], c_p[i], H[i],
                             LE[i])

            u_friction[i] = MO.calc_u_star(u[i], z_u[i], L[i], d_0[i], z_0M[i])
            u_friction[i] = np.asarray(
                np.maximum(u_friction_min, u_friction[i]))

            # We check convergence against the value of L from previous iteration but as well
            # against values from 2 or 3 iterations back. This is to catch situations (not
            # infrequent) where L oscillates between 2 or 3 steady state values.
            L_new = np.array(L)
            L_new[L_new == 0] = 1e-36
            L_queue.appendleft(L_new)
            i = ~L_converged
            L_converged[i] = _L_diff(L_queue[0][i], L_queue[1][i]) < L_thres
            L_diff_max = np.max(_L_diff(L_queue[0][i], L_queue[1][i]))
            if len(L_queue) >= 4:
                i = ~L_converged
                L_converged[i] = np.logical_and(
                    _L_diff(L_queue[0][i], L_queue[2][i]) < L_thres,
                    _L_diff(L_queue[1][i], L_queue[3][i]) < L_thres)
            if len(L_queue) == 6:
                i = ~L_converged
                L_converged[i] = np.logical_and.reduce(
                    (_L_diff(L_queue[0][i], L_queue[3][i]) < L_thres,
                     _L_diff(L_queue[1][i], L_queue[4][i]) < L_thres,
                     _L_diff(L_queue[2][i], L_queue[5][i]) < L_thres))

    flag, Ln, LE, H, G, R_A, u_friction, L, iterations = map(
        np.asarray, (flag, Ln, LE, H, G, R_A, u_friction, L, iterations))

    return flag, Ln, LE, H, G, R_A, u_friction, L, iterations
Beispiel #6
0
    def run_METRIC(self, in_data, mask=None):
        ''' Execute the routines to calculate energy fluxes.

        Parameters
        ----------
        in_data : dict
            The input data for the model.
        mask : int array or None
            If None then fluxes will be calculated for all input points. Otherwise, fluxes will be
            calculated only for points for which mask is 1.

        Returns
        -------
        out_data : dict
            The output data from the model.
        '''

        print("Processing...")
        model_params = dict()

        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

        print(
            'Estimating net shortwave radiation using Cambpell two layers approach'
        )
        # 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']

        del difvis, difnir, fvis, fnir

        # ======================================
        # NEt radiation for bare soil
        noVegPixels = np.logical_and(in_data['LAI'] == 0, mask == 1)
        # Calculate roughness
        out_data['z_0M'][noVegPixels] = in_data['z0_soil'][noVegPixels]
        out_data['d_0'][noVegPixels] = 0

        # 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['R_ns1'][noVegPixels] = (1. - spectraGrdOSEB[noVegPixels]) * \
            (out_data['S_dn_dir'][noVegPixels] + out_data['S_dn_dif'][noVegPixels])

        # ======================================
        # Then process vegetated cases
        # Calculate roughness
        i = np.logical_and(in_data['LAI'] > 0, mask == 1)

        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])

        del in_data['h_C'], in_data['w_C'], in_data['f_c']

        Sn_C1, Sn_S1 = 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])

        out_data['R_ns1'][i] = Sn_C1 + Sn_S1
        del Sn_C1, Sn_S1, in_data['LAI'], in_data['x_LAD']
        del in_data['rho_vis_C'], in_data['tau_vis_C'], in_data[
            'rho_nir_C'], in_data['tau_nir_C']
        del in_data['rho_vis_S'], in_data['rho_nir_S']

        out_data['emiss'] = in_data['VI'] * in_data['emis_C'] + (
            1 - in_data['VI']) * in_data['emis_S']

        del in_data['emis_C'], in_data['emis_S']

        out_data['albedo'] = 1.0 - out_data['R_ns1'] / in_data['S_dn']

        # Compute normalized temperatures by adiabatic correction
        gamma_w = met.calc_lapse_rate_moist(in_data['T_A1'], in_data['ea'],
                                            in_data['p'])

        Tr_datum = in_data['T_R1'] + gamma_w * in_data['alt']
        Ta_datum = in_data['T_A1'] + gamma_w * in_data['alt']

        del gamma_w

        # Reduce potential ET based on vegetation density based on Allen et al. 2013
        out_data['ET_r_f_cold'] = np.ones(in_data['T_R1'].shape) * 1.05
        out_data['ET_r_f_cold'][
            in_data['VI'] < VI_MAX] = 1.05 / VI_MAX * in_data['VI'][
                in_data['VI'] < VI_MAX]  # Eq. 4 [Allen 2013]

        out_data['ET_r_f_hot'] = in_data['VI'] * out_data['ET_r_f_cold'] \
                                 + (1.0 - in_data['VI']) * in_data['ET_bare_soil'] # Eq. 5 [Allen 2013]

        # Compute spatial homogeneity metrics
        cv_ndvi, _, _ = endmember_search.moving_cv_filter(
            in_data['VI'], (11, 11))
        cv_lst, _, std_lst = endmember_search.moving_cv_filter(
            Tr_datum, (11, 11))
        cv_albedo, _, _ = endmember_search.moving_cv_filter(
            out_data['albedo'], (11, 11))

        # Create METRIC output metadata
        out_data['T_sd'] = []
        out_data['T_vw'] = []
        out_data['VI_sd'] = []
        out_data['VI_vw'] = []
        out_data['cold_pixel_global'] = []
        out_data['hot_pixel_global'] = []
        out_data['LE_cold'] = []
        out_data['LE_hot'] = []
        out_data['flag'] = np.ones(in_data['T_R1'].shape, dtype=np.byte) * 255
        for j, lc_type in enumerate(SEARCH_ORDER):
            aoi = np.zeros(in_data['T_R1'].shape, dtype=bool)

            print('Running METRIC for %s vegetation' % LC_SEARCH_STRING[j])

            for lc in lc_type:
                aoi[np.logical_and(in_data['landcover'] == lc, mask == 1)] = 1

            # Compute potential ET
            out_data['ET0_datum'][aoi] = METRIC.pet_asce(
                Ta_datum[aoi],
                in_data['u'][aoi],
                in_data['ea'][aoi],
                in_data['p'][aoi],
                in_data['S_dn'][aoi],
                in_data['z_u'][aoi],
                in_data['z_T'][aoi],
                f_cd=1,
                reference=ET0_SEARCH_STRING[j])

            print('Automatic search of METRIC hot and cold pixels')
            # Find hot and cold endmembers in the Area of Interest
            if self.endmember_search == 0:
                [in_data['cold_pixel'], in_data['hot_pixel']
                 ] = endmember_search.cimec(in_data['VI'][aoi],
                                            Tr_datum[aoi],
                                            out_data['albedo'][aoi],
                                            in_data['SZA'][aoi],
                                            cv_ndvi[aoi],
                                            cv_lst[aoi],
                                            adjust_rainfall=False)

            elif self.endmember_search == 1:
                [out_data['cold_pixel'], out_data['hot_pixel']
                 ] = endmember_search.esa(in_data['VI'][aoi], Tr_datum[aoi],
                                          cv_ndvi[aoi], std_lst[aoi],
                                          cv_albedo[aoi])

            else:
                [out_data['cold_pixel'], out_data['hot_pixel']
                 ] = endmember_search.cimec(in_data['VI'][aoi],
                                            Tr_datum[aoi],
                                            out_data['albedo'][aoi],
                                            in_data['SZA'][aoi],
                                            cv_ndvi[aoi],
                                            cv_lst[aoi],
                                            adjust_rainfall=False)

            if out_data['cold_pixel'] == None or out_data['hot_pixel'] == None:
                out_data['T_sd'].append(-9999)
                out_data['T_vw'].append(-9999)
                out_data['VI_sd'].append(-9999)
                out_data['VI_vw'].append(-9999)
                out_data['cold_pixel_global'].append(-9999)
                out_data['hot_pixel_global'].append(-9999)
                out_data['LE_cold'].append(-9999)
                out_data['LE_hot'].append(-9999)
                continue
            else:
                out_data['T_sd'].append(
                    float(Tr_datum[aoi][out_data['hot_pixel']]))
                out_data['T_vw'].append(
                    float(Tr_datum[aoi][out_data['cold_pixel']]))
                out_data['VI_sd'].append(
                    float(in_data['VI'][aoi][out_data['hot_pixel']]))
                out_data['VI_vw'].append(
                    float(in_data['VI'][aoi][out_data['cold_pixel']]))
                out_data['cold_pixel_global'].append(
                    get_nested_position(out_data['cold_pixel'], aoi))
                out_data['hot_pixel_global'].append(
                    get_nested_position(out_data['hot_pixel'], aoi))
                out_data['LE_cold'].append(
                    float(
                        out_data['ET_r_f_cold'][out_data['cold_pixel_global']
                                                [j]] *
                        out_data['ET0_datum'][out_data['cold_pixel_global'][j]]
                    ))
                out_data['LE_hot'].append(
                    float(
                        out_data['ET_r_f_hot'][out_data['hot_pixel_global'][j]]
                        *
                        out_data['ET0_datum'][out_data['hot_pixel_global'][j]])
                )

                # Model settings
                if self.G_form[0][0] == 4:
                    model_params["calcG_params"] = [
                        [1],
                        np.ones(in_data['T_R1'][aoi].shape) * self.G_form[1][j]
                    ]

                elif self.G_form[0][0] == 5:
                    model_params["calcG_params"] = [
                        [1], (in_data['T_R1'][aoi] - 273.15) *
                        (0.0038 + 0.0074 * out_data['albedo'][aoi]) *
                        (1.0 - 0.98 * in_data['VI'][aoi]**4)
                    ]

                else:
                    model_params["calcG_params"] = [
                        self.G_form[0], self.G_form[1][aoi]
                    ]

                # Other fluxes for vegetation
                self._call_flux_model(in_data, out_data, model_params, aoi)

        del in_data, model_params, aoi, Tr_datum, cv_ndvi, cv_lst, std_lst, cv_albedo

        # Calculate the global net radiation
        out_data['R_n1'] = out_data['R_ns1'] + out_data['R_nl1']

        print("Finished processing!")
        return out_data