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.core.ij.IJTrackProgress; import gdsc.smlm.ij.plugins.ResultsManager.InputSource; import gdsc.core.ij.Utils; import gdsc.smlm.results.FilePeakResults; import gdsc.smlm.results.MemoryPeakResults; import gdsc.smlm.results.Trace; import gdsc.smlm.results.TraceManager; import ij.IJ; import ij.gui.GenericDialog; import ij.io.OpenDialog; import ij.plugin.PlugIn; /** * Run a tracing algorithm on the peak results to trace neighbours across the frames. */ public class NeighbourAnalysis implements PlugIn { private static final String TITLE = "Neighbour Analysis"; private static String inputOption = ""; private static double distanceThreshold = 0.6; private static int timeThreshold = 1; private static String filename = ""; private MemoryPeakResults results; /* * (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, "No localisations in memory"); return; } if (!showDialog()) return; TraceManager manager = new TraceManager(results); // Run the tracing manager.setTracker(new IJTrackProgress()); Trace[] traces = manager.findNeighbours(distanceThreshold, timeThreshold); saveTraces(traces); } private void saveTraces(Trace[] traces) { String[] path = Utils.decodePath(filename); OpenDialog chooser = new OpenDialog("Traces_File", path[0], path[1]); if (chooser.getFileName() != null) { filename = chooser.getDirectory() + chooser.getFileName(); // Remove extension and replace with .xls int index = filename.lastIndexOf('.'); if (index > 0) { filename = filename.substring(0, index); } filename += ".xls"; boolean showDeviations = (!results.getResults().isEmpty() && results.getHead().paramsStdDev != null); FilePeakResults traceResults = new FilePeakResults(filename, showDeviations); traceResults.copySettings(results); traceResults.begin(); if (!traceResults.isActive()) { IJ.error(TITLE, "Failed to write to file: " + filename); return; } traceResults.addComment(createSettingsComment()); for (Trace trace : traces) traceResults.addCluster(trace); // addTrace(...) does a sort on the results traceResults.end(); } } private String createSettingsComment() { return String.format("Neighbour tracing : distance-threshold = %f : time-threshold = %d", distanceThreshold, timeThreshold); } private boolean showDialog() { GenericDialog gd = new GenericDialog(TITLE); gd.addHelp(About.HELP_URL); ResultsManager.addInput(gd, inputOption, InputSource.MEMORY); gd.addNumericField("Distance_Threshold (px)", distanceThreshold, 4); gd.addNumericField("Time_Threshold (frames)", timeThreshold, 0); gd.showDialog(); if (gd.wasCanceled() || !readDialog(gd)) return false; // Load the results results = ResultsManager.loadInputResults(inputOption, false); if (results == null || results.size() == 0) { IJ.error(TITLE, "No results could be loaded"); IJ.showStatus(""); return false; } return true; } private boolean readDialog(GenericDialog gd) { inputOption = ResultsManager.getInputSource(gd); distanceThreshold = gd.getNextNumber(); timeThreshold = (int) gd.getNextNumber(); if (distanceThreshold < 0) distanceThreshold = 0; if (timeThreshold < 0) timeThreshold = 0; if (timeThreshold == 0 && distanceThreshold == 0) { IJ.error(TITLE, "No thresholds specified"); return false; } return !gd.invalidNumber(); } }