(
nd_v_chunks: tuple[tuple[int, ...], ...] | None,
enc_chunks: tuple[int, ...],
backend_shape: tuple[int, ...],
region: tuple[slice, ...],
allow_partial_chunks: bool,
name: str,
)
| 182 | |
| 183 | |
| 184 | def validate_grid_chunks_alignment( |
| 185 | nd_v_chunks: tuple[tuple[int, ...], ...] | None, |
| 186 | enc_chunks: tuple[int, ...], |
| 187 | backend_shape: tuple[int, ...], |
| 188 | region: tuple[slice, ...], |
| 189 | allow_partial_chunks: bool, |
| 190 | name: str, |
| 191 | ): |
| 192 | if nd_v_chunks is None: |
| 193 | return |
| 194 | base_error = ( |
| 195 | "Specified Zarr chunks encoding['chunks']={enc_chunks!r} for " |
| 196 | "variable named {name!r} would overlap multiple Dask chunks. " |
| 197 | "Please check the Dask chunks at position {v_chunk_pos} and " |
| 198 | "{v_chunk_pos_next}, on axis {axis}, they are overlapped " |
| 199 | "on the same Zarr chunk in the region {region}. " |
| 200 | "Writing this array in parallel with Dask could lead to corrupted data. " |
| 201 | "To resolve this issue, consider one of the following options: " |
| 202 | "- Rechunk the array using `chunk()`. " |
| 203 | "- Modify or delete `encoding['chunks']`. " |
| 204 | "- Set `safe_chunks=False`. " |
| 205 | "- Enable automatic chunks alignment with `align_chunks=True`." |
| 206 | ) |
| 207 | |
| 208 | for axis, chunk_size, v_chunks, interval, size in zip( |
| 209 | range(len(enc_chunks)), |
| 210 | enc_chunks, |
| 211 | nd_v_chunks, |
| 212 | region, |
| 213 | backend_shape, |
| 214 | strict=True, |
| 215 | ): |
| 216 | for i, chunk in enumerate(v_chunks[1:-1]): |
| 217 | if chunk % chunk_size: |
| 218 | raise ValueError( |
| 219 | base_error.format( |
| 220 | v_chunk_pos=i + 1, |
| 221 | v_chunk_pos_next=i + 2, |
| 222 | v_chunk_size=chunk, |
| 223 | axis=axis, |
| 224 | name=name, |
| 225 | chunk_size=chunk_size, |
| 226 | region=interval, |
| 227 | enc_chunks=enc_chunks, |
| 228 | ) |
| 229 | ) |
| 230 | |
| 231 | interval_start = interval.start or 0 |
| 232 | |
| 233 | if len(v_chunks) > 1: |
| 234 | # The first border size is the amount of data that needs to be updated on the |
| 235 | # first chunk taking into account the region slice. |
| 236 | first_border_size = chunk_size |
| 237 | if allow_partial_chunks: |
| 238 | first_border_size = chunk_size - interval_start % chunk_size |
| 239 | |
| 240 | if (v_chunks[0] - first_border_size) % chunk_size: |
| 241 | raise ValueError( |
no test coverage detected
searching dependent graphs…