Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Registration of Two Lineages #10

Merged
merged 38 commits into from
Mar 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
299fe30
Add coding style
maarzt Feb 7, 2023
ad15427
Add a plugin for lineage registration based on spindle directions
maarzt Jun 15, 2022
99974b7
LineageRegistrationAlgorithm: add getMapping() method
maarzt Jan 24, 2023
96e16b2
Refactor EstimateTransform & reduce dependencies
maarzt Feb 13, 2023
f0b4149
Rename RootsPairing.pairRoots
maarzt Feb 13, 2023
9258efc
Improve and fix LineageRegistrationDialog
maarzt Feb 13, 2023
ca09963
Change LineageTreeUtils.getBranchEnd to not allocation memory
maarzt Feb 14, 2023
a50b0a6
Change test methods to meet reviewers comments
maarzt Feb 10, 2023
2ad057e
Add and improve javadoc
maarzt Feb 14, 2023
eee66e5
Make the LineageRegistrationPlugin an independent MamutPlugin
maarzt Feb 14, 2023
2a9ae00
LineageRegistrationDialog: allow selection of two open Mastodon projects
maarzt Feb 15, 2023
14d654b
Add functionality for the coloring of lineages
maarzt Feb 15, 2023
310b881
Extract method to sort TrackScheme from LineageRegistrationAlgorithm
maarzt Feb 16, 2023
bb00599
Add buttons for tagging unmatched and flipped branches
maarzt Feb 15, 2023
2e7be5f
Implement tagging of unmatched and flipped branches
maarzt Feb 22, 2023
742c109
Allow to copy tag set from one mastodon project to a registered project
maarzt Feb 20, 2023
f660888
Add code that allows to couple the focused spot etc. of two MastodonA…
maarzt Feb 20, 2023
d321f80
Add buttons to the LineageRegistrationDialog that allow to couple the…
maarzt Feb 21, 2023
a844f5b
LineageRegistrationAlgorithm: make run method public
maarzt Feb 22, 2023
0b59966
Introduce class TagSetUtils
maarzt Feb 22, 2023
1dc9b20
Remove LineageTreeUtils.getBranchEnd in favor of BranchGraphUtils.get…
maarzt Feb 22, 2023
291f73e
LineageRegistrationAlgorithmTest: extract tests for LineageRegistrati…
maarzt Feb 22, 2023
1769601
Acquire locks and set undo points for operations on the ModelGraph an…
maarzt Feb 23, 2023
271dbf9
Update the description text in the lineage registration dialog
maarzt Feb 23, 2023
4b08f00
Remove the incomplete "improve window titles" functionality
maarzt Feb 23, 2023
03a9186
Improve the names of created tag sets in LineageRegistrationUtils
maarzt Feb 28, 2023
c2a1c62
LineageRegistrationDialog: add tool tip texts to the buttons
maarzt Feb 28, 2023
3097071
LineageRegistrationDialog: use the lock icon for the sync group buttons
maarzt Feb 28, 2023
39ec173
LineageRegistrationDialog: only enable buttons if two projects are se…
maarzt Feb 28, 2023
5cce342
LineageRegistrationPlugin: rename the menu entry
maarzt Feb 28, 2023
7fb432d
LineageRegistration: add javadoc
maarzt Feb 28, 2023
6cabc68
LineageRegistrationControlService: bring dialog to the front when req…
maarzt Mar 7, 2023
6fd49cc
LineageRegistrationDialog: let it extend JFrame instead of JDialog
maarzt Mar 7, 2023
04dd5ce
LineageRegistrationFrame: Improve tool tip text
maarzt Mar 7, 2023
8c723bf
LineageRegistration: update BranchGraph after sorting the TrackScheme
maarzt Mar 7, 2023
0e406cd
LineageRegistrationPlugin: change which cells are tagges as flipped.
maarzt Mar 12, 2023
4dcd974
LineageResgistration: add a log window to give the user more feedback
maarzt Mar 13, 2023
38d6faa
RefMapUtils: update TODO comment
maarzt Mar 13, 2023
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
399 changes: 399 additions & 0 deletions mastodon-coding-style.xml

