Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
4f745f9
add convertTileIdToUseWafers6061RenderOrder method
trautmane Jul 31, 2026
70239e1
move MaskHackClient from mask package to tile package
trautmane Jul 31, 2026
e8ccb4d
add TileIdHackClient
trautmane Aug 3, 2026
c2f3033
add excludeDifferentMfovNeighbors parameter for match tile pair deriv…
trautmane Aug 3, 2026
c3115a3
move most ThomasCalibrationIntensityCorrectionClient parameters into …
trautmane Aug 3, 2026
7c2ca70
add toString method to CreepCorrectionParameters
trautmane Aug 3, 2026
8b0a2ff
add toString method to BeamCorrectionParameters
trautmane Aug 3, 2026
bbcd239
first draft of BeamCorrectionSparkClient
trautmane Aug 4, 2026
0538794
modify ThomasCalibrationIntensityCorrectionClient to support reading …
trautmane Aug 4, 2026
09b24b3
rename ThomasCalibrationIntensityCorrectionClient to BeamCorrectionCl…
trautmane Aug 4, 2026
5906b35
add 'other' pipeline stackId naming group and use it for TileIdHackCl…
trautmane Aug 4, 2026
09dc583
test tile pairs with excludeDifferentMfovNeighbors true
trautmane Aug 4, 2026
569f19e
add overwriteSourceStack parameter to BeamCorrectionParameters
trautmane Aug 4, 2026
687900f
switch BeamCorrectionSparkClient and TileIdHackClient back to rawNami…
trautmane Aug 4, 2026
e31c625
switch TileIdHackClient back to rawNamingGroup
trautmane Aug 5, 2026
0c3e128
improve list-match-collections.sh output
trautmane Aug 5, 2026
2e8a4cc
replace skipMatchCorrection parameter for creep correction with match…
trautmane Aug 6, 2026
f5d698d
add OVERWRITE_SOURCE_AND_RENAME_AS_TARGET matchCorrectionType
trautmane Aug 6, 2026
6989d58
remove duplicated step 1 paragraph in javadoc
trautmane Aug 6, 2026
6631383
add rawNamingGroup check to CreepCorrectionSparkClient
trautmane Aug 6, 2026
0a945b0
change MFOV_AS_TILE naming group from raw to other
trautmane Aug 6, 2026
931c5ac
change MFOV_AS_TILE naming group from raw to other
trautmane Aug 6, 2026
e38b135
remove unused affine alignment setup from MFOVAsTileClient
trautmane Aug 6, 2026
0b53d2b
rename MFOVASTileClient as MFOVAsTileClient
trautmane Aug 6, 2026
d7be26c
add removeMatchPairsWithDifferentMFOVs method
trautmane Aug 7, 2026
37372f7
fix canvas groupId bug
trautmane Aug 7, 2026
a80113a
add deriveSfovMatchData to MFOVAsTileParameters
trautmane Aug 9, 2026
e1effd3
add applyOffsets method to Matches
trautmane Aug 10, 2026
7b7e29b
add changeMatchesToWorldCoordinates method and change removeMatchPair…
trautmane Aug 10, 2026
84b40ec
Update the MFOV pre-alignment step to read matches from render's web …
trautmane Aug 10, 2026
fd054ed
first draft of the MatchCollectionRenameClient
trautmane Aug 10, 2026
805defa
rename owner as matchCollectionOwner to keep parameter name and attri…
trautmane Aug 10, 2026
79af524
Treat resinMfovStartPositionMatchWeight as unspecified if it is negat…
trautmane Aug 10, 2026
b99c798
fix expectedTileClusterCount for MFOV montage match patching when iso…
trautmane Aug 11, 2026
46149f5
remove unneeded writeable directory checks for Google Cloud storage t…
trautmane Aug 12, 2026
24118a6
increase stack serial number range
trautmane Aug 17, 2026
716b173
add load-rough-align-data.sh script
trautmane Aug 17, 2026
a0e142e
debug w61 mfov-as-tile match connection issues
trautmane Aug 17, 2026
163b3be
fix exception message logic
trautmane Aug 17, 2026
13f5d05
add comment to explain coding choice
trautmane Aug 17, 2026
ae18977
Merge remote-tracking branch 'origin/feature/thomas-intensity-changes…
trautmane Aug 17, 2026
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
13 changes: 13 additions & 0 deletions render-app/src/main/java/org/janelia/alignment/match/Matches.java
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,19 @@ public ArrayList<PointMatch> createPointMatches() {
return matches;
}

public void applyOffsets(final double pxOffset,
final double pyOffset,
final double qxOffset,
final double qyOffset) {
// NOTE: point coordinates are stored by dimension, so p[0] holds all x values and p[1] holds all y values
for (int i = 0; i < w.length; ++i) {
p[0][i] += pxOffset;
p[1][i] += pyOffset;
q[0][i] += qxOffset;
q[1][i] += qyOffset;
}
}

// NOTE: Convenience getter methods for derived data should be excluded from the JSON model - hence the JsonIgnore annotation.
// Newer Jackson versions (e.g. 2.9.6) fail to parse RealPoint with an IllegalArgumentException:
// Conflicting setter definitions for property "position": net.imglib2.RealPoint#setPosition(1 params) vs net.imglib2.RealPoint#setPosition(1 params)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,12 @@ public class TilePairDerivationParameters implements Serializable {
arity = 1)
public boolean excludeSameMfovNeighbors = false;

@Parameter(
names = "--excludeDifferentMfovNeighbors",
description = "Exclude neighbor tiles in the same layer (z) with a different MFOV from the source tile",
arity = 1)
public boolean excludeDifferentMfovNeighbors = 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
Expand Up @@ -263,6 +263,36 @@ public static boolean isSimpleMFOVName(final String name) {
/** Each MFOV has 91 SFOVs or tiles */
public static int NUMBER_OF_TILES_IN_MFOV = 91;

/**
* @return the specified tileId with its render order updated
* (e.g.'w60_magc0399_scan005_m0013_r42_s09' for 'w60_magc0399_scan005_m0013_r37_s09')
*/
public static String convertTileIdToUseWafers6061RenderOrder(final String tileId) {
final String sfovString = getSFOVIndexForTileId(tileId); // "09" for "w60_magc0399_scan005_m0013_r37_s09"
final int i = Integer.parseInt(sfovString.trim()) - 1; // 8 for "09"
final String renderOrderString = WAFERS_60_61_RENDER_ORDER_STRINGS[i]; // "r42_" for 8
return tileId.substring(0, 27) + renderOrderString + sfovString;
}

/**
* Thomas' optimal SFOV render order for wafers 60 and 61 that was copied from
* <a href="https://github.com/JaneliaSciComp/EM_recon_pipeline/blob/multisem/src/python/janelia_emrp/msem/render_sfov_order.py#L24-L35">
* render_sfov_order.py
* </a>.
*/
private static final String[] WAFERS_60_61_RENDER_ORDER_STRINGS = {
"r57_s", "r50_s", "r46_s", "r51_s", "r60_s", "r65_s", "r59_s", "r47_s", "r42_s", "r36_s",
"r43_s", "r48_s", "r54_s", "r56_s", "r69_s", "r76_s", "r72_s", "r68_s", "r55_s", "r44_s",
"r37_s", "r31_s", "r24_s", "r32_s", "r38_s", "r18_s", "r25_s", "r33_s", "r39_s", "r64_s",
"r71_s", "r83_s", "r79_s", "r75_s", "r70_s", "r63_s", "r52_s", "r34_s", "r26_s", "r19_s",
"r12_s", "r07_s", "r20_s", "r27_s", "r13_s", "r08_s", "r14_s", "r21_s", "r28_s", "r35_s",
"r45_s", "r67_s", "r78_s", "r86_s", "r88_s", "r85_s", "r82_s", "r77_s", "r66_s", "r58_s",
"r49_s", "r29_s", "r22_s", "r15_s", "r09_s", "r03_s", "r01_s", "r04_s", "r16_s", "r10_s",
"r05_s", "r02_s", "r06_s", "r11_s", "r17_s", "r23_s", "r30_s", "r40_s", "r62_s", "r74_s",
"r81_s", "r90_s", "r91_s", "r89_s", "r87_s", "r84_s", "r80_s", "r73_s", "r61_s", "r53_s",
"r41_s"
};

private static final Pattern SIMPLE_MFOV_NAME_PATTERN = Pattern.compile("^m(\\d{4})$");

private static final Logger LOG = LoggerFactory.getLogger(MultiSemUtilities.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,63 @@ public void normalize(final Integer maxZDistance,
this.matchPairs = normalizedMatchPairs;
}

/**
* Remove any match pairs where the pTile and/or the qTile do not exist in this collection's resolvedTileSpecs.
*/
public void removeMatchPairsThatReferenceTilesOutsideThisCollection() {

final Set<CanvasMatches> updatedMatchPairs = new HashSet<>(matchPairs.size());

for (final CanvasMatches pair : matchPairs) {
if (resolvedTileSpecs.hasTileSpec(pair.getpId()) &&
resolvedTileSpecs.hasTileSpec(pair.getqId())) {
updatedMatchPairs.add(pair);
}
}

// pairs from web service are not sorted, so sort here to make usage loops more intuitive
this.matchPairs = updatedMatchPairs.stream().sorted().collect(Collectors.toList());
}

/**
* Change all match points to world coordinates using tile min x and y as offset.
*
* @throws IllegalStateException
* if any match pair identifies a tile spec that is missing from this collection.
*/
public void changeMatchesToWorldCoordinates()
throws IllegalStateException {

for (final CanvasMatches pair : matchPairs) {

final TileSpec pTileSpec = resolvedTileSpecs.getTileSpec(pair.getpId());
final TileSpec qTileSpec = resolvedTileSpecs.getTileSpec(pair.getqId());

if ((pTileSpec != null) && (qTileSpec != null)) {

pair.getMatches().applyOffsets(pTileSpec.getMinX(),
pTileSpec.getMinY(),
qTileSpec.getMinX(),
qTileSpec.getMinY());

} else {

final StringBuilder sb = new StringBuilder();
if (qTileSpec == null) {
if (pTileSpec == null) {
sb.append("s ").append(pair.getpId()).append(" and ");
}
sb.append(" ").append(pair.getqId());
} else {
sb.append(" ").append(pair.getpId());
}
throw new IllegalStateException("missing tile" + sb + " for match pair " + pair.toKeyString());

}
}

}

public static ResolvedTileSpecsWithMatchPairs fromJson(final Reader json) {
return JSON_HELPER.fromJson(json);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,8 @@ public Set<OrderedCanvasIdPair> getCircleNeighbors(final List<TileBounds> source
final boolean excludeCornerNeighbors,
final boolean excludeSameLayerNeighbors,
final boolean excludeSameSectionNeighbors,
final boolean excludeSameMfovNeighbors) {
final boolean excludeSameMfovNeighbors,
final boolean excludeDifferentMfovNeighbors) {

String firstTileId = null;
if (! sourceTileBoundsList.isEmpty()) {
Expand Down Expand Up @@ -258,15 +259,17 @@ public Set<OrderedCanvasIdPair> getCircleNeighbors(final List<TileBounds> source

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

for (final TileBoundsRTree neighborTree : neighborTrees) {
searchResults = neighborTree.findTilesInCircle(circle);
neighborTileIdPairs.addAll(
getDistinctPairs(tileBounds, searchResults,
excludeCornerNeighbors, excludeSameSectionNeighbors, excludeSameMfovNeighbors,
excludeCornerNeighbors, excludeSameSectionNeighbors,
excludeSameMfovNeighbors, excludeDifferentMfovNeighbors,
false));
}
}
Expand Down Expand Up @@ -310,10 +313,11 @@ public static Set<OrderedCanvasIdPair> getDistinctPairs(final TileBounds fromTil
final boolean excludeCornerNeighbors,
final boolean excludeSameSectionNeighbors,
final boolean excludeSameMfovNeighbors,
final boolean excludeDifferentMfovNeighbors,
final boolean includeRelativePosition) {
final Set<OrderedCanvasIdPair> pairs = new HashSet<>(toTiles.size() * 2);
final String pTileId = fromTile.getTileId();
final String pMfov = excludeSameMfovNeighbors ? MultiSemUtilities.getMagcMfovForTileId(pTileId) : null;
final String pMfov = (excludeSameMfovNeighbors || excludeDifferentMfovNeighbors) ? MultiSemUtilities.getMagcMfovForTileId(pTileId) : null;

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

// note: only execute multi-SEM string extraction and comparison code if flag indicates it is needed
if (excludeSameMfovNeighbors && (pMfov.equals(MultiSemUtilities.getMagcMfovForTileId(qTileId)))) {
continue;
} else if (excludeDifferentMfovNeighbors && (! pMfov.equals(MultiSemUtilities.getMagcMfovForTileId(qTileId)))) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For readability, consider declaring final boolean isSameMfov = pMfov.equals(MultiSemUtilities.getMagcMfovForTileId(qTileId)).

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree adding isSameMfov would improve readability, but because this spot in the code is heavily used for FIB-SEM data sets I prefer to save time (for the FIBSEM data sets) by not doing the multi-SEM string conversion and comparison unless the parameters indicate this is a multi-SEM stack.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a comment to explain this in the code

continue;
}

final OrderedCanvasIdPair pair;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,22 @@ public class PipelineStackIdNamingGroups
private final StackIdNamingGroup raw;
private final StackIdNamingGroup aligned;
private final StackIdNamingGroup intensityCorrected;
private final StackIdNamingGroup other;

/** No-arg constructor required for JSON deserialization. */
@SuppressWarnings("unused")
private PipelineStackIdNamingGroups() {
this(null, null, null);
this(null, null, null, null);
}

public PipelineStackIdNamingGroups(final StackIdNamingGroup raw,
final StackIdNamingGroup aligned,
final StackIdNamingGroup intensityCorrected) {
final StackIdNamingGroup intensityCorrected,
final StackIdNamingGroup other) {
this.raw = raw;
this.aligned = aligned;
this.intensityCorrected = intensityCorrected;
this.other = other;
}

public StackIdNamingGroup getRaw() {
Expand All @@ -39,4 +42,9 @@ public StackIdNamingGroup getAligned() {
public StackIdNamingGroup getIntensityCorrected() {
return intensityCorrected;
}

public StackIdNamingGroup getOther() {
return other;
}

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

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

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

final Set<OrderedCanvasIdPair> expectedPairs = new TreeSet<>();
Expand Down Expand Up @@ -197,6 +200,7 @@ public void testGetCanvasIdPairs() {
false,
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,
Expand All @@ -208,6 +212,7 @@ public void testGetCanvasIdPairs() {
true,
false,
false,
false,
true);
Assert.assertEquals("incorrect number of combinations (without corner neighbors) in " + pairs,
expectedNumberOfCombinations, pairs.size());
Expand Down Expand Up @@ -236,6 +241,7 @@ public void testGetDifferentMFovCanvasIdPairs() {
false,
false,
true,
false,
false);
Assert.assertEquals("incorrect number of combinations in " + pairs,
2, pairs.size());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,7 @@ private List<String> debugPairsForStack(final String stackName)
false,
false,
false,
false,
false);

neighborPairs.addAll(currentNeighborPairs);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ void printConnections()
true,
false,
false,
false,
false)
.stream()
.map(pair -> {
Expand Down Expand Up @@ -246,6 +247,7 @@ void printConnections()
true,
true,
false,
false,
false)
.stream().sorted().collect(Collectors.toList());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,7 @@ private Set<OrderedCanvasIdPair> getSameLayerPairs(final Map<Double, TileBoundsR
true,
false,
false,
false,
false);
sameLayerPairs.addAll(pairs);
});
Expand Down Expand Up @@ -373,6 +374,7 @@ private Set<OrderedCanvasIdPair> getCrossLayerPairs(final Map<Double, TileBounds
false,
true,
false,
false,
false));
}
fromZ = consistentLayerRange.getMaximumDouble();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,8 @@ private void deriveAndSaveSortedNeighborPairsForZValues(final List<Double> sorte
tpdp.excludeCornerNeighbors,
tpdp.excludeSameLayerNeighbors,
tpdp.excludeSameSectionNeighbors,
tpdp.excludeSameMfovNeighbors);
tpdp.excludeSameMfovNeighbors,
tpdp.excludeDifferentMfovNeighbors);

if (tpdp.excludeSameLayerPairsWithPosition != null) {
final MontageRelativePosition excludedPosition = tpdp.excludeSameLayerPairsWithPosition;
Expand Down
Loading