-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
wip: toward a builder patter for metadata configurations
- Loading branch information
Showing
12 changed files
with
857 additions
and
0 deletions.
There are no files selected for viewing
23 changes: 23 additions & 0 deletions
23
src/main/java/org/janelia/saalfeldlab/n5/config/AbstractConfigurationBuilder.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package org.janelia.saalfeldlab.n5.config; | ||
|
||
import org.janelia.saalfeldlab.n5.metadata.MetadataHierarchyWriter; | ||
|
||
public abstract class AbstractConfigurationBuilder implements ConfigurationBuilder { | ||
|
||
protected Parameters parameters; | ||
|
||
public AbstractConfigurationBuilder() { | ||
|
||
parameters = new Parameters(); | ||
} | ||
|
||
@Override | ||
public Parameters getParameters() { | ||
|
||
return parameters; | ||
} | ||
|
||
@Override | ||
public abstract MetadataHierarchyWriter getWriter(); | ||
|
||
} |
188 changes: 188 additions & 0 deletions
188
src/main/java/org/janelia/saalfeldlab/n5/config/ConfigurationBuilder.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,188 @@ | ||
package org.janelia.saalfeldlab.n5.config; | ||
|
||
import java.util.Map; | ||
import java.util.function.IntFunction; | ||
import java.util.stream.IntStream; | ||
|
||
import org.janelia.saalfeldlab.n5.Compression; | ||
import org.janelia.saalfeldlab.n5.DataType; | ||
import org.janelia.saalfeldlab.n5.DatasetAttributes; | ||
import org.janelia.saalfeldlab.n5.N5Exception; | ||
import org.janelia.saalfeldlab.n5.imglib2.N5Utils; | ||
import org.janelia.saalfeldlab.n5.metadata.MetadataHierarchyWriter; | ||
import org.janelia.saalfeldlab.n5.universe.metadata.axes.Axis; | ||
|
||
import net.imglib2.RandomAccessibleInterval; | ||
import net.imglib2.img.cell.AbstractCellImg; | ||
import net.imglib2.img.cell.CellImg; | ||
import net.imglib2.type.NativeType; | ||
|
||
public interface ConfigurationBuilder { | ||
|
||
public Parameters getParameters(); | ||
|
||
public MetadataHierarchyWriter getWriter(); | ||
|
||
public default ConfigurationBuilder image( | ||
final RandomAccessibleInterval<? extends NativeType<?>> img, | ||
final Axis[] axes) { | ||
|
||
dataType((NativeType<?>)img.getType()); | ||
dimensions(img.dimensionsAsLongArray()); | ||
numChannels(img, axes); | ||
numTimepoints(img, axes); | ||
|
||
if (img instanceof CellImg) { | ||
AbstractCellImg<?, ?, ?, ?> cellimg = (AbstractCellImg<?, ?, ?, ?>)img; | ||
blockSize(cellimg.getCellGrid().getCellDimensions()); | ||
} | ||
|
||
return this; | ||
} | ||
|
||
public default ConfigurationBuilder dimensions(final long... dimensions) { | ||
|
||
getParameters().dimensions = dimensions; | ||
return this; | ||
} | ||
|
||
public default ConfigurationBuilder blockSize(final int... blockSize) { | ||
|
||
getParameters().blockSize = blockSize; | ||
return this; | ||
} | ||
|
||
public default ConfigurationBuilder dataType(final DataType dataType ) { | ||
|
||
getParameters().dataType = dataType; | ||
return this; | ||
} | ||
|
||
public default ConfigurationBuilder dataType(@SuppressWarnings("rawtypes") final NativeType type ) { | ||
|
||
@SuppressWarnings("unchecked") | ||
final DataType dtype = N5Utils.dataType(type); | ||
if (dtype != null) | ||
dataType(dtype); | ||
|
||
return this; | ||
} | ||
|
||
public default ConfigurationBuilder compression(final Compression compression ) { | ||
|
||
getParameters().compression = compression; | ||
return this; | ||
} | ||
|
||
public default ConfigurationBuilder resolution(final double... resolution) { | ||
|
||
getParameters().resolution = resolution; | ||
return this; | ||
} | ||
|
||
public default ConfigurationBuilder offset(final double... offset) { | ||
|
||
getParameters().offset = offset; | ||
return this; | ||
} | ||
|
||
public default ConfigurationBuilder unit(final String... units) { | ||
|
||
getParameters().units = units; | ||
return this; | ||
} | ||
|
||
public default ConfigurationBuilder numChannels(final int numChannels) { | ||
|
||
getParameters().numChannels = numChannels; | ||
return this; | ||
} | ||
|
||
public default ConfigurationBuilder multichannelGroups(final IntFunction<String> relativeChannelGroupName) { | ||
|
||
getParameters().relativeChannelGroupName = relativeChannelGroupName; | ||
return this; | ||
} | ||
|
||
public default ConfigurationBuilder multichannelGroups(final String... relativeChannelGroupNames) { | ||
|
||
getParameters().relativeChannelGroupName = c -> relativeChannelGroupNames[c]; | ||
return this; | ||
} | ||
|
||
public default ConfigurationBuilder multichannelGroups(final Map<Integer,String> relativeChannelGroupNames) { | ||
|
||
getParameters().relativeChannelGroupName = c -> relativeChannelGroupNames.get(c); | ||
return this; | ||
} | ||
|
||
public default ConfigurationBuilder numScales(final int numScales) { | ||
|
||
getParameters().numScales = numScales; | ||
return this; | ||
} | ||
|
||
public default ConfigurationBuilder multiscaleGroups(final IntFunction<String> relativeScaleLevelGroupName) { | ||
|
||
getParameters().relativeScaleLevelGroupName = relativeScaleLevelGroupName; | ||
return this; | ||
} | ||
|
||
public default ConfigurationBuilder multiscaleGroups(final String... relativeScaleLevelGroupName) { | ||
|
||
getParameters().relativeScaleLevelGroupName = c -> relativeScaleLevelGroupName[c]; | ||
return this; | ||
} | ||
|
||
public default ConfigurationBuilder multiscaleGroups(final Map<Integer, String> relativeScaleLevelGroupName) { | ||
|
||
getParameters().relativeScaleLevelGroupName = s -> relativeScaleLevelGroupName.get(s); | ||
return this; | ||
} | ||
|
||
public default ConfigurationBuilder downsampleFactors(IntFunction<int[]> downsamplingFactors) { | ||
|
||
getParameters().downsamplingFactors = downsamplingFactors; | ||
return this; | ||
} | ||
|
||
public default ConfigurationBuilder downsampleFactors(int[][] downsamplingFactors) { | ||
|
||
getParameters().numScales = downsamplingFactors.length; | ||
getParameters().downsamplingFactors = s -> downsamplingFactors[s]; | ||
return this; | ||
} | ||
|
||
public default DatasetAttributes getBaseDatasetAttributes() { | ||
|
||
return new DatasetAttributes( | ||
getParameters().dimensions, | ||
getParameters().blockSize, | ||
getParameters().dataType, | ||
getParameters().compression); | ||
} | ||
|
||
public static long numChannels(final RandomAccessibleInterval<? extends NativeType<?>> img, final Axis[] axes) { | ||
|
||
return countElementsOfType(img, axes, Axis.CHANNEL); | ||
} | ||
|
||
public static long numTimepoints(final RandomAccessibleInterval<? extends NativeType<?>> img, final Axis[] axes) { | ||
|
||
return countElementsOfType(img, axes, Axis.SPACE); | ||
} | ||
|
||
public static long countElementsOfType(final RandomAccessibleInterval<? extends NativeType<?>> img, final Axis[] axes, final String type) { | ||
|
||
final int[] indexes = IntStream.range(0, axes.length) | ||
.filter(i -> axes[i].getType().equals(type)) | ||
.toArray(); | ||
if (indexes.length == 1) | ||
throw new N5Exception(String.format("Multiple %s axes detected, but only one allowed", type)); | ||
else if (indexes.length == 1) | ||
return img.dimension(indexes[0]); | ||
else | ||
return 1; | ||
} | ||
|
||
} |
48 changes: 48 additions & 0 deletions
48
src/main/java/org/janelia/saalfeldlab/n5/config/N5ViewerBuilder.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package org.janelia.saalfeldlab.n5.config; | ||
|
||
import org.janelia.saalfeldlab.n5.N5Exception; | ||
import org.janelia.saalfeldlab.n5.metadata.N5ViewerMultiscaleHierarchyWriter; | ||
import org.janelia.saalfeldlab.n5.universe.metadata.axes.AxisUtils; | ||
|
||
import net.imglib2.img.cell.CellImgFactory; | ||
import net.imglib2.type.numeric.integer.UnsignedByteType; | ||
|
||
public class N5ViewerBuilder extends AbstractConfigurationBuilder { | ||
|
||
public N5ViewerBuilder() { | ||
|
||
super(); | ||
} | ||
|
||
@Override | ||
public N5ViewerMultiscaleHierarchyWriter getWriter() { | ||
|
||
// TODO check that all units are equal? | ||
return N5ViewerMultiscaleHierarchyWriter.build( | ||
getParameters().numChannels, | ||
getBaseDatasetAttributes(), | ||
getParameters().numScales, | ||
getParameters().resolution, | ||
getParameters().units[0], | ||
getParameters().downsamplingFactors); | ||
} | ||
|
||
@Override | ||
public ConfigurationBuilder offset(final double[] offset) { | ||
|
||
throw new N5Exception("N5Viewer does not support offset"); | ||
} | ||
|
||
public static void main(String[] args) { | ||
|
||
final N5ViewerBuilder builder = new N5ViewerBuilder(); | ||
builder.image( | ||
new CellImgFactory<UnsignedByteType>(new UnsignedByteType()).create(4, 3, 2), | ||
AxisUtils.buildAxes("x", "y", "z")); | ||
System.out.println(builder.parameters); | ||
|
||
// throws exception | ||
// builder.offset(new double[]{2, 3, 4}); | ||
} | ||
|
||
} |
51 changes: 51 additions & 0 deletions
51
src/main/java/org/janelia/saalfeldlab/n5/config/Parameters.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
package org.janelia.saalfeldlab.n5.config; | ||
|
||
import java.util.Arrays; | ||
import java.util.function.IntFunction; | ||
|
||
import org.janelia.saalfeldlab.n5.Compression; | ||
import org.janelia.saalfeldlab.n5.DataType; | ||
import org.janelia.saalfeldlab.n5.GzipCompression; | ||
|
||
public class Parameters { | ||
|
||
// single (base) dataset | ||
public long[] dimensions; | ||
public int[] blockSize; | ||
public DataType dataType; | ||
public Compression compression = new GzipCompression(); | ||
|
||
// spatial and time resolution | ||
public double[] resolution; | ||
public double[] offset; | ||
public String[] units; | ||
|
||
// multichannel | ||
public int numChannels = 1; | ||
public IntFunction<String> relativeChannelGroupName = c -> String.format("c%d", c); | ||
|
||
// multiscale | ||
public int numScales; | ||
public IntFunction<String> relativeScaleLevelGroupName = s -> String.format("s%d", s); | ||
public IntFunction<int[]> blockSizePerScaleLevel = s -> blockSize; | ||
public IntFunction<int[]> downsamplingFactors = s -> { | ||
final int[] factors = new int[dimensions.length]; | ||
Arrays.fill(factors, (int)Math.pow(2, s)); | ||
return factors; | ||
}; | ||
|
||
public String toString() { | ||
|
||
return String.format( | ||
"dimensions : %s\n" + | ||
"dataType : %s\n" + | ||
"blockSize : %s\n" + | ||
"resolution : %s\n" + | ||
"offset : %s\n", | ||
Arrays.toString(dimensions), | ||
dataType, | ||
Arrays.toString(blockSize), | ||
Arrays.toString(resolution), | ||
Arrays.toString(offset)); | ||
} | ||
} |
42 changes: 42 additions & 0 deletions
42
src/main/java/org/janelia/saalfeldlab/n5/metadata/DatasetUtils.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
package org.janelia.saalfeldlab.n5.metadata; | ||
|
||
import java.util.function.IntFunction; | ||
import java.util.function.Supplier; | ||
import java.util.stream.IntStream; | ||
|
||
import org.janelia.saalfeldlab.n5.Compression; | ||
import org.janelia.saalfeldlab.n5.DatasetAttributes; | ||
import org.janelia.saalfeldlab.n5.imglib2.N5Utils; | ||
import org.janelia.scicomp.n5.zstandard.ZstandardCompression; | ||
|
||
import net.imglib2.RandomAccessibleInterval; | ||
import net.imglib2.type.NativeType; | ||
|
||
public class DatasetUtils { | ||
|
||
public static <T extends NativeType<T>> DatasetAttributes defaultDatasetAttributes( | ||
final RandomAccessibleInterval<T> img ) { | ||
|
||
return datasetAttributes(img, | ||
() -> IntStream.generate(() -> 64).limit(img.numDimensions()).toArray(), | ||
ZstandardCompression::new); | ||
} | ||
|
||
public static <T extends NativeType<T>> DatasetAttributes datasetAttributes( | ||
final RandomAccessibleInterval<T> img, | ||
final Supplier<int[]> blockSize, | ||
final Supplier<Compression> compression) { | ||
|
||
return new DatasetAttributes( | ||
img.dimensionsAsLongArray(), | ||
blockSize.get(), | ||
N5Utils.dataType(img.getType()), | ||
compression.get()); | ||
} | ||
|
||
public static IntFunction<int[]> toFunction(int[][] arr) { | ||
|
||
return i -> arr[i]; | ||
} | ||
|
||
} |
9 changes: 9 additions & 0 deletions
9
src/main/java/org/janelia/saalfeldlab/n5/metadata/MetadataHierarchyWriter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package org.janelia.saalfeldlab.n5.metadata; | ||
|
||
import org.janelia.saalfeldlab.n5.N5Writer; | ||
|
||
public interface MetadataHierarchyWriter { | ||
|
||
public void write(final N5Writer n5, final String baseDataset); | ||
|
||
} |
Oops, something went wrong.