BESS-JPL 1.26.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.
- BESS_JPL/BESS_JPL.py +54 -0
- BESS_JPL/C3_photosynthesis.py +165 -0
- BESS_JPL/C4_fraction.jpeg +0 -0
- BESS_JPL/C4_fraction.tif +0 -0
- BESS_JPL/C4_fraction.tif.aux.xml +11 -0
- BESS_JPL/C4_photosynthesis.py +133 -0
- BESS_JPL/ECOv002-cal-val-BESS-JPL-GEOS5FP-inputs.csv +1066 -0
- BESS_JPL/ECOv002-cal-val-BESS-JPL-inputs.csv +1066 -0
- BESS_JPL/ECOv002-cal-val-BESS-JPL-outputs.csv +1066 -0
- BESS_JPL/ECOv002-cal-val-FLiESANN-inputs.csv +1066 -0
- BESS_JPL/ECOv002-static-tower-BESS-JPL-inputs.csv +122 -0
- BESS_JPL/ECOv002_calval_BESS_inputs.py +30 -0
- BESS_JPL/ECOv002_static_tower_BESS_inputs.py +19 -0
- BESS_JPL/FVC_from_NDVI.py +22 -0
- BESS_JPL/LAI_from_NDVI.py +28 -0
- BESS_JPL/NDVI_maximum.jpeg +0 -0
- BESS_JPL/NDVI_maximum.tif +0 -0
- BESS_JPL/NDVI_minimum.jpeg +0 -0
- BESS_JPL/NDVI_minimum.tif +0 -0
- BESS_JPL/__init__.py +5 -0
- BESS_JPL/ball_berry_intercept_C3.jpeg +0 -0
- BESS_JPL/ball_berry_intercept_C3.tif +0 -0
- BESS_JPL/ball_berry_slope_C3.jpeg +0 -0
- BESS_JPL/ball_berry_slope_C3.tif +0 -0
- BESS_JPL/ball_berry_slope_C4.jpeg +0 -0
- BESS_JPL/ball_berry_slope_C4.tif +0 -0
- BESS_JPL/calculate_VCmax.py +90 -0
- BESS_JPL/calculate_bulk_aerodynamic_resistance.py +119 -0
- BESS_JPL/calculate_friction_velocity.py +111 -0
- BESS_JPL/canopy_energy_balance.py +110 -0
- BESS_JPL/canopy_longwave_radiation.py +117 -0
- BESS_JPL/canopy_shortwave_radiation.py +276 -0
- BESS_JPL/carbon_uptake_efficiency.jpeg +0 -0
- BESS_JPL/carbon_uptake_efficiency.tif +0 -0
- BESS_JPL/carbon_water_fluxes.py +313 -0
- BESS_JPL/colors.py +33 -0
- BESS_JPL/constants.py +25 -0
- BESS_JPL/exceptions.py +3 -0
- BESS_JPL/generate_BESS_GEOS5FP_inputs.py +58 -0
- BESS_JPL/generate_BESS_inputs_table.py +186 -0
- BESS_JPL/generate_input_dataset.py +243 -0
- BESS_JPL/generate_output_dataset.py +26 -0
- BESS_JPL/interpolate_C3_C4.py +12 -0
- BESS_JPL/kn.jpeg +0 -0
- BESS_JPL/kn.tif +0 -0
- BESS_JPL/load_C4_fraction.py +20 -0
- BESS_JPL/load_NDVI_maximum.py +17 -0
- BESS_JPL/load_NDVI_minimum.py +17 -0
- BESS_JPL/load_ball_berry_intercept_C3.py +10 -0
- BESS_JPL/load_ball_berry_slope_C3.py +10 -0
- BESS_JPL/load_ball_berry_slope_C4.py +10 -0
- BESS_JPL/load_carbon_uptake_efficiency.py +10 -0
- BESS_JPL/load_kn.py +10 -0
- BESS_JPL/load_peakVCmax_C3.py +12 -0
- BESS_JPL/load_peakVCmax_C4.py +12 -0
- BESS_JPL/meteorology.py +429 -0
- BESS_JPL/model.py +594 -0
- BESS_JPL/peakVCmax_C3.jpeg +0 -0
- BESS_JPL/peakVCmax_C3.tif +0 -0
- BESS_JPL/peakVCmax_C4.jpeg +0 -0
- BESS_JPL/peakVCmax_C4.tif +0 -0
- BESS_JPL/process_BESS_table.py +365 -0
- BESS_JPL/process_paw_and_gao_LE.py +50 -0
- BESS_JPL/retrieve_BESS_JPL_GEOS5FP_inputs.py +257 -0
- BESS_JPL/retrieve_BESS_inputs.py +279 -0
- BESS_JPL/soil_energy_balance.py +35 -0
- BESS_JPL/verify.py +127 -0
- BESS_JPL/version.py +3 -0
- bess_jpl-1.26.0.dist-info/METADATA +102 -0
- bess_jpl-1.26.0.dist-info/RECORD +73 -0
- bess_jpl-1.26.0.dist-info/WHEEL +5 -0
- bess_jpl-1.26.0.dist-info/licenses/LICENSE +201 -0
- bess_jpl-1.26.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,279 @@
|
|
|
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 calculate_solar_day_of_year, calculate_solar_hour_of_day
|
|
13
|
+
from koppengeiger import load_koppen_geiger
|
|
14
|
+
from gedi_canopy_height import load_canopy_height, GEDI_DOWNLOAD_DIRECTORY
|
|
15
|
+
from FLiESANN import FLiESANN
|
|
16
|
+
from GEOS5FP import GEOS5FP
|
|
17
|
+
from MODISCI import MODISCI
|
|
18
|
+
from NASADEM import NASADEMConnection
|
|
19
|
+
|
|
20
|
+
from .constants import *
|
|
21
|
+
from .exceptions import *
|
|
22
|
+
from .colors import *
|
|
23
|
+
from .C3_photosynthesis import *
|
|
24
|
+
from .C4_photosynthesis import *
|
|
25
|
+
from .canopy_energy_balance import *
|
|
26
|
+
from .canopy_longwave_radiation import *
|
|
27
|
+
from .canopy_shortwave_radiation import *
|
|
28
|
+
from .carbon_water_fluxes import *
|
|
29
|
+
from .FVC_from_NDVI import *
|
|
30
|
+
from .interpolate_C3_C4 import *
|
|
31
|
+
from .LAI_from_NDVI import *
|
|
32
|
+
from .load_C4_fraction import *
|
|
33
|
+
from .load_carbon_uptake_efficiency import *
|
|
34
|
+
from .load_kn import *
|
|
35
|
+
from .load_NDVI_minimum import *
|
|
36
|
+
from .load_NDVI_maximum import *
|
|
37
|
+
from .load_peakVCmax_C3 import *
|
|
38
|
+
from .load_peakVCmax_C4 import *
|
|
39
|
+
from .load_ball_berry_intercept_C3 import *
|
|
40
|
+
from .load_ball_berry_slope_C3 import *
|
|
41
|
+
from .load_ball_berry_slope_C4 import *
|
|
42
|
+
from .calculate_VCmax import *
|
|
43
|
+
from .meteorology import *
|
|
44
|
+
from .soil_energy_balance import *
|
|
45
|
+
from .retrieve_BESS_JPL_GEOS5FP_inputs import retrieve_BESS_JPL_GEOS5FP_inputs
|
|
46
|
+
|
|
47
|
+
logger = logging.getLogger(__name__)
|
|
48
|
+
|
|
49
|
+
def retrieve_BESS_inputs(ST_C: Union[Raster, np.ndarray], # surface temperature in Celsius
|
|
50
|
+
NDVI: Union[Raster, np.ndarray], # NDVI
|
|
51
|
+
albedo: Union[Raster, np.ndarray], # surface albedo
|
|
52
|
+
geometry: RasterGeometry = None,
|
|
53
|
+
time_UTC: datetime = None,
|
|
54
|
+
hour_of_day: np.ndarray = None,
|
|
55
|
+
day_of_year: np.ndarray = None,
|
|
56
|
+
GEOS5FP_connection: GEOS5FP = None,
|
|
57
|
+
elevation_m: Union[Raster, np.ndarray] = None, # elevation in meters
|
|
58
|
+
Ta_C: Union[Raster, np.ndarray] = None, # air temperature in Celsius
|
|
59
|
+
RH: Union[Raster, np.ndarray] = None, # relative humidity as a proportion
|
|
60
|
+
NDVI_minimum: Union[Raster, np.ndarray] = None, # minimum NDVI
|
|
61
|
+
NDVI_maximum: Union[Raster, np.ndarray] = None, # maximum NDVI
|
|
62
|
+
PAR_albedo: Union[Raster, np.ndarray] = None, # surface albedo in visible wavelengths (initialized to surface albedo if left as None)
|
|
63
|
+
NIR_albedo: Union[Raster, np.ndarray] = None, # surface albedo in near-infrared wavelengths (initialized to surface albedo if left as None)
|
|
64
|
+
COT: Union[Raster, np.ndarray] = None, # cloud optical thickness
|
|
65
|
+
AOT: Union[Raster, np.ndarray] = None, # aerosol optical thickness
|
|
66
|
+
vapor_gccm: Union[Raster, np.ndarray] = None, # water vapor in g/ccm
|
|
67
|
+
ozone_cm: Union[Raster, np.ndarray] = None, # ozone in cm
|
|
68
|
+
KG_climate: Union[Raster, np.ndarray] = None, # KG climate
|
|
69
|
+
canopy_height_meters: Union[Raster, np.ndarray] = None, # canopy height in meters
|
|
70
|
+
Ca: Union[Raster, np.ndarray] = None, # atmospheric CO2 concentration in ppm
|
|
71
|
+
wind_speed_mps: Union[Raster, np.ndarray] = None, # wind speed in meters per second
|
|
72
|
+
SZA_deg: Union[Raster, np.ndarray] = None, # solar zenith angle in degrees
|
|
73
|
+
canopy_temperature_C: Union[Raster, np.ndarray] = None, # canopy temperature in Celsius (initialized to surface temperature if left as None)
|
|
74
|
+
soil_temperature_C: Union[Raster, np.ndarray] = None, # soil temperature in Celsius (initialized to surface temperature if left as None)
|
|
75
|
+
C4_fraction: Union[Raster, np.ndarray] = None, # fraction of C4 plants
|
|
76
|
+
carbon_uptake_efficiency: Union[Raster, np.ndarray] = None, # intrinsic quantum efficiency for carbon uptake
|
|
77
|
+
kn: np.ndarray = None,
|
|
78
|
+
ball_berry_intercept_C3: np.ndarray = None, # Ball-Berry intercept for C3 plants
|
|
79
|
+
ball_berry_intercept_C4: Union[np.ndarray, float] = BALL_BERRY_INTERCEPT_C4, # Ball-Berry intercept for C4 plants
|
|
80
|
+
ball_berry_slope_C3: np.ndarray = None, # Ball-Berry slope for C3 plants
|
|
81
|
+
ball_berry_slope_C4: np.ndarray = None, # Ball-Berry slope for C4 plants
|
|
82
|
+
peakVCmax_C3_μmolm2s1: np.ndarray = None, # peak maximum carboxylation rate for C3 plants
|
|
83
|
+
peakVCmax_C4_μmolm2s1: np.ndarray = None, # peak maximum carboxylation rate for C4 plants
|
|
84
|
+
CI: Union[Raster, np.ndarray] = None,
|
|
85
|
+
C4_fraction_scale_factor: float = C4_FRACTION_SCALE_FACTOR,
|
|
86
|
+
MODISCI_connection: MODISCI = None,
|
|
87
|
+
NASADEM_connection: NASADEMConnection = None,
|
|
88
|
+
resampling: str = RESAMPLING,
|
|
89
|
+
GEDI_download_directory: str = GEDI_DOWNLOAD_DIRECTORY,
|
|
90
|
+
offline_mode: bool = False) -> dict:
|
|
91
|
+
results = {}
|
|
92
|
+
|
|
93
|
+
if (day_of_year is None or hour_of_day is None) and time_UTC is not None and geometry is not None:
|
|
94
|
+
day_of_year = calculate_solar_day_of_year(time_UTC=time_UTC, geometry=geometry)
|
|
95
|
+
hour_of_day = calculate_solar_hour_of_day(time_UTC=time_UTC, geometry=geometry)
|
|
96
|
+
|
|
97
|
+
if time_UTC is None and day_of_year is None and hour_of_day is None:
|
|
98
|
+
raise ValueError("no time given between time_UTC, day_of_year, and hour_of_day")
|
|
99
|
+
|
|
100
|
+
# calculate solar zenith angle if not provided
|
|
101
|
+
if SZA_deg is None:
|
|
102
|
+
SZA_deg = calculate_SZA_from_DOY_and_hour(geometry.lat, geometry.lon, day_of_year, hour_of_day)
|
|
103
|
+
|
|
104
|
+
if isinstance(SZA_deg, np.ndarray):
|
|
105
|
+
# If array contains string representations, convert them first
|
|
106
|
+
if SZA_deg.dtype == object or SZA_deg.dtype.kind in ['U', 'S']:
|
|
107
|
+
# Handle string arrays by converting each element
|
|
108
|
+
# This handles cases like '[71.46303285]' or '71.46303285'
|
|
109
|
+
SZA_deg = np.array([float(str(x).strip('[]')) for x in SZA_deg], dtype=np.float32)
|
|
110
|
+
else:
|
|
111
|
+
# cast SZA_deg numpy array to float32
|
|
112
|
+
SZA_deg = SZA_deg.astype(np.float32)
|
|
113
|
+
|
|
114
|
+
print(type(SZA_deg))
|
|
115
|
+
print(SZA_deg.dtype if isinstance(SZA_deg, np.ndarray) else type(SZA_deg))
|
|
116
|
+
|
|
117
|
+
check_distribution(SZA_deg, "SZA_deg")
|
|
118
|
+
results["SZA_deg"] = SZA_deg
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
if CI is None and geometry is not None:
|
|
122
|
+
if offline_mode:
|
|
123
|
+
raise MissingOfflineParameter("CI not provided in offline mode")
|
|
124
|
+
|
|
125
|
+
if MODISCI_connection is None:
|
|
126
|
+
MODISCI_connection = MODISCI()
|
|
127
|
+
|
|
128
|
+
CI = MODISCI_connection.CI(geometry=geometry, resampling=resampling)
|
|
129
|
+
|
|
130
|
+
check_distribution(CI, "CI")
|
|
131
|
+
results["CI"] = CI
|
|
132
|
+
|
|
133
|
+
if elevation_m is None and geometry is not None:
|
|
134
|
+
if offline_mode:
|
|
135
|
+
raise MissingOfflineParameter("elevation_m not provided in offline mode")
|
|
136
|
+
|
|
137
|
+
if NASADEM_connection is None:
|
|
138
|
+
NASADEM_connection = NASADEMConnection()
|
|
139
|
+
|
|
140
|
+
elevation_m = NASADEM_connection.elevation_m(geometry=geometry)
|
|
141
|
+
|
|
142
|
+
check_distribution(elevation_m, "elevation_m")
|
|
143
|
+
results["elevation_m"] = elevation_m
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
# load minimum NDVI if not provided
|
|
147
|
+
if NDVI_minimum is None and geometry is not None:
|
|
148
|
+
NDVI_minimum = load_NDVI_minimum(geometry=geometry, resampling=resampling)
|
|
149
|
+
|
|
150
|
+
check_distribution(NDVI_minimum, "NDVI_minimum")
|
|
151
|
+
results["NDVI_minimum"] = NDVI_minimum
|
|
152
|
+
|
|
153
|
+
# load maximum NDVI if not provided
|
|
154
|
+
if NDVI_maximum is None and geometry is not None:
|
|
155
|
+
NDVI_maximum = load_NDVI_maximum(geometry=geometry, resampling=resampling)
|
|
156
|
+
|
|
157
|
+
check_distribution(NDVI_maximum, "NDVI_maximum")
|
|
158
|
+
results["NDVI_maximum"] = NDVI_maximum
|
|
159
|
+
|
|
160
|
+
# load C4 fraction if not provided
|
|
161
|
+
if C4_fraction is None:
|
|
162
|
+
C4_fraction = load_C4_fraction(
|
|
163
|
+
geometry=geometry,
|
|
164
|
+
resampling=resampling,
|
|
165
|
+
scale_factor=C4_fraction_scale_factor
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
check_distribution(C4_fraction, "C4_fraction")
|
|
169
|
+
results["C4_fraction"] = C4_fraction
|
|
170
|
+
|
|
171
|
+
# load carbon uptake efficiency if not provided
|
|
172
|
+
if carbon_uptake_efficiency is None:
|
|
173
|
+
carbon_uptake_efficiency = load_carbon_uptake_efficiency(geometry=geometry, resampling=resampling)
|
|
174
|
+
|
|
175
|
+
check_distribution(carbon_uptake_efficiency, "carbon_uptake_efficiency")
|
|
176
|
+
results["carbon_uptake_efficiency"] = carbon_uptake_efficiency
|
|
177
|
+
|
|
178
|
+
# load kn if not provided
|
|
179
|
+
if kn is None:
|
|
180
|
+
kn = load_kn(geometry=geometry, resampling=resampling)
|
|
181
|
+
|
|
182
|
+
check_distribution(kn, "kn")
|
|
183
|
+
results["kn"] = kn
|
|
184
|
+
|
|
185
|
+
# load peak VC max for C3 plants if not provided
|
|
186
|
+
if peakVCmax_C3_μmolm2s1 is None:
|
|
187
|
+
peakVCmax_C3_μmolm2s1 = load_peakVCmax_C3(geometry=geometry, resampling=resampling)
|
|
188
|
+
|
|
189
|
+
check_distribution(peakVCmax_C3_μmolm2s1, "peakVCmax_C3_μmolm2s1")
|
|
190
|
+
results["peakVCmax_C3_μmolm2s1"] = peakVCmax_C3_μmolm2s1
|
|
191
|
+
|
|
192
|
+
# load peak VC max for C4 plants if not provided
|
|
193
|
+
if peakVCmax_C4_μmolm2s1 is None:
|
|
194
|
+
peakVCmax_C4_μmolm2s1 = load_peakVCmax_C4(geometry=geometry, resampling=resampling)
|
|
195
|
+
|
|
196
|
+
check_distribution(peakVCmax_C4_μmolm2s1, "peakVCmax_C4_μmolm2s1")
|
|
197
|
+
results["peakVCmax_C4_μmolm2s1"] = peakVCmax_C4_μmolm2s1
|
|
198
|
+
|
|
199
|
+
# load Ball-Berry slope for C3 plants if not provided
|
|
200
|
+
if ball_berry_slope_C3 is None:
|
|
201
|
+
ball_berry_slope_C3 = load_ball_berry_slope_C3(geometry=geometry, resampling=resampling)
|
|
202
|
+
|
|
203
|
+
check_distribution(ball_berry_slope_C3, "ball_berry_slope_C3")
|
|
204
|
+
results["ball_berry_slope_C3"] = ball_berry_slope_C3
|
|
205
|
+
|
|
206
|
+
# load Ball-Berry slope for C4 plants if not provided
|
|
207
|
+
if ball_berry_slope_C4 is None:
|
|
208
|
+
ball_berry_slope_C4 = load_ball_berry_slope_C4(geometry=geometry, resampling=resampling)
|
|
209
|
+
|
|
210
|
+
check_distribution(ball_berry_slope_C4, "ball_berry_slope_C4")
|
|
211
|
+
results["ball_berry_slope_C4"] = ball_berry_slope_C4
|
|
212
|
+
|
|
213
|
+
# load Ball-Berry intercept for C3 plants if not provided
|
|
214
|
+
if ball_berry_intercept_C3 is None:
|
|
215
|
+
ball_berry_intercept_C3 = load_ball_berry_intercept_C3(geometry=geometry, resampling=resampling)
|
|
216
|
+
|
|
217
|
+
check_distribution(ball_berry_intercept_C3, "ball_berry_intercept_C3")
|
|
218
|
+
results["ball_berry_intercept_C3"] = ball_berry_intercept_C3
|
|
219
|
+
|
|
220
|
+
# load koppen geiger climate classification if not provided
|
|
221
|
+
if KG_climate is None:
|
|
222
|
+
KG_climate = load_koppen_geiger(geometry=geometry)
|
|
223
|
+
|
|
224
|
+
check_distribution(np.float32(KG_climate), "KG_climate")
|
|
225
|
+
results["KG_climate"] = KG_climate
|
|
226
|
+
|
|
227
|
+
# load canopy height in meters if not provided
|
|
228
|
+
if canopy_height_meters is None:
|
|
229
|
+
canopy_height_meters = load_canopy_height(
|
|
230
|
+
geometry=geometry,
|
|
231
|
+
resampling=resampling,
|
|
232
|
+
source_directory=GEDI_download_directory
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
# canopy height defaults to zero
|
|
236
|
+
canopy_height_meters = np.where(np.isnan(canopy_height_meters), 0, canopy_height_meters)
|
|
237
|
+
|
|
238
|
+
check_distribution(canopy_height_meters, "canopy_height_meters")
|
|
239
|
+
results["canopy_height_meters"] = canopy_height_meters
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
# Retrieve GEOS-5 FP inputs if not provided
|
|
243
|
+
GEOS5FP_inputs = retrieve_BESS_JPL_GEOS5FP_inputs(
|
|
244
|
+
time_UTC=time_UTC,
|
|
245
|
+
geometry=geometry,
|
|
246
|
+
albedo=albedo,
|
|
247
|
+
GEOS5FP_connection=GEOS5FP_connection,
|
|
248
|
+
Ta_C=Ta_C,
|
|
249
|
+
RH=RH,
|
|
250
|
+
COT=COT,
|
|
251
|
+
AOT=AOT,
|
|
252
|
+
vapor_gccm=vapor_gccm,
|
|
253
|
+
ozone_cm=ozone_cm,
|
|
254
|
+
PAR_albedo=PAR_albedo,
|
|
255
|
+
NIR_albedo=NIR_albedo,
|
|
256
|
+
Ca=Ca,
|
|
257
|
+
wind_speed_mps=wind_speed_mps,
|
|
258
|
+
resampling=resampling,
|
|
259
|
+
offline_mode=offline_mode
|
|
260
|
+
)
|
|
261
|
+
|
|
262
|
+
# Merge GEOS-5 FP inputs into results dictionary
|
|
263
|
+
results.update(GEOS5FP_inputs)
|
|
264
|
+
|
|
265
|
+
# canopy temperature defaults to surface temperature
|
|
266
|
+
if canopy_temperature_C is None:
|
|
267
|
+
canopy_temperature_C = ST_C
|
|
268
|
+
|
|
269
|
+
check_distribution(canopy_temperature_C, "canopy_temperature_C")
|
|
270
|
+
results["canopy_temperature_C"] = canopy_temperature_C
|
|
271
|
+
|
|
272
|
+
# soil temperature defaults to surface temperature
|
|
273
|
+
if soil_temperature_C is None:
|
|
274
|
+
soil_temperature_C = ST_C
|
|
275
|
+
|
|
276
|
+
check_distribution(soil_temperature_C, "soil_temperature_C")
|
|
277
|
+
results["soil_temperature_C"] = soil_temperature_C
|
|
278
|
+
|
|
279
|
+
return results
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def soil_energy_balance(
|
|
5
|
+
Ts_K: np.ndarray,
|
|
6
|
+
Ta_K: np.ndarray,
|
|
7
|
+
G_Wm2: np.ndarray,
|
|
8
|
+
VPD_Pa: np.ndarray,
|
|
9
|
+
RH: np.ndarray,
|
|
10
|
+
gamma: np.ndarray,
|
|
11
|
+
Cp: np.ndarray,
|
|
12
|
+
rhoa: np.ndarray,
|
|
13
|
+
desTa: np.ndarray,
|
|
14
|
+
Rs: np.ndarray,
|
|
15
|
+
ASW_soil_Wm2: np.ndarray,
|
|
16
|
+
ALW_soil_Wm2: np.ndarray,
|
|
17
|
+
Ls: np.ndarray,
|
|
18
|
+
epsa: np.ndarray):
|
|
19
|
+
# Net radiation
|
|
20
|
+
# Rn = Rnet - Rn_Sun - Rn_Sh
|
|
21
|
+
sigma = 5.670373e-8 # [W m-2 K-4] (Wiki)
|
|
22
|
+
Rn_soil_Wm2 = np.clip(ASW_soil_Wm2 + ALW_soil_Wm2 - Ls - 4.0 * epsa * sigma * (Ta_K ** 3) * (Ts_K - Ta_K), 0, None)
|
|
23
|
+
# G = Rn * 0.35
|
|
24
|
+
|
|
25
|
+
# Latent heat
|
|
26
|
+
LE_soil_Wm2 = desTa / (desTa + gamma) * (Rn_soil_Wm2 - G_Wm2) * (RH ** (VPD_Pa / 1000.0)) # (Ryu et al., 2011)
|
|
27
|
+
LE_soil_Wm2 = np.clip(LE_soil_Wm2, 0, Rn_soil_Wm2)
|
|
28
|
+
# Sensible heat
|
|
29
|
+
H_soil_Wm2 = np.clip(Rn_soil_Wm2 - G_Wm2 - LE_soil_Wm2, 0, Rn_soil_Wm2)
|
|
30
|
+
|
|
31
|
+
# Update temperature
|
|
32
|
+
dT = np.clip(Rs / (rhoa * Cp) * H_soil_Wm2, -20, 20)
|
|
33
|
+
Ts_K = Ta_K + dT
|
|
34
|
+
|
|
35
|
+
return Rn_soil_Wm2, LE_soil_Wm2, Ts_K
|
BESS_JPL/verify.py
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
def verify() -> bool:
|
|
2
|
+
"""
|
|
3
|
+
Verifies the correctness of the BESS model implementation by comparing
|
|
4
|
+
its outputs to a reference dataset.
|
|
5
|
+
|
|
6
|
+
This function loads a known input table and the corresponding expected output table.
|
|
7
|
+
It runs the model on the input data, then compares the resulting outputs to the
|
|
8
|
+
reference outputs for key variables using strict numerical tolerances. If all
|
|
9
|
+
outputs match within tolerance, the function returns True. Otherwise, it prints
|
|
10
|
+
which column failed and returns False.
|
|
11
|
+
|
|
12
|
+
Returns:
|
|
13
|
+
bool: True if all model outputs match the reference outputs within tolerance, False otherwise.
|
|
14
|
+
"""
|
|
15
|
+
import pandas as pd
|
|
16
|
+
import numpy as np
|
|
17
|
+
from .ECOv002_calval_BESS_inputs import load_ECOv002_calval_BESS_inputs
|
|
18
|
+
from .process_BESS_table import process_BESS_table
|
|
19
|
+
import os
|
|
20
|
+
|
|
21
|
+
# Load input and output tables
|
|
22
|
+
input_df = load_ECOv002_calval_BESS_inputs()
|
|
23
|
+
module_dir = os.path.dirname(os.path.abspath(__file__))
|
|
24
|
+
output_file_path = os.path.join(module_dir, "ECOv002-cal-val-BESS-JPL-outputs.csv")
|
|
25
|
+
output_df = pd.read_csv(output_file_path)
|
|
26
|
+
|
|
27
|
+
# Check that input dataset contains all required inputs for BESS model
|
|
28
|
+
# This ensures no on-the-fly data retrieval is needed
|
|
29
|
+
required_inputs = [
|
|
30
|
+
# Core inputs
|
|
31
|
+
'ST_C', 'NDVI', 'albedo', 'time_UTC',
|
|
32
|
+
# Geometry (either geometry or lat/lon)
|
|
33
|
+
# 'geometry' or both 'lat' and 'lon' required - checked separately
|
|
34
|
+
'day_of_year', 'hour_of_day',
|
|
35
|
+
# Meteorological inputs
|
|
36
|
+
'Ta_C', # or 'Ta'
|
|
37
|
+
'RH', 'elevation_m', # or 'elevation_km'
|
|
38
|
+
'wind_speed_mps',
|
|
39
|
+
# Atmospheric inputs from GEOS5FP
|
|
40
|
+
'COT', 'AOT', 'vapor_gccm', 'ozone_cm',
|
|
41
|
+
# Note: Ca defaults to 400 ppm if not provided
|
|
42
|
+
# Radiation inputs
|
|
43
|
+
'PAR_albedo', 'NIR_albedo',
|
|
44
|
+
# Vegetation parameters
|
|
45
|
+
'NDVI_minimum', 'NDVI_maximum', 'C4_fraction',
|
|
46
|
+
'carbon_uptake_efficiency', 'kn',
|
|
47
|
+
# Photosynthesis parameters
|
|
48
|
+
'peakVCmax_C3', 'peakVCmax_C4',
|
|
49
|
+
'ball_berry_slope_C3', 'ball_berry_slope_C4', 'ball_berry_intercept_C3',
|
|
50
|
+
# Other required inputs
|
|
51
|
+
'KG_climate', 'CI', 'canopy_height_meters', 'SZA_deg',
|
|
52
|
+
# Note: canopy_temperature_C and soil_temperature_C default to ST_C if not provided
|
|
53
|
+
]
|
|
54
|
+
|
|
55
|
+
# Check for alternative column names
|
|
56
|
+
missing_inputs = []
|
|
57
|
+
for col in required_inputs:
|
|
58
|
+
# Handle alternative names
|
|
59
|
+
if col == 'Ta_C' and 'Ta_C' not in input_df and 'Ta' not in input_df:
|
|
60
|
+
missing_inputs.append('Ta_C (or Ta)')
|
|
61
|
+
elif col == 'elevation_m' and 'elevation_m' not in input_df and 'elevation_km' not in input_df:
|
|
62
|
+
missing_inputs.append('elevation_m (or elevation_km)')
|
|
63
|
+
elif col not in ['Ta_C', 'elevation_m'] and col not in input_df:
|
|
64
|
+
missing_inputs.append(col)
|
|
65
|
+
|
|
66
|
+
# Check geometry requirement
|
|
67
|
+
has_geometry = 'geometry' in input_df or ('lat' in input_df and 'lon' in input_df)
|
|
68
|
+
if not has_geometry:
|
|
69
|
+
missing_inputs.append('geometry (or lat and lon)')
|
|
70
|
+
|
|
71
|
+
if missing_inputs:
|
|
72
|
+
print("Input verification failed: Missing required inputs for BESS model.")
|
|
73
|
+
print("The following inputs are missing from the input dataset:")
|
|
74
|
+
for inp in missing_inputs:
|
|
75
|
+
print(f" - {inp}")
|
|
76
|
+
print("\nThese inputs must be present to run the model without on-the-fly data retrieval.")
|
|
77
|
+
return False
|
|
78
|
+
|
|
79
|
+
print("Input verification passed: All required BESS inputs are present.")
|
|
80
|
+
|
|
81
|
+
# Run the model on the input table
|
|
82
|
+
model_df = process_BESS_table(input_df, offline_mode=True)
|
|
83
|
+
|
|
84
|
+
# Columns to compare (model outputs)
|
|
85
|
+
output_columns = [
|
|
86
|
+
"G_Wm2",
|
|
87
|
+
"Rn_Wm2",
|
|
88
|
+
"LE_Wm2"
|
|
89
|
+
]
|
|
90
|
+
|
|
91
|
+
# Compare each output column and collect mismatches
|
|
92
|
+
mismatches = []
|
|
93
|
+
for col in output_columns:
|
|
94
|
+
if col not in model_df or col not in output_df:
|
|
95
|
+
mismatches.append((col, 'missing_column', None))
|
|
96
|
+
continue
|
|
97
|
+
model_vals = model_df[col].values
|
|
98
|
+
ref_vals = output_df[col].values
|
|
99
|
+
# Use numpy allclose for floating point comparison
|
|
100
|
+
# Tolerances account for minor platform/version differences (macOS vs Ubuntu, different numpy versions)
|
|
101
|
+
if not np.allclose(model_vals, ref_vals, rtol=1e-4, atol=1e-7, equal_nan=True):
|
|
102
|
+
# Find indices where values differ
|
|
103
|
+
diffs = np.abs(model_vals - ref_vals)
|
|
104
|
+
max_diff = np.nanmax(diffs)
|
|
105
|
+
idxs = np.where(~np.isclose(model_vals, ref_vals, rtol=1e-4, atol=1e-7, equal_nan=True))[0]
|
|
106
|
+
mismatch_info = {
|
|
107
|
+
'indices': idxs.tolist(),
|
|
108
|
+
'model_values': model_vals[idxs].tolist(),
|
|
109
|
+
'ref_values': ref_vals[idxs].tolist(),
|
|
110
|
+
'diffs': diffs[idxs].tolist(),
|
|
111
|
+
'max_diff': float(max_diff)
|
|
112
|
+
}
|
|
113
|
+
mismatches.append((col, 'value_mismatch', mismatch_info))
|
|
114
|
+
if mismatches:
|
|
115
|
+
print("Verification failed. Details:")
|
|
116
|
+
for col, reason, info in mismatches:
|
|
117
|
+
if reason == 'missing_column':
|
|
118
|
+
print(f" Missing column: {col}")
|
|
119
|
+
elif reason == 'value_mismatch':
|
|
120
|
+
print(f" Mismatch in column: {col}")
|
|
121
|
+
print(f" Max difference: {info['max_diff']}")
|
|
122
|
+
print(f" Indices off: {info['indices']}")
|
|
123
|
+
print(f" Model values: {info['model_values']}")
|
|
124
|
+
print(f" Reference values: {info['ref_values']}")
|
|
125
|
+
print(f" Differences: {info['diffs']}")
|
|
126
|
+
return False
|
|
127
|
+
return True
|
BESS_JPL/version.py
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: BESS-JPL
|
|
3
|
+
Version: 1.26.0
|
|
4
|
+
Summary: Breathing Earth System Simulator (BESS) Gross Primary Production (GPP) and Evapotranspiration (ET) Model Python
|
|
5
|
+
Author-email: Gregory Halverson <gregory.h.halverson@jpl.nasa.gov>
|
|
6
|
+
Project-URL: Homepage, https://github.com/JPL-Evapotranspiration-Algorithms/BESS-JPL
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: Operating System :: OS Independent
|
|
9
|
+
Requires-Python: >=3.10
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Requires-Dist: check-distribution>=1.2.0
|
|
13
|
+
Requires-Dist: daylight-evapotranspiration
|
|
14
|
+
Requires-Dist: ECOv002-calval-tables>=1.6.0
|
|
15
|
+
Requires-Dist: FLiESANN>=2.13.0
|
|
16
|
+
Requires-Dist: gedi-canopy-height>=1.1.0
|
|
17
|
+
Requires-Dist: GEOS5FP>=2.19.0
|
|
18
|
+
Requires-Dist: koppengeiger>=1.1.0
|
|
19
|
+
Requires-Dist: MODISCI>=1.4.0
|
|
20
|
+
Requires-Dist: monte-carlo-sensitivity>=1.5.0
|
|
21
|
+
Requires-Dist: NASADEM>=1.3.0
|
|
22
|
+
Requires-Dist: numpy
|
|
23
|
+
Requires-Dist: pytictoc
|
|
24
|
+
Requires-Dist: rasters>=1.9.0
|
|
25
|
+
Requires-Dist: seaborn
|
|
26
|
+
Requires-Dist: solar-apparent-time>=1.5.3
|
|
27
|
+
Provides-Extra: dev
|
|
28
|
+
Requires-Dist: build; extra == "dev"
|
|
29
|
+
Requires-Dist: pytest>=6.0; extra == "dev"
|
|
30
|
+
Requires-Dist: pytest-cov; extra == "dev"
|
|
31
|
+
Requires-Dist: jupyter; extra == "dev"
|
|
32
|
+
Requires-Dist: pytest; extra == "dev"
|
|
33
|
+
Requires-Dist: twine; extra == "dev"
|
|
34
|
+
Dynamic: license-file
|
|
35
|
+
|
|
36
|
+
# Breathing Earth System Simulator (BESS) Model Python Implementation
|
|
37
|
+
|
|
38
|
+
[](https://github.com/JPL-Evapotranspiration-Algorithms/breathing-earth-system-simulator/actions/workflows/ci.yml)
|
|
39
|
+
|
|
40
|
+
This software package is a Python implementation of the Breathing Earth System Simulator (BESS) model. It was re-implemented in Python by Gregory Halverson at Jet Propulsion Laboratory based on [MATLAB code](https://www.environment.snu.ac.kr/bess-flux) produced by Youngryel Ryu at Seoul University. The BESS model was designed to quantify global gross primary productivity (GPP) and evapotranspiration (ET) using MODIS with a spatial resolution of 1–5 km and a temporal resolution of 8 days. It couples atmospheric and canopy radiative transfer processes with photosynthesis, stomatal conductance, and transpiration models on sunlit and shaded portions of vegetation and soil. An artificial neural network emulator of Hideki Kobayashi's Forest Light Environmental Simulator (FLiES) radiative transfer model is used to estimate incoming solar radiation. This implementation of BESS was designed to process GPP at fine spatial resolution using surface temperature from the ECOsystem Spaceborne Thermal Radiometer Experiment on Space Station (ECOSTRESS) mission and normalized difference vegetation index (NDVI) and albedo from the [Spatial Timeseries for Automated high-Resolution multi-Sensor (STARS) data fusion system](https://github.com/STARS-Data-Fusion). The software was developed as part of a research grant by the NASA Research Opportunities in Space and Earth Sciences (ROSES) program. It was designed for use by the ECOSTRESS mission as a precursor for the Surface Biology and Geology (SBG) mission. However, it may also be useful for general remote sensing and GIS projects in Python. This package can be utilized for remote sensing research in Jupyter notebooks and deployed for operations in data processing pipelines. This software is being released according to the SPD-41 open-science requirements of NASA-funded ROSES projects.
|
|
41
|
+
|
|
42
|
+
Gregory H. Halverson (they/them)<br>
|
|
43
|
+
[gregory.h.halverson@jpl.nasa.gov](mailto:gregory.h.halverson@jpl.nasa.gov)<br>
|
|
44
|
+
Lead developer<br>
|
|
45
|
+
NASA Jet Propulsion Laboratory 329G
|
|
46
|
+
|
|
47
|
+
Youngryel Ryu (he/him)<br>
|
|
48
|
+
[yryu@snu.ac.kr](mailto:yryu@snu.ac.kr)<br>
|
|
49
|
+
BESS algorithm inventor<br>
|
|
50
|
+
Seoul National University
|
|
51
|
+
|
|
52
|
+
Hideki Kobayashi (he/him)<br>
|
|
53
|
+
[hkoba@jamstec.go.jp](mailto:hkoba@jamstec.go.jp)<br>
|
|
54
|
+
FLiES algorithm inventor<br>
|
|
55
|
+
Japan Agency for Marine-Earth Science and Technology
|
|
56
|
+
|
|
57
|
+
Robert Freepartner (he/him)<br>
|
|
58
|
+
[robert.freepartner@jpl.nasa.gov](robert.freepartner@jpl.nasa.gov)<br>
|
|
59
|
+
MATLAB to python translation<br>
|
|
60
|
+
Raytheon
|
|
61
|
+
|
|
62
|
+
Joshua Fisher (he/him)<br>
|
|
63
|
+
[jbfisher@chapman.edu](mailto:jbfisher@chapman.edu)<br>
|
|
64
|
+
Concept development and project management<br>
|
|
65
|
+
Chapman University
|
|
66
|
+
|
|
67
|
+
Kerry Cawse-Nicholson (she/her)<br>
|
|
68
|
+
[kerry-anne.cawse-nicholson@jpl.nasa.gov](mailto:kerry-anne.cawse-nicholson@jpl.nasa.gov)<br>
|
|
69
|
+
Project management<br>
|
|
70
|
+
NASA Jet Propulsion Laboratory 329G
|
|
71
|
+
|
|
72
|
+
Zoe Pierrat (she/her)<br>
|
|
73
|
+
[zoe.a.pierrat@jpl.nasa.gov](mailto:zoe.a.pierrat@jpl.nasa.gov)<br>
|
|
74
|
+
Algorithm maintenance<br>
|
|
75
|
+
NASA Jet Propulsion Laboratory 329G
|
|
76
|
+
|
|
77
|
+
Claire Villanueva-Weeks (she/her)<br>
|
|
78
|
+
[claire.s.villanueva-weeks@jpl.nasa.gov](mailto:claire.s.villanueva-weeks@jpl.nasa.gov)<br>
|
|
79
|
+
Code maintenance<br>
|
|
80
|
+
NASA Jet Propulsion Laboratory 329G
|
|
81
|
+
|
|
82
|
+
## Installation
|
|
83
|
+
|
|
84
|
+
Use the pip package manager to install this package
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
pip install breathing-earth-system-simulator
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## References
|
|
91
|
+
|
|
92
|
+
The following scientific references provide detailed information about the BESS model and its underlying algorithms:
|
|
93
|
+
|
|
94
|
+
1. Ryu, Y., Baldocchi, D. D., Kobayashi, H., van Ingen, C., Li, J., Black, T. A., ... & Ueyama, M. (2011). Integration of MODIS land and atmosphere products with a coupled-process model to estimate gross primary productivity and evapotranspiration from 1 km to global scales. *Remote Sensing of Environment, 115*(8), 1865-1874. https://doi.org/10.1016/j.rse.2011.03.009
|
|
95
|
+
|
|
96
|
+
2. Kobayashi, H., Ryu, Y., Baldocchi, D. D., Welles, J. M., & Norman, J. M. (2012). On the correct estimation of gap fraction: How to remove scattered radiation in gap fraction measurements? *Agricultural and Forest Meteorology, 160*, 14-25. https://doi.org/10.1016/j.agrformet.2012.03.001
|
|
97
|
+
|
|
98
|
+
3. Fisher, J. B., Lee, B., Purdy, A. J., Halverson, G. H., Dohlen, M. B., & Tu, K. P. (2020). ECOSTRESS: NASA's next generation mission to measure evapotranspiration from the International Space Station. *Water Resources Research, 56*(4), e2019WR026058. https://doi.org/10.1029/2019WR026058
|
|
99
|
+
|
|
100
|
+
4. Ryu, Y., Jiang, C., Kobayashi, H., & Detto, M. (2018). Modis-derived global land products of shortwave radiation and diffuse and total photosynthetically active radiation at 5 km resolution from 2000. *Remote Sensing of Environment, 204*, 812-825. https://doi.org/10.1016/j.rse.2017.09.021
|
|
101
|
+
|
|
102
|
+
5. Kobayashi, H., & Iwabuchi, H. (2008). A coupled 1-D atmosphere and canopy radiative transfer model for an atmosphere with a nonlambertian surface. *Journal of Quantitative Spectroscopy and Radiative Transfer, 109*(17-18), 2955-2970. https://doi.org/10.1016/j.jqsrt.2008.07.008
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
BESS_JPL/BESS_JPL.py,sha256=l5ubRRpPYlZxhmHjsB-88J5_2exgNLB5lvvVVO10fjw,1720
|
|
2
|
+
BESS_JPL/C3_photosynthesis.py,sha256=VmBYwxCK1URhA2_Etb96JXSqubyvuftjyuhHha9QOXQ,6506
|
|
3
|
+
BESS_JPL/C4_fraction.jpeg,sha256=ECaEYWA8MnNd5z0Yq3beeUCR93KtTDxM8MrH-YYon3Y,2746
|
|
4
|
+
BESS_JPL/C4_fraction.tif,sha256=DFS-J08JCjnf0hi_T_dFridAegVTiU3FGyMBjS9yc1w,25446
|
|
5
|
+
BESS_JPL/C4_fraction.tif.aux.xml,sha256=5Ytn5UtZdGWQUKNmg_kiOU2zRQsm82sY7bq-j3TS1QY,358
|
|
6
|
+
BESS_JPL/C4_photosynthesis.py,sha256=NtT-fV8DQbLXMyePGGDSwYadbsDY0ZW3WFGJ9pxxL40,7035
|
|
7
|
+
BESS_JPL/ECOv002-cal-val-BESS-JPL-GEOS5FP-inputs.csv,sha256=aw7YL3S81qu3SUNp3DHG7Q4HtOdOWxBLycEcKUJIBrA,104716
|
|
8
|
+
BESS_JPL/ECOv002-cal-val-BESS-JPL-inputs.csv,sha256=3oQVYY_dSzIyclORmE181gtbVvWcj8fTFR9E_XW9gjQ,1317067
|
|
9
|
+
BESS_JPL/ECOv002-cal-val-BESS-JPL-outputs.csv,sha256=W5cDy2I3X37z3YaY0ehEeprljIOqfGgEC_5NlpSoUVY,2984084
|
|
10
|
+
BESS_JPL/ECOv002-cal-val-FLiESANN-inputs.csv,sha256=AybkhW0EmPGlkoYe_Ph0aoh7TrA9yd0ozJ6cvDwS4fE,946508
|
|
11
|
+
BESS_JPL/ECOv002-static-tower-BESS-JPL-inputs.csv,sha256=uRrCRPfbnsU_a3Otnnpk47gcBpTrS079EZPrB0KNc8s,33603
|
|
12
|
+
BESS_JPL/ECOv002_calval_BESS_inputs.py,sha256=9XTFJHn9EczVNLr2WDjsJ4b5nHZonkxWpS5yEogo2RY,1109
|
|
13
|
+
BESS_JPL/ECOv002_static_tower_BESS_inputs.py,sha256=jvMGMWVo0UnNsGXebrYDVTgJXroH-MTkLj2zYcCYADk,622
|
|
14
|
+
BESS_JPL/FVC_from_NDVI.py,sha256=LYI1ESsrO8UxlPOr_dxJYDeUsrwjVAwrV_OhL-tcAWc,567
|
|
15
|
+
BESS_JPL/LAI_from_NDVI.py,sha256=uwV1voc2q45hmsSHzIhehA3ZHLivzSeoST-ht9ecSIE,783
|
|
16
|
+
BESS_JPL/NDVI_maximum.jpeg,sha256=6kc0-eE_WOU31bUztdjoWsZ3ZmqHAG-ZwS7lMiZyBGA,763946
|
|
17
|
+
BESS_JPL/NDVI_maximum.tif,sha256=yRgdpB-xoVNMveIUapCrnGAwHX7WkH6pVXu4HECuFfc,19664541
|
|
18
|
+
BESS_JPL/NDVI_minimum.jpeg,sha256=AfpRU8PikwExBJ2IdcFKewg6aTcp3gx3y3EQMzeA7vg,644871
|
|
19
|
+
BESS_JPL/NDVI_minimum.tif,sha256=wPV0CFfQSLfiTAEDlwIAI857pA7aw0iqWhVlOAZFsJg,18762242
|
|
20
|
+
BESS_JPL/__init__.py,sha256=UaK3mWbc5jNoA4kNzIWF9h7CQs64O_chKrpuxNkH48o,95
|
|
21
|
+
BESS_JPL/ball_berry_intercept_C3.jpeg,sha256=c8jlRD3i8cnWXQNRUfyNTuObEpptcG6p6kQd2RGMK70,634200
|
|
22
|
+
BESS_JPL/ball_berry_intercept_C3.tif,sha256=O7ATUIKtXcIjkUI2lloTiHAgvRk4gWyWjYGh5Xc_CRY,1026642
|
|
23
|
+
BESS_JPL/ball_berry_slope_C3.jpeg,sha256=KdFUYG4h1nRNb_eK7w-M2kqChJnhbcGmal9Z2Jos1nI,225597
|
|
24
|
+
BESS_JPL/ball_berry_slope_C3.tif,sha256=PEAZ09AMMbDUXi5R4FsyMQGsanLd4Ptzk-pRHnaa-oU,407646
|
|
25
|
+
BESS_JPL/ball_berry_slope_C4.jpeg,sha256=JJJn3C17duBOlEe98PCyycBT3SS-YBhHJpJZYTq4GMw,1009208
|
|
26
|
+
BESS_JPL/ball_berry_slope_C4.tif,sha256=UedoUOnOjBxQ9pAaf5nXgDa8wvKOHVBD3sVToV12aM8,1012948
|
|
27
|
+
BESS_JPL/calculate_VCmax.py,sha256=dQ6uGzgqrv2rAaUlhxuLauWhMSuUGvb9fgS2pRYugLY,4129
|
|
28
|
+
BESS_JPL/calculate_bulk_aerodynamic_resistance.py,sha256=5j0YJGI_dEnMDud4pv0AyOf03hYxv5cJ6m0nbIJtlWU,5668
|
|
29
|
+
BESS_JPL/calculate_friction_velocity.py,sha256=njTyo9H5tXxqS7-VNGOqf5pCqTV3Y5vaNwYEmF1kxsI,4932
|
|
30
|
+
BESS_JPL/canopy_energy_balance.py,sha256=aNnODLouI33GkVrqmNaviWGzyPvV0DgnbV4iQncKsw4,4945
|
|
31
|
+
BESS_JPL/canopy_longwave_radiation.py,sha256=Hv5TUJ1O_PBIYRmx8kn6Ake8cyKEL9h0cfN4wsC0UgM,5436
|
|
32
|
+
BESS_JPL/canopy_shortwave_radiation.py,sha256=WmzH6birUGkT4O0q7eG1Eo4ed3xi9LVKTydIf9r8J_s,13280
|
|
33
|
+
BESS_JPL/carbon_uptake_efficiency.jpeg,sha256=wz2cLk_4-DRdF71xR2c-cx1MsE0CH-EDWjs2pDJcRF0,704540
|
|
34
|
+
BESS_JPL/carbon_uptake_efficiency.tif,sha256=Nnc8h2ImU6_sip0WzDh3q0BRoBe-CfCbwzDtYo5BSog,819269
|
|
35
|
+
BESS_JPL/carbon_water_fluxes.py,sha256=hfTug6k7ch_i2k-HoICVJZTJW310Uc5esK258qaEN-M,16758
|
|
36
|
+
BESS_JPL/colors.py,sha256=vRZoazJwgSa6v3sC678GoyVPRUxVfYg1JMibzI3jHiw,635
|
|
37
|
+
BESS_JPL/constants.py,sha256=LYtSoFHA8zaerW4BOSY8mRcKvqpf3foIX5NX8xwVVFM,688
|
|
38
|
+
BESS_JPL/exceptions.py,sha256=KpYl0RC4FtfmXrMHpRhVb6InwbrALwh3WfZIfbdbpgA,132
|
|
39
|
+
BESS_JPL/generate_BESS_GEOS5FP_inputs.py,sha256=7J5Cv6t6fZZbpETOquTKWf604dvLC1vePE3y8almUK8,1685
|
|
40
|
+
BESS_JPL/generate_BESS_inputs_table.py,sha256=QqYUG98bWXLoTp5TqBfDPI8xXoOu9kEQG04g7oirkBI,9763
|
|
41
|
+
BESS_JPL/generate_input_dataset.py,sha256=4YbPdKvcY69PQVjTDKVb5pYvt7DbMLSzAZcsRIQFY1E,11768
|
|
42
|
+
BESS_JPL/generate_output_dataset.py,sha256=tz7pM3JF2fI1HqKWT3ub1P40VQYzOLoT-qrTV4zeIOI,839
|
|
43
|
+
BESS_JPL/interpolate_C3_C4.py,sha256=adIyk03Yt6SJ_jFCUm6ivK9QpZYw10C3wJKpx1O56Pk,394
|
|
44
|
+
BESS_JPL/kn.jpeg,sha256=wsI40jabT9_iPpQmOxd3GZzfAN7oZ2DubiARmULFUS0,854097
|
|
45
|
+
BESS_JPL/kn.tif,sha256=nZAIAms7LRDVsadxa4z8yRqOudWu3AjJSm6l1T3ywuY,819988
|
|
46
|
+
BESS_JPL/load_C4_fraction.py,sha256=qemgzsyDVKvzvql1p_N7g23L8KYvbLw-qxjWlUC3p_Q,624
|
|
47
|
+
BESS_JPL/load_NDVI_maximum.py,sha256=HMOvChb9CWItkDpGCZtZ9Ode2N4Q_MllmnOgiAt5yzQ,528
|
|
48
|
+
BESS_JPL/load_NDVI_minimum.py,sha256=ed_qmkNCIy-H7Q5POA4mSlUvYUTknKiz31ioXZGpbvU,528
|
|
49
|
+
BESS_JPL/load_ball_berry_intercept_C3.py,sha256=6auXZHej127rhUCFXe7vdEg9C4CosFSHLTcdqKs06Ls,388
|
|
50
|
+
BESS_JPL/load_ball_berry_slope_C3.py,sha256=9nmbdkGnJ7UWXwktpkE8rL1LGA1vi71YZdzpme04P84,380
|
|
51
|
+
BESS_JPL/load_ball_berry_slope_C4.py,sha256=lsKwrkbChEm3sspUgAXjm86Q4VBirwFOZStiO9NuGx8,380
|
|
52
|
+
BESS_JPL/load_carbon_uptake_efficiency.py,sha256=RbWxLbqHnxiHw7XHyFBuWRToc8hDjUR6EUUntiJfe0M,390
|
|
53
|
+
BESS_JPL/load_kn.py,sha256=39RkQkkdmey0IPInziJI0kSiI8alRk5Hz42pzm-qihU,346
|
|
54
|
+
BESS_JPL/load_peakVCmax_C3.py,sha256=A-Wg4PjPgogfpRsAMo6ZNEXM7G3KbnF7ZRV3k_jTtEA,401
|
|
55
|
+
BESS_JPL/load_peakVCmax_C4.py,sha256=iVmJTitkMkB4AjfjanAi3yv1lWO4sSF6J7cjuRmaCwU,401
|
|
56
|
+
BESS_JPL/meteorology.py,sha256=B7tguKu_1H0bWKJI0YQpSZzk9cXS-wc6W4OIe_5igds,14799
|
|
57
|
+
BESS_JPL/model.py,sha256=r4fpvRngARgkQsDmbNVPH7KeC_lHYQiwYheNOI0nanE,25838
|
|
58
|
+
BESS_JPL/peakVCmax_C3.jpeg,sha256=nVvwLx8JyRhtm5lWRW93HLz0mInshEdOCJ1tAdcFqa8,1006133
|
|
59
|
+
BESS_JPL/peakVCmax_C3.tif,sha256=ax6wCOPc_ovgJJl9YRjPWNY13OCGlzs2djXqwob_U7A,1583598
|
|
60
|
+
BESS_JPL/peakVCmax_C4.jpeg,sha256=s7dhpcD573KW9Se4mejDeSzbSHqPtQY2EL6KJKt7ZIo,961497
|
|
61
|
+
BESS_JPL/peakVCmax_C4.tif,sha256=EST4_yy-HHYmazIv--RePL_bhLejMWql6hoV9EE38ok,1556928
|
|
62
|
+
BESS_JPL/process_BESS_table.py,sha256=U3SMtCEESm7bAu3Vaccdy_MnL2l2Er7LdbZnbryYBkI,13039
|
|
63
|
+
BESS_JPL/process_paw_and_gao_LE.py,sha256=e-hMowIWC-aORGOyJU-omGsFk0Pp8YmTjl5wwQiOXOQ,1760
|
|
64
|
+
BESS_JPL/retrieve_BESS_JPL_GEOS5FP_inputs.py,sha256=mS6IcXELzj2j8fHAAVwregI-FU3g_9l4tolu24x1_l8,10651
|
|
65
|
+
BESS_JPL/retrieve_BESS_inputs.py,sha256=VubZ3ui6ZYnLGpjDjgrcwVRRobeEslCG6fpIPIzzK6A,11924
|
|
66
|
+
BESS_JPL/soil_energy_balance.py,sha256=u5YMywVQPard8DSutBuI37WfyDcCtm64YwxaHZDm-rs,1095
|
|
67
|
+
BESS_JPL/verify.py,sha256=RvGVvaQ68WOfA42KwdZCKOBnydBri4dQfpcYCwDA01M,5628
|
|
68
|
+
BESS_JPL/version.py,sha256=oPRGJspBmrZU7gLv4L_3WPX3aGwee0inKgfzcyvkXcc,74
|
|
69
|
+
bess_jpl-1.26.0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
70
|
+
bess_jpl-1.26.0.dist-info/METADATA,sha256=TfruStH4jfszvGX0-wjbRnDKv6BIueGhK2PaThb0UFU,6543
|
|
71
|
+
bess_jpl-1.26.0.dist-info/WHEEL,sha256=qELbo2s1Yzl39ZmrAibXA2jjPLUYfnVhUNTlyF1rq0Y,92
|
|
72
|
+
bess_jpl-1.26.0.dist-info/top_level.txt,sha256=GaKnzt-BBktYn1o-w4Qzh_jHxse4Y3ACOxZQrB2ufhc,9
|
|
73
|
+
bess_jpl-1.26.0.dist-info/RECORD,,
|