|
12 | 12 | from zarr.attrs import Attributes
|
13 | 13 | from zarr.codecs import AsType, get_codec
|
14 | 14 | from zarr.errors import ArrayNotFoundError, ReadOnlyError, ArrayIndexError
|
15 |
| -from zarr.indexing import (BasicIndexer, CoordinateIndexer, MaskIndexer, |
16 |
| - OIndex, OrthogonalIndexer, VIndex, PartialChunkIterator, |
17 |
| - check_fields, |
18 |
| - check_no_multi_fields, ensure_tuple, |
19 |
| - err_too_many_indices, is_contiguous_selection, |
20 |
| - is_scalar, pop_fields) |
| 15 | +from zarr.indexing import ( |
| 16 | + BasicIndexer, |
| 17 | + CoordinateIndexer, |
| 18 | + MaskIndexer, |
| 19 | + OIndex, |
| 20 | + OrthogonalIndexer, |
| 21 | + VIndex, |
| 22 | + PartialChunkIterator, |
| 23 | + check_fields, |
| 24 | + check_no_multi_fields, |
| 25 | + ensure_tuple, |
| 26 | + err_too_many_indices, |
| 27 | + is_contiguous_selection, |
| 28 | + is_scalar, |
| 29 | + pop_fields, |
| 30 | +) |
21 | 31 | from zarr.meta import decode_array_metadata, encode_array_metadata
|
22 | 32 | from zarr.storage import array_meta_key, attrs_key, getsize, listdir
|
23 |
| -from zarr.util import (InfoReporter, check_array_shape, human_readable_size, |
24 |
| - is_total_slice, nolock, normalize_chunks, |
25 |
| - normalize_resize_args, normalize_shape, |
26 |
| - normalize_storage_path, PartialReadBuffer) |
| 33 | +from zarr.util import ( |
| 34 | + InfoReporter, |
| 35 | + check_array_shape, |
| 36 | + human_readable_size, |
| 37 | + is_total_slice, |
| 38 | + nolock, |
| 39 | + normalize_chunks, |
| 40 | + normalize_resize_args, |
| 41 | + normalize_shape, |
| 42 | + normalize_storage_path, |
| 43 | + PartialReadBuffer, |
| 44 | +) |
27 | 45 |
|
28 | 46 |
|
29 | 47 | # noinspection PyUnresolvedReferences
|
@@ -107,9 +125,17 @@ class Array(object):
|
107 | 125 |
|
108 | 126 | """
|
109 | 127 |
|
110 |
| - def __init__(self, store, path=None, read_only=False, chunk_store=None, |
111 |
| - synchronizer=None, cache_metadata=True, cache_attrs=True, |
112 |
| - partial_decompress=True): |
| 128 | + def __init__( |
| 129 | + self, |
| 130 | + store, |
| 131 | + path=None, |
| 132 | + read_only=False, |
| 133 | + chunk_store=None, |
| 134 | + synchronizer=None, |
| 135 | + cache_metadata=True, |
| 136 | + cache_attrs=True, |
| 137 | + partial_decompress=True, |
| 138 | + ): |
113 | 139 | # N.B., expect at this point store is fully initialized with all
|
114 | 140 | # configuration metadata fully specified and normalized
|
115 | 141 |
|
@@ -1026,8 +1052,9 @@ def _get_selection(self, indexer, out=None, fields=None):
|
1026 | 1052 | else:
|
1027 | 1053 | check_array_shape('out', out, out_shape)
|
1028 | 1054 |
|
1029 |
| - # iterate over chunks, not self.size becuase then indexer none and cant be zipped, will raise error |
1030 |
| - if not hasattr(self.chunk_store, "getitems") or not self.size: |
| 1055 | + # iterate over chunks |
| 1056 | + if not hasattr(self.chunk_store, "getitems") or \ |
| 1057 | + any(map(lambda x: x == 0, self.shape)): |
1031 | 1058 | # sequentially get one key at a time from storage
|
1032 | 1059 | for chunk_coords, chunk_selection, out_selection in indexer:
|
1033 | 1060 |
|
@@ -1586,9 +1613,17 @@ def _set_selection(self, indexer, value, fields=None):
|
1586 | 1613 | self._chunk_setitems(lchunk_coords, lchunk_selection, chunk_values,
|
1587 | 1614 | fields=fields)
|
1588 | 1615 |
|
1589 |
| - def _process_chunk(self, out, cdata, chunk_selection, drop_axes, |
1590 |
| - out_is_ndarray, fields, out_selection, |
1591 |
| - partial_read_decode=False): |
| 1616 | + def _process_chunk( |
| 1617 | + self, |
| 1618 | + out, |
| 1619 | + cdata, |
| 1620 | + chunk_selection, |
| 1621 | + drop_axes, |
| 1622 | + out_is_ndarray, |
| 1623 | + fields, |
| 1624 | + out_selection, |
| 1625 | + partial_read_decode=False, |
| 1626 | + ): |
1592 | 1627 | """Take binary data from storage and fill output array"""
|
1593 | 1628 | if (out_is_ndarray and
|
1594 | 1629 | not fields and
|
@@ -1630,13 +1665,20 @@ def _process_chunk(self, out, cdata, chunk_selection, drop_axes,
|
1630 | 1665 | index_selection = PartialChunkIterator(chunk_selection, self.chunks)
|
1631 | 1666 | for start, nitems, partial_out_selection in index_selection:
|
1632 | 1667 | expected_shape = [
|
1633 |
| - len(range(*partial_out_selection[i].indices(self.chunks[0]+1))) |
1634 |
| - if i < len(partial_out_selection) else dim |
1635 |
| - for i, dim in enumerate(self.chunks)] |
| 1668 | + len( |
| 1669 | + range(*partial_out_selection[i].indices(self.chunks[0] + 1)) |
| 1670 | + ) |
| 1671 | + if i < len(partial_out_selection) |
| 1672 | + else dim |
| 1673 | + for i, dim in enumerate(self.chunks) |
| 1674 | + ] |
1636 | 1675 | cdata.read_part(start, nitems)
|
1637 | 1676 | chunk_partial = self._decode_chunk(
|
1638 |
| - cdata.buff, start=start, nitems=nitems, |
1639 |
| - expected_shape=expected_shape) |
| 1677 | + cdata.buff, |
| 1678 | + start=start, |
| 1679 | + nitems=nitems, |
| 1680 | + expected_shape=expected_shape, |
| 1681 | + ) |
1640 | 1682 | tmp[partial_out_selection] = chunk_partial
|
1641 | 1683 | out[out_selection] = tmp[chunk_selection]
|
1642 | 1684 | return
|
@@ -1716,20 +1758,35 @@ def _chunk_getitems(self, lchunk_coords, lchunk_selection, out, lout_selection,
|
1716 | 1758 | out_is_ndarray = False
|
1717 | 1759 |
|
1718 | 1760 | ckeys = [self._chunk_key(ch) for ch in lchunk_coords]
|
1719 |
| - if self._partial_decompress and self._compressor \ |
1720 |
| - and self._compressor.codec_id == 'blosc' and not fields \ |
1721 |
| - and self.dtype != object and hasattr(self.chunk_store, "getitems"): |
| 1761 | + if ( |
| 1762 | + self._partial_decompress |
| 1763 | + and self._compressor |
| 1764 | + and self._compressor.codec_id == "blosc" |
| 1765 | + and not fields |
| 1766 | + and self.dtype != object |
| 1767 | + and hasattr(self.chunk_store, "getitems") |
| 1768 | + ): |
1722 | 1769 | partial_read_decode = True
|
1723 |
| - cdatas = {ckey: PartialReadBuffer(ckey, self.chunk_store) |
1724 |
| - for ckey in ckeys if ckey in self.chunk_store} |
| 1770 | + cdatas = { |
| 1771 | + ckey: PartialReadBuffer(ckey, self.chunk_store) |
| 1772 | + for ckey in ckeys |
| 1773 | + if ckey in self.chunk_store |
| 1774 | + } |
1725 | 1775 | else:
|
1726 | 1776 | partial_read_decode = False
|
1727 | 1777 | cdatas = self.chunk_store.getitems(ckeys, on_error="omit")
|
1728 | 1778 | for ckey, chunk_select, out_select in zip(ckeys, lchunk_selection, lout_selection):
|
1729 | 1779 | if ckey in cdatas:
|
1730 |
| - self._process_chunk(out, cdatas[ckey], chunk_select, drop_axes, |
1731 |
| - out_is_ndarray, fields, out_select, |
1732 |
| - partial_read_decode=partial_read_decode) |
| 1780 | + self._process_chunk( |
| 1781 | + out, |
| 1782 | + cdatas[ckey], |
| 1783 | + chunk_select, |
| 1784 | + drop_axes, |
| 1785 | + out_is_ndarray, |
| 1786 | + fields, |
| 1787 | + out_select, |
| 1788 | + partial_read_decode=partial_read_decode, |
| 1789 | + ) |
1733 | 1790 | else:
|
1734 | 1791 | # check exception type
|
1735 | 1792 | if self._fill_value is not None:
|
@@ -1842,9 +1899,10 @@ def _decode_chunk(self, cdata, start=None, nitems=None, expected_shape=None):
|
1842 | 1899 | # decompress
|
1843 | 1900 | if self._compressor:
|
1844 | 1901 | # only decode requested items
|
1845 |
| - if ((all([x is not None for x in [start, nitems]]) |
1846 |
| - and self._compressor.codec_id == 'blosc') |
1847 |
| - and hasattr(self._compressor, 'decode_partial')): |
| 1902 | + if ( |
| 1903 | + all([x is not None for x in [start, nitems]]) |
| 1904 | + and self._compressor.codec_id == "blosc" |
| 1905 | + ) and hasattr(self._compressor, "decode_partial"): |
1848 | 1906 | chunk = self._compressor.decode_partial(cdata, start, nitems)
|
1849 | 1907 | else:
|
1850 | 1908 | chunk = self._compressor.decode(cdata)
|
|
0 commit comments