Skip to content
Snippets Groups Projects
Commit 1fc29753 authored by Vojtech Moravec's avatar Vojtech Moravec
Browse files

Improve voxel loading methods.

parent b99c301c
No related branches found
No related tags found
No related merge requests found
...@@ -23,7 +23,7 @@ public abstract class BasicLoader { ...@@ -23,7 +23,7 @@ public abstract class BasicLoader {
return wrappingStrategy; return wrappingStrategy;
} }
public void setWrappingStrategy(DataWrappingStrategy strategy) { public void setWrappingStrategy(final DataWrappingStrategy strategy) {
wrappingStrategy = strategy; wrappingStrategy = strategy;
} }
...@@ -47,7 +47,7 @@ public abstract class BasicLoader { ...@@ -47,7 +47,7 @@ public abstract class BasicLoader {
final int rowVectorCount = (int) Math.ceil((double) dims.getX() / (double) vectorSize); final int rowVectorCount = (int) Math.ceil((double) dims.getX() / (double) vectorSize);
final int planeCount = planeRange.getTo() - planeRange.getFrom(); final int planeCount = planeRange.getTo() - planeRange.getFrom();
final int vectorCount = planeCount * dims.getY() * rowVectorCount; final int vectorCount = planeCount * dims.getY() * rowVectorCount;
int[][] rowVectors = new int[vectorCount][vectorSize]; final int[][] rowVectors = new int[vectorCount][vectorSize];
int vectorIndex = 0; int vectorIndex = 0;
int baseX; int baseX;
...@@ -75,7 +75,7 @@ public abstract class BasicLoader { ...@@ -75,7 +75,7 @@ public abstract class BasicLoader {
final int rowVectorCount = (int) Math.ceil((double) dims.getX() / (double) vectorSize); final int rowVectorCount = (int) Math.ceil((double) dims.getX() / (double) vectorSize);
final int vectorCount = dims.getZ() * dims.getY() * rowVectorCount; final int vectorCount = dims.getZ() * dims.getY() * rowVectorCount;
int[][] rowVectors = new int[vectorCount][vectorSize]; final int[][] rowVectors = new int[vectorCount][vectorSize];
int vectorIndex = 0; int vectorIndex = 0;
int baseX; int baseX;
...@@ -103,7 +103,7 @@ public abstract class BasicLoader { ...@@ -103,7 +103,7 @@ public abstract class BasicLoader {
final int planeCount = planeRange.getTo() - planeRange.getFrom(); final int planeCount = planeRange.getTo() - planeRange.getFrom();
final int blockCount = planeCount * Block.calculateRequiredChunkCount(dims.toV2i(), blockDim); final int blockCount = planeCount * Block.calculateRequiredChunkCount(dims.toV2i(), blockDim);
int[][] blocks = new int[blockCount][blockSize]; final int[][] blocks = new int[blockCount][blockSize];
int blockIndex = 0; int blockIndex = 0;
for (int plane = planeRange.getFrom(); plane < planeRange.getTo(); plane++) { for (int plane = planeRange.getFrom(); plane < planeRange.getTo(); plane++) {
...@@ -122,7 +122,7 @@ public abstract class BasicLoader { ...@@ -122,7 +122,7 @@ public abstract class BasicLoader {
final int planeCount = planeRange.getTo() - planeRange.getFrom(); final int planeCount = planeRange.getTo() - planeRange.getFrom();
final int blockCount = planeCount * Block.calculateRequiredChunkCount(dims.toV2i(), blockDim); final int blockCount = planeCount * Block.calculateRequiredChunkCount(dims.toV2i(), blockDim);
int[][] blocks = new int[blockCount][blockSize]; final int[][] blocks = new int[blockCount][blockSize];
int blockIndex = 0; int blockIndex = 0;
for (int plane = planeRange.getFrom(); plane < planeRange.getTo(); plane++) { for (int plane = planeRange.getFrom(); plane < planeRange.getTo(); plane++) {
...@@ -248,11 +248,7 @@ public abstract class BasicLoader { ...@@ -248,11 +248,7 @@ public abstract class BasicLoader {
} }
} }
private void loadVoxel(final int[] voxel, private void loadVoxel(final int[] voxel, final int voxelXOffset, final int voxelYOffset, final int voxelZOffset, final V3i voxelDim) {
final int voxelXOffset,
final int voxelYOffset,
final int voxelZOffset,
final V3i voxelDim) {
int srcX, srcY, srcZ; int srcX, srcY, srcZ;
for (int z = 0; z < voxelDim.getZ(); z++) { for (int z = 0; z < voxelDim.getZ(); z++) {
srcZ = voxelZOffset + z; srcZ = voxelZOffset + z;
...@@ -273,152 +269,102 @@ public abstract class BasicLoader { ...@@ -273,152 +269,102 @@ public abstract class BasicLoader {
break; break;
} }
voxel[Voxel.dataIndex(x, y, z, voxelDim)] = valueAt(srcZ, Block.index(x, y, dims.getX())); voxel[Voxel.dataIndex(x, y, z, voxelDim)] = valueAt(srcZ, Block.index(srcX, srcY, dims.getX()));
} }
} }
} }
} }
protected int[][] experimentalLoadVoxelsImplByValueAt(final V3i voxelDim, final Range<Integer> planeRange) { private void loadVoxel(final int[] voxel,
System.out.println("experimentalLoadVoxelsImplByValueAt"); final int[][] planesData,
final int voxelCount = Voxel.calculateRequiredVoxelCount(dims, voxelDim); final int voxelXOffset,
final int voxelElementCount = (int) voxelDim.multiplyTogether(); final int voxelYOffset,
int[][] voxels = new int[voxelCount][voxelElementCount]; final V3i voxelDim) {
int voxelIndex = 0; int srcX, srcY;
for (int voxelZOffset = planeRange.getFrom(); voxelZOffset < planeRange.getTo(); voxelZOffset += voxelDim.getZ()) { for (int z = 0; z < voxelDim.getZ(); z++) {
for (int voxelYOffset = 0; voxelYOffset < dims.getY(); voxelYOffset += voxelDim.getY()) { for (int y = 0; y < voxelDim.getY(); y++) {
for (int voxelXOffset = 0; voxelXOffset < dims.getX(); voxelXOffset += voxelDim.getX()) { srcY = voxelYOffset + y;
loadVoxel(voxels[voxelIndex++], voxelXOffset, voxelYOffset, voxelZOffset, voxelDim); if (srcY >= dims.getY()) {
// Handle row overflow.
break;
}
for (int x = 0; x < voxelDim.getX(); x++) {
srcX = voxelXOffset + x;
if (srcX >= dims.getX()) {
// Handle column overflow
break;
}
voxel[Voxel.dataIndex(x, y, z, voxelDim)] = planesData[z][Block.index(srcX, srcY, dims.getX())];
} }
} }
} }
return voxels;
} }
/** /**
* Load specified planes from dataset to voxel of specified dimensions. * Load specified planes from dataset to voxel of specified dimensions.
* This overload uses the loadPlaneData function to read src data. * This overload uses the valueAt function to read src data.
* *
* @param voxelDim Single voxel dimensions. * @param voxelDim Single voxel dimensions.
* @param planeRange Range of planes to load voxels from. * @param planeRange Range of planes to load voxels from.
* @return Voxel data arranged in arrays. * @return Voxel data arranged in arrays.
*/ */
protected int[][] loadVoxelsImplByLoadPlaneData(final V3i voxelDim, final Range<Integer> planeRange) throws IOException { protected int[][] loadVoxelsImplByValueAt(final V3i voxelDim, final Range<Integer> planeRange) {
final Voxel dstVoxel = new Voxel(voxelDim); final int voxelElementCount = (int) voxelDim.multiplyTogether();
final int rangeSize = planeRange.getTo() - planeRange.getFrom(); final int rangeSize = planeRange.getTo() - planeRange.getFrom();
final V3i srcVoxel = new V3i(dims.getX(), dims.getY(), rangeSize); final V3i srcVoxel = new V3i(dims.getX(), dims.getY(), rangeSize);
final int xVoxelCount = (int) Math.ceil((double) dims.getX() / (double) voxelDim.getX()); final int voxelCount = Voxel.calculateRequiredVoxelCount(srcVoxel, voxelDim);
final int yVoxelCount = (int) Math.ceil((double) dims.getY() / (double) voxelDim.getY()); final int[][] voxels = new int[voxelCount][voxelElementCount];
int voxelIndex = 0;
final int voxelIndexOffset = -((planeRange.getFrom() / voxelDim.getZ()) * (xVoxelCount * yVoxelCount));
int[][] voxels = new int[Voxel.calculateRequiredVoxelCount(srcVoxel, voxelDim)][(int) voxelDim.multiplyTogether()];
final int dimX = dims.getX();
final int dimY = dims.getY();
final int dimZ = planeRange.getTo();
final int voxelDimX = voxelDim.getX();
final int voxelDimY = voxelDim.getY();
final int voxelDimZ = voxelDim.getZ();
int dstZ, dstY, dstX, voxelX, voxelY, voxelZ, voxelIndex;
int[] planeData;
for (int srcZ = planeRange.getFrom(); srcZ < dimZ; srcZ++) {
planeData = loadPlaneData(srcZ);
dstZ = srcZ / voxelDimZ;
voxelZ = srcZ - (dstZ * voxelDimZ);
for (int srcY = 0; srcY < dimY; srcY++) {
dstY = srcY / voxelDimY;
voxelY = srcY - (dstY * voxelDimY);
for (int srcX = 0; srcX < dimX; srcX++) {
dstX = srcX / voxelDimX;
voxelX = srcX - (dstX * voxelDimX);
voxelIndex = voxelIndexOffset + ((dstZ * (xVoxelCount * yVoxelCount)) + (dstY * xVoxelCount) + dstX);
voxels[voxelIndex][dstVoxel.dataIndex(voxelX, voxelY, voxelZ, voxelDim)] = planeData[(srcY * dimX) + srcX]; for (int voxelZOffset = planeRange.getFrom(); voxelZOffset < planeRange.getTo(); voxelZOffset += voxelDim.getZ()) {
for (int voxelYOffset = 0; voxelYOffset < dims.getY(); voxelYOffset += voxelDim.getY()) {
for (int voxelXOffset = 0; voxelXOffset < dims.getX(); voxelXOffset += voxelDim.getX()) {
loadVoxel(voxels[voxelIndex++], voxelXOffset, voxelYOffset, voxelZOffset, voxelDim);
} }
} }
} }
return voxels; return voxels;
} }
private void preloadPlanesData(final int[][] planesData, final int planeOffset, final int count) throws IOException {
for (int i = 0; i < count; i++) {
if (planeOffset + i < dims.getZ())
planesData[i] = loadPlaneData(planeOffset + i);
else
planesData[i] = new int[dims.toV2i().multiplyTogether()];
}
}
/** /**
* Load specified planes from dataset to voxel of specified dimensions. * Load specified planes from dataset to voxel of specified dimensions.
* This overload uses the valueAt function to read src data. * This overload uses the loadPlaneData function to read src data.
* *
* @param voxelDim Single voxel dimensions. * @param voxelDim Single voxel dimensions.
* @param planeRange Range of planes to load voxels from. * @param planeRange Range of planes to load voxels from.
* @return Voxel data arranged in arrays. * @return Voxel data arranged in arrays.
* @throws IOException When fails to load plane data.
*/ */
protected int[][] loadVoxelsImplByValueAt(final V3i voxelDim, protected int[][] loadVoxelsImplByLoadPlaneData(final V3i voxelDim, final Range<Integer> planeRange) throws IOException {
final Range<Integer> planeRange) throws IOException { final int voxelElementCount = (int) voxelDim.multiplyTogether();
// TODO(Moravec): Improve performance of loading.
final Voxel dstVoxel = new Voxel(voxelDim);
final int rangeSize = planeRange.getTo() - planeRange.getFrom(); final int rangeSize = planeRange.getTo() - planeRange.getFrom();
final V3i srcVoxel = new V3i(dims.getX(), dims.getY(), rangeSize); final V3i srcVoxel = new V3i(dims.getX(), dims.getY(), rangeSize);
final int xVoxelCount = (int) Math.ceil((double) dims.getX() / (double) voxelDim.getX()); final int voxelCount = Voxel.calculateRequiredVoxelCount(srcVoxel, voxelDim);
final int yVoxelCount = (int) Math.ceil((double) dims.getY() / (double) voxelDim.getY());
// NOTE(Moravec): We need voxelIndexOffset in case that planeRange is not the whole dataset. final int[][] voxels = new int[voxelCount][voxelElementCount];
// voxelIndex which is calculated inside the loop doesn't know that we are loading int voxelIndex = 0;
// only some voxel layer. So we need to set the offset and start filling voxel data from the start.
final int voxelIndexOffset = -((planeRange.getFrom() / voxelDim.getZ()) * (xVoxelCount * yVoxelCount)); final int[][] planesData = new int[voxelDim.getZ()][0];
int[][] voxels = new int[Voxel.calculateRequiredVoxelCount(srcVoxel, voxelDim)][(int) voxelDim.multiplyTogether()];
for (int voxelZOffset = planeRange.getFrom(); voxelZOffset < planeRange.getTo(); voxelZOffset += voxelDim.getZ()) {
final int workSize = rangeSize / threadCount; preloadPlanesData(planesData, voxelZOffset, voxelDim.getZ());
final Thread[] threads = new Thread[threadCount]; for (int voxelYOffset = 0; voxelYOffset < dims.getY(); voxelYOffset += voxelDim.getY()) {
for (int voxelXOffset = 0; voxelXOffset < dims.getX(); voxelXOffset += voxelDim.getX()) {
for (int wId = 0; wId < threadCount; wId++) { loadVoxel(voxels[voxelIndex++], planesData, voxelXOffset, voxelYOffset, voxelDim);
final int fromZ = wId * workSize;
final int toZ = (wId == threadCount - 1) ? rangeSize : (workSize + (wId * workSize));
threads[wId] = new Thread(() -> {
final int dimX = dims.getX();
final int dimY = dims.getY();
final int zBase = planeRange.getFrom();
final int voxelDimX = voxelDim.getX();
final int voxelDimY = voxelDim.getY();
final int voxelDimZ = voxelDim.getZ();
int srcZ, dstZ, dstY, dstX, voxelX, voxelY, voxelZ, voxelIndex;
for (int zOffset = fromZ; zOffset < toZ; zOffset++) {
srcZ = zBase + zOffset;
dstZ = srcZ / voxelDimZ;
voxelZ = srcZ - (dstZ * voxelDimZ);
for (int srcY = 0; srcY < dimY; srcY++) {
dstY = srcY / voxelDimY;
voxelY = srcY - (dstY * voxelDimY);
for (int srcX = 0; srcX < dimX; srcX++) {
dstX = srcX / voxelDimX;
voxelX = srcX - (dstX * voxelDimX);
voxelIndex = voxelIndexOffset + ((dstZ * (xVoxelCount * yVoxelCount)) + (dstY * xVoxelCount) + dstX);
voxels[voxelIndex][dstVoxel.dataIndex(voxelX, voxelY, voxelZ, voxelDim)] = valueAt(srcZ, (srcY * dimX) + srcX);
}
}
} }
});
threads[wId].start();
}
try {
for (int wId = 0; wId < threadCount; wId++) {
threads[wId].join();
} }
} catch (InterruptedException e) {
throw new IOException("threads[wId].join() failed.", e);
} }
return voxels; return voxels;
} }
......
...@@ -104,8 +104,7 @@ public class FlatBufferLoader extends BasicLoader implements IPlaneLoader { ...@@ -104,8 +104,7 @@ public class FlatBufferLoader extends BasicLoader implements IPlaneLoader {
} }
@Override @Override
public int[][] loadVoxels(final V3i voxelDim, final Range<Integer> planeRange) throws IOException { public int[][] loadVoxels(final V3i voxelDim, final Range<Integer> planeRange) {
// return loadVoxelsImplByValueAt(voxelDim, planeRange); return loadVoxelsImplByValueAt(voxelDim, planeRange);
return experimentalLoadVoxelsImplByValueAt(voxelDim, planeRange);
} }
} }
...@@ -25,7 +25,7 @@ public final class ImageJBufferLoader extends BasicLoader implements IPlaneLoade ...@@ -25,7 +25,7 @@ public final class ImageJBufferLoader extends BasicLoader implements IPlaneLoade
return true; return true;
} }
private void copyShortArrayIntoBuffer(short[] srcArray, int[] destBuffer, int destOffset, int copyLen) { private void copyShortArrayIntoBuffer(final short[] srcArray, final int[] destBuffer, final int destOffset, final int copyLen) {
for (int i = 0; i < copyLen; i++) { for (int i = 0; i < copyLen; i++) {
destBuffer[destOffset + i] = TypeConverter.shortToInt(srcArray[i]); destBuffer[destOffset + i] = TypeConverter.shortToInt(srcArray[i]);
} }
...@@ -39,12 +39,12 @@ public final class ImageJBufferLoader extends BasicLoader implements IPlaneLoade ...@@ -39,12 +39,12 @@ public final class ImageJBufferLoader extends BasicLoader implements IPlaneLoade
@Override @Override
protected int valueAt(int plane, int offset) { protected int valueAt(final int plane, final int offset) {
return TypeConverter.shortToInt(((short[]) bufferInputData.getPixelBuffer(plane))[offset]); return TypeConverter.shortToInt(((short[]) bufferInputData.getPixelBuffer(plane))[offset]);
} }
@Override @Override
public int[] loadPlanesU16Data(int[] planes) throws IOException { public int[] loadPlanesU16Data(final int[] planes) throws IOException {
if (planes.length < 1) { if (planes.length < 1) {
return new int[0]; return new int[0];
} else if (planes.length == 1) { } else if (planes.length == 1) {
...@@ -62,7 +62,7 @@ public final class ImageJBufferLoader extends BasicLoader implements IPlaneLoade ...@@ -62,7 +62,7 @@ public final class ImageJBufferLoader extends BasicLoader implements IPlaneLoade
Arrays.sort(planes); Arrays.sort(planes);
int[] destBuffer = new int[(int) totalValueCount]; final int[] destBuffer = new int[(int) totalValueCount];
int destOffset = 0; int destOffset = 0;
for (final int planeIndex : planes) { for (final int planeIndex : planes) {
final short[] srcBuffer = (short[]) bufferInputData.getPixelBuffer(planeIndex); final short[] srcBuffer = (short[]) bufferInputData.getPixelBuffer(planeIndex);
...@@ -82,7 +82,7 @@ public final class ImageJBufferLoader extends BasicLoader implements IPlaneLoade ...@@ -82,7 +82,7 @@ public final class ImageJBufferLoader extends BasicLoader implements IPlaneLoade
throw new IOException("Unable to load all image data, file size is too big."); throw new IOException("Unable to load all image data, file size is too big.");
} }
int[] destBuffer = new int[(int) totalValueCount]; final int[] destBuffer = new int[(int) totalValueCount];
int destOffset = 0; int destOffset = 0;
for (int planeIndex = 0; planeIndex < imageDims.getZ(); planeIndex++) { for (int planeIndex = 0; planeIndex < imageDims.getZ(); planeIndex++) {
final short[] srcBuffer = (short[]) bufferInputData.getPixelBuffer(planeIndex); final short[] srcBuffer = (short[]) bufferInputData.getPixelBuffer(planeIndex);
...@@ -98,14 +98,13 @@ public final class ImageJBufferLoader extends BasicLoader implements IPlaneLoade ...@@ -98,14 +98,13 @@ public final class ImageJBufferLoader extends BasicLoader implements IPlaneLoade
} }
@Override @Override
public int[][] loadBlocks(V2i blockDim, Range<Integer> planeRange) { public int[][] loadBlocks(final V2i blockDim, final Range<Integer> planeRange) {
return loadBlocksImplByValueAt(blockDim, planeRange); return loadBlocksImplByValueAt(blockDim, planeRange);
} }
@Override @Override
public int[][] loadVoxels(final V3i voxelDim, final Range<Integer> planeRange) throws IOException { public int[][] loadVoxels(final V3i voxelDim, final Range<Integer> planeRange) {
// return loadVoxelsImplByValueAt(voxelDim, planeRange); return loadVoxelsImplByValueAt(voxelDim, planeRange);
return experimentalLoadVoxelsImplByValueAt(voxelDim, planeRange);
} }
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment