Skip to content

Commit

Permalink
add excludeSameMfovNeighbors option to TilePairDerivationParameters, …
Browse files Browse the repository at this point in the history
…rename multisem.Utilities as MultiSemUtilities and move from render-ws-java-client module to render-app module
  • Loading branch information
trautmane committed Dec 6, 2024
1 parent 92675be commit 1674081
Show file tree
Hide file tree
Showing 17 changed files with 191 additions and 123 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@ public class TilePairDerivationParameters implements Serializable {
arity = 1)
public boolean excludeSameSectionNeighbors = false;

@Parameter(
names = "--excludeSameMfovNeighbors",
description = "Exclude neighbor tiles in the same layer (z) and MFOV as the source tile",
arity = 1)
public boolean excludeSameMfovNeighbors = false;

@Parameter(
names = "--excludePairsInMatchCollection",
description = "Name of match collection whose existing pairs should be excluded from the generated list (default is to include all pairs)"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.janelia.render.client.multisem;
package org.janelia.alignment.multisem;

import java.io.IOException;
import java.nio.file.Files;
Expand All @@ -9,16 +9,6 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.janelia.alignment.match.CanvasId;
import org.janelia.alignment.match.CanvasMatchResult;
import org.janelia.alignment.match.CanvasMatches;
import org.janelia.alignment.match.OrderedCanvasIdPair;
import org.janelia.alignment.spec.TileSpec;
import org.janelia.render.client.RenderDataClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import mpicbg.models.AbstractAffineModel2D;
import mpicbg.models.CoordinateTransform;
Expand All @@ -28,12 +18,20 @@
import mpicbg.models.Point;
import mpicbg.models.PointMatch;

import org.janelia.alignment.match.CanvasId;
import org.janelia.alignment.match.CanvasMatchResult;
import org.janelia.alignment.match.CanvasMatches;
import org.janelia.alignment.match.OrderedCanvasIdPair;
import org.janelia.alignment.spec.TileSpec;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Utility methods for working with Multi-SEM data sets.
*
* @author Eric Trautman
*/
public class Utilities {
public class MultiSemUtilities {

/**
* @return 0399_m0013 for w60_magc0399_scan005_m0013_s001
Expand Down Expand Up @@ -229,20 +227,5 @@ public static List<Point> getMatchingTransformedCornersForTile(final TileSpec ti
return tileSpec.getMatchingTransformedPoints(rawLocations);
}

/**
* @return list of distinct sorted MFOV names for the specified stack z-layer.
*/
public static List<String> getMFOVNames(final RenderDataClient renderDataClient,
final String stack,
final Double z)
throws IOException {
return renderDataClient.getTileBounds(stack, z)
.stream()
.map(tileBounds -> getMFOVForTileId(tileBounds.getTileId()))
.distinct()
.sorted()
.collect(Collectors.toList());
}

private static final Logger LOG = LoggerFactory.getLogger(Utilities.class);
private static final Logger LOG = LoggerFactory.getLogger(MultiSemUtilities.class);
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import org.janelia.alignment.match.CanvasId;
import org.janelia.alignment.match.OrderedCanvasIdPair;
import org.janelia.alignment.multisem.MultiSemUtilities;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -193,7 +194,8 @@ public Set<OrderedCanvasIdPair> getCircleNeighbors(final List<TileBounds> source
final Double explicitRadius,
final boolean excludeCornerNeighbors,
final boolean excludeSameLayerNeighbors,
final boolean excludeSameSectionNeighbors) {
final boolean excludeSameSectionNeighbors,
final boolean excludeSameMfovNeighbors) {

String firstTileId = null;
if (! sourceTileBoundsList.isEmpty()) {
Expand Down Expand Up @@ -232,14 +234,16 @@ public Set<OrderedCanvasIdPair> getCircleNeighbors(final List<TileBounds> source

neighborTileIdPairs.addAll(
getDistinctPairs(tileBounds, searchResults,
excludeCornerNeighbors, excludeSameSectionNeighbors, true));
excludeCornerNeighbors, excludeSameSectionNeighbors, excludeSameMfovNeighbors,
true));
}

for (final TileBoundsRTree neighborTree : neighborTrees) {
searchResults = neighborTree.findTilesInCircle(circle);
neighborTileIdPairs.addAll(
getDistinctPairs(tileBounds, searchResults,
excludeCornerNeighbors, excludeSameSectionNeighbors, false));
excludeCornerNeighbors, excludeSameSectionNeighbors, excludeSameMfovNeighbors,
false));
}
}

