BESS-JPL 1.9.2__py3-none-any.whl → 1.10.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of BESS-JPL might be problematic. Click here for more details.
- BESS_JPL/BESS_JPL.py +1 -493
- BESS_JPL/model.py +520 -0
- BESS_JPL/process_BESS_table.py +55 -0
- BESS_JPL/version.txt +1 -1
- {bess_jpl-1.9.2.dist-info → bess_jpl-1.10.0.dist-info}/METADATA +1 -1
- {bess_jpl-1.9.2.dist-info → bess_jpl-1.10.0.dist-info}/RECORD +9 -7
- {bess_jpl-1.9.2.dist-info → bess_jpl-1.10.0.dist-info}/WHEEL +1 -1
- {bess_jpl-1.9.2.dist-info → bess_jpl-1.10.0.dist-info}/licenses/LICENSE +0 -0
- {bess_jpl-1.9.2.dist-info → bess_jpl-1.10.0.dist-info}/top_level.txt +0 -0
BESS_JPL/BESS_JPL.py
CHANGED
|
@@ -41,496 +41,4 @@ from .load_ball_berry_slope_C4 import *
|
|
|
41
41
|
from .calculate_VCmax import *
|
|
42
42
|
from .meteorology import *
|
|
43
43
|
from .soil_energy_balance import *
|
|
44
|
-
|
|
45
|
-
logger = logging.getLogger(__name__)
|
|
46
|
-
|
|
47
|
-
def BESS_JPL(
|
|
48
|
-
ST_C: Union[Raster, np.ndarray], # surface temperature in Celsius
|
|
49
|
-
NDVI: Union[Raster, np.ndarray], # NDVI
|
|
50
|
-
albedo: Union[Raster, np.ndarray], # surface albedo
|
|
51
|
-
geometry: RasterGeometry = None,
|
|
52
|
-
time_UTC: datetime = None,
|
|
53
|
-
hour_of_day: np.ndarray = None,
|
|
54
|
-
day_of_year: np.ndarray = None,
|
|
55
|
-
GEOS5FP_connection: GEOS5FP = None,
|
|
56
|
-
elevation_km: Union[Raster, np.ndarray] = None, # elevation in kilometers
|
|
57
|
-
Ta_C: Union[Raster, np.ndarray] = None, # air temperature in Celsius
|
|
58
|
-
RH: Union[Raster, np.ndarray] = None, # relative humidity as a proportion
|
|
59
|
-
NDVI_minimum: Union[Raster, np.ndarray] = None, # minimum NDVI
|
|
60
|
-
NDVI_maximum: Union[Raster, np.ndarray] = None, # maximum NDVI
|
|
61
|
-
Rg: Union[Raster, np.ndarray] = None, # incoming shortwave radiation in W/m^2
|
|
62
|
-
VISdiff: Union[Raster, np.ndarray] = None, # diffuse visible radiation in W/m^2
|
|
63
|
-
VISdir: Union[Raster, np.ndarray] = None, # direct visible radiation in W/m^2
|
|
64
|
-
NIRdiff: Union[Raster, np.ndarray] = None, # diffuse near-infrared radiation in W/m^2
|
|
65
|
-
NIRdir: Union[Raster, np.ndarray] = None, # direct near-infrared radiation in W/m^2
|
|
66
|
-
UV: Union[Raster, np.ndarray] = None, # incoming ultraviolet radiation in W/m^2
|
|
67
|
-
albedo_visible: Union[Raster, np.ndarray] = None, # surface albedo in visible wavelengths (initialized to surface albedo if left as None)
|
|
68
|
-
albedo_NIR: Union[Raster, np.ndarray] = None, # surface albedo in near-infrared wavelengths (initialized to surface albedo if left as None)
|
|
69
|
-
COT: Union[Raster, np.ndarray] = None, # cloud optical thickness
|
|
70
|
-
AOT: Union[Raster, np.ndarray] = None, # aerosol optical thickness
|
|
71
|
-
vapor_gccm: Union[Raster, np.ndarray] = None, # water vapor in g/ccm
|
|
72
|
-
ozone_cm: Union[Raster, np.ndarray] = None, # ozone in cm
|
|
73
|
-
KG_climate: Union[Raster, np.ndarray] = None, # KG climate
|
|
74
|
-
canopy_height_meters: Union[Raster, np.ndarray] = None, # canopy height in meters
|
|
75
|
-
Ca: Union[Raster, np.ndarray] = None, # atmospheric CO2 concentration in ppm
|
|
76
|
-
wind_speed_mps: Union[Raster, np.ndarray] = None, # wind speed in meters per second
|
|
77
|
-
SZA: Union[Raster, np.ndarray] = None, # solar zenith angle in degrees
|
|
78
|
-
canopy_temperature_C: Union[Raster, np.ndarray] = None, # canopy temperature in Celsius (initialized to surface temperature if left as None)
|
|
79
|
-
soil_temperature_C: Union[Raster, np.ndarray] = None, # soil temperature in Celsius (initialized to surface temperature if left as None)
|
|
80
|
-
C4_fraction: Union[Raster, np.ndarray] = None, # fraction of C4 plants
|
|
81
|
-
carbon_uptake_efficiency: Union[Raster, np.ndarray] = None, # intrinsic quantum efficiency for carbon uptake
|
|
82
|
-
kn: np.ndarray = None,
|
|
83
|
-
ball_berry_intercept_C3: np.ndarray = None, # Ball-Berry intercept for C3 plants
|
|
84
|
-
ball_berry_intercept_C4: Union[np.ndarray, float] = BALL_BERRY_INTERCEPT_C4, # Ball-Berry intercept for C4 plants
|
|
85
|
-
ball_berry_slope_C3: np.ndarray = None, # Ball-Berry slope for C3 plants
|
|
86
|
-
ball_berry_slope_C4: np.ndarray = None, # Ball-Berry slope for C4 plants
|
|
87
|
-
peakVCmax_C3: np.ndarray = None, # peak maximum carboxylation rate for C3 plants
|
|
88
|
-
peakVCmax_C4: np.ndarray = None, # peak maximum carboxylation rate for C4 plants
|
|
89
|
-
CI: Union[Raster, np.ndarray] = None,
|
|
90
|
-
resampling: str = RESAMPLING): # clumping index
|
|
91
|
-
if geometry is None and isinstance(ST_C, Raster):
|
|
92
|
-
geometry = ST_C.geometry
|
|
93
|
-
|
|
94
|
-
if GEOS5FP_connection is None:
|
|
95
|
-
GEOS5FP_connection = GEOS5FP()
|
|
96
|
-
|
|
97
|
-
if (day_of_year is None or hour_of_day is None) and time_UTC is not None and geometry is not None:
|
|
98
|
-
day_of_year = solar_day_of_year_for_area(time_UTC=time_UTC, geometry=geometry)
|
|
99
|
-
hour_of_day = solar_hour_of_day_for_area(time_UTC=time_UTC, geometry=geometry)
|
|
100
|
-
|
|
101
|
-
if time_UTC is None and day_of_year is None and hour_of_day is None:
|
|
102
|
-
raise ValueError("no time given between time_UTC, day_of_year, and hour_of_day")
|
|
103
|
-
|
|
104
|
-
if elevation_km is None and geometry is not None:
|
|
105
|
-
elevation_km = NASADEM.elevation_km(geometry=geometry)
|
|
106
|
-
|
|
107
|
-
# load air temperature in Celsius if not provided
|
|
108
|
-
if Ta_C is None:
|
|
109
|
-
Ta_C = GEOS5FP_connection.Ta_C(time_UTC=time_UTC, geometry=geometry, resampling=resampling)
|
|
110
|
-
|
|
111
|
-
# load relative humidity if not provided
|
|
112
|
-
if RH is None:
|
|
113
|
-
RH = GEOS5FP_connection.RH(time_UTC=time_UTC, geometry=geometry, resampling=resampling)
|
|
114
|
-
|
|
115
|
-
# load minimum NDVI if not provided
|
|
116
|
-
if NDVI_minimum is None and geometry is not None:
|
|
117
|
-
NDVI_minimum = load_NDVI_minimum(geometry=geometry, resampling=resampling)
|
|
118
|
-
|
|
119
|
-
# load maximum NDVI if not provided
|
|
120
|
-
if NDVI_maximum is None and geometry is not None:
|
|
121
|
-
NDVI_maximum = load_NDVI_maximum(geometry=geometry, resampling=resampling)
|
|
122
|
-
|
|
123
|
-
# load C4 fraction if not provided
|
|
124
|
-
if C4_fraction is None:
|
|
125
|
-
C4_fraction = load_C4_fraction(geometry=geometry, resampling=resampling)
|
|
126
|
-
|
|
127
|
-
# load carbon uptake efficiency if not provided
|
|
128
|
-
if carbon_uptake_efficiency is None:
|
|
129
|
-
carbon_uptake_efficiency = load_carbon_uptake_efficiency(geometry=geometry, resampling=resampling)
|
|
130
|
-
|
|
131
|
-
# load kn if not provided
|
|
132
|
-
if kn is None:
|
|
133
|
-
kn = load_kn(geometry=geometry, resampling=resampling)
|
|
134
|
-
|
|
135
|
-
# load peak VC max for C3 plants if not provided
|
|
136
|
-
if peakVCmax_C3 is None:
|
|
137
|
-
peakVCmax_C3 = load_peakVCmax_C3(geometry=geometry, resampling=resampling)
|
|
138
|
-
|
|
139
|
-
# load peak VC max for C4 plants if not provided
|
|
140
|
-
if peakVCmax_C4 is None:
|
|
141
|
-
peakVCmax_C4 = load_peakVCmax_C4(geometry=geometry, resampling=resampling)
|
|
142
|
-
|
|
143
|
-
# load Ball-Berry slope for C3 plants if not provided
|
|
144
|
-
if ball_berry_slope_C3 is None:
|
|
145
|
-
ball_berry_slope_C3 = load_ball_berry_slope_C3(geometry=geometry, resampling=resampling)
|
|
146
|
-
|
|
147
|
-
# load Ball-Berry slope for C4 plants if not provided
|
|
148
|
-
if ball_berry_slope_C4 is None:
|
|
149
|
-
ball_berry_slope_C4 = load_ball_berry_slope_C4(geometry=geometry, resampling=resampling)
|
|
150
|
-
|
|
151
|
-
# load Ball-Berry intercept for C3 plants if not provided
|
|
152
|
-
if ball_berry_intercept_C3 is None:
|
|
153
|
-
ball_berry_intercept_C3 = load_ball_berry_intercept_C3(geometry=geometry, resampling=resampling)
|
|
154
|
-
|
|
155
|
-
# Create a dictionary of variables to check
|
|
156
|
-
variables_to_check = {
|
|
157
|
-
"Rg": Rg,
|
|
158
|
-
"VISdiff": VISdiff,
|
|
159
|
-
"VISdir": VISdir,
|
|
160
|
-
"NIRdiff": NIRdiff,
|
|
161
|
-
"NIRdir": NIRdir,
|
|
162
|
-
"UV": UV,
|
|
163
|
-
"albedo_visible": albedo_visible,
|
|
164
|
-
"albedo_NIR": albedo_NIR
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
# Check for None values and size mismatches
|
|
168
|
-
reference_size = None
|
|
169
|
-
missing_radiative_transfer_variables = []
|
|
170
|
-
need_radiative_transfer = False
|
|
171
|
-
|
|
172
|
-
for name, var in variables_to_check.items():
|
|
173
|
-
if var is None:
|
|
174
|
-
logger.info(f"{name}: None")
|
|
175
|
-
else:
|
|
176
|
-
logger.info(f"{name}: {var.shape}")
|
|
177
|
-
|
|
178
|
-
if var is None:
|
|
179
|
-
logger.warning(f"Variable '{name}' is None.")
|
|
180
|
-
missing_radiative_transfer_variables = missing_radiative_transfer_variables.append(name)
|
|
181
|
-
else:
|
|
182
|
-
# Get the size of the variable if it's a numpy array
|
|
183
|
-
size = var.shape if isinstance(var, np.ndarray) else None
|
|
184
|
-
|
|
185
|
-
if reference_size is None:
|
|
186
|
-
reference_size = size # Set the first non-None size as the reference
|
|
187
|
-
elif size != reference_size:
|
|
188
|
-
logger.warning(f"Variable '{name}' has a different size: {size} (expected: {reference_size}).")
|
|
189
|
-
missing_radiative_transfer_variables = missing_radiative_transfer_variables.append(name)
|
|
190
|
-
|
|
191
|
-
if len(missing_radiative_transfer_variables) > 0:
|
|
192
|
-
need_radiative_transfer = True
|
|
193
|
-
|
|
194
|
-
# check if any of the FLiES outputs are not given
|
|
195
|
-
if need_radiative_transfer:
|
|
196
|
-
logger.info(f"running FLiES for missing variables: {', '.join(missing_radiative_transfer_variables)}")
|
|
197
|
-
# load cloud optical thickness if not provided
|
|
198
|
-
if COT is None:
|
|
199
|
-
COT = GEOS5FP_connection.COT(time_UTC=time_UTC, geometry=geometry, resampling=resampling)
|
|
200
|
-
|
|
201
|
-
# load aerosol optical thickness if not provided
|
|
202
|
-
if AOT is None:
|
|
203
|
-
AOT = GEOS5FP_connection.AOT(time_UTC=time_UTC, geometry=geometry, resampling=resampling)
|
|
204
|
-
|
|
205
|
-
## FIXME fix FLiES interface
|
|
206
|
-
|
|
207
|
-
# run FLiES radiative transfer model
|
|
208
|
-
FLiES_results = FLiESANN(
|
|
209
|
-
time_UTC=time_UTC,
|
|
210
|
-
day_of_year=day_of_year,
|
|
211
|
-
hour_of_day=hour_of_day,
|
|
212
|
-
geometry=geometry,
|
|
213
|
-
albedo=albedo,
|
|
214
|
-
COT=COT,
|
|
215
|
-
AOT=AOT,
|
|
216
|
-
vapor_gccm=vapor_gccm,
|
|
217
|
-
ozone_cm=ozone_cm,
|
|
218
|
-
elevation_km=elevation_km,
|
|
219
|
-
SZA=SZA,
|
|
220
|
-
KG_climate=KG_climate,
|
|
221
|
-
GEOS5FP_connection=GEOS5FP_connection
|
|
222
|
-
)
|
|
223
|
-
|
|
224
|
-
# extract FLiES outputs
|
|
225
|
-
Rg = FLiES_results["Rg"]
|
|
226
|
-
VISdiff = FLiES_results["VISdiff"]
|
|
227
|
-
VISdir = FLiES_results["VISdir"]
|
|
228
|
-
NIRdiff = FLiES_results["NIRdiff"]
|
|
229
|
-
NIRdir = FLiES_results["NIRdir"]
|
|
230
|
-
UV = FLiES_results["UV"]
|
|
231
|
-
# albedo_visible = FLiES_results["VIS"]
|
|
232
|
-
# albedo_NIR = FLiES_results["NIR"]
|
|
233
|
-
albedo_NWP = GEOS5FP_connection.ALBEDO(time_UTC=time_UTC, geometry=geometry, resampling=resampling)
|
|
234
|
-
RVIS_NWP = GEOS5FP_connection.ALBVISDR(time_UTC=time_UTC, geometry=geometry, resampling=resampling)
|
|
235
|
-
albedo_visible = rt.clip(albedo * (RVIS_NWP / albedo_NWP), 0, 1)
|
|
236
|
-
check_distribution(albedo_visible, "RVIS")
|
|
237
|
-
RNIR_NWP = GEOS5FP_connection.ALBNIRDR(time_UTC=time_UTC, geometry=geometry, resampling=resampling)
|
|
238
|
-
albedo_NIR = rt.clip(albedo * (RNIR_NWP / albedo_NWP), 0, 1)
|
|
239
|
-
check_distribution(albedo_NIR, "RNIR")
|
|
240
|
-
PARDir = VISdir
|
|
241
|
-
check_distribution(PARDir, "PARDir")
|
|
242
|
-
else:
|
|
243
|
-
logger.info("using given FLiES output as BESS parameters")
|
|
244
|
-
|
|
245
|
-
# load koppen geiger climate classification if not provided
|
|
246
|
-
if KG_climate is None:
|
|
247
|
-
KG_climate = load_koppen_geiger(geometry=geometry)
|
|
248
|
-
|
|
249
|
-
# load canopy height in meters if not provided
|
|
250
|
-
if canopy_height_meters is None:
|
|
251
|
-
canopy_height_meters = load_canopy_height(geometry=geometry, resampling=resampling)
|
|
252
|
-
|
|
253
|
-
# load CO2 concentration in ppm if not provided
|
|
254
|
-
if Ca is None:
|
|
255
|
-
Ca = GEOS5FP_connection.CO2SC(time_UTC=time_UTC, geometry=geometry, resampling=resampling)
|
|
256
|
-
|
|
257
|
-
# load wind speed in meters per second if not provided
|
|
258
|
-
if wind_speed_mps is None:
|
|
259
|
-
wind_speed_mps = GEOS5FP_connection.wind_speed(time_UTC=time_UTC, geometry=geometry, resampling=resampling)
|
|
260
|
-
|
|
261
|
-
# canopy temperature defaults to surface temperature
|
|
262
|
-
if canopy_temperature_C is None:
|
|
263
|
-
canopy_temperature_C = ST_C
|
|
264
|
-
|
|
265
|
-
# soil temperature defaults to surface temperature
|
|
266
|
-
if soil_temperature_C is None:
|
|
267
|
-
soil_temperature_C = ST_C
|
|
268
|
-
|
|
269
|
-
# visible albedo defaults to surface albedo
|
|
270
|
-
if albedo_visible is None:
|
|
271
|
-
albedo_visible = albedo
|
|
272
|
-
|
|
273
|
-
# near-infrared albedo defaults to surface albedo
|
|
274
|
-
if albedo_NIR is None:
|
|
275
|
-
albedo_NIR = albedo
|
|
276
|
-
|
|
277
|
-
# calculate solar zenith angle if not provided
|
|
278
|
-
if SZA is None:
|
|
279
|
-
SZA = calculate_SZA_from_DOY_and_hour(geometry.lat, geometry.lon, day_of_year, hour_of_day)
|
|
280
|
-
|
|
281
|
-
if CI is None and geometry is not None:
|
|
282
|
-
modisci = MODISCI()
|
|
283
|
-
CI = modisci.CI(geometry=geometry, resampling=resampling)
|
|
284
|
-
|
|
285
|
-
# canopy height defaults to zero
|
|
286
|
-
canopy_height_meters = np.where(np.isnan(canopy_height_meters), 0, canopy_height_meters)
|
|
287
|
-
|
|
288
|
-
# calculate saturation vapor pressure in Pascal from air temperature in Kelvin
|
|
289
|
-
Ta_K = Ta_C + 273.15
|
|
290
|
-
SVP_Pa = SVP_Pa_from_Ta_K(Ta_K)
|
|
291
|
-
|
|
292
|
-
# calculate actual vapor pressure in Pascal from relative humidity and saturation vapor pressure
|
|
293
|
-
Ea_Pa = RH * SVP_Pa
|
|
294
|
-
|
|
295
|
-
# convert elevation to meters
|
|
296
|
-
elevation_m = elevation_km * 1000
|
|
297
|
-
|
|
298
|
-
latitude = geometry.lat
|
|
299
|
-
|
|
300
|
-
Ps_Pa, VPD_Pa, RH, desTa, ddesTa, gamma, Cp, rhoa, epsa, R, Rc, Rs, SFd, SFd2, DL, Ra, fStress = meteorology(
|
|
301
|
-
day_of_year=day_of_year,
|
|
302
|
-
hour_of_day=hour_of_day,
|
|
303
|
-
latitude=latitude,
|
|
304
|
-
elevation_m=elevation_m,
|
|
305
|
-
SZA=SZA,
|
|
306
|
-
Ta_K=Ta_K,
|
|
307
|
-
Ea_Pa=Ea_Pa,
|
|
308
|
-
Rg=Rg,
|
|
309
|
-
wind_speed_mps=wind_speed_mps,
|
|
310
|
-
canopy_height_meters=canopy_height_meters
|
|
311
|
-
)
|
|
312
|
-
|
|
313
|
-
meteorology_outputs = {
|
|
314
|
-
"Ps_Pa": Ps_Pa,
|
|
315
|
-
"VPD_Pa": VPD_Pa,
|
|
316
|
-
"RH": RH,
|
|
317
|
-
"desTa": desTa,
|
|
318
|
-
"ddesTa": ddesTa,
|
|
319
|
-
"gamma": gamma,
|
|
320
|
-
"Cp": Cp,
|
|
321
|
-
"rhoa": rhoa,
|
|
322
|
-
"epsa": epsa,
|
|
323
|
-
"R": R,
|
|
324
|
-
"Rc": Rc,
|
|
325
|
-
"Rs": Rs,
|
|
326
|
-
"SFd": SFd,
|
|
327
|
-
"SFd2": SFd2,
|
|
328
|
-
"DL": DL,
|
|
329
|
-
"Ra": Ra,
|
|
330
|
-
"fStress": fStress
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
# Check the distribution for each variable
|
|
334
|
-
for var_name, var_value in meteorology_outputs.items():
|
|
335
|
-
check_distribution(var_value, var_name, time_UTC)
|
|
336
|
-
|
|
337
|
-
# convert NDVI to LAI
|
|
338
|
-
LAI = LAI_from_NDVI(NDVI)
|
|
339
|
-
LAI_minimum = LAI_from_NDVI(NDVI_minimum)
|
|
340
|
-
LAI_maximum = LAI_from_NDVI(NDVI_maximum)
|
|
341
|
-
|
|
342
|
-
VCmax_C3_sunlit, VCmax_C4_sunlit, VCmax_C3_shaded, VCmax_C4_shaded = calculate_VCmax(
|
|
343
|
-
LAI=LAI,
|
|
344
|
-
LAI_minimum=LAI_minimum,
|
|
345
|
-
LAI_maximum=LAI_maximum,
|
|
346
|
-
peakVCmax_C3=peakVCmax_C3,
|
|
347
|
-
peakVCmax_C4=peakVCmax_C4,
|
|
348
|
-
SZA=SZA,
|
|
349
|
-
kn=kn
|
|
350
|
-
)
|
|
351
|
-
|
|
352
|
-
# List of variable names and their corresponding values
|
|
353
|
-
VCmax_outputs = {
|
|
354
|
-
"VCmax_C3_sunlit": VCmax_C3_sunlit,
|
|
355
|
-
"VCmax_C4_sunlit": VCmax_C4_sunlit,
|
|
356
|
-
"VCmax_C3_shaded": VCmax_C3_shaded,
|
|
357
|
-
"VCmax_C4_shaded": VCmax_C4_shaded
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
# Check the distribution for each variable
|
|
361
|
-
for var_name, var_value in VCmax_outputs.items():
|
|
362
|
-
check_distribution(var_value, var_name, time_UTC)
|
|
363
|
-
|
|
364
|
-
sunlit_fraction, APAR_sunlit, APAR_shaded, ASW_sunlit, ASW_shaded, ASW_soil, G = canopy_shortwave_radiation(
|
|
365
|
-
PARDiff=VISdiff, # diffuse photosynthetically active radiation in W/m^2
|
|
366
|
-
PARDir=VISdir, # direct photosynthetically active radiation in W/m^2
|
|
367
|
-
NIRDiff=NIRdiff, # diffuse near-infrared radiation in W/m^2
|
|
368
|
-
NIRDir=NIRdir, # direct near-infrared radiation in W/m^2
|
|
369
|
-
UV=UV, # incoming ultraviolet radiation in W/m^2
|
|
370
|
-
SZA=SZA, # solar zenith angle in degrees
|
|
371
|
-
LAI=LAI, # leaf area index
|
|
372
|
-
CI=CI, # clumping index
|
|
373
|
-
albedo_visible=albedo_visible, # surface albedo in visible wavelengths
|
|
374
|
-
albedo_NIR=albedo_NIR # surface albedo in near-infrared wavelengths
|
|
375
|
-
)
|
|
376
|
-
|
|
377
|
-
# List of variable names and their corresponding values
|
|
378
|
-
canopy_radiation_outputs = {
|
|
379
|
-
"sunlit_fraction": sunlit_fraction,
|
|
380
|
-
"APAR_sunlit": APAR_sunlit,
|
|
381
|
-
"APAR_shaded": APAR_shaded,
|
|
382
|
-
"ASW_sunlit": ASW_sunlit,
|
|
383
|
-
"ASW_shaded": ASW_shaded,
|
|
384
|
-
"ASW_soil": ASW_soil,
|
|
385
|
-
"G": G
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
# Check the distribution for each variable
|
|
389
|
-
for var_name, var_value in canopy_radiation_outputs.items():
|
|
390
|
-
check_distribution(var_value, var_name, time_UTC)
|
|
391
|
-
|
|
392
|
-
canopy_temperature_K = canopy_temperature_C + 273.15
|
|
393
|
-
soil_temperature_K = soil_temperature_C + 273.15
|
|
394
|
-
|
|
395
|
-
GPP_C3, LE_C3, LE_soil_C3, LE_canopy_C3, Rn_C3, Rn_soil_C3, Rn_canopy_C3 = carbon_water_fluxes(
|
|
396
|
-
canopy_temperature_K=canopy_temperature_K, # canopy temperature in Kelvin
|
|
397
|
-
soil_temperature_K=soil_temperature_K, # soil temperature in Kelvin
|
|
398
|
-
LAI=LAI, # leaf area index
|
|
399
|
-
Ta_K=Ta_K, # air temperature in Kelvin
|
|
400
|
-
APAR_sunlit=APAR_sunlit, # sunlit leaf absorptance of photosynthetically active radiation
|
|
401
|
-
APAR_shaded=APAR_shaded, # shaded leaf absorptance of photosynthetically active radiation
|
|
402
|
-
ASW_sunlit=ASW_sunlit, # sunlit absorbed shortwave radiation
|
|
403
|
-
ASW_shaded=ASW_shaded, # shaded absorbed shortwave radiation
|
|
404
|
-
ASW_soil=ASW_soil, # absorbed shortwave radiation of soil
|
|
405
|
-
Vcmax25_sunlit=VCmax_C3_sunlit, # sunlit maximum carboxylation rate at 25 degrees C
|
|
406
|
-
Vcmax25_shaded=VCmax_C3_shaded, # shaded maximum carboxylation rate at 25 degrees C
|
|
407
|
-
ball_berry_slope=ball_berry_slope_C3, # Ball-Berry slope for C3 photosynthesis
|
|
408
|
-
ball_berry_intercept=ball_berry_intercept_C3, # Ball-Berry intercept for C3 photosynthesis
|
|
409
|
-
sunlit_fraction=sunlit_fraction, # fraction of sunlit leaves
|
|
410
|
-
G=G, # soil heat flux
|
|
411
|
-
SZA=SZA, # solar zenith angle
|
|
412
|
-
Ca=Ca, # atmospheric CO2 concentration
|
|
413
|
-
Ps_Pa=Ps_Pa, # surface pressure in Pascal
|
|
414
|
-
gamma=gamma, # psychrometric constant
|
|
415
|
-
Cp=Cp, # specific heat of air in J/kg/K
|
|
416
|
-
rhoa=rhoa, # density of air in kg/m3
|
|
417
|
-
VPD_Pa=VPD_Pa, # vapor pressure deficit in Pascal
|
|
418
|
-
RH=RH, # relative humidity as a fraction
|
|
419
|
-
desTa=desTa,
|
|
420
|
-
ddesTa=ddesTa,
|
|
421
|
-
epsa=epsa,
|
|
422
|
-
Rc=Rc,
|
|
423
|
-
Rs=Rs,
|
|
424
|
-
carbon_uptake_efficiency=carbon_uptake_efficiency, # intrinsic quantum efficiency for carbon uptake
|
|
425
|
-
fStress=fStress,
|
|
426
|
-
C4_photosynthesis=False # C3 or C4 photosynthesis
|
|
427
|
-
)
|
|
428
|
-
|
|
429
|
-
# List of variable names and their corresponding values
|
|
430
|
-
carbon_water_fluxes_outputs = {
|
|
431
|
-
"GPP_C3": GPP_C3,
|
|
432
|
-
"LE_C3": LE_C3,
|
|
433
|
-
"LE_soil_C3": LE_soil_C3,
|
|
434
|
-
"LE_canopy_C3": LE_canopy_C3,
|
|
435
|
-
"Rn_C3": Rn_C3,
|
|
436
|
-
"Rn_soil_C3": Rn_soil_C3,
|
|
437
|
-
"Rn_canopy_C3": Rn_canopy_C3
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
# Check the distribution for each variable
|
|
441
|
-
for var_name, var_value in carbon_water_fluxes_outputs.items():
|
|
442
|
-
check_distribution(var_value, var_name, time_UTC)
|
|
443
|
-
|
|
444
|
-
GPP_C4, LE_C4, LE_soil_C4, LE_canopy_C4, Rn_C4, Rn_soil_C4, Rn_canopy_C4 = carbon_water_fluxes(
|
|
445
|
-
canopy_temperature_K=canopy_temperature_K, # canopy temperature in Kelvin
|
|
446
|
-
soil_temperature_K=soil_temperature_K, # soil temperature in Kelvin
|
|
447
|
-
LAI=LAI, # leaf area index
|
|
448
|
-
Ta_K=Ta_K, # air temperature in Kelvin
|
|
449
|
-
APAR_sunlit=APAR_sunlit, # sunlit leaf absorptance of photosynthetically active radiation
|
|
450
|
-
APAR_shaded=APAR_shaded, # shaded leaf absorptance of photosynthetically active radiation
|
|
451
|
-
ASW_sunlit=ASW_sunlit, # sunlit absorbed shortwave radiation
|
|
452
|
-
ASW_shaded=ASW_shaded, # shaded absorbed shortwave radiation
|
|
453
|
-
ASW_soil=ASW_soil, # absorbed shortwave radiation of soil
|
|
454
|
-
Vcmax25_sunlit=VCmax_C4_sunlit, # sunlit maximum carboxylation rate at 25 degrees C
|
|
455
|
-
Vcmax25_shaded=VCmax_C4_shaded, # shaded maximum carboxylation rate at 25 degrees C
|
|
456
|
-
ball_berry_slope=ball_berry_slope_C4, # Ball-Berry slope for C4 photosynthesis
|
|
457
|
-
ball_berry_intercept=ball_berry_intercept_C4, # Ball-Berry intercept for C4 photosynthesis
|
|
458
|
-
sunlit_fraction=sunlit_fraction, # fraction of sunlit leaves
|
|
459
|
-
G=G, # soil heat flux
|
|
460
|
-
SZA=SZA, # solar zenith angle
|
|
461
|
-
Ca=Ca, # atmospheric CO2 concentration
|
|
462
|
-
Ps_Pa=Ps_Pa, # surface pressure in Pascal
|
|
463
|
-
gamma=gamma, # psychrometric constant
|
|
464
|
-
Cp=Cp, # specific heat of air in J/kg/K
|
|
465
|
-
rhoa=rhoa, # density of air in kg/m3
|
|
466
|
-
VPD_Pa=VPD_Pa, # vapor pressure deficit in Pascal
|
|
467
|
-
RH=RH, # relative humidity as a fraction
|
|
468
|
-
desTa=desTa,
|
|
469
|
-
ddesTa=ddesTa,
|
|
470
|
-
epsa=epsa,
|
|
471
|
-
Rc=Rc,
|
|
472
|
-
Rs=Rs,
|
|
473
|
-
carbon_uptake_efficiency=carbon_uptake_efficiency, # intrinsic quantum efficiency for carbon uptake
|
|
474
|
-
fStress=fStress,
|
|
475
|
-
C4_photosynthesis=True # C3 or C4 photosynthesis
|
|
476
|
-
)
|
|
477
|
-
|
|
478
|
-
# List of variable names and their corresponding values
|
|
479
|
-
carbon_water_fluxes_C4_outputs = {
|
|
480
|
-
"GPP_C4": GPP_C4,
|
|
481
|
-
"LE_C4": LE_C4,
|
|
482
|
-
"LE_soil_C4": LE_soil_C4,
|
|
483
|
-
"LE_canopy_C4": LE_canopy_C4,
|
|
484
|
-
"Rn_C4": Rn_C4,
|
|
485
|
-
"Rn_soil_C4": Rn_soil_C4,
|
|
486
|
-
"Rn_canopy_C4": Rn_canopy_C4
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
# Check the distribution for each variable
|
|
490
|
-
for var_name, var_value in carbon_water_fluxes_C4_outputs.items():
|
|
491
|
-
check_distribution(var_value, var_name, time_UTC)
|
|
492
|
-
|
|
493
|
-
# interpolate C3 and C4 GPP
|
|
494
|
-
ST_K = ST_C + 273.15
|
|
495
|
-
GPP = np.clip(interpolate_C3_C4(GPP_C3, GPP_C4, C4_fraction), 0, 50)
|
|
496
|
-
GPP = np.where(np.isnan(ST_K), np.nan, GPP)
|
|
497
|
-
|
|
498
|
-
if isinstance(geometry, RasterGeometry):
|
|
499
|
-
GPP = Raster(GPP, geometry=geometry)
|
|
500
|
-
|
|
501
|
-
# upscale from instantaneous to daily
|
|
502
|
-
|
|
503
|
-
# upscale GPP to daily
|
|
504
|
-
GPP_daily = 1800 * GPP / SFd * 1e-6 * 12 # Eq. (3) in Ryu et al 2008
|
|
505
|
-
GPP_daily = np.where(SFd < 0.01, 0, GPP_daily)
|
|
506
|
-
GPP_daily = np.where(SZA >= 90, 0, GPP_daily)
|
|
507
|
-
|
|
508
|
-
# interpolate C3 and C4 net radiation
|
|
509
|
-
Rn = np.clip(interpolate_C3_C4(Rn_C3, Rn_C4, C4_fraction), 0, 1000)
|
|
510
|
-
|
|
511
|
-
# interpolate C3 and C4 soil net radiation
|
|
512
|
-
Rn_soil = np.clip(interpolate_C3_C4(Rn_soil_C3, Rn_soil_C4, C4_fraction), 0, 1000)
|
|
513
|
-
|
|
514
|
-
# interpolate C3 and C4 canopy net radiation
|
|
515
|
-
Rn_canopy = np.clip(interpolate_C3_C4(Rn_canopy_C3, Rn_canopy_C4, C4_fraction), 0, 1000)
|
|
516
|
-
|
|
517
|
-
# interpolate C3 and C4 latent heat flux
|
|
518
|
-
LE = np.clip(interpolate_C3_C4(LE_C3, LE_C4, C4_fraction), 0, 1000)
|
|
519
|
-
|
|
520
|
-
# interpolate C3 and C4 soil latent heat flux
|
|
521
|
-
LE_soil = np.clip(interpolate_C3_C4(LE_soil_C3, LE_soil_C4, C4_fraction), 0, 1000)
|
|
522
|
-
|
|
523
|
-
# interpolate C3 and C4 canopy latent heat flux
|
|
524
|
-
LE_canopy = np.clip(interpolate_C3_C4(LE_canopy_C3, LE_canopy_C4, C4_fraction), 0, 1000)
|
|
525
|
-
|
|
526
|
-
return {
|
|
527
|
-
"GPP": GPP,
|
|
528
|
-
"GPP_daily": GPP_daily,
|
|
529
|
-
"Rn": Rn,
|
|
530
|
-
"Rn_soil": Rn_soil,
|
|
531
|
-
"Rn_canopy": Rn_canopy,
|
|
532
|
-
"G": G,
|
|
533
|
-
"LE": LE,
|
|
534
|
-
"LE_soil": LE_soil,
|
|
535
|
-
"LE_canopy": LE_canopy
|
|
536
|
-
}
|
|
44
|
+
from .model import *
|
BESS_JPL/model.py
ADDED
|
@@ -0,0 +1,520 @@
|
|
|
1
|
+
from typing import Union
|
|
2
|
+
from datetime import datetime
|
|
3
|
+
import logging
|
|
4
|
+
import numpy as np
|
|
5
|
+
|
|
6
|
+
import rasters as rt
|
|
7
|
+
from rasters import Raster, RasterGeometry
|
|
8
|
+
|
|
9
|
+
from check_distribution import check_distribution
|
|
10
|
+
|
|
11
|
+
from sun_angles import calculate_SZA_from_DOY_and_hour
|
|
12
|
+
from solar_apparent_time import solar_day_of_year_for_area, solar_hour_of_day_for_area
|
|
13
|
+
|
|
14
|
+
from koppengeiger import load_koppen_geiger
|
|
15
|
+
from gedi_canopy_height import load_canopy_height
|
|
16
|
+
from FLiESANN import FLiESANN
|
|
17
|
+
from GEOS5FP import GEOS5FP
|
|
18
|
+
from MODISCI import MODISCI
|
|
19
|
+
from NASADEM import NASADEM
|
|
20
|
+
|
|
21
|
+
from .constants import *
|
|
22
|
+
from .C3_photosynthesis import *
|
|
23
|
+
from .C4_photosynthesis import *
|
|
24
|
+
from .canopy_energy_balance import *
|
|
25
|
+
from .canopy_longwave_radiation import *
|
|
26
|
+
from .canopy_shortwave_radiation import *
|
|
27
|
+
from .carbon_water_fluxes import *
|
|
28
|
+
from .FVC_from_NDVI import *
|
|
29
|
+
from .interpolate_C3_C4 import *
|
|
30
|
+
from .LAI_from_NDVI import *
|
|
31
|
+
from .load_C4_fraction import *
|
|
32
|
+
from .load_carbon_uptake_efficiency import *
|
|
33
|
+
from .load_kn import *
|
|
34
|
+
from .load_NDVI_minimum import *
|
|
35
|
+
from .load_NDVI_maximum import *
|
|
36
|
+
from .load_peakVCmax_C3 import *
|
|
37
|
+
from .load_peakVCmax_C4 import *
|
|
38
|
+
from .load_ball_berry_intercept_C3 import *
|
|
39
|
+
from .load_ball_berry_slope_C3 import *
|
|
40
|
+
from .load_ball_berry_slope_C4 import *
|
|
41
|
+
from .calculate_VCmax import *
|
|
42
|
+
from .meteorology import *
|
|
43
|
+
from .soil_energy_balance import *
|
|
44
|
+
|
|
45
|
+
logger = logging.getLogger(__name__)
|
|
46
|
+
|
|
47
|
+
def BESS_JPL(
|
|
48
|
+
ST_C: Union[Raster, np.ndarray], # surface temperature in Celsius
|
|
49
|
+
NDVI: Union[Raster, np.ndarray], # NDVI
|
|
50
|
+
albedo: Union[Raster, np.ndarray], # surface albedo
|
|
51
|
+
geometry: RasterGeometry = None,
|
|
52
|
+
time_UTC: datetime = None,
|
|
53
|
+
hour_of_day: np.ndarray = None,
|
|
54
|
+
day_of_year: np.ndarray = None,
|
|
55
|
+
GEOS5FP_connection: GEOS5FP = None,
|
|
56
|
+
elevation_km: Union[Raster, np.ndarray] = None, # elevation in kilometers
|
|
57
|
+
Ta_C: Union[Raster, np.ndarray] = None, # air temperature in Celsius
|
|
58
|
+
RH: Union[Raster, np.ndarray] = None, # relative humidity as a proportion
|
|
59
|
+
NDVI_minimum: Union[Raster, np.ndarray] = None, # minimum NDVI
|
|
60
|
+
NDVI_maximum: Union[Raster, np.ndarray] = None, # maximum NDVI
|
|
61
|
+
Rg: Union[Raster, np.ndarray] = None, # incoming shortwave radiation in W/m^2
|
|
62
|
+
VISdiff: Union[Raster, np.ndarray] = None, # diffuse visible radiation in W/m^2
|
|
63
|
+
VISdir: Union[Raster, np.ndarray] = None, # direct visible radiation in W/m^2
|
|
64
|
+
NIRdiff: Union[Raster, np.ndarray] = None, # diffuse near-infrared radiation in W/m^2
|
|
65
|
+
NIRdir: Union[Raster, np.ndarray] = None, # direct near-infrared radiation in W/m^2
|
|
66
|
+
UV: Union[Raster, np.ndarray] = None, # incoming ultraviolet radiation in W/m^2
|
|
67
|
+
albedo_visible: Union[Raster, np.ndarray] = None, # surface albedo in visible wavelengths (initialized to surface albedo if left as None)
|
|
68
|
+
albedo_NIR: Union[Raster, np.ndarray] = None, # surface albedo in near-infrared wavelengths (initialized to surface albedo if left as None)
|
|
69
|
+
COT: Union[Raster, np.ndarray] = None, # cloud optical thickness
|
|
70
|
+
AOT: Union[Raster, np.ndarray] = None, # aerosol optical thickness
|
|
71
|
+
vapor_gccm: Union[Raster, np.ndarray] = None, # water vapor in g/ccm
|
|
72
|
+
ozone_cm: Union[Raster, np.ndarray] = None, # ozone in cm
|
|
73
|
+
KG_climate: Union[Raster, np.ndarray] = None, # KG climate
|
|
74
|
+
canopy_height_meters: Union[Raster, np.ndarray] = None, # canopy height in meters
|
|
75
|
+
Ca: Union[Raster, np.ndarray] = None, # atmospheric CO2 concentration in ppm
|
|
76
|
+
wind_speed_mps: Union[Raster, np.ndarray] = None, # wind speed in meters per second
|
|
77
|
+
SZA: Union[Raster, np.ndarray] = None, # solar zenith angle in degrees
|
|
78
|
+
canopy_temperature_C: Union[Raster, np.ndarray] = None, # canopy temperature in Celsius (initialized to surface temperature if left as None)
|
|
79
|
+
soil_temperature_C: Union[Raster, np.ndarray] = None, # soil temperature in Celsius (initialized to surface temperature if left as None)
|
|
80
|
+
C4_fraction: Union[Raster, np.ndarray] = None, # fraction of C4 plants
|
|
81
|
+
carbon_uptake_efficiency: Union[Raster, np.ndarray] = None, # intrinsic quantum efficiency for carbon uptake
|
|
82
|
+
kn: np.ndarray = None,
|
|
83
|
+
ball_berry_intercept_C3: np.ndarray = None, # Ball-Berry intercept for C3 plants
|
|
84
|
+
ball_berry_intercept_C4: Union[np.ndarray, float] = BALL_BERRY_INTERCEPT_C4, # Ball-Berry intercept for C4 plants
|
|
85
|
+
ball_berry_slope_C3: np.ndarray = None, # Ball-Berry slope for C3 plants
|
|
86
|
+
ball_berry_slope_C4: np.ndarray = None, # Ball-Berry slope for C4 plants
|
|
87
|
+
peakVCmax_C3: np.ndarray = None, # peak maximum carboxylation rate for C3 plants
|
|
88
|
+
peakVCmax_C4: np.ndarray = None, # peak maximum carboxylation rate for C4 plants
|
|
89
|
+
CI: Union[Raster, np.ndarray] = None,
|
|
90
|
+
resampling: str = RESAMPLING): # clumping index
|
|
91
|
+
if geometry is None and isinstance(ST_C, Raster):
|
|
92
|
+
geometry = ST_C.geometry
|
|
93
|
+
|
|
94
|
+
if GEOS5FP_connection is None:
|
|
95
|
+
GEOS5FP_connection = GEOS5FP()
|
|
96
|
+
|
|
97
|
+
if (day_of_year is None or hour_of_day is None) and time_UTC is not None and geometry is not None:
|
|
98
|
+
day_of_year = solar_day_of_year_for_area(time_UTC=time_UTC, geometry=geometry)
|
|
99
|
+
hour_of_day = solar_hour_of_day_for_area(time_UTC=time_UTC, geometry=geometry)
|
|
100
|
+
|
|
101
|
+
if time_UTC is None and day_of_year is None and hour_of_day is None:
|
|
102
|
+
raise ValueError("no time given between time_UTC, day_of_year, and hour_of_day")
|
|
103
|
+
|
|
104
|
+
if elevation_km is None and geometry is not None:
|
|
105
|
+
elevation_km = NASADEM.elevation_km(geometry=geometry)
|
|
106
|
+
|
|
107
|
+
# load air temperature in Celsius if not provided
|
|
108
|
+
if Ta_C is None:
|
|
109
|
+
Ta_C = GEOS5FP_connection.Ta_C(time_UTC=time_UTC, geometry=geometry, resampling=resampling)
|
|
110
|
+
|
|
111
|
+
# load relative humidity if not provided
|
|
112
|
+
if RH is None:
|
|
113
|
+
RH = GEOS5FP_connection.RH(time_UTC=time_UTC, geometry=geometry, resampling=resampling)
|
|
114
|
+
|
|
115
|
+
# load minimum NDVI if not provided
|
|
116
|
+
if NDVI_minimum is None and geometry is not None:
|
|
117
|
+
NDVI_minimum = load_NDVI_minimum(geometry=geometry, resampling=resampling)
|
|
118
|
+
|
|
119
|
+
# load maximum NDVI if not provided
|
|
120
|
+
if NDVI_maximum is None and geometry is not None:
|
|
121
|
+
NDVI_maximum = load_NDVI_maximum(geometry=geometry, resampling=resampling)
|
|
122
|
+
|
|
123
|
+
# load C4 fraction if not provided
|
|
124
|
+
if C4_fraction is None:
|
|
125
|
+
C4_fraction = load_C4_fraction(geometry=geometry, resampling=resampling)
|
|
126
|
+
|
|
127
|
+
# load carbon uptake efficiency if not provided
|
|
128
|
+
if carbon_uptake_efficiency is None:
|
|
129
|
+
carbon_uptake_efficiency = load_carbon_uptake_efficiency(geometry=geometry, resampling=resampling)
|
|
130
|
+
|
|
131
|
+
# load kn if not provided
|
|
132
|
+
if kn is None:
|
|
133
|
+
kn = load_kn(geometry=geometry, resampling=resampling)
|
|
134
|
+
|
|
135
|
+
# load peak VC max for C3 plants if not provided
|
|
136
|
+
if peakVCmax_C3 is None:
|
|
137
|
+
peakVCmax_C3 = load_peakVCmax_C3(geometry=geometry, resampling=resampling)
|
|
138
|
+
|
|
139
|
+
# load peak VC max for C4 plants if not provided
|
|
140
|
+
if peakVCmax_C4 is None:
|
|
141
|
+
peakVCmax_C4 = load_peakVCmax_C4(geometry=geometry, resampling=resampling)
|
|
142
|
+
|
|
143
|
+
# load Ball-Berry slope for C3 plants if not provided
|
|
144
|
+
if ball_berry_slope_C3 is None:
|
|
145
|
+
ball_berry_slope_C3 = load_ball_berry_slope_C3(geometry=geometry, resampling=resampling)
|
|
146
|
+
|
|
147
|
+
# load Ball-Berry slope for C4 plants if not provided
|
|
148
|
+
if ball_berry_slope_C4 is None:
|
|
149
|
+
ball_berry_slope_C4 = load_ball_berry_slope_C4(geometry=geometry, resampling=resampling)
|
|
150
|
+
|
|
151
|
+
# load Ball-Berry intercept for C3 plants if not provided
|
|
152
|
+
if ball_berry_intercept_C3 is None:
|
|
153
|
+
ball_berry_intercept_C3 = load_ball_berry_intercept_C3(geometry=geometry, resampling=resampling)
|
|
154
|
+
|
|
155
|
+
# Create a dictionary of variables to check
|
|
156
|
+
variables_to_check = {
|
|
157
|
+
"Rg": Rg,
|
|
158
|
+
"VISdiff": VISdiff,
|
|
159
|
+
"VISdir": VISdir,
|
|
160
|
+
"NIRdiff": NIRdiff,
|
|
161
|
+
"NIRdir": NIRdir,
|
|
162
|
+
"UV": UV,
|
|
163
|
+
"albedo_visible": albedo_visible,
|
|
164
|
+
"albedo_NIR": albedo_NIR
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
# Check for None values and size mismatches
|
|
168
|
+
reference_size = None
|
|
169
|
+
for name, var in variables_to_check.items():
|
|
170
|
+
if var is None:
|
|
171
|
+
logger.warning(f"Variable '{name}' is None.")
|
|
172
|
+
else:
|
|
173
|
+
# Get the size of the variable if it's a numpy array
|
|
174
|
+
size = var.shape if isinstance(var, np.ndarray) else None
|
|
175
|
+
if reference_size is None:
|
|
176
|
+
reference_size = size # Set the first non-None size as the reference
|
|
177
|
+
elif size != reference_size:
|
|
178
|
+
logger.warning(f"Variable '{name}' has a different size: {size} (expected: {reference_size}).")
|
|
179
|
+
|
|
180
|
+
# check if any of the FLiES outputs are not given
|
|
181
|
+
if None in (Rg, VISdiff, VISdir, NIRdiff, NIRdir, UV, albedo_visible, albedo_NIR):
|
|
182
|
+
# load cloud optical thickness if not provided
|
|
183
|
+
if COT is None:
|
|
184
|
+
COT = GEOS5FP_connection.COT(time_UTC=time_UTC, geometry=geometry, resampling=resampling)
|
|
185
|
+
|
|
186
|
+
# load aerosol optical thickness if not provided
|
|
187
|
+
if AOT is None:
|
|
188
|
+
AOT = GEOS5FP_connection.AOT(time_UTC=time_UTC, geometry=geometry, resampling=resampling)
|
|
189
|
+
|
|
190
|
+
## FIXME fix FLiES interface
|
|
191
|
+
|
|
192
|
+
# run FLiES radiative transfer model
|
|
193
|
+
FLiES_results = FLiESANN(
|
|
194
|
+
time_UTC=time_UTC,
|
|
195
|
+
day_of_year=day_of_year,
|
|
196
|
+
hour_of_day=hour_of_day,
|
|
197
|
+
geometry=geometry,
|
|
198
|
+
albedo=albedo,
|
|
199
|
+
COT=COT,
|
|
200
|
+
AOT=AOT,
|
|
201
|
+
vapor_gccm=vapor_gccm,
|
|
202
|
+
ozone_cm=ozone_cm,
|
|
203
|
+
elevation_km=elevation_km,
|
|
204
|
+
SZA=SZA,
|
|
205
|
+
KG_climate=KG_climate,
|
|
206
|
+
GEOS5FP_connection=GEOS5FP_connection
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
# extract FLiES outputs
|
|
210
|
+
Rg = FLiES_results["Rg"]
|
|
211
|
+
VISdiff = FLiES_results["VISdiff"]
|
|
212
|
+
VISdir = FLiES_results["VISdir"]
|
|
213
|
+
NIRdiff = FLiES_results["NIRdiff"]
|
|
214
|
+
NIRdir = FLiES_results["NIRdir"]
|
|
215
|
+
UV = FLiES_results["UV"]
|
|
216
|
+
# albedo_visible = FLiES_results["VIS"]
|
|
217
|
+
# albedo_NIR = FLiES_results["NIR"]
|
|
218
|
+
albedo_NWP = GEOS5FP_connection.ALBEDO(time_UTC=time_UTC, geometry=geometry, resampling=resampling)
|
|
219
|
+
RVIS_NWP = GEOS5FP_connection.ALBVISDR(time_UTC=time_UTC, geometry=geometry, resampling=resampling)
|
|
220
|
+
albedo_visible = rt.clip(albedo * (RVIS_NWP / albedo_NWP), 0, 1)
|
|
221
|
+
check_distribution(albedo_visible, "RVIS")
|
|
222
|
+
RNIR_NWP = GEOS5FP_connection.ALBNIRDR(time_UTC=time_UTC, geometry=geometry, resampling=resampling)
|
|
223
|
+
albedo_NIR = rt.clip(albedo * (RNIR_NWP / albedo_NWP), 0, 1)
|
|
224
|
+
check_distribution(albedo_NIR, "RNIR")
|
|
225
|
+
PARDir = VISdir
|
|
226
|
+
check_distribution(PARDir, "PARDir")
|
|
227
|
+
else:
|
|
228
|
+
logger.info("using given FLiES output as BESS parameters")
|
|
229
|
+
|
|
230
|
+
# load koppen geiger climate classification if not provided
|
|
231
|
+
if KG_climate is None:
|
|
232
|
+
KG_climate = load_koppen_geiger(geometry=geometry)
|
|
233
|
+
|
|
234
|
+
# load canopy height in meters if not provided
|
|
235
|
+
if canopy_height_meters is None:
|
|
236
|
+
canopy_height_meters = load_canopy_height(geometry=geometry, resampling=resampling)
|
|
237
|
+
|
|
238
|
+
# load CO2 concentration in ppm if not provided
|
|
239
|
+
if Ca is None:
|
|
240
|
+
Ca = GEOS5FP_connection.CO2SC(time_UTC=time_UTC, geometry=geometry, resampling=resampling)
|
|
241
|
+
|
|
242
|
+
# load wind speed in meters per second if not provided
|
|
243
|
+
if wind_speed_mps is None:
|
|
244
|
+
wind_speed_mps = GEOS5FP_connection.wind_speed(time_UTC=time_UTC, geometry=geometry, resampling=resampling)
|
|
245
|
+
|
|
246
|
+
# canopy temperature defaults to surface temperature
|
|
247
|
+
if canopy_temperature_C is None:
|
|
248
|
+
canopy_temperature_C = ST_C
|
|
249
|
+
|
|
250
|
+
# soil temperature defaults to surface temperature
|
|
251
|
+
if soil_temperature_C is None:
|
|
252
|
+
soil_temperature_C = ST_C
|
|
253
|
+
|
|
254
|
+
# visible albedo defaults to surface albedo
|
|
255
|
+
if albedo_visible is None:
|
|
256
|
+
albedo_visible = albedo
|
|
257
|
+
|
|
258
|
+
# near-infrared albedo defaults to surface albedo
|
|
259
|
+
if albedo_NIR is None:
|
|
260
|
+
albedo_NIR = albedo
|
|
261
|
+
|
|
262
|
+
# calculate solar zenith angle if not provided
|
|
263
|
+
if SZA is None:
|
|
264
|
+
SZA = calculate_SZA_from_DOY_and_hour(geometry.lat, geometry.lon, day_of_year, hour_of_day)
|
|
265
|
+
|
|
266
|
+
if CI is None and geometry is not None:
|
|
267
|
+
modisci = MODISCI()
|
|
268
|
+
CI = modisci.CI(geometry=geometry, resampling=resampling)
|
|
269
|
+
|
|
270
|
+
# canopy height defaults to zero
|
|
271
|
+
canopy_height_meters = np.where(np.isnan(canopy_height_meters), 0, canopy_height_meters)
|
|
272
|
+
|
|
273
|
+
# calculate saturation vapor pressure in Pascal from air temperature in Kelvin
|
|
274
|
+
Ta_K = Ta_C + 273.15
|
|
275
|
+
SVP_Pa = SVP_Pa_from_Ta_K(Ta_K)
|
|
276
|
+
|
|
277
|
+
# calculate actual vapor pressure in Pascal from relative humidity and saturation vapor pressure
|
|
278
|
+
Ea_Pa = RH * SVP_Pa
|
|
279
|
+
|
|
280
|
+
# convert elevation to meters
|
|
281
|
+
elevation_m = elevation_km * 1000
|
|
282
|
+
|
|
283
|
+
latitude = geometry.lat
|
|
284
|
+
|
|
285
|
+
Ps_Pa, VPD_Pa, RH, desTa, ddesTa, gamma, Cp, rhoa, epsa, R, Rc, Rs, SFd, SFd2, DL, Ra, fStress = meteorology(
|
|
286
|
+
day_of_year=day_of_year,
|
|
287
|
+
hour_of_day=hour_of_day,
|
|
288
|
+
latitude=latitude,
|
|
289
|
+
elevation_m=elevation_m,
|
|
290
|
+
SZA=SZA,
|
|
291
|
+
Ta_K=Ta_K,
|
|
292
|
+
Ea_Pa=Ea_Pa,
|
|
293
|
+
Rg=Rg,
|
|
294
|
+
wind_speed_mps=wind_speed_mps,
|
|
295
|
+
canopy_height_meters=canopy_height_meters
|
|
296
|
+
)
|
|
297
|
+
|
|
298
|
+
meteorology_outputs = {
|
|
299
|
+
"Ps_Pa": Ps_Pa,
|
|
300
|
+
"VPD_Pa": VPD_Pa,
|
|
301
|
+
"RH": RH,
|
|
302
|
+
"desTa": desTa,
|
|
303
|
+
"ddesTa": ddesTa,
|
|
304
|
+
"gamma": gamma,
|
|
305
|
+
"Cp": Cp,
|
|
306
|
+
"rhoa": rhoa,
|
|
307
|
+
"epsa": epsa,
|
|
308
|
+
"R": R,
|
|
309
|
+
"Rc": Rc,
|
|
310
|
+
"Rs": Rs,
|
|
311
|
+
"SFd": SFd,
|
|
312
|
+
"SFd2": SFd2,
|
|
313
|
+
"DL": DL,
|
|
314
|
+
"Ra": Ra,
|
|
315
|
+
"fStress": fStress
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
# Check the distribution for each variable
|
|
319
|
+
for var_name, var_value in meteorology_outputs.items():
|
|
320
|
+
check_distribution(var_value, var_name, time_UTC)
|
|
321
|
+
|
|
322
|
+
# convert NDVI to LAI
|
|
323
|
+
LAI = LAI_from_NDVI(NDVI)
|
|
324
|
+
LAI_minimum = LAI_from_NDVI(NDVI_minimum)
|
|
325
|
+
LAI_maximum = LAI_from_NDVI(NDVI_maximum)
|
|
326
|
+
|
|
327
|
+
VCmax_C3_sunlit, VCmax_C4_sunlit, VCmax_C3_shaded, VCmax_C4_shaded = calculate_VCmax(
|
|
328
|
+
LAI=LAI,
|
|
329
|
+
LAI_minimum=LAI_minimum,
|
|
330
|
+
LAI_maximum=LAI_maximum,
|
|
331
|
+
peakVCmax_C3=peakVCmax_C3,
|
|
332
|
+
peakVCmax_C4=peakVCmax_C4,
|
|
333
|
+
SZA=SZA,
|
|
334
|
+
kn=kn
|
|
335
|
+
)
|
|
336
|
+
|
|
337
|
+
# List of variable names and their corresponding values
|
|
338
|
+
VCmax_outputs = {
|
|
339
|
+
"VCmax_C3_sunlit": VCmax_C3_sunlit,
|
|
340
|
+
"VCmax_C4_sunlit": VCmax_C4_sunlit,
|
|
341
|
+
"VCmax_C3_shaded": VCmax_C3_shaded,
|
|
342
|
+
"VCmax_C4_shaded": VCmax_C4_shaded
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
# Check the distribution for each variable
|
|
346
|
+
for var_name, var_value in VCmax_outputs.items():
|
|
347
|
+
check_distribution(var_value, var_name, time_UTC)
|
|
348
|
+
|
|
349
|
+
sunlit_fraction, APAR_sunlit, APAR_shaded, ASW_sunlit, ASW_shaded, ASW_soil, G = canopy_shortwave_radiation(
|
|
350
|
+
PARDiff=VISdiff, # diffuse photosynthetically active radiation in W/m^2
|
|
351
|
+
PARDir=VISdir, # direct photosynthetically active radiation in W/m^2
|
|
352
|
+
NIRDiff=NIRdiff, # diffuse near-infrared radiation in W/m^2
|
|
353
|
+
NIRDir=NIRdir, # direct near-infrared radiation in W/m^2
|
|
354
|
+
UV=UV, # incoming ultraviolet radiation in W/m^2
|
|
355
|
+
SZA=SZA, # solar zenith angle in degrees
|
|
356
|
+
LAI=LAI, # leaf area index
|
|
357
|
+
CI=CI, # clumping index
|
|
358
|
+
albedo_visible=albedo_visible, # surface albedo in visible wavelengths
|
|
359
|
+
albedo_NIR=albedo_NIR # surface albedo in near-infrared wavelengths
|
|
360
|
+
)
|
|
361
|
+
|
|
362
|
+
# List of variable names and their corresponding values
|
|
363
|
+
canopy_radiation_outputs = {
|
|
364
|
+
"sunlit_fraction": sunlit_fraction,
|
|
365
|
+
"APAR_sunlit": APAR_sunlit,
|
|
366
|
+
"APAR_shaded": APAR_shaded,
|
|
367
|
+
"ASW_sunlit": ASW_sunlit,
|
|
368
|
+
"ASW_shaded": ASW_shaded,
|
|
369
|
+
"ASW_soil": ASW_soil,
|
|
370
|
+
"G": G
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
# Check the distribution for each variable
|
|
374
|
+
for var_name, var_value in canopy_radiation_outputs.items():
|
|
375
|
+
check_distribution(var_value, var_name, time_UTC)
|
|
376
|
+
|
|
377
|
+
canopy_temperature_K = canopy_temperature_C + 273.15
|
|
378
|
+
soil_temperature_K = soil_temperature_C + 273.15
|
|
379
|
+
|
|
380
|
+
GPP_C3, LE_C3, LE_soil_C3, LE_canopy_C3, Rn_C3, Rn_soil_C3, Rn_canopy_C3 = carbon_water_fluxes(
|
|
381
|
+
canopy_temperature_K=canopy_temperature_K, # canopy temperature in Kelvin
|
|
382
|
+
soil_temperature_K=soil_temperature_K, # soil temperature in Kelvin
|
|
383
|
+
LAI=LAI, # leaf area index
|
|
384
|
+
Ta_K=Ta_K, # air temperature in Kelvin
|
|
385
|
+
APAR_sunlit=APAR_sunlit, # sunlit leaf absorptance of photosynthetically active radiation
|
|
386
|
+
APAR_shaded=APAR_shaded, # shaded leaf absorptance of photosynthetically active radiation
|
|
387
|
+
ASW_sunlit=ASW_sunlit, # sunlit absorbed shortwave radiation
|
|
388
|
+
ASW_shaded=ASW_shaded, # shaded absorbed shortwave radiation
|
|
389
|
+
ASW_soil=ASW_soil, # absorbed shortwave radiation of soil
|
|
390
|
+
Vcmax25_sunlit=VCmax_C3_sunlit, # sunlit maximum carboxylation rate at 25 degrees C
|
|
391
|
+
Vcmax25_shaded=VCmax_C3_shaded, # shaded maximum carboxylation rate at 25 degrees C
|
|
392
|
+
ball_berry_slope=ball_berry_slope_C3, # Ball-Berry slope for C3 photosynthesis
|
|
393
|
+
ball_berry_intercept=ball_berry_intercept_C3, # Ball-Berry intercept for C3 photosynthesis
|
|
394
|
+
sunlit_fraction=sunlit_fraction, # fraction of sunlit leaves
|
|
395
|
+
G=G, # soil heat flux
|
|
396
|
+
SZA=SZA, # solar zenith angle
|
|
397
|
+
Ca=Ca, # atmospheric CO2 concentration
|
|
398
|
+
Ps_Pa=Ps_Pa, # surface pressure in Pascal
|
|
399
|
+
gamma=gamma, # psychrometric constant
|
|
400
|
+
Cp=Cp, # specific heat of air in J/kg/K
|
|
401
|
+
rhoa=rhoa, # density of air in kg/m3
|
|
402
|
+
VPD_Pa=VPD_Pa, # vapor pressure deficit in Pascal
|
|
403
|
+
RH=RH, # relative humidity as a fraction
|
|
404
|
+
desTa=desTa,
|
|
405
|
+
ddesTa=ddesTa,
|
|
406
|
+
epsa=epsa,
|
|
407
|
+
Rc=Rc,
|
|
408
|
+
Rs=Rs,
|
|
409
|
+
carbon_uptake_efficiency=carbon_uptake_efficiency, # intrinsic quantum efficiency for carbon uptake
|
|
410
|
+
fStress=fStress,
|
|
411
|
+
C4_photosynthesis=False # C3 or C4 photosynthesis
|
|
412
|
+
)
|
|
413
|
+
|
|
414
|
+
# List of variable names and their corresponding values
|
|
415
|
+
carbon_water_fluxes_outputs = {
|
|
416
|
+
"GPP_C3": GPP_C3,
|
|
417
|
+
"LE_C3": LE_C3,
|
|
418
|
+
"LE_soil_C3": LE_soil_C3,
|
|
419
|
+
"LE_canopy_C3": LE_canopy_C3,
|
|
420
|
+
"Rn_C3": Rn_C3,
|
|
421
|
+
"Rn_soil_C3": Rn_soil_C3,
|
|
422
|
+
"Rn_canopy_C3": Rn_canopy_C3
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
# Check the distribution for each variable
|
|
426
|
+
for var_name, var_value in carbon_water_fluxes_outputs.items():
|
|
427
|
+
check_distribution(var_value, var_name, time_UTC)
|
|
428
|
+
|
|
429
|
+
GPP_C4, LE_C4, LE_soil_C4, LE_canopy_C4, Rn_C4, Rn_soil_C4, Rn_canopy_C4 = carbon_water_fluxes(
|
|
430
|
+
canopy_temperature_K=canopy_temperature_K, # canopy temperature in Kelvin
|
|
431
|
+
soil_temperature_K=soil_temperature_K, # soil temperature in Kelvin
|
|
432
|
+
LAI=LAI, # leaf area index
|
|
433
|
+
Ta_K=Ta_K, # air temperature in Kelvin
|
|
434
|
+
APAR_sunlit=APAR_sunlit, # sunlit leaf absorptance of photosynthetically active radiation
|
|
435
|
+
APAR_shaded=APAR_shaded, # shaded leaf absorptance of photosynthetically active radiation
|
|
436
|
+
ASW_sunlit=ASW_sunlit, # sunlit absorbed shortwave radiation
|
|
437
|
+
ASW_shaded=ASW_shaded, # shaded absorbed shortwave radiation
|
|
438
|
+
ASW_soil=ASW_soil, # absorbed shortwave radiation of soil
|
|
439
|
+
Vcmax25_sunlit=VCmax_C4_sunlit, # sunlit maximum carboxylation rate at 25 degrees C
|
|
440
|
+
Vcmax25_shaded=VCmax_C4_shaded, # shaded maximum carboxylation rate at 25 degrees C
|
|
441
|
+
ball_berry_slope=ball_berry_slope_C4, # Ball-Berry slope for C4 photosynthesis
|
|
442
|
+
ball_berry_intercept=ball_berry_intercept_C4, # Ball-Berry intercept for C4 photosynthesis
|
|
443
|
+
sunlit_fraction=sunlit_fraction, # fraction of sunlit leaves
|
|
444
|
+
G=G, # soil heat flux
|
|
445
|
+
SZA=SZA, # solar zenith angle
|
|
446
|
+
Ca=Ca, # atmospheric CO2 concentration
|
|
447
|
+
Ps_Pa=Ps_Pa, # surface pressure in Pascal
|
|
448
|
+
gamma=gamma, # psychrometric constant
|
|
449
|
+
Cp=Cp, # specific heat of air in J/kg/K
|
|
450
|
+
rhoa=rhoa, # density of air in kg/m3
|
|
451
|
+
VPD_Pa=VPD_Pa, # vapor pressure deficit in Pascal
|
|
452
|
+
RH=RH, # relative humidity as a fraction
|
|
453
|
+
desTa=desTa,
|
|
454
|
+
ddesTa=ddesTa,
|
|
455
|
+
epsa=epsa,
|
|
456
|
+
Rc=Rc,
|
|
457
|
+
Rs=Rs,
|
|
458
|
+
carbon_uptake_efficiency=carbon_uptake_efficiency, # intrinsic quantum efficiency for carbon uptake
|
|
459
|
+
fStress=fStress,
|
|
460
|
+
C4_photosynthesis=True # C3 or C4 photosynthesis
|
|
461
|
+
)
|
|
462
|
+
|
|
463
|
+
# List of variable names and their corresponding values
|
|
464
|
+
carbon_water_fluxes_C4_outputs = {
|
|
465
|
+
"GPP_C4": GPP_C4,
|
|
466
|
+
"LE_C4": LE_C4,
|
|
467
|
+
"LE_soil_C4": LE_soil_C4,
|
|
468
|
+
"LE_canopy_C4": LE_canopy_C4,
|
|
469
|
+
"Rn_C4": Rn_C4,
|
|
470
|
+
"Rn_soil_C4": Rn_soil_C4,
|
|
471
|
+
"Rn_canopy_C4": Rn_canopy_C4
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
# Check the distribution for each variable
|
|
475
|
+
for var_name, var_value in carbon_water_fluxes_C4_outputs.items():
|
|
476
|
+
check_distribution(var_value, var_name, time_UTC)
|
|
477
|
+
|
|
478
|
+
# interpolate C3 and C4 GPP
|
|
479
|
+
ST_K = ST_C + 273.15
|
|
480
|
+
GPP = np.clip(interpolate_C3_C4(GPP_C3, GPP_C4, C4_fraction), 0, 50)
|
|
481
|
+
GPP = np.where(np.isnan(ST_K), np.nan, GPP)
|
|
482
|
+
|
|
483
|
+
if isinstance(geometry, RasterGeometry):
|
|
484
|
+
GPP = Raster(GPP, geometry=geometry)
|
|
485
|
+
|
|
486
|
+
# upscale from instantaneous to daily
|
|
487
|
+
|
|
488
|
+
# upscale GPP to daily
|
|
489
|
+
GPP_daily = 1800 * GPP / SFd * 1e-6 * 12 # Eq. (3) in Ryu et al 2008
|
|
490
|
+
GPP_daily = np.where(SFd < 0.01, 0, GPP_daily)
|
|
491
|
+
GPP_daily = np.where(SZA >= 90, 0, GPP_daily)
|
|
492
|
+
|
|
493
|
+
# interpolate C3 and C4 net radiation
|
|
494
|
+
Rn = np.clip(interpolate_C3_C4(Rn_C3, Rn_C4, C4_fraction), 0, 1000)
|
|
495
|
+
|
|
496
|
+
# interpolate C3 and C4 soil net radiation
|
|
497
|
+
Rn_soil = np.clip(interpolate_C3_C4(Rn_soil_C3, Rn_soil_C4, C4_fraction), 0, 1000)
|
|
498
|
+
|
|
499
|
+
# interpolate C3 and C4 canopy net radiation
|
|
500
|
+
Rn_canopy = np.clip(interpolate_C3_C4(Rn_canopy_C3, Rn_canopy_C4, C4_fraction), 0, 1000)
|
|
501
|
+
|
|
502
|
+
# interpolate C3 and C4 latent heat flux
|
|
503
|
+
LE = np.clip(interpolate_C3_C4(LE_C3, LE_C4, C4_fraction), 0, 1000)
|
|
504
|
+
|
|
505
|
+
# interpolate C3 and C4 soil latent heat flux
|
|
506
|
+
LE_soil = np.clip(interpolate_C3_C4(LE_soil_C3, LE_soil_C4, C4_fraction), 0, 1000)
|
|
507
|
+
|
|
508
|
+
# interpolate C3 and C4 canopy latent heat flux
|
|
509
|
+
LE_canopy = np.clip(interpolate_C3_C4(LE_canopy_C3, LE_canopy_C4, C4_fraction), 0, 1000)
|
|
510
|
+
|
|
511
|
+
return {
|
|
512
|
+
"GPP": GPP,
|
|
513
|
+
"GPP_daily": GPP_daily,
|
|
514
|
+
"Rn": Rn,
|
|
515
|
+
"Rn_soil": Rn_soil,
|
|
516
|
+
"Rn_canopy": Rn_canopy,
|
|
517
|
+
"LE": LE,
|
|
518
|
+
"LE_soil": LE_soil,
|
|
519
|
+
"LE_canopy": LE_canopy
|
|
520
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
import rasters as rt
|
|
5
|
+
from dateutil import parser
|
|
6
|
+
from pandas import DataFrame
|
|
7
|
+
|
|
8
|
+
from .model import BESS_JPL
|
|
9
|
+
|
|
10
|
+
logger = logging.getLogger(__name__)
|
|
11
|
+
|
|
12
|
+
def process_BESS_table(input_df: DataFrame) -> DataFrame:
|
|
13
|
+
ST_C = np.array(input_df.ST_C).astype(np.float64)
|
|
14
|
+
NDVI = np.array(input_df.NDVI).astype(np.float64)
|
|
15
|
+
|
|
16
|
+
NDVI = np.where(NDVI > 0.06, NDVI, np.nan).astype(np.float64)
|
|
17
|
+
|
|
18
|
+
albedo = np.array(input_df.albedo).astype(np.float64)
|
|
19
|
+
|
|
20
|
+
if "Ta_C" in input_df:
|
|
21
|
+
Ta_C = np.array(input_df.Ta_C).astype(np.float64)
|
|
22
|
+
elif "Ta" in input_df:
|
|
23
|
+
Ta_C = np.array(input_df.Ta).astype(np.float64)
|
|
24
|
+
|
|
25
|
+
RH = np.array(input_df.RH).astype(np.float64)
|
|
26
|
+
# Rn = np.array(input_df.Rn).astype(np.float64)
|
|
27
|
+
# Topt = np.array(input_df.Topt).astype(np.float64)
|
|
28
|
+
# fAPARmax = np.array(input_df.fAPARmax).astype(np.float64)
|
|
29
|
+
|
|
30
|
+
# fAPARmax = np.where(fAPARmax == 0, np.nan, fAPARmax).astype(np.float64)
|
|
31
|
+
|
|
32
|
+
# if "G" in input_df:
|
|
33
|
+
# G = np.array(input_df.G).astype(np.float64)
|
|
34
|
+
# else:
|
|
35
|
+
# G = calculate_SEBAL_soil_heat_flux(
|
|
36
|
+
# Rn=Rn,
|
|
37
|
+
# ST_C=ST_C,
|
|
38
|
+
# NDVI=NDVI,
|
|
39
|
+
# albedo=albedo
|
|
40
|
+
# ).astype(np.float64)
|
|
41
|
+
|
|
42
|
+
results = BESS_JPL(
|
|
43
|
+
ST_C=ST_C,
|
|
44
|
+
albedo=albedo,
|
|
45
|
+
NDVI=NDVI,
|
|
46
|
+
Ta_C=Ta_C,
|
|
47
|
+
RH=RH
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
output_df = input_df.copy()
|
|
51
|
+
|
|
52
|
+
for key, value in results.items():
|
|
53
|
+
output_df[key] = value
|
|
54
|
+
|
|
55
|
+
return output_df
|
BESS_JPL/version.txt
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
1.
|
|
1
|
+
1.10.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: BESS-JPL
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.10.0
|
|
4
4
|
Summary: Breathing Earth System Simulator (BESS) Gross Primary Production (GPP) and Evapotranspiration (ET) Model Python
|
|
5
5
|
Author-email: Gregory Halverson <gregory.h.halverson@jpl.nasa.gov>
|
|
6
6
|
Project-URL: Homepage, https://github.com/JPL-Evapotranspiration-Algorithms/BESS-JPL
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
BESS_JPL/BESS_JPL.py,sha256=
|
|
1
|
+
BESS_JPL/BESS_JPL.py,sha256=CTby93_HwhONe2NOlt-8DuqDH7jL9mAc3euuzbouANg,1365
|
|
2
2
|
BESS_JPL/C3_photosynthesis.py,sha256=-ormDycaWttCOoYJdOoOV_zlM6n0nxkgXxj7fyH_mIs,2760
|
|
3
3
|
BESS_JPL/C4_fraction.jpeg,sha256=ECaEYWA8MnNd5z0Yq3beeUCR93KtTDxM8MrH-YYon3Y,2746
|
|
4
4
|
BESS_JPL/C4_fraction.tif,sha256=DFS-J08JCjnf0hi_T_dFridAegVTiU3FGyMBjS9yc1w,25446
|
|
@@ -38,14 +38,16 @@ BESS_JPL/load_kn.py,sha256=_IE7w_VfahubfqjvgE6F6HCO0SizcpMu104_7ZXOiaw,345
|
|
|
38
38
|
BESS_JPL/load_peakVCmax_C3.py,sha256=ISaCyaN81F3CyYbYwUqvUfQ_vjn4_jCpt1_x_b4fY5o,365
|
|
39
39
|
BESS_JPL/load_peakVCmax_C4.py,sha256=8vtjEiJKCqSK04DfTs8Zgn-rWwGucmeeLMzblLT1U-Y,365
|
|
40
40
|
BESS_JPL/meteorology.py,sha256=xIPQnIk9wGJPy8esJyxn35d6c_7UyiNuWTJXDnuSwf8,6995
|
|
41
|
+
BESS_JPL/model.py,sha256=sJ_CkZ98h-5HDpAGUJnyTpUODDlTTgc_8s5Ib8Kz-90,22295
|
|
41
42
|
BESS_JPL/peakVCmax_C3.jpeg,sha256=nVvwLx8JyRhtm5lWRW93HLz0mInshEdOCJ1tAdcFqa8,1006133
|
|
42
43
|
BESS_JPL/peakVCmax_C3.tif,sha256=ax6wCOPc_ovgJJl9YRjPWNY13OCGlzs2djXqwob_U7A,1583598
|
|
43
44
|
BESS_JPL/peakVCmax_C4.jpeg,sha256=s7dhpcD573KW9Se4mejDeSzbSHqPtQY2EL6KJKt7ZIo,961497
|
|
44
45
|
BESS_JPL/peakVCmax_C4.tif,sha256=EST4_yy-HHYmazIv--RePL_bhLejMWql6hoV9EE38ok,1556928
|
|
46
|
+
BESS_JPL/process_BESS_table.py,sha256=TYsDEZNELGdUc0xkB1MRQIDkVonNL5d49q7Zl1iaJvo,1472
|
|
45
47
|
BESS_JPL/soil_energy_balance.py,sha256=5TKDVkKYJ8jhjuiwbRva_03fi_0gTM0IAKbSm4WhWnY,944
|
|
46
|
-
BESS_JPL/version.txt,sha256=
|
|
47
|
-
bess_jpl-1.
|
|
48
|
-
bess_jpl-1.
|
|
49
|
-
bess_jpl-1.
|
|
50
|
-
bess_jpl-1.
|
|
51
|
-
bess_jpl-1.
|
|
48
|
+
BESS_JPL/version.txt,sha256=6R3uO0EpIuVteI11fNMOqq6SsIRjI6vbme61i5z-MME,6
|
|
49
|
+
bess_jpl-1.10.0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
50
|
+
bess_jpl-1.10.0.dist-info/METADATA,sha256=PM7zyAhRude_y8P-nnEQTsPB_Y5WaOD8xKmT2oHr3wg,6340
|
|
51
|
+
bess_jpl-1.10.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
52
|
+
bess_jpl-1.10.0.dist-info/top_level.txt,sha256=GaKnzt-BBktYn1o-w4Qzh_jHxse4Y3ACOxZQrB2ufhc,9
|
|
53
|
+
bess_jpl-1.10.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|