示例#1
0
def main(biophysical_file, output_file):

    # Read the required data
    lai_cab, geo_coding = su.read_snappy_product(biophysical_file, 'lai_cab')
    lai_cw = su.read_snappy_product(biophysical_file, 'lai_cw')[0]

    cab = np.clip(np.array(lai_cab), 0.0, 140.0)
    refl_vis, trans_vis = cab_to_vis_spectrum(cab)

    cw = np.clip(np.array(lai_cw), 0.0, 0.1)
    refl_nir, trans_nir = cw_to_nir_spectrum(cw)

    su.write_snappy_product(output_file, [{
        'band_name': 'refl_vis_c',
        'band_data': refl_vis
    }, {
        'band_name': 'refl_nir_c',
        'band_data': refl_nir
    }, {
        'band_name': 'trans_vis_c',
        'band_data': trans_vis
    }, {
        'band_name': 'trans_nir_c',
        'band_data': trans_nir
    }], 'leafSpectra', geo_coding)
示例#2
0
def main(sza_file, biophysical_file, min_frac_green, output_file):

    # Read the required data
    fapar, geo_coding = su.read_snappy_product(biophysical_file, 'fapar')
    fapar = fapar.astype(np.float32)
    lai = su.read_snappy_product(biophysical_file, 'lai')[0].astype(np.float32)
    sza = su.read_snappy_product(sza_file, 'sun_zenith')[0].astype(np.float32)

    # Calculate fraction of vegetation which is green
    f_g = np.ones(lai.shape, np.float32)
    # Iterate until f_g converges
    converged = np.zeros(lai.shape, dtype=bool)
    # For pixels where LAI or FAPAR are below tolerance threshold of the S2 biophysical
    # processor, assume that the soil is bare and f_g = 1
    converged[np.logical_or(lai <= 0.2, fapar <= 0.1)] = True
    for c in range(50):
        f_g_old = f_g.copy()
        fipar = TSEB.calc_F_theta_campbell(sza[~converged],
                                           lai[~converged]/f_g[~converged],
                                           w_C=1, Omega0=1, x_LAD=1)
        f_g[~converged] = fapar[~converged] / fipar
        f_g = np.clip(f_g, min_frac_green, 1.)
        converged = np.logical_or(np.isnan(f_g), np.abs(f_g - f_g_old) < 0.02)
        if np.all(converged):
            break

    su.write_snappy_product(output_file, [{'band_name': 'frac_green', 'band_data': f_g}],
                            'fracGreen', geo_coding)
示例#3
0
def main(source, template, output, resample_algorithm):

    # Save source and template to GeoTIFF becasue it will need to be read by GDAL
    temp_file = tempfile.NamedTemporaryFile(suffix=".tif", delete=False)
    temp_source_path = temp_file.name
    temp_file.close()
    su.copy_bands_to_file(source, temp_source_path)
    temp_file = tempfile.NamedTemporaryFile(suffix=".tif", delete=False)
    temp_template_path = temp_file.name
    temp_file.close()
    su.copy_bands_to_file(template, temp_template_path)

    # Wrap the source based on tamplate
    wraped = gu.resample_with_gdalwarp(temp_source_path, temp_template_path,
                                       resample_algorithm)

    # Save with snappy
    name, geo_coding = su.get_product_info(template)[0:2]
    bands = su.get_bands_info(source)
    for i, band in enumerate(bands):
        band['band_data'] = wraped.GetRasterBand(i + 1).ReadAsArray()
    su.write_snappy_product(output, bands, name, geo_coding)

    # Clean up
    try:
        os.remove(temp_source_path)
        os.remove(temp_template_path)
    except Exception:
        pass
def main(meteo_product, at_band, vp_band, ap_band, at_height, output_file):

    at, geo_coding = su.read_snappy_product(meteo_product, at_band)
    at = at.astype(np.float32)
    vp = su.read_snappy_product(meteo_product, vp_band)[0].astype(np.float32)
    ap = su.read_snappy_product(meteo_product, ap_band)[0].astype(np.float32)

    irrad = rad.calc_longwave_irradiance(vp, at, ap, at_height)

    band_data = [{'band_name': 'longwave_irradiance', 'band_data': irrad}]

    su.write_snappy_product(output_file, band_data, 'longwaveIrradiance',
                            geo_coding)
