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

Label spots systematically docs #73

Merged
merged 8 commits into from
Dec 10, 2024
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,19 @@ place.

#### Systematically label spots (extern-intern)

* Menu Location: `Plugins > Spots management > Rename spots > Systematically label spots (extern-intern)`
* Derives the name of child cells from the name of the parent by appending a "1" or a "2" to the parent cell name.
* The child cell further away from the center landmark gets "1" appended.
* The child cell closer to the center landmark gets "2" appended.
* The command is useful for systematically labeling cells in a lineage tree.
* The renaming can be restricted to
* Selected spots
* Spots with a certain tag
* Spots that are yet labeled with a number only (indicating that they were automatically detected and not yet
manually labeled)
* Spots whose names end with "1" or "2" (indicating that they were labeled with this command before)
* Example: ![systematically_label_spots.gif](doc/spotsmanagement/systematically_label_spots.gif)

## Tags

### Locate tags
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public class LabelSpotsSystematicallyDialog extends JDialog
private final JButton actionButton;

private LabelSpotsSystematicallyDialog( ProjectModel appModel ) {
super(( Frame ) null, "Sort Lineage Tree", false);
super( ( Frame ) null, "Label spots systematically", false );
setResizable( false );
this.appModel = appModel;
this.centerLandmark = new SelectSpotsComponent( appModel );
Expand Down Expand Up @@ -121,6 +121,11 @@ private void renameButtonClicked()
try
{
Collection<Spot> center = centerLandmark.getSelectedSpots();
if ( center.isEmpty() )
{
dispose();
return;
}
Collection<Spot> selected = selectSpots.getSelectedSpots();
LabelSpotsSystematically.setLabelsBasedOnExternIntern( graph, center, selected, renameUnnamed, renameLabelsEndingWith1Or2 );
model.setUndoPoint();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,13 @@

import org.mastodon.mamut.model.ModelGraph;
import org.mastodon.mamut.model.Spot;
import org.mastodon.mamut.tomancak.sort_tree.SortTreeUtils;

import java.util.Collection;
import java.util.List;
import java.util.function.Predicate;

import net.imglib2.util.LinAlgHelpers;

/**
* Returns true, if and only if, the first child of the given spot is further
* away from the "center landmark" than the second child.
Expand All @@ -59,9 +60,9 @@ public boolean test( Spot spot )
{
if(spot.outgoingEdges().size() != 2)
return true;
double[] devisionDirection = SortTreeUtils.directionOfCellDevision( graph, spot );
double[] divisionDirection = SortTreeUtils.directionOfCellDivision( graph, spot );
double[] centerPosition = centerPositions.get( spot.getTimepoint() );
double[] centerDirection = SortTreeUtils.subtract( spot.positionAsDoubleArray(), centerPosition );
return SortTreeUtils.scalarProduct( devisionDirection, centerDirection ) < 0;
return LinAlgHelpers.dot( divisionDirection, centerDirection ) < 0;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
import java.util.List;
import java.util.function.Predicate;

import net.imglib2.util.LinAlgHelpers;

public class LeftRightOrder implements Predicate<Spot>
{

Expand All @@ -56,8 +58,8 @@ public boolean test( Spot spot )
{
if (spot.outgoingEdges().size() != 2)
return true;
double[] divisionDirection = SortTreeUtils.directionOfCellDevision( graph, spot );
double[] divisionDirection = SortTreeUtils.directionOfCellDivision( graph, spot );
double[] sortingDirection = directions.get( spot.getTimepoint() );
return SortTreeUtils.scalarProduct( sortingDirection, divisionDirection) >= 0;
return LinAlgHelpers.dot( sortingDirection, divisionDirection ) >= 0;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

import org.mastodon.collection.RefSet;
import org.mastodon.collection.ref.RefSetImp;
import org.mastodon.graph.algorithm.RootFinder;
import org.mastodon.mamut.ProjectModel;
import org.mastodon.mamut.model.Link;
import org.mastodon.mamut.model.Model;
Expand Down Expand Up @@ -156,10 +157,7 @@ private void addSubdividedLineageMenu( JPopupMenu popupMenu, List<Spot> roots )
map.put( key, new ArrayList<>() );
for(Spot root : roots) {
Character character = root.getLabel().charAt( 0 );
if(map.containsKey( character ))
map.get( character ).add( root );
else
other.add( root );
map.getOrDefault( character, other ).add( root );
}
map.forEach( (key, list) -> addLineageSubMenu( popupMenu, "\"" + key + "...\"", list ) );
addLineageSubMenu( popupMenu, "\"A-Z...\"", other );
Expand All @@ -184,15 +182,7 @@ private JMenuItem createLineageMenuItem( Spot root )

private List<Spot> getRoots()
{
ModelGraph graph = mastodonModel.getGraph();
List<Spot> roots = new ArrayList<>();
for ( Spot spot : graph.vertices() )
if ( spot.incomingEdges().size() == 0 )
{
Spot ref = graph.vertexRef().refTo( spot );
roots.add( ref );
}
return roots;
return new ArrayList<>( RootFinder.getRoots( mastodonModel.getGraph() ) );
}

private JMenu createTagSetMenu( TagSetStructure.TagSet tagSet )
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public class SortTreeUtils
/**
* If {@code spot} is a {@link Spot} that divides at timepoint
* {@code t = spot.getTimepoint}. Then the cell division direction
* returned by {@link #directionOfCellDevision} is sampled not at
* returned by {@link #directionOfCellDivision} is sampled not at
* timepoint {@code t} but at a timepoint {@code s}. With
* {@code s = t + DIVISION_DIRECTION_TIME_OFFSET}.
*/
Expand All @@ -62,7 +62,7 @@ public class SortTreeUtils
* three time points. And returns the vector from the first daughter cell
* to the second daughter cell.
*/
public static double[] directionOfCellDevision( ModelGraph graph, Spot spot )
public static double[] directionOfCellDivision( ModelGraph graph, Spot spot )
{
if(spot.outgoingEdges().size() != 2)
return new double[]{ 0, 0, 0 };
Expand Down Expand Up @@ -110,15 +110,6 @@ private static double[] averageStartingPosition( ModelGraph graph, int count, Sp
}
}

public static double scalarProduct( double[] a, double[] b )
{
assert a.length == b.length;
double sum = 0;
for ( int i = 0; i < a.length; i++ )
sum += a[ i ] * b[ i ];
return sum;
}

static List<double[]> subtract( List<double[]> a, List<double[]> b )
{
final int n = a.size();
Expand Down Expand Up @@ -152,8 +143,8 @@ public static void divide( double[] average, int size )
}

/**
* Given a collection of {@link Spot spots}, this the average position of
* the spots for each time point. The position is interpolated (or
* Given a collection of {@link Spot spots}, this method computes the average position of
* the spots at each time point. The position is interpolated (or
* extrapolated), if there is a time point with no given cell.
*/
public static List<double[]> calculateAndInterpolateAveragePosition( int numTimePoint, Collection<Spot> spots )
Expand Down Expand Up @@ -292,7 +283,7 @@ public static int getNumberOfTimePoints( ModelGraph graph )
*/
public static double angle( double[] directionA, double[] directionB )
{
double cos = scalarProduct( directionA, directionB ) / LinAlgHelpers.length( directionA ) / LinAlgHelpers.length( directionB );
double cos = LinAlgHelpers.dot( directionA, directionB ) / LinAlgHelpers.length( directionA ) / LinAlgHelpers.length( directionB );
return Math.acos( cos );
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
* By doing so it figures out which spots need to be flipped in order
* to match the TrackSchemes of both lineages.
*
* @see SortTreeUtils#directionOfCellDevision(ModelGraph, Spot)
* @see SortTreeUtils#directionOfCellDivision(ModelGraph, Spot)
*/
public class SpatialTrackMatchingAlgorithm
{
Expand Down Expand Up @@ -164,8 +164,8 @@ private void matchTree( Spot rootA, Spot rootB )
dividingB.outgoingEdges().size() == 2;
if ( !bothDivide )
return;
double[] directionA = SortTreeUtils.directionOfCellDevision( graphA, dividingA );
double[] directionB = SortTreeUtils.directionOfCellDevision( graphB, dividingB );
double[] directionA = SortTreeUtils.directionOfCellDivision( graphA, dividingA );
double[] directionB = SortTreeUtils.directionOfCellDivision( graphB, dividingB );
AffineTransform3D transformAB = noOffsetTransform( spatialRegistration.getTransformationAtoB(
dividingA.getTimepoint() + TIME_OFFSET, dividingB.getTimepoint() + TIME_OFFSET ) );
transformAB.apply( directionA, directionA );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@
public class SortTreeUtilsTest
{
@Test
public void testDirectionOfCellDevision() {
public void testDirectionOfCellDivision()
{
// setup
ModelGraph graph = new ModelGraph();
Spot spot = graph.addVertex().init( 0, array(2, 2, 2), 0.5 );
Expand All @@ -52,13 +53,14 @@ public void testDirectionOfCellDevision() {
graph.addEdge( spot, a ).init();
graph.addEdge( spot, b ).init();
// process
double[] direction = SortTreeUtils.directionOfCellDevision( graph, spot );
double[] direction = SortTreeUtils.directionOfCellDivision( graph, spot );
// test
assertArrayEquals(array(2, 0, 0), direction, 0.0);
}

@Test
public void testDirectionOfCellDevision2() {
public void testDirectionOfCellDivision2()
{
// setup
ModelGraph graph = new ModelGraph();
Spot spot = graph.addVertex().init( 0, array(2, 2, 2), 0.5 );
Expand All @@ -79,7 +81,7 @@ public void testDirectionOfCellDevision2() {
graph.addEdge( b2, b3_1 ).init();
graph.addEdge( b2, b3_2 ).init();
// process
double[] direction = SortTreeUtils.directionOfCellDevision( graph, spot );
double[] direction = SortTreeUtils.directionOfCellDivision( graph, spot );
// test
assertArrayEquals(array(0.5, 0, 0), direction, 0.0);

Expand Down
Loading