Expand Down Expand Up @@ -281,9 +285,11 @@ public static Set<OrderedCanvasIdPair> getDistinctPairs(final TileBounds fromTil
final List<TileBounds> toTiles,
final boolean excludeCornerNeighbors,
final boolean excludeSameSectionNeighbors,
final boolean excludeSameMfovNeighbors,
final boolean includeRelativePosition) {
final Set<OrderedCanvasIdPair> pairs = new HashSet<>(toTiles.size() * 2);
final String pTileId = fromTile.getTileId();
final String pMfov = excludeSameMfovNeighbors ? MultiSemUtilities.getMFOVForTileId(pTileId) : null;

final double fromMinX = fromTile.getMinX();
final double fromMaxX = fromTile.getMaxX();
Expand All @@ -302,6 +308,10 @@ public static Set<OrderedCanvasIdPair> getDistinctPairs(final TileBounds fromTil
isNeighborCenterInRange(fromMinX, fromMaxX, toTile.getMinX(), toTile.getMaxX()) ||
isNeighborCenterInRange(fromMinY, fromMaxY, toTile.getMinY(), toTile.getMaxY())) {

if (excludeSameMfovNeighbors && (pMfov.equals(MultiSemUtilities.getMFOVForTileId(qTileId)))) {
continue;
}

final OrderedCanvasIdPair pair;
if (includeRelativePosition) {
pair = OrderedCanvasIdPair.withRelativeMontagePositions(fromTile, toTile);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package org.janelia.alignment.multisem;

import org.junit.Assert;
import org.junit.Test;

/**
* Tests the {@link MultiSemUtilities} class.
*
* @author Eric Trautman
*/
public class MultiSemUtilitiesTest {

@Test
public void testTileIdParsers() {
final String tileId = "w60_magc0399_scan005_m0013_s001";
Assert.assertEquals("invalid MFOVForTileId",
"0399_m0013", MultiSemUtilities.getMFOVForTileId(tileId));
Assert.assertEquals("invalid SFOVForTileId",
"0399_m0013_s001", MultiSemUtilities.getSFOVForTileId(tileId));
Assert.assertEquals("invalid SFOVIndexForTileId",
"001", MultiSemUtilities.getSFOVIndexForTileId(tileId));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ public void testGetCircleNeighbors() {
null,
false,
false,
false,
false);

final Set<OrderedCanvasIdPair> expectedPairs = new TreeSet<>();
Expand All @@ -94,6 +95,7 @@ public void testGetCircleNeighbors() {
explicitRadius,
false,
false,
false,
false);

expectedPairs.clear();
Expand Down Expand Up @@ -123,6 +125,7 @@ public void testGetCircleNeighborsWithFullyOverlappingTiles() {
null,
false,
false,
false,
false);

final Set<OrderedCanvasIdPair> expectedPairs = new TreeSet<>();
Expand All @@ -147,17 +150,55 @@ public void testGetCanvasIdPairs() {
final TileBounds centerTile = tileBoundsList.get(4);

Set<OrderedCanvasIdPair> pairs =
TileBoundsRTree.getDistinctPairs(centerTile, tileBoundsList, false, false, false);
TileBoundsRTree.getDistinctPairs(centerTile,
tileBoundsList,
false,
false,
false,
false);
int expectedNumberOfCombinations = tileBoundsList.size() - 1; // all tiles except the center
Assert.assertEquals("incorrect number of combinations (with corner neighbors) in " + pairs,
expectedNumberOfCombinations, pairs.size());

expectedNumberOfCombinations = expectedNumberOfCombinations - 4; // remove the 4 corner tiles
pairs = TileBoundsRTree.getDistinctPairs(centerTile, tileBoundsList, true, false, true);
pairs = TileBoundsRTree.getDistinctPairs(centerTile,
tileBoundsList,
true,
false,
false,
true);
Assert.assertEquals("incorrect number of combinations (without corner neighbors) in " + pairs,
expectedNumberOfCombinations, pairs.size());
}

@Test
public void testGetDifferentMFovCanvasIdPairs() {

final Double z = 1.0;
final String sectionId = String.valueOf(z);
// s082 s083 s084
// s071 s070
final List<TileBounds> tileBoundsList = Arrays.asList(
new TileBounds("w60_magc0399_scan012_m0013_s082", sectionId, z, 5.0, 0.0, 17.0, 12.0),
new TileBounds("w60_magc0399_scan012_m0013_s083", sectionId, z, 15.0, 0.0, 27.0, 12.0),
new TileBounds("w60_magc0399_scan012_m0013_s084", sectionId, z, 25.0, 0.0, 37.0, 12.0),
new TileBounds("w60_magc0399_scan012_m0014_s071", sectionId, z, 10.0, 10.0, 22.0, 22.0),
new TileBounds("w60_magc0399_scan012_m0014_s070", sectionId, z, 20.0, 10.0, 32.0, 22.0)
);

final TileBounds testTile = tileBoundsList.get(1); // s083

final Set<OrderedCanvasIdPair> pairs =
TileBoundsRTree.getDistinctPairs(testTile,
tileBoundsList,
false,
false,
true,
false);
Assert.assertEquals("incorrect number of combinations in " + pairs,
2, pairs.size());
}

@Test
public void testFindCompletelyObscuredTiles() {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ public Parameters() {
}

public boolean hasTileIds() {
return (tileIds != null) && (tileIds.size() > 0);
return (tileIds != null) && (! tileIds.isEmpty());
}
}

Expand Down Expand Up @@ -154,7 +154,7 @@ public void runClient(final String[] args)
parameters.layerRange.minZ,
parameters.layerRange.maxZ,
explicitZValues);
if (this.zValues.size() == 0) {
if (this.zValues.isEmpty()) {
throw new IllegalArgumentException(
"stack " + firstStackName + " does not contain any layers with the specified z values, " +
"confirm --minZ and --maxZ are correct");
Expand Down Expand Up @@ -262,6 +262,7 @@ private List<String> debugPairsForStack(final String stackName)
null,
false,
false,
false,
false);

neighborPairs.addAll(currentNeighborPairs);
Expand All @@ -271,7 +272,7 @@ private List<String> debugPairsForStack(final String stackName)
final List<Point> pTransformedCornersAll = new ArrayList<>();
final List<Point> qTransformedCornersAll = new ArrayList<>();

if (neighborPairs.size() > 0) {
if (! neighborPairs.isEmpty()) {
final Map<Double, ResolvedTileSpecCollection> zToTilesMap = new HashMap<>(zValues.size());
for (final Double zVal : zValues) {
zToTilesMap.put(zVal, renderDataClient.getResolvedTiles(stackName, zVal));
Expand Down Expand Up @@ -329,8 +330,9 @@ private List<String> debugPairsForStack(final String stackName)
}
//System.out.println( model + ", " + model.getClass().getSimpleName());
//System.exit( 0 );
} catch (NotEnoughDataPointsException | IllDefinedDataPointsException e) {
e.printStackTrace();
} catch (final NotEnoughDataPointsException | IllDefinedDataPointsException e) {
//noinspection CallToPrintStackTrace
e.printStackTrace();
}
}

Expand Down Expand Up @@ -366,14 +368,15 @@ private List<String> debugPairsForStack(final String stackName)
}

// e.g. "[1.0, 0.0, 957.4067568339881], [0.0, 1.0, -1640.2727272727273]"
public static AffineModel2D stringToModel( String modelString )
@SuppressWarnings("unused")
public static AffineModel2D stringToModel(String modelString )
{
modelString = modelString.replace("[", "" );
modelString = modelString.replace("]", "" );
modelString = modelString.replace(" ", "" );
modelString = modelString.trim();

String[] s = modelString.split( "," );
final String[] s = modelString.split( "," );

final AffineModel2D model = new AffineModel2D();
model.set(Double.parseDouble(s[0]), Double.parseDouble(s[1]), Double.parseDouble(s[3]), Double.parseDouble(s[4]), Double.parseDouble(s[2]), Double.parseDouble(s[5]));
Expand Down Expand Up @@ -417,9 +420,10 @@ public static void computeError( final List<PointMatch> matches, final Model<?>
model.setCost( error );
System.out.println( "maxE=" + maxError + " " + model + ", " + model.getClass().getSimpleName());

} catch (NotEnoughDataPointsException | IllDefinedDataPointsException e) {
} catch (final NotEnoughDataPointsException | IllDefinedDataPointsException e) {
// TODO Auto-generated catch block
e.printStackTrace();
//noinspection CallToPrintStackTrace
e.printStackTrace();
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,6 @@ public void runClient(final String[] args) throws Exception {
* ('::' for existing connections and '??' for missing connections) to standard out.
* This is sufficient for the single row FIB-SEM stacks with the same number of tiles in each layer.
* It won't work for many other cases.
*
* Since the primary goal of the client is to demonstrate how to pull tile and match data from render,
* it has been left in its current less-than-ideal state.
*
Expand All @@ -185,7 +184,7 @@ void printConnections()

final List<Double> zValues = zToSectionIdMap.keySet().stream().sorted().collect(Collectors.toList());

if (zValues.size() == 0) {
if (zValues.isEmpty()) {
throw new IllegalArgumentException(
"stack " + parameters.stack + " does not contain any layers with the specified z values");
}
Expand All @@ -209,7 +208,8 @@ void printConnections()
null,
true,
false,
false)
false,
false)
.stream()
.map(pair -> {
// Minor Hack: Remove same layer relative position data inserted by
Expand Down Expand Up @@ -245,7 +245,8 @@ void printConnections()
null,
true,
true,
false)
false,
false)
.stream().sorted().collect(Collectors.toList());

for (final OrderedCanvasIdPair pair : crossLayerNeighborPairs) {
Expand Down
Loading

0 comments on commit 1674081

Please sign in to comment.