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.ij.plugins.ResultsManager.InputSource; import gdsc.smlm.ij.utils.ObjectAnalyzer; import gdsc.core.ij.Utils; import gdsc.smlm.results.MemoryPeakResults; import gdsc.smlm.results.PeakResult; import ij.IJ; import ij.ImagePlus; import ij.WindowManager; import ij.gui.GenericDialog; import ij.plugin.PlugIn; import ij.process.ByteProcessor; import ij.process.ImageProcessor; import ij.process.ShortProcessor; /** * Splits PeakFit results into separate datasets using an input mask of objects. */ public class SplitResults implements PlugIn { private static final String TITLE = "Split Results"; private static String inputOption = ""; private static String objectMask = ""; private static boolean showObjectMask = false; private static boolean nonMaskDataset = false; /* * (non-Javadoc) * * @see ij.plugin.PlugIn#run(java.lang.String) */ public void run(String arg) { SMLMUsageTracker.recordPlugin(this.getClass(), arg); if (MemoryPeakResults.isMemoryEmpty()) { IJ.error(TITLE, "There are no fitting results in memory"); return; } String[] items = Utils.getImageList(Utils.GREY_8_16); if (items.length == 0) { IJ.error(TITLE, "There are no suitable mask images"); return; } // Show a dialog allowing the results set to be filtered GenericDialog gd = new GenericDialog(TITLE); gd.addMessage("Select a dataset to split"); ResultsManager.addInput(gd, inputOption, InputSource.MEMORY); gd.addChoice("Object_mask", items, objectMask); gd.addCheckbox("Show_object_mask", showObjectMask); gd.addCheckbox("Non_mask_dataset", nonMaskDataset); gd.showDialog(); if (gd.wasCanceled()) return; inputOption = ResultsManager.getInputSource(gd); objectMask = gd.getNextChoice(); showObjectMask = gd.getNextBoolean(); nonMaskDataset = gd.getNextBoolean(); MemoryPeakResults results = ResultsManager.loadInputResults(inputOption, false); if (results == null || results.size() == 0) { IJ.error(TITLE, "No results could be loaded"); return; } ImagePlus imp = WindowManager.getImage(objectMask); if (imp == null) { IJ.error(TITLE, "No object mask could be found"); return; } splitResults(results, imp.getProcessor()); } private void splitResults(MemoryPeakResults results, ImageProcessor ip) { IJ.showStatus("Splitting " + Utils.pleural(results.size(), "result")); // Create an object mask ObjectAnalyzer objectAnalyzer = new ObjectAnalyzer(ip, false); final int maxx = ip.getWidth(); final int maxy = ip.getHeight(); final float scaleX = (float) results.getBounds().width / maxx; final float scaleY = (float) results.getBounds().height / maxy; // Create a results set for each object final int maxObject = objectAnalyzer.getMaxObject(); MemoryPeakResults[] resultsSet = new MemoryPeakResults[maxObject + 1]; for (int object = 0; object <= maxObject; object++) { MemoryPeakResults newResults = new MemoryPeakResults(); newResults.copySettings(results); newResults.setName(results.getName() + " " + object); resultsSet[object] = newResults; } final int[] mask = objectAnalyzer.getObjectMask(); if (showObjectMask) { ImageProcessor objectIp = (maxObject <= 255) ? new ByteProcessor(maxx, maxy) : new ShortProcessor(maxx, maxy); for (int i = 0; i < mask.length; i++) objectIp.set(i, mask[i]); ImagePlus imp = Utils.display(objectMask + " Objects", objectIp); imp.setDisplayRange(0, maxObject); imp.updateAndDraw(); } // Process the results mapping them to their objects int i = 0; final int size = results.size(); final int step = Utils.getProgressInterval(size); for (PeakResult result : results.getResults()) { if (++i % step == 0) IJ.showProgress(i, size); // Map to the mask objects final int object; int x = (int) (result.getXPosition() / scaleX); int y = (int) (result.getYPosition() / scaleY); if (x < 0 || x >= maxx || y < 0 || y >= maxy) { object = 0; } else { final int index = y * maxx + x; if (index < 0 || index >= mask.length) object = 0; else object = mask[index]; } resultsSet[object].add(result); } IJ.showProgress(1); // Add the new results sets to memory i = 0; for (int object = (nonMaskDataset) ? 0 : 1; object <= maxObject; object++) { if (!resultsSet[object].isEmpty()) { MemoryPeakResults.addResults(resultsSet[object]); i++; } } IJ.showStatus("Split " + Utils.pleural(results.size(), "result") + " into " + Utils.pleural(i, "set")); } }