def main(ief_file, mi_file, output_file):

    # Read the required data
    le_band, geo_coding = su.read_snappy_product(ief_file, 'latent_heat_flux')
    le_band = le_band.astype(np.float32)
    sdn_band = su.read_snappy_product(mi_file, 'clear_sky_solar_radiation')[0].astype(np.float32)
    sdn_24_band = su.read_snappy_product(mi_file, 'average_daily_solar_irradiance')[0].astype(np.float32)

    le = np.array(le_band)
    sdn = np.array(sdn_band)
    sdn_24 = np.array(sdn_24_band)

    et_daily = met.flux_2_evaporation(sdn_24 * le / sdn, T_K=20+273.15, time_domain=24)
    
    su.write_snappy_product(output_file, [{'band_name': 'daily_evapotranspiration', 'band_data': et_daily}],
                            'dailySpectra', geo_coding)
示例#6
0
def main(lai_map, landcover_params_map, soil_roughness, output_file):

    lai, geo_coding = su.read_snappy_product(lai_map, 'lai')
    lai = lai.astype(np.float32)
    height = su.read_snappy_product(landcover_params_map,
                                    'veg_height')[0].astype(np.float32)
    height_width_ratio = su.read_snappy_product(
        landcover_params_map, 'veg_height_width_ratio')[0].astype(np.float32)
    fractional_cover = su.read_snappy_product(
        landcover_params_map, 'veg_fractional_cover')[0].astype(np.float32)
    classification = su.read_snappy_product(
        landcover_params_map, 'igbp_classification')[0].astype(np.float32)

    z_OM = np.full(lai.shape, np.nan, np.float32)
    d_0 = np.full(lai.shape, np.nan, np.float32)

    i = lai <= 0
    z_OM[i] = soil_roughness
    d_0[i] = 0

    i = lai > 0
    z_OM[i], d_0[i] = res.calc_roughness(lai[i], height[i],
                                         height_width_ratio[i],
                                         classification[i],
                                         fractional_cover[i])

    band_data = [{
        'band_name': 'roughness_length',
        'band_data': z_OM
    }, {
        'band_name': 'zero_plane_displacement',
        'band_data': d_0
    }]

    su.write_snappy_product(output_file, band_data, 'aerodynamicRoughness',
                            geo_coding)
def main(lsp_product, lai_product, csp_product, mi_product, sza_product,
         soil_ref_vis, soil_ref_nir, output_file):

    refl_vis_c, geo_coding = su.read_snappy_product(lsp_product, 'refl_vis_c')
    refl_vis_c = refl_vis_c.astype(np.float32)
    refl_nir_c = su.read_snappy_product(lsp_product,
                                        'refl_nir_c')[0].astype(np.float32)
    trans_vis_c = su.read_snappy_product(lsp_product,
                                         'trans_vis_c')[0].astype(np.float32)
    trans_nir_c = su.read_snappy_product(lsp_product,
                                         'trans_nir_c')[0].astype(np.float32)

    lai = su.read_snappy_product(lai_product, 'lai')[0].astype(np.float32)

    lad = su.read_snappy_product(
        csp_product, 'veg_inclination_distribution')[0].astype(np.float32)
    frac_cover = su.read_snappy_product(
        csp_product, 'veg_fractional_cover')[0].astype(np.float32)
    hw_ratio = su.read_snappy_product(
        csp_product, 'veg_height_width_ratio')[0].astype(np.float32)

    p = su.read_snappy_product(mi_product,
                               'air_pressure')[0].astype(np.float32)
    irradiance = su.read_snappy_product(
        mi_product, 'clear_sky_solar_radiation')[0].astype(np.float32)

    sza = su.read_snappy_product(sza_product,
                                 'solar_zenith_tn')[0].astype(np.float32)

    net_rad_c = np.zeros(lai.shape, np.float32)
    net_rad_s = np.zeros(lai.shape, np.float32)
    soil_ref_vis = np.full(lai.shape, soil_ref_vis, np.float32)
    soil_ref_nir = np.full(lai.shape, soil_ref_nir, np.float32)

    #Estimate diffuse and direct irradiance
    difvis, difnir, fvis, fnir = rad.calc_difuse_ratio(irradiance, sza, p)
    skyl = difvis * fvis + difnir * fnir
    irradiance_dir = irradiance * (1.0 - skyl)
    irradiance_dif = irradiance * skyl

    # Net shortwave radition for bare soil
    i = lai <= 0
    spectra_soil = fvis[i] * soil_ref_vis[i] + fnir[i] * soil_ref_nir[i]
    net_rad_s[i] = (1. - spectra_soil) * (irradiance_dir[i] +
                                          irradiance_dif[i])

    # Net shortwave radiation for vegetated areas
    i = lai > 0
    F = lai[i] / frac_cover[i]
    # Clumping index
    omega0 = ci.calc_omega0_Kustas(lai[i],
                                   frac_cover[i],
                                   lad[i],
                                   isLAIeff=True)
    omega = ci.calc_omega_Kustas(omega0, sza[i], hw_ratio[i])
    lai_eff = F * omega
    [net_rad_c[i], net_rad_s[i]] = rad.calc_Sn_Campbell(
        lai[i], sza[i], irradiance_dir[i], irradiance_dif[i], fvis[i], fnir[i],
        refl_vis_c[i], trans_vis_c[i], refl_nir_c[i], trans_nir_c[i],
        soil_ref_vis[i], soil_ref_nir[i], lad[i], lai_eff)

    band_data = [{
        'band_name': 'net_shortwave_radiation_canopy',
        'band_data': net_rad_c
    }, {
        'band_name': 'net_shortwave_radiation_soil',
        'band_data': net_rad_s
    }]

    su.write_snappy_product(output_file, band_data, 'netShortwaveRadiation',
                            geo_coding)
