Skip to content

Commit 19f6f59

Browse files
Merge pull request #8 from gregory-halverson-jpl/main
fixing `daily_ET_from_instantaneous`
2 parents 44f55b0 + c4b77d3 commit 19f6f59

File tree

3 files changed

+83
-9
lines changed

3 files changed

+83
-9
lines changed

daily_evapotranspiration_upscaling/daily_evapotranspiration_upscaling.py

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import datetime
2+
from datetime import datetime
23
from typing import Union
34
from sun_angles import SHA_deg_from_DOY_lat, daylight_from_SHA, sunrise_from_SHA, calculate_daylight
45
from dateutil import parser
@@ -75,12 +76,12 @@ def daily_ET_from_instantaneous(
7576
LE_instantaneous_Wm2: Union[Raster, np.ndarray, float],
7677
Rn_instantaneous_Wm2: Union[Raster, np.ndarray, float],
7778
G_instantaneous_Wm2: Union[Raster, np.ndarray, float],
78-
DOY: Union[Raster, np.ndarray, int] = None,
79+
day_of_year: Union[Raster, np.ndarray, int] = None,
7980
lat: Union[Raster, np.ndarray, float] = None,
8081
hour_of_day: Union[Raster, np.ndarray, float] = None,
8182
sunrise_hour: Union[Raster, np.ndarray, float] = None,
8283
daylight_hours: Union[Raster, np.ndarray, float] = None,
83-
datetime_UTC: datetime = None,
84+
time_UTC: Union[datetime, str, np.ndarray, list] = None,
8485
geometry: SpatialGeometry = None,
8586
lambda_Jkg: Union[Raster, np.ndarray, float] = LAMBDA_JKG_WATER_20C
8687
) -> Union[Raster, np.ndarray]:
@@ -96,6 +97,9 @@ def daily_ET_from_instantaneous(
9697
Returns:
9798
Union[Raster, np.ndarray]: Daily evapotranspiration in kilograms.
9899
"""
100+
if lat is None and geometry is not None:
101+
lat = geometry.lat
102+
99103
# Calculate evaporative fraction
100104
EF = calculate_evaporative_fraction(
101105
LE=LE_instantaneous_Wm2,
@@ -106,21 +110,21 @@ def daily_ET_from_instantaneous(
106110
# Calculate daylight hours if not provided
107111
if daylight_hours is None:
108112
daylight_hours = calculate_daylight(
109-
DOY=DOY,
113+
day_of_year=day_of_year,
110114
lat=lat,
111-
datetime_UTC=datetime_UTC,
115+
time_UTC=time_UTC,
112116
geometry=geometry
113117
)
114118

115119
# Calculate sunrise hour if not provided
116120
if sunrise_hour is None:
117-
sunrise_hour = sunrise_from_SHA(SHA_deg_from_DOY_lat(DOY, lat))
121+
sunrise_hour = sunrise_from_SHA(SHA_deg_from_DOY_lat(day_of_year, lat))
118122

119123
# Integrate net radiation over the day
120124
Rn_daylight = daily_Rn_integration_verma(
121125
Rn=Rn_instantaneous_Wm2,
122126
hour_of_day=hour_of_day,
123-
DOY=DOY,
127+
DOY=day_of_year,
124128
lat=lat,
125129
sunrise_hour=sunrise_hour,
126130
daylight_hours=daylight_hours
@@ -130,6 +134,6 @@ def daily_ET_from_instantaneous(
130134
LE_daylight = EF * Rn_daylight
131135

132136
# Calculate daily ET
133-
ET = daily_ET_from_daily_LE(LE_daylight, daylight_hours=daylight_hours, DOY=DOY, lat=lat, datetime_UTC=datetime_UTC, geometry=geometry, lambda_Jkg=lambda_Jkg)
137+
ET = daily_ET_from_daily_LE(LE_daylight, daylight_hours=daylight_hours, DOY=day_of_year, lat=lat, datetime_UTC=time_UTC, geometry=geometry, lambda_Jkg=lambda_Jkg)
134138

135139
return ET

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ requires = ["setuptools>=60", "setuptools-scm>=8.0", "wheel"]
33

44
[project]
55
name = "daily-evapotranspiration-upscaling"
6-
version = "1.0.6"
6+
version = "1.1.0"
77
description = "Instantaneous/Daily Evapotranspiration Upscaling Utilities Python Package"
88
readme = "README.md"
99
authors = [
@@ -19,7 +19,7 @@ dependencies = [
1919
"python-dateutil",
2020
"rasters",
2121
"solar-apparent-time",
22-
"sun-angles>=1.3.0",
22+
"sun-angles>=1.4.0",
2323
"verma-net-radiation"
2424
]
2525

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import unittest
2+
import numpy as np
3+
from datetime import datetime
4+
from daily_evapotranspiration_upscaling.daily_evapotranspiration_upscaling import daily_ET_from_instantaneous
5+
6+
class TestDailyETFromInstantaneous(unittest.TestCase):
7+
def test_scalar_inputs_datetime(self):
8+
# Simple test with scalar values and datetime
9+
LE = 100.0 # W/m^2
10+
Rn = 200.0 # W/m^2
11+
G = 20.0 # W/m^2
12+
day_of_year = 180
13+
lat = 35.0
14+
hour_of_day = 12.0
15+
time_UTC = datetime(2023, 6, 29, 12, 0, 0)
16+
# Should run without error and return a float or np.ndarray
17+
result = daily_ET_from_instantaneous(
18+
LE_instantaneous_Wm2=LE,
19+
Rn_instantaneous_Wm2=Rn,
20+
G_instantaneous_Wm2=G,
21+
day_of_year=day_of_year,
22+
lat=lat,
23+
hour_of_day=hour_of_day,
24+
time_UTC=time_UTC
25+
)
26+
self.assertIsInstance(result, (float, np.floating, np.ndarray))
27+
28+
def test_scalar_inputs_string_time(self):
29+
# Test with time as string
30+
LE = 100.0
31+
Rn = 200.0
32+
G = 20.0
33+
day_of_year = 180
34+
lat = 35.0
35+
hour_of_day = 12.0
36+
time_UTC = '2023-06-29T12:00:00'
37+
result = daily_ET_from_instantaneous(
38+
LE_instantaneous_Wm2=LE,
39+
Rn_instantaneous_Wm2=Rn,
40+
G_instantaneous_Wm2=G,
41+
day_of_year=day_of_year,
42+
lat=lat,
43+
hour_of_day=hour_of_day,
44+
time_UTC=time_UTC
45+
)
46+
self.assertIsInstance(result, (float, np.floating, np.ndarray))
47+
48+
def test_array_inputs(self):
49+
# Test with numpy arrays
50+
LE = np.array([100.0, 110.0])
51+
Rn = np.array([200.0, 210.0])
52+
G = np.array([20.0, 25.0])
53+
day_of_year = np.array([180, 181])
54+
lat = np.array([35.0, 36.0])
55+
hour_of_day = np.array([12.0, 13.0])
56+
time_UTC = [datetime(2023, 6, 29, 12, 0, 0), datetime(2023, 6, 30, 13, 0, 0)]
57+
result = daily_ET_from_instantaneous(
58+
LE_instantaneous_Wm2=LE,
59+
Rn_instantaneous_Wm2=Rn,
60+
G_instantaneous_Wm2=G,
61+
day_of_year=day_of_year,
62+
lat=lat,
63+
hour_of_day=hour_of_day,
64+
time_UTC=time_UTC
65+
)
66+
self.assertIsInstance(result, np.ndarray)
67+
self.assertEqual(result.shape, (2,))
68+
69+
if __name__ == '__main__':
70+
unittest.main()

0 commit comments

Comments
 (0)