Skip to content

Commit

Permalink
Implement Command to set a transformation
Browse files Browse the repository at this point in the history
  • Loading branch information
tischi committed Jan 1, 2024
1 parent f733744 commit 7756015
Show file tree
Hide file tree
Showing 32 changed files with 367 additions and 92 deletions.
4 changes: 2 additions & 2 deletions src/main/java/org/embl/mobie/MoBIE.java
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@
import org.embl.mobie.lib.table.TableDataFormat;
import org.embl.mobie.lib.table.saw.TableOpener;
import org.embl.mobie.lib.transform.GridType;
import org.embl.mobie.lib.ui.UserInterface;
import org.embl.mobie.lib.ui.WindowArrangementHelper;
import org.embl.mobie.ui.UserInterface;
import org.embl.mobie.ui.WindowArrangementHelper;
import org.embl.mobie.lib.view.ViewManager;
import sc.fiji.bdvpg.PlaygroundPrefs;
import sc.fiji.bdvpg.scijava.services.SourceAndConverterService;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import ij.IJ;
import ij.ImagePlus;
import ij.ImageStack;
import ij.process.ImageConverter;
import net.imglib2.realtransform.AffineTransform3D;
import org.embl.mobie.command.CommandConstants;
import org.embl.mobie.lib.MoBIEHelper;
Expand All @@ -52,12 +53,12 @@

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;

@Plugin(type = BdvPlaygroundActionCommand.class, menuPath = CommandConstants.CONTEXT_MENU_ITEMS_ROOT + "Transform>Registration - Automatic")
public class AutomaticRegistrationCommand extends DynamicCommand implements BdvPlaygroundActionCommand, Interactive, Initializable
{

public static final String TRANSLATION = "Translation";
public static final String RIGID = "Rigid";
public static final String SIMILARITY = "Similarity";
Expand All @@ -74,6 +75,9 @@ public class AutomaticRegistrationCommand extends DynamicCommand implements BdvP
@Parameter(label="Registration Voxel Size", persist = false, min = "0.0", style="format:#.00000")
public Double voxelSize = 1D;

@Parameter(label="Out of Bounds Value")
public String outOfBoundsValue = "Do not use";

@Parameter ( label = "Transformation", choices = { TRANSLATION, RIGID, SIMILARITY, AFFINE } )
private String transformationType = TRANSLATION;

Expand Down Expand Up @@ -149,6 +153,15 @@ private void compute()
// create two 2D ImagePlus that are to be aligned
//
ScreenShotMaker screenShotMaker = new ScreenShotMaker( bdvHandle, sacA.getSpimSource().getVoxelDimensions().unit() );
try
{
// useful for images with bright background
// to avoid an edge with the black background of BDV
screenShotMaker.setOutOfBoundsValue( Float.parseFloat( this.outOfBoundsValue ) );
} catch ( Exception e )
{
// don't set an out-of-bounds value.
}
screenShotMaker.run( Arrays.asList( sacA, sacB ), voxelSize );
CompositeImage compositeImage = screenShotMaker.getCompositeImagePlus();
AffineTransform3D canvasToGlobalTransform = screenShotMaker.getCanvasToGlobalTransform();
Expand All @@ -157,12 +170,16 @@ private void compute()
ImagePlus impA = new ImagePlus( imageA + " (fixed)", stack.getProcessor( 1 ) );
ImagePlus impB = new ImagePlus( imageB + " (moving)", stack.getProcessor( 2 ) );

// set the display ranges
// as those will be used by the SIFT for normalising the pixel values
// set the display ranges and burn them in by converting to unit8
// this is important for the intensity based registration methods
compositeImage.setPosition( 1 );
impA.getProcessor().setMinAndMax( compositeImage.getDisplayRangeMin(), compositeImage.getDisplayRangeMax() );
compositeImage.setPosition( 2 );
impB.getProcessor().setMinAndMax( compositeImage.getDisplayRangeMin(), compositeImage.getDisplayRangeMax() );
new ImageConverter( impA ).convertToGray8();
new ImageConverter( impB ).convertToGray8();
double min = impA.getProcessor().getMax();
double max = impA.getProcessor().getMax();

// compute the transformation that aligns the two images in 2D
//
Expand All @@ -178,6 +195,11 @@ else if ( registrationMethod.equals( "TurboReg" ) )
TurboReg2DAligner turboReg2DAligner = new TurboReg2DAligner( impA, impB, transformationType );
turboReg2DAligner.run( showIntermediates );
localRegistration = turboReg2DAligner.getAlignmentTransform();
if ( showIntermediates )
{
impA.show();
impB.show();
}
}

