Skip to content

Commit 0df9f1f

Browse files
committed
adds javadoc
1 parent 5356562 commit 0df9f1f

File tree

6 files changed

+212
-29
lines changed

6 files changed

+212
-29
lines changed

README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
This repository contains an early preview of a Java implementation of the Zarr specification.
44
It is intended for collecting feedback from the community and not for use. The API is subject to changes.
55

6+
Refer to [JZarr](https://github.com/zarr-developers/jzarr) for a stable implementation of Zarr version 2.
67

78
## Usage
89
```java
@@ -18,8 +19,8 @@ Group hierarchy = Group.open(
1819
);
1920
Array array = hierarchy.get("color").get("1");
2021
ucar.ma2.Array outArray = array.read(
21-
new long[]{0, 3073, 3073, 513},
22-
new int[]{1, 64, 64, 64}
22+
new long[]{0, 3073, 3073, 513}, // offset
23+
new int[]{1, 64, 64, 64} // shape
2324
);
2425

2526
Array array = Array.create(
@@ -33,7 +34,7 @@ Array array = Array.create(
3334
.build();
3435
);
3536
array.write(
36-
new long[]{0, 0, 0, 0},
37+
new long[]{0, 0, 0, 0}, // offset
3738
ucar.ma2.Array.factory(ucar.ma2.DataType.UINT, new int[]{1, 1024, 1024, 1024})
3839
);
3940
```

TODO

Lines changed: 0 additions & 16 deletions
This file was deleted.

src/main/java/com/scalableminds/zarrjava/utils/Utils.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public static long[] toLongArray(int[] array) {
4848

4949
public static int[] toIntArray(long[] array) {
5050
return Arrays.stream(array)
51-
.mapToInt(i -> (int) i)
51+
.mapToInt(Math::toIntExact)
5252
.toArray();
5353
}
5454

src/main/java/com/scalableminds/zarrjava/v3/Array.java

Lines changed: 179 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@
1010
import java.io.IOException;
1111
import java.nio.ByteBuffer;
1212
import java.util.Arrays;
13+
import java.util.HashMap;
1314
import java.util.Map;
1415
import java.util.function.Function;
1516
import java.util.stream.Collectors;
1617
import javax.annotation.Nonnull;
18+
import javax.annotation.Nullable;
1719
import ucar.ma2.InvalidRangeException;
1820

1921
public class Array extends Node {
@@ -28,6 +30,13 @@ protected Array(StoreHandle storeHandle, ArrayMetadata arrayMetadata)
2830
this.codecPipeline = new CodecPipeline(arrayMetadata.codecs);
2931
}
3032

33+
/**
34+
* Opens an existing Zarr array at a specified storage location.
35+
*
36+
* @param storeHandle
37+
* @throws IOException
38+
* @throws ZarrException
39+
*/
3140
public static Array open(StoreHandle storeHandle) throws IOException, ZarrException {
3241
return new Array(
3342
storeHandle,
@@ -39,11 +48,32 @@ public static Array open(StoreHandle storeHandle) throws IOException, ZarrExcept
3948
);
4049
}
4150

51+
/**
52+
* Creates a new Zarr array with the provided metadata at a specified storage location. This
53+
* method will raise an exception if a Zarr array already exists at the specified storage
54+
* location.
55+
*
56+
* @param storeHandle
57+
* @param arrayMetadata
58+
* @throws IOException
59+
* @throws ZarrException
60+
*/
4261
public static Array create(StoreHandle storeHandle, ArrayMetadata arrayMetadata)
4362
throws IOException, ZarrException {
4463
return Array.create(storeHandle, arrayMetadata, false);
4564
}
4665

66+
/**
67+
* Creates a new Zarr array with the provided metadata at a specified storage location. If
68+
* `existsOk` is false, this method will raise an exception if a Zarr array already exists at the
69+
* specified storage location.
70+
*
71+
* @param storeHandle
72+
* @param arrayMetadata
73+
* @param existsOk
74+
* @throws IOException
75+
* @throws ZarrException
76+
*/
4777
public static Array create(StoreHandle storeHandle, ArrayMetadata arrayMetadata, boolean existsOk)
4878
throws IOException, ZarrException {
4979
StoreHandle metadataHandle = storeHandle.resolve(ZARR_JSON);
@@ -58,18 +88,53 @@ public static Array create(StoreHandle storeHandle, ArrayMetadata arrayMetadata,
5888
return new Array(storeHandle, arrayMetadata);
5989
}
6090

91+
/**
92+
* Creates a new Zarr array at a specified storage location. This method provides a callback that
93+
* gets an ArrayMetadataBuilder and needs to return such an ArrayMetadataBuilder. The callback can
94+
* be used to construct the metadata of the Zarr array. If `existsOk` is false, this method will
95+
* raise an exception if a Zarr array already exists at the specified storage location.
96+
*
97+
* @param storeHandle
98+
* @param arrayMetadataBuilderMapper
99+
* @param existsOk
100+
* @throws IOException
101+
* @throws ZarrException
102+
*/
103+
public static Array create(StoreHandle storeHandle,
104+
Function<ArrayMetadataBuilder, ArrayMetadataBuilder> arrayMetadataBuilderMapper,
105+
boolean existsOk) throws IOException, ZarrException {
106+
return Array.create(storeHandle,
107+
arrayMetadataBuilderMapper.apply(new ArrayMetadataBuilder()).build(), existsOk);
108+
}
109+
110+
@Nonnull
61111
public static ArrayMetadataBuilder metadataBuilder() {
62112
return new ArrayMetadataBuilder();
63113
}
64114

115+
@Nonnull
65116
public static ArrayMetadataBuilder metadataBuilder(ArrayMetadata existingMetadata) {
66117
return ArrayMetadataBuilder.fromArrayMetadata(existingMetadata);
67118
}
68119

120+
/**
121+
* Reads the entire Zarr array into an ucar.ma2.Array.
122+
*
123+
* @throws ZarrException
124+
*/
125+
@Nonnull
69126
public ucar.ma2.Array read() throws ZarrException {
70127
return read(new long[metadata.ndim()], Utils.toIntArray(metadata.shape));
71128
}
72129

130+
/**
131+
* Reads a part of the Zarr array based on a requested offset and shape into an ucar.ma2.Array.
132+
*
133+
* @param offset
134+
* @param shape
135+
* @throws ZarrException
136+
*/
137+
@Nonnull
73138
public ucar.ma2.Array read(final long[] offset, final int[] shape) throws ZarrException {
74139
if (offset.length != metadata.ndim()) {
75140
throw new IllegalArgumentException("'offset' needs to have rank '" + metadata.ndim() + "'.");
@@ -105,15 +170,13 @@ public ucar.ma2.Array read(final long[] offset, final int[] shape) throws ZarrEx
105170
final StoreHandle chunkHandle = storeHandle.resolve(chunkKeys);
106171

107172
if (codecPipeline.supportsPartialDecode()) {
108-
System.out.println("decodePartial");
109173
final ucar.ma2.Array chunkArray = codecPipeline.decodePartial(chunkHandle,
110174
Utils.toLongArray(chunkProjection.chunkOffset), chunkProjection.shape,
111175
metadata.coreArrayMetadata);
112176
MultiArrayUtils.copyRegion(chunkArray, new int[metadata.ndim()], outputArray,
113177
chunkProjection.outOffset, chunkProjection.shape
114178
);
115179
} else {
116-
System.out.println("decode");
117180
MultiArrayUtils.copyRegion(readChunk(chunkCoords), chunkProjection.chunkOffset,
118181
outputArray, chunkProjection.outOffset, chunkProjection.shape
119182
);
@@ -137,6 +200,14 @@ boolean chunkIsInArray(long[] chunkCoords) {
137200
return true;
138201
}
139202

203+
/**
204+
* Reads one chunk of the Zarr array as specified by the chunk coordinates into an
205+
* ucar.ma2.Array.
206+
*
207+
* @param chunkCoords The coordinates of the chunk as computed by the offset of the chunk divided
208+
* by the chunk shape.
209+
* @throws ZarrException
210+
*/
140211
@Nonnull
141212
public ucar.ma2.Array readChunk(long[] chunkCoords)
142213
throws ZarrException {
@@ -155,10 +226,23 @@ public ucar.ma2.Array readChunk(long[] chunkCoords)
155226
return codecPipeline.decode(chunkBytes, metadata.coreArrayMetadata);
156227
}
157228

229+
/**
230+
* Writes a ucar.ma2.Array into the Zarr array at the beginning of the Zarr array. The shape of
231+
* the Zarr array needs be large enough for the write.
232+
*
233+
* @param array
234+
*/
158235
public void write(ucar.ma2.Array array) {
159236
write(new long[metadata.ndim()], array);
160237
}
161238

239+
/**
240+
* Writes a ucar.ma2.Array into the Zarr array at a specified offset. The shape of the Zarr array
241+
* needs be large enough for the write.
242+
*
243+
* @param offset
244+
* @param array
245+
*/
162246
public void write(long[] offset, ucar.ma2.Array array) {
163247
if (offset.length != metadata.ndim()) {
164248
throw new IllegalArgumentException("'offset' needs to have rank '" + metadata.ndim() + "'.");
@@ -200,6 +284,14 @@ public void write(long[] offset, ucar.ma2.Array array) {
200284
});
201285
}
202286

287+
/**
288+
* Writes one chunk into the Zarr array as specified by the chunk coordinates. The shape of the
289+
* Zarr array needs be large enough for the write.
290+
*
291+
* @param chunkCoords
292+
* @param chunkArray
293+
* @throws ZarrException
294+
*/
203295
public void writeChunk(long[] chunkCoords, ucar.ma2.Array chunkArray) throws ZarrException {
204296
String[] chunkKeys = metadata.chunkKeyEncoding.encodeChunkKey(chunkCoords);
205297
StoreHandle chunkHandle = storeHandle.resolve(chunkKeys);
@@ -212,6 +304,10 @@ public void writeChunk(long[] chunkCoords, ucar.ma2.Array chunkArray) throws Zar
212304
}
213305
}
214306

307+
public ArrayAccessor access() {
308+
return new ArrayAccessor(this);
309+
}
310+
215311
private Array writeMetadata(ArrayMetadata newArrayMetadata) throws ZarrException, IOException {
216312
ObjectMapper objectMapper = Node.makeObjectMapper();
217313
ByteBuffer metadataBytes = ByteBuffer.wrap(objectMapper.writeValueAsBytes(newArrayMetadata));
@@ -220,6 +316,15 @@ private Array writeMetadata(ArrayMetadata newArrayMetadata) throws ZarrException
220316
return new Array(storeHandle, newArrayMetadata);
221317
}
222318

319+
/**
320+
* Sets a new shape for the Zarr array. It only changes the metadata, no array data is modified or
321+
* deleted. This method returns a new instance of the Zarr array class and the old instance
322+
* becomes invalid.
323+
*
324+
* @param newShape
325+
* @throws ZarrException
326+
* @throws IOException
327+
*/
223328
public Array resize(long[] newShape) throws ZarrException, IOException {
224329
if (newShape.length != metadata.ndim()) {
225330
throw new IllegalArgumentException(
@@ -232,6 +337,14 @@ public Array resize(long[] newShape) throws ZarrException, IOException {
232337
return writeMetadata(newArrayMetadata);
233338
}
234339

340+
/**
341+
* Sets the attributes of the Zarr array. It overwrites and removes any existing attributes. This
342+
* method returns a new instance of the Zarr array class and the old instance becomes invalid.
343+
*
344+
* @param newAttributes
345+
* @throws ZarrException
346+
* @throws IOException
347+
*/
235348
public Array setAttributes(Map<String, Object> newAttributes) throws ZarrException, IOException {
236349
ArrayMetadata newArrayMetadata =
237350
ArrayMetadataBuilder.fromArrayMetadata(metadata)
@@ -240,9 +353,20 @@ public Array setAttributes(Map<String, Object> newAttributes) throws ZarrExcepti
240353
return writeMetadata(newArrayMetadata);
241354
}
242355

356+
/**
357+
* Updates the attributes of the Zarr array. It provides a callback that gets the current
358+
* attributes as input and needs to return the new set of attributes. The attributes in the
359+
* callback may be mutated. This method overwrites and removes any existing attributes. This
360+
* method returns a new instance of the Zarr array class and the old instance becomes invalid.
361+
*
362+
* @param attributeMapper
363+
* @throws ZarrException
364+
* @throws IOException
365+
*/
243366
public Array updateAttributes(Function<Map<String, Object>, Map<String, Object>> attributeMapper)
244367
throws ZarrException, IOException {
245-
return setAttributes(attributeMapper.apply(metadata.attributes));
368+
return setAttributes(attributeMapper.apply(new HashMap<String, Object>(metadata.attributes) {
369+
}));
246370
}
247371

248372
@Override
@@ -254,4 +378,56 @@ public String toString() {
254378
metadata.dataType
255379
);
256380
}
381+
382+
public static final class ArrayAccessor {
383+
384+
@Nullable
385+
long[] offset;
386+
@Nullable
387+
int[] shape;
388+
@Nonnull
389+
Array array;
390+
391+
private ArrayAccessor(@Nonnull Array array) {
392+
this.array = array;
393+
}
394+
395+
@Nonnull
396+
public ArrayAccessor withOffset(@Nonnull long... offset) {
397+
this.offset = offset;
398+
return this;
399+
}
400+
401+
402+
@Nonnull
403+
public ArrayAccessor withShape(@Nonnull int... shape) {
404+
this.shape = shape;
405+
return this;
406+
}
407+
408+
@Nonnull
409+
public ArrayAccessor withShape(@Nonnull long... shape) {
410+
this.shape = Utils.toIntArray(shape);
411+
return this;
412+
}
413+
414+
@Nonnull
415+
public ucar.ma2.Array read() throws ZarrException {
416+
if (offset == null) {
417+
throw new ZarrException("`offset` needs to be set.");
418+
}
419+
if (shape == null) {
420+
throw new ZarrException("`shape` needs to be set.");
421+
}
422+
return array.read(offset, shape);
423+
}
424+
425+
public void write(@Nonnull ucar.ma2.Array content) throws ZarrException {
426+
if (offset == null) {
427+
throw new ZarrException("`offset` needs to be set.");
428+
}
429+
array.write(offset, content);
430+
}
431+
432+
}
257433
}

src/main/java/com/scalableminds/zarrjava/v3/Group.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,12 @@ public Array createArray(String key, ArrayMetadata arrayMetadata)
9898
return Array.create(storeHandle.resolve(key), arrayMetadata);
9999
}
100100

101+
public Array createArray(String key,
102+
Function<ArrayMetadataBuilder, ArrayMetadataBuilder> arrayMetadataBuilderMapper)
103+
throws IOException, ZarrException {
104+
return Array.create(storeHandle.resolve(key), arrayMetadataBuilderMapper, false);
105+
}
106+
101107
public Stream<Node> list() {
102108
return storeHandle.list()
103109
.map(key -> {

0 commit comments

Comments
 (0)