Skip to content

Commit 0984e4b

Browse files
committed
feat: add DatasetAttributes.builder
1 parent 47976dc commit 0984e4b

2 files changed

Lines changed: 113 additions & 1 deletion

File tree

src/main/java/org/janelia/saalfeldlab/n5/DatasetAttributes.java

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,83 @@ public HashMap<String, Object> asMap() {
341341
return map;
342342
}
343343

344+
public static Builder builder(final long[] dimensions, final DataType dataType) {
345+
346+
return new Builder(dimensions, dataType);
347+
}
348+
349+
public static Builder builder(final DatasetAttributes attributes) {
350+
351+
return new Builder(attributes);
352+
}
353+
354+
protected static int[] defaultBlockSize(final long[] dimensions) {
355+
356+
final int[] blockSize;
357+
if (dimensions.length == 1)
358+
blockSize = new int[]{1024};
359+
else if (dimensions.length == 2)
360+
blockSize = new int[]{256, 256};
361+
else if (dimensions.length == 3)
362+
blockSize = new int[]{128, 128, 128};
363+
else {
364+
blockSize = new int[dimensions.length];
365+
Arrays.fill(blockSize, 64);
366+
}
367+
for (int i = 0; i < blockSize.length; i++)
368+
blockSize[i] = (int)Math.min(blockSize[i], dimensions[i]);
369+
return blockSize;
370+
}
371+
372+
public static class Builder {
373+
374+
private final long[] dimensions;
375+
private final DataType dataType;
376+
377+
private int[] blockSize;
378+
private DataCodecInfo[] dataCodecInfos = new DataCodecInfo[0];
379+
380+
public Builder(final long[] dimensions, final DataType dataType) {
381+
382+
this.dimensions = dimensions.clone();
383+
this.dataType = dataType;
384+
this.blockSize = defaultBlockSize(dimensions);
385+
}
386+
387+
public Builder(final DatasetAttributes attributes) {
388+
389+
this.dimensions = attributes.getDimensions();
390+
this.dataType = attributes.getDataType();
391+
this.blockSize = attributes.getBlockSize();
392+
this.dataCodecInfos = attributes.getDataCodecInfos();
393+
}
394+
395+
public Builder blockSize(final int[] blockSize) {
396+
397+
this.blockSize = blockSize.clone();
398+
return this;
399+
}
400+
401+
/**
402+
* Sets the compression codec. Has no effect if {@code compression} is
403+
* null or {@link RawCompression}.
404+
*
405+
* @param compression the compression to use
406+
* @return this builder
407+
*/
408+
public Builder compression(final Compression compression) {
409+
410+
if (compression != null && !(compression instanceof RawCompression))
411+
this.dataCodecInfos = new DataCodecInfo[]{compression};
412+
return this;
413+
}
414+
415+
public DatasetAttributes build() {
416+
final int[] resolvedBlockSize = blockSize != null ? blockSize : defaultBlockSize(dimensions);
417+
return new DatasetAttributes(dimensions, resolvedBlockSize, dataType, new N5BlockCodecInfo(), null, dataCodecInfos);
418+
}
419+
}
420+
344421
private static DatasetAttributesAdapter adapter = null;
345422

346423
public static DatasetAttributesAdapter getJsonAdapter() {

src/test/java/org/janelia/saalfeldlab/n5/DatasetAttributesTest.java

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package org.janelia.saalfeldlab.n5;
22

3+
import static org.junit.Assert.assertArrayEquals;
34
import static org.junit.Assert.assertEquals;
5+
import static org.junit.Assert.assertFalse;
46
import static org.junit.Assert.assertThrows;
57
import static org.junit.Assert.assertTrue;
68

@@ -82,6 +84,39 @@ private static DatasetAttributes shardDatasetAttributes(
8284
return new DatasetAttributes(dimensions, shardSize, dataType, blockCodecInfo);
8385
}
8486

87+
@Test
88+
public void builderTests() {
89+
90+
final long[] dims = new long[]{100, 200, 300};
91+
final int[] blk = new int[]{32, 32, 32};
92+
93+
// default blockSize uses defaultBlockSize, not full dimensions
94+
final DatasetAttributes defaultBlk = DatasetAttributes.builder(dims, DataType.FLOAT32).build();
95+
assertArrayEquals(DatasetAttributes.defaultBlockSize(dims), defaultBlk.getBlockSize());
96+
97+
// blockSize is reflected in output
98+
final DatasetAttributes withBlk = DatasetAttributes.builder(dims, DataType.FLOAT32)
99+
.blockSize(blk).build();
100+
assertArrayEquals(blk, withBlk.getBlockSize());
101+
assertFalse(withBlk.isSharded());
102+
103+
// compression sets a data codec; RawCompression is a no-op
104+
final DatasetAttributes withGzip = DatasetAttributes.builder(dims, DataType.FLOAT32)
105+
.blockSize(blk).compression(new GzipCompression()).build();
106+
assertEquals(1, withGzip.getDataCodecInfos().length);
107+
108+
final DatasetAttributes withRaw = DatasetAttributes.builder(dims, DataType.FLOAT32)
109+
.blockSize(blk).compression(new RawCompression()).build();
110+
assertEquals(0, withRaw.getDataCodecInfos().length);
111+
112+
// round-trip through Builder(DatasetAttributes)
113+
final DatasetAttributes roundTrip = DatasetAttributes.builder(withGzip).build();
114+
assertArrayEquals(withGzip.getDimensions(), roundTrip.getDimensions());
115+
assertArrayEquals(withGzip.getBlockSize(), roundTrip.getBlockSize());
116+
assertEquals(withGzip.getDataType(), roundTrip.getDataType());
117+
assertEquals(withGzip.getDataCodecInfos().length, roundTrip.getDataCodecInfos().length);
118+
}
119+
85120
/**
86121
* Test that validateBlockShardSizes method rejects invalid shard and block size combinations.
87122
*/
@@ -91,7 +126,7 @@ public void testValidateBlockShardSizesInvalid() {
91126
final long[] dimensions = new long[]{100, 200, 300};
92127
final DataType dataType = DataType.UINT8;
93128

94-
// Block size too small
129+
// Block size too smallcompression != null && !(compression instanceof RawCompression)
95130
IllegalArgumentException ex0 = assertThrows(
96131
IllegalArgumentException.class,
97132
() -> shardDatasetAttributes(dimensions, new int[]{1, 1, 1}, new int[]{1, 0, -1}, dataType));

0 commit comments

Comments
 (0)