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.smlm.results.MemoryPeakResults; import gdsc.smlm.results.PeakResult; import gdsc.core.logging.TrackProgress; import ij.IJ; import ij.gui.GenericDialog; import ij.plugin.PlugIn; /** * Updates the frame numbers on results that are stored in memory. */ public class ResequenceResults implements PlugIn { private static final String TITLE = "Resequence Results"; private static String inputOption = ""; private static int start = 1; private static int block = 1; private static int skip = 0; private static boolean logMapping = false; /* * (non-) * * @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; } if (!showDialog()) return; MemoryPeakResults results = ResultsManager.loadInputResults(inputOption, true); if (results == null || results.size() == 0) { IJ.error(TITLE, "No results could be loaded"); return; } if (resequenceResults(results, start, block, skip, (logMapping) ? new IJTrackProgress() : null)) IJ.showStatus("Resequenced " + results.getName()); } private boolean showDialog() { GenericDialog gd = new GenericDialog(TITLE); gd.addHelp(About.HELP_URL); gd.addMessage("Resequence the results in memory (assumed to be continuous from 1).\n" + "Describe the regular repeat of the original image:\n" + "Start = The first frame that contained the data\n" + "Block = The number of continuous frames containing data\n" + "Skip = The number of continuous frames to ignore before the next data\n \n" + "E.G. 2:9:1 = Data was imaged from frame 2 for 9 frames, 1 frame to ignore, then repeat."); ResultsManager.addInput(gd, inputOption, InputSource.MEMORY); gd.addNumericField("Start", start, 0); gd.addNumericField("Block", block, 0); gd.addNumericField("Skip", skip, 0); gd.addCheckbox("Log_mapping", logMapping); gd.showDialog(); if (gd.wasCanceled()) return false; inputOption = ResultsManager.getInputSource(gd); start = (int) gd.getNextNumber(); block = (int) gd.getNextNumber(); skip = (int) gd.getNextNumber(); logMapping = gd.getNextBoolean(); // Check arguments try { Parameters.isAboveZero("Start", start); Parameters.isAboveZero("Block", block); Parameters.isPositive("Skip", skip); } catch (IllegalArgumentException e) { IJ.error(TITLE, e.getMessage()); return false; } return true; } /** * Resequence the results for the original imaging sequence provided. Results are assumed to be continuous from 1. * * @param results * @param start * The first frame that contained the data * @param block * The number of continuous frames containing data * @param skip * The number of continuous frames to ignore before the next data * @param tracker * Used to report the mapping * @return */ private static boolean resequenceResults(MemoryPeakResults results, int start, int block, int skip, TrackProgress tracker) { if (results == null || results.size() == 0) return false; results.sort(); // Assume the results start from frame 1 (or above) if (results.getHead().getFrame() < 1) { return false; } int t = 1; // The current frame in the results int mapped = start; // The mapped frame in the results int b = 1; // The current block size boolean print = true; for (PeakResult r : results.getResults()) { if (t != r.getFrame()) { // Update the mapped position while (t < r.getFrame()) { // Move to the next position mapped++; // Check if this move will make the current block too large if (++b > block) { // Skip mapped += skip; b = 1; } t++; } t = r.getFrame(); print = true; } r.setFrame(mapped); if (print) { print = false; if (tracker != null) tracker.log("Map %d -> %d", t, mapped); } } return true; } }