Skip to content

Commit ef8de86

Browse files
authored
to_grass: replace inf by nan (#11)
1 parent 6065ca3 commit ef8de86

File tree

2 files changed

+76
-0
lines changed

2 files changed

+76
-0
lines changed

src/xarray_grass/to_grass.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,14 @@ def _write_stds(self, data: xr.DataArray, dims: Mapping):
309309
darray = data.sel({dims["start_time"]: time})
310310
darray = self.transpose(darray, dims, arr_type=arr_type)
311311
nd_array = darray.values
312+
313+
# Check for and sanitize infinity values before writing
314+
# SQLite cannot handle 'inf' literal in GRASS temporal database
315+
if np.isinf(nd_array).any():
316+
# Replace infinity with NaN (create copy to avoid modifying original)
317+
nd_array = nd_array.copy()
318+
nd_array[np.isinf(nd_array)] = np.nan
319+
312320
# 3.1 Write each map individually
313321
raster_name = f"{data.name}_{temporal_type}_{index}"
314322
if not is_3d:

tests/test_tograss_error_handling.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,3 +158,71 @@ def test_invalid_dims_invalid_var(self, temp_gisdb, grass_i: GrassInterface):
158158
dataset=sample_da,
159159
dims={"invalid_var_name": {"x": "my_x"}},
160160
)
161+
162+
def test_strds_with_infinity_values(self, temp_gisdb, grass_i: GrassInterface):
163+
"""Test that STRDS with infinity values are sanitized (converted to NaN)."""
164+
import grass.script as gs
165+
166+
session_crs_wkt = grass_i.get_crs_wkt_str()
167+
168+
# Create a STRDS with infinity values (similar to Froude number data)
169+
img_width = 10
170+
img_height = 12
171+
num_times = 3
172+
173+
# Create data with infinity values
174+
data_with_inf = np.random.rand(num_times, img_height, img_width).astype(float)
175+
# Add some infinity values to simulate Froude number where depth -> 0
176+
data_with_inf[1, 5:8, 3:6] = np.inf # Positive infinity
177+
data_with_inf[2, 2:4, 7:9] = np.inf # More infinity
178+
179+
sample_da = create_sample_dataarray(
180+
dims_spec={
181+
"time": np.arange(num_times),
182+
"y": np.arange(img_height, dtype=float),
183+
"x": np.arange(img_width, dtype=float),
184+
},
185+
shape=(num_times, img_height, img_width),
186+
crs_wkt=session_crs_wkt,
187+
name="test_strds_inf",
188+
time_dim_type="relative",
189+
fill_value_generator=lambda s: data_with_inf,
190+
)
191+
192+
# Override the time unit to "seconds" (helper sets it to "minutes" by default)
193+
sample_da["time"].attrs["units"] = "seconds"
194+
195+
strds_id = grass_i.get_id_from_name(sample_da.name)
196+
197+
try:
198+
# This should now succeed (infinity values replaced with NaN)
199+
to_grass(
200+
dataset=sample_da,
201+
dims={"test_strds_inf": {"start_time": "time"}},
202+
)
203+
204+
# Verify the STRDS was created successfully
205+
available_strds = grass_i.list_strds()
206+
assert strds_id in available_strds, (
207+
f"STRDS '{strds_id}' not found in available STRDS: {available_strds}"
208+
)
209+
210+
# Verify maps were registered
211+
strds_maps = grass_i.list_maps_in_strds(strds_id)
212+
assert len(strds_maps) == num_times, (
213+
f"Expected {num_times} maps in STRDS, but found {len(strds_maps)}"
214+
)
215+
216+
finally:
217+
# Clean up
218+
try:
219+
gs.run_command(
220+
"t.remove",
221+
inputs=strds_id,
222+
type="strds",
223+
flags="rfd",
224+
quiet=True,
225+
errors="ignore",
226+
)
227+
except Exception:
228+
pass # Ignore cleanup errors

0 commit comments

Comments
 (0)