BESS-JPL 1.6.0__tar.gz
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-1.6.0/.github/workflows/ci.yml +34 -0
- bess_jpl-1.6.0/.github/workflows/python-publish.yml +39 -0
- bess_jpl-1.6.0/.gitignore +162 -0
- bess_jpl-1.6.0/BESS_JPL/BESS.py +468 -0
- bess_jpl-1.6.0/BESS_JPL/BESS_JPL.py +23 -0
- bess_jpl-1.6.0/BESS_JPL/C3_photosynthesis.py +72 -0
- bess_jpl-1.6.0/BESS_JPL/C4_fraction.jpeg +0 -0
- bess_jpl-1.6.0/BESS_JPL/C4_fraction.tif +0 -0
- bess_jpl-1.6.0/BESS_JPL/C4_photosynthesis.py +56 -0
- bess_jpl-1.6.0/BESS_JPL/FVC_from_NDVI.py +22 -0
- bess_jpl-1.6.0/BESS_JPL/LAI_from_NDVI.py +29 -0
- bess_jpl-1.6.0/BESS_JPL/NDVI_maximum.jpeg +0 -0
- bess_jpl-1.6.0/BESS_JPL/NDVI_maximum.tif +0 -0
- bess_jpl-1.6.0/BESS_JPL/NDVI_minimum.jpeg +0 -0
- bess_jpl-1.6.0/BESS_JPL/NDVI_minimum.tif +0 -0
- bess_jpl-1.6.0/BESS_JPL/SZA/__init__.py +1 -0
- bess_jpl-1.6.0/BESS_JPL/SZA/daylight_hours.py +74 -0
- bess_jpl-1.6.0/BESS_JPL/__init__.py +10 -0
- bess_jpl-1.6.0/BESS_JPL/ball_berry_intercept_C3.jpeg +0 -0
- bess_jpl-1.6.0/BESS_JPL/ball_berry_intercept_C3.tif +0 -0
- bess_jpl-1.6.0/BESS_JPL/ball_berry_slope_C3.jpeg +0 -0
- bess_jpl-1.6.0/BESS_JPL/ball_berry_slope_C3.tif +0 -0
- bess_jpl-1.6.0/BESS_JPL/ball_berry_slope_C4.jpeg +0 -0
- bess_jpl-1.6.0/BESS_JPL/ball_berry_slope_C4.tif +0 -0
- bess_jpl-1.6.0/BESS_JPL/calculate_VCmax.py +54 -0
- bess_jpl-1.6.0/BESS_JPL/canopy_energy_balance.py +146 -0
- bess_jpl-1.6.0/BESS_JPL/canopy_longwave_radiation.py +92 -0
- bess_jpl-1.6.0/BESS_JPL/canopy_shortwave_radiation.py +234 -0
- bess_jpl-1.6.0/BESS_JPL/carbon_uptake_efficiency.jpeg +0 -0
- bess_jpl-1.6.0/BESS_JPL/carbon_uptake_efficiency.tif +0 -0
- bess_jpl-1.6.0/BESS_JPL/carbon_water_fluxes.py +277 -0
- bess_jpl-1.6.0/BESS_JPL/constants.py +8 -0
- bess_jpl-1.6.0/BESS_JPL/interpolate_C3_C4.py +12 -0
- bess_jpl-1.6.0/BESS_JPL/kn.jpeg +0 -0
- bess_jpl-1.6.0/BESS_JPL/kn.tif +0 -0
- bess_jpl-1.6.0/BESS_JPL/load_C4_fraction.py +10 -0
- bess_jpl-1.6.0/BESS_JPL/load_NDVI_maximum.py +10 -0
- bess_jpl-1.6.0/BESS_JPL/load_NDVI_minimum.py +10 -0
- bess_jpl-1.6.0/BESS_JPL/load_ball_berry_intercept_C3.py +10 -0
- bess_jpl-1.6.0/BESS_JPL/load_ball_berry_slope_C3.py +10 -0
- bess_jpl-1.6.0/BESS_JPL/load_ball_berry_slope_C4.py +10 -0
- bess_jpl-1.6.0/BESS_JPL/load_carbon_uptake_efficiency.py +10 -0
- bess_jpl-1.6.0/BESS_JPL/load_kn.py +10 -0
- bess_jpl-1.6.0/BESS_JPL/load_peakVCmax_C3.py +10 -0
- bess_jpl-1.6.0/BESS_JPL/load_peakVCmax_C4.py +10 -0
- bess_jpl-1.6.0/BESS_JPL/meteorology.py +204 -0
- bess_jpl-1.6.0/BESS_JPL/peakVCmax_C3.jpeg +0 -0
- bess_jpl-1.6.0/BESS_JPL/peakVCmax_C3.tif +0 -0
- bess_jpl-1.6.0/BESS_JPL/peakVCmax_C4.jpeg +0 -0
- bess_jpl-1.6.0/BESS_JPL/peakVCmax_C4.tif +0 -0
- bess_jpl-1.6.0/BESS_JPL/soil_energy_balance.py +35 -0
- bess_jpl-1.6.0/BESS_JPL/vegetation_conversion/__init__.py +1 -0
- bess_jpl-1.6.0/BESS_JPL/vegetation_conversion/vegetation_conversion.py +71 -0
- bess_jpl-1.6.0/BESS_JPL/version.txt +1 -0
- bess_jpl-1.6.0/BESS_JPL.egg-info/PKG-INFO +95 -0
- bess_jpl-1.6.0/BESS_JPL.egg-info/SOURCES.txt +70 -0
- bess_jpl-1.6.0/BESS_JPL.egg-info/dependency_links.txt +1 -0
- bess_jpl-1.6.0/BESS_JPL.egg-info/requires.txt +16 -0
- bess_jpl-1.6.0/BESS_JPL.egg-info/top_level.txt +1 -0
- bess_jpl-1.6.0/C4 Fraction.ipynb +56 -0
- bess_jpl-1.6.0/Dockerfile +27 -0
- bess_jpl-1.6.0/LICENSE +201 -0
- bess_jpl-1.6.0/Li_2023_RSE.pdf +0 -0
- bess_jpl-1.6.0/MANIFEST.in +1 -0
- bess_jpl-1.6.0/PKG-INFO +95 -0
- bess_jpl-1.6.0/Processing BESS with rasters.ipynb +9608 -0
- bess_jpl-1.6.0/README.md +67 -0
- bess_jpl-1.6.0/makefile +59 -0
- bess_jpl-1.6.0/pyproject.toml +43 -0
- bess_jpl-1.6.0/setup.cfg +4 -0
- bess_jpl-1.6.0/tests/test_import_breathing_earth_system_simulator.py +2 -0
- bess_jpl-1.6.0/tests/test_import_dependencies.py +17 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
pull_request:
|
|
8
|
+
branches:
|
|
9
|
+
- main
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
test:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
strategy:
|
|
15
|
+
matrix:
|
|
16
|
+
python-version: ["3.10"]
|
|
17
|
+
|
|
18
|
+
steps:
|
|
19
|
+
- name: Checkout repository
|
|
20
|
+
uses: actions/checkout@v3 # This is already the latest version
|
|
21
|
+
|
|
22
|
+
- name: Set up Python
|
|
23
|
+
uses: actions/setup-python@v4 # This is also the latest version
|
|
24
|
+
with:
|
|
25
|
+
python-version: ${{ matrix.python-version }}
|
|
26
|
+
|
|
27
|
+
- name: Install dependencies
|
|
28
|
+
run: |
|
|
29
|
+
python -m pip install --upgrade pip
|
|
30
|
+
pip install .[dev] # Use dev to install pytest
|
|
31
|
+
|
|
32
|
+
- name: Run tests
|
|
33
|
+
run: |
|
|
34
|
+
pytest
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# This workflow will upload a Python Package using Twine when a release is created
|
|
2
|
+
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries
|
|
3
|
+
|
|
4
|
+
# This workflow uses actions that are not certified by GitHub.
|
|
5
|
+
# They are provided by a third-party and are governed by
|
|
6
|
+
# separate terms of service, privacy policy, and support
|
|
7
|
+
# documentation.
|
|
8
|
+
|
|
9
|
+
name: Upload Python Package
|
|
10
|
+
|
|
11
|
+
on:
|
|
12
|
+
release:
|
|
13
|
+
types: [published]
|
|
14
|
+
|
|
15
|
+
permissions:
|
|
16
|
+
contents: read
|
|
17
|
+
|
|
18
|
+
jobs:
|
|
19
|
+
deploy:
|
|
20
|
+
|
|
21
|
+
runs-on: ubuntu-latest
|
|
22
|
+
|
|
23
|
+
steps:
|
|
24
|
+
- uses: actions/checkout@v4
|
|
25
|
+
- name: Set up Python
|
|
26
|
+
uses: actions/setup-python@v3
|
|
27
|
+
with:
|
|
28
|
+
python-version: '3.x'
|
|
29
|
+
- name: Install dependencies
|
|
30
|
+
run: |
|
|
31
|
+
python -m pip install --upgrade pip
|
|
32
|
+
pip install build
|
|
33
|
+
- name: Build package
|
|
34
|
+
run: python -m build
|
|
35
|
+
- name: Publish package
|
|
36
|
+
uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29
|
|
37
|
+
with:
|
|
38
|
+
user: __token__
|
|
39
|
+
password: ${{ secrets.PYPI_API_TOKEN }}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
share/python-wheels/
|
|
24
|
+
*.egg-info/
|
|
25
|
+
.installed.cfg
|
|
26
|
+
*.egg
|
|
27
|
+
MANIFEST
|
|
28
|
+
|
|
29
|
+
# PyInstaller
|
|
30
|
+
# Usually these files are written by a python script from a template
|
|
31
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
32
|
+
*.manifest
|
|
33
|
+
*.spec
|
|
34
|
+
|
|
35
|
+
# Installer logs
|
|
36
|
+
pip-log.txt
|
|
37
|
+
pip-delete-this-directory.txt
|
|
38
|
+
|
|
39
|
+
# Unit test / coverage reports
|
|
40
|
+
htmlcov/
|
|
41
|
+
.tox/
|
|
42
|
+
.nox/
|
|
43
|
+
.coverage
|
|
44
|
+
.coverage.*
|
|
45
|
+
.cache
|
|
46
|
+
nosetests.xml
|
|
47
|
+
coverage.xml
|
|
48
|
+
*.cover
|
|
49
|
+
*.py,cover
|
|
50
|
+
.hypothesis/
|
|
51
|
+
.pytest_cache/
|
|
52
|
+
cover/
|
|
53
|
+
|
|
54
|
+
# Translations
|
|
55
|
+
*.mo
|
|
56
|
+
*.pot
|
|
57
|
+
|
|
58
|
+
# Django stuff:
|
|
59
|
+
*.log
|
|
60
|
+
local_settings.py
|
|
61
|
+
db.sqlite3
|
|
62
|
+
db.sqlite3-journal
|
|
63
|
+
|
|
64
|
+
# Flask stuff:
|
|
65
|
+
instance/
|
|
66
|
+
.webassets-cache
|
|
67
|
+
|
|
68
|
+
# Scrapy stuff:
|
|
69
|
+
.scrapy
|
|
70
|
+
|
|
71
|
+
# Sphinx documentation
|
|
72
|
+
docs/_build/
|
|
73
|
+
|
|
74
|
+
# PyBuilder
|
|
75
|
+
.pybuilder/
|
|
76
|
+
target/
|
|
77
|
+
|
|
78
|
+
# Jupyter Notebook
|
|
79
|
+
.ipynb_checkpoints
|
|
80
|
+
|
|
81
|
+
# IPython
|
|
82
|
+
profile_default/
|
|
83
|
+
ipython_config.py
|
|
84
|
+
|
|
85
|
+
# pyenv
|
|
86
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
87
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
88
|
+
# .python-version
|
|
89
|
+
|
|
90
|
+
# pipenv
|
|
91
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
92
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
93
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
94
|
+
# install all needed dependencies.
|
|
95
|
+
#Pipfile.lock
|
|
96
|
+
|
|
97
|
+
# poetry
|
|
98
|
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
99
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
100
|
+
# commonly ignored for libraries.
|
|
101
|
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
102
|
+
#poetry.lock
|
|
103
|
+
|
|
104
|
+
# pdm
|
|
105
|
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
106
|
+
#pdm.lock
|
|
107
|
+
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
|
108
|
+
# in version control.
|
|
109
|
+
# https://pdm.fming.dev/#use-with-ide
|
|
110
|
+
.pdm.toml
|
|
111
|
+
|
|
112
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
113
|
+
__pypackages__/
|
|
114
|
+
|
|
115
|
+
# Celery stuff
|
|
116
|
+
celerybeat-schedule
|
|
117
|
+
celerybeat.pid
|
|
118
|
+
|
|
119
|
+
# SageMath parsed files
|
|
120
|
+
*.sage.py
|
|
121
|
+
|
|
122
|
+
# Environments
|
|
123
|
+
.env
|
|
124
|
+
.venv
|
|
125
|
+
env/
|
|
126
|
+
venv/
|
|
127
|
+
ENV/
|
|
128
|
+
env.bak/
|
|
129
|
+
venv.bak/
|
|
130
|
+
|
|
131
|
+
# Spyder project settings
|
|
132
|
+
.spyderproject
|
|
133
|
+
.spyproject
|
|
134
|
+
|
|
135
|
+
# Rope project settings
|
|
136
|
+
.ropeproject
|
|
137
|
+
|
|
138
|
+
# mkdocs documentation
|
|
139
|
+
/site
|
|
140
|
+
|
|
141
|
+
# mypy
|
|
142
|
+
.mypy_cache/
|
|
143
|
+
.dmypy.json
|
|
144
|
+
dmypy.json
|
|
145
|
+
|
|
146
|
+
# Pyre type checker
|
|
147
|
+
.pyre/
|
|
148
|
+
|
|
149
|
+
# pytype static type analyzer
|
|
150
|
+
.pytype/
|
|
151
|
+
|
|
152
|
+
# Cython debug symbols
|
|
153
|
+
cython_debug/
|
|
154
|
+
|
|
155
|
+
# PyCharm
|
|
156
|
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
157
|
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
158
|
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
159
|
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
160
|
+
.idea/
|
|
161
|
+
|
|
162
|
+
.DS_Store
|
|
@@ -0,0 +1,468 @@
|
|
|
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
|
+
|
|
13
|
+
from koppengeiger import load_koppen_geiger
|
|
14
|
+
from gedi_canopy_height import load_canopy_height
|
|
15
|
+
from FLiESANN import FLiESANN
|
|
16
|
+
from GEOS5FP import GEOS5FP
|
|
17
|
+
from MODISCI import MODISCI
|
|
18
|
+
|
|
19
|
+
from .constants import *
|
|
20
|
+
from .vegetation_conversion import LAI_from_NDVI
|
|
21
|
+
from .canopy_shortwave_radiation import canopy_shortwave_radiation
|
|
22
|
+
from .carbon_water_fluxes import carbon_water_fluxes
|
|
23
|
+
from .meteorology import meteorology, SVP_Pa_from_Ta_K
|
|
24
|
+
from .interpolate_C3_C4 import interpolate_C3_C4
|
|
25
|
+
from .calculate_VCmax import calculate_VCmax
|
|
26
|
+
from .load_NDVI_minimum import load_NDVI_minimum
|
|
27
|
+
from .load_NDVI_maximum import load_NDVI_maximum
|
|
28
|
+
from .load_C4_fraction import load_C4_fraction
|
|
29
|
+
from .load_carbon_uptake_efficiency import load_carbon_uptake_efficiency
|
|
30
|
+
from .load_kn import load_kn
|
|
31
|
+
from .load_peakVCmax_C3 import load_peakVCmax_C3
|
|
32
|
+
from .load_peakVCmax_C4 import load_peakVCmax_C4
|
|
33
|
+
from .load_ball_berry_intercept_C3 import load_ball_berry_intercept_C3
|
|
34
|
+
from .load_ball_berry_slope_C3 import load_ball_berry_slope_C3
|
|
35
|
+
from .load_ball_berry_slope_C4 import load_ball_berry_slope_C4
|
|
36
|
+
|
|
37
|
+
logger = logging.getLogger(__name__)
|
|
38
|
+
|
|
39
|
+
def BESS(
|
|
40
|
+
ST_C: Union[Raster, np.ndarray], # surface temperature in Celsius
|
|
41
|
+
NDVI: Union[Raster, np.ndarray], # NDVI
|
|
42
|
+
albedo: Union[Raster, np.ndarray], # surface albedo
|
|
43
|
+
elevation_km: Union[Raster, np.ndarray], # elevation in kilometers
|
|
44
|
+
geometry: RasterGeometry = None,
|
|
45
|
+
time_UTC: datetime = None,
|
|
46
|
+
hour_of_day: np.ndarray = None,
|
|
47
|
+
day_of_year: np.ndarray = None,
|
|
48
|
+
GEOS5FP_connection: GEOS5FP = None,
|
|
49
|
+
Ta_C: Union[Raster, np.ndarray] = None, # air temperature in Celsius
|
|
50
|
+
RH: Union[Raster, np.ndarray] = None, # relative humidity as a proportion
|
|
51
|
+
NDVI_minimum: Union[Raster, np.ndarray] = None, # minimum NDVI
|
|
52
|
+
NDVI_maximum: Union[Raster, np.ndarray] = None, # maximum NDVI
|
|
53
|
+
Rg: Union[Raster, np.ndarray] = None, # incoming shortwave radiation in W/m^2
|
|
54
|
+
VISdiff: Union[Raster, np.ndarray] = None, # diffuse visible radiation in W/m^2
|
|
55
|
+
VISdir: Union[Raster, np.ndarray] = None, # direct visible radiation in W/m^2
|
|
56
|
+
NIRdiff: Union[Raster, np.ndarray] = None, # diffuse near-infrared radiation in W/m^2
|
|
57
|
+
NIRdir: Union[Raster, np.ndarray] = None, # direct near-infrared radiation in W/m^2
|
|
58
|
+
UV: Union[Raster, np.ndarray] = None, # incoming ultraviolet radiation in W/m^2
|
|
59
|
+
albedo_visible: Union[Raster, np.ndarray] = None, # surface albedo in visible wavelengths (initialized to surface albedo if left as None)
|
|
60
|
+
albedo_NIR: Union[Raster, np.ndarray] = None, # surface albedo in near-infrared wavelengths (initialized to surface albedo if left as None)
|
|
61
|
+
COT: Union[Raster, np.ndarray] = None, # cloud optical thickness
|
|
62
|
+
AOT: Union[Raster, np.ndarray] = None, # aerosol optical thickness
|
|
63
|
+
vapor_gccm: Union[Raster, np.ndarray] = None, # water vapor in g/ccm
|
|
64
|
+
ozone_cm: Union[Raster, np.ndarray] = None, # ozone in cm
|
|
65
|
+
KG_climate: Union[Raster, np.ndarray] = None, # KG climate
|
|
66
|
+
canopy_height_meters: Union[Raster, np.ndarray] = None, # canopy height in meters
|
|
67
|
+
Ca: Union[Raster, np.ndarray] = None, # atmospheric CO2 concentration in ppm
|
|
68
|
+
wind_speed_mps: Union[Raster, np.ndarray] = None, # wind speed in meters per second
|
|
69
|
+
SZA: Union[Raster, np.ndarray] = None, # solar zenith angle in degrees
|
|
70
|
+
canopy_temperature_C: Union[Raster, np.ndarray] = None, # canopy temperature in Celsius (initialized to surface temperature if left as None)
|
|
71
|
+
soil_temperature_C: Union[Raster, np.ndarray] = None, # soil temperature in Celsius (initialized to surface temperature if left as None)
|
|
72
|
+
C4_fraction: Union[Raster, np.ndarray] = None, # fraction of C4 plants
|
|
73
|
+
carbon_uptake_efficiency: Union[Raster, np.ndarray] = None, # intrinsic quantum efficiency for carbon uptake
|
|
74
|
+
kn: np.ndarray = None,
|
|
75
|
+
ball_berry_intercept_C3: np.ndarray = None, # Ball-Berry intercept for C3 plants
|
|
76
|
+
ball_berry_intercept_C4: Union[np.ndarray, float] = BALL_BERRY_INTERCEPT_C4, # Ball-Berry intercept for C4 plants
|
|
77
|
+
ball_berry_slope_C3: np.ndarray = None, # Ball-Berry slope for C3 plants
|
|
78
|
+
ball_berry_slope_C4: np.ndarray = None, # Ball-Berry slope for C4 plants
|
|
79
|
+
peakVCmax_C3: np.ndarray = None, # peak maximum carboxylation rate for C3 plants
|
|
80
|
+
peakVCmax_C4: np.ndarray = None, # peak maximum carboxylation rate for C4 plants
|
|
81
|
+
CI: Union[Raster, np.ndarray] = None,
|
|
82
|
+
resampling: str = RESAMPLING): # clumping index
|
|
83
|
+
if geometry is None and isinstance(ST_C, Raster):
|
|
84
|
+
geometry = ST_C.geometry
|
|
85
|
+
|
|
86
|
+
if (day_of_year is None or hour_of_day is None) and time_UTC is not None and geometry is not None:
|
|
87
|
+
day_of_year = solar_day_of_year_for_area(time_UTC=time_UTC, geometry=geometry)
|
|
88
|
+
hour_of_day = solar_hour_of_day_for_area(time_UTC=time_UTC, geometry=geometry)
|
|
89
|
+
|
|
90
|
+
if time_UTC is None and day_of_year is None and hour_of_day is None:
|
|
91
|
+
raise ValueError("no time given between time_UTC, day_of_year, and hour_of_day")
|
|
92
|
+
|
|
93
|
+
# load air temperature in Celsius if not provided
|
|
94
|
+
if Ta_C is None:
|
|
95
|
+
Ta_C = GEOS5FP_connection.Ta_C(time_UTC=time_UTC, geometry=geometry, resampling=resampling)
|
|
96
|
+
|
|
97
|
+
# load relative humidity if not provided
|
|
98
|
+
if RH is None:
|
|
99
|
+
RH = GEOS5FP_connection.RH(time_UTC=time_UTC, geometry=geometry, resampling=resampling)
|
|
100
|
+
|
|
101
|
+
# load minimum NDVI if not provided
|
|
102
|
+
if NDVI_minimum is None and geometry is not None:
|
|
103
|
+
NDVI_minimum = load_NDVI_minimum(geometry=geometry, resampling=resampling)
|
|
104
|
+
|
|
105
|
+
# load maximum NDVI if not provided
|
|
106
|
+
if NDVI_maximum is None and geometry is not None:
|
|
107
|
+
NDVI_maximum = load_NDVI_maximum(geometry=geometry, resampling=resampling)
|
|
108
|
+
|
|
109
|
+
# load C4 fraction if not provided
|
|
110
|
+
if C4_fraction is None:
|
|
111
|
+
C4_fraction = load_C4_fraction(geometry=geometry, resampling=resampling)
|
|
112
|
+
|
|
113
|
+
# load carbon uptake efficiency if not provided
|
|
114
|
+
if carbon_uptake_efficiency is None:
|
|
115
|
+
carbon_uptake_efficiency = load_carbon_uptake_efficiency(geometry=geometry, resampling=resampling)
|
|
116
|
+
|
|
117
|
+
# load kn if not provided
|
|
118
|
+
if kn is None:
|
|
119
|
+
kn = load_kn(geometry=geometry, resampling=resampling)
|
|
120
|
+
|
|
121
|
+
# load peak VC max for C3 plants if not provided
|
|
122
|
+
if peakVCmax_C3 is None:
|
|
123
|
+
peakVCmax_C3 = load_peakVCmax_C3(geometry=geometry, resampling=resampling)
|
|
124
|
+
|
|
125
|
+
# load peak VC max for C4 plants if not provided
|
|
126
|
+
if peakVCmax_C4 is None:
|
|
127
|
+
peakVCmax_C4 = load_peakVCmax_C4(geometry=geometry, resampling=resampling)
|
|
128
|
+
|
|
129
|
+
# load Ball-Berry slope for C3 plants if not provided
|
|
130
|
+
if ball_berry_slope_C3 is None:
|
|
131
|
+
ball_berry_slope_C3 = load_ball_berry_slope_C3(geometry=geometry, resampling=resampling)
|
|
132
|
+
|
|
133
|
+
# load Ball-Berry slope for C4 plants if not provided
|
|
134
|
+
if ball_berry_slope_C4 is None:
|
|
135
|
+
ball_berry_slope_C4 = load_ball_berry_slope_C4(geometry=geometry, resampling=resampling)
|
|
136
|
+
|
|
137
|
+
# load Ball-Berry intercept for C3 plants if not provided
|
|
138
|
+
if ball_berry_intercept_C3 is None:
|
|
139
|
+
ball_berry_intercept_C3 = load_ball_berry_intercept_C3(geometry=geometry, resampling=resampling)
|
|
140
|
+
|
|
141
|
+
# check if any of the FLiES outputs are not given
|
|
142
|
+
if None in (Rg, VISdiff, VISdir, NIRdiff, NIRdir, UV, albedo_visible, albedo_NIR):
|
|
143
|
+
# load cloud optical thickness if not provided
|
|
144
|
+
if COT is None:
|
|
145
|
+
COT = GEOS5FP_connection.COT(time_UTC=time_UTC, geometry=geometry, resampling=resampling)
|
|
146
|
+
|
|
147
|
+
# load aerosol optical thickness if not provided
|
|
148
|
+
if AOT is None:
|
|
149
|
+
AOT = GEOS5FP_connection.AOT(time_UTC=time_UTC, geometry=geometry, resampling=resampling)
|
|
150
|
+
|
|
151
|
+
## FIXME fix FLiES interface
|
|
152
|
+
|
|
153
|
+
# run FLiES radiative transfer model
|
|
154
|
+
FLiES_results = FLiESANN(
|
|
155
|
+
day_of_year=day_of_year,
|
|
156
|
+
hour_of_day=hour_of_day,
|
|
157
|
+
albedo=albedo,
|
|
158
|
+
COT=COT,
|
|
159
|
+
AOT=AOT,
|
|
160
|
+
vapor_gccm=vapor_gccm,
|
|
161
|
+
ozone_cm=ozone_cm,
|
|
162
|
+
elevation_km=elevation_km,
|
|
163
|
+
SZA=SZA,
|
|
164
|
+
KG_climate=KG_climate,
|
|
165
|
+
geometry=geometry,
|
|
166
|
+
GEOS5FP_connection=GEOS5FP_connection
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
# extract FLiES outputs
|
|
170
|
+
Rg = FLiES_results["Rg"]
|
|
171
|
+
VISdiff = FLiES_results["VISdiff"]
|
|
172
|
+
VISdir = FLiES_results["VISdir"]
|
|
173
|
+
NIRdiff = FLiES_results["NIRdiff"]
|
|
174
|
+
NIRdir = FLiES_results["NIRdir"]
|
|
175
|
+
UV = FLiES_results["UV"]
|
|
176
|
+
albedo_visible = FLiES_results["VIS"]
|
|
177
|
+
albedo_NIR = FLiES_results["NIR"]
|
|
178
|
+
|
|
179
|
+
# load koppen geiger climate classification if not provided
|
|
180
|
+
if KG_climate is None:
|
|
181
|
+
KG_climate = load_koppen_geiger(geometry=geometry)
|
|
182
|
+
|
|
183
|
+
# load canopy height in meters if not provided
|
|
184
|
+
if canopy_height_meters is None:
|
|
185
|
+
canopy_height_meters = load_canopy_height(geometry=geometry, resampling=resampling)
|
|
186
|
+
|
|
187
|
+
# load CO2 concentration in ppm if not provided
|
|
188
|
+
if Ca is None:
|
|
189
|
+
Ca = GEOS5FP_connection.CO2SC(time_UTC=time_UTC, geometry=geometry, resampling=resampling)
|
|
190
|
+
|
|
191
|
+
# load wind speed in meters per second if not provided
|
|
192
|
+
if wind_speed_mps is None:
|
|
193
|
+
wind_speed_mps = GEOS5FP_connection.wind_speed(time_UTC=time_UTC, geometry=geometry, resampling=resampling)
|
|
194
|
+
|
|
195
|
+
# canopy temperature defaults to surface temperature
|
|
196
|
+
if canopy_temperature_C is None:
|
|
197
|
+
canopy_temperature_C = ST_C
|
|
198
|
+
|
|
199
|
+
# soil temperature defaults to surface temperature
|
|
200
|
+
if soil_temperature_C is None:
|
|
201
|
+
soil_temperature_C = ST_C
|
|
202
|
+
|
|
203
|
+
# visible albedo defaults to surface albedo
|
|
204
|
+
if albedo_visible is None:
|
|
205
|
+
albedo_visible = albedo
|
|
206
|
+
|
|
207
|
+
# near-infrared albedo defaults to surface albedo
|
|
208
|
+
if albedo_NIR is None:
|
|
209
|
+
albedo_NIR = albedo
|
|
210
|
+
|
|
211
|
+
# calculate solar zenith angle if not provided
|
|
212
|
+
if SZA is None:
|
|
213
|
+
SZA = calculate_SZA_from_DOY_and_hour(lat, lon, day_of_year, hour_of_day)
|
|
214
|
+
|
|
215
|
+
if CI is None and geometry is not None:
|
|
216
|
+
modisci = MODISCI()
|
|
217
|
+
CI = modisci.CI(geometry=geometry, resampling=resampling)
|
|
218
|
+
|
|
219
|
+
# canopy height defaults to zero
|
|
220
|
+
canopy_height_meters = np.where(np.isnan(canopy_height_meters), 0, canopy_height_meters)
|
|
221
|
+
|
|
222
|
+
# calculate saturation vapor pressure in Pascal from air temperature in Kelvin
|
|
223
|
+
Ta_K = Ta_C + 273.15
|
|
224
|
+
SVP_Pa = SVP_Pa_from_Ta_K(Ta_K)
|
|
225
|
+
|
|
226
|
+
# calculate actual vapor pressure in Pascal from relative humidity and saturation vapor pressure
|
|
227
|
+
Ea_Pa = RH * SVP_Pa
|
|
228
|
+
|
|
229
|
+
# convert elevation to meters
|
|
230
|
+
elevation_m = elevation_km * 1000
|
|
231
|
+
|
|
232
|
+
latitude = geometry.lat
|
|
233
|
+
|
|
234
|
+
Ps_Pa, VPD_Pa, RH, desTa, ddesTa, gamma, Cp, rhoa, epsa, R, Rc, Rs, SFd, SFd2, DL, Ra, fStress = meteorology(
|
|
235
|
+
day_of_year=day_of_year,
|
|
236
|
+
hour_of_day=hour_of_day,
|
|
237
|
+
latitude=latitude,
|
|
238
|
+
elevation_m=elevation_m,
|
|
239
|
+
SZA=SZA,
|
|
240
|
+
Ta_K=Ta_K,
|
|
241
|
+
Ea_Pa=Ea_Pa,
|
|
242
|
+
Rg=Rg,
|
|
243
|
+
wind_speed_mps=wind_speed_mps,
|
|
244
|
+
canopy_height_meters=canopy_height_meters
|
|
245
|
+
)
|
|
246
|
+
|
|
247
|
+
meteorology_outputs = {
|
|
248
|
+
"Ps_Pa": Ps_Pa,
|
|
249
|
+
"VPD_Pa": VPD_Pa,
|
|
250
|
+
"RH": RH,
|
|
251
|
+
"desTa": desTa,
|
|
252
|
+
"ddesTa": ddesTa,
|
|
253
|
+
"gamma": gamma,
|
|
254
|
+
"Cp": Cp,
|
|
255
|
+
"rhoa": rhoa,
|
|
256
|
+
"epsa": epsa,
|
|
257
|
+
"R": R,
|
|
258
|
+
"Rc": Rc,
|
|
259
|
+
"Rs": Rs,
|
|
260
|
+
"SFd": SFd,
|
|
261
|
+
"SFd2": SFd2,
|
|
262
|
+
"DL": DL,
|
|
263
|
+
"Ra": Ra,
|
|
264
|
+
"fStress": fStress
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
# Check the distribution for each variable
|
|
268
|
+
for var_name, var_value in meteorology_outputs.items():
|
|
269
|
+
check_distribution(var_value, var_name, time_UTC)
|
|
270
|
+
|
|
271
|
+
# convert NDVI to LAI
|
|
272
|
+
LAI = LAI_from_NDVI(NDVI)
|
|
273
|
+
LAI_minimum = LAI_from_NDVI(NDVI_minimum)
|
|
274
|
+
LAI_maximum = LAI_from_NDVI(NDVI_maximum)
|
|
275
|
+
|
|
276
|
+
VCmax_C3_sunlit, VCmax_C4_sunlit, VCmax_C3_shaded, VCmax_C4_shaded = calculate_VCmax(
|
|
277
|
+
LAI=LAI,
|
|
278
|
+
LAI_minimum=LAI_minimum,
|
|
279
|
+
LAI_maximum=LAI_maximum,
|
|
280
|
+
peakVCmax_C3=peakVCmax_C3,
|
|
281
|
+
peakVCmax_C4=peakVCmax_C4,
|
|
282
|
+
SZA=SZA,
|
|
283
|
+
kn=kn
|
|
284
|
+
)
|
|
285
|
+
|
|
286
|
+
# List of variable names and their corresponding values
|
|
287
|
+
VCmax_outputs = {
|
|
288
|
+
"VCmax_C3_sunlit": VCmax_C3_sunlit,
|
|
289
|
+
"VCmax_C4_sunlit": VCmax_C4_sunlit,
|
|
290
|
+
"VCmax_C3_shaded": VCmax_C3_shaded,
|
|
291
|
+
"VCmax_C4_shaded": VCmax_C4_shaded
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
# Check the distribution for each variable
|
|
295
|
+
for var_name, var_value in VCmax_outputs.items():
|
|
296
|
+
check_distribution(var_value, var_name, time_UTC)
|
|
297
|
+
|
|
298
|
+
sunlit_fraction, APAR_sunlit, APAR_shaded, ASW_sunlit, ASW_shaded, ASW_soil, G = canopy_shortwave_radiation(
|
|
299
|
+
PARDiff=VISdiff, # diffuse photosynthetically active radiation in W/m^2
|
|
300
|
+
PARDir=VISdir, # direct photosynthetically active radiation in W/m^2
|
|
301
|
+
NIRDiff=NIRdiff, # diffuse near-infrared radiation in W/m^2
|
|
302
|
+
NIRDir=NIRdir, # direct near-infrared radiation in W/m^2
|
|
303
|
+
UV=UV, # incoming ultraviolet radiation in W/m^2
|
|
304
|
+
SZA=SZA, # solar zenith angle in degrees
|
|
305
|
+
LAI=LAI, # leaf area index
|
|
306
|
+
CI=CI, # clumping index
|
|
307
|
+
albedo_visible=albedo_visible, # surface albedo in visible wavelengths
|
|
308
|
+
albedo_NIR=albedo_NIR # surface albedo in near-infrared wavelengths
|
|
309
|
+
)
|
|
310
|
+
|
|
311
|
+
# List of variable names and their corresponding values
|
|
312
|
+
canopy_radiation_outputs = {
|
|
313
|
+
"sunlit_fraction": sunlit_fraction,
|
|
314
|
+
"APAR_sunlit": APAR_sunlit,
|
|
315
|
+
"APAR_shaded": APAR_shaded,
|
|
316
|
+
"ASW_sunlit": ASW_sunlit,
|
|
317
|
+
"ASW_shaded": ASW_shaded,
|
|
318
|
+
"ASW_soil": ASW_soil,
|
|
319
|
+
"G": G
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
# Check the distribution for each variable
|
|
323
|
+
for var_name, var_value in canopy_radiation_outputs.items():
|
|
324
|
+
check_distribution(var_value, var_name, time_UTC)
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
canopy_temperature_K = canopy_temperature_C + 273.15
|
|
328
|
+
soil_temperature_K = soil_temperature_C + 273.15
|
|
329
|
+
|
|
330
|
+
GPP_C3, LE_C3, LE_soil_C3, LE_canopy_C3, Rn_C3, Rn_soil_C3, Rn_canopy_C3 = carbon_water_fluxes(
|
|
331
|
+
canopy_temperature_K=canopy_temperature_K, # canopy temperature in Kelvin
|
|
332
|
+
soil_temperature_K=soil_temperature_K, # soil temperature in Kelvin
|
|
333
|
+
LAI=LAI, # leaf area index
|
|
334
|
+
Ta_K=Ta_K, # air temperature in Kelvin
|
|
335
|
+
APAR_sunlit=APAR_sunlit, # sunlit leaf absorptance of photosynthetically active radiation
|
|
336
|
+
APAR_shaded=APAR_shaded, # shaded leaf absorptance of photosynthetically active radiation
|
|
337
|
+
ASW_sunlit=ASW_sunlit, # sunlit absorbed shortwave radiation
|
|
338
|
+
ASW_shaded=ASW_shaded, # shaded absorbed shortwave radiation
|
|
339
|
+
ASW_soil=ASW_soil, # absorbed shortwave radiation of soil
|
|
340
|
+
Vcmax25_sunlit=VCmax_C3_sunlit, # sunlit maximum carboxylation rate at 25 degrees C
|
|
341
|
+
Vcmax25_shaded=VCmax_C3_shaded, # shaded maximum carboxylation rate at 25 degrees C
|
|
342
|
+
ball_berry_slope=ball_berry_slope_C3, # Ball-Berry slope for C3 photosynthesis
|
|
343
|
+
ball_berry_intercept=ball_berry_intercept_C3, # Ball-Berry intercept for C3 photosynthesis
|
|
344
|
+
sunlit_fraction=sunlit_fraction, # fraction of sunlit leaves
|
|
345
|
+
G=G, # soil heat flux
|
|
346
|
+
SZA=SZA, # solar zenith angle
|
|
347
|
+
Ca=Ca, # atmospheric CO2 concentration
|
|
348
|
+
Ps_Pa=Ps_Pa, # surface pressure in Pascal
|
|
349
|
+
gamma=gamma, # psychrometric constant
|
|
350
|
+
Cp=Cp, # specific heat of air in J/kg/K
|
|
351
|
+
rhoa=rhoa, # density of air in kg/m3
|
|
352
|
+
VPD_Pa=VPD_Pa, # vapor pressure deficit in Pascal
|
|
353
|
+
RH=RH, # relative humidity as a fraction
|
|
354
|
+
desTa=desTa,
|
|
355
|
+
ddesTa=ddesTa,
|
|
356
|
+
epsa=epsa,
|
|
357
|
+
Rc=Rc,
|
|
358
|
+
Rs=Rs,
|
|
359
|
+
carbon_uptake_efficiency=carbon_uptake_efficiency, # intrinsic quantum efficiency for carbon uptake
|
|
360
|
+
fStress=fStress,
|
|
361
|
+
C4_photosynthesis=False # C3 or C4 photosynthesis
|
|
362
|
+
)
|
|
363
|
+
|
|
364
|
+
# List of variable names and their corresponding values
|
|
365
|
+
carbon_water_fluxes_outputs = {
|
|
366
|
+
"GPP_C3": GPP_C3,
|
|
367
|
+
"LE_C3": LE_C3,
|
|
368
|
+
"LE_soil_C3": LE_soil_C3,
|
|
369
|
+
"LE_canopy_C3": LE_canopy_C3,
|
|
370
|
+
"Rn_C3": Rn_C3,
|
|
371
|
+
"Rn_soil_C3": Rn_soil_C3,
|
|
372
|
+
"Rn_canopy_C3": Rn_canopy_C3
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
# Check the distribution for each variable
|
|
376
|
+
for var_name, var_value in carbon_water_fluxes_outputs.items():
|
|
377
|
+
check_distribution(var_value, var_name, time_UTC)
|
|
378
|
+
|
|
379
|
+
|
|
380
|
+
GPP_C4, LE_C4, LE_soil_C4, LE_canopy_C4, Rn_C4, Rn_soil_C4, Rn_canopy_C4 = 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_C4_sunlit, # sunlit maximum carboxylation rate at 25 degrees C
|
|
391
|
+
Vcmax25_shaded=VCmax_C4_shaded, # shaded maximum carboxylation rate at 25 degrees C
|
|
392
|
+
ball_berry_slope=ball_berry_slope_C4, # Ball-Berry slope for C4 photosynthesis
|
|
393
|
+
ball_berry_intercept=ball_berry_intercept_C4, # Ball-Berry intercept for C4 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=True # C3 or C4 photosynthesis
|
|
412
|
+
)
|
|
413
|
+
|
|
414
|
+
# List of variable names and their corresponding values
|
|
415
|
+
carbon_water_fluxes_C4_outputs = {
|
|
416
|
+
"GPP_C4": GPP_C4,
|
|
417
|
+
"LE_C4": LE_C4,
|
|
418
|
+
"LE_soil_C4": LE_soil_C4,
|
|
419
|
+
"LE_canopy_C4": LE_canopy_C4,
|
|
420
|
+
"Rn_C4": Rn_C4,
|
|
421
|
+
"Rn_soil_C4": Rn_soil_C4,
|
|
422
|
+
"Rn_canopy_C4": Rn_canopy_C4
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
# Check the distribution for each variable
|
|
426
|
+
for var_name, var_value in carbon_water_fluxes_C4_outputs.items():
|
|
427
|
+
check_distribution(var_value, var_name, time_UTC)
|
|
428
|
+
|
|
429
|
+
# interpolate C3 and C4 GPP
|
|
430
|
+
ST_K = ST_C + 273.15
|
|
431
|
+
GPP = np.clip(interpolate_C3_C4(GPP_C3, GPP_C4, C4_fraction), 0, 50)
|
|
432
|
+
GPP = np.where(np.isnan(ST_K), np.nan, GPP)
|
|
433
|
+
|
|
434
|
+
# upscale from instantaneous to daily
|
|
435
|
+
|
|
436
|
+
# upscale GPP to daily
|
|
437
|
+
GPP_daily = 1800 * GPP / SFd * 1e-6 * 12 # Eq. (3) in Ryu et al 2008
|
|
438
|
+
GPP_daily = np.where(SFd < 0.01, 0, GPP_daily)
|
|
439
|
+
GPP_daily = np.where(SZA >= 90, 0, GPP_daily)
|
|
440
|
+
|
|
441
|
+
# interpolate C3 and C4 net radiation
|
|
442
|
+
Rn = np.clip(interpolate_C3_C4(Rn_C3, Rn_C4, C4_fraction), 0, 1000)
|
|
443
|
+
|
|
444
|
+
# interpolate C3 and C4 soil net radiation
|
|
445
|
+
Rn_soil = np.clip(interpolate_C3_C4(Rn_soil_C3, Rn_soil_C4, C4_fraction), 0, 1000)
|
|
446
|
+
|
|
447
|
+
# interpolate C3 and C4 canopy net radiation
|
|
448
|
+
Rn_canopy = np.clip(interpolate_C3_C4(Rn_canopy_C3, Rn_canopy_C4, C4_fraction), 0, 1000)
|
|
449
|
+
|
|
450
|
+
# interpolate C3 and C4 latent heat flux
|
|
451
|
+
LE = np.clip(interpolate_C3_C4(LE_C3, LE_C4, C4_fraction), 0, 1000)
|
|
452
|
+
|
|
453
|
+
# interpolate C3 and C4 soil latent heat flux
|
|
454
|
+
LE_soil = np.clip(interpolate_C3_C4(LE_soil_C3, LE_soil_C4, C4_fraction), 0, 1000)
|
|
455
|
+
|
|
456
|
+
# interpolate C3 and C4 canopy latent heat flux
|
|
457
|
+
LE_canopy = np.clip(interpolate_C3_C4(LE_canopy_C3, LE_canopy_C4, C4_fraction), 0, 1000)
|
|
458
|
+
|
|
459
|
+
return {
|
|
460
|
+
"GPP": GPP,
|
|
461
|
+
"GPP_daily": GPP_daily,
|
|
462
|
+
"Rn": Rn,
|
|
463
|
+
"Rn_soil": Rn_soil,
|
|
464
|
+
"Rn_canopy": Rn_canopy,
|
|
465
|
+
"LE": LE,
|
|
466
|
+
"LE_soil": LE_soil,
|
|
467
|
+
"LE_canopy": LE_canopy
|
|
468
|
+
}
|