示例#8
0
def main(high_res_reflectance, low_res_lst, high_res_dem, lst_quality_mask,
         elevation_band, lst_good_quality_flags, cv_homogeneity_threshold,
         moving_window_size, parallel_jobs, output):

    print('INFO: Preparing high-resolution data...')
    # Elevation
    temp_file = tempfile.NamedTemporaryFile(suffix=".tif", delete=False)
    temp_dem_file = temp_file.name
    temp_file.close()
    su.copy_bands_to_file(high_res_dem, temp_dem_file, [elevation_band])
    # Reflectance
    temp_file = tempfile.NamedTemporaryFile(suffix=".tif", delete=False)
    temp_refl_file = temp_file.name
    temp_file.close()
    su.copy_bands_to_file(high_res_reflectance, temp_refl_file)
    # Combine all high-resolution data into one virtual raster
    vrt_filename = pth.splitext(temp_refl_file)[0] + ".vrt"
    fp = gu.merge_raster_layers([temp_refl_file, temp_dem_file],
                                vrt_filename,
                                separate=True)
    fp = None
    high_res_filename = vrt_filename

    print('INFO: Preparing low-resolution data...')
    # LST
    temp_file = tempfile.NamedTemporaryFile(suffix=".tif", delete=False)
    temp_lst_file = temp_file.name
    temp_file.close()
    su.copy_bands_to_file(low_res_lst, temp_lst_file, ["LST"])
    # Quality mask
    temp_file = tempfile.NamedTemporaryFile(suffix=".tif", delete=False)
    temp_mask_file = temp_file.name
    temp_file.close()
    su.copy_bands_to_file(lst_quality_mask, temp_mask_file)

    # Set disaggregator options
    flags = [int(i) for i in lst_good_quality_flags.split(",")]
    dms_options = {
        "highResFiles": [high_res_filename],
        "lowResFiles": [temp_lst_file],
        "lowResQualityFiles": [temp_mask_file],
        "lowResGoodQualityFlags": flags,
        "cvHomogeneityThreshold": cv_homogeneity_threshold,
        "movingWindowSize": moving_window_size,
        "disaggregatingTemperature": True,
        "baggingRegressorOpt": {
            "n_jobs": parallel_jobs,
            "n_estimators": 30,
            "max_samples": 0.8,
            "max_features": 0.8
        }
    }
    disaggregator = DecisionTreeSharpener(**dms_options)

    # Sharpen
    print("INFO: Training regressor...")
    disaggregator.trainSharpener()
    print("INFO: Sharpening...")
    downscaled_file = disaggregator.applySharpener(high_res_filename,
                                                   temp_lst_file)
    print("INFO: Residual analysis...")
    residual_image, corrected_image = disaggregator.residualAnalysis(
        downscaled_file, temp_lst_file, temp_mask_file, doCorrection=True)
    # Save the sharpened file
    band = {
        "band_name": "LST",
        "description": "Sharpened Sentinel-3 LST",
        "unit": "K",
        "band_data": corrected_image.GetRasterBand(1).ReadAsArray()
    }
    geo_coding = su.get_product_info(high_res_reflectance)[1]
    su.write_snappy_product(output, [band], "sharpenedLST", geo_coding)

    # Clean up
    try:
        os.remove(temp_dem_file)
        os.remove(temp_refl_file)
        os.remove(temp_lst_file)
        os.remove(temp_mask_file)
    except Exception:
        pass
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)
def main(low_res_lst, sharp_lst, gt_high_res_lst, save_residuals,
         output_residual):

    # Read rasters from BEAM-DIMAP products
    low_res_raster, _ = su.read_snappy_product(low_res_lst, band_name='LST')
    sharp_raster, geo_coding = su.read_snappy_product(sharp_lst,
                                                      band_name='LST')
    gt_high_res_raster, _ = su.read_snappy_product(gt_high_res_lst,
                                                   band_name='LST')

    height, width = sharp_raster.shape

    # Create baseline nearest-neighbor-interpolation sharpening
    baseline_raster = cv2.resize(low_res_raster,
                                 dsize=(width, height),
                                 interpolation=cv2.INTER_NEAREST)

    # Make sure ground-truth and sharpened LST are the same size
    gt_high_res_raster = cv2.resize(gt_high_res_raster,
                                    dsize=(width, height),
                                    interpolation=cv2.INTER_NEAREST)

    # Get quality pixels
    quality_mask = ~np.isnan(sharp_raster)  # Ignore pixels with NaN values
    n_quality_pixels = np.sum(quality_mask)

    # Evaluate baseline
    baseline_residual = gt_high_res_raster - baseline_raster
    rmse = np.sqrt(
        np.nansum(baseline_residual[quality_mask]**2) / n_quality_pixels)
    median_bias = np.nanmedian(baseline_residual[quality_mask])
    std_bias = np.nanstd(baseline_residual[quality_mask])
    print("\nBaseline nearest neighbor upsampling:")
    print("\tRMSE: {:.2f}".format(rmse))
    print("\tMedian bias: {:.2f}".format(median_bias))
    print("\tStandard deviation of bias: {:.2f}".format(std_bias))

    # Evaluate sharpening
    sharp_residual = gt_high_res_raster - sharp_raster
    rmse = np.sqrt(
        np.nansum(sharp_residual[quality_mask]**2) / n_quality_pixels)
    median_bias = np.nanmedian(sharp_residual[quality_mask])
    std_bias = np.nanstd(sharp_residual[quality_mask])
    print("\nSharpening:")
    print("\tRMSE: {:.2f}".format(rmse))
    print("\tMedian bias: {:.2f}".format(median_bias))
    print("\tStandard deviation of bias: {:.2f}".format(std_bias))

    if save_residuals:  # Save the residuals
        baseline_band = {
            "band_name": "baseline_LST_residual",
            "description": "Residual of the baseline LST upsampling via " +
            "nearest neighbor interpolation",
            "unit": "K",
            "band_data": baseline_residual
        }
        sharp_band = {
            "band_name": "sharp_LST_residual",
            "description": "Residual of the sharpened LST",
            "unit": "K",
            "band_data": sharp_residual
        }
        if output_residual is None:
            output_residual = os.path.splitext(low_res_lst)[0] + \
                              'residuals.dim'
        su.write_snappy_product(output_residual, [baseline_band, sharp_band],
                                "sharpening_residuals", geo_coding)
