-
Notifications
You must be signed in to change notification settings - Fork 13
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
Add MaskedSource #607
Draft
tischi
wants to merge
30
commits into
develop
Choose a base branch
from
crop
base: develop
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Add MaskedSource #607
Changes from 11 commits
Commits
Show all changes
30 commits
Select commit
Hold shift + click to select a range
3610c16
Init CroppedViewCommand
tischi 1bdf0cb
Add more code
tischi aac23a4
WIP FunctionRealRandomAccessible...
tischi 4dd15ae
Implement crop
tischi 5163455
Cropping works using mask
tischi cd15862
Make MaskedSource serialisable
tischi 5a70be6
Make masked sources work with manual transformations
tischi cfd8c79
Add crop to source
tischi 1a11971
Remove center parameter
tischi b11c7eb
Get MoBIE instance in Command
tischi 002ce44
Get MoBIE instance in Command
tischi ff0e687
merge
tischi dffc0a3
Add crop to view and UI
tischi 82248e2
WIP replace Resampled Source?|
tischi c2209d2
Successfully create a view for a cropped source
tischi fc12d68
Minor fix
tischi 38f6968
Implement proper bounding box for crop
tischi 60e8720
Improve MaskedSource
tischi baecaba
Improve...
tischi 2909d94
merge develop
tischi edabbdf
Add option to center and rectify the crop
tischi bd2646d
new crop spec
tischi eeb028a
something
tischi ee0f128
Refactor
tischi 997615a
Merge branch 'develop' into crop
tischi da2e157
Make BigWarp work better
tischi 7b97128
Put back stuff that was actually working
tischi 2450e79
Refactor
tischi c976040
Add MoBIEViewerTransformAdjuster
tischi de90930
Refactor
tischi File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
176 changes: 176 additions & 0 deletions
176
src/main/java/org/embl/mobie/viewer/bdv/BdvBoundingBoxDialog.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,176 @@ | ||
/*- | ||
* #%L | ||
* Fiji plugin for inspection and processing of big image data | ||
* %% | ||
* Copyright (C) 2018 - 2021 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.viewer.bdv; | ||
|
||
import bdv.tools.boundingbox.BoxSelectionOptions; | ||
import bdv.tools.boundingbox.TransformedRealBoxSelectionDialog; | ||
import bdv.util.Affine3DHelpers; | ||
import bdv.util.Bdv; | ||
import bdv.util.BdvFunctions; | ||
import bdv.util.BdvHandle; | ||
import bdv.viewer.SourceAndConverter; | ||
import net.imglib2.FinalInterval; | ||
import net.imglib2.FinalRealInterval; | ||
import net.imglib2.Interval; | ||
import net.imglib2.RealInterval; | ||
import net.imglib2.realtransform.AffineTransform3D; | ||
import net.imglib2.realtransform.Scale3D; | ||
import net.imglib2.util.Intervals; | ||
|
||
import java.util.List; | ||
|
||
public class BdvBoundingBoxDialog | ||
{ | ||
private BdvHandle bdvHandle; | ||
private final List< SourceAndConverter > sourceAndConverters; | ||
|
||
private FinalRealInterval initialInterval; | ||
private FinalRealInterval rangeInterval; | ||
private RealInterval interval; | ||
private int minTimepoint; | ||
private int maxTimepoint; | ||
private AffineTransform3D boxTransform; | ||
private TransformedRealBoxSelectionDialog.Result result; | ||
|
||
public BdvBoundingBoxDialog( BdvHandle bdvHandle, List< SourceAndConverter > sourceAndConverters ) | ||
{ | ||
this.bdvHandle = bdvHandle; | ||
this.sourceAndConverters = sourceAndConverters; | ||
|
||
// viewer transform: physical to screen (0,0,w,h) | ||
this.boxTransform = bdvHandle.getViewerPanel().state().getViewerTransform(); | ||
|
||
// physical to screen with (-w/2,-h/2,w/2,h/2) | ||
boxTransform.translate( -0.5 * bdvHandle.getViewerPanel().getDisplay().getWidth(), -0.5 * bdvHandle.getViewerPanel().getDisplay().getHeight(), 0 ); | ||
|
||
// remove bdv window scale from transform | ||
// note that the scale of the viewer transform is uniform in 3-D | ||
// thus we can just pick either width or height | ||
final double scale = 1.0 / bdvHandle.getViewerPanel().getDisplay().getWidth(); | ||
final Scale3D scale3D = new Scale3D( scale, scale, scale ); | ||
boxTransform.preConcatenate( scale3D ); | ||
|
||
// inverse: box to physical | ||
boxTransform = boxTransform.inverse(); | ||
|
||
// check that it is correct (just for debugging) | ||
final double[] center = { 0, 0, 0 }; | ||
final double[] left = { -0.5, -0.5, -0.5 }; | ||
final double[] right = { 0.5, 0.5, 0.5 }; | ||
final double[] physicalLeft = { 0, 0, 0 }; | ||
final double[] physicalRight = { 0, 0, 0 }; | ||
final double[] physicalCenter = { 0, 0, 0 }; | ||
boxTransform.apply( left, physicalLeft ); | ||
boxTransform.apply( right, physicalRight ); | ||
boxTransform.apply( center, physicalCenter ); | ||
} | ||
|
||
public void showDialog() | ||
{ | ||
setInitialSelectionAndRange(); | ||
result = showRealBox( boxTransform ); | ||
} | ||
|
||
public TransformedRealBoxSelectionDialog.Result getResult() | ||
{ | ||
return result; | ||
} | ||
|
||
private TransformedRealBoxSelectionDialog.Result showRealBox( AffineTransform3D boxTransform ) | ||
{ | ||
return BdvFunctions.selectRealBox( | ||
bdvHandle, | ||
boxTransform, | ||
initialInterval, | ||
rangeInterval, | ||
BoxSelectionOptions.options() | ||
.title( "Crop" ) | ||
.initialTimepointRange( bdvHandle.getViewerPanel().state().getCurrentTimepoint(), bdvHandle.getViewerPanel().state().getCurrentTimepoint() ) | ||
.selectTimepointRange( 0, bdvHandle.getViewerPanel().state().getNumTimepoints() - 1 ) | ||
); | ||
} | ||
|
||
private void setInitialSelectionAndRange( ) | ||
{ | ||
final FinalRealInterval viewerBoundingInterval = getViewerGlobalBoundingInterval( bdvHandle ); | ||
|
||
double[] initialCenter = new double[ 3 ]; | ||
double[] initialSize = new double[ 3 ]; | ||
|
||
for (int d = 0; d < 3; d++) | ||
{ | ||
initialCenter[ d ] = ( viewerBoundingInterval.realMax( d ) + viewerBoundingInterval.realMin( d ) ) / 2.0; | ||
initialSize[ d ] = ( viewerBoundingInterval.realMax( d ) - viewerBoundingInterval.realMin( d ) ); | ||
} | ||
|
||
initialSize[ 2 ] = 10.0; | ||
|
||
double[] minInitial = new double[ 3 ]; | ||
double[] maxInitial = new double[ 3 ]; | ||
double[] minRange = new double[ 3 ]; | ||
double[] maxRange = new double[ 3 ]; | ||
|
||
for ( int d = 0; d < 3; d++ ) | ||
{ | ||
minInitial[ d ] = initialCenter[ d ] - initialSize[ d ] / 4; | ||
maxInitial[ d ] = initialCenter[ d ] + initialSize[ d ] / 4; | ||
minRange[ d ] = initialCenter[ d ] - initialSize[ d ] / 2; | ||
maxRange[ d ] = initialCenter[ d ] + initialSize[ d ] / 2; | ||
} | ||
|
||
// initialInterval = Intervals.createMinMax( | ||
// (long) minInitial[0], (long) minInitial[1], (long) minInitial[2], | ||
// (long) maxInitial[0], (long) maxInitial[1], (long) maxInitial[2]); | ||
|
||
// rangeInterval = Intervals.createMinMax( | ||
// (long) minRange[0], (long) minRange[1], (long) minRange[2], | ||
// (long) maxRange[0], (long) maxRange[1], (long) maxRange[2]); | ||
|
||
initialInterval = new FinalRealInterval( | ||
new double[]{-0.25,-0.25,-0.25}, | ||
new double[]{+0.25,+0.25,+0.25}); | ||
rangeInterval = new FinalRealInterval( | ||
new double[]{-0.5,-0.5,-0.5}, | ||
new double[]{+0.5,+0.5,+0.5}); | ||
} | ||
|
||
private static FinalRealInterval getViewerGlobalBoundingInterval( Bdv bdv ) | ||
{ | ||
AffineTransform3D viewerTransform = new AffineTransform3D(); | ||
bdv.getBdvHandle().getViewerPanel().state().getViewerTransform( viewerTransform ); | ||
viewerTransform = viewerTransform.inverse(); | ||
final long[] min = new long[ 3 ]; | ||
final long[] max = new long[ 3 ]; | ||
max[ 0 ] = bdv.getBdvHandle().getViewerPanel().getWidth(); | ||
max[ 1 ] = bdv.getBdvHandle().getViewerPanel().getHeight(); | ||
final FinalRealInterval realInterval | ||
= viewerTransform.estimateBounds( new FinalInterval( min, max ) ); | ||
return realInterval; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
105 changes: 105 additions & 0 deletions
105
src/main/java/org/embl/mobie/viewer/command/CropSourcesCommand.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
package org.embl.mobie.viewer.command; | ||
|
||
import bdv.tools.boundingbox.TransformedRealBoxSelectionDialog; | ||
import bdv.tools.transformation.TransformedSource; | ||
import bdv.util.BdvFunctions; | ||
import bdv.util.BdvHandle; | ||
import bdv.util.BdvOptions; | ||
import bdv.viewer.SourceAndConverter; | ||
import net.imagej.patcher.LegacyInjector; | ||
import net.imglib2.RealInterval; | ||
import net.imglib2.realtransform.AffineTransform3D; | ||
import org.embl.mobie.viewer.MoBIE; | ||
import org.embl.mobie.viewer.bdv.BdvBoundingBoxDialog; | ||
import org.embl.mobie.viewer.playground.SourceAffineTransformer; | ||
import org.embl.mobie.viewer.transform.MaskedSource; | ||
import org.scijava.plugin.Parameter; | ||
import org.scijava.plugin.Plugin; | ||
import sc.fiji.bdvpg.scijava.command.BdvPlaygroundActionCommand; | ||
import sc.fiji.bdvpg.sourceandconverter.SourceAndConverterHelper; | ||
|
||
import java.util.Arrays; | ||
import java.util.HashMap; | ||
import java.util.List; | ||
import java.util.stream.Collectors; | ||
|
||
@Plugin(type = BdvPlaygroundActionCommand.class, menuPath = CommandConstants.CONTEXT_MENU_ITEMS_ROOT + CropSourcesCommand.NAME ) | ||
public class CropSourcesCommand implements BdvPlaygroundActionCommand | ||
{ | ||
static{ LegacyInjector.preinit(); } | ||
|
||
public static final String NAME = "Crop Source(s)"; | ||
|
||
@Parameter( label = "Bdv" ) | ||
BdvHandle bdvHandle; | ||
|
||
@Parameter( label = "Source(s)" ) | ||
public SourceAndConverter[] sourceAndConverterArray; | ||
|
||
@Parameter( label = "Suffix" ) | ||
public String suffix = "_crop"; | ||
|
||
@Parameter( label = "Add to current view" ) | ||
public boolean addToCurrentView = true; | ||
|
||
@Override | ||
public void run() | ||
{ | ||
final List< SourceAndConverter > sourceAndConverters = Arrays.stream( sourceAndConverterArray ).collect( Collectors.toList() ); | ||
if ( sourceAndConverters.size() == 0 ) return; | ||
|
||
new Thread( () -> { | ||
final BdvBoundingBoxDialog boxDialog = new BdvBoundingBoxDialog( bdvHandle, sourceAndConverters ); | ||
boxDialog.showDialog(); | ||
final TransformedRealBoxSelectionDialog.Result result = boxDialog.getResult(); | ||
if ( ! result.isValid() ) return; | ||
final RealInterval maskInterval = result.getInterval(); | ||
final AffineTransform3D maskTransform = new AffineTransform3D(); | ||
result.getTransform( maskTransform ); | ||
|
||
for ( SourceAndConverter sourceAndConverter : sourceAndConverters ) | ||
{ | ||
final SourceAndConverter cropSource = cropSource( maskInterval, maskTransform, sourceAndConverter ); | ||
|
||
// TODO: can we create a view for this? | ||
final MoBIE moBIE = MoBIE.getInstance( bdvHandle ); | ||
moBIE.getViewManager(); // .... | ||
|
||
if ( addToCurrentView ) | ||
{ | ||
// TODO: how to do this properly? | ||
BdvFunctions.show( cropSource, BdvOptions.options().addTo( bdvHandle ) ); | ||
} | ||
|
||
// TODO: Add to UI (maybe simply to same UI group as the input source) | ||
|
||
|
||
} | ||
}).start(); | ||
} | ||
|
||
private SourceAndConverter cropSource( RealInterval maskInterval, AffineTransform3D maskTransform, SourceAndConverter sourceAndConverter ) | ||
{ | ||
final MaskedSource maskedSource = new MaskedSource<>( sourceAndConverter.getSpimSource(), sourceAndConverter.getSpimSource().getName() + suffix, maskInterval.minAsDoubleArray(), maskInterval.maxAsDoubleArray(), maskTransform ); | ||
|
||
final MaskedSource volatileMaskedSource = new MaskedSource<>( sourceAndConverter.asVolatile().getSpimSource(), sourceAndConverter.getSpimSource().getName() + suffix, maskInterval.minAsDoubleArray(), maskInterval.maxAsDoubleArray(), maskTransform ); | ||
|
||
final SourceAndConverter maskedSourceAndConverter = new SourceAndConverter( maskedSource, SourceAndConverterHelper.cloneConverter( sourceAndConverter.getConverter(), sourceAndConverter ), new SourceAndConverter( volatileMaskedSource, SourceAndConverterHelper.cloneConverter( sourceAndConverter.asVolatile().getConverter(), sourceAndConverter.asVolatile() ) ) ); | ||
|
||
// Wrap into TransformedSource for, e.g., manual transformation | ||
final SourceAndConverter sourceOut = new SourceAffineTransformer( maskedSourceAndConverter, new AffineTransform3D() ).getSourceOut(); | ||
return sourceOut; | ||
} | ||
|
||
private HashMap< SourceAndConverter< ? >, AffineTransform3D > fetchTransforms( List< SourceAndConverter< ? > > sourceAndConverters ) | ||
{ | ||
final HashMap< SourceAndConverter< ? >, AffineTransform3D > sacToTransform = new HashMap<>(); | ||
for ( SourceAndConverter movingSac : sourceAndConverters ) | ||
{ | ||
final AffineTransform3D fixedTransform = new AffineTransform3D(); | ||
( ( TransformedSource ) movingSac.getSpimSource()).getFixedTransform( fixedTransform ); | ||
sacToTransform.put( movingSac, fixedTransform ); | ||
} | ||
return sacToTransform; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@K-Meech Do you have experience here and could help? The point is to somehow create and register a new
view
for thecropSource
(actually this is aMaskedSource
, need to change names later, maybe).There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you would need to create the relevant
SourceTransformer
by getting the min/max of the crop etc from the Source. Then somehow add it to the thecurrentSourceTransformers
in theViewManager
. Then, when you save the current settings as a view, it will be made into a view when this function is called: https://github.com/mobie/mobie-viewer-fiji/blob/develop/src/main/java/org/embl/mobie/viewer/view/ViewManager.java#L208