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_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_Image_set_landcover_vars_invalid_lc_type(): """Test that setting an invalid lc_type value raises a KeyError exception""" d_obj = disalexi.Image(test_img, landcover=ee.Image('USGS/NLCD/NLCD2011'), lc_type='DEADBEEF') # print(d_obj._set_landcover_vars()) with pytest.raises(KeyError) as e_info: d_obj._set_landcover_vars()
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_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_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_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_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_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_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_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_init_missing_lc_type(): """Test that only setting a land cover image raises a ValueError exception""" with pytest.raises(ValueError) as e_info: d_obj = disalexi.Image(test_img, landcover=ee.Image('USGS/NLCD/NLCD2011'))
def test_Image_init_missing_landcover(): """Test that only setting a land cover type raises a ValueError exception""" with pytest.raises(ValueError) as e_info: d_obj = disalexi.Image(test_img, lc_type='NLCD')
def test_Image_init_dates(): d_obj = disalexi.Image(test_img) assert d_obj.date.format('yyyy-MM-dd').getInfo() == img_date_str assert d_obj.doy.getInfo() == img_doy assert int(d_obj.hour.getInfo()) == img_hour assert float(d_obj.time.getInfo()) == img_time