Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions src/zarr/core/array.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
from zarr.abc.numcodec import Numcodec, _is_numcodec
from zarr.codecs._v2 import V2Codec
from zarr.codecs.bytes import BytesCodec
from zarr.codecs.transpose import TransposeCodec
from zarr.codecs.vlen_utf8 import VLenBytesCodec, VLenUTF8Codec
from zarr.codecs.zstd import ZstdCodec
from zarr.core._info import ArrayInfo
Expand Down Expand Up @@ -4674,13 +4675,24 @@ async def init_array(
attributes=attributes,
)
else:
if order is not None and config is None:
_warn_order_kwarg()
array_array, array_bytes, bytes_bytes = _parse_chunk_encoding_v3(
compressors=compressors,
filters=filters,
serializer=serializer,
dtype=zdtype,
)
sub_codecs = cast("tuple[Codec, ...]", (*array_array, array_bytes, *bytes_bytes))

if order is not None and not any(isinstance(codec, TransposeCodec) for codec in sub_codecs):
sub_codecs = (
*array_array,
TransposeCodec(order=tuple(reversed(range(len(shape_parsed))))),
array_bytes,
*bytes_bytes,
)
config = replace(parse_array_config(config), order=order)
# A stored chunk grid passed as chunks= / shards= (e.g. by the "keep"
# path of from_array) becomes the stored grid verbatim, so the new
# array preserves the source grid exactly — including trailing edges
Expand Down Expand Up @@ -4710,8 +4722,6 @@ async def init_array(
else:
codecs_out = sub_codecs

if order is not None:
_warn_order_kwarg()
meta = AsyncArray._create_metadata_v3(
shape=shape_parsed,
dtype=zdtype,
Expand Down
26 changes: 26 additions & 0 deletions tests/test_codecs/test_transpose.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,32 @@ async def test_transpose(
assert read_data.flags["C_CONTIGUOUS"]


@pytest.mark.parametrize("store", ["local", "memory"], indirect=["store"])
def test_create_array_v3_order_f_preserves_fortran_output(store: Store) -> None:
data = np.arange(12, dtype="float32").reshape((3, 4), order="F")
spath = StorePath(store, "transpose_from_order")

with pytest.warns(
RuntimeWarning, match="The `order` keyword argument has no effect for Zarr format 3 arrays"
):
a = zarr.create_array(
spath,
shape=data.shape,
chunks=data.shape,
dtype=data.dtype,
order="F",
)
a[:] = data

reopened = zarr.open_array(spath).with_config({"order": "F"})
read_data = np.asarray(reopened[:])

assert np.array_equal(read_data, data)
assert read_data.flags["F_CONTIGUOUS"]
assert not read_data.flags["C_CONTIGUOUS"]
assert any(isinstance(codec, TransposeCodec) for codec in reopened.filters)


@pytest.mark.parametrize("store", ["local", "memory"], indirect=["store"])
@pytest.mark.parametrize("order", [[1, 2, 0], [1, 2, 3, 0], [3, 2, 4, 0, 1]])
def test_transpose_non_self_inverse(store: Store, order: list[int]) -> None:
Expand Down
Loading