Skip to content

Commit 985c2a4

Browse files
committed
N5: use "." internally for dimension separation
This allows N5 to detect the split between key and chunks and pre-process them (re-ordering and changing the separator). see: zarr-developers#773 zarr-developers#793
1 parent ce8a79e commit 985c2a4

File tree

1 file changed

+31
-6
lines changed

1 file changed

+31
-6
lines changed

zarr/n5.py

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -327,9 +327,21 @@ def __init__(self, *args, **kwargs):
327327
if 'dimension_separator' in kwargs:
328328
kwargs.pop('dimension_separator')
329329
warnings.warn('Keyword argument `dimension_separator` will be ignored')
330-
dimension_separator = "/"
330+
dimension_separator = "."
331331
super().__init__(*args, dimension_separator=dimension_separator, **kwargs)
332332

333+
def swap_separator(self, key):
334+
old = key
335+
segments = list(key.split('/'))
336+
if segments:
337+
last_segment = segments[-1]
338+
if _prog_ckey.match(last_segment):
339+
coords = list(last_segment.split('.'))
340+
last_segment = '/'.join(coords[::-1])
341+
segments = segments[:-1] + [last_segment]
342+
key = '/'.join(segments)
343+
return key
344+
333345
def _normalize_key(self, key):
334346
if is_chunk_key(key):
335347
key = invert_chunk_coords(key)
@@ -339,7 +351,7 @@ def _normalize_key(self, key):
339351
*bits, end = key.split("/")
340352

341353
if end not in (self.array_meta_key, self.group_meta_key, self.attrs_key):
342-
end = end.replace(".", self.key_separator)
354+
end = end.replace(".", "/")
343355
key = "/".join(bits + [end])
344356
return key.lower() if self.normalize_keys else key
345357

@@ -367,6 +379,10 @@ def __getitem__(self, key):
367379
raise KeyError(key)
368380
else:
369381
return json_dumps(value)
382+
383+
elif is_chunk_key(key):
384+
key = self.swap_separator(key)
385+
370386
return super().__getitem__(key)
371387

372388
def __setitem__(self, key, value):
@@ -411,6 +427,9 @@ def __setitem__(self, key, value):
411427

412428
value = json_dumps(n5_attrs)
413429

430+
elif is_chunk_key(key):
431+
key = self.swap_separator(key)
432+
414433
super().__setitem__(key, value)
415434

416435
def __delitem__(self, key):
@@ -421,6 +440,8 @@ def __delitem__(self, key):
421440
key = key.replace(zarr_array_meta_key, self.array_meta_key)
422441
elif key.endswith(zarr_attrs_key): # pragma: no cover
423442
key = key.replace(zarr_attrs_key, self.attrs_key)
443+
elif is_chunk_key(key):
444+
key = self.swap_separator(key)
424445

425446
super().__delitem__(key)
426447

@@ -444,6 +465,9 @@ def __contains__(self, key):
444465
key = key.replace(zarr_attrs_key, self.attrs_key)
445466
return self._contains_attrs(key)
446467

468+
elif is_chunk_key(key):
469+
key = self.swap_separator(key)
470+
447471
return super().__contains__(key)
448472

449473
def __eq__(self, other):
@@ -538,19 +562,20 @@ def _contains_attrs(self, path):
538562
return len(attrs) > 0
539563

540564
def is_chunk_key(key):
565+
rv = False
541566
segments = list(key.split('/'))
542567
if segments:
543568
last_segment = segments[-1]
544-
return _prog_ckey.match(last_segment)
545-
return False # pragma: no cover
569+
rv = _prog_ckey.match(last_segment)
570+
return rv
546571

547572
def invert_chunk_coords(key):
548573
segments = list(key.split('/'))
549574
if segments:
550575
last_segment = segments[-1]
551576
if _prog_ckey.match(last_segment):
552577
coords = list(last_segment.split('.'))
553-
last_segment = '.'.join(coords[::-1])
578+
last_segment = '/'.join(coords[::-1])
554579
segments = segments[:-1] + [last_segment]
555580
key = '/'.join(segments)
556581
return key
@@ -627,7 +652,7 @@ def array_metadata_to_zarr(array_metadata):
627652
array_metadata['fill_value'] = 0 # also if None was requested
628653
array_metadata['order'] = 'C'
629654
array_metadata['filters'] = []
630-
array_metadata['dimension_separator'] = '/'
655+
array_metadata['dimension_separator'] = '.'
631656

632657
compressor_config = array_metadata['compressor']
633658
compressor_config = compressor_config_to_zarr(compressor_config)

0 commit comments

Comments
 (0)