raster_tools.Raster.map_overlap#
- Raster.map_overlap(func, *rasters, depth, boundary=None, dtype=None, null_value=None, meta=None, return_mask=False, **kwargs)[source]#
Apply
funcblock-wise with overlap across one or more rasters.Thin wrapper over
dask.array.overlap.map_overlap(). Each call tofuncreceives one block from each input raster, in input order, withdepthextra cells of overlap on each side. dask trims the overlap from the result before it’s wrapped back into a Raster on the first input’s grid, so the user function returns same-shape (overlap-included) blocks and doesn’t need to trim itself.Available both as a module function and as a
Rastermethod:r1.map_overlap(func, r2, depth=1)is equivalent tomap_overlap(func, r1, r2, depth=1)– in the method form the calling raster is the first input. References to the “first input” below meanr1in either spelling.Per-block contract
Per-block kwargs (opt-in):
input_masks,input_null_values,block_info,block_id,out_null_value. Name any of these infunc’s signature to receive them per chunk; see below.By default the output Raster’s mask is rebuilt from the output data and the resolved output null value (
out_data == null_value, ornp.isnan(out_data)for NaN nulls) – write the sentinel only at cells you want masked. Cells your func happens to leave equal to the sentinel will appear masked even if you didn’t intend them to; cells you wanted masked but didn’t write the sentinel to will not. This is true regardless of the input rasters’ masks: input masks do not carry through unchanged. To set the output mask explicitly instead – decoupling nullness from the data values – passreturn_mask=Trueand havefuncreturn a(data, mask)pair (both overlap-included); seereturn_maskbelow.Always passed positionally:
func(*input_data, **kwargs)
where
input_datais a tuple of N NumPy blocks, one per input raster, in input order. Each block already includes the overlap region.The user can also opt in to receive per-block extras by including named parameters in
func’s signature. Detection mirrors dask’s ownblock_info=/block_id=mechanism and usesinspect.signature()(viadask.utils.has_keyword()). Recognized names (same set asmap_blocks()):input_masks– tuple of Nnp.ndarray(bool) per-block mask arrays, parallel toinput_dataand overlap-included.input_null_values– tuple of N scalars, each input raster’snull_value(Noneif unset).block_info– dask’s standard per-block info dict.block_id– dask’s standard per-block index tuple: the block’schunk-location(equivalentlyblock_info[None]["chunk-location"]).Noneduring the meta inference call.out_null_value– scalar; the resolved output null value the wrapper will use to derive the output mask. Write this sentinel at cells you want masked. See “Output null value resolution” in Notes below.
A function whose only kwargs absorber is
**kwargsdoes NOT trigger any of these injections – name the kwargs you want.Reserved kwargs
input_masks,input_null_values,block_info,block_id, andout_null_valueare reserved. Passing any of them viamap_overlap’s own**kwargsraisesValueError.- Parameters
func (callable) – Per-block function. See “Per-block contract” above. Must return an array-like that dask can ingest (NumPy ndarray, cupy ndarray, sparse array, etc.) with the same shape as a single (overlap-included) data block. For non-numpy backends, also pass
meta=.*rasters (Raster or str) – The input rasters. In the method form the calling raster is the first input and
*rastersholds any additional ones; in the function form at least one is required. Path strings are accepted. Only the 3D shape is validated; CRS and affine are not checked. The caller is responsible for aligning inputs – typically viar2.reproject(r1.geobox). Inputs are auto-rechunked to the first input’s chunk structure, so same-shape inputs with differing chunking are handled. For a geo-aware variant that strictly requires matching grids, seegeo_map_overlap().depth (int, tuple of int, or dict) – Number of overlap cells per spatial axis.
intapplies to bothyandx(band axis fixed at 0).(dy, dx)sets per-spatial-axis depth.dictmaps axis index to depth (or to a(top, bottom)/(left, right)tuple for asymmetric depths). Asymmetric depths requireboundary=Noneorboundary="none"per dask’s restriction.boundary (optional) –
How to fill cells outside the array’s edges. Choices:
None(default): no padding (matches dask)."null"/"null_value"/"nodata"(case-insensitive, so"NODATA"/"NoData"also work): fill with the input raster’s null value (orget_default_null_value(dtype)if unset). The corresponding mask cells are set toTrue.a numeric scalar: fill with that value. If the value matches the raster’s null value, mask cells are set to
True; otherwise they’re set toFalse."reflect"/"periodic"/"nearest": dask’s standard padding modes. The mask is padded the same way so reflected/wrapped/copied data and mask stay in sync at the source cell."none": explicit no-padding (same asNone).
For multi-input, each raster’s null value is consulted independently.
The boundary -> mask rule only affects what the user’s function sees in the mask block when it opts in to
input_masks=. The output Raster’s mask is built independently from the output data (see Returns / Notes below); padded cells are trimmed off before the user sees them.dtype (dtype-like, optional) – Output dtype. When
None(default), dask infers the dtype by callingfuncon tiny meta samples.null_value (scalar, optional) –
Output null value.
None(default): if there is exactly one input raster and the output dtype matches its dtype, the output inherits that input’s null value. Otherwise, the value is a dtype-appropriate default fromraster_tools.masking.get_default_null_value().scalar: used as-is.
meta (array-like, optional) – Empty array with the desired output array type. Forwarded to
dask.array.overlap.map_overlap(). When provided, dask uses this as the output meta and skips the 0-shape sample call it would otherwise make to derive one – useful whenfunccannot tolerate 0-shape input. WhenNone(default), dask derives a NumPy meta by callingfuncon 0-shape inputs.return_mask (bool, optional) –
If
True,funcmust return a(data, mask)pair instead of a single array. The returnedmask– not a sentinel comparison – defines the output Raster’s null cells.maskis a boolean array the same shape asdata(both overlap-included; dask trims them together). Masked cells are set to the resolved output null value (burned in). Use this to decouple which cells are null from what value they hold, avoiding the sentinel-collision pitfalls described above. The default isFalse(sentinel-derived mask). Notes:The two arrays are carried through dask packed into a single NumPy structured-dtype block, then split apart again – an internal detail;
funcjust returns the plain pair.Passing
dtype=(ormeta=) describing the data dtype is recommended: it lets dask skip its 0-shape probe. Without a hint the func must tolerate that probe.Requires NumPy-backed blocks (the structured-dtype carrier is a NumPy concept). Composes with
input_masksand everyboundarymode.out_null_valueinjection is unnecessary (though harmless) whenreturn_mask=True.
**kwargs – Extra keyword arguments forwarded per-block to
func. The reserved names listed above are not allowed here.
- Returns
A new lazy Raster on the first input’s grid.
- Return type
Notes
The wrapper always trims overlap before returning so the result matches the input grid. If you need un-trimmed output, call
dask.array.overlap.map_overlap()directly onraster.data.The output mask is all-False if no null value is set (see the per-block contract above for how the mask is built when one is). To write the output mask directly, pass
return_mask=Trueand return a(data, mask)pair fromfunc(seereturn_mask).Asymmetric per-side depths are only supported with no padding (
boundary=Noneor"none").Dask invokes
funconce on 0-shape inputs to derive the output array meta – this happens whether or notdtype=is provided. Passmeta=to skip the call entirely;dtype=only skips the additional sample call dask would otherwise make to infer the output dtype, not the 0-shape meta call. (Exception: withreturn_mask=True,dtype=is folded into a structuredmeta=and so does skip the 0-shape meta call – seereturn_mask.) Most NumPy ops handle 0-shape inputs fine. If dask raisesdtype inference failed in map_blocks. Please specify the dtype explicitly using the dtype kwarg, that’s the sample call (dask routes overlap through its inner map_blocks, so the message says map_blocks even from this function) –dtype=per dask’s hint is usually enough; passmeta=instead if your func also can’t tolerate 0-shape inputs (dask silently swallows that crash, but your downstream output meta will be wrong).Output null value resolution
When
funcopts in toout_null_value, the wrapper resolves the scalar per-chunk without an extra dtype-inference pass:With
meta=ordtype=set, from that hint (dask leavesblock_info[None]["dtype"]asNonewhenevermeta=is set, which is why the hint is consulted first).Otherwise, from
block_info[None]["dtype"].
During dask’s meta inference call (where
block_infoisNone),out_null_valueis a typed zero of the first input’s dtype so funcs likenp.where(m, out_null_value, d)infer the same dtype as their input rather than collapsing to object. If your func’s output dtype depends on the specificout_null_valuescalar, passmeta=to skip dask’s 0-shape meta call entirely;dtype=skips only the additional sample call, not the meta call.Examples
3x3 mean with reflected edges:
>>> def mean_3x3(d): ... pad = d[0] ... out = np.zeros_like(pad, dtype=np.float32) ... ... # convolve and write to out[1:-1, 1:-1] ... return out[None] >>> smoothed = r.map_overlap( ... mean_3x3, depth=1, boundary="reflect", ... )
See also
raster_tools.map_blocksBlock-wise without overlap; same per-block contract.
raster_tools.geo_map_overlapGeo-aware variant that hands
funcgeoreferencedxr.DataArrayblocks.