// convert the transformation that aligns the images in 2D
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
/*-
* #%L
* Fiji viewer for MoBIE projects
* %%
* Copyright (C) 2018 - 2023 EMBL
* %%
* 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.embl.mobie.command.context;

import bdv.tools.transformation.TransformedSource;
import bdv.util.BdvHandle;
import bdv.viewer.SourceAndConverter;
import ij.IJ;
import net.imglib2.realtransform.AffineTransform3D;
import org.embl.mobie.command.CommandConstants;
import org.embl.mobie.lib.MoBIEHelper;
import org.embl.mobie.lib.serialize.transformation.AffineTransformation;
import org.scijava.Initializable;
import org.scijava.command.DynamicCommand;
import org.scijava.plugin.Parameter;
import org.scijava.plugin.Plugin;
import org.scijava.widget.Button;
import sc.fiji.bdvpg.scijava.command.BdvPlaygroundActionCommand;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

@Plugin(type = BdvPlaygroundActionCommand.class, menuPath = CommandConstants.CONTEXT_MENU_ITEMS_ROOT + "Transform>Registration - Set Transformation")
public class SetTransformationCommand extends DynamicCommand implements BdvPlaygroundActionCommand, Initializable
{
static { net.imagej.patcher.LegacyInjector.preinit(); }

@Parameter
public BdvHandle bdvHandle;

@Parameter ( label = "Image", choices = {""} )
private String sourceName;

@Parameter ( label = "3D Affine" )
private String transformation = Arrays.toString( new AffineTransform3D().getRowPackedCopy() );
private AffineTransform3D previousTransform;
private TransformedSource< ? > transformedSource;

public enum AdditionMode
{
Concatenate,
Replace;
}

@Parameter ( label = "Addition Mode" )
private AdditionMode mode = AdditionMode.Replace;

@Parameter ( label = "Preview", callback = "apply" )
private Button preview;

private List< SourceAndConverter< ? > > sourceAndConverters;

@Override
public void initialize()
{
sourceAndConverters = MoBIEHelper.getVisibleSacs( bdvHandle );

final List< String > imageNames = sourceAndConverters.stream()
.map( sac -> sac.getSpimSource().getName() )
.collect( Collectors.toList() );

getInfo().getMutableInput( "sourceName", String.class )
.setChoices( imageNames );

}

@Override
public void run()
{
apply();
}

@Override
public void cancel()
{
if ( transformedSource != null )
{
transformedSource.setFixedTransform( previousTransform );
bdvHandle.getViewerPanel().requestRepaint();
}
}

private void apply()
{
double[] doubles = parseStringToDoubleArray( transformation );
AffineTransform3D additionalTransform = new AffineTransform3D();
additionalTransform.set( doubles );

if ( additionalTransform.isIdentity() )
return;

// TODO: the below logic will break when the
// user decides to change the source name
SourceAndConverter< ? > sourceAndConverter = sourceAndConverters.stream()
.filter( sac -> sac.getSpimSource().getName().equals( sourceName ) )
.findFirst().get();

if ( sourceAndConverter.getSpimSource() instanceof TransformedSource )
{
transformedSource = ( TransformedSource< ? > ) sourceAndConverter.getSpimSource();

if ( previousTransform != null )
{
// reset transform to initial state
transformedSource.setFixedTransform( previousTransform );
}
else
{
// remember the previous transform
// such that we can reset it
previousTransform = new AffineTransform3D();
transformedSource.getFixedTransform( previousTransform );
}

if ( mode.equals( AdditionMode.Replace ) )
{
transformedSource.setFixedTransform( additionalTransform );
}
else if ( mode.equals( AdditionMode.Concatenate ) )
{
AffineTransform3D newTransform = previousTransform.copy().preConcatenate( additionalTransform );
transformedSource.setFixedTransform( newTransform );
}

bdvHandle.getViewerPanel().requestRepaint();
}
else
{
IJ.error( "Cannot set the transformation of a " + sourceAndConverter.getSpimSource().getClass() );
}
}

public static double[] parseStringToDoubleArray(String arrayStr) {
arrayStr = arrayStr.replaceAll("[^0-9.,]", "");
String[] items = arrayStr.split(",\\s*");
double[] doubles = Arrays.stream(items).mapToDouble(Double::parseDouble).toArray();
return doubles;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*-
* #%L
* Fiji viewer for MoBIE projects
* %%
* Copyright (C) 2018 - 2023 EMBL
* %%
* 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.embl.mobie.command.context;

import bdv.tools.transformation.TransformedSource;
import bdv.util.BdvHandle;
import bdv.viewer.Source;
import bdv.viewer.SourceAndConverter;
import ij.IJ;
import net.imglib2.realtransform.AffineTransform3D;
import org.embl.mobie.MoBIE;
import org.embl.mobie.command.CommandConstants;
import org.embl.mobie.lib.MoBIEHelper;
import org.embl.mobie.lib.bdv.ScreenShotMaker;
import org.scijava.Initializable;
import org.scijava.command.DynamicCommand;
import org.scijava.module.MutableModuleItem;
import org.scijava.plugin.Parameter;
import org.scijava.plugin.Plugin;
import sc.fiji.bdvpg.bdv.BdvHandleHelper;
import sc.fiji.bdvpg.scijava.command.BdvPlaygroundActionCommand;

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

@Plugin(type = BdvPlaygroundActionCommand.class, menuPath = CommandConstants.CONTEXT_MENU_ITEMS_ROOT + "Log Images Info")
public class SourcesInfoCommand implements BdvPlaygroundActionCommand
{
static { net.imagej.patcher.LegacyInjector.preinit(); }

public static final String CAPTURE_SIZE_PIXELS = "Capture size [pixels]: ";

@Parameter
public BdvHandle bdvHandle;

@Override
public void run()
{
List< SourceAndConverter< ? > > visibleSacs = MoBIEHelper.getVisibleSacs( bdvHandle );
visibleSacs.forEach( sac ->
{
Source< ? > source = sac.getSpimSource();
IJ.log( "# " + source.getName() );
IJ.log( "Number of resolution levels: " + source.getNumMipmapLevels() );
IJ.log( "Voxel size: " + Arrays.toString( source.getVoxelDimensions().dimensionsAsDoubleArray() ) );

if ( source instanceof TransformedSource )
{
AffineTransform3D transform3D = new AffineTransform3D();
( ( TransformedSource<?> ) source ).getFixedTransform( transform3D );
IJ.log( "Additional transform: " + transform3D );
source.getSourceTransform( 0, 0, transform3D );
IJ.log( "Full transform: " + transform3D );
}
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,35 +28,23 @@
*/
package org.embl.mobie.command.open;

import loci.common.DebugTools;
import org.embl.mobie.MoBIE;
import org.embl.mobie.MoBIESettings;
import org.embl.mobie.command.CommandConstants;
import org.embl.mobie.lib.transform.GridType;
import org.scijava.command.Command;
import org.scijava.plugin.Parameter;
import org.scijava.plugin.Plugin;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

@Plugin(type = Command.class, menuPath = CommandConstants.MOBIE_PLUGIN_OPEN + "Open Table (Advanced)..." )
public class OpenTableAdvancedCommand extends OpenTableCommand {

static { net.imagej.patcher.LegacyInjector.preinit(); }

@Parameter( label = "Grid type", choices = {"Stitched", "Transformable"} )
public String gridTypeString = "Transformable" ;
// FIXME: SciJava supports enums now?!
@Parameter( label = "Grid type" )
public GridType gridType = GridType.Transformed;

@Override
public void run()
{
gridType = gridTypeString.equals( "Stitched" ) ? GridType.Stitched : GridType.Transformed;
super.run();
super.run( gridType );
}
}
Loading

0 comments on commit 7756015

Please sign in to comment.