@@ -51,6 +51,7 @@ def __init__(
5151 dt_min = 5 ,
5252 dt_max = 25 ,
5353 et_fraction_type = 'alfalfa' ,
54+ et_fraction_grass_source = None ,
5455 reflectance_type = 'SR' ,
5556 ** kwargs ,
5657 ):
@@ -85,7 +86,7 @@ def __init__(
8586 'DAYMET_MEDIAN_V2', 'CIMIS_MEDIAN_V1',
8687 collection ID, or float}, optional
8788 Maximum air temperature source. The default is
88- 'projects/usgs-ssebop/tmax/daymet_v3_median_1980_2018 '.
89+ 'projects/usgs-ssebop/tmax/daymet_v4_mean_1981_2010 '.
8990 elr_flag : bool, str, optional
9091 If True, apply Elevation Lapse Rate (ELR) adjustment
9192 (the default is False).
@@ -94,10 +95,16 @@ def __init__(
9495 dt_max : float, optional
9596 Maximum allowable dT [K] (the default is 25).
9697 et_fraction_type : {'alfalfa', 'grass'}, optional
97- ET fraction (the default is 'alfalfa').
98+ ET fraction reference type (the default is 'alfalfa').
99+ If set to "grass" the et_fraction_grass_source must also be set.
100+ et_fraction_grass_source : {'NASA/NLDAS/FORA0125_H002',
101+ 'ECMWF/ERA5_LAND/HOURLY'}, float, optional
102+ Reference ET source for alfalfa to grass reference adjustment.
103+ Parameter must be set if et_fraction_type is 'grass'.
104+ The default is currently the NLDAS hourly collection,
105+ but having a default will likely be removed in a future version.
98106 reflectance_type : {'SR', 'TOA'}, optional
99- Used to set the Tcorr NDVI thresholds
100- (the default is 'SR').
107+ Used to set the Tcorr NDVI thresholds (the default is 'SR').
101108 kwargs : dict, optional
102109 dt_resample : {'nearest', 'bilinear'}
103110 tcorr_resample : {'nearest', 'bilinear'}
@@ -194,14 +201,28 @@ def __init__(
194201 raise ValueError (f'elr_flag "{ self ._elr_flag } " could not be interpreted as bool' )
195202
196203 # ET fraction type
197- # CGM - Should et_fraction_type be set as a kwarg instead?
198204 if et_fraction_type .lower () not in ['alfalfa' , 'grass' ]:
199205 raise ValueError ('et_fraction_type must "alfalfa" or "grass"' )
200206 self .et_fraction_type = et_fraction_type .lower ()
201- # if 'et_fraction_type' in kwargs.keys():
202- # self.et_fraction_type = kwargs['et_fraction_type'].lower()
203- # else:
204- # self.et_fraction_type = 'alfalfa'
207+
208+ # ET fraction alfalfa to grass reference adjustment
209+ # The NLDAS hourly collection will be used if a source value is not set
210+ if self .et_fraction_type .lower () == 'grass' and not et_fraction_grass_source :
211+ warnings .warn (
212+ 'NLDAS is being set as the default ET fraction grass adjustment source. '
213+ 'In a future version the parameter will need to be set explicitly as: '
214+ 'et_fraction_grass_source="NASA/NLDAS/FORA0125_H002".' ,
215+ FutureWarning
216+ )
217+ et_fraction_grass_source = 'NASA/NLDAS/FORA0125_H002'
218+ self .et_fraction_grass_source = et_fraction_grass_source
219+ # if self.et_fraction_type.lower() == 'grass' and not et_fraction_grass_source:
220+ # raise ValueError(
221+ # 'et_fraction_grass_source parameter must be set if et_fraction_type==\'grass\''
222+ # )
223+ # # Should the supported source values be checked here instead of in model.py?
224+ # if et_fraction_grass_source not in et_fraction_grass_sources:
225+ # raise ValueError('unsupported et_fraction_grass_source')
205226
206227 self .reflectance_type = reflectance_type
207228 if reflectance_type not in ['SR' , 'TOA' ]:
@@ -333,50 +354,16 @@ def et_fraction(self):
333354
334355 et_fraction = model .et_fraction (lst = self .lst , tmax = tmax , tcorr = self .tcorr , dt = dt )
335356
336- # TODO: Add support for setting the conversion source dataset
337- # TODO: Interpolate "instantaneous" ETo and ETr?
338- # TODO: Move openet.refetgee import to top?
339- # TODO: Check if etr/eto is right (I think it is)
340- if self .et_fraction_type .lower () == 'grass' :
341- import openet .refetgee
342- nldas_coll = (
343- ee .ImageCollection ('NASA/NLDAS/FORA0125_H002' )
344- .select (['temperature' , 'specific_humidity' , 'shortwave_radiation' , 'wind_u' , 'wind_v' ])
345- )
346-
347- # Interpolating hourly NLDAS to the Landsat scene time
348- # CGM - The 2 hour window is useful in case an image is missing
349- # I think EEMETRIC is using a 4 hour window
350- # CGM - Need to check if the NLDAS images are instantaneous
351- # or some sort of average of the previous or next hour
352- time_start = ee .Number (self ._time_start )
353- prev_img = ee .Image (
354- nldas_coll
355- .filterDate (time_start .subtract (2 * 60 * 60 * 1000 ), time_start )
356- .limit (1 , 'system:time_start' , False )
357- .first ()
358- )
359- next_img = ee .Image (
360- nldas_coll .filterDate (time_start , time_start .add (2 * 60 * 60 * 1000 )).first ()
361- )
362- prev_time = ee .Number (prev_img .get ('system:time_start' ))
363- next_time = ee .Number (next_img .get ('system:time_start' ))
364- time_ratio = time_start .subtract (prev_time ).divide (next_time .subtract (prev_time ))
365- nldas_img = (
366- next_img .subtract (prev_img ).multiply (time_ratio ).add (prev_img )
367- .set ({'system:time_start' : self ._time_start })
368- )
369-
370- # # DEADBEEF - Select NLDAS image before the Landsat scene time
371- # nldas_img = ee.Image(nldas_coll
372- # .filterDate(self._date.advance(-1, 'hour'), self._date)
373- # .first())
374-
375- et_fraction = (
376- et_fraction
377- .multiply (openet .refetgee .Hourly .nldas (nldas_img ).etr )
378- .divide (openet .refetgee .Hourly .nldas (nldas_img ).eto )
379- )
357+ # Convert the ET fraction to a grass reference fraction
358+ if self .et_fraction_type .lower () == 'grass' and self .et_fraction_grass_source :
359+ if utils .is_number (self .et_fraction_grass_source ):
360+ et_fraction = et_fraction .multiply (self .et_fraction_grass_source )
361+ else :
362+ et_fraction = model .etf_grass_type_adjust (
363+ etf = et_fraction ,
364+ src_coll_id = self .et_fraction_grass_source ,
365+ time_start = self ._time_start
366+ )
380367
381368 return et_fraction .set (self ._properties )\
382369 .set ({
0 commit comments