@@ -118,13 +118,28 @@ def _write_with_tensorstore(
118118 internal_chunk_shape = None ,
119119 full_array_shape = None ,
120120 create_dataset = True ,
121+ original_chunks = None , # Add parameter for consistent chunk tracking
121122) -> None :
122123 """Write array using tensorstore backend"""
123124 import tensorstore as ts
124125
125126 # Use full array shape if provided, otherwise use the region array shape
126127 dataset_shape = full_array_shape if full_array_shape is not None else array .shape
127128
129+ # Use original chunks for consistency if provided, otherwise use current chunks
130+ consistent_chunks = original_chunks if original_chunks is not None else chunks
131+
132+ # Validate chunk shapes to prevent zero or negative values
133+ validated_chunks = []
134+ for i , chunk_size in enumerate (consistent_chunks ):
135+ if chunk_size <= 0 :
136+ # Fallback to minimum valid chunk size or array dimension
137+ fallback_size = min (64 , dataset_shape [i ]) if dataset_shape else 64
138+ validated_chunks .append (fallback_size )
139+ else :
140+ validated_chunks .append (chunk_size )
141+ consistent_chunks = tuple (validated_chunks )
142+
128143 spec = {
129144 "kvstore" : {
130145 "driver" : "file" ,
@@ -136,14 +151,14 @@ def _write_with_tensorstore(
136151 }
137152 if zarr_format == 2 :
138153 spec ["driver" ] = "zarr"
139- spec ["metadata" ]["chunks" ] = chunks
154+ spec ["metadata" ]["chunks" ] = consistent_chunks
140155 spec ["metadata" ]["dimension_separator" ] = "/"
141156 spec ["metadata" ]["dtype" ] = array .dtype .str
142157 elif zarr_format == 3 :
143158 spec ["driver" ] = "zarr3"
144159 spec ["metadata" ]["chunk_grid" ] = {
145160 "name" : "regular" ,
146- "configuration" : {"chunk_shape" : chunks },
161+ "configuration" : {"chunk_shape" : consistent_chunks },
147162 }
148163 spec ["metadata" ]["data_type" ] = _numpy_to_zarr_dtype (array .dtype )
149164 if dimension_names :
@@ -337,6 +352,7 @@ def _write_array_with_tensorstore(
337352 region : Tuple [slice , ...],
338353 full_array_shape : Optional [Tuple [int , ...]] = None ,
339354 create_dataset : bool = True ,
355+ original_chunks : Optional [Tuple [int , ...]] = None , # Add parameter
340356 ** kwargs ,
341357) -> None :
342358 """Write an array using the TensorStore backend."""
@@ -351,6 +367,7 @@ def _write_array_with_tensorstore(
351367 dimension_names = dimension_names ,
352368 full_array_shape = full_array_shape ,
353369 create_dataset = create_dataset ,
370+ original_chunks = original_chunks ,
354371 ** kwargs ,
355372 )
356373 else : # Sharding
@@ -364,6 +381,7 @@ def _write_array_with_tensorstore(
364381 internal_chunk_shape = internal_chunk_shape ,
365382 full_array_shape = full_array_shape ,
366383 create_dataset = create_dataset ,
384+ original_chunks = original_chunks ,
367385 ** kwargs ,
368386 )
369387
@@ -435,6 +453,7 @@ def _handle_large_array_writing(
435453 progress : Optional [Union [NgffProgress , NgffProgressCallback ]],
436454 index : int ,
437455 nscales : int ,
456+ original_chunks : Tuple [int , ...], # Add parameter to track original chunks
438457 ** kwargs ,
439458) -> None :
440459 """Handle writing large arrays by splitting them into manageable pieces."""
@@ -498,6 +517,7 @@ def _handle_large_array_writing(
498517 region ,
499518 full_array_shape = arr .shape ,
500519 create_dataset = (region_index == 0 ), # Only create on first region
520+ original_chunks = original_chunks , # Pass original chunks for consistency
501521 ** kwargs ,
502522 )
503523 else :
@@ -818,6 +838,9 @@ def to_ngff_zarr(
818838 dim_factors = {d : 1 for d in dims }
819839 previous_dim_factors = dim_factors
820840
841+ # Capture original chunks before any rechunking operations
842+ original_chunks = tuple ([c [0 ] for c in arr .chunks ])
843+
821844 # Configure sharding if needed
822845 sharding_kwargs , internal_chunk_shape , arr = _configure_sharding (
823846 arr , chunks_per_shard , dims , kwargs .copy ()
@@ -859,6 +882,7 @@ def to_ngff_zarr(
859882 progress ,
860883 index ,
861884 nscales ,
885+ original_chunks , # Pass original chunks for consistency
862886 ** kwargs ,
863887 )
864888 else :
@@ -882,6 +906,7 @@ def to_ngff_zarr(
882906 region ,
883907 full_array_shape = arr .shape ,
884908 create_dataset = True , # Always create for small arrays
909+ original_chunks = original_chunks , # Pass original chunks for consistency
885910 ** kwargs ,
886911 )
887912 else :
0 commit comments