示例#11
0
def main(elevation_map, elevation_band, ecmwf_data_file, date_time_utc,
         time_zone, prepare_temperature, prepare_vapour_pressure,
         prepare_air_pressure, prepare_wind_speed,
         prepare_clear_sky_solar_radiation, prepare_daily_solar_irradiance,
         output_file):

    # Save elevation to GeoTIFF becasue it will need to be read by GDAL later
    temp_file = tempfile.NamedTemporaryFile(suffix=".tif", delete=False)
    temp_elev_path = temp_file.name
    temp_file.close()
    su.copy_bands_to_file(elevation_map, temp_elev_path, [elevation_band])

    # Calculate required meteorological parameters
    bands = []
    if prepare_temperature:
        data = eu.get_ECMWF_data(ecmwf_data_file, 'air_temperature',
                                 date_time_utc, temp_elev_path, time_zone)
        bands.append({
            'band_data': data,
            'band_name': 'air_temperature',
            'description': 'Air temperature at 100 m above surface(K)'
        })
    if prepare_vapour_pressure:
        data = eu.get_ECMWF_data(ecmwf_data_file, 'vapour_pressure',
                                 date_time_utc, temp_elev_path, time_zone)
        bands.append({
            'band_data': data,
            'band_name': 'vapour_pressure',
            'description': 'Surface vapour pressure (mb)'
        })
    if prepare_air_pressure:
        data = eu.get_ECMWF_data(ecmwf_data_file, 'air_pressure',
                                 date_time_utc, temp_elev_path, time_zone)
        bands.append({
            'band_data': data,
            'band_name': 'air_pressure',
            'description': 'Surface air pressure (mb)'
        })
    if prepare_wind_speed:
        data = eu.get_ECMWF_data(ecmwf_data_file, 'wind_speed', date_time_utc,
                                 temp_elev_path, time_zone)
        bands.append({
            'band_data': data,
            'band_name': 'wind_speed',
            'description': 'Wind speed at 100 m above surface (m/s)'
        })
    if prepare_clear_sky_solar_radiation:
        data = eu.get_ECMWF_data(ecmwf_data_file, 'clear_sky_solar_radiation',
                                 date_time_utc, temp_elev_path, time_zone)
        bands.append({
            'band_data':
            data,
            'band_name':
            'clear_sky_solar_radiation',
            'description':
            'Instantenous clear sky surface solar irradiance (W/m^2)'
        })
    if prepare_daily_solar_irradiance:
        data = eu.get_ECMWF_data(ecmwf_data_file,
                                 'average_daily_solar_irradiance',
                                 date_time_utc, temp_elev_path, time_zone)
        bands.append({
            'band_data': data,
            'band_name': 'average_daily_solar_irradiance',
            'description': 'Average daily solar irradiance (W/m^2)'
        })

    # Save the output file
    geo_coding = su.read_snappy_product(elevation_map, elevation_band)[1]
    su.write_snappy_product(output_file, bands, 'ecmwfData', geo_coding)
def main(landsat_product_path, band_number, lst_output):

    # Find files for the specified TIR band
    tir_files = glob(
        os.path.join(landsat_product_path, '*_B{}*'.format(band_number)))
    try:
        # If more than one matching file, open the first match by default
        tir_file = tir_files[0]
    except IndexError:
        print("Found zero files corresponding to band {}".format(band))
    tir_data = gdal.Open(tir_file)
    tir_raster = tir_data.GetRasterBand(1).ReadAsArray().astype(float)

    # Get conversion parameters from the metadata
    metadata_files = glob(os.path.join(landsat_product_path, '*_MTL*'))
    try:
        # If more than one matching file, open the first match by default
        metadata_file = metadata_files[0]
    except IndexError:
        print("Found zero metadata (MTL) files")
    params = get_conversion_params(metadata_file, band_number)

    print('INFO: Converting DN to TOA spectral radiance...')
    radiance = dn_to_radiance(tir_raster, params['radiance_mult_band'],
                              params['radiance_add_band'])

    print('INFO: Converting TOA spectral radiance to ' +
          'at-sensor brightness temperature...')
    bt = radiance_to_bt(radiance, params['k1'], params['k2'])

    print('INFO: Estimating land surface emissivity...')
    lse = land_surface_emissivity(landsat_product_path)

    print('INFO: Converting at-sensor brightness temperature to ' +
          'land surface temperature...')
    lst = bt_to_lst(bt, lse, band_number)

    # Write estimated LST into new GeoTiff
    print('INFO: Saving output...')
    driver = gdal.GetDriverByName("GTiff")
    driver.Register()
    # Ensure that output is saved in GeoTiff format
    file_name = os.path.splitext(lst_output)[0] + '.TIF'
    lst_data = driver.CreateCopy(file_name, tir_data, strict=0)
    lst_data.GetRasterBand(1).WriteArray(lst)
    lst_data.GetRasterBand(1).FlushCache()

    # Clean up
    tir_data = None
    lst_data = None
    try:
        os.remove(os.path.splitext(lst_output)[0] + '.IMD')
    except Exception:
        pass

    # Keep a BEAM-DIMAP file instead if the output extension is '.dim'
    ext = os.path.splitext(lst_output)[-1]
    if ext.casefold() == '.dim':
        # Read from recently saved GeoTiff
        old_file_name = file_name
        product = ProductIO.readProduct(old_file_name)
        band = {
            "band_name": "LST",
            "description": "LST estimated from Landsat TIR",
            "unit": "K",
            "band_data": lst
        }
        geo_coding = product.getSceneGeoCoding()
        file_name = os.path.splitext(lst_output)[0] + '.dim'
        su.write_snappy_product(file_name, [band], "Landsat_LST", geo_coding)
        try:
            os.remove(old_file_name)  # Remove GeoTiff copy
        except Exception:
            pass
    elif (ext.casefold() != '.TIF') and (ext.casefold() != '.TIFF'):
        print("INFO: Given output file extension was not recognized. " +
              "Output was saved as a GeoTiff instead.")
示例#13
0
def main(landcover_map, lai_map, fgv_map, landcover_band, lookup_table, produce_vh, produce_fc,
        produce_chwr, produce_lw, produce_lid, produce_igbp, output_file):

    # Read the required data

    PARAMS = ['veg_height', 'lai_max', 'is_herbaceous', 'veg_fractional_cover',
              'veg_height_width_ratio', 'veg_leaf_width', 'veg_inclination_distribution',
              'igbp_classification'
              ]
    
    landcover, geo_coding = su.read_snappy_product(landcover_map, landcover_band)
    landcover = landcover.astype(np.float32)
    lai = su.read_snappy_product(lai_map, 'lai')[0].astype(np.float32)
    fg = su.read_snappy_product(fgv_map, 'frac_green')[0].astype(np.float32)
    with open(lookup_table, 'r') as fp:
        lines = fp.readlines()
    headers = lines[0].rstrip().split(';')
    values = [x.rstrip().split(';') for x in lines[1:]]
    lut = {key: [float(x[idx]) for x in values if len(x) == len(headers)]
            for idx, key in enumerate(headers)}

    for param in PARAMS:
        if param not in lut.keys():
            print(f'Error: Missing {param} in the look-up table')
            return

    band_data = []
    param_value = np.ones(landcover.shape, np.float32) + np.nan

    if produce_vh:
        for lc_class in np.unique(landcover[~np.isnan(landcover)]):
            lc_pixels = np.where(landcover == lc_class)
            lc_index = lut["landcover_class"].index(lc_class)
            param_value[lc_pixels] = lut['veg_height'][lc_index]

            # Vegetation height in herbaceous vegetation depends on plant area index
            if lut["is_herbaceous"][lc_index] == 1:
                pai = lai / fg
                pai = pai[lc_pixels]
                param_value[lc_pixels] = \
                    0.1 * param_value[lc_pixels] + 0.9 * param_value[lc_pixels] *\
                    np.minimum((pai / lut['veg_height'][lc_index])**3.0, 1.0)
        band_data.append({'band_name': 'veg_height', 'band_data': param_value})
    
    if produce_fc:
        band_name = 'veg_fractional_cover'
        param_value = _estimate_param_value(landcover, lut, band_name)
        band_data.append({'band_name': band_name, 'band_data': param_value})
    
    if produce_chwr:
        band_name = 'veg_height_width_ratio'
        param_value = _estimate_param_value(landcover, lut, band_name)
        band_data.append({'band_name': band_name, 'band_data': param_value})

    if produce_lw:
        band_name = 'veg_leaf_width'
        param_value = _estimate_param_value(landcover, lut, band_name)
        band_data.append({'band_name': band_name, 'band_data': param_value})

    if produce_lid:
        band_name = 'veg_inclination_distribution'
        param_value = _estimate_param_value(landcover, lut, band_name)
        band_data.append({'band_name': band_name, 'band_data': param_value})

    if produce_igbp:
        band_name = 'igbp_classification'
        param_value = _estimate_param_value(landcover, lut, band_name)
        band_data.append({'band_name': band_name, 'band_data': param_value})

    su.write_snappy_product(output_file, band_data, 'landcoverParams', geo_coding)
示例#14
0
def main(sentinel_2_reflectance, sentinel_3_lst, high_res_dem, high_res_geom, lst_quality_mask,
         date_time_utc, elevation_band, lst_good_quality_flags, cv_homogeneity_threshold,
         moving_window_size, parallel_jobs, output):

    # Derive illumination conditions from the DEM
    print('INFO: Deriving solar illumination conditions...')
    temp_file = tempfile.NamedTemporaryFile(suffix=".tif", delete=False)
    temp_dem_file = temp_file.name
    temp_file.close()
    su.copy_bands_to_file(high_res_dem, temp_dem_file, [elevation_band])
    temp_slope_file = gu.slope_from_dem(temp_dem_file)
    temp_aspect_file = gu.aspect_from_dem(temp_dem_file)
    slope = gu.raster_data(temp_slope_file)
    aspect = gu.raster_data(temp_aspect_file)
    try:
        lat = su.read_snappy_product(high_res_geom, 'latitude_tx')[0]
    except RuntimeError:
        lat = su.read_snappy_product(high_res_geom, 'latitude_in')[0]
    try:
        lon = su.read_snappy_product(high_res_geom, 'longitude_tx')[0]
    except RuntimeError:
        lon = su.read_snappy_product(high_res_geom, 'longitude_in')[0]
    doy = date_time_utc.timetuple().tm_yday
    ftime = date_time_utc.hour + date_time_utc.minute/60.0
    cos_theta = incidence_angle_tilted(lat, lon, doy, ftime, stdlon=0, A_ZS=aspect, slope=slope)
    proj, gt = gu.raster_info(temp_dem_file)[0:2]
    temp_cos_theta_file = pth.splitext(temp_dem_file)[0] + '_cos_theta.tif'
    fp = gu.save_image(cos_theta, gt, proj, temp_cos_theta_file)
    fp = None
    slope = None
    aspect = None
    cos_theta = None

    print('INFO: Preparing high-resolution data...')
    # Combine all high-resolution data into one virtual raster
    temp_file = tempfile.NamedTemporaryFile(suffix=".tif", delete=False)
    temp_refl_file = temp_file.name
    temp_file.close()
    su.copy_bands_to_file(sentinel_2_reflectance, temp_refl_file)
    vrt_filename = pth.splitext(temp_refl_file)[0]+".vrt"
    fp = gu.merge_raster_layers([temp_refl_file, temp_dem_file, temp_cos_theta_file],
                                vrt_filename, separate=True)
    fp = None
    high_res_filename = vrt_filename

    # Save low resolution files as geotiffs
    temp_file = tempfile.NamedTemporaryFile(suffix=".tif", delete=False)
    temp_lst_file = temp_file.name
    temp_file.close()
    su.copy_bands_to_file(sentinel_3_lst, temp_lst_file, ["LST"])
    temp_file = tempfile.NamedTemporaryFile(suffix=".tif", delete=False)
    temp_mask_file = temp_file.name
    temp_file.close()
    su.copy_bands_to_file(lst_quality_mask, temp_mask_file)

    # Set options of the disaggregator
    flags = [int(i) for i in lst_good_quality_flags.split(",")]
    dms_options =\
        {"highResFiles": [high_res_filename],
         "lowResFiles": [temp_lst_file],
         "lowResQualityFiles": [temp_mask_file],
         "lowResGoodQualityFlags": flags,
         "cvHomogeneityThreshold": cv_homogeneity_threshold,
         "movingWindowSize": moving_window_size,
         "disaggregatingTemperature":  True,
         "baggingRegressorOpt":        {"n_jobs": parallel_jobs, "n_estimators": 30,
                                        "max_samples": 0.8, "max_features": 0.8}}
    disaggregator = DecisionTreeSharpener(**dms_options)

    # Do the sharpening
    print("INFO: Training regressor...")
    disaggregator.trainSharpener()
    print("INFO: Sharpening...")
    downscaled_file = disaggregator.applySharpener(high_res_filename, temp_lst_file)
    print("INFO: Residual analysis...")
    residual_image, corrected_image = disaggregator.residualAnalysis(downscaled_file,
                                                                     temp_lst_file,
                                                                     temp_mask_file,
                                                                     doCorrection=True)
    # Save the sharpened file
    band = {"band_name": "sharpened_LST", "description": "Sharpened Sentinel-3 LST", "unit": "K",
            "band_data": corrected_image.GetRasterBand(1).ReadAsArray()}
    geo_coding = su.get_product_info(sentinel_2_reflectance)[1]
    su.write_snappy_product(output, [band], "sharpenedLST", geo_coding)

    # Clean up
    try:
        os.remove(temp_dem_file)
        os.remove(temp_aspect_file)
        os.remove(temp_slope_file)
        os.remove(temp_cos_theta_file)
        os.remove(temp_refl_file)
        os.remove(temp_lst_file)
        os.remove(temp_mask_file)
    except Exception:
        pass