Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

<groupId>org.janelia.saalfeldlab</groupId>
<artifactId>n5-hdf5</artifactId>
<version>2.3.0-alpha-4-SNAPSHOT</version>
<version>2.3.0-alpha-4-fix</version>

<name>N5 HDF5 Bindings</name>
<description>Best effort N5 implementation on HDF5 files.</description>
Expand Down Expand Up @@ -139,7 +139,7 @@

<!-- NB: Deploy releases to the SciJava Maven repository. -->
<releaseProfiles>sign,deploy-to-scijava</releaseProfiles>
<n5.version>4.0.0-alpha-4</n5.version>
<n5.version>4.0.0-alpha-6</n5.version>
</properties>

<dependencies>
Expand Down
132 changes: 132 additions & 0 deletions src/main/java/org/janelia/saalfeldlab/n5/hdf5/N5HDF5Writer.java
Original file line number Diff line number Diff line change
Expand Up @@ -552,6 +552,138 @@ public <T> void writeBlock(
}
}

@Override
public <T> void writeRegion(
final String datasetPath,
final DatasetAttributes datasetAttributes,
final long[] min,
final long[] size,
final DataBlockSupplier<T> dataBlocks,
final boolean writeFully) throws N5Exception {

// For HDF5 (no sharding support), iterate through blocks in the region
// and write each one using writeBlock
final int n = min.length;
final int[] blockSize = datasetAttributes.getBlockSize();

// Compute min and max block grid positions
final long[] minBlock = new long[n];
final long[] maxBlock = new long[n];
for (int d = 0; d < n; ++d) {
minBlock[d] = min[d] / blockSize[d];
maxBlock[d] = (min[d] + size[d] - 1) / blockSize[d];
}

// Iterate through all blocks in the region
final long[] gridPosition = minBlock.clone();
while (true) {
// Check if we need to read existing data for this block
final DataBlock<T> existingBlock;
if (writeFully) {
existingBlock = null;
} else {
// Check if block is fully contained in the region
boolean fullyContained = true;
for (int d = 0; d < n; ++d) {
final long blockStart = gridPosition[d] * blockSize[d];
final long blockEnd = blockStart + blockSize[d];
if (blockStart < min[d] || blockEnd > min[d] + size[d]) {
fullyContained = false;
break;
}
}
@SuppressWarnings("unchecked")
final DataBlock<T> readBlockUnchecked = (DataBlock<T>) readBlock(datasetPath, datasetAttributes, gridPosition);
existingBlock = fullyContained ? null : readBlockUnchecked;
}

// Get the new block from the supplier
final DataBlock<T> dataBlock = dataBlocks.get(gridPosition, existingBlock);
if (dataBlock != null) {
writeBlock(datasetPath, datasetAttributes, dataBlock);
}

// Increment grid position
int d = 0;
for (; d < n; ++d) {
if (gridPosition[d] < maxBlock[d]) {
gridPosition[d]++;
break;
}
gridPosition[d] = minBlock[d];
}
if (d == n) break; // Done iterating
}
}

@Override
public <T> void writeRegion(
final String datasetPath,
final DatasetAttributes datasetAttributes,
final long[] min,
final long[] size,
final DataBlockSupplier<T> dataBlocks,
final boolean writeFully,
final java.util.concurrent.ExecutorService executor) throws N5Exception {

// For HDF5 (no sharding support), iterate through blocks in the region
// and write each one using writeBlock, parallelized with executor
final int n = min.length;
final int[] blockSize = datasetAttributes.getBlockSize();

// Compute min and max block grid positions
final long[] minBlock = new long[n];
final long[] maxBlock = new long[n];
for (int d = 0; d < n; ++d) {
minBlock[d] = min[d] / blockSize[d];
maxBlock[d] = (min[d] + size[d] - 1) / blockSize[d];
}

// Iterate through all blocks in the region and submit tasks to executor
final long[] gridPosition = minBlock.clone();
while (true) {
final long[] currentGridPosition = gridPosition.clone();
executor.submit(() -> {
// Check if we need to read existing data for this block
final DataBlock<T> existingBlock;
if (writeFully) {
existingBlock = null;
} else {
// Check if block is fully contained in the region
boolean fullyContained = true;
for (int d = 0; d < n; ++d) {
final long blockStart = currentGridPosition[d] * blockSize[d];
final long blockEnd = blockStart + blockSize[d];
if (blockStart < min[d] || blockEnd > min[d] + size[d]) {
fullyContained = false;
break;
}
}
@SuppressWarnings("unchecked")
final DataBlock<T> readBlockUnchecked = (DataBlock<T>) readBlock(datasetPath, datasetAttributes, currentGridPosition);
existingBlock = fullyContained ? null : readBlockUnchecked;
}

// Get the new block from the supplier (must be thread-safe)
final DataBlock<T> dataBlock = dataBlocks.get(currentGridPosition, existingBlock);
if (dataBlock != null) {
writeBlock(datasetPath, datasetAttributes, dataBlock);
}
});

// Increment grid position
int d = 0;
for (; d < n; ++d) {
if (gridPosition[d] < maxBlock[d]) {
gridPosition[d]++;
break;
}
gridPosition[d] = minBlock[d];
}
if (d == n) break; // Done iterating
}
}

@Override
public boolean deleteBlock(String pathName, final long... gridPosition) throws N5Exception {

Expand Down