|
13 | 13 |
|
14 | 14 | def chunk_to_slice(chunk): |
15 | 15 | """ |
16 | | - Convert an openPMD_api.ChunkInfo to np.s_ |
| 16 | + Convert an openPMD_api.ChunkInfo to slice |
17 | 17 | """ |
18 | 18 | stops = [a + b for a, b in zip(chunk.offset, chunk.extent)] |
19 | 19 | indices_per_dim = zip(chunk.offset, stops) |
20 | 20 | index_tuple = map(lambda s: slice(s[0], s[1], None), indices_per_dim) |
21 | 21 | return tuple(index_tuple) |
22 | 22 |
|
| 23 | + |
23 | 24 | def get_data(series, record_component, i_slice=None, pos_slice=None, |
24 | 25 | output_type=np.float64): |
25 | 26 | """ |
@@ -67,46 +68,57 @@ def get_data(series, record_component, i_slice=None, pos_slice=None, |
67 | 68 | series.flush() |
68 | 69 | data[chunk_slice] = x |
69 | 70 | else: |
70 | | - # Get largest element of pos_slice |
71 | | - max_pos = max(pos_slice) |
72 | | - # Create list of indices list_index of type |
73 | | - # [:, :, :, ...] where Ellipsis starts at max_pos + 1 |
74 | | - list_index = [np.s_[:]] * (max_pos + 2) |
75 | | - list_index[max_pos + 1] = np.s_[...] |
76 | | - # Fill list_index with elements of i_slice |
77 | | - for count, dir_index in enumerate(pos_slice): |
78 | | - list_index[dir_index] = i_slice[count] |
79 | | - # Convert list_index into a tuple |
80 | | - tuple_index = tuple(list_index) |
81 | | - print("tuple_index={}".format(tuple_index)) |
82 | | - |
83 | | - # potentially a better approach as below, since we only slice |
84 | | - # out hyperplanes, planes & lines: |
85 | | - # - allocate zero array for result, which is a hyperplane/plane/line |
86 | | - # - iterate over slices in tuple_index |
87 | | - # - reduce selected read range to "valid" range |
88 | | - |
89 | | - # initial experiment: |
90 | | - # full_indices can be HUGE, avoid!! |
91 | | - full_indices = np.indices(record_component.shape)[0] |
92 | | - #full_shape = full_indices.shape |
93 | | - #print("full_shape.shape={}".format(full_shape)) |
94 | | - #print("full_shape={}".format(full_shape)) |
95 | | - |
96 | | - # prepare sliced data according to tuple_index |
97 | | - slice_indices = full_indices[tuple_index] |
98 | | - slice_shape = slice_indices.shape |
| 71 | + full_shape = record_component.shape |
| 72 | + for dir_index, index in zip(pos_slice, i_slice): |
| 73 | + slice_shape = list(full_shape) # copy |
| 74 | + # future note: this needs to be converted to list and back to |
| 75 | + # tuple once we fix |
| 76 | + # https://github.com/openPMD/openPMD-api/issues/808 |
| 77 | + del slice_shape[dir_index] |
| 78 | + |
| 79 | + # mask invalid regions with zero |
99 | 80 | data = np.zeros(slice_shape, dtype=output_type) |
100 | | - # write now in index space between intersection of slice_indices and chunk indices |
| 81 | + |
| 82 | + # build requested ND slice with respect to full data |
| 83 | + s = [] |
| 84 | + for d in range(len(full_shape)): |
| 85 | + if d in pos_slice: |
| 86 | + s.append(index) # one index in such directions |
| 87 | + else: # all indices in other direction |
| 88 | + s.append(slice(None, None, None)) |
| 89 | + s = tuple(s) |
| 90 | + |
| 91 | + # now we check which chunks contribute to the slice |
101 | 92 | for chunk in chunks: |
| 93 | + skip_this_chunk = False |
| 94 | + s_valid = list(s) # same as s but reduced to valid regions in chunk |
| 95 | + s_target = [] # starts and stops in sliced array |
102 | 96 | chunk_slice = chunk_to_slice(chunk) |
103 | | - chunk_indices = full_indices[chunk_slice] |
104 | | - intersect_indices = np.intersect1d(chunk_indices, slice_indices) |
105 | | - print(intersect_indices) |
106 | | - data[slice_indices] = record_component[intersect_indices] |
107 | | - #data = np.zeros_like(record_component)[tuple_index] # just avoid invalid reads for now |
108 | | - |
109 | | - series.flush() |
| 97 | + # read only valid region |
| 98 | + for d, slice_d in enumerate(s): |
| 99 | + start = chunk_slice[d].start |
| 100 | + stop = chunk_slice[d].stop |
| 101 | + if isinstance(slice_d, int): |
| 102 | + # Nothing to do for s_target (dimension sliced out) |
| 103 | + # Nothing to do for s_valid (dimension index is set) |
| 104 | + if slice_d < start or slice_d > stop: |
| 105 | + # chunk not in slice line/plane |
| 106 | + skip_this_chunk = True |
| 107 | + else: |
| 108 | + if slice_d.start is None or slide_dir.start < start: |
| 109 | + s_valid[d] = slice(start, s_valid[d].stop) |
| 110 | + if slice_d.start is None or slide_dir.start > stop: |
| 111 | + s_valid[d] = slice(s_valid[d].start, stop) |
| 112 | + s_target.append(slice(start, stop)) |
| 113 | + |
| 114 | + s_valid = tuple(s_valid) |
| 115 | + s_target = tuple(s_target) |
| 116 | + |
| 117 | + # read |
| 118 | + if not skip_this_chunk: |
| 119 | + x = record_component[s_valid] |
| 120 | + series.flush() |
| 121 | + data[s_target] = x |
110 | 122 |
|
111 | 123 | # Convert to the right type |
112 | 124 | if data.dtype != output_type: |
|
0 commit comments