Skip to content

Commit

Permalink
Correct stupid width and height calculation bug when deriving width a…
Browse files Browse the repository at this point in the history
…nd height for tile render parameters. Refactor core logic into separate method to simplify testing. Add test to catch bug. This fixes #24.
  • Loading branch information
trautmane committed Mar 22, 2017
1 parent a0870ea commit a9e9a8f
Show file tree
Hide file tree
Showing 2 changed files with 123 additions and 69 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -142,80 +142,13 @@ public RenderParameters getRenderParameters(@PathParam("owner") final String own

RenderParameters parameters = null;
try {
final TileSpec tileSpec = getTileSpec(owner, project, stack, tileId, true);
tileSpec.flattenTransforms();

double tileRenderX = tileSpec.getMinX();
double tileRenderY = tileSpec.getMinY();

int tileRenderWidth;
if (width == null) {
tileRenderWidth = (int) (tileSpec.getMaxX() - tileSpec.getMinX());
} else {
tileRenderWidth = width;
}

int tileRenderHeight;
if (height == null) {
tileRenderHeight = (int) (tileSpec.getMaxY() - tileSpec.getMinY());
} else {
tileRenderHeight = height;
}

final StackId stackId = new StackId(owner, project, stack);
final StackMetaData stackMetaData = getStackMetaData(stackId);

if ((normalizeForMatching != null) && normalizeForMatching) {

// When deriving point matches for a tile pair in which each tile has different lens correction
// transformations, the bounding box for each rendered tile needs to be normalized.
//
// Normalization is achieved by:
// (1) Removing the last transform spec (assumed to be an affine that positions the tile in the world).
// (2) Setting the render start coordinate to (0,0).
// (3) Padding the raw tile width and height by multiplying a normalization factor (1.05).
// Assuming that all tiles in a stack have the same raw width and height, this ensures
// that normalized tiles also have the same width and height with a little extra room
// for edges that are rotated/skewed by lens correction.
// (4) Ensuring that the normalized width and height are even by adding a pixel as needed.
//
// Consistent and even tile sizes are currently a requirement for generating DMesh point matches.

final double normalizationFactor = 1.05;
if (width == null) {
tileRenderWidth = (int) (tileSpec.getWidth() * normalizationFactor);
}
if (height == null) {
tileRenderHeight = (int) (tileSpec.getHeight() * normalizationFactor);
}

tileSpec.removeLastTransformSpec();
final TileSpec tileSpec = getTileSpec(owner, project, stack, tileId, true);

// If the tile still has more than 3 transforms, remove all but the last 3.
// This assumes that the last 3 transforms are for lens correction.
// Hopefully at some point we'll label transforms so that it is possible to
// explicitly include only lens correction transforms.
while (tileSpec.getTransforms().size() > 3) {
tileSpec.removeLastTransformSpec();
}

tileRenderX = 0;
tileRenderY = 0;

if ((tileRenderWidth % 2) == 1) {
tileRenderWidth++;
}
if ((tileRenderHeight % 2) == 1) {
tileRenderHeight++;
}
}
parameters = getCoreTileRenderParameters(width, height, scale, normalizeForMatching, tileSpec);

parameters = new RenderParameters(null,
tileRenderX,
tileRenderY,
tileRenderWidth,
tileRenderHeight,
scale);
parameters.setDoFilter(filter);
parameters.setBinaryMask(binaryMask);
parameters.setExcludeMask(excludeMask);
Expand Down Expand Up @@ -340,6 +273,78 @@ public RenderParameters getTileWithNeighborsRenderParameters(@PathParam("owner")
return parameters;
}

protected static RenderParameters getCoreTileRenderParameters(final Integer width,
final Integer height,
final Double scale,
final Boolean normalizeForMatching,
final TileSpec tileSpec) {
tileSpec.flattenTransforms();

double tileRenderX = tileSpec.getMinX();
double tileRenderY = tileSpec.getMinY();

int tileRenderWidth;
if (width == null) {
tileRenderWidth = (int) (tileSpec.getMaxX() - tileSpec.getMinX() + 1);
} else {
tileRenderWidth = width;
}

int tileRenderHeight;
if (height == null) {
tileRenderHeight = (int) (tileSpec.getMaxY() - tileSpec.getMinY() + 1);
} else {
tileRenderHeight = height;
}

if ((normalizeForMatching != null) && normalizeForMatching) {

// When deriving point matches for a tile pair in which each tile has different lens correction
// transformations, the bounding box for each rendered tile needs to be normalized.
//
// Normalization is achieved by:
// (1) Removing the last transform spec (assumed to be an affine that positions the tile in the world).
// (2) Setting the render start coordinate to (0,0).
// (3) Padding the raw tile width and height by multiplying a normalization factor (1.05).
// Assuming that all tiles in a stack have the same raw width and height, this ensures
// that normalized tiles also have the same width and height with a little extra room
// for edges that are rotated/skewed by lens correction.
// (4) Ensuring that the normalized width and height are even by adding a pixel as needed.
//
// Consistent and even tile sizes are currently a requirement for generating DMesh point matches.

final double normalizationFactor = 1.05;
if (width == null) {
tileRenderWidth = (int) (tileSpec.getWidth() * normalizationFactor);
}
if (height == null) {
tileRenderHeight = (int) (tileSpec.getHeight() * normalizationFactor);
}

tileSpec.removeLastTransformSpec();

// If the tile still has more than 3 transforms, remove all but the last 3.
// This assumes that the last 3 transforms are for lens correction.
// Hopefully at some point we'll label transforms so that it is possible to
// explicitly include only lens correction transforms.
while (tileSpec.getTransforms().size() > 3) {
tileSpec.removeLastTransformSpec();
}

tileRenderX = 0;
tileRenderY = 0;

if ((tileRenderWidth % 2) == 1) {
tileRenderWidth++;
}
if ((tileRenderHeight % 2) == 1) {
tileRenderHeight++;
}
}

return new RenderParameters(null, tileRenderX, tileRenderY, tileRenderWidth, tileRenderHeight, scale);
}

private StackMetaData getStackMetaData(final StackId stackId)
throws ObjectNotFoundException {

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package org.janelia.render.service;

import org.janelia.alignment.RenderParameters;
import org.janelia.alignment.spec.TileSpec;
import org.junit.Assert;
import org.junit.Test;

/**
* Tests the {@link TileDataService} class.
*
* @author Eric Trautman
*/
public class TileDataServiceTest {

@Test
public void testGetCoreTileRenderParameters() throws Exception {

final String json =
"{\n" +
" \"tileId\" : \"1,3484_aligned_0_1_flip\",\n" +
" \"z\" : 3484.0, \"minX\" : 1896.0, \"minY\" : 876.0, \"maxX\" : 2919.0, \"maxY\" : 1899.0,\n" +
" \"width\" : 1024.0, \"height\" : 1024.0,\n" +
" \"mipmapLevels\" : {\n" +
" \"0\" : {\n" +
" \"imageUrl\" : \"file:///data/nc-em/russelt/20170227_Princeton_Pinky40/4_aligned_tiled/1,3484_aligned_0_1_flip.png\"\n" +
" }\n" +
" },\n" +
" \"transforms\" : {\n" +
" \"type\" : \"list\",\n" +
" \"specList\" : [ {\n" +
" \"className\" : \"mpicbg.trakem2.transform.AffineModel2D\",\n" +
" \"dataString\" : \"1.0000000000 0.0000000000 0.0000000000 1.0000000000 1896.0000000000 -876.0000000000\"\n" +
" }, {\n" +
" \"className\" : \"mpicbg.trakem2.transform.AffineModel2D\",\n" +
" \"dataString\" : \"1.0000000000 0.0000000000 0.0000000000 1.0000000000 0.0000000000 1752.0000000000\"\n" +
" } ]\n" +
" }\n" +
"}";

final TileSpec tileSpec = TileSpec.fromJson(json);

final RenderParameters renderParameters =
TileDataService.getCoreTileRenderParameters(null, null, null, null, tileSpec);

Assert.assertEquals("invalid width for tile", 1024, renderParameters.getWidth());
Assert.assertEquals("invalid height for tile", 1024, renderParameters.getHeight());
}

}

0 comments on commit a9e9a8f

Please sign in to comment.