Skip to content

Commit

Permalink
Merge pull request #12 from mastodon-sc/fix-fit-ellipsoid-test
Browse files Browse the repository at this point in the history
Fix fit ellipsoid test
  • Loading branch information
maarzt authored Nov 30, 2023
2 parents 5c98b7e + b273841 commit 4b10c5b
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 22 deletions.
21 changes: 13 additions & 8 deletions src/main/java/org/mastodon/mamut/fitting/FitEllipsoidPlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -126,17 +126,22 @@ public void getCommandDescriptions( final CommandDescriptions descriptions )

private final AbstractNamedAction fitSelectedVerticesAction;

private ProjectModel projectModel;
private MinimalProjectModel minimalProjectModel;

public FitEllipsoidPlugin()
{
fitSelectedVerticesAction = new RunnableAction( FIT_SELECTED_VERTICES, this::fitSelectedVertices );
}

@Override
public void setAppPluginModel( final ProjectModel model )
public void setAppPluginModel( final ProjectModel projectModel )
{
this.projectModel = model;
this.minimalProjectModel = new MinimalProjectModel( projectModel );
}

void setMinimalProjectModel( final MinimalProjectModel minimalProjectModel )
{
this.minimalProjectModel = minimalProjectModel;
}

@Override
Expand Down Expand Up @@ -164,7 +169,7 @@ void fitSelectedVertices()
{
// TODO: parameters to select which source to act on
final int sourceIndex = 0;
final SourceAndConverter< ? > source = projectModel.getSharedBdvData().getSources().get( sourceIndex );
final SourceAndConverter< ? > source = minimalProjectModel.getSharedBdvData().getSources().get( sourceIndex );
if ( !( source.getSpimSource().getType() instanceof RealType ) )
throw new IllegalArgumentException( "Expected RealType image source" );
process( Cast.unchecked( source ) );
Expand All @@ -179,7 +184,7 @@ void fitSelectedVertices()
@SuppressWarnings( "unused" )
private < T extends RealType< T > > void process( final SourceAndConverter< T > source )
{
final RefSet< Spot > vertices = projectModel.getSelectionModel().getSelectedVertices();
final RefSet< Spot > vertices = minimalProjectModel.getSelectionModel().getSelectedVertices();
if ( vertices.isEmpty() )
System.err.println( "no vertex selected" );

Expand All @@ -193,7 +198,7 @@ private < T extends RealType< T > > void process( final SourceAndConverter< T >
final ArrayList< Spot > threadSafeVertices = asArrayList( vertices );
// NB: RefSet is not thread-safe for iteration.
final int totalTasks = vertices.size();
final ReentrantReadWriteLock.WriteLock writeLock = projectModel.getModel().getGraph().getLock().writeLock();
final ReentrantReadWriteLock.WriteLock writeLock = minimalProjectModel.getModel().getGraph().getLock().writeLock();

Parallelization.getTaskExecutor().forEach( threadSafeVertices, spot -> {
// loop over vertices in parallel using multiple threads
Expand Down Expand Up @@ -253,7 +258,7 @@ private < T extends RealType< T > > void process( final SourceAndConverter< T >

// set undo point if at least one spot was fitted
if ( found.get() > 0 )
projectModel.getModel().setUndoPoint();
minimalProjectModel.getModel().setUndoPoint();
}

private static ArrayList< Spot > asArrayList( final RefSet< Spot > vertices )
Expand Down Expand Up @@ -405,7 +410,7 @@ private void showBdvDebugWindow( final SourceAndConverter< ? > source, final dou
{
final BdvStackSource< FloatType > inputSource =
BdvFunctions.show( input, "FloatType input", Bdv.options().sourceTransform( sourceToGlobal ) );
final ConverterSetups setups = projectModel.getSharedBdvData().getConverterSetups();
final ConverterSetups setups = minimalProjectModel.getSharedBdvData().getConverterSetups();
final ConverterSetup cs = setups.getConverterSetup( source );
final Bounds bounds = setups.getBounds().getBounds( cs );
inputSource.setDisplayRange( cs.getDisplayRangeMin(), cs.getDisplayRangeMax() );
Expand Down
53 changes: 53 additions & 0 deletions src/main/java/org/mastodon/mamut/fitting/MinimalProjectModel.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package org.mastodon.mamut.fitting;

import org.mastodon.mamut.ProjectModel;
import org.mastodon.mamut.model.Link;
import org.mastodon.mamut.model.Model;
import org.mastodon.mamut.model.Spot;
import org.mastodon.model.SelectionModel;
import org.mastodon.views.bdv.SharedBigDataViewerData;

/**
* A minimal interface to the data model of a Mastodon project.<p>
* This interface facilities testing of the ellipsoid fitting, since it allows to circumvent the fact that the {@link org.mastodon.mamut.ProjectModel} creates GUI components on instantiation.<p>
* It contains accessor methods to parts of the {@link org.mastodon.mamut.ProjectModel} that are safe to be used in a headless way.
*
* @author Stefan Hahmann
*/
public class MinimalProjectModel
{
private final Model model;

private final SharedBigDataViewerData sharedBdvData;

private final SelectionModel< Spot, Link > selectionModel;

MinimalProjectModel(
final Model model, final SharedBigDataViewerData sharedBdvData, final SelectionModel< Spot, Link > selectionModel
)
{
this.model = model;
this.sharedBdvData = sharedBdvData;
this.selectionModel = selectionModel;
}

public MinimalProjectModel( final ProjectModel projectModel )
{
this( projectModel.getModel(), projectModel.getSharedBdvData(), projectModel.getSelectionModel() );
}

public Model getModel()
{
return model;
}

public SharedBigDataViewerData getSharedBdvData()
{
return sharedBdvData;
}

public SelectionModel< Spot, Link > getSelectionModel()
{
return selectionModel;
}
}
28 changes: 17 additions & 11 deletions src/test/java/org/mastodon/mamut/fitting/ArtificialData.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,11 @@
import org.mastodon.collection.ref.RefObjectHashMap;
import org.mastodon.mamut.ProjectModel;
import org.mastodon.mamut.fitting.ellipsoid.Ellipsoid;
import org.mastodon.mamut.model.Link;
import org.mastodon.mamut.model.Model;
import org.mastodon.mamut.model.Spot;
import org.mastodon.model.DefaultSelectionModel;
import org.mastodon.model.SelectionModel;
import org.mastodon.views.bdv.SharedBigDataViewerData;
import org.scijava.Context;

Expand All @@ -56,7 +59,7 @@
import net.imglib2.view.Views;

/**
* Renders a grid of ellipsoids in 3D, and wraps the result in a {@link MamutAppModel}.
* Renders a grid of ellipsoids in 3D, and wraps the result in a {@link ProjectModel}.
*/
public class ArtificialData
{
Expand All @@ -69,12 +72,15 @@ public class ArtificialData

private final int numberOfSpots = columns * columns * columns;

private final ProjectModel appModel;
private final Context context;

private final MinimalProjectModel minimalProjectModel;

private final RefObjectMap< Spot, Ellipsoid > ellipsoids;

public ArtificialData( final Context context )
{
this.context = context;
final Model model = new Model();
ellipsoids = new RefObjectHashMap<>( model.getGraph().vertices().getRefPool(), numberOfSpots );
final Img< FloatType > image = ArrayImgs.floats( columns * size, columns * size, columns * size );
Expand All @@ -91,8 +97,9 @@ public ArtificialData( final Context context )
ellipsoids.put( spot, ellipsoid );
drawSpot( image, interval, ellipsoid );
}

appModel = wrapAsAppModel( image, model, context );
SharedBigDataViewerData sharedBDVData = asSharedBdvDataXyz( image );
SelectionModel< Spot, Link > selectionModel = new DefaultSelectionModel<>( model.getGraph(), model.getGraphIdBimap() );
minimalProjectModel = new MinimalProjectModel( model, sharedBDVData, selectionModel );
selectAllVerticies();
}

Expand All @@ -112,8 +119,8 @@ private static SharedBigDataViewerData asSharedBdvDataXyz( final Img< FloatType

private void selectAllVerticies()
{
for ( final Spot vertex : appModel.getModel().getGraph().vertices() )
appModel.getSelectionModel().setSelected( vertex, true );
for ( final Spot vertex : minimalProjectModel.getModel().getGraph().vertices() )
minimalProjectModel.getSelectionModel().setSelected( vertex, true );
}

private Ellipsoid randomizedEllipsoid( final double[] center )
Expand Down Expand Up @@ -167,15 +174,14 @@ private static AffineTransform3D transposed( final AffineTransform3D transform )
return r;
}

private static ProjectModel wrapAsAppModel( final Img< FloatType > image, final Model model, final Context context )
public ProjectModel getAppModel()
{
final SharedBigDataViewerData sharedBigDataViewerData = asSharedBdvDataXyz( image );
return ProjectModel.create( context, model, sharedBigDataViewerData, null );
return ProjectModel.create( context, minimalProjectModel.getModel(), minimalProjectModel.getSharedBdvData(), null );
}

public ProjectModel getAppModel()
public MinimalProjectModel getMinimalProjectModel()
{
return appModel;
return minimalProjectModel;
}

public RefObjectMap< Spot, Ellipsoid> getExpectedEllipsoids()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import org.junit.Test;
import org.mastodon.collection.RefObjectMap;
import org.mastodon.mamut.fitting.ellipsoid.Ellipsoid;
import org.mastodon.mamut.model.ModelGraph;
import org.mastodon.mamut.model.Spot;
import org.scijava.Context;

Expand All @@ -56,18 +57,20 @@ public void testFitEllipsoidPlugin() {
final ArtificialData data = new ArtificialData( new Context() );
final StopWatch watch = StopWatch.createAndStart();
final FitEllipsoidPlugin plugin = new FitEllipsoidPlugin();
plugin.setAppPluginModel( data.getAppModel() );
plugin.setMinimalProjectModel( data.getMinimalProjectModel() );
plugin.fitSelectedVertices();
System.out.println( watch );
final int success = countCorrectEllipsoids( data );
assertEquals( "Not all ellipsoids were fitted correctly.", data.getAppModel().getModel().getGraph().vertices().size(), success );
ModelGraph graph = data.getMinimalProjectModel().getModel().getGraph();
assertEquals( "Not all ellipsoids were fitted correctly.", graph.vertices().size(), success );
}

private static int countCorrectEllipsoids( final ArtificialData data )
{
int success = 0;
final RefObjectMap< Spot, Ellipsoid > expectedEllipsoids = data.getExpectedEllipsoids();
for( final Spot spot : data.getAppModel().getModel().getGraph().vertices() ) {
for ( final Spot spot : data.getMinimalProjectModel().getModel().getGraph().vertices() )
{
final Ellipsoid actualEllipsoid = asEllipsoid( spot );
final Ellipsoid expectedEllipsoid = expectedEllipsoids.get( spot );
final boolean equal = isEllipsoidEqual( expectedEllipsoid, actualEllipsoid );
Expand Down

0 comments on commit 4b10c5b

Please sign in to comment.