STIC-JPL 1.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of STIC-JPL might be problematic. Click here for more details.

@@ -0,0 +1,114 @@
1
+ from typing import Union, Tuple
2
+ import numpy as np
3
+
4
+ import rasters as rt
5
+ from rasters import Raster
6
+
7
+ from .vegetation_conversion.vegetation_conversion import FVC_from_NDVI
8
+
9
+ from .constants import GAMMA_HPA
10
+ from .root_zone_initialization import calculate_root_zone_moisture
11
+
12
+ def initialize_soil_moisture(
13
+ delta_hPa: Union[Raster, np.ndarray], # Rate of change of saturation vapor pressure with temperature (hPa/°C)
14
+ ST_C: Union[Raster, np.ndarray], # Surface temperature (°C)
15
+ Ta_C: Union[Raster, np.ndarray], # Air temperature (°C)
16
+ Td_C: Union[Raster, np.ndarray], # Dewpoint temperature (°C)
17
+ dTS: Union[Raster, np.ndarray], # Difference between surface and air temperature (°C)
18
+ Rn_Wm2: Union[Raster, np.ndarray], # Net radiation (W/m²)
19
+ LWnet_Wm2: Union[Raster, np.ndarray], # Net longwave radiation (W/m²)
20
+ FVC: Union[Raster, np.ndarray], # Fractional vegetation cover (unitless)
21
+ VPD_hPa: Union[Raster, np.ndarray], # Vapor pressure deficit (hPa)
22
+ SVP_hPa: Union[Raster, np.ndarray], # Saturation vapor pressure (hPa)
23
+ Ea_hPa: Union[Raster, np.ndarray], # Actual vapor pressure (hPa)
24
+ Estar_hPa: Union[Raster, np.ndarray], # Saturation vapor pressure at surface temperature (hPa)
25
+ gamma_hPa: Union[Raster, np.ndarray, float] = GAMMA_HPA # Psychrometric constant (hPa/°C)
26
+ ) -> Tuple[Union[Raster, np.ndarray]]:
27
+ """
28
+ This function estimates the soil moisture availability (SM) based on thermal IR and meteorological information.
29
+ The estimated SM is treated as initial SM, which will be later estimated through iteration in the actual ET estimation loop to establish feedback between SM and biophysical states.
30
+
31
+ Parameters:
32
+ delta (np.ndarray): Rate of change of saturation vapor pressure with temperature (kPa/°C)
33
+ ST_C (np.ndarray): Surface temperature (°C)
34
+ Ta_C (np.ndarray): Air temperature (°C)
35
+ Td_C (np.ndarray): Dewpoint temperature (°C)
36
+ dTS (np.ndarray): Difference between surface and air temperature (°C)
37
+ Rn (np.ndarray): Net radiation (W/m²)
38
+ LWnet (np.ndarray): Net longwave radiation (W/m²)
39
+ NDVI (np.ndarray): Normalized Difference Vegetation Index (unitless)
40
+ VPD_hPa (np.ndarray): Vapor pressure deficit (hPa)
41
+ SVP_hPa (np.ndarray): Saturation vapor pressure (hPa)
42
+ Ea_hPa (np.ndarray): Actual vapor pressure (hPa)
43
+ Estar (np.ndarray): Saturation vapor pressure at surface temperature (hPa)
44
+
45
+ Returns:
46
+ SM (np.ndarray): soil moisture (m³/m³)
47
+ Mrz (np.ndarray): The rootzone moisture (m³/m³)
48
+ Ms (np.ndarray): The surface moisture (m³/m³)
49
+ Ep_PT (np.ndarray): The potential evaporation (Priestley-Taylor eqn.) (mm/day)
50
+ Ds (np.ndarray): The vapor pressure deficit at surface (hPa)
51
+ s1 (np.ndarray): The slope of SVP at dewpoint temperature (hPa/K)
52
+ s3 (np.ndarray): The slope of SVP at surface temperature (hPa/K)
53
+ Tsd_C (np.ndarray): The surface dewpoint temperature (°C)
54
+ """
55
+ # Compute the surface dewpoint temperature
56
+ s11 = (45.03 + 3.014 * Td_C + 0.05345 * Td_C ** 2 + 0.00224 * Td_C ** 3) * 1e-2 # slope of SVP at TD (hpa/K)
57
+ s22 = (Estar_hPa - Ea_hPa) / (ST_C - Td_C)
58
+ s33 = (45.03 + 3.014 * ST_C + 0.05345 * ST_C ** 2 + 0.00224 * ST_C ** 3) * 1e-2 # slope of SVP at TS (hpa/K)
59
+ s44 = (SVP_hPa - Ea_hPa) / (Ta_C - Td_C)
60
+ Tsd_C = (Estar_hPa - Ea_hPa - s33 * ST_C + s11 * Td_C) / (s11 - s33) # Surface dewpoint temperature (degC)
61
+
62
+ # Calculate the surface moisture or wetness
63
+ Msurf = (s11 / s22) * ((Tsd_C - Td_C) / (ST_C - Td_C)) # Surface wetness
64
+ Msurf = rt.clip(Msurf, 0.0001, 0.9999)
65
+
66
+ # Calculate the surface vapor pressure and deficit
67
+ esurf = Ea_hPa + Msurf * (Estar_hPa - Ea_hPa)
68
+ Dsurf = esurf - Ea_hPa
69
+
70
+ # Separate the soil and canopy wetness to form a composite surface moisture
71
+ Ms = Msurf
72
+ Mcan = FVC * Msurf
73
+ Msoil = (1 - FVC) * Msurf
74
+
75
+ TdewIndex = (ST_C - Tsd_C) / (Ta_C - Td_C) # % TdewIndex > 1 signifies super dry condition
76
+ Ep_PT = (1.26 * delta_hPa * Rn_Wm2) / (delta_hPa + gamma_hPa) # Potential evaporation (Priestley-Taylor eqn.)
77
+
78
+ # Adjust surface wetness based on certain conditions
79
+ Ms = rt.where((FVC <= 0.25) & (TdewIndex < 1), Msoil, Ms)
80
+ Mcan = rt.where((FVC <= 0.25) & (TdewIndex < 1), 0, Mcan)
81
+ Ms = rt.where((FVC <= 0.25) & (Ta_C > 10) & (Td_C < 0) & (LWnet_Wm2 < -125), Msoil, Ms)
82
+ Mcan = rt.where((FVC <= 0.25) & (Ta_C > 10) & (Td_C < 0) & (LWnet_Wm2 < -125), 0, Mcan)
83
+
84
+ # Calculate the root-zone moisture
85
+ SMrz = calculate_root_zone_moisture(
86
+ delta_hPa=delta_hPa,
87
+ ST_C=ST_C,
88
+ Ta_C=Ta_C,
89
+ Td_C=Td_C,
90
+ s11=s11,
91
+ s33=s33,
92
+ s44=s44,
93
+ Tsd_C=Tsd_C,
94
+ gamma_hPa=gamma_hPa
95
+ )
96
+
97
+ # Combine soil moisture to account for hysteresis and initial estimation of surface vapor pressure
98
+ SM = Ms
99
+ SM = rt.where((Ep_PT > Rn_Wm2) & (dTS > 0), SMrz, SM)
100
+ SM = rt.where((Ep_PT > Rn_Wm2) & (FVC <= 0.25), SMrz, SM)
101
+ SM = rt.where((Ep_PT > Rn_Wm2) & (Dsurf > VPD_hPa), SMrz, SM)
102
+ SM = rt.where((FVC <= 0.25) & (dTS > 0) & (Ta_C > 10) & (Td_C < 0) & (LWnet_Wm2 < -125), SMrz, SM)
103
+ SM = rt.where((FVC <= 0.25) & (dTS > 0) & (Ta_C > 10) & (Td_C < 0) & (Dsurf > VPD_hPa), SMrz, SM)
104
+ SM = rt.where((Ep_PT < Rn_Wm2) & (FVC <= 0.25) & (Dsurf > VPD_hPa), SMrz, SM)
105
+
106
+ es = Ea_hPa + SM * (Estar_hPa - Ea_hPa)
107
+
108
+ # vapor pressure deficit at surface
109
+ Ds = (Estar_hPa - es)
110
+
111
+ s1 = s11
112
+ s3 = s33
113
+
114
+ return SM, SMrz, Ms, Ep_PT, Ds, s1, s3, Tsd_C
@@ -0,0 +1,131 @@
1
+ from typing import Union
2
+ import numpy as np
3
+
4
+ import rasters as rt
5
+
6
+ from rasters import Raster
7
+
8
+ from .constants import GAMMA_HPA
9
+ from .root_zone_iteration import calculate_rootzone_moisture
10
+
11
+ def iterate_soil_moisture(
12
+ delta_hPa: Union[Raster, np.ndarray], # Rate of change of saturation vapor pressure with temperature (hPa/°C)
13
+ s1: Union[Raster, np.ndarray], # The slope of SVP at surface temperature (hPa/K)
14
+ s3: Union[Raster, np.ndarray], # The slope of SVP at dewpoint temperature (hPa/K)
15
+ ST_C: Union[Raster, np.ndarray], # surface temperature (°C)
16
+ Ta_C: Union[Raster, np.ndarray], # air temperature (°C)
17
+ dTS_C: Union[Raster, np.ndarray], # difference between surface and air temperature (°C)
18
+ Td_C: Union[Raster, np.ndarray], # dewpoint temperature (°C)
19
+ Tsd_C: Union[Raster, np.ndarray], # surface dewpoint temperature (°C)
20
+ Rg_Wm2: Union[Raster, np.ndarray], # Incoming solar radiation (W/m^2)
21
+ Rn_Wm2: Union[Raster, np.ndarray], # Net radiation (W/m^2)
22
+ LWnet_Wm2: Union[Raster, np.ndarray], # Net longwave radiation (W/m^2)
23
+ FVC: Union[Raster, np.ndarray], # Fractional vegetation cover (unitless)
24
+ VPD_hPa: Union[Raster, np.ndarray], # Vapor pressure deficit (hPa)
25
+ D0_hPa: Union[Raster, np.ndarray], # Vapor pressure deficit at source (hPa)
26
+ SVP_hPa: Union[Raster, np.ndarray], # Saturation vapor pressure (hPa)
27
+ Ea_hPa: Union[Raster, np.ndarray], # Actual vapor pressure (hPa)
28
+ T0: Union[Raster, np.ndarray], # Temperature at source (°C)
29
+ gamma_hPa: Union[Raster, np.ndarray, float] = GAMMA_HPA # Psychrometric constant (hPa/°C)
30
+ ) -> Union[Raster, np.ndarray]:
31
+ """
32
+ Estimates the soil moisture availability (SM) (or wetness) (value 0 to 1) based on thermal IR and meteorological
33
+ information. However, this M will be treated as initial M, which will be later on estimated through iteration in the
34
+ actual ET estimation loop to establish feedback between M and biophysical states.
35
+
36
+ Args:
37
+ delta (np.ndarray): Rate of change of saturation vapor pressure with temperature (kPa/°C).
38
+ s1 (np.ndarray): The slope of saturation vapor pressure at surface temperature (hPa/K).
39
+ s3 (np.ndarray): The slope of saturation vapor pressure at dewpoint temperature (hPa/K).
40
+ ST_C (np.ndarray): Surface temperature in degrees Celsius.
41
+ Ta_C (np.ndarray): Air temperature in degrees Celsius.
42
+ dTS (np.ndarray): Difference between surface and air temperature in degrees Celsius.
43
+ Td_C (np.ndarray): Dewpoint temperature in degrees Celsius.
44
+ Tsd_C (np.ndarray): Surface dewpoint temperature in degrees Celsius.
45
+ Rg (np.ndarray): Incoming solar radiation in W/m^2.
46
+ Rn (np.ndarray): Net radiation in W/m^2.
47
+ LWnet (np.ndarray): Net longwave radiation in W/m^2.
48
+ FVC (np.ndarray): Fractional vegetation cover (unitless).
49
+ VPD_hPa (np.ndarray): Vapor pressure deficit in hPa.
50
+ D0 (np.ndarray): Vapor pressure deficit at source in hPa.
51
+ SVP_hPa (np.ndarray): Saturation vapor pressure in hPa.
52
+ Ea_hPa (np.ndarray): Actual vapor pressure in hPa.
53
+ T0 (np.ndarray): Temperature at source in degrees Celsius.
54
+
55
+ Returns:
56
+ np.ndarray: Soil moisture availability (SM) (or wetness) (value 0 to 1).
57
+ """
58
+ # calculate surface wetness (Msurf)
59
+ kTSTD = (T0 - Td_C) / (ST_C - Td_C)
60
+ Msurf = (s1 / s3) * ((Tsd_C - Td_C) / (kTSTD * (ST_C - Td_C))) # Surface wetness
61
+ Msurf = rt.where((Rn_Wm2 < 0) & (dTS_C < 0) & (Msurf < 0), np.abs(Msurf), Msurf)
62
+ Msurf = rt.where((Rn_Wm2 < 0) & (dTS_C > 0) & (Msurf < 0), np.abs(Msurf), Msurf)
63
+ Msurf = rt.where((Rn_Wm2 > 0) & (dTS_C < 0) & (Msurf < 0), np.abs(Msurf), Msurf)
64
+ Msurf = rt.where((Rn_Wm2 > 0) & (dTS_C > 0) & (Msurf < 0), np.abs(Msurf), Msurf)
65
+
66
+ # solar radiation is only used to correct negative values of surface wetness
67
+ Msurf = rt.where((Rg_Wm2 > 0) & (Msurf < 0), np.abs(Msurf), Msurf)
68
+ Msurf = rt.where((Rg_Wm2 < 0) & (Msurf < 0), np.abs(Msurf), Msurf)
69
+
70
+ Msurf = rt.where((Td_C < 0) & (Msurf < 0), np.abs(Msurf), Msurf)
71
+ Msurf = rt.clip(Msurf, 0.0001, 1)
72
+
73
+ # Separating soil and canopy wetness to form a composite surface moisture
74
+ Ms = Msurf
75
+ Mcan = FVC * Msurf
76
+ Msoil = (1 - FVC) * Msurf
77
+
78
+ TdewIndex = (ST_C - Tsd_C) / (Ta_C - Td_C)
79
+
80
+ # Potential evaporation (Priestley-Taylor eqn.)
81
+ Ep_PT = (1.26 * delta_hPa * Rn_Wm2) / (delta_hPa + gamma_hPa)
82
+
83
+ # calculate surface wetness (Ms)
84
+ Ms = rt.where((Ep_PT > Rn_Wm2) & (FVC <= 0.25) & (TdewIndex < 1), Msoil, Ms)
85
+ Ms = rt.where((FVC <= 0.25) & (Ta_C > 10) & (Td_C < 0) & (LWnet_Wm2 < -125), Msoil, Ms)
86
+ Ms = rt.where((Rn_Wm2 > Ep_PT) & (FVC <= 0.25) & (TdewIndex < 1) & (Td_C <= 0), Msoil, Ms)
87
+ Ms = rt.where((Rn_Wm2 > Ep_PT) & (FVC <= 0.25) & (TdewIndex < 1), Msoil, Ms)
88
+ Ms = rt.where((D0_hPa > VPD_hPa) & (FVC <= 0.25) & (TdewIndex < 1), Msoil, Ms)
89
+
90
+ # calculate canopy wetness (Mcan)
91
+ Mcan = rt.where((Ep_PT > Rn_Wm2) & (FVC <= 0.25) & (TdewIndex < 1), 0, Mcan)
92
+ Mcan = rt.where((FVC <= 0.25) & (Ta_C > 10) & (Td_C < 0) & (LWnet_Wm2 < -125), 0, Mcan)
93
+ Mcan = rt.where((Rn_Wm2 > Ep_PT) & (FVC <= 0.25) & (TdewIndex < 1) & (Td_C <= 0), 0, Mcan)
94
+ Mcan = rt.where((Rn_Wm2 > Ep_PT) & (FVC <= 0.25) & (TdewIndex < 1), 0, Mcan)
95
+ Mcan = rt.where((D0_hPa > VPD_hPa) & (FVC <= 0.25) & (TdewIndex < 1), 0, Mcan)
96
+
97
+ # calculate rootzone moisture (Mrz)
98
+ Mrz = calculate_rootzone_moisture(
99
+ delta_hPa=delta_hPa,
100
+ s1_hPa=s1,
101
+ s3_hPa=s3,
102
+ ST_C=ST_C,
103
+ Ta_C=Ta_C,
104
+ dTS_C=dTS_C,
105
+ Td_C=Td_C,
106
+ Tsd_C=Tsd_C,
107
+ Rg_Wm2=Rg_Wm2,
108
+ Rn_Wm2=Rn_Wm2,
109
+ LWnet_Wm2=LWnet_Wm2,
110
+ FVC=FVC,
111
+ VPD_hPa=VPD_hPa,
112
+ D0_hPa=D0_hPa,
113
+ SVP_hPa=SVP_hPa,
114
+ Ea_hPa=Ea_hPa,
115
+ gamma_hPa=gamma_hPa
116
+ )
117
+
118
+ TdewIndex = (ST_C - Tsd_C) / (Ta_C - Td_C)
119
+
120
+ # Potential evaporation (Priestley-Taylor eqn.)
121
+ Ep_PT = (1.26 * delta_hPa * Rn_Wm2) / (delta_hPa + gamma_hPa)
122
+
123
+ # COMBINE M to account for Hysteresis and initial estimation of surface vapor pressure
124
+ SM = Msurf
125
+ SM = rt.where((Ep_PT > Rn_Wm2) & (dTS_C > 0) & (FVC <= 0.25) & (D0_hPa > VPD_hPa) & (TdewIndex < 1), Mrz, SM)
126
+ SM = rt.where((FVC <= 0.25) & (dTS_C > 0) & (Ta_C > 10) & (Td_C < 0) & (LWnet_Wm2 < -125) & (D0_hPa > VPD_hPa), Mrz, SM)
127
+
128
+ return SM
129
+
130
+
131
+
@@ -0,0 +1 @@
1
+ from .timer import *
@@ -0,0 +1,77 @@
1
+ """
2
+ This is a minimalistic performance timer.
3
+ """
4
+ import time
5
+
6
+ __author__ = "Gregory Halverson"
7
+
8
+ DEFAULT_FORMAT = "0.2f"
9
+
10
+ class Timer(object):
11
+ """
12
+ This is a minimalistic performance timer.
13
+ """
14
+
15
+ def __init__(self):
16
+ self._start_time = None
17
+ self._end_time = None
18
+ self.start()
19
+
20
+ def __enter__(self, *args, **kwargs):
21
+ self.start()
22
+ return self
23
+
24
+ def __exit__(self, *args, **kwargs):
25
+ self.end()
26
+
27
+ def __repr__(self):
28
+ # print("Timer.__repr__")
29
+ return self.__format__(format_string=DEFAULT_FORMAT)
30
+
31
+ def __str__(self):
32
+ # print("Timer.__str__")
33
+ return self.__repr__()
34
+
35
+ def __format__(self, format_string=DEFAULT_FORMAT):
36
+ if format_string is None or format_string == "":
37
+ format_string = DEFAULT_FORMAT
38
+
39
+ return format(self.duration, format_string)
40
+
41
+ @property
42
+ def now(self):
43
+ # return datetime.now()
44
+ return time.perf_counter()
45
+
46
+ def start(self):
47
+ self._start_time = self.now
48
+
49
+ return self.start_time
50
+
51
+ @property
52
+ def start_time(self):
53
+ return self._start_time
54
+
55
+ def end(self):
56
+ self._end_time = self.now
57
+
58
+ return self.end_time
59
+
60
+ @property
61
+ def end_time(self):
62
+ return self._end_time
63
+
64
+ @property
65
+ def duration(self):
66
+ if self.start_time is None:
67
+ raise Exception("timer never started")
68
+
69
+ if self.end_time is None:
70
+ end_time = self.now
71
+ else:
72
+ end_time = self.end_time
73
+
74
+ duration = end_time - self.start_time
75
+
76
+ return duration
77
+
@@ -0,0 +1 @@
1
+ from .vegetation_conversion import *
@@ -0,0 +1,47 @@
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
27
+
28
+ def LAI_from_NDVI(
29
+ NDVI: Union[Raster, np.ndarray],
30
+ min_fIPAR: float = MIN_FIPAR,
31
+ max_fIPAR: float = MAX_FIPAR,
32
+ min_LAI: float = MIN_LAI,
33
+ max_LAI: float = MAX_LAI) -> Union[Raster, np.ndarray]:
34
+ """
35
+ Convert Normalized Difference Vegetation Index (NDVI) to Leaf Area Index (LAI).
36
+
37
+ Parameters:
38
+ NDVI (Union[Raster, np.ndarray]): Input NDVI data.
39
+
40
+ Returns:
41
+ Union[Raster, np.ndarray]: Converted LAI data.
42
+ """
43
+ fIPAR = rt.clip(NDVI - 0.05, min_fIPAR, max_fIPAR)
44
+ fIPAR = np.where(fIPAR == 0, np.nan, fIPAR)
45
+ LAI = rt.clip(-np.log(1 - fIPAR) * (1 / KPAR), min_LAI, max_LAI)
46
+
47
+ return LAI
STIC_JPL/version.txt ADDED
@@ -0,0 +1 @@
1
+ 1.0.4
@@ -0,0 +1,90 @@
1
+ Metadata-Version: 2.4
2
+ Name: STIC-JPL
3
+ Version: 1.1.0
4
+ Summary: Surface Temperature Initiated Closure (STIC) Evapotranspiration Model Python Implementation
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
+ Project-URL: Homepage, https://github.com/JPL-Evapotranspiration-Algorithms/STIC-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
+ Requires-Dist: colored-logging
12
+ Requires-Dist: ECOv002-CMR
13
+ Requires-Dist: ECOv002-granules
14
+ Requires-Dist: GEOS5FP>=1.1.1
15
+ Requires-Dist: numpy
16
+ Requires-Dist: pandas
17
+ Requires-Dist: rasters
18
+ Requires-Dist: solar-apparent-time
19
+ Provides-Extra: dev
20
+ Requires-Dist: build; extra == "dev"
21
+ Requires-Dist: pytest>=6.0; extra == "dev"
22
+ Requires-Dist: pytest-cov; extra == "dev"
23
+ Requires-Dist: jupyter; extra == "dev"
24
+ Requires-Dist: pytest; extra == "dev"
25
+ Requires-Dist: twine; extra == "dev"
26
+
27
+ # Surface Temperature Initiated Closure (STIC) Evapotranspiration Model Python Implementation
28
+
29
+ [![CI](https://github.com/JPL-Evapotranspiration-Algorithms/STIC/actions/workflows/ci.yml/badge.svg)](https://github.com/JPL-Evapotranspiration-Algorithms/STIC/actions/workflows/ci.yml)
30
+
31
+ This repository contains the python implementation for the Surface Temperature Initiated Closure (STIC) evapotranspiration model, used by the ECOsystem Spaceborne Thermal Radiometer Experiment on Space Station (ECOSTRESS) and Surface Biology and Geology (SBG) missions.
32
+
33
+ This software package is a Python implementation of the Surface Temperature Initiated Closure (STIC) version 1.3 model designed to implement LST to solve the aerodynamic temperature, which is critical for ET modeling. The original STIC model produced by Kaniska Mallick (Mallick et al. 2015; 2018; 2022) was re-implemented from MATLAB code to Python by Gregory Halverson and Madeleine Pascolini-Campbell. The software was developed under a research grant by the NASA Research Opportunities in Space and Earth Sciences (ROSES) program. It is intended for use by the Hyperspectral Thermal Emission Spectrometer (HyTES), MODIS/ASTER (MASTER) Airborne Simulator, Ecosystem Spaceborne Thermal Radiometer Experiment on Space Station (ECOSTRESS) mission and as a precursor for the Surface Biology and Geology (SBG) mission.
34
+
35
+ 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 Hyperspectral Thermal Emission Spectrometer (HyTES), MODIS/ASTER (MASTER) Airborne Simulator, Ecosystem Spaceborne Thermal Radiometer Experiment on Space Station (ECOSTRESS) mission as a precursor for the Surface Biology and Geology (SBG) mission. 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.
36
+
37
+ The software is being released according to the SPD-41 open-science requirements of NASA-funded ROSES projects.
38
+
39
+ Gregory H. Halverson (they/them)<br>
40
+ [gregory.h.halverson@jpl.nasa.gov](mailto:gregory.h.halverson@jpl.nasa.gov)<br>
41
+ Lead developer<br>
42
+ NASA Jet Propulsion Laboratory 329G
43
+
44
+ Kaniska Mallick (he/him)<br>
45
+ [kaniska.mallick@list.lu](mailto:kaniska.mallick@list.lu)<br>
46
+ Algorithm inventor<br>
47
+ Luxembourg Institute of Science and Technology
48
+
49
+ Tian Hu (he/him)<br>
50
+ [tian.hu@list.lu](mailto:tian.hu@list.lu)<br>
51
+ Algorithm developer<br>
52
+ Luxembourg Institute of Science and Technology
53
+
54
+ Madeleine Pascolini-Campbell (she/her)<br>
55
+ [madeleine.a.pascolini-campbell@jpl.nasa.gov](mailto:madeleine.a.pascolini-campbell@jpl.nasa.gov)<br>
56
+ Algorithm developer<br>
57
+ NASA Jet Propulsion Laboratory 329F
58
+
59
+ Claire Villanueva-Weeks (she/her)<br>
60
+ [claire.s.villanueva-weeks@jpl.nasa.gov](mailto:claire.s.villanueva-weeks@jpl.nasa.gov)<br>
61
+ Code maintenance<br>
62
+ NASA Jet Propulsion Laboratory 329G
63
+
64
+ ## Installation
65
+
66
+ Use the pip package manager to install the `STIC` PyPi package.
67
+
68
+ ```
69
+ pip install STIC
70
+ ```
71
+
72
+ ## Usage
73
+
74
+ Import the `STIC` function from the `STIC` package.
75
+
76
+ ```
77
+ from STIC import STIC
78
+ ```
79
+
80
+ See the [ECOSTRESS example](ECOSTRESS%20Example.ipynb) for usage.
81
+
82
+ ## References
83
+
84
+ Mallick, K., Boegh, E., Trebs, I., Alfieri, J. G., Kustas, W. P., Prueger, J. H., ... & Jarvis, A. J. (2015). Reintroducing radiometric surface temperature into the P enman‐M onteith formulation. Water Resources Research, 51(8), 6214-6243. https://doi.org/10.1002/2014WR016106
85
+
86
+ Mallick, K., Toivonen, E., Trebs, I., Boegh, E., Cleverly, J., Eamus, D., ... & Garcia, M. (2018). Bridging Thermal Infrared Sensing and Physically‐Based Evapotranspiration Modeling: From Theoretical Implementation to Validation Across an Aridity Gradient in Australian Ecosystems. Water Resources Research, 54(5), 3409-3435. https://doi.org/10.1029/2017WR021357
87
+
88
+ Mallick, K., Baldocchi, D., Jarvis, A., Hu, T., Trebs, I., Sulis, M., ... & Kustas, W. P. (2022). Insights Into the Aerodynamic Versus Radiometric Surface Temperature Debate in Thermal‐Based Evaporation Modeling. Geophysical Research Letters, 49(15), e2021GL097568. https://doi.org/10.1029/2021GL097568
89
+
90
+
@@ -0,0 +1,28 @@
1
+ STIC_JPL/STIC_JPL.py,sha256=a0EpRTX6Sd75RPIqAzWckIuj9-KwbCE8T1aSEDpLM-c,17434
2
+ STIC_JPL/__init__.py,sha256=FmTp-Ir0Wbae0SbZgxlNIxq48TDrWCev17Gv1hWskxU,216
3
+ STIC_JPL/canopy_air_stream.py,sha256=UYp3l7mt0XH4SqvCGZhRzCIL-v7-Rvxxfm-C81lheSU,1637
4
+ STIC_JPL/closure.py,sha256=AzWoLnpoZ1MlQAKq0CgpmCMfDGVsp8-hYZ50ry33cic,4031
5
+ STIC_JPL/constants.py,sha256=xIVTsdc3_Rf3EPSgSk1QPjWiojFGn4lf1Swffov3oTM,595
6
+ STIC_JPL/diagnostic.py,sha256=RXjtZbCEJMiTyRuiMGUvekDgO_GcrhXVXvorR0WlAsk,2613
7
+ STIC_JPL/initialize_with_solar.py,sha256=6DUUHdVfeKvDk1pf_bOteSW8qd-n9pU4dowO1sMYOpw,3825
8
+ STIC_JPL/initialize_without_solar.py,sha256=M_7QfP2pr2w5sQO7UOW1GPqxpmQkjmsQ526BgYVVALk,4675
9
+ STIC_JPL/iterate_with_solar.py,sha256=WKySvuIJ4HzcDni0UYafmk5lXex2lJfde82kGnGUDI8,6368
10
+ STIC_JPL/iterate_without_solar.py,sha256=09RERpN6tdZr6ORDhMwEFXwx8941vyn1HMJQ-Q_bY6s,6140
11
+ STIC_JPL/net_radiation.py,sha256=Uwudsazul8V-x5t8KQLi3wpYi-wjMwT__eqZCRV2bIw,1187
12
+ STIC_JPL/root_zone_initialization.py,sha256=3JVKNDt3ebIiGVfuhBawjKs-BicNwkbfMprkzSxd4Cg,1581
13
+ STIC_JPL/root_zone_iteration.py,sha256=1XOMFE3-TdJZzUU5vouflUO4NKaZwAW6s1KJrNez3Es,3787
14
+ STIC_JPL/soil_moisture_initialization.py,sha256=YF0GcHkpH5amABNPpxD8f1lLPRyIAkG2dYJTfEuIX4g,5599
15
+ STIC_JPL/soil_moisture_iteration.py,sha256=QJXOPMxxwIIskpx9zLkXUPfuhWgFPUBcRnGhZo2UjAw,6493
16
+ STIC_JPL/version.txt,sha256=rqWtvvV0eFJzxPOcG3aHz4AZk-DLa_Z4GkFonk7bsgw,5
17
+ STIC_JPL/meteorology_conversion/__init__.py,sha256=dLF40imqJCC_l8_QMetbsj1YzkXZuFt9tQ2fsd7Wcdw,38
18
+ STIC_JPL/meteorology_conversion/meteorology_conversion.py,sha256=8vzx71FLLNhR5v6EQBL8OSgAmupQcgdLX2c9tL9TPxA,4202
19
+ STIC_JPL/soil_heat_flux/__init__.py,sha256=bN0dHUfqR9ob68M1TqdjQTK3kmaL5S4P08yK0Thub6k,74
20
+ STIC_JPL/soil_heat_flux/calculate_SEBAL_soil_heat_flux.py,sha256=PZylUGET5-Uj6BGfhOeqS4tp2pGE__gdc5X1nidLjxw,1516
21
+ STIC_JPL/timer/__init__.py,sha256=I_MQKp_aamBLUzZv0psEbRgs6GZLOJd4mmJ7bli0Ikc,21
22
+ STIC_JPL/timer/timer.py,sha256=tn5e3NQmsh55Jp9Fstjf-8KJW4F8UIJs-d_ZLooFYE8,1610
23
+ STIC_JPL/vegetation_conversion/__init__.py,sha256=8gnz0yK_euCV0TtVGDrSGaVfx4g0EJCG2J68ppuA5oc,37
24
+ STIC_JPL/vegetation_conversion/vegetation_conversion.py,sha256=-K3FLV6pXkpxtRxQvimqqkXAgkn9mUUlHQ8FIscq1Zg,1306
25
+ stic_jpl-1.1.0.dist-info/METADATA,sha256=sDO9vRDdU6d-qTxHfk-0ZoCLX5ZyT1o1F086M0hbqWA,5348
26
+ stic_jpl-1.1.0.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
27
+ stic_jpl-1.1.0.dist-info/top_level.txt,sha256=9NkchxttzACJcGcAaWzMaZarzX40OXQ216hERNA9LIo,9
28
+ stic_jpl-1.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (78.1.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1 @@
1
+ STIC_JPL