2323``(target, source, weight)`` rows. So *applying* a regridding is::
2424
2525 SELECT w.dst_lat, w.dst_lon, SUM(s.value * w.weight) AS regridded
26- FROM weights w JOIN src s ON s.cell_id = w.src_id
26+ FROM weights w JOIN src s ON s.lat = w.src_lat AND s.lon = w.src_lon
2727 GROUP BY w.dst_lat, w.dst_lon
2828
2929— a JOIN against the weight table plus a weighted GROUP BY. This is the most
@@ -93,26 +93,28 @@ def _bilinear_weight_table(
9393 """Build the sparse bilinear weight matrix as a weight table.
9494
9595 The 2-D weight is the outer product of the 1-D lat and lon weights. Each
96- nonzero is one row: the target cell named by its ``(dst_lat, dst_lon)`` and
97- the source cell by its row-major ``src_id`` — so the regrid SQL can GROUP BY
98- the target coordinates and round-trip straight back to a (lat, lon) grid.
96+ nonzero is one row naming the target cell by its ``(dst_lat, dst_lon)`` and
97+ the source cell by its ``(src_lat, src_lon)`` — so the regrid SQL joins the
98+ source grid on its coordinates (no pre-raveled cell id), lets the engine read
99+ the source lazily, and rounds the result straight back to a (lat, lon) grid.
99100 """
100- nslon = len (slon )
101101 lat_w = _linear_weights (slat , tlat )
102102 lon_w = _linear_weights (slon , tlon )
103- dst_lats , dst_lons , src_ids , weights = [], [], [], []
103+ dst_lats , dst_lons , src_lats , src_lons , weights = [], [], [], [], []
104104 for tj , si , wlat in lat_w :
105105 for tk , sj , wlon in lon_w :
106106 dst_lats .append (tlat [tj ])
107107 dst_lons .append (tlon [tk ])
108- src_ids .append (si * nslon + sj )
108+ src_lats .append (slat [si ])
109+ src_lons .append (slon [sj ])
109110 weights .append (wlat * wlon )
110111 n = len (weights )
111112 return xr .Dataset (
112113 {
113114 "dst_lat" : (["pair" ], np .array (dst_lats , dtype = "float64" )),
114115 "dst_lon" : (["pair" ], np .array (dst_lons , dtype = "float64" )),
115- "src_id" : (["pair" ], np .array (src_ids , dtype = "int64" )),
116+ "src_lat" : (["pair" ], np .array (src_lats , dtype = "float64" )),
117+ "src_lon" : (["pair" ], np .array (src_lons , dtype = "float64" )),
116118 "weight" : (["pair" ], np .array (weights , dtype = "float64" )),
117119 },
118120 coords = {"pair" : np .arange (n )},
@@ -150,19 +152,22 @@ def _open_srtm() -> xr.DataArray:
150152 rename [d ] = "lat"
151153 elif dl in ("x" , "lon" , "longitude" ):
152154 rename [d ] = "lon"
153- return da .rename (rename ).sortby ("lat" ).sortby ("lon" ).load ()
155+ da = da .rename (rename ).sortby ("lat" ).sortby ("lon" )
156+ # Stay lazy (no .load()): the source is read on demand by both the SQL table
157+ # and the .interp reference, so each pays its own read. Force float64 coords
158+ # so the weight table's src lat/lon match the source grid's exactly in the
159+ # join.
160+ return da .assign_coords (
161+ lat = da .lat .astype ("float64" ), lon = da .lon .astype ("float64" )
162+ )
154163
155164
156165def main () -> None :
157- with timed ("open SRTM via Xee" ):
166+ with timed ("open SRTM via Xee (lazy) " ):
158167 src_da = _open_srtm ()
159168 slat = src_da .lat .values
160169 slon = src_da .lon .values
161- field = src_da .values .astype ("float64" )
162- print (
163- f" SRTM elevation source grid { len (slat )} ×{ len (slon )} "
164- f"({ float (np .nanmin (field )):.0f} –{ float (np .nanmax (field )):.0f} m)"
165- )
170+ print (f" SRTM elevation source grid { len (slat )} ×{ len (slon )} (read lazily)" )
166171
167172 # Finer target grid strictly inside the source extent (bilinear upsampling).
168173 tlat = np .linspace (slat [1 ], slat [- 2 ], 60 )
@@ -171,27 +176,28 @@ def main() -> None:
171176 f" regrid { len (slat )} ×{ len (slon )} → { len (tlat )} ×{ len (tlon )} (bilinear)"
172177 )
173178
174- # Source field as a flat (cell_id, value) table.
175- src_table = xr .Dataset (
176- {"value" : (["cell_id" ], field .ravel ())},
177- coords = {"cell_id" : np .arange (field .size )},
178- ).chunk ({"cell_id" : field .size })
179179 weights = _bilinear_weight_table (slat , slon , tlat , tlon )
180180 print (
181181 f" weight matrix: { weights .sizes ['pair' ]:,} nonzeros "
182182 f"({ len (tlat ) * len (tlon )} targets × 4 corners)"
183183 )
184184
185185 ctx = xql .XarrayContext ()
186- ctx .from_dataset ("src" , src_table , chunks = {"cell_id" : field .size })
186+ # Register the source grid itself (lazy) — the join reads it on demand, the
187+ # same source the .interp reference reads, so both pay an equal lazy read.
188+ ctx .from_dataset (
189+ "src" ,
190+ src_da .to_dataset (name = "value" ),
191+ chunks = {"lat" : len (slat ), "lon" : len (slon )},
192+ )
187193 ctx .from_dataset ("weights" , weights , chunks = {"pair" : weights .sizes ["pair" ]})
188194
189195 sql = """
190196 SELECT w.dst_lat AS lat,
191197 w.dst_lon AS lon,
192198 SUM(s.value * w.weight) AS regridded
193199 FROM weights w
194- JOIN src s ON s.cell_id = w.src_id
200+ JOIN src s ON s.lat = w.src_lat AND s.lon = w.src_lon
195201 GROUP BY w.dst_lat, w.dst_lon
196202 ORDER BY w.dst_lat, w.dst_lon
197203 """
@@ -202,7 +208,7 @@ def main() -> None:
202208 for _ in measured ("SQL regrid (weight-table JOIN + weighted SUM)" ):
203209 got = ctx .sql (sql ).to_dataset (dims = ["lat" , "lon" ]).regridded
204210
205- # Array reference: xarray's own bilinear interpolation of the same field.
211+ # Array reference: xarray's own bilinear interpolation of the same lazy field.
206212 for _ in measured ("xarray .interp reference" ):
207213 ref = src_da .interp (lat = tlat , lon = tlon , method = "linear" )
208214
0 commit comments