All Downloads are FREE. Search and download functionalities are using the official Maven repository.

SIMcheck.Rec_SAMismatch Maven / Gradle / Ivy

Go to download

ImageJ plugin suite for super-resolution structured illumination microscopy data quality control.

There is a newer version: 1.3
Show newest version
/*                                                                              
 *  Copyright (c) 2015, Graeme Ball and Micron Oxford,                          
 *  University of Oxford, Department of Biochemistry.                           
 *                                                                               
 *  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.                                          
 *                                                                               
 *  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/ .         
 */ 

package SIMcheck;
import java.awt.Color;

import ij.*;
import ij.plugin.PlugIn;
import ij.gui.Plot;
import ij.process.*;

/** This plugin takes reconstructed data and produces produces plots of
 * slice minimum and average feature intensity, as well as summarising standard
 * deviation of the minimum to diagnose refractive index mismatch between
 * the sample and PSF.
 * @author Graeme Ball 
 */
public class Rec_SAMismatch implements PlugIn, Executable {
    
    public static final String name = "Spherical Aberration Mismatch";
    public static final String TLA = "SAM";
    private ResultSet results = new ResultSet(name, TLA);
    
    public void run(String arg) {
        ImagePlus imp = IJ.getImage();
        exec(imp);
        results.report();
    }

    /** Execute plugin functionality: plot slice minimum and feature mean
     * scaled to stack mode as zero point, and report stdDev of minima. 
     * @param imps reconstructed data ImagePlus should be first imp
     * @return ResultSet containing plots of mnimum and mean variation 
     */
     public ResultSet exec(ImagePlus... imps) {  
        IJ.showStatus(name + "...");
        int nc = imps[0].getNChannels();
        ImagePlus[] plots = new ImagePlus[nc];
        for (int c = 1; c <= nc; c++) {
            ImagePlus imp2 = singleChannel(imps[0], c);
            StackStatistics stackStats = new StackStatistics(imp2);
            int nz = imp2.getNSlices();
            // build arrays of stats per Z plane
            double[] sliceMinima = new double[nz];
            double[] sliceMeans = new double[nz];
            double[] zPlanes = new double[nz];
            double plotMax = stackStats.min;
            double plotMin = stackStats.max;
            // commented out normalization to mode -- may add back in as option
//            double stackMode = stackStats.dmode;
            double stackMode = 0.0d;
            for (int z = 0; z < nz; z++) {
                zPlanes[z] = z + 1;  // Z value for the plot (x-axis)
                imp2.setSlice(z + 1);
                ImageProcessor ip = imp2.getProcessor();
                ImageStatistics stats = ip.getStatistics();
                ImageStatistics featStats = I1l.featStats(ip);
                // normalize all statistics to stack mode (not!) as 0 point
                double nmin = stats.min - stackMode;
                double nmean = featStats.mean - stackMode;
                sliceMinima[z] = nmin;
                sliceMeans[z] = nmean; 
                if (nmin < plotMin) {
                    plotMin = nmin;
                }
                if (nmean > plotMax) {
                    plotMax = nmean;
                }
                if (nmean < plotMin) {
                    plotMin = nmean;
                }
            }
            Plot plot = new Plot(
                    "Reconstructed normalized min variation, C" + c,
                    "Z-section", "Intensity");
            // display 20% beyond min and max
            plotMin -= 0.2 * Math.abs(plotMin);
            plotMax += 0.2 * Math.abs(plotMax);
            plot.setLimits(1.0d, (double)nz, plotMin, plotMax);
            plot.setLineWidth(2);
            plot.setColor(Color.BLACK);
            plot.addPoints(zPlanes, sliceMinima, Plot.LINE);
            plot.setColor(Color.LIGHT_GRAY);
            plot.addPoints(zPlanes, sliceMeans, Plot.LINE);
            plot.setLineWidth(1);
            ImagePlus impPlot = plot.getImagePlus();
            I1l.drawPlotTitle(impPlot, "Reconstructed data intensity profile"
                    + " (feature mean=gray, z-minimum=black)");
            plots[c - 1] = impPlot;
            double nstdev = Math.sqrt(J.variance(sliceMinima)) / 
                    J.mean(sliceMeans);
            results.addStat("C" + c + " Z-minimum variation", nstdev,
                    checkZmv(nstdev));  // FIXME, StatOK);
            
        }
        String title = I1l.makeTitle(imps[0], TLA);
        ImagePlus impAllPlots = I1l.mergeChannels(title, plots);
        impAllPlots.setDimensions(nc, 1, 1);
        impAllPlots.setOpenAsHyperStack(true);
        results.addImp("Z-section minimum (black) and mean feature intensity (gray)",
                impAllPlots);
        results.addInfo("How to interpret", "Z-minimum variation (ZMV)"
                + " is calculated as the"
                + " standard deviation of z-section minimum intensity"
                + " normalized to the average feature intensity. High ZMV"
                + " indicates spherical aberration mismatch between sample"
                + " and optical transfer function used for the reconstruction."
                + " Typically this is seen as dip in the minimum intensity"
                + " plot at the sample boundary. Note, that the absolute value"
                + " depends on image content.");
        return results;
    }
     
     /** Is ZMV value acceptable? */
     private static ResultSet.StatOK checkZmv(Double statValue) {
         if (statValue < 0.3) {
             return ResultSet.StatOK.YES;
         } else if (statValue < 1.0) {
             return ResultSet.StatOK.MAYBE;
         } else {
             return ResultSet.StatOK.NO;
         }
     }

    /**  Return a new ImagePlus containing a single channel of the input. */
    private ImagePlus singleChannel(ImagePlus imp, int channel) {
        int stackSize = imp.getStackSize();
        int channels = imp.getNChannels();
        ImageStack nuStack = new ImageStack(imp.getWidth(),imp.getHeight());
        for (int s = 1; s <= stackSize; s++) {
            if (((s % channels) == channel) || 
                    ((channel == channels) && ((s % channels) == 0))) {
                nuStack.addSlice(imp.getStack().getProcessor(s));
            }
        }
        String nuTitle = imp.getShortTitle() + "_Ch" + Integer.toString(channel);
        ImagePlus imp2 = new ImagePlus(nuTitle, nuStack);
        imp2.setDimensions(1, imp.getNSlices(), imp.getNFrames());  // 1 channel
        return imp2;
    }
    
    /** Interactive test method */
    public static void main(String[] args) {
        new ImageJ();
        TestData.recon.show();
        IJ.runPlugIn(Rec_SAMismatch.class.getName(), "");
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy