def test_Image_set_solar_vars_defaults(xy, interp, rs1, rs24, tol=1E-4): """Test that the default MERRA2 Rs values are returned""" d_obj = disalexi.Image(test_img) d_obj._set_solar_vars(interpolate_flag=interp) assert abs( utils.image_value(ee.Image(d_obj.rs1), xy, scale=0.1)['rs'] - rs1) <= tol assert abs( utils.image_value(ee.Image(d_obj.rs24), xy, scale=0.1)['rs'] - rs24) <= tol
def test_Image_set_solar_vars_assets_no_interp(xy, rs1, rs24, tol=1E-4): """Test that the default MERRA2 Rs values are returned""" d_obj = disalexi.Image(test_img) d_obj.rs_hourly_coll = ee.ImageCollection([ ee.Image(asset_ws + 'Insol1').setMulti( {'system:time_start': img_hour_start}) ]) d_obj.rs_daily_coll = ee.ImageCollection([ ee.Image(asset_ws + 'Insol24') \ .setMulti({'system:time_start': img_date_start})]) d_obj._set_solar_vars(interpolate_flag=False) assert abs(utils.image_value(ee.Image(d_obj.rs1), xy)['rs'] - rs1) <= tol assert abs(utils.image_value(ee.Image(d_obj.rs24), xy)['rs'] - rs24) <= tol
def test_Image_set_time_vars_defaults(xy, t_rise, t_end, tol=1E-8): """Test setting the land cover image and type directly on the object High NDVI test point values CGM - Should probably switch this to a constant image test """ d_obj = disalexi.Image(test_img) d_obj._set_time_vars() assert abs( utils.image_value(ee.Image(d_obj.t_rise), xy)['t_rise'] - t_rise) <= tol assert abs(utils.image_value(ee.Image(d_obj.t_end), xy)['t_end'] - t_end) <= tol
def test_Image_set_landcover_vars_init_asset(tol=1E-6): """Test setting the land cover image and type as the object is initialized""" d_obj = disalexi.Image(test_img, lc_type='NLCD', landcover=ee.Image(asset_ws + 'landcover')) d_obj._set_landcover_vars() assert utils.image_value(ee.Image(d_obj.aleafv))['aleafv'] == 0.83
def test_Landsat_get_lst(red, nir, bt, expected, tol=0.001): """Test that different emissivity values (from NDVI & LAI) change LST""" input_img = ee.Image.constant([0.2, 0.2, red, nir, 0.2, 0.2, bt, 0]) \ .rename(['B2', 'B3', 'B4', 'B5', 'B6', 'B7', 'B10', 'BQA']) \ .setMulti(l8_properties) lst = ee.Image(landsat.Landsat(input_img)._get_lst()) assert abs(utils.image_value(lst)['lst'] - expected) <= tol
def test_Image_set_landcover_vars_set_asset(tol=1E-6): """Test setting the land cover image and type directly on the object""" d_obj = disalexi.Image(test_img) d_obj.landcover = ee.Image(asset_ws + 'landcover'), d_obj.lc_type = 'NLCD' d_obj._set_landcover_vars() assert utils.image_value(ee.Image(d_obj.aleafv))['aleafv'] == 0.83
def test_Image_set_elevation_vars(xy, elevation, pressure, tol=1E-6): """""" d_obj = disalexi.Image(test_img) d_obj.elevation = ee.Image.constant(elevation) d_obj._set_elevation_vars() assert abs( utils.image_value(ee.Image(d_obj.pressure), xy=xy)['pressure'] - pressure) <= tol
def test_Image_set_weather_var_assets(tol=0.01): d_obj = disalexi.Image(test_img) d_obj.windspeed_coll = ee.ImageCollection([ ee.Image([ee.Image(asset_ws + 'u'), ee.Image(asset_ws + 'u').multiply(0)]) \ .setMulti({'system:time_start': img_date_start})]) d_obj._set_weather_vars() assert abs( utils.image_value(ee.Image(d_obj.windspeed))['windspeed'] - 7.02662301063538) <= tol
def test_Image_set_landcover_vars_default(tol=1E-6): """Test default land cover image and type It might make more sense to just test that the value at the test pixel is 82 (for NLCD) for 10 (for GLC30)""" d_obj = disalexi.Image(test_img) d_obj._set_landcover_vars() assert utils.image_value(ee.Image(d_obj.aleafv))['aleafv'] == 0.83 assert utils.image_value(ee.Image(d_obj.aleafn))['aleafn'] == 0.35 assert utils.image_value(ee.Image(d_obj.aleafl))['aleafl'] == 0.95 assert utils.image_value(ee.Image(d_obj.adeadv))['adeadv'] == 0.49 assert utils.image_value(ee.Image(d_obj.adeadn))['adeadn'] == 0.13 assert utils.image_value(ee.Image(d_obj.adeadl))['adeadl'] == 0.95 assert utils.image_value(ee.Image(d_obj.leaf_width))['xl'] == 0.05 assert utils.image_value(ee.Image(d_obj.clump))['omega'] == 0.83
def test_solar_zenith_image(timestamp, xy, expected, tol=1E-10): """Check that the solar zenith function works for real images""" output_images = tseb_utils.solar_zenith( date=ee.Date(timestamp), lon=ee.Image.pixelLonLat().select(['longitude' ]).multiply(math.pi / 180), lat=ee.Image.pixelLonLat().select(['latitude' ]).multiply(math.pi / 180)) output = utils.image_value(ee.Image(output_images).rename(['vs']), xy=xy)['vs'] logging.debug('\n Target values: {}'.format(expected)) logging.debug(' Output values: {}'.format(output)) assert abs(output - expected) <= tol
def test_Landsat_get_albedo(blue, green, red, nir, swir1, swir2, tol=0.000001): """Test the albedo calculation Ensure that the Green band is not being used to compute albedo """ expected = sum([ a * b for a, b in zip([blue, red, nir, swir1, swir2, 1], [0.356, 0.130, 0.373, 0.085, 0.072, -0.0018]) ]) input_img = ee.Image.constant([blue, green, red, nir, swir1, swir2, 300, 0]) \ .rename(['B2', 'B3', 'B4', 'B5', 'B6', 'B7', 'B10', 'BQA']) \ .setMulti(l8_properties) albedo = ee.Image(landsat.Landsat(ee.Image(input_img))._get_albedo()) assert abs(utils.image_value(albedo)['albedo'] - expected) <= tol
def test_Image_compute_ta_test_asset(xy, iterations, expected, tol=0.01): """Test coarse scale air temperature at a single point using the test assets""" d_obj = disalexi.Image(test_img, elevation=ee.Image.constant(350.0), iterations=iterations, lc_type='NLCD', landcover=ee.Image(asset_ws + 'landcover')) # Overwrite the default ancillary images with the test assets d_obj.windspeed_coll = ee.ImageCollection([ ee.Image([ ee.Image(asset_ws + 'u'), ee.Image(asset_ws + 'u').multiply(0)]) \ .setMulti({'system:time_start': img_date_start})]) d_obj.rs_hourly_coll = ee.ImageCollection([ ee.Image(asset_ws + 'Insol1').setMulti( {'system:time_start': img_hour_start.subtract(3600000)}), ee.Image(asset_ws + 'Insol1').setMulti( {'system:time_start': img_hour_start}), ee.Image(asset_ws + 'Insol1').setMulti( {'system:time_start': img_hour_start.add(3600000)}) ]) d_obj.rs_daily_coll = ee.ImageCollection([ ee.Image(asset_ws + 'Insol24') \ .setMulti({'system:time_start': img_date_start})]) d_obj.et_coll = ee.ImageCollection([ ee.Image(asset_ws + 'alexiET') \ .setMulti({'system:time_start': img_date_start})]) d_obj.et_transform = [0.04, 0, -96.442, 0, -0.04, 41.297] d_obj._set_solar_vars(interpolate_flag=False) d_obj._set_weather_vars() # Get the spatial reference and geoTransform of the assets # asset_crs = ee.Image(asset_ws + 'albedo').projection().crs().getInfo() # asset_transform = ee.Image(asset_ws + 'albedo') \ # .projection().getInfo()['transform'] # Compute ALEXI scale air temperature ta_coarse_img = d_obj.compute_ta_test() # .reproject(crs=asset_crs, crsTransform=asset_transform) # .reproject(crs='EPSG:4326', crsTransform=d_obj.et_transform) # Extract image values at a point using reduceRegion (with point geom) output = utils.image_value(ta_coarse_img.select(['t_air']), tile_scale=4) logging.debug(' Target values: {}'.format(expected['t_air'])) logging.debug(' Output values: {}'.format(output['t_air'])) assert abs(output['t_air'] - expected['t_air']) <= tol
def test_Image_set_alexi_et_vars_assets(xy, et, tol=1E-6): """ Don't use scale parameter in image_value since ALEXI ET assets are already resampled to the Landsat grid. Add separate check that band name is set correctly? """ d_obj = disalexi.Image(test_img) d_obj.et_coll = ee.ImageCollection([ ee.Image(asset_ws + 'alexiET') \ .setMulti({'system:time_start': img_date_start})]) d_obj.et_transform = [0.04, 0, -96.442, 0, -0.04, 41.297] d_obj._set_alexi_et_vars() assert abs( utils.image_value(ee.Image(d_obj.alexi_et), xy=xy)['alexi_et'] - et) <= tol
def test_Image_compute_ta_asset(xy, iterations, expected, tol=0.01): """Test fine scale air temperature at a single point using the test assets""" d_obj = disalexi.Image(test_img, elevation=ee.Image.constant(350.0), iterations=iterations, lc_type='NLCD', landcover=ee.Image(asset_ws + 'landcover')) # Overwrite the default ancillary images with the test assets d_obj.windspeed_coll = ee.ImageCollection([ ee.Image([ ee.Image(asset_ws + 'u'), ee.Image(asset_ws + 'u').multiply(0)]) \ .setMulti({'system:time_start': img_date_start})]) d_obj.rs_hourly_coll = ee.ImageCollection([ ee.Image(asset_ws + 'Insol1').setMulti( {'system:time_start': img_hour_start.subtract(3600000)}), ee.Image(asset_ws + 'Insol1').setMulti( {'system:time_start': img_hour_start}), ee.Image(asset_ws + 'Insol1').setMulti( {'system:time_start': img_hour_start.add(3600000)}) ]) d_obj.rs_daily_coll = ee.ImageCollection([ ee.Image(asset_ws + 'Insol24') \ .setMulti({'system:time_start': img_date_start})]) d_obj.et_coll = ee.ImageCollection([ ee.Image(asset_ws + 'alexiET') \ .setMulti({'system:time_start': img_date_start})]) d_obj.et_transform = [0.04, 0, -96.442, 0, -0.04, 41.297] # Get the spatial reference and geoTransform of the assets asset_crs = ee.Image(asset_ws + 'albedo').projection().crs().getInfo() asset_transform = ee.Image(asset_ws + 'albedo') \ .projection().getInfo()['transform'] # Compute Tair ta_img = d_obj.compute_ta() \ .reproject(crs=asset_crs, crsTransform=asset_transform) # Extract image values at a point using reduceRegion (with point geom) output = list(utils.image_value(ta_img, xy=xy).values())[0] # output = utils.image_value(ta_img)['t_air'] logging.debug(' Target values: {}'.format(expected)) logging.debug(' Output values: {}'.format(output)) assert abs(output - expected) <= tol
def test_sunrise_sunset_image(timestamp, xy, expected, tol=1E-10): """Check that the sunset_sunrise function works for real images""" output_images = tseb_utils.sunrise_sunset( date=ee.Date(timestamp), # date=ee.Date(datetime.datetime.utcfromtimestamp(timestamp / 1000)), lon=ee.Image.pixelLonLat().select(['longitude' ]).multiply(math.pi / 180), lat=ee.Image.pixelLonLat().select(['latitude' ]).multiply(math.pi / 180)) output = utils.image_value(ee.Image(output_images).rename( ['t_rise', 't_end']), xy=xy) for k in expected.keys(): logging.debug('\n {}'.format(k)) logging.debug(' Target values: {:.12f}'.format(expected[k])) logging.debug(' Output values: {:.12f}'.format(output[k])) assert abs(output[k] - expected[k]) <= tol
def test_image_value_scale(lon, lat, expected, tol=0.000001): input = ee.Image('USGS/NED') output = utils.image_value(input, xy=(lon, lat), scale=0.1)['elevation'] assert abs(output - expected) <= tol
def test_Image_set_alexi_et_vars_defaults(xy, et, tol=1E-6): d_obj = disalexi.Image(test_img) d_obj._set_alexi_et_vars() assert abs( utils.image_value(ee.Image(d_obj.alexi_et), xy=xy, scale=0.1) ['alexi_et'] - et) <= tol
def test_Image_set_weather_vars_defaults(tol=0.01): d_obj = disalexi.Image(test_img) d_obj._set_weather_vars() assert abs( utils.image_value(ee.Image(d_obj.windspeed))['windspeed'] - 4.12) <= tol
def test_Landsat_get_bqa_cfmask(bqa, expected): input_img = ee.Image.constant([0.2, 0, 0, 0, 0, 0, 300, int(bqa, 2)]) \ .rename(['B2', 'B3', 'B4', 'B5', 'B6', 'B7', 'B10', 'BQA']) \ .setMulti(l8_properties) cfmask = ee.Image(landsat.Landsat(input_img)._get_bqa_cfmask()) assert utils.image_value(cfmask)['cfmask'] == expected
def test_Landsat_get_lai(red=0.2, nir=0.7, expected=1.200, tol=0.001): input_img = ee.Image.constant([0.2, 0.2, red, nir, 0.2, 0.2, 300, 0]) \ .rename(['B2', 'B3', 'B4', 'B5', 'B6', 'B7', 'B10', 'BQA']) \ .setMulti(l8_properties) lai = ee.Image(landsat.Landsat(input_img)._get_lai()) assert abs(utils.image_value(lai)['lai'] - expected) <= tol