package gdsc.smlm.ij.plugins;
/*-----------------------------------------------------------------------------
* GDSC SMLM Software
*
* Copyright (C) 2013 Alex Herbert
* Genome Damage and Stability Centre
* University of Sussex, UK
*
* 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 3 of the License, or
* (at your option) any later version.
*---------------------------------------------------------------------------*/
import gdsc.smlm.engine.DataFilter;
import gdsc.smlm.engine.FitEngineConfiguration;
import gdsc.smlm.filters.DataProcessor;
import gdsc.smlm.filters.DifferenceSpotFilter;
import gdsc.smlm.filters.MaximaSpotFilter;
import gdsc.smlm.filters.SingleSpotFilter;
import gdsc.smlm.ij.settings.SettingsManager;
import ij.IJ;
import ij.ImagePlus;
import ij.gui.DialogListener;
import ij.gui.GenericDialog;
import ij.gui.Roi;
import ij.plugin.filter.ExtendedPlugInFilter;
import ij.plugin.filter.PlugInFilterRunner;
import ij.process.FloatProcessor;
import ij.process.ImageProcessor;
import java.awt.AWTEvent;
import java.awt.Rectangle;
/**
* Smooths the selected rectangular ROI using a mean filter.
*/
public class SmoothImage implements ExtendedPlugInFilter, DialogListener
{
private final static String TITLE = "Smooth Image";
private static final String[] filterNames;
private static final DataFilter[] filters;
static
{
filters = DataFilter.values();
filterNames = SettingsManager.getNames((Object[]) filters);
}
private static int filter1 = 0;
private static double smooth1 = 1;
private static boolean differenceFilter = false;
private static int filter2 = 0;
private static double smooth2 = 3;
private int flags = DOES_16 | DOES_8G | DOES_32 | PARALLELIZE_STACKS | FINAL_PROCESSING;
/*
* (non-Javadoc)
*
* @see ij.plugin.filter.PlugInFilter#setup(java.lang.String, ij.ImagePlus)
*/
public int setup(String arg, ImagePlus imp)
{
if (arg.equals("final"))
{
//imp.resetDisplayRange();
imp.updateAndDraw();
return DONE;
}
SMLMUsageTracker.recordPlugin(this.getClass(), arg);
if (imp == null)
{
IJ.noImage();
return DONE;
}
Roi roi = imp.getRoi();
if (roi != null && roi.getType() != Roi.RECTANGLE)
{
IJ.error("Rectangular ROI required");
return DONE;
}
return flags;
}
/*
* (non-Javadoc)
*
* @see ij.plugin.filter.ExtendedPlugInFilter#showDialog(ij.ImagePlus, java.lang.String,
* ij.plugin.filter.PlugInFilterRunner)
*/
public int showDialog(ImagePlus imp, String command, PlugInFilterRunner pfr)
{
// Note: We cannot use a NonBlockinnericDialog as scrolling through the image
// throws away the snap shot. The pixel data for the previous slice is then fixed
// with the preview. So we can only support a single slice.
GenericDialog gd = new GenericDialog(TITLE);
gd.addHelp(About.HELP_URL);
gd.addMessage("Smooth image:");
gd.addChoice("Spot_filter", filterNames, filterNames[filter1]);
gd.addSlider("Smoothing", 0, 4.5, smooth1);
gd.addCheckbox("Difference_filter", differenceFilter);
gd.addChoice("Spot_filter2", filterNames, filterNames[filter2]);
gd.addSlider("Smoothing2", 1.5, 6, smooth2);
gd.addPreviewCheckbox(pfr);
gd.addDialogListener(this);
gd.showDialog();
if (gd.wasCanceled() || !dialogItemChanged(gd, null))
return DONE;
return IJ.setupDialog(imp, flags);
}
/*
* (non-Javadoc)
*
* @see ij.gui.DialogListener#dialogItemChanged(ij.gui.GenericDialog, java.awt.AWTEvent)
*/
public boolean dialogItemChanged(GenericDialog gd, AWTEvent e)
{
filter1 = gd.getNextChoiceIndex();
smooth1 = gd.getNextNumber();
if (differenceFilter = gd.getNextBoolean())
{
filter2 = gd.getNextChoiceIndex();
smooth2 = gd.getNextNumber();
}
return !gd.invalidNumber();
}
/*
* (non-Javadoc)
*
* @see ij.plugin.filter.PlugInFilter#run(ij.process.ImageProcessor)
*/
public void run(ImageProcessor ip)
{
Rectangle bounds = ip.getRoi();
// Crop to the ROI
FloatProcessor fp = ip.crop().toFloat(0, null);
float[] data = (float[]) fp.getPixels();
MaximaSpotFilter filter = createSpotFilter();
int width = fp.getWidth();
int height = fp.getHeight();
data = filter.preprocessData(data, width, height);
//System.out.println(filter.getDescription());
fp = new FloatProcessor(width, height, data);
ip.insert(fp, bounds.x, bounds.y);
//ip.resetMinAndMax();
ip.setMinAndMax(fp.getMin(), fp.getMax());
}
private MaximaSpotFilter createSpotFilter()
{
final int search = 1;
final int border = 0;
DataProcessor processor0 = FitEngineConfiguration.createDataProcessor(border, filters[filter1], smooth1);
if (differenceFilter)
{
DataProcessor processor1 = FitEngineConfiguration.createDataProcessor(border, filters[filter2], smooth2);
return new DifferenceSpotFilter(search, border, processor0, processor1);
}
return new SingleSpotFilter(search, border, processor0);
}
/*
* (non-Javadoc)
*
* @see ij.plugin.filter.ExtendedPlugInFilter#setNPasses(int)
*/
public void setNPasses(int nPasses)
{
// Nothing to do
}
}