diff --git a/openet/ptjpl/image.py b/openet/ptjpl/image.py index 977e0de..90c3ba2 100644 --- a/openet/ptjpl/image.py +++ b/openet/ptjpl/image.py @@ -909,12 +909,12 @@ def from_image_id(cls, image_id, **kwargs): @classmethod def from_landsat_c2_sr(cls, sr_image, cloudmask_args={}, **kwargs): - """Returns a PT-JPL Image instance from a Landsat Collection 2 SR image + """Returns a PT-JPL Image instance from a Landsat C02 level 2 (SR) image Parameters ---------- - sr_image : ee.Image - A raw Landsat Collection 2 SR image. + sr_image : ee.Image, str + A raw Landsat Collection 2 level 2 (SR) image or image ID. cloudmask_args : dict keyword arguments to pass through to cloud mask function kwargs : dict @@ -964,7 +964,9 @@ def from_landsat_c2_sr(cls, sr_image, cloudmask_args={}, **kwargs): if 'cloud_score_flag' not in cloudmask_args.keys(): cloudmask_args['cloud_score_flag'] = True if 'cloud_score_pct' not in cloudmask_args.keys(): - cloudmask_args['cloud_score_pct'] = True + cloudmask_args['cloud_score_pct'] = 100 + if 'filter_flag' not in cloudmask_args.keys(): + cloudmask_args['filter_flag'] = False # QA_RADSAT band will need to be added above if applying saturated masking # if 'saturated_flag' not in cloudmask_args.keys(): # cloudmask_args['saturated_flag'] = False @@ -1011,7 +1013,6 @@ def from_landsat_c2_sr(cls, sr_image, cloudmask_args={}, **kwargs): # Instantiate the class return cls(input_image, **kwargs) - # CGM - Copied from _crop_type() in the SIMS model.py @lazy_property def crop_type(self): """Crop type @@ -1038,6 +1039,10 @@ def crop_type(self): ------ ValueError for unsupported crop_type_sources + Notes + ----- + Copied from _crop_type() in the OpenET SIMS model.py + """ properties = ee.Dictionary() @@ -1072,7 +1077,8 @@ def crop_type(self): crop_type_img = ee.Image(self.crop_type_source).select(['cropland']) properties = properties.set('id', crop_type_img.get('system:id')) elif (type(self.crop_type_source) is str and - 'projects/openet/crop_type' in self.crop_type_source.lower()): + (('projects/openet/crop_type' in self.crop_type_source.lower()) or + ('projects/openet/assets/crop_type' in self.crop_type_source.lower()))): # Use the crop_type image closest to the image date crop_coll = ee.ImageCollection(self.crop_type_source) cdl_year = ( diff --git a/openet/ptjpl/interpolate.py b/openet/ptjpl/interpolate.py index 11ad046..9e03247 100644 --- a/openet/ptjpl/interpolate.py +++ b/openet/ptjpl/interpolate.py @@ -143,14 +143,18 @@ def from_scene_et_fraction( if type(et_reference_source) is str: # Assume a string source is an single image collection ID # not an list of collection IDs or ee.ImageCollection - daily_et_ref_coll = ee.ImageCollection(et_reference_source) \ - .filterDate(start_date, end_date) \ + daily_et_ref_coll = ( + ee.ImageCollection(et_reference_source) + .filterDate(start_date, end_date) .select([et_reference_band], ['et_reference']) + ) # elif isinstance(et_reference_source, computedobject.ComputedObject): # # Interpret computed objects as image collections - # daily_et_reference_coll = et_reference_source \ - # .filterDate(self.start_date, self.end_date) \ + # daily_et_reference_coll = ( + # et_reference_source + # .filterDate(self.start_date, self.end_date) # .select([et_reference_band]) + # ) else: raise ValueError(f'unsupported et_reference_source: {et_reference_source}') @@ -212,7 +216,8 @@ def interpolate_prep(img): if 'count' in variables: aggregate_coll = openet.core.interpolate.aggregate_to_daily( image_coll=scene_coll.select(['mask']), - start_date=start_date, end_date=end_date) + start_date=start_date, end_date=end_date, + ) # The following is needed because the aggregate collection can be # empty if there are no scenes in the target date range but there # are scenes in the interpolation date range. @@ -232,7 +237,7 @@ def interpolate_prep(img): interp_method=interp_method, interp_days=interp_days, use_joins=use_joins, - compute_product=False + compute_product=False, ) # Compute ET from ETf and ETr (if necessary) @@ -506,8 +511,8 @@ def from_scene_et_actual( # logging.debug('et_reference_resample was not set, default to nearest') # # raise ValueError('et_reference_resample was not set') - # Assume a string source is an single image collection ID - # not an list of collection IDs or ee.ImageCollection + # Assume a string source is a single image collection ID + # not a list of collection IDs or ee.ImageCollection daily_et_ref_coll_id = model_args['et_reference_source'] daily_et_ref_coll = ( ee.ImageCollection(daily_et_ref_coll_id) diff --git a/openet/ptjpl/tests/test_a_utils.py b/openet/ptjpl/tests/test_a_utils.py index 8babc6b..6533630 100644 --- a/openet/ptjpl/tests/test_a_utils.py +++ b/openet/ptjpl/tests/test_a_utils.py @@ -47,7 +47,7 @@ def test_point_coll_value(image_id, image_date, xy, scale, expected, tol): def test_c_to_k(c=20, k=293.15, tol=0.000001): output = utils.constant_image_value(utils.c_to_k(ee.Image.constant(c))) - assert abs(output - k) <= tol + assert abs(output['constant'] - k) <= tol @pytest.mark.parametrize( diff --git a/openet/ptjpl/tests/test_b_daily_integration.py b/openet/ptjpl/tests/test_b_daily_integration.py index 325fb76..0ca2cb8 100644 --- a/openet/ptjpl/tests/test_b_daily_integration.py +++ b/openet/ptjpl/tests/test_b_daily_integration.py @@ -40,7 +40,7 @@ def test_day_angle_rad_from_doy_image(rn, hour_of_day, sunrise_hour, sunrise_hour=ee.Image.constant(sunrise_hour), daylight_hours=ee.Image.constant(daylight_hours), )) - assert abs(output - expected) <= tol + assert abs(output['constant'] - expected) <= tol @pytest.mark.parametrize( diff --git a/openet/ptjpl/tests/test_b_daylight_hours.py b/openet/ptjpl/tests/test_b_daylight_hours.py index e44497f..64e5510 100644 --- a/openet/ptjpl/tests/test_b_daylight_hours.py +++ b/openet/ptjpl/tests/test_b_daylight_hours.py @@ -38,7 +38,7 @@ def test_sha_deg_from_doy_lat(doy, latitude, expected, tol=0.000001): ee.Number(doy), ee.Image.constant(latitude) )) # output = utils.getinfo(dh.sha_deg_from_doy_lat(ee.Number(doy), ee.Number(latitude))) - assert abs(output - expected) <= tol + assert abs(output['constant'] - expected) <= tol @pytest.mark.parametrize( diff --git a/openet/ptjpl/tests/test_b_landsat.py b/openet/ptjpl/tests/test_b_landsat.py index 3360290..3574333 100644 --- a/openet/ptjpl/tests/test_b_landsat.py +++ b/openet/ptjpl/tests/test_b_landsat.py @@ -32,6 +32,11 @@ def sr_image(blue=0.2, green=0.2, red=0.2, nir=0.7, swir1=0.2, swir2=0.2, bt=300 # Test the static methods of the class first # Do these need to be inside the TestClass? +def test_Image_ndvi_band_name(): + output = landsat.ndvi(sr_image()).getInfo()['bands'][0]['id'] + assert output == 'ndvi' + + @pytest.mark.parametrize( 'red, nir, expected', [ @@ -49,22 +54,22 @@ def sr_image(blue=0.2, green=0.2, red=0.2, nir=0.7, swir1=0.2, swir2=0.2, bt=300 ) def test_Image_ndvi_calculation(red, nir, expected, tol=0.000001): output = utils.constant_image_value(landsat.ndvi(sr_image(red=red, nir=nir))) - assert abs(output - expected) <= tol + assert abs(output['ndvi'] - expected) <= tol -def test_Image_ndvi_band_name(): - output = landsat.ndvi(sr_image()).getInfo()['bands'][0]['id'] - assert output == 'ndvi' +def test_Image_ndwi_band_name(): + output = landsat.ndwi(sr_image()).getInfo()['bands'][0]['id'] + assert output == 'ndwi' def test_Image_ndwi_calculation(green=0.2, nir=0.2, expected=0, tol=0.000001): output = utils.constant_image_value(landsat.ndwi(sr_image(green=green, nir=nir))) - assert abs(output - expected) <= tol + assert abs(output['ndwi'] - expected) <= tol -def test_Image_ndwi_band_name(): - output = landsat.ndwi(sr_image()).getInfo()['bands'][0]['id'] - assert output == 'ndwi' +def test_Image_mndwi_band_name(): + output = landsat.mndwi(sr_image()).getInfo()['bands'][0]['id'] + assert output == 'mndwi' @pytest.mark.parametrize( @@ -76,12 +81,12 @@ def test_Image_ndwi_band_name(): ) def test_Image_mndwi_calculation(green, swir2, expected, tol=0.000001): output = utils.constant_image_value(landsat.mndwi(sr_image(green=green, swir2=swir2))) - assert abs(output - expected) <= tol + assert abs(output['mndwi'] - expected) <= tol -def test_Image_mndwi_band_name(): - output = landsat.mndwi(sr_image()).getInfo()['bands'][0]['id'] - assert output == 'mndwi' +def test_Image_wri_band_name(): + output = landsat.wri(sr_image()).getInfo()['bands'][0]['id'] + assert output == 'wri' @pytest.mark.parametrize( @@ -95,12 +100,12 @@ def test_Image_wri_calculation(green, red, nir, swir2, expected, tol=0.000001): output = utils.constant_image_value(landsat.wri( sr_image(green=green, red=red, nir=nir, swir2=swir2) )) - assert abs(output - expected) <= tol + assert abs(output['wri'] - expected) <= tol -def test_Image_wri_band_name(): - output = landsat.wri(sr_image()).getInfo()['bands'][0]['id'] - assert output == 'wri' +def test_Image_emissivity_ptjpl_band_name(): + output = landsat.emissivity_ptjpl(sr_image()).getInfo()['bands'][0]['id'] + assert output == 'emissivity' @pytest.mark.parametrize( @@ -121,11 +126,11 @@ def test_Image_wri_band_name(): ) def test_Image_emissivity_ptjpl_calculation(red, nir, expected, tol=0.000001): output = utils.constant_image_value(landsat.emissivity_ptjpl(sr_image(red=red, nir=nir))) - assert abs(output - expected) <= tol + assert abs(output['emissivity'] - expected) <= tol -def test_Image_emissivity_disalexi_band_name(): - output = landsat.emissivity_ptjpl(sr_image()).getInfo()['bands'][0]['id'] +def test_Image_emissivity_metric_band_name(): + output = landsat.emissivity_metric(sr_image()).getInfo()['bands'][0]['id'] assert output == 'emissivity' @@ -146,12 +151,12 @@ def test_Image_emissivity_disalexi_band_name(): ) def test_Image_emissivity_metric_calculation(red, nir, expected, tol=0.000001): output = utils.constant_image_value(landsat.emissivity_metric(sr_image(red=red, nir=nir))) - assert abs(output - expected) <= tol + assert abs(output['emissivity'] - expected) <= tol -def test_Image_emissivity_metric_band_name(): - output = landsat.emissivity_metric(sr_image()).getInfo()['bands'][0]['id'] - assert output == 'emissivity' +def test_Image_lst_band_name(): + output = landsat.lst(sr_image()).getInfo()['bands'][0]['id'] + assert output == 'lst' @pytest.mark.parametrize( @@ -163,12 +168,12 @@ def test_Image_emissivity_metric_band_name(): ) def test_Image_lst_calculation(red, nir, bt, expected, tol=0.000001): output = utils.constant_image_value(landsat.lst(sr_image(red=red, nir=nir, bt=bt))) - assert abs(output - expected) <= tol + assert abs(output['lst'] - expected) <= tol -def test_Image_lst_band_name(): - output = landsat.lst(sr_image()).getInfo()['bands'][0]['id'] - assert output == 'lst' +def test_Image_albedo_band_name(): + output = landsat.albedo_metric(sr_image()).getInfo()['bands'][0]['id'] + assert output == 'albedo' @pytest.mark.parametrize( @@ -181,9 +186,4 @@ def test_Image_albedo_calculation(blue, green, red, nir, swir1, swir2, expected, output = utils.constant_image_value(landsat.albedo_metric( sr_image(blue=blue, green=green, red=red, nir=nir, swir1=swir1, swir2=swir2) )) - assert abs(output - expected) <= tol - - -def test_Image_albedo_band_name(): - output = landsat.albedo_metric(sr_image()).getInfo()['bands'][0]['id'] - assert output == 'albedo' + assert abs(output['albedo'] - expected) <= tol diff --git a/openet/ptjpl/tests/test_b_meteorology.py b/openet/ptjpl/tests/test_b_meteorology.py index 4358e81..9396886 100644 --- a/openet/ptjpl/tests/test_b_meteorology.py +++ b/openet/ptjpl/tests/test_b_meteorology.py @@ -68,8 +68,8 @@ def test_pascal_to_kilopascal(P_Pa, expected, tol=0.000001): def test_meteorology_svp(Ta_C, Ea_kPa, expected, tol=0.000001): # CGM - This test uses images due to .updateMask() call in meteorology SVP, VPD, RH = meteorology.meteorology(ee.Image.constant(Ta_C), ee.Image.constant(Ea_kPa)) - output = utils.constant_image_value(SVP) - assert abs(output - expected) <= tol + output = utils.constant_image_value(SVP.rename(['svp'])) + assert abs(output['svp'] - expected) <= tol @pytest.mark.parametrize( @@ -82,11 +82,11 @@ def test_meteorology_svp(Ta_C, Ea_kPa, expected, tol=0.000001): def test_meteorology_vpd(Ta_C, Ea_kPa, expected, tol=0.000001): # CGM - This test uses images due to .updateMask() call in meteorology SVP, VPD, RH = meteorology.meteorology(ee.Image.constant(Ta_C), ee.Image.constant(Ea_kPa)) - output = utils.constant_image_value(VPD) - if expected is None and output is None: + output = utils.constant_image_value(VPD.rename(['vpd'])) + if expected is None and output['vpd'] is None: assert True else: - assert abs(output - expected) <= tol + assert abs(output['vpd'] - expected) <= tol @pytest.mark.parametrize( @@ -99,8 +99,8 @@ def test_meteorology_vpd(Ta_C, Ea_kPa, expected, tol=0.000001): def test_meteorology_rh(Ta_C, Ea_kPa, expected, tol=0.000001): # CGM - This test uses images due to .updateMask() call in meteorology SVP, VPD, RH = meteorology.meteorology(ee.Image.constant(Ta_C), ee.Image.constant(Ea_kPa)) - output = utils.constant_image_value(RH) - assert abs(output - expected) <= tol + output = utils.constant_image_value(RH.rename(['rh'])) + assert abs(output['rh'] - expected) <= tol @pytest.mark.parametrize( diff --git a/openet/ptjpl/tests/test_b_vegetation.py b/openet/ptjpl/tests/test_b_vegetation.py index 7003b42..5f7f653 100644 --- a/openet/ptjpl/tests/test_b_vegetation.py +++ b/openet/ptjpl/tests/test_b_vegetation.py @@ -7,7 +7,7 @@ def test_savi_from_ndvi(ndvi=0.5, expected=0.5 * 0.45 + 0.132, tol=0.000001): output = utils.constant_image_value(vegetation.savi_from_ndvi(ee.Image.constant(ndvi))) - assert abs(output - expected) <= tol + assert abs(output['constant'] - expected) <= tol @pytest.mark.parametrize( @@ -20,14 +20,14 @@ def test_savi_from_ndvi(ndvi=0.5, expected=0.5 * 0.45 + 0.132, tol=0.000001): ) def test_fAPAR_from_savi(savi, expected, tol=0.000001): output = utils.constant_image_value(vegetation.fAPAR_from_savi(ee.Image.constant(savi))) - assert abs(output - expected) <= tol + assert abs(output['constant'] - expected) <= tol @pytest.mark.parametrize( 'ndvi, expected', [[0.5, (0.45 * 0.5 + 0.132) * 1.3632 - 0.048]]) def test_fAPAR_from_ndvi(ndvi, expected, tol=0.000001): output = utils.constant_image_value(vegetation.fAPAR_from_ndvi(ee.Image.constant(ndvi))) - assert abs(output - expected) <= tol + assert abs(output['constant'] - expected) <= tol @pytest.mark.parametrize( @@ -40,4 +40,4 @@ def test_fAPAR_from_ndvi(ndvi, expected, tol=0.000001): ) def test_fIPAR_from_ndvi(ndvi, expected, tol=0.000001): output = utils.constant_image_value(vegetation.fIPAR_from_ndvi(ee.Image.constant(ndvi))) - assert abs(output - expected) <= tol + assert abs(output['constant'] - expected) <= tol diff --git a/openet/ptjpl/tests/test_c_ptjpl.py b/openet/ptjpl/tests/test_c_ptjpl.py index 30bc49c..6813eda 100644 --- a/openet/ptjpl/tests/test_c_ptjpl.py +++ b/openet/ptjpl/tests/test_c_ptjpl.py @@ -34,9 +34,9 @@ def test_Model_Rns_calculation(Rn, LAI, water_mask, expected, tol=0.001): water_mask=ee.Image.constant(water_mask) )) if expected is None: - assert output is None + assert output['constant'] is None else: - assert abs(output - expected) <= tol + assert abs(output['constant'] - expected) <= tol # @pytest.mark.parametrize( @@ -53,7 +53,7 @@ def test_Model_Rns_calculation(Rn, LAI, water_mask, expected, tol=0.001): # Rn=ee.Image.constant(Rn), fIPAR=ee.Image.constant(fIPAR), # Rns=ee.Image.constant(Rns), W=ee.Image.constant(W), # water_mask=ee.Image.constant(water_mask))) -# assert abs(output - expected) <= tol +# assert abs(output['constant'] - expected) <= tol # @pytest.mark.parametrize( @@ -83,5 +83,5 @@ def test_Model_Rns_calculation(Rn, LAI, water_mask, expected, tol=0.001): # ) # output = utils.constant_image_value(output_image) # logging.debug(f'\n Target values: {expected}') -# logging.debug(f' Output values: {output}') -# assert abs(output - expected) <= tol +# logging.debug(f' Output values: {output['constant']}') +# assert abs(output['constant'] - expected) <= tol diff --git a/openet/ptjpl/tests/test_d_image.py b/openet/ptjpl/tests/test_d_image.py index e03bcea..fad91aa 100644 --- a/openet/ptjpl/tests/test_d_image.py +++ b/openet/ptjpl/tests/test_d_image.py @@ -241,7 +241,7 @@ def test_Image_nldas_interpolate(band, time, interp_flag, xy, expected, tol=0.00 output = utils.point_image_value( ptjpl.Image.nldas_interpolate(band, ee.Date(time), interp_flag), xy ) - assert abs(output - expected) <= tol + assert abs(output[band] - expected) <= tol @pytest.mark.parametrize( @@ -260,7 +260,7 @@ def test_Image_ea_sources(ea_source, xy, expected, tol=0.01): # m._start_date = ee.Date(start_date) # m._end_date = m._start_date.advance(1, 'day') output = utils.point_image_value(ee.Image(m.ea), xy) - assert abs(output - expected) <= tol + assert abs(output['ea'] - expected) <= tol def test_Image_ea_sources_exception(): @@ -284,7 +284,7 @@ def test_Image_LWin_sources(LWin_source, xy, expected, tol=0.01): # m._start_date = ee.Date(start_date) # m._end_date = m._start_date.advance(1, 'day') output = utils.point_image_value(ee.Image(m.LWin), xy) - assert abs(output - expected) <= tol + assert abs(output['LWin'] - expected) <= tol def test_Image_LWin_sources_exception(): @@ -308,7 +308,7 @@ def test_Image_rs_sources(rs_source, xy, expected, tol=0.0001): # m._start_date = ee.Date(start_date) # m._end_date = m._start_date.advance(1, 'day') output = utils.point_image_value(ee.Image(m.rs), xy) - assert abs(output - expected) <= tol + assert abs(output['rs'] - expected) <= tol def test_Image_rs_sources_exception(): @@ -332,7 +332,7 @@ def test_Image_ta_sources(ta_source, xy, expected, tol=0.0001): # m._start_date = ee.Date(start_date) # m._end_date = m._start_date.advance(1, 'day') output = utils.point_image_value(ee.Image(m.ta), xy) - assert abs(output - expected) <= tol + assert abs(output['Ta'] - expected) <= tol def test_Image_ta_sources_exception(): @@ -356,7 +356,7 @@ def test_Image_windspeed_sources(windspeed_source, xy, expected, tol=0.0001): # m._start_date = ee.Date(start_date) # m._end_date = m._start_date.advance(1, 'day') output = utils.point_image_value(ee.Image(m.U), xy) - assert abs(output - expected) <= tol + assert abs(output['U'] - expected) <= tol def test_Image_windspeed_sources_exception(): @@ -385,13 +385,13 @@ def test_Image_topt_sources(topt_source, xy, expected, tol=0.001): # m._start_date = ee.Date(start_date) # m._end_date = m._start_date.advance(1, 'day') output = utils.point_image_value(ee.Image(m.Topt), xy) - assert abs(output - expected) <= tol + assert abs(output['Topt'] - expected) <= tol def test_Image_topt_floor(topt_source=15, ta_source=40, tol=0.001): m = default_image_obj(topt_source=topt_source, ta_source=ta_source+273.15, floor_Topt=True) output = utils.point_image_value(ee.Image(m.Topt), TEST_POINT) - assert abs(output - ta_source) <= tol + assert abs(output['Topt'] - ta_source) <= tol def test_Image_topt_sources_exception(): @@ -420,7 +420,7 @@ def test_Image_faparmax_sources(faparmax_source, xy, expected, tol=0.0001): # m._start_date = ee.Date(start_date) # m._end_date = m._start_date.advance(1, 'day') output = utils.point_image_value(ee.Image(m.fAPARmax), xy) - assert abs(output - expected) <= tol + assert abs(output['fAPARmax'] - expected) <= tol def test_Image_faparmax_sources_exception(): @@ -440,22 +440,23 @@ def test_Image_SWin_properties(): def test_Image_SWin_value(): """Test that a non-zero value is returned for the default inputs""" - assert utils.constant_image_value(default_image_obj().SWin) > 0 + output = utils.constant_image_value(ee.Image(default_image_obj().SWin)) + assert output['SWin'] > 0 def test_Image_LE_defaults(expected=517.674, tol=0.001): output = utils.constant_image_value(ee.Image(default_image_obj().LE)) - assert abs(output - expected) <= tol + assert abs(output['LE'] - expected) <= tol def test_Image_PET_defaults(expected=718.188, tol=0.001): output = utils.constant_image_value(ee.Image(default_image_obj().PET)) - assert abs(output - expected) <= tol + assert abs(output['PET'] - expected) <= tol def test_Image_ESI_defaults(expected=0.721, tol=0.001): output = utils.constant_image_value(ee.Image(default_image_obj().ESI)) - assert abs(output - expected) <= tol + assert abs(output['ESI'] - expected) <= tol def test_Image_et_properties(): @@ -469,7 +470,7 @@ def test_Image_et_properties(): def test_Image_et_defaults(expected=6.128, tol=0.001): output = utils.constant_image_value(ee.Image(default_image_obj().et)) - assert abs(output - expected) <= tol + assert abs(output['et'] - expected) <= tol # CGM - Test if there are any conditions that should return nodata @@ -480,10 +481,9 @@ def test_Image_et_defaults(expected=6.128, tol=0.001): # ] # ) # def test_Image_et_nodata(albedo, emissivity, lst, ndvi, expected): -# output_img = default_image_obj(albedo=albedo, emissivity=emissivity, -# lst=lst, ndvi=ndvi) +# output_img = default_image_obj(albedo=albedo, emissivity=emissivity, lst=lst, ndvi=ndvi) # output = utils.constant_image_value(ee.Image(output_img.et)) -# assert output is None +# assert output['et'] is None def test_Image_et_reference_properties(): @@ -500,8 +500,12 @@ def test_Image_et_reference_properties(): [ ['IDAHO_EPSCOR/GRIDMET', 'etr', 1, TEST_POINT, 12.9], ['IDAHO_EPSCOR/GRIDMET', 'etr', 0.85, TEST_POINT, 12.9 * 0.85], - ['projects/earthengine-legacy/assets/projects/climate-engine/cimis/daily', - 'ETr_ASCE', 1, TEST_POINT, 11.7839], + ['projects/openet/assets/reference_et/california/cimis/daily/v1', + 'etr', 1, TEST_POINT, 11.7893], + ['projects/openet/reference_et/california/cimis/daily/v1', + 'etr', 1, TEST_POINT, 11.7893], + ['projects/earthengine-legacy/assets/projects/openet/reference_et/california/cimis/daily/v1', + 'etr', 1, TEST_POINT, 11.7893], [10, 'FOO', 1, TEST_POINT, 10.0], [10, 'FOO', 0.85, TEST_POINT, 8.5], ] @@ -511,14 +515,14 @@ def test_Image_et_reference_sources(source, band, factor, xy, expected, tol=0.00 output = utils.point_image_value(default_image_obj( et_reference_source=source, et_reference_band=band, et_reference_factor=factor).et_reference, xy) - assert abs(output - expected) <= tol + assert abs(output['et_reference'] - expected) <= tol # # DEADBEEF - Current implementation does not use etr_source for computing etr # def test_Image_etr_values(etr_source=15, etr_factor=0.85, tol=0.0001): # output = utils.constant_image_value(default_image_obj( # etr_source=etr_source, etr_factor=etr_factor).etr) -# assert abs(output - etr_source * etr_factor) <= tol +# assert abs(output['constant'] - etr_source * etr_factor) <= tol def test_Image_et_fraction_properties(): @@ -531,17 +535,15 @@ def test_Image_et_fraction_properties(): # def test_Image_et_fraction_defaults(expected=0.721, tol=0.001): -# output = utils.constant_image_value( -# ee.Image(default_image_obj().et_fraction)) -# assert abs(output - expected) <= tol +# output = utils.constant_image_value(ee.Image(default_image_obj().et_fraction)) +# assert abs(output['et_fraction'] - expected) <= tol # # DEADBEEF - Current implementation does not use etr_source for computing etr -# def test_Image_etf_values(etr_source=15, etr_factor=0.85, expected=13.335, -# tol=0.0001): +# def test_Image_etf_values(etr_source=15, etr_factor=0.85, expected=13.335, tol=0.0001): # output = utils.constant_image_value(default_image_obj( # etr_source=etr_source, etr_factor=etr_factor).etf) -# assert abs(output - expected / (etr_source * etr_factor)) <= tol +# assert abs(output['etf'] - expected / (etr_source * etr_factor)) <= tol # CGM - Can't check mask, time, and calculate() until ET is working @@ -555,7 +557,7 @@ def test_Image_mask_properties(): def test_Image_mask_values(): - assert utils.constant_image_value(default_image_obj().mask) == 1 + assert utils.constant_image_value(default_image_obj().mask)['mask'] == 1 def test_Image_time_properties(): @@ -570,7 +572,7 @@ def test_Image_time_properties(): def test_Image_time_values(): """The time band should have the 0 UTC time in it for interpolation""" assert utils.constant_image_value( - default_image_obj().time) == utils.millis(SCENE_0UTC_DT) + default_image_obj().time)['time'] == utils.millis(SCENE_0UTC_DT) def test_Image_calculate_properties(): @@ -602,9 +604,9 @@ def test_Image_calculate_values(): """Test if the calculate method returns values""" output_img = default_image_obj().calculate(['et']) # output_img = default_image_obj().calculate(['et', 'et_reference', 'et_fraction']) - assert utils.constant_image_value(output_img.select(['et'])) > 0 - # assert utils.constant_image_value(output_img.select(['et_reference'])) > 0 - # assert utils.constant_image_value(output_img.select(['et_fraction'])) > 0 + assert utils.constant_image_value(output_img.select(['et']))['et'] > 0 + # assert utils.constant_image_value(output_img.select(['et_reference']))['et_reference'] > 0 + # assert utils.constant_image_value(output_img.select(['et_fraction']))['et_fraction'] > 0 def test_Image_calculate_variables_valueerror(): @@ -617,6 +619,7 @@ def test_Image_from_landsat_c2_sr_default_image(): """Test that the classmethod is returning a class object""" output = ptjpl.Image.from_landsat_c2_sr( ee.Image('LANDSAT/LC08/C02/T1_L2/LC08_038031_20130828') + # 'LANDSAT/LC08/C02/T1_L2/LC08_038031_20130828' ) assert type(output) == type(default_image_obj()) @@ -624,8 +627,8 @@ def test_Image_from_landsat_c2_sr_default_image(): @pytest.mark.parametrize( 'image_id', [ - # 'LANDSAT/LT04/C02/T1_L2/LT04_044033_19830812', - # 'LANDSAT/LT05/C02/T1_L2/LT05_044033_20110716', + 'LANDSAT/LT04/C02/T1_L2/LT04_044033_19830812', + 'LANDSAT/LT05/C02/T1_L2/LT05_044033_20110716', 'LANDSAT/LE07/C02/T1_L2/LE07_044033_20170708', 'LANDSAT/LC08/C02/T1_L2/LC08_044033_20170716', 'LANDSAT/LC09/C02/T1_L2/LC09_044033_20220127', @@ -640,7 +643,8 @@ def test_Image_from_landsat_c2_sr_landsat_image(image_id): def test_Image_from_landsat_c2_sr_exception(): """Test instantiating the class for an invalid image ID""" with pytest.raises(Exception): - utils.getinfo(ptjpl.Image.from_landsat_c2_sr(ee.Image('DEADBEEF'))._index) + # Intentionally using .getInfo() since utils.getinfo() might catch the exception + ptjpl.Image.from_landsat_c2_sr(ee.Image('FOO')).ndvi.getInfo() def test_Image_from_landsat_c2_sr_scaling(): @@ -655,44 +659,55 @@ def test_Image_from_landsat_c2_sr_scaling(): 'system:time_start': ee.Number(sr_img.get('system:time_start'))}) ) - output = utils.constant_image_value(ptjpl.Image.from_landsat_c2_sr(input_img).albedo) - assert abs(output - 0.1) <= 0.01 + # LST correction and cloud score masking do not work with a constant image + # and must be explicitly set to False + output = utils.constant_image_value(ptjpl.Image.from_landsat_c2_sr( + input_img, c2_lst_correct=False, + cloudmask_args={'cloud_score_flag': False, 'filter_flag': False}).albedo) + assert abs(output['albedo'] - 0.1) <= 0.01 - output = utils.constant_image_value(ptjpl.Image.from_landsat_c2_sr(input_img).LST) - assert abs(output - 300) <= 0.1 + output = utils.constant_image_value(ptjpl.Image.from_landsat_c2_sr( + input_img, c2_lst_correct=False, + cloudmask_args={'cloud_score_flag': False, 'filter_flag': False}).LST) + assert abs(output['lst'] - 300) <= 0.1 def test_Image_from_landsat_c2_sr_cloud_mask_args(): """Test if the cloud_mask_args parameter can be set (not if it works)""" - image_id = 'LANDSAT/LC08/C02/T1_L2/LC08_044033_20170716' output = ptjpl.Image.from_landsat_c2_sr( - image_id, cloudmask_args={'snow_flag': True, 'cirrus_flag': True} + 'LANDSAT/LC08/C02/T1_L2/LC08_044033_20170716', + cloudmask_args={'snow_flag': True, 'cirrus_flag': True} ) assert type(output) == type(default_image_obj()) +def test_Image_from_landsat_c2_sr_cloud_score_mask_arg(): + """Test if the cloud_score_flag parameter can be set in cloudmask_args""" + output = ptjpl.Image.from_landsat_c2_sr( + 'LANDSAT/LC08/C02/T1_L2/LC08_044033_20170716', + cloudmask_args={'cloud_score_flag': True, 'cloud_score_pct': 50}) + assert type(output) == type(default_image_obj()) + + def test_Image_from_landsat_c2_sr_c2_lst_correct_arg(): """Test if the c2_lst_correct parameter can be set (not if it works)""" - image_id = 'LANDSAT/LC08/C02/T1_L2/LC08_031034_20160702' - output = ptjpl.Image.from_landsat_c2_sr(image_id, c2_lst_correct=True) + output = ptjpl.Image.from_landsat_c2_sr( + 'LANDSAT/LC08/C02/T1_L2/LC08_031034_20160702', c2_lst_correct=True) assert type(output) == type(default_image_obj()) def test_Image_from_landsat_c2_sr_c2_lst_correct_fill(): """Test if the c2_lst_correct fills the LST holes in Nebraska""" image_id = 'LANDSAT/LC08/C02/T1_L2/LC08_031034_20160702' - point_xy = [-102.08284, 37.81728] + xy = [-102.08284, 37.81728] + # CGM - Is the uncorrected test needed? uncorrected = utils.point_image_value( - ptjpl.Image.from_landsat_c2_sr(image_id, c2_lst_correct=False).LST, - point_xy) - assert uncorrected is None - # assert uncorrected['lst'] is None + ptjpl.Image.from_landsat_c2_sr(image_id, c2_lst_correct=False).LST, xy) + assert uncorrected['lst'] is None corrected = utils.point_image_value( - ptjpl.Image.from_landsat_c2_sr(image_id, c2_lst_correct=True).LST, - point_xy) - assert corrected > 0 - # assert corrected['lst'] > 0 + ptjpl.Image.from_landsat_c2_sr(image_id, c2_lst_correct=True).LST, xy) + assert corrected['lst'] > 0 # # Exact test values copied from openet-core # assert abs(corrected['lst'] - 306.83) <= 0.25 @@ -722,12 +737,13 @@ def test_Image_from_method_kwargs(): # CGM - Copied from SIMS test_b_model.py def test_Model_crop_type_source_exception(): with pytest.raises(ValueError): - utils.getinfo(default_image_obj(crop_type_source='FOO').crop_type) + # Intentionally using .getInfo() since utils.getinfo() might catch the exception + default_image_obj(crop_type_source='FOO').crop_type.getInfo() def test_Model_crop_type_constant_value(): output = utils.constant_image_value(default_image_obj(crop_type_source=10).crop_type) - assert output == 10 + assert output['crop_type'] == 10 @pytest.mark.parametrize( @@ -758,19 +774,17 @@ def test_Model_crop_type_source_cdl_image(): def test_Model_crop_type_source_cdl_image_exception(): """Requesting a CDL image that doesn't exist should raise an EE exception""" with pytest.raises(Exception): - utils.getinfo(default_image_obj(crop_type_source='USDA/NASS/CDL/2099')) - # CGM - The exception is raised in the _crop_type() method which is - # in the init. If crop_type is a lazy property then it is necessary - # to request the property in order to raise the exception. - # utils.getinfo(default_model_obj( - # crop_type_source='USDA/NASS/CDL/2099').crop_type) + # Intentionally using .getInfo() since utils.getinfo() might catch the exception + default_image_obj(crop_type_source='USDA/NASS/CDL/2099').crop_type.getInfo() @pytest.mark.parametrize( 'crop_type_source', [ - 'projects/openet/crop_type/v2021a', - 'projects/earthengine-legacy/assets/projects/openet/crop_type/v2021a', + 'projects/openet/assets/crop_type/v2023a', + 'projects/openet/assets/crop_type/v2021a', + # 'projects/openet/crop_type/v2021a', + # 'projects/earthengine-legacy/assets/projects/openet/crop_type/v2021a', ] ) def test_Model_crop_type_source_openet_crop_type(crop_type_source): @@ -784,15 +798,17 @@ def test_Model_crop_type_source_openet_crop_type(crop_type_source): [ ['USDA/NASS/CDL', TEST_POINT, 36], ['USDA/NASS/CDL/2016', TEST_POINT, 36], - ['projects/openet/crop_type/v2021a', TEST_POINT, 47], - ['projects/earthengine-legacy/assets/projects/openet/crop_type/v2021a', TEST_POINT, 47], + ['projects/openet/assets/crop_type/v2023a', TEST_POINT, 47], + ['projects/openet/assets/crop_type/v2021a', TEST_POINT, 47], + # ['projects/openet/crop_type/v2021a', TEST_POINT, 47], + # ['projects/earthengine-legacy/assets/projects/openet/crop_type/v2021a', TEST_POINT, 47], ] ) def test_Model_crop_type_values(crop_type_source, xy, expected): output = utils.point_image_value( default_image_obj(crop_type_source=crop_type_source).crop_type, xy ) - assert output == expected + assert output['crop_type'] == expected @pytest.mark.parametrize( @@ -809,7 +825,7 @@ def test_Model_crop_mask_constant_value(crop_type_source, expected): output = utils.constant_image_value( default_image_obj(crop_type_source=crop_type_source).crop_mask ) - assert output == expected + assert output['crop_mask'] == expected def test_Model_crop_pm_adjust_source_exception(): @@ -821,28 +837,29 @@ def test_Model_crop_pm_adjust_constant_value(): output = utils.constant_image_value( default_image_obj(crop_pm_adjust_source=2, crop_type_source=36).crop_pm_adjust ) - assert output == 2 + assert output['crop_pm_adjust'] == 2 @pytest.mark.parametrize( 'crop_pm_adjust_source, xy, expected', [ - ['projects/openet/ptjpl/ancillary/alpha/gridmet_1980-2020_dgs', + ['projects/openet/assets/ptjpl/ancillary/alpha/gridmet_1980-2020_dgs', TEST_POINT, 1.3024652077503645], + # ['projects/openet/ptjpl/ancillary/alpha/gridmet_1980-2020_dgs', + # TEST_POINT, 1.3024652077503645], ] ) def test_Model_crop_pm_adjust_values(crop_pm_adjust_source, xy, expected, tol=0.001): output = utils.point_image_value( default_image_obj(crop_pm_adjust_source=crop_pm_adjust_source).crop_pm_adjust, xy ) - assert abs(output - expected) <= tol + assert abs(output['crop_pm_adjust'] - expected) <= tol # def test_Model_crop_pm_adjust_band(): # output = utils.constant_image_value(default_image_obj( -# crop_pm_adjust_source=2, -# crop_type_source=36).crop_pm_adjust) -# assert output == 2 +# crop_pm_adjust_source=2, crop_type_source=36).crop_pm_adjust) +# assert output['crop_pm_adjust'] == 2 @pytest.mark.parametrize( @@ -850,10 +867,14 @@ def test_Model_crop_pm_adjust_values(crop_pm_adjust_source, xy, expected, tol=0. [ [True, 2, TEST_POINT, 2 * 6.128485756837151], [False, 2, TEST_POINT, 6.128485756837151], - [True, 'projects/openet/ptjpl/ancillary/alpha/gridmet_1980-2020_dgs', + [True, 'projects/openet/assets/ptjpl/ancillary/alpha/gridmet_1980-2020_dgs', TEST_POINT, 6.128485756837151 * 1.302], - [False, 'projects/openet/ptjpl/ancillary/alpha/gridmet_1980-2020_dgs', + [False, 'projects/openet/assets/ptjpl/ancillary/alpha/gridmet_1980-2020_dgs', TEST_POINT, 6.128485756837151], + # [True, 'projects/openet/ptjpl/ancillary/alpha/gridmet_1980-2020_dgs', + # TEST_POINT, 6.128485756837151 * 1.302], + # [False, 'projects/openet/ptjpl/ancillary/alpha/gridmet_1980-2020_dgs', + # TEST_POINT, 6.128485756837151], ] ) def test_Model_et_crop_pm_adjust_flag(crop_pm_adjust_flag, crop_pm_adjust_source, @@ -861,4 +882,4 @@ def test_Model_et_crop_pm_adjust_flag(crop_pm_adjust_flag, crop_pm_adjust_source output = utils.point_image_value(default_image_obj( crop_pm_adjust_flag=crop_pm_adjust_flag, crop_pm_adjust_source=crop_pm_adjust_source).et, xy) - assert abs(output - expected) <= tol + assert abs(output['et'] - expected) <= tol diff --git a/openet/ptjpl/tests/test_e_collection.py b/openet/ptjpl/tests/test_e_collection.py index 0b366cb..d3b2a2c 100644 --- a/openet/ptjpl/tests/test_e_collection.py +++ b/openet/ptjpl/tests/test_e_collection.py @@ -31,7 +31,9 @@ 'et_reference_source': 'IDAHO_EPSCOR/GRIDMET', 'et_reference_band': 'eto', 'et_reference_factor': 0.85, - 'et_reference_resample': 'nearest'}, + 'et_reference_resample': 'nearest', + 'cloudmask_args': {'cloud_score_flag': False, 'filter_flag': False}, + }, 'filter_args': {}, # 'interp_args': {}, } @@ -65,7 +67,7 @@ def test_Collection_init_default_parameters(): m = ptjpl.Collection(**args) assert m.variables is None assert m.cloud_cover_max == 70 - assert m.model_args == {} + # assert m.model_args == {} assert m.filter_args == {} # assert m.interp_args == {} diff --git a/openet/ptjpl/tests/test_e_interpolate.py b/openet/ptjpl/tests/test_e_interpolate.py index 76f6d5d..afef6b7 100644 --- a/openet/ptjpl/tests/test_e_interpolate.py +++ b/openet/ptjpl/tests/test_e_interpolate.py @@ -23,8 +23,10 @@ def scene_coll(variables, et_fraction=0.4, et=5, ndvi=0.6): ee.ImageCollection """ - img = ee.Image('LANDSAT/LC08/C02/T1_L2/LC08_044033_20170716') \ + img = ( + ee.Image('LANDSAT/LC08/C02/T1_L2/LC08_044033_20170716') .select(['SR_B3']).double().multiply(0) + ) mask = img.add(1).updateMask(1).uint8() time1 = ee.Number(ee.Date.fromYMD(2017, 7, 8).millis()) @@ -33,8 +35,10 @@ def scene_coll(variables, et_fraction=0.4, et=5, ndvi=0.6): # Mask and time bands currently get added on to the scene collection # and images are unscaled just before interpolating in the export tool - scene_img = ee.Image([img.add(et_fraction), img.add(et), img.add(ndvi), mask])\ + scene_img = ( + ee.Image([img.add(et_fraction), img.add(et), img.add(ndvi), mask]) .rename(['et_fraction', 'et', 'ndvi', 'mask']) + ) scene_coll = ee.ImageCollection([ scene_img.addBands([img.add(time1).rename('time')]) \ .set({'system:index': 'LE07_044033_20170708', @@ -65,7 +69,7 @@ def test_from_scene_et_fraction_daily_values(tol=0.0001): t_interval='daily') TEST_POINT = (-121.5265, 38.7399) - output = utils.point_coll_value(output_coll, TEST_POINT, scale=10) + output = utils.point_coll_value(output_coll, TEST_POINT, scale=30) assert abs(output['ndvi']['2017-07-10'] - 0.6) <= tol assert abs(output['et_fraction']['2017-07-10'] - 0.4) <= tol assert abs(output['et_reference']['2017-07-10'] - 8.0) <= tol @@ -89,7 +93,7 @@ def test_from_scene_et_fraction_monthly_values(tol=0.0001): t_interval='monthly') TEST_POINT = (-121.5265, 38.7399) - output = utils.point_coll_value(output_coll, TEST_POINT, scale=10) + output = utils.point_coll_value(output_coll, TEST_POINT, scale=30) assert abs(output['ndvi']['2017-07-01'] - 0.6) <= tol assert abs(output['et_fraction']['2017-07-01'] - 0.4) <= tol assert abs(output['et_reference']['2017-07-01'] - 236.5) <= tol @@ -110,7 +114,7 @@ def test_from_scene_et_fraction_custom_values(tol=0.0001): t_interval='custom') TEST_POINT = (-121.5265, 38.7399) - output = utils.point_coll_value(output_coll, TEST_POINT, scale=10) + output = utils.point_coll_value(output_coll, TEST_POINT, scale=30) assert abs(output['ndvi']['2017-07-01'] - 0.6) <= tol assert abs(output['et_fraction']['2017-07-01'] - 0.4) <= tol assert abs(output['et_reference']['2017-07-01'] - 236.5) <= tol @@ -135,7 +139,7 @@ def test_from_scene_et_actual_daily_values(tol=0.0001): t_interval='daily') TEST_POINT = (-121.5265, 38.7399) - output = utils.point_coll_value(output_coll, TEST_POINT, scale=10) + output = utils.point_coll_value(output_coll, TEST_POINT, scale=30) assert abs(output['et_fraction']['2017-07-10'] - 0.5970309972763062) <= tol assert abs(output['et_reference']['2017-07-10'] - 8) <= tol assert abs(output['et']['2017-07-10'] - 4.776247978210449) <= tol @@ -162,7 +166,7 @@ def test_from_scene_et_actual_monthly_values(tol=0.0001): t_interval='monthly') TEST_POINT = (-121.5265, 38.7399) - output = utils.point_coll_value(output_coll, TEST_POINT, scale=10) + output = utils.point_coll_value(output_coll, TEST_POINT, scale=30) assert abs(output['et']['2017-07-01'] - 145.9705047607422) <= tol assert abs(output['et_reference']['2017-07-01'] - 236.5) <= tol assert abs(output['et_fraction']['2017-07-01'] - 145.9705047607422 / 236.5) <= tol @@ -186,7 +190,7 @@ def test_from_scene_et_actual_custom_values(tol=0.0001): t_interval='custom') TEST_POINT = (-121.5265, 38.7399) - output = utils.point_coll_value(output_coll, TEST_POINT, scale=10) + output = utils.point_coll_value(output_coll, TEST_POINT, scale=30) assert abs(output['et']['2017-07-01'] - 145.9705047607422) <= tol assert abs(output['et_reference']['2017-07-01'] - 236.5) <= tol assert abs(output['et_fraction']['2017-07-01'] - 145.9705047607422 / 236.5) <= tol @@ -210,7 +214,7 @@ def test_from_scene_et_actual_monthly_et_reference_factor(tol=0.0001): t_interval='monthly') TEST_POINT = (-121.5265, 38.7399) - output = utils.point_coll_value(output_coll, TEST_POINT, scale=10) + output = utils.point_coll_value(output_coll, TEST_POINT, scale=30) assert abs(output['et']['2017-07-01'] - 145.9705047607422) <= tol assert abs(output['et_reference']['2017-07-01'] - 236.5 * 0.5) <= tol assert abs(output['et_fraction']['2017-07-01'] - 145.9705047607422 / 236.5 / 0.5) <= tol @@ -235,7 +239,7 @@ def test_from_scene_et_actual_monthly_et_reference_resample(tol=0.0001): t_interval='monthly') TEST_POINT = (-121.5265, 38.7399) - output = utils.point_coll_value(output_coll, TEST_POINT, scale=10) + output = utils.point_coll_value(output_coll, TEST_POINT, scale=30) assert abs(output['et']['2017-07-01'] - 145.9705047607422) <= tol assert abs(output['et_reference']['2017-07-01'] - 236.5) <= tol assert abs(output['et_fraction']['2017-07-01'] - 145.9705047607422 / 236.5) <= tol @@ -263,7 +267,7 @@ def test_from_scene_et_actual_daily_et_fraction_max(tol=0.0001): t_interval='daily') TEST_POINT = (-121.5265, 38.7399) - output = utils.point_coll_value(output_coll, TEST_POINT, scale=10) + output = utils.point_coll_value(output_coll, TEST_POINT, scale=30) assert abs(output['et_fraction']['2017-07-10'] - 1.4) <= tol diff --git a/openet/ptjpl/utils.py b/openet/ptjpl/utils.py index e7550f0..fc5b001 100644 --- a/openet/ptjpl/utils.py +++ b/openet/ptjpl/utils.py @@ -13,40 +13,45 @@ def getinfo(ee_obj, n=4): try: output = ee_obj.getInfo() except ee.ee_exception.EEException as e: - if ('Earth Engine memory capacity exceeded' in str(e) or - 'Earth Engine capacity exceeded' in str(e)): - logging.info(f' Resending query ({i}/10)') - logging.debug(f' {e}') - sleep(i ** 2) - else: - raise e + logging.info(f' Resending query ({i}/{n})') + logging.info(f' {e}') + sleep(i ** 3) + # if ('Earth Engine memory capacity exceeded' in str(e) or + # 'Earth Engine capacity exceeded' in str(e)): + # logging.info(f' Resending query ({i}/{n})') + # logging.debug(f' {e}') + # sleep(i ** 2) + # else: + # raise e + except Exception as e: + logging.info(e) + break if output: break - # output = ee_obj.getInfo() return output -# TODO: Import from common.utils -# Should these be test fixtures instead? -# I'm not sure how to make them fixtures and allow input parameters +# TODO: Import from openet.core.utils instead of defining here def constant_image_value(image, crs='EPSG:32613', scale=1): """Extract the output value from a calculation done with constant images""" - return ee.Image(image).rename(['output']) \ - .reduceRegion( - reducer=ee.Reducer.first(), scale=scale, - geometry=ee.Geometry.Rectangle([0, 0, 10, 10], crs, False)) \ - .getInfo()['output'] + rr_params = { + 'reducer': ee.Reducer.first(), + 'geometry': ee.Geometry.Rectangle([0, 0, 10, 10], crs, False), + 'scale': scale, + } + return getinfo(ee.Image(image).reduceRegion(**rr_params)) def point_image_value(image, xy, scale=1): """Extract the output value from a calculation at a point""" - return ee.Image(image).rename(['output']) \ - .reduceRegion( - reducer=ee.Reducer.first(), geometry=ee.Geometry.Point(xy), - scale=scale) \ - .getInfo()['output'] + rr_params = { + 'reducer': ee.Reducer.first(), + 'geometry': ee.Geometry.Point(xy), + 'scale': scale, + } + return getinfo(ee.Image(image).reduceRegion(**rr_params)) def point_coll_value(coll, xy, scale=1): @@ -61,10 +66,10 @@ def point_coll_value(coll, xy, scale=1): col_dict[k] = i + 4 info_dict[k] = {} for row in output[1:]: - date = datetime.datetime.utcfromtimestamp(row[3] / 1000.0).strftime( - '%Y-%m-%d') + date = datetime.datetime.utcfromtimestamp(row[3] / 1000.0).strftime('%Y-%m-%d') for k, v in col_dict.items(): info_dict[k][date] = row[col_dict[k]] + return info_dict # return pd.DataFrame.from_dict(info_dict) @@ -95,13 +100,11 @@ def date_to_time_0utc(date): ------- ee.Number - Notes - ----- - Extra operations are needed since update() does not set milliseconds to 0. - """ - return date.update(hour=0, minute=0, second=0).millis() \ - .divide(1000).floor().multiply(1000) + return ee.Date.fromYMD(date.get('year'), date.get('month'), date.get('day')).millis() + # Extra operations are needed since update() does not set milliseconds to 0. + # return date.update(hour=0, minute=0, second=0).millis()\ + # .divide(1000).floor().multiply(1000) def is_number(x):