Large diffs are not rendered by default.

21 changes: 20 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@
<groupId>org.scijava</groupId>
<artifactId>ui-behaviour</artifactId>
</dependency>
<dependency>
<groupId>mpicbg</groupId>
<artifactId>mpicbg</artifactId>
maarzt marked this conversation as resolved.
Show resolved Hide resolved
</dependency>

<!-- Test dependencies -->
<dependency>
Expand Down Expand Up @@ -80,7 +84,7 @@
<license.organizationName>Mastodon authors</license.organizationName>
<license.copyrightOwners>Tobias Pietzsch</license.copyrightOwners>

<mastodon.version>1.0.0-beta-26</mastodon.version>
<mastodon.version>1.0.0-beta-27-SNAPSHOT</mastodon.version>

<!-- NB: Deploy releases to the SciJava Maven repository. -->
<releaseProfiles>sign,deploy-to-scijava</releaseProfiles>
Expand Down Expand Up @@ -111,4 +115,19 @@
<url>https://maven.scijava.org/content/groups/public</url>
</repository>
</repositories>

<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>net.revelc.code.formatter</groupId>
<artifactId>formatter-maven-plugin</artifactId>
<version>${formatter-maven-plugin.version}</version>
<configuration>
<configFile>mastodon-coding-style.xml</configFile>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ public class TomancakPlugins extends AbstractContextual implements MamutPlugin
private static final String COMPACT_LINEAGE_VIEW = "[tomancak] show compact lineage";
private static final String SORT_TREE = "[tomancak] sort lineage tree";
private static final String SORT_TREE_EXTERN_INTERN = "[tomancak] sort lineage tree extern intern";

private static final String LABEL_SPOTS_SYSTEMATICALLY = "[tomancak] label spots systematically";
private static final String REMOVE_SOLISTS_SPOTS = "[tomancak] remove solists spots";
private static final String EXPORTS_LINEAGE_LENGTHS = "[tomancak] export lineage lengths";
Expand All @@ -93,6 +94,7 @@ public class TomancakPlugins extends AbstractContextual implements MamutPlugin
private static final String[] COMPACT_LINEAGE_VIEW_KEYS = { "not mapped" };
private static final String[] SORT_TREE_KEYS = { "ctrl S" };
private static final String[] SORT_TREE_EXTERN_INTERN_KEYS = { "not mapped" };

private static final String[] LABEL_SPOTS_SYSTEMATICALLY_KEYS = { "not mapped" };
private static final String[] REMOVE_SOLISTS_SPOTS_KEYS = { "not mapped" };
private static final String[] EXPORTS_LINEAGE_LENGTHS_KEYS = { "not mapped" };
Expand All @@ -112,8 +114,8 @@ public class TomancakPlugins extends AbstractContextual implements MamutPlugin
menuTexts.put( CHANGE_BRANCH_LABELS, "Change Branch's Labels");
menuTexts.put( COMPACT_LINEAGE_VIEW, "Show Compact Lineage" );
menuTexts.put( SORT_TREE, "Sort Lineage Tree" );
menuTexts.put( SORT_TREE_EXTERN_INTERN, "Sort Lineage Tree, Extern-Intern");
menuTexts.put( LABEL_SPOTS_SYSTEMATICALLY, "Systematically Label Spots, Extern-Intern" );
menuTexts.put( SORT_TREE_EXTERN_INTERN, "Sort Lineage Tree (Extern-Intern)" );
menuTexts.put( LABEL_SPOTS_SYSTEMATICALLY, "Systematically Label Spots (Extern-Intern)" );
menuTexts.put( REMOVE_SOLISTS_SPOTS, "Remove Spots Solists" );
menuTexts.put( EXPORTS_LINEAGE_LENGTHS, "Export Lineage Lengths" );
menuTexts.put( EXPORTS_SPOTS_COUNTS, "Export Spots Counts" );
Expand Down Expand Up @@ -228,7 +230,7 @@ public List< ViewMenuBuilder.MenuItem > getMenuItems()
item( FLIP_DESCENDANTS ),
item( SORT_TREE ),
item( SORT_TREE_EXTERN_INTERN ),
item( LABEL_SPOTS_SYSTEMATICALLY )),
item( LABEL_SPOTS_SYSTEMATICALLY ) ),
menu( "Exports",
item( EXPORTS_LINEAGE_LENGTHS ),
item( EXPORTS_SPOTS_COUNTS ),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
/*-
* #%L
* A Mastodon plugin data allows to show the embryo in Blender.
* %%
* Copyright (C) 2022 - 2023 Matthias Arzt
* %%
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* #L%
*/
package org.mastodon.mamut.tomancak.lineage_registration;

import net.imglib2.util.Pair;
import net.imglib2.util.ValuePair;

import org.mastodon.collection.RefList;
import org.mastodon.collection.RefSet;
import org.mastodon.collection.ref.RefArrayList;
import org.mastodon.collection.ref.RefSetImp;
import org.mastodon.mamut.model.Link;
import org.mastodon.mamut.model.ModelGraph;
import org.mastodon.mamut.model.Spot;

public class BranchGraphUtils
{
private BranchGraphUtils()
{
// prevent instantiation
}

public static Spot getBranchStart( Spot spot, Spot ref )
{
Spot s = spot;
while ( s.incomingEdges().size() == 1 )
{
Link edge = s.incomingEdges().iterator().next();
s = edge.getSource( ref );
if ( s.outgoingEdges().size() != 1 )
return edge.getTarget( ref );
}
return s;
}

public static Spot getBranchEnd( Spot spot, Spot ref )
{
Spot s = spot;
while ( s.outgoingEdges().size() == 1 )
{
Link edge = s.outgoingEdges().iterator().next();
s = edge.getTarget( ref );
if ( s.incomingEdges().size() != 1 )
return edge.getSource( ref );
}
return s;
}

static Spot findVertexForTimePoint( Spot branchStart, int timePoint, Spot ref )
{
Spot spot = branchStart;
if ( spot.getTimepoint() >= timePoint )
return spot;
while ( spot.outgoingEdges().size() == 1 )
{
spot = spot.outgoingEdges().iterator().next().getTarget( ref );
if ( spot.getTimepoint() >= timePoint )
return spot;
}
return spot;
}

static Pair< RefList< Spot >, RefList< Link > > getBranchSpotsAndLinks( ModelGraph graph, Spot branchStart )
{
RefList< Link > links = new RefArrayList<>( graph.edges().getRefPool() );
RefList< Spot > spots = new RefArrayList<>( graph.vertices().getRefPool() );
spots.add( branchStart );
Spot ref = graph.vertexRef();
Spot spot = branchStart;
while ( spot.outgoingEdges().size() == 1 )
{
Link link = spot.outgoingEdges().iterator().next();
spot = link.getTarget( ref );
if ( spot.incomingEdges().size() != 1 )
break;
links.add( link );
spots.add( spot );
}
graph.releaseRef( ref );
return new ValuePair<>( spots, links );
}

static RefSet< Spot > getAllBranchStarts( ModelGraph graph )
{
Spot ref = graph.vertexRef();
try
{
RefSet< Spot > set = new RefSetImp<>( graph.vertices().getRefPool() );
for ( Spot spot : graph.vertices() )
{
if ( spot.incomingEdges().size() != 1 )
set.add( spot );
if ( spot.outgoingEdges().size() > 1 )
for ( Link link : spot.outgoingEdges() )
set.add( link.getTarget( ref ) );
}
return set;
}
finally
{
graph.releaseRef( ref );
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.mastodon.mamut.tomancak.lineage_registration;

/**
* Similar to {@link AutoCloseable}, but without the checked exception.
*/
interface ClosableLock extends AutoCloseable
{
void close();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package org.mastodon.mamut.tomancak.lineage_registration;

import java.awt.Component;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;

import javax.swing.JOptionPane;

import net.imglib2.util.Cast;

public class ComboBoxDialog
{

public static < T > T showComboBoxDialog( Component parent, String title, String message, List< T > options,
Function< T, String > toString )
{
Choice[] choices = options.stream()
.map( option -> new Choice( toString.apply( option ), option ) )
.toArray( Choice[]::new );
Choice choice = ( Choice ) JOptionPane.showInputDialog( parent, message, title,
JOptionPane.QUESTION_MESSAGE, null, choices, choices[ 0 ] );
return choice != null ? Cast.unchecked( choice.getValue() ) : null;
}

private static class Choice
{
private final String name;

private final Object value;

public Choice( String name, Object value )
{
this.name = name;
this.value = value;
}

public Object getValue()
{
return value;
}

@Override
public String toString()
{
return name;
}
}

public static void main( String... args )
{
// NB: Small demo method
List< String > options = Arrays.asList( "a", "b", "c" );
String choice = showComboBoxDialog( null, "title", "message", options, a -> "choose: " + a );
System.out.println( choice );
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package org.mastodon.mamut.tomancak.lineage_registration;

import java.util.ArrayList;
import java.util.List;

import mpicbg.models.IllDefinedDataPointsException;
import mpicbg.models.NotEnoughDataPointsException;
import mpicbg.models.Point;
import mpicbg.models.PointMatch;
import mpicbg.models.SimilarityModel3D;

import net.imglib2.realtransform.AffineTransform3D;

import org.mastodon.collection.RefRefMap;
import org.mastodon.mamut.model.Spot;

/**
* This class holds a function for estimating a 3d rigid transformation
* between two sets of points.
*/
class EstimateTransformation
{

private EstimateTransformation()
{
// prevent instantiation
}

/**
* <p>
* @return a 3d rigid transform (that is composed of scaling, rotation and translation).
* The returned transformation is the optimal transformation, that when applied on the "key" spots
* of the given "pairs" map minimizes the distance to the "value" spots.
* </p>
* <p>
* See "Closed-form solution of absolute orientation using unit quaternions",
* Horn, B. K. P., Journal of the Optical Society of America A, Vol. 4, page 629, April 1987
* </p>
* @param pairs A map that serves as a list of pairs of spots. Each pair consists of a "key" spot
* and a "value" spot. The algorithm only uses the coordinates of the spots, all other
* properties are ignored.
* @see SimilarityModel3D
*/
public static AffineTransform3D estimateScaleRotationAndTranslation( RefRefMap< Spot, Spot > pairs )
{
// NB: This method is not as memory efficient as it could be.
// It creates multiple objects (Point, PointMatch, arrays) per item in "pairs".
// Memory efficiency should be improved if performance problems arise.
Spot refB = pairs.createValueRef();
try
{
List< PointMatch > matches = new ArrayList<>( pairs.size() );
for ( Spot spotA : pairs.keySet() )
{
Spot spotB = pairs.get( spotA );
Point pointA = new Point( spotA.positionAsDoubleArray() );
Point pointB = new Point( spotB.positionAsDoubleArray() );
matches.add( new PointMatch( pointA, pointB, 1 ) );
}
return fitTransform( matches );
}
finally
{
pairs.releaseValueRef( refB );
}
}

private static AffineTransform3D fitTransform( List< PointMatch > matches )
{
try
{
SimilarityModel3D model = new SimilarityModel3D();
model.fit( matches );
maarzt marked this conversation as resolved.
Show resolved Hide resolved
AffineTransform3D transform = new AffineTransform3D();
transform.set( model.getMatrix( null ) );
return transform;
}
catch ( NotEnoughDataPointsException | IllDefinedDataPointsException e )
{
throw new RuntimeException( e );
}
}
}
Loading