1010from exactextract import exact_extract
1111from exactextract .raster import NumPyRasterSource
1212
13+ from ..rasterize .core import _get_affine
1314from ..utils import get_grid_mapping_var
1415from .utils import clip_to_bbox , geometries_as_dask_array , is_in_memory
1516
@@ -103,9 +104,9 @@ def get_dtype(coverage_weight: CoverageWeights, geometries):
103104
104105
105106def np_coverage (
106- x : np .ndarray ,
107- y : np .ndarray ,
107+ affine ,
108108 * ,
109+ shape : tuple [int , int ],
109110 geometries : gpd .GeoDataFrame ,
110111 strategy : Strategy = DEFAULT_STRATEGY ,
111112 coverage_weight : CoverageWeights = "fraction" ,
@@ -115,8 +116,7 @@ def np_coverage(
115116 if len (geometries .columns ) > 1 :
116117 raise ValueError ("Require a single geometries column or a GeoSeries." )
117118
118- shape = (y .size , x .size )
119- raster = xy_to_raster_source (x , y , srs_wkt = geometries .crs .to_wkt ())
119+ raster = affine_to_raster_source (affine , shape , srs_wkt = geometries .crs .to_wkt ())
120120 result = exact_extract (
121121 rast = raster ,
122122 vec = geometries ,
@@ -161,43 +161,59 @@ def np_coverage(
161161
162162def coverage_np_dask_wrapper (
163163 geom_array : np .ndarray ,
164- x : np .ndarray ,
165- y : np .ndarray ,
164+ x_offsets : np .ndarray ,
165+ y_offsets : np .ndarray ,
166+ x_sizes : np .ndarray ,
167+ y_sizes : np .ndarray ,
168+ affine ,
166169 coverage_weight : CoverageWeights ,
167170 strategy : Strategy ,
168171 crs ,
169172) -> np .ndarray :
173+ shape = (y_sizes .item (), x_sizes .item ())
174+ chunk_affine = affine * affine .translation (x_offsets .item (), y_offsets .item ())
170175 return np_coverage (
171- x = x . squeeze ( axis = ( GEOM_AXIS , Y_AXIS )) ,
172- y = y . squeeze ( axis = ( GEOM_AXIS , X_AXIS )) ,
176+ chunk_affine ,
177+ shape = shape ,
173178 geometries = gpd .GeoDataFrame (geometry = geom_array .squeeze (axis = (X_AXIS , Y_AXIS )), crs = crs ),
174179 coverage_weight = coverage_weight ,
175180 )
176181
177182
178183def dask_coverage (
179- x : dask .array .Array ,
180- y : dask .array .Array ,
184+ affine ,
181185 * ,
186+ chunks : tuple [tuple [int , ...], tuple [int , ...]],
182187 geom_array : dask .array .Array ,
183188 coverage_weight : CoverageWeights = "fraction" ,
184189 strategy : Strategy = DEFAULT_STRATEGY ,
185190 crs : Any ,
186191) -> dask .array .Array :
187192 import dask .array
193+ from dask .array import from_array
188194
189- if any (c == 1 for c in x .chunks [0 ]) or any (c == 1 for c in y .chunks [0 ]):
195+ y_chunks , x_chunks = chunks
196+
197+ if any (c == 1 for c in x_chunks ) or any (c == 1 for c in y_chunks ):
190198 raise ValueError ("exactextract does not support a chunksize of 1. Please rechunk to avoid this" )
191199
200+ x_sizes = from_array (x_chunks , chunks = 1 )
201+ y_sizes = from_array (y_chunks , chunks = 1 )
202+ x_offsets = from_array (np .cumulative_sum (x_chunks [:- 1 ], include_initial = True ), chunks = 1 )
203+ y_offsets = from_array (np .cumulative_sum (y_chunks [:- 1 ], include_initial = True ), chunks = 1 )
204+
192205 out = dask .array .map_blocks (
193206 coverage_np_dask_wrapper ,
194207 geom_array [:, np .newaxis , np .newaxis ],
195- x [np .newaxis , np .newaxis , :],
196- y [np .newaxis , :, np .newaxis ],
208+ x_offsets [np .newaxis , np .newaxis , :],
209+ y_offsets [np .newaxis , :, np .newaxis ],
210+ x_sizes [np .newaxis , np .newaxis , :],
211+ y_sizes [np .newaxis , :, np .newaxis ],
212+ affine = affine ,
197213 crs = crs ,
198214 coverage_weight = coverage_weight ,
199215 strategy = strategy ,
200- chunks = (* geom_array .chunks , * y . chunks , * x . chunks ),
216+ chunks = (* geom_array .chunks , tuple ( y_chunks ), tuple ( x_chunks ) ),
201217 meta = sparse .COO (
202218 [], data = np .array ([], dtype = get_dtype (coverage_weight , geom_array )), shape = (0 , 0 , 0 ), fill_value = 0
203219 ),
@@ -290,32 +306,30 @@ def coverage(
290306
291307 if clip :
292308 obj = clip_to_bbox (obj , geometries , xdim = xdim , ydim = ydim )
309+
310+ affine = _get_affine (obj , x_dim = xdim , y_dim = ydim )
311+ shape = (obj .sizes [ydim ], obj .sizes [xdim ])
312+
293313 if is_in_memory (obj = obj , geometries = geometries ):
294314 out = np_coverage (
295- x = obj [ xdim ]. data ,
296- y = obj [ ydim ]. data ,
315+ affine ,
316+ shape = shape ,
297317 geometries = geometries ,
298318 coverage_weight = coverage_weight ,
299319 strategy = strategy ,
300320 )
301321 geom_array = geometries .to_numpy ().squeeze (axis = 1 )
302322 else :
303- from dask .array import Array , from_array
304-
305323 geom_dask_array = geometries_as_dask_array (geometries )
306- if not isinstance (obj [xdim ].data , Array ):
307- dask_x = from_array (obj [xdim ].data , chunks = obj .chunksizes .get (xdim , - 1 ))
308- else :
309- dask_x = obj [xdim ].data
310324
311- if not isinstance ( obj [ ydim ]. data , Array ):
312- dask_y = from_array ( obj [ ydim ]. data , chunks = obj . chunksizes .get (ydim , - 1 ))
313- else :
314- dask_y = obj [ ydim ]. data
325+ chunks = (
326+ obj . chunksizes .get (ydim , ( obj . sizes [ ydim ],)),
327+ obj . chunksizes . get ( xdim , ( obj . sizes [ xdim ],)),
328+ )
315329
316330 out = dask_coverage (
317- x = dask_x ,
318- y = dask_y ,
331+ affine ,
332+ chunks = chunks ,
319333 geom_array = geom_dask_array ,
320334 crs = geometries .crs ,
321335 coverage_weight = coverage_weight ,
0 commit comments