STIC-JPL 1.1.0__tar.gz → 1.2.1__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 STIC-JPL might be problematic. Click here for more details.
- {stic_jpl-1.1.0 → stic_jpl-1.2.1}/PKG-INFO +18 -10
- {stic_jpl-1.1.0 → stic_jpl-1.2.1}/README.md +9 -6
- stic_jpl-1.2.1/STIC_JPL/FVC_from_NDVI.py +26 -0
- stic_jpl-1.1.0/STIC_JPL/vegetation_conversion/vegetation_conversion.py → stic_jpl-1.2.1/STIC_JPL/LAI_from_NDVI.py +0 -16
- stic_jpl-1.2.1/STIC_JPL/STIC_JPL.py +3 -0
- stic_jpl-1.2.1/STIC_JPL/celcius_to_kelvin.py +11 -0
- stic_jpl-1.2.1/STIC_JPL/generate_STIC_inputs.py +65 -0
- {stic_jpl-1.1.0 → stic_jpl-1.2.1}/STIC_JPL/initialize_with_solar.py +1 -2
- {stic_jpl-1.1.0 → stic_jpl-1.2.1}/STIC_JPL/iterate_with_solar.py +1 -1
- stic_jpl-1.1.0/STIC_JPL/STIC_JPL.py → stic_jpl-1.2.1/STIC_JPL/model.py +5 -6
- stic_jpl-1.2.1/STIC_JPL/process_STIC_table.py +61 -0
- {stic_jpl-1.1.0 → stic_jpl-1.2.1}/STIC_JPL/soil_moisture_initialization.py +2 -1
- stic_jpl-1.2.1/STIC_JPL/version.txt +1 -0
- {stic_jpl-1.1.0 → stic_jpl-1.2.1}/STIC_JPL.egg-info/PKG-INFO +18 -10
- {stic_jpl-1.1.0 → stic_jpl-1.2.1}/STIC_JPL.egg-info/SOURCES.txt +7 -8
- stic_jpl-1.2.1/STIC_JPL.egg-info/requires.txt +21 -0
- {stic_jpl-1.1.0 → stic_jpl-1.2.1}/pyproject.toml +10 -5
- stic_jpl-1.1.0/STIC_JPL/meteorology_conversion/__init__.py +0 -1
- stic_jpl-1.1.0/STIC_JPL/meteorology_conversion/meteorology_conversion.py +0 -123
- stic_jpl-1.1.0/STIC_JPL/soil_heat_flux/__init__.py +0 -1
- stic_jpl-1.1.0/STIC_JPL/soil_heat_flux/calculate_SEBAL_soil_heat_flux.py +0 -40
- stic_jpl-1.1.0/STIC_JPL/timer/__init__.py +0 -1
- stic_jpl-1.1.0/STIC_JPL/vegetation_conversion/__init__.py +0 -1
- stic_jpl-1.1.0/STIC_JPL/version.txt +0 -1
- stic_jpl-1.1.0/STIC_JPL.egg-info/requires.txt +0 -16
- {stic_jpl-1.1.0 → stic_jpl-1.2.1}/STIC_JPL/__init__.py +0 -0
- {stic_jpl-1.1.0 → stic_jpl-1.2.1}/STIC_JPL/canopy_air_stream.py +0 -0
- {stic_jpl-1.1.0 → stic_jpl-1.2.1}/STIC_JPL/closure.py +0 -0
- {stic_jpl-1.1.0 → stic_jpl-1.2.1}/STIC_JPL/constants.py +0 -0
- {stic_jpl-1.1.0 → stic_jpl-1.2.1}/STIC_JPL/diagnostic.py +0 -0
- {stic_jpl-1.1.0 → stic_jpl-1.2.1}/STIC_JPL/initialize_without_solar.py +0 -0
- {stic_jpl-1.1.0 → stic_jpl-1.2.1}/STIC_JPL/iterate_without_solar.py +0 -0
- {stic_jpl-1.1.0 → stic_jpl-1.2.1}/STIC_JPL/net_radiation.py +0 -0
- {stic_jpl-1.1.0 → stic_jpl-1.2.1}/STIC_JPL/root_zone_initialization.py +0 -0
- {stic_jpl-1.1.0 → stic_jpl-1.2.1}/STIC_JPL/root_zone_iteration.py +0 -0
- {stic_jpl-1.1.0 → stic_jpl-1.2.1}/STIC_JPL/soil_moisture_iteration.py +0 -0
- {stic_jpl-1.1.0/STIC_JPL/timer → stic_jpl-1.2.1/STIC_JPL}/timer.py +0 -0
- {stic_jpl-1.1.0 → stic_jpl-1.2.1}/STIC_JPL.egg-info/dependency_links.txt +0 -0
- {stic_jpl-1.1.0 → stic_jpl-1.2.1}/STIC_JPL.egg-info/top_level.txt +0 -0
- {stic_jpl-1.1.0 → stic_jpl-1.2.1}/setup.cfg +0 -0
- {stic_jpl-1.1.0 → stic_jpl-1.2.1}/tests/test_import_STIC.py +0 -0
- {stic_jpl-1.1.0 → stic_jpl-1.2.1}/tests/test_import_dependencies.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: STIC-JPL
|
|
3
|
-
Version: 1.1
|
|
3
|
+
Version: 1.2.1
|
|
4
4
|
Summary: Surface Temperature Initiated Closure (STIC) Evapotranspiration Model Python Implementation
|
|
5
5
|
Author-email: Gregory Halverson <gregory.h.halverson@jpl.nasa.gov>, Kaniska Mallick <kaniska.mallick@list.lu>, Madeleine Pascolini-Campbell <madeleine.a.pascolini-campbell@jpl.nasa.gov>, "Claire S. Villanueva-Weeks" <claire.s.villanueva-weeks@jpl.gov>
|
|
6
6
|
Project-URL: Homepage, https://github.com/JPL-Evapotranspiration-Algorithms/STIC-JPL
|
|
@@ -9,13 +9,18 @@ Classifier: Operating System :: OS Independent
|
|
|
9
9
|
Requires-Python: >=3.10
|
|
10
10
|
Description-Content-Type: text/markdown
|
|
11
11
|
Requires-Dist: colored-logging
|
|
12
|
-
Requires-Dist: ECOv002-CMR
|
|
13
|
-
Requires-Dist: ECOv002-granules
|
|
12
|
+
Requires-Dist: ECOv002-CMR>=1.0.5
|
|
13
|
+
Requires-Dist: ECOv002-granules>=1.0.3
|
|
14
|
+
Requires-Dist: ECOv003-granules
|
|
14
15
|
Requires-Dist: GEOS5FP>=1.1.1
|
|
16
|
+
Requires-Dist: monte-carlo-sensitivity
|
|
15
17
|
Requires-Dist: numpy
|
|
16
18
|
Requires-Dist: pandas
|
|
17
|
-
Requires-Dist: rasters
|
|
19
|
+
Requires-Dist: rasters>=1.4.6
|
|
20
|
+
Requires-Dist: seaborn
|
|
21
|
+
Requires-Dist: SEBAL-soil-heat-flux
|
|
18
22
|
Requires-Dist: solar-apparent-time
|
|
23
|
+
Requires-Dist: verma-net-radiation>=1.1.0
|
|
19
24
|
Provides-Extra: dev
|
|
20
25
|
Requires-Dist: build; extra == "dev"
|
|
21
26
|
Requires-Dist: pytest>=6.0; extra == "dev"
|
|
@@ -24,7 +29,8 @@ Requires-Dist: jupyter; extra == "dev"
|
|
|
24
29
|
Requires-Dist: pytest; extra == "dev"
|
|
25
30
|
Requires-Dist: twine; extra == "dev"
|
|
26
31
|
|
|
27
|
-
#
|
|
32
|
+
# `STIC-JPL`
|
|
33
|
+
## Surface Temperature Initiated Closure (STIC) Evapotranspiration Model Python Implementation
|
|
28
34
|
|
|
29
35
|
[](https://github.com/JPL-Evapotranspiration-Algorithms/STIC/actions/workflows/ci.yml)
|
|
30
36
|
|
|
@@ -63,21 +69,23 @@ NASA Jet Propulsion Laboratory 329G
|
|
|
63
69
|
|
|
64
70
|
## Installation
|
|
65
71
|
|
|
66
|
-
Use the pip package manager to install the `STIC` PyPi package.
|
|
72
|
+
Use the pip package manager to install the `STIC-JPL` PyPi package with dashes in the name.
|
|
67
73
|
|
|
68
74
|
```
|
|
69
|
-
pip install STIC
|
|
75
|
+
pip install STIC-JPL
|
|
70
76
|
```
|
|
71
77
|
|
|
72
78
|
## Usage
|
|
73
79
|
|
|
74
|
-
Import the `
|
|
80
|
+
Import the `STIC_JPL` function from the `STIC_JPL` package with underscores in the name.
|
|
75
81
|
|
|
76
82
|
```
|
|
77
|
-
from
|
|
83
|
+
from STIC_JPL import STIC_JPL
|
|
78
84
|
```
|
|
79
85
|
|
|
80
|
-
See the [ECOSTRESS example](ECOSTRESS%20Example.ipynb) for usage.
|
|
86
|
+
See the [ECOSTRESS example](ECOSTRESS%20Example.ipynb) notebook for usage.
|
|
87
|
+
|
|
88
|
+
See the [STIC sensitivity](STIC%20Sensitivity.ipynb) notebook for sensitivity analysis.
|
|
81
89
|
|
|
82
90
|
## References
|
|
83
91
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
#
|
|
1
|
+
# `STIC-JPL`
|
|
2
|
+
## Surface Temperature Initiated Closure (STIC) Evapotranspiration Model Python Implementation
|
|
2
3
|
|
|
3
4
|
[](https://github.com/JPL-Evapotranspiration-Algorithms/STIC/actions/workflows/ci.yml)
|
|
4
5
|
|
|
@@ -37,21 +38,23 @@ NASA Jet Propulsion Laboratory 329G
|
|
|
37
38
|
|
|
38
39
|
## Installation
|
|
39
40
|
|
|
40
|
-
Use the pip package manager to install the `STIC` PyPi package.
|
|
41
|
+
Use the pip package manager to install the `STIC-JPL` PyPi package with dashes in the name.
|
|
41
42
|
|
|
42
43
|
```
|
|
43
|
-
pip install STIC
|
|
44
|
+
pip install STIC-JPL
|
|
44
45
|
```
|
|
45
46
|
|
|
46
47
|
## Usage
|
|
47
48
|
|
|
48
|
-
Import the `
|
|
49
|
+
Import the `STIC_JPL` function from the `STIC_JPL` package with underscores in the name.
|
|
49
50
|
|
|
50
51
|
```
|
|
51
|
-
from
|
|
52
|
+
from STIC_JPL import STIC_JPL
|
|
52
53
|
```
|
|
53
54
|
|
|
54
|
-
See the [ECOSTRESS example](ECOSTRESS%20Example.ipynb) for usage.
|
|
55
|
+
See the [ECOSTRESS example](ECOSTRESS%20Example.ipynb) notebook for usage.
|
|
56
|
+
|
|
57
|
+
See the [STIC sensitivity](STIC%20Sensitivity.ipynb) notebook for sensitivity analysis.
|
|
55
58
|
|
|
56
59
|
## References
|
|
57
60
|
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
from typing import Union
|
|
2
|
+
import numpy as np
|
|
3
|
+
import rasters as rt
|
|
4
|
+
from rasters import Raster
|
|
5
|
+
|
|
6
|
+
KPAR = 0.5
|
|
7
|
+
MIN_FIPAR = 0.0
|
|
8
|
+
MAX_FIPAR = 1.0
|
|
9
|
+
MIN_LAI = 0.0
|
|
10
|
+
MAX_LAI = 10.0
|
|
11
|
+
|
|
12
|
+
def FVC_from_NDVI(NDVI: Union[Raster, np.ndarray]) -> Union[Raster, np.ndarray]:
|
|
13
|
+
"""
|
|
14
|
+
Convert Normalized Difference Vegetation Index (NDVI) to Fractional Vegetation Cover (FVC).
|
|
15
|
+
|
|
16
|
+
Parameters:
|
|
17
|
+
NDVI (Union[Raster, np.ndarray]): Input NDVI data.
|
|
18
|
+
|
|
19
|
+
Returns:
|
|
20
|
+
Union[Raster, np.ndarray]: Converted FVC data.
|
|
21
|
+
"""
|
|
22
|
+
NDVIv = 0.52 # +- 0.03
|
|
23
|
+
NDVIs = 0.04 # +- 0.03
|
|
24
|
+
FVC = rt.clip((NDVI - NDVIs) / (NDVIv - NDVIs), 0.0, 1.0)
|
|
25
|
+
|
|
26
|
+
return FVC
|
|
@@ -9,22 +9,6 @@ MAX_FIPAR = 1.0
|
|
|
9
9
|
MIN_LAI = 0.0
|
|
10
10
|
MAX_LAI = 10.0
|
|
11
11
|
|
|
12
|
-
def FVC_from_NDVI(NDVI: Union[Raster, np.ndarray]) -> Union[Raster, np.ndarray]:
|
|
13
|
-
"""
|
|
14
|
-
Convert Normalized Difference Vegetation Index (NDVI) to Fractional Vegetation Cover (FVC).
|
|
15
|
-
|
|
16
|
-
Parameters:
|
|
17
|
-
NDVI (Union[Raster, np.ndarray]): Input NDVI data.
|
|
18
|
-
|
|
19
|
-
Returns:
|
|
20
|
-
Union[Raster, np.ndarray]: Converted FVC data.
|
|
21
|
-
"""
|
|
22
|
-
NDVIv = 0.52 # +- 0.03
|
|
23
|
-
NDVIs = 0.04 # +- 0.03
|
|
24
|
-
FVC = rt.clip((NDVI - NDVIs) / (NDVIv - NDVIs), 0.0, 1.0)
|
|
25
|
-
|
|
26
|
-
return FVC
|
|
27
|
-
|
|
28
12
|
def LAI_from_NDVI(
|
|
29
13
|
NDVI: Union[Raster, np.ndarray],
|
|
30
14
|
min_fIPAR: float = MIN_FIPAR,
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from typing import Union
|
|
2
|
+
import numpy as np
|
|
3
|
+
from rasters import Raster
|
|
4
|
+
|
|
5
|
+
def celcius_to_kelvin(T_C: Union[Raster, np.ndarray]) -> Union[Raster, np.ndarray]:
|
|
6
|
+
"""
|
|
7
|
+
convert temperature in celsius to kelvin.
|
|
8
|
+
:param T_C: temperature in celsius
|
|
9
|
+
:return: temperature in kelvin
|
|
10
|
+
"""
|
|
11
|
+
return T_C + 273.15
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
from dateutil import parser
|
|
5
|
+
from pandas import DataFrame
|
|
6
|
+
from rasters import Point
|
|
7
|
+
from sentinel_tiles import sentinel_tiles
|
|
8
|
+
from solar_apparent_time import UTC_to_solar
|
|
9
|
+
from SEBAL_soil_heat_flux import calculate_SEBAL_soil_heat_flux
|
|
10
|
+
|
|
11
|
+
from .model import STIC_JPL, MAX_ITERATIONS, USE_VARIABLE_ALPHA
|
|
12
|
+
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
def generate_STIC_inputs(STIC_inputs_from_calval_df: DataFrame) -> DataFrame:
|
|
16
|
+
"""
|
|
17
|
+
STIC_inputs_from_claval_df:
|
|
18
|
+
Pandas DataFrame containing the columns: tower, lat, lon, time_UTC, albedo, elevation_km
|
|
19
|
+
return:
|
|
20
|
+
Pandas DataFrame containing the columns: tower, lat, lon, time_UTC, doy, albedo, elevation_km, AOT, COT, vapor_gccm, ozone_cm, SZA, KG
|
|
21
|
+
"""
|
|
22
|
+
# output_rows = []
|
|
23
|
+
STIC_inputs_df = STIC_inputs_from_calval_df.copy()
|
|
24
|
+
|
|
25
|
+
hour_of_day = []
|
|
26
|
+
doy = []
|
|
27
|
+
Topt = []
|
|
28
|
+
fAPARmax = []
|
|
29
|
+
|
|
30
|
+
for i, input_row in STIC_inputs_from_calval_df.iterrows():
|
|
31
|
+
tower = input_row.tower
|
|
32
|
+
lat = input_row.lat
|
|
33
|
+
lon = input_row.lon
|
|
34
|
+
time_UTC = input_row.time_UTC
|
|
35
|
+
albedo = input_row.albedo
|
|
36
|
+
elevation_km = input_row.elevation_km
|
|
37
|
+
logger.info(f"collecting STIC inputs for tower {tower} lat {lat} lon {lon} time {time_UTC} UTC")
|
|
38
|
+
time_UTC = parser.parse(str(time_UTC))
|
|
39
|
+
time_solar = UTC_to_solar(time_UTC, lon)
|
|
40
|
+
hour_of_day.append(time_solar.hour)
|
|
41
|
+
doy.append(time_UTC.timetuple().tm_yday)
|
|
42
|
+
date_UTC = time_UTC.date()
|
|
43
|
+
tile = sentinel_tiles.toMGRS(lat, lon)[:5]
|
|
44
|
+
tile_grid = sentinel_tiles.grid(tile=tile, cell_size=70)
|
|
45
|
+
rows, cols = tile_grid.shape
|
|
46
|
+
row, col = tile_grid.index_point(Point(lon, lat))
|
|
47
|
+
geometry = tile_grid[max(0, row - 1):min(row + 2, rows - 1),
|
|
48
|
+
max(0, col - 1):min(col + 2, cols - 1)]
|
|
49
|
+
|
|
50
|
+
if not "hour_of_day" in STIC_inputs_df.columns:
|
|
51
|
+
STIC_inputs_df["hour_of_day"] = hour_of_day
|
|
52
|
+
|
|
53
|
+
if not "doy" in STIC_inputs_df.columns:
|
|
54
|
+
STIC_inputs_df["doy"] = doy
|
|
55
|
+
|
|
56
|
+
if not "Topt" in STIC_inputs_df.columns:
|
|
57
|
+
STIC_inputs_df["Topt"] = Topt
|
|
58
|
+
|
|
59
|
+
if not "fAPARmax" in STIC_inputs_df.columns:
|
|
60
|
+
STIC_inputs_df["fAPARmax"] = fAPARmax
|
|
61
|
+
|
|
62
|
+
if "Ta" in STIC_inputs_df and "Ta_C" not in STIC_inputs_df:
|
|
63
|
+
STIC_inputs_df.rename({"Ta": "Ta_C"}, inplace=True)
|
|
64
|
+
|
|
65
|
+
return STIC_inputs_df
|
|
@@ -5,8 +5,7 @@ import rasters as rt
|
|
|
5
5
|
|
|
6
6
|
from rasters import Raster
|
|
7
7
|
|
|
8
|
-
from
|
|
9
|
-
from .soil_heat_flux import calculate_SEBAL_soil_heat_flux
|
|
8
|
+
from SEBAL_soil_heat_flux import calculate_SEBAL_soil_heat_flux
|
|
10
9
|
|
|
11
10
|
from .constants import *
|
|
12
11
|
from .soil_moisture_initialization import initialize_soil_moisture
|
|
@@ -5,7 +5,7 @@ import rasters as rt
|
|
|
5
5
|
|
|
6
6
|
from rasters import Raster
|
|
7
7
|
|
|
8
|
-
from
|
|
8
|
+
from SEBAL_soil_heat_flux import calculate_SEBAL_soil_heat_flux
|
|
9
9
|
|
|
10
10
|
from .constants import *
|
|
11
11
|
from .canopy_air_stream import calculate_canopy_air_stream_vapor_pressure
|
|
@@ -7,17 +7,13 @@ import numpy as np
|
|
|
7
7
|
import warnings
|
|
8
8
|
from .diagnostic import diagnostic
|
|
9
9
|
import colored_logging as cl
|
|
10
|
-
from .meteorology_conversion import calculate_air_density, calculate_specific_heat, calculate_specific_humidity, calculate_surface_pressure, celcius_to_kelvin
|
|
11
10
|
import rasters as rt
|
|
12
11
|
from GEOS5FP import GEOS5FP
|
|
13
12
|
from solar_apparent_time import solar_day_of_year_for_area, solar_hour_of_day_for_area
|
|
14
|
-
|
|
15
|
-
from .timer import Timer
|
|
13
|
+
from SEBAL_soil_heat_flux import calculate_SEBAL_soil_heat_flux
|
|
16
14
|
|
|
17
15
|
from rasters import Raster, RasterGeometry
|
|
18
16
|
|
|
19
|
-
from .vegetation_conversion.vegetation_conversion import FVC_from_NDVI, LAI_from_NDVI
|
|
20
|
-
|
|
21
17
|
from .constants import *
|
|
22
18
|
from .closure import STIC_closure
|
|
23
19
|
from .soil_moisture_initialization import initialize_soil_moisture
|
|
@@ -29,8 +25,11 @@ from .initialize_without_solar import initialize_without_solar
|
|
|
29
25
|
from .iterate_with_solar import iterate_with_solar
|
|
30
26
|
from .iterate_without_solar import iterate_without_solar
|
|
31
27
|
from .root_zone_initialization import calculate_root_zone_moisture
|
|
28
|
+
from .FVC_from_NDVI import FVC_from_NDVI
|
|
29
|
+
from .LAI_from_NDVI import LAI_from_NDVI
|
|
30
|
+
from .celcius_to_kelvin import celcius_to_kelvin
|
|
32
31
|
|
|
33
|
-
from .
|
|
32
|
+
from .timer import Timer
|
|
34
33
|
|
|
35
34
|
__author__ = 'Kaniska Mallick, Madeleine Pascolini-Campbell, Gregory Halverson'
|
|
36
35
|
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
from dateutil import parser
|
|
5
|
+
from pandas import DataFrame
|
|
6
|
+
from rasters import Point
|
|
7
|
+
from sentinel_tiles import sentinel_tiles
|
|
8
|
+
from solar_apparent_time import UTC_to_solar
|
|
9
|
+
from SEBAL_soil_heat_flux import calculate_SEBAL_soil_heat_flux
|
|
10
|
+
|
|
11
|
+
from .model import STIC_JPL, MAX_ITERATIONS, USE_VARIABLE_ALPHA
|
|
12
|
+
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
def process_STIC_table(
|
|
16
|
+
input_df: DataFrame,
|
|
17
|
+
max_iterations = MAX_ITERATIONS,
|
|
18
|
+
use_variable_alpha = USE_VARIABLE_ALPHA) -> DataFrame:
|
|
19
|
+
hour_of_day = np.float64(np.array(input_df.hour_of_day))
|
|
20
|
+
lon = np.float64(np.array(input_df.lon))
|
|
21
|
+
ST_C = np.float64(np.array(input_df.ST_C))
|
|
22
|
+
emissivity = np.float64(np.array(input_df.EmisWB))
|
|
23
|
+
NDVI = np.float64(np.array(input_df.NDVI))
|
|
24
|
+
albedo = np.float64(np.array(input_df.albedo))
|
|
25
|
+
Ta_C = np.float64(np.array(input_df.Ta_C))
|
|
26
|
+
RH = np.float64(np.array(input_df.RH))
|
|
27
|
+
Rn = np.float64(np.array(input_df.Rn))
|
|
28
|
+
Rg = np.float64(np.array(input_df.Rg))
|
|
29
|
+
|
|
30
|
+
if "G" in input_df:
|
|
31
|
+
G = np.array(input_df.G)
|
|
32
|
+
else:
|
|
33
|
+
G = calculate_SEBAL_soil_heat_flux(
|
|
34
|
+
Rn=Rn,
|
|
35
|
+
ST_C=ST_C,
|
|
36
|
+
NDVI=NDVI,
|
|
37
|
+
albedo=albedo
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
results = STIC_JPL(
|
|
41
|
+
hour_of_day=hour_of_day,
|
|
42
|
+
# longitude=lon,
|
|
43
|
+
ST_C = ST_C,
|
|
44
|
+
emissivity=emissivity,
|
|
45
|
+
NDVI=NDVI,
|
|
46
|
+
albedo=albedo,
|
|
47
|
+
Ta_C=Ta_C,
|
|
48
|
+
RH=RH,
|
|
49
|
+
Rn_Wm2=Rn,
|
|
50
|
+
G=G,
|
|
51
|
+
# Rg_Wm2=Rg,
|
|
52
|
+
max_iterations=max_iterations,
|
|
53
|
+
use_variable_alpha=use_variable_alpha
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
output_df = input_df.copy()
|
|
57
|
+
|
|
58
|
+
for key, value in results.items():
|
|
59
|
+
output_df[key] = value
|
|
60
|
+
|
|
61
|
+
return output_df
|
|
@@ -4,7 +4,8 @@ import numpy as np
|
|
|
4
4
|
import rasters as rt
|
|
5
5
|
from rasters import Raster
|
|
6
6
|
|
|
7
|
-
from .
|
|
7
|
+
from .FVC_from_NDVI import FVC_from_NDVI
|
|
8
|
+
from .LAI_from_NDVI import LAI_from_NDVI
|
|
8
9
|
|
|
9
10
|
from .constants import GAMMA_HPA
|
|
10
11
|
from .root_zone_initialization import calculate_root_zone_moisture
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
1.2.1
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: STIC-JPL
|
|
3
|
-
Version: 1.1
|
|
3
|
+
Version: 1.2.1
|
|
4
4
|
Summary: Surface Temperature Initiated Closure (STIC) Evapotranspiration Model Python Implementation
|
|
5
5
|
Author-email: Gregory Halverson <gregory.h.halverson@jpl.nasa.gov>, Kaniska Mallick <kaniska.mallick@list.lu>, Madeleine Pascolini-Campbell <madeleine.a.pascolini-campbell@jpl.nasa.gov>, "Claire S. Villanueva-Weeks" <claire.s.villanueva-weeks@jpl.gov>
|
|
6
6
|
Project-URL: Homepage, https://github.com/JPL-Evapotranspiration-Algorithms/STIC-JPL
|
|
@@ -9,13 +9,18 @@ Classifier: Operating System :: OS Independent
|
|
|
9
9
|
Requires-Python: >=3.10
|
|
10
10
|
Description-Content-Type: text/markdown
|
|
11
11
|
Requires-Dist: colored-logging
|
|
12
|
-
Requires-Dist: ECOv002-CMR
|
|
13
|
-
Requires-Dist: ECOv002-granules
|
|
12
|
+
Requires-Dist: ECOv002-CMR>=1.0.5
|
|
13
|
+
Requires-Dist: ECOv002-granules>=1.0.3
|
|
14
|
+
Requires-Dist: ECOv003-granules
|
|
14
15
|
Requires-Dist: GEOS5FP>=1.1.1
|
|
16
|
+
Requires-Dist: monte-carlo-sensitivity
|
|
15
17
|
Requires-Dist: numpy
|
|
16
18
|
Requires-Dist: pandas
|
|
17
|
-
Requires-Dist: rasters
|
|
19
|
+
Requires-Dist: rasters>=1.4.6
|
|
20
|
+
Requires-Dist: seaborn
|
|
21
|
+
Requires-Dist: SEBAL-soil-heat-flux
|
|
18
22
|
Requires-Dist: solar-apparent-time
|
|
23
|
+
Requires-Dist: verma-net-radiation>=1.1.0
|
|
19
24
|
Provides-Extra: dev
|
|
20
25
|
Requires-Dist: build; extra == "dev"
|
|
21
26
|
Requires-Dist: pytest>=6.0; extra == "dev"
|
|
@@ -24,7 +29,8 @@ Requires-Dist: jupyter; extra == "dev"
|
|
|
24
29
|
Requires-Dist: pytest; extra == "dev"
|
|
25
30
|
Requires-Dist: twine; extra == "dev"
|
|
26
31
|
|
|
27
|
-
#
|
|
32
|
+
# `STIC-JPL`
|
|
33
|
+
## Surface Temperature Initiated Closure (STIC) Evapotranspiration Model Python Implementation
|
|
28
34
|
|
|
29
35
|
[](https://github.com/JPL-Evapotranspiration-Algorithms/STIC/actions/workflows/ci.yml)
|
|
30
36
|
|
|
@@ -63,21 +69,23 @@ NASA Jet Propulsion Laboratory 329G
|
|
|
63
69
|
|
|
64
70
|
## Installation
|
|
65
71
|
|
|
66
|
-
Use the pip package manager to install the `STIC` PyPi package.
|
|
72
|
+
Use the pip package manager to install the `STIC-JPL` PyPi package with dashes in the name.
|
|
67
73
|
|
|
68
74
|
```
|
|
69
|
-
pip install STIC
|
|
75
|
+
pip install STIC-JPL
|
|
70
76
|
```
|
|
71
77
|
|
|
72
78
|
## Usage
|
|
73
79
|
|
|
74
|
-
Import the `
|
|
80
|
+
Import the `STIC_JPL` function from the `STIC_JPL` package with underscores in the name.
|
|
75
81
|
|
|
76
82
|
```
|
|
77
|
-
from
|
|
83
|
+
from STIC_JPL import STIC_JPL
|
|
78
84
|
```
|
|
79
85
|
|
|
80
|
-
See the [ECOSTRESS example](ECOSTRESS%20Example.ipynb) for usage.
|
|
86
|
+
See the [ECOSTRESS example](ECOSTRESS%20Example.ipynb) notebook for usage.
|
|
87
|
+
|
|
88
|
+
See the [STIC sensitivity](STIC%20Sensitivity.ipynb) notebook for sensitivity analysis.
|
|
81
89
|
|
|
82
90
|
## References
|
|
83
91
|
|
|
@@ -1,33 +1,32 @@
|
|
|
1
1
|
README.md
|
|
2
2
|
pyproject.toml
|
|
3
|
+
STIC_JPL/FVC_from_NDVI.py
|
|
4
|
+
STIC_JPL/LAI_from_NDVI.py
|
|
3
5
|
STIC_JPL/STIC_JPL.py
|
|
4
6
|
STIC_JPL/__init__.py
|
|
5
7
|
STIC_JPL/canopy_air_stream.py
|
|
8
|
+
STIC_JPL/celcius_to_kelvin.py
|
|
6
9
|
STIC_JPL/closure.py
|
|
7
10
|
STIC_JPL/constants.py
|
|
8
11
|
STIC_JPL/diagnostic.py
|
|
12
|
+
STIC_JPL/generate_STIC_inputs.py
|
|
9
13
|
STIC_JPL/initialize_with_solar.py
|
|
10
14
|
STIC_JPL/initialize_without_solar.py
|
|
11
15
|
STIC_JPL/iterate_with_solar.py
|
|
12
16
|
STIC_JPL/iterate_without_solar.py
|
|
17
|
+
STIC_JPL/model.py
|
|
13
18
|
STIC_JPL/net_radiation.py
|
|
19
|
+
STIC_JPL/process_STIC_table.py
|
|
14
20
|
STIC_JPL/root_zone_initialization.py
|
|
15
21
|
STIC_JPL/root_zone_iteration.py
|
|
16
22
|
STIC_JPL/soil_moisture_initialization.py
|
|
17
23
|
STIC_JPL/soil_moisture_iteration.py
|
|
24
|
+
STIC_JPL/timer.py
|
|
18
25
|
STIC_JPL/version.txt
|
|
19
26
|
STIC_JPL.egg-info/PKG-INFO
|
|
20
27
|
STIC_JPL.egg-info/SOURCES.txt
|
|
21
28
|
STIC_JPL.egg-info/dependency_links.txt
|
|
22
29
|
STIC_JPL.egg-info/requires.txt
|
|
23
30
|
STIC_JPL.egg-info/top_level.txt
|
|
24
|
-
STIC_JPL/meteorology_conversion/__init__.py
|
|
25
|
-
STIC_JPL/meteorology_conversion/meteorology_conversion.py
|
|
26
|
-
STIC_JPL/soil_heat_flux/__init__.py
|
|
27
|
-
STIC_JPL/soil_heat_flux/calculate_SEBAL_soil_heat_flux.py
|
|
28
|
-
STIC_JPL/timer/__init__.py
|
|
29
|
-
STIC_JPL/timer/timer.py
|
|
30
|
-
STIC_JPL/vegetation_conversion/__init__.py
|
|
31
|
-
STIC_JPL/vegetation_conversion/vegetation_conversion.py
|
|
32
31
|
tests/test_import_STIC.py
|
|
33
32
|
tests/test_import_dependencies.py
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
colored-logging
|
|
2
|
+
ECOv002-CMR>=1.0.5
|
|
3
|
+
ECOv002-granules>=1.0.3
|
|
4
|
+
ECOv003-granules
|
|
5
|
+
GEOS5FP>=1.1.1
|
|
6
|
+
monte-carlo-sensitivity
|
|
7
|
+
numpy
|
|
8
|
+
pandas
|
|
9
|
+
rasters>=1.4.6
|
|
10
|
+
seaborn
|
|
11
|
+
SEBAL-soil-heat-flux
|
|
12
|
+
solar-apparent-time
|
|
13
|
+
verma-net-radiation>=1.1.0
|
|
14
|
+
|
|
15
|
+
[dev]
|
|
16
|
+
build
|
|
17
|
+
pytest>=6.0
|
|
18
|
+
pytest-cov
|
|
19
|
+
jupyter
|
|
20
|
+
pytest
|
|
21
|
+
twine
|
|
@@ -3,7 +3,7 @@ requires = ["setuptools", "wheel"]
|
|
|
3
3
|
|
|
4
4
|
[project]
|
|
5
5
|
name = "STIC-JPL"
|
|
6
|
-
version = "1.1
|
|
6
|
+
version = "1.2.1"
|
|
7
7
|
description = "Surface Temperature Initiated Closure (STIC) Evapotranspiration Model Python Implementation"
|
|
8
8
|
readme = "README.md"
|
|
9
9
|
authors = [
|
|
@@ -18,13 +18,18 @@ classifiers = [
|
|
|
18
18
|
]
|
|
19
19
|
dependencies = [
|
|
20
20
|
"colored-logging",
|
|
21
|
-
"ECOv002-CMR",
|
|
22
|
-
"ECOv002-granules",
|
|
21
|
+
"ECOv002-CMR>=1.0.5",
|
|
22
|
+
"ECOv002-granules>=1.0.3",
|
|
23
|
+
"ECOv003-granules",
|
|
23
24
|
"GEOS5FP>=1.1.1",
|
|
25
|
+
"monte-carlo-sensitivity",
|
|
24
26
|
"numpy",
|
|
25
27
|
"pandas",
|
|
26
|
-
"rasters",
|
|
27
|
-
"
|
|
28
|
+
"rasters>=1.4.6",
|
|
29
|
+
"seaborn",
|
|
30
|
+
"SEBAL-soil-heat-flux",
|
|
31
|
+
"solar-apparent-time",
|
|
32
|
+
"verma-net-radiation>=1.1.0"
|
|
28
33
|
]
|
|
29
34
|
requires-python = ">=3.10"
|
|
30
35
|
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
from .meteorology_conversion import *
|
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
from typing import Union
|
|
2
|
-
import numpy as np
|
|
3
|
-
import rasters as rt
|
|
4
|
-
from rasters import Raster
|
|
5
|
-
|
|
6
|
-
# gas constant for dry air in joules per kilogram per kelvin
|
|
7
|
-
RD = 286.9
|
|
8
|
-
|
|
9
|
-
# gas constant for moist air in joules per kilogram per kelvin
|
|
10
|
-
RW = 461.5
|
|
11
|
-
|
|
12
|
-
# specific heat of water vapor in joules per kilogram per kelvin
|
|
13
|
-
CPW = 1846.0
|
|
14
|
-
|
|
15
|
-
# specific heat of dry air in joules per kilogram per kelvin
|
|
16
|
-
CPD = 1005.0
|
|
17
|
-
|
|
18
|
-
def kelvin_to_celsius(T_K: Union[Raster, np.ndarray]) -> Union[Raster, np.ndarray]:
|
|
19
|
-
"""
|
|
20
|
-
convert temperature in kelvin to celsius.
|
|
21
|
-
:param T_K: temperature in kelvin
|
|
22
|
-
:return: temperature in celsius
|
|
23
|
-
"""
|
|
24
|
-
return T_K - 273.15
|
|
25
|
-
|
|
26
|
-
def celcius_to_kelvin(T_C: Union[Raster, np.ndarray]) -> Union[Raster, np.ndarray]:
|
|
27
|
-
"""
|
|
28
|
-
convert temperature in celsius to kelvin.
|
|
29
|
-
:param T_C: temperature in celsius
|
|
30
|
-
:return: temperature in kelvin
|
|
31
|
-
"""
|
|
32
|
-
return T_C + 273.15
|
|
33
|
-
|
|
34
|
-
def calculate_specific_humidity(
|
|
35
|
-
Ea_Pa: Union[Raster, np.ndarray],
|
|
36
|
-
Ps_Pa: Union[Raster, np.ndarray]) -> Union[Raster, np.ndarray]:
|
|
37
|
-
"""
|
|
38
|
-
Calculate the specific humidity of air as a ratio of kilograms of water to kilograms of air.
|
|
39
|
-
|
|
40
|
-
Args:
|
|
41
|
-
Ea_Pa (Union[Raster, np.ndarray]): Actual water vapor pressure in Pascal.
|
|
42
|
-
surface_pressure_Pa (Union[Raster, np.ndarray]): Surface pressure in Pascal.
|
|
43
|
-
|
|
44
|
-
Returns:
|
|
45
|
-
Union[Raster, np.ndarray]: Specific humidity in kilograms of water per kilograms of air.
|
|
46
|
-
"""
|
|
47
|
-
return ((0.622 * Ea_Pa) / (Ps_Pa - (0.387 * Ea_Pa)))
|
|
48
|
-
|
|
49
|
-
def calculate_specific_heat(specific_humidity: Union[Raster, np.ndarray]):
|
|
50
|
-
# calculate specific heat capacity of the air (Cp)
|
|
51
|
-
# in joules per kilogram per kelvin
|
|
52
|
-
# from specific heat of water vapor (CPW)
|
|
53
|
-
# and specific heat of dry air (CPD)
|
|
54
|
-
Cp_Jkg = specific_humidity * CPW + (1 - specific_humidity) * CPD
|
|
55
|
-
|
|
56
|
-
return Cp_Jkg
|
|
57
|
-
|
|
58
|
-
def calculate_air_density(
|
|
59
|
-
surface_pressure_Pa: Union[Raster, np.ndarray],
|
|
60
|
-
Ta_K: Union[Raster, np.ndarray],
|
|
61
|
-
specific_humidity: Union[Raster, np.ndarray]) -> Union[Raster, np.ndarray]:
|
|
62
|
-
"""
|
|
63
|
-
Calculate air density.
|
|
64
|
-
|
|
65
|
-
Parameters:
|
|
66
|
-
surface_pressure_Pa (Union[Raster, np.ndarray]): Surface pressure in Pascal.
|
|
67
|
-
Ta_K (Union[Raster, np.ndarray]): Air temperature in Kelvin.
|
|
68
|
-
specific_humidity (Union[Raster, np.ndarray]): Specific humidity.
|
|
69
|
-
|
|
70
|
-
Returns:
|
|
71
|
-
Union[Raster, np.ndarray]: Air density in kilograms per cubic meter.
|
|
72
|
-
"""
|
|
73
|
-
# numerator: Pa(N / m ^ 2 = kg * m / s ^ 2); denominator: J / kg / K * K)
|
|
74
|
-
rhoD = surface_pressure_Pa / (RD * Ta_K)
|
|
75
|
-
|
|
76
|
-
# calculate air density (rho) in kilograms per cubic meter
|
|
77
|
-
rho = rhoD * ((1.0 + specific_humidity) / (1.0 + specific_humidity * (RW / RD)))
|
|
78
|
-
|
|
79
|
-
return rho
|
|
80
|
-
|
|
81
|
-
def SVP_kPa_from_Ta_C(Ta_C: Union[Raster, np.ndarray]) -> Union[Raster, np.ndarray]:
|
|
82
|
-
"""
|
|
83
|
-
Calculate the saturation vapor pressure in kiloPascal (kPa) from air temperature in Celsius.
|
|
84
|
-
|
|
85
|
-
Parameters:
|
|
86
|
-
Ta_C (Union[Raster, np.ndarray]): Air temperature in Celsius.
|
|
87
|
-
|
|
88
|
-
Returns:
|
|
89
|
-
Union[Raster, np.ndarray]: Saturation vapor pressure in kPa.
|
|
90
|
-
|
|
91
|
-
"""
|
|
92
|
-
SVP_kPa = np.clip(0.611 * np.exp((Ta_C * 17.27) / (Ta_C + 237.7)), 1, None)
|
|
93
|
-
|
|
94
|
-
return SVP_kPa
|
|
95
|
-
|
|
96
|
-
def SVP_Pa_from_Ta_C(Ta_C: Union[Raster, np.ndarray]) -> Union[Raster, np.ndarray]:
|
|
97
|
-
"""
|
|
98
|
-
Calculate the saturation vapor pressure in Pascal (Pa) from the air temperature in Celsius (Ta_C).
|
|
99
|
-
|
|
100
|
-
Parameters:
|
|
101
|
-
Ta_C (Union[Raster, np.ndarray]): Air temperature in Celsius.
|
|
102
|
-
|
|
103
|
-
Returns:
|
|
104
|
-
Union[Raster, np.ndarray]: Saturation vapor pressure in Pascal (Pa).
|
|
105
|
-
"""
|
|
106
|
-
return SVP_kPa_from_Ta_C(Ta_C) * 1000
|
|
107
|
-
|
|
108
|
-
def calculate_surface_pressure(elevation_m: Union[Raster, np.ndarray], Ta_C: Union[Raster, np.ndarray]) -> Union[Raster, np.ndarray]:
|
|
109
|
-
"""
|
|
110
|
-
Calculate surface pressure using elevation and air temperature.
|
|
111
|
-
|
|
112
|
-
Parameters:
|
|
113
|
-
elevation_m (Union[Raster, np.ndarray]): Elevation in meters.
|
|
114
|
-
Ta_K (Union[Raster, np.ndarray]): Air temperature in Kelvin.
|
|
115
|
-
|
|
116
|
-
Returns:
|
|
117
|
-
Union[Raster, np.ndarray]: Surface pressure in Pascal (Pa).
|
|
118
|
-
"""
|
|
119
|
-
Ta_K = kelvin_to_celsius(Ta_C)
|
|
120
|
-
Ps_Pa = 101325.0 * (1.0 - 0.0065 * elevation_m / Ta_K) ** (9.807 / (0.0065 * 287.0)) # [Pa]
|
|
121
|
-
|
|
122
|
-
return Ps_Pa
|
|
123
|
-
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
from .calculate_SEBAL_soil_heat_flux import calculate_SEBAL_soil_heat_flux
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
from typing import Union
|
|
2
|
-
|
|
3
|
-
import numpy as np
|
|
4
|
-
import rasters as rt
|
|
5
|
-
from rasters import Raster
|
|
6
|
-
|
|
7
|
-
def calculate_SEBAL_soil_heat_flux(
|
|
8
|
-
Rn: Union[Raster, np.ndarray],
|
|
9
|
-
ST_C: Union[Raster, np.ndarray],
|
|
10
|
-
NDVI: Union[Raster, np.ndarray],
|
|
11
|
-
albedo: Union[Raster, np.ndarray]) -> Union[Raster, np.ndarray]:
|
|
12
|
-
"""
|
|
13
|
-
This function calculates the soil heat flux (G) in the Surface Energy Balance Algorithm for Land (SEBAL) model.
|
|
14
|
-
The formula used in the function is a simplification of the more complex relationship between these variables in the energy balance at the surface.
|
|
15
|
-
|
|
16
|
-
Parameters:
|
|
17
|
-
Rn (np.ndarray): Net radiation at the surface.
|
|
18
|
-
ST_C (np.ndarray): Surface temperature in Celsius.
|
|
19
|
-
NDVI (np.ndarray): Normalized Difference Vegetation Index, indicating the presence and condition of vegetation.
|
|
20
|
-
albedo (np.ndarray): Measure of the diffuse reflection of solar radiation.
|
|
21
|
-
|
|
22
|
-
Returns:
|
|
23
|
-
np.ndarray: The soil heat flux (G), a key component in the energy balance.
|
|
24
|
-
|
|
25
|
-
Reference:
|
|
26
|
-
"Evapotranspiration Estimation Based on Remote Sensing and the SEBAL Model in the Bosten Lake Basin of China" [^1^][1]
|
|
27
|
-
"""
|
|
28
|
-
# Empirical coefficients used in the calculation
|
|
29
|
-
coeff1 = 0.0038
|
|
30
|
-
coeff2 = 0.0074
|
|
31
|
-
|
|
32
|
-
# Vegetation cover correction factor
|
|
33
|
-
NDVI_correction = 1 - 0.98 * NDVI ** 4
|
|
34
|
-
|
|
35
|
-
# Calculation of the soil heat flux (G)
|
|
36
|
-
G = Rn * ST_C * (coeff1 + coeff2 * albedo) * NDVI_correction
|
|
37
|
-
|
|
38
|
-
G = rt.clip(G, 0, None)
|
|
39
|
-
|
|
40
|
-
return G
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
from .timer import *
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
from .vegetation_conversion import *
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
1.0.4
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|