/*-
* #%L
* Fiji distribution of ImageJ for the life sciences.
* %%
* Copyright (C) 2007 - 2017 Fiji developers.
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-2.0.html>.
* #L%
*/
package spim.process.fusion.boundingbox;
import ij.gui.GenericDialog;
import java.awt.Label;
import java.awt.TextField;
import java.awt.event.TextEvent;
import java.awt.event.TextListener;
import java.util.List;
import java.util.Vector;
import mpicbg.spim.data.sequence.Channel;
import mpicbg.spim.data.sequence.TimePoint;
import mpicbg.spim.data.sequence.ViewId;
import spim.fiji.plugin.fusion.Fusion;
import spim.fiji.plugin.util.GUIHelper;
import spim.fiji.spimdata.SpimData2;
import spim.process.fusion.boundingbox.automatic.MinFilterThreshold;
import spim.process.fusion.export.ImgExport;
public class AutomaticBoundingBox extends BoundingBoxGUI
{
public static int defaultTimepointIndex = 0;
public static int defaultChannelIndex = 0;
public static int defaultDownsamplingAutomatic = 4;
public static double defaultBackgroundIntensity = 5;
public static int defaultDiscardedObjectSize = 25;
public static boolean defaultLoadSequentially = true;
public static boolean defaultDisplaySegmentationImage = false;
public AutomaticBoundingBox( final SpimData2 spimData, final List< ViewId > viewIdsToProcess )
{
super( spimData, viewIdsToProcess );
}
@Override
public boolean queryParameters( final Fusion fusion, final ImgExport imgExport )
{
// first get an idea of the maximal bounding box
final double[] minBB = new double[ 3 ];
final double[] maxBB = new double[ 3 ];
BoundingBoxGUI.computeMaxBoundingBoxDimensions( spimData, viewIdsToProcess, minBB, maxBB );
// compute dimensions and update size for this instance
final long[] dim = new long[ maxBB.length ];
// first time called on this object
if ( this.min == null || this.max == null )
{
this.min = new int[ minBB.length ];
this.max = new int[ minBB.length ];
}
for ( int d = 0; d < dim.length; ++d )
{
this.min[ d ] = (int)Math.round( minBB[ d ] );
this.max[ d ] = (int)Math.round( maxBB[ d ] );
dim[ d ] = this.max[ d ] - this.min[ d ] + 1;
}
final GenericDialog gd = new GenericDialog( "Automatically define Bounding Box" );
final List< TimePoint > timepointsToProcess = SpimData2.getAllTimePointsSorted( spimData, viewIdsToProcess );
final List< Channel > channelsToProcess = SpimData2.getAllChannelsSorted( spimData, viewIdsToProcess );
final String[] timepoints = assembleTimepoints( timepointsToProcess );
final String[] channels = assembleChannels( channelsToProcess );
if ( defaultTimepointIndex >= timepoints.length )
defaultTimepointIndex = 0;
if ( defaultChannelIndex >= channels.length )
defaultChannelIndex = 0;
gd.addMessage( "Parameters for automatic segmentation", GUIHelper.largestatusfont );
gd.addChoice( "Timepoint", timepoints, timepoints[ defaultTimepointIndex ] );
gd.addChoice( "Channel", channels, channels[ defaultChannelIndex ] );
gd.addSlider( "Background intensity [%]", 1.0, 99.0, defaultBackgroundIntensity );
gd.addSlider( "Size_of_objects to be discarded", 1, 100, defaultDiscardedObjectSize );
gd.addMessage( "" );
gd.addSlider( "Downsampling", 1.0, 10.0, defaultDownsamplingAutomatic );
gd.addCheckbox( "Load_input_images sequentially", defaultLoadSequentially );
gd.addCheckbox( "Display_image_used for segmentation", defaultDisplaySegmentationImage );
gd.addMessage( "Image size: ???x???x??? pixels", GUIHelper.mediumstatusfont, GUIHelper.good );
Label l = (Label)gd.getMessage();
// add listeners and update values
addListeners( gd, gd.getNumericFields(), l, dim );
gd.showDialog();
if ( gd.wasCanceled() )
return false;
final TimePoint timepoint = timepointsToProcess.get( defaultTimepointIndex = gd.getNextChoiceIndex() );
final Channel channel = channelsToProcess.get( defaultChannelIndex = gd.getNextChoiceIndex() );
final double background = defaultBackgroundIntensity = gd.getNextNumber();
final int discardedObjectSize = defaultDiscardedObjectSize = (int)Math.round( gd.getNextNumber() );
this.downsampling = defaultDownsamplingAutomatic = (int)Math.round( gd.getNextNumber() );
final boolean loadSequentially = defaultLoadSequentially = gd.getNextBoolean();
final boolean displaySegmentationImage = defaultDisplaySegmentationImage = gd.getNextBoolean();
// compute approx bounding box
final MinFilterThreshold automatic = new MinFilterThreshold(
spimData,
viewIdsToProcess,
channel,
timepoint,
this,
background,
discardedObjectSize,
loadSequentially,
displaySegmentationImage );
if ( !automatic.run() )
{
return false;
}
else
{
this.min = automatic.getMin().clone();
this.max = automatic.getMax().clone();
BoundingBoxGUI.defaultMin = automatic.getMin().clone();
BoundingBoxGUI.defaultMax = automatic.getMax().clone();
}
return super.queryParameters( fusion, imgExport );
}
protected String[] assembleTimepoints( final List< TimePoint > timepoints )
{
final String[] t = new String[ timepoints.size() ];
for ( int i = 0; i < timepoints.size(); ++i )
t[ i ] = timepoints.get( i ).getName();
return t;
}
protected String[] assembleChannels( final List< Channel > channels )
{
final String[] c = new String[ channels.size() ];
for ( int i = 0; i < channels.size(); ++i )
c[ i ] = channels.get( i ).getName();
return c;
}
protected void addListeners(
final GenericDialog gd,
final Vector<?> tf,
final Label label,
final long[] dim )
{
final TextField downsample = (TextField)tf.get( 2 );
downsample.addTextListener(
new TextListener()
{
@Override
public void textValueChanged(TextEvent arg0)
{
int downsampling = Integer.parseInt( downsample.getText() );
final long numPixels = numPixels( dim, downsampling );
final long megabytes = (numPixels * 4) / (1024*1024);
label.setText( "Image size for segmentation: " +
(dim[ 0 ])/downsampling + " x " +
(dim[ 1 ])/downsampling + " x " +
(dim[ 2 ])/downsampling + " pixels, " + megabytes + " MB" );
label.setForeground( GUIHelper.good );
}
} );
}
protected static long numPixels( final long[] dim, final int downsampling )
{
long numpixels = 1;
for ( int d = 0; d < dim.length; ++d )
numpixels *= (dim[ d ])/downsampling;
return numpixels;
}
@Override
public AutomaticBoundingBox newInstance( final SpimData2 spimData, final List< ViewId > viewIdsToProcess )
{
return new AutomaticBoundingBox( spimData, viewIdsToProcess );
}
@Override
public String getDescription()
{
return "Estimate automatically (experimental)";
}
}