Search in sources :

Example 1 with SeriesImageSource

use of uk.ac.sussex.gdsc.smlm.ij.SeriesImageSource in project GDSC-SMLM by aherbert.

the class PeakResultTableModelFrame method doSourceShowImage.

private void doSourceShowImage() {
    final PeakResultTableModel model = getModel();
    if (model == null) {
        return;
    }
    final ImageSource source = model.getSource();
    if (source == null) {
        return;
    }
    // Check if already open
    final ImagePlus imp = WindowManager.getImage(source.getName());
    if (imp != null) {
        imp.getWindow().toFront();
        return;
    }
    // Check if an ImageJ image source
    if (source instanceof IJImageSource) {
        final IJImageSource imageSource = (IJImageSource) source;
        final String path = imageSource.getPath();
        if (path != null && new File(path).exists()) {
            IJ.showStatus("Opening image ...");
            IJ.open(path);
            IJ.showStatus("");
        } else {
            IJ.log("Cannot find the image source: " + path);
        }
        return;
    }
    // Open a SeriesImageSource.
    if (source instanceof SeriesImageSource) {
        final SeriesImageSource imageSource = (SeriesImageSource) source;
        // No memory buffer
        imageSource.setBufferLimit(0);
        imageSource.setReadHint(ReadHint.NONSEQUENTIAL);
        if (!source.open()) {
            IJ.log("Cannot open the series image source");
            return;
        }
        new TiffSeriesVirtualStack(imageSource).show();
    }
}
Also used : IJImageSource(uk.ac.sussex.gdsc.smlm.ij.IJImageSource) SeriesImageSource(uk.ac.sussex.gdsc.smlm.ij.SeriesImageSource) ImageSource(uk.ac.sussex.gdsc.smlm.results.ImageSource) IJImageSource(uk.ac.sussex.gdsc.smlm.ij.IJImageSource) SeriesImageSource(uk.ac.sussex.gdsc.smlm.ij.SeriesImageSource) ImagePlus(ij.ImagePlus) File(java.io.File) TiffSeriesVirtualStack(uk.ac.sussex.gdsc.smlm.ij.plugins.TiffSeriesViewer.TiffSeriesVirtualStack)

Example 2 with SeriesImageSource

use of uk.ac.sussex.gdsc.smlm.ij.SeriesImageSource in project GDSC-SMLM by aherbert.

the class PeakFit method setup.

@Override
public int setup(String arg, ImagePlus imp) {
    SmlmUsageTracker.recordPlugin(this.getClass(), arg);
    pluginFlags = FLAGS;
    extraOptions = ImageJUtils.isExtraOptions();
    maximaIdentification = StringUtils.contains(arg, "spot");
    fitMaxima = StringUtils.contains(arg, "maxima");
    simpleFit = StringUtils.contains(arg, "simple");
    final boolean runSeries = StringUtils.contains(arg, "series");
    ImageSource imageSource = null;
    if (fitMaxima) {
        // The image source will be found from the peak results.
        if (!showMaximaDialog()) {
            return DONE;
        }
        final MemoryPeakResults localResults = ResultsManager.loadInputResults(settings.inputOption, false, DistanceUnit.PIXEL);
        if (localResults == null || localResults.size() == 0) {
            IJ.error(TITLE, "No results could be loaded");
            return DONE;
        }
        if (settings.fitAcrossAllFrames) {
            // Allow the user to select a different image. The source will be set as per the
            // main fit routine from the image (imp).
            singleFrame = 0;
        } else {
            // Check for single frame
            singleFrame = getSingleFrame(localResults);
            // Forces the maxima to be used with their original source.
            imp = null;
            imageSource = localResults.getSource();
            pluginFlags |= NO_IMAGE_REQUIRED;
        }
    } else if (runSeries) {
        imp = null;
        // Select input folder
        final String inputDirectory = IJ.getDirectory("Select image series ...");
        if (inputDirectory == null) {
            return DONE;
        }
        // Load input series ...
        SeriesOpener series;
        if (extraOptions) {
            final String helpKey = maximaIdentification ? "spot-finder-series" : "peak-fit-series";
            series = SeriesOpener.create(inputDirectory, true, HelpUrls.getUrl(helpKey));
        } else {
            series = new SeriesOpener(inputDirectory);
        }
        if (series.getNumberOfImages() == 0) {
            IJ.error(TITLE, "No images in the selected directory:\n" + inputDirectory);
            return DONE;
        }
        final SeriesImageSource seriesImageSource = new SeriesImageSource(getName(series.getImageList()), series);
        // TrackProgress logging is very verbose if the series has many images
        // Status is used only when reading TIFF info.
        // seriesImageSource.setTrackProgress(SimpleImageJTrackProgress.getInstance());
        seriesImageSource.setTrackProgress(new TrackProgressAdaptor() {

            @Override
            public void status(String format, Object... args) {
                ImageJUtils.showStatus(() -> String.format(format, args));
            }
        });
        imageSource = seriesImageSource;
        pluginFlags |= NO_IMAGE_REQUIRED;
    }
    // If the image source has not been set then use the input image
    if (imageSource == null) {
        if (imp == null) {
            IJ.noImage();
            return DONE;
        }
        // Check it is not a previous result
        if (imp.getTitle().endsWith(ImageJImagePeakResults.IMAGE_SUFFIX)) {
            IJImageSource ijImageSource = null;
            // Check the image to see if it has an image source XML structure in the info property
            final Object o = imp.getProperty("Info");
            final Pattern pattern = Pattern.compile("Source: (<.*IJImageSource>.*<.*IJImageSource>)", Pattern.DOTALL);
            final Matcher match = pattern.matcher((o == null) ? "" : o.toString());
            if (match.find()) {
                final ImageSource tmpSource = ImageSource.fromXml(match.group(1));
                if (tmpSource instanceof IJImageSource) {
                    ijImageSource = (IJImageSource) tmpSource;
                    if (!ijImageSource.open()) {
                        ijImageSource = null;
                    } else {
                        imp = WindowManager.getImage(ijImageSource.getName());
                    }
                }
            }
            if (ijImageSource == null) {
                // Look for a parent using the title
                final String parentTitle = imp.getTitle().substring(0, imp.getTitle().length() - ImageJImagePeakResults.IMAGE_SUFFIX.length() - 1);
                final ImagePlus parentImp = WindowManager.getImage(parentTitle);
                if (parentImp != null) {
                    ijImageSource = new IJImageSource(parentImp);
                    imp = parentImp;
                }
            }
            String message = "The selected image may be a previous fit result";
            if (ijImageSource != null) {
                if (!TextUtils.isNullOrEmpty(ijImageSource.getName())) {
                    message += " of: \n \n" + ijImageSource.getName();
                }
                message += " \n \nFit the parent?";
            } else {
                message += " \n \nDo you want to continue?";
            }
            final YesNoCancelDialog d = new YesNoCancelDialog(null, TITLE, message);
            if (ijImageSource == null) {
                if (!d.yesPressed()) {
                    return DONE;
                }
            } else {
                if (d.yesPressed()) {
                    imageSource = ijImageSource;
                }
                if (d.cancelPressed()) {
                    return DONE;
                }
            }
        }
        if (imageSource == null) {
            try {
                imageSource = new IJImageSource(imp);
            } catch (final IllegalArgumentException ex) {
                // This can happen if the image has an origin not in integer pixels
                // e.g. the plugin is run on a plot
                IJ.error(TITLE, "Error using image: " + imp.getTitle() + "\n \n" + ex.getMessage());
                return DONE;
            }
        }
    }
    time = -1;
    if (!initialiseImage(imageSource, getBounds(imp), false)) {
        IJ.error(TITLE, "Failed to initialise the source image: " + imageSource.getName());
        return DONE;
    }
    final int flags = showDialog(imp);
    if ((flags & DONE) == 0) {
        initialiseFitting();
    }
    return flags;
}
Also used : Pattern(java.util.regex.Pattern) Matcher(java.util.regex.Matcher) SeriesImageSource(uk.ac.sussex.gdsc.smlm.ij.SeriesImageSource) SeriesOpener(uk.ac.sussex.gdsc.core.ij.SeriesOpener) ImagePlus(ij.ImagePlus) TrackProgressAdaptor(uk.ac.sussex.gdsc.core.logging.TrackProgressAdaptor) IJImageSource(uk.ac.sussex.gdsc.smlm.ij.IJImageSource) MemoryPeakResults(uk.ac.sussex.gdsc.smlm.results.MemoryPeakResults) YesNoCancelDialog(ij.gui.YesNoCancelDialog) ImageSource(uk.ac.sussex.gdsc.smlm.results.ImageSource) AggregatedImageSource(uk.ac.sussex.gdsc.smlm.results.AggregatedImageSource) InterlacedImageSource(uk.ac.sussex.gdsc.smlm.results.InterlacedImageSource) SeriesImageSource(uk.ac.sussex.gdsc.smlm.ij.SeriesImageSource) IJImageSource(uk.ac.sussex.gdsc.smlm.ij.IJImageSource)

Example 3 with SeriesImageSource

use of uk.ac.sussex.gdsc.smlm.ij.SeriesImageSource in project GDSC-SMLM by aherbert.

the class CmosAnalysis method runAnalysis.

private void runAnalysis() {
    final long start = System.currentTimeMillis();
    // Create thread pool and workers. The system is likely to be IO limited
    // so reduce the computation threads to allow the reading thread in the
    // SeriesImageSource to run.
    // If the images are small enough to fit into memory then 3 threads are used,
    // otherwise it is 1.
    final int nThreads = Math.max(1, getThreads() - 3);
    final ExecutorService executor = Executors.newFixedThreadPool(nThreads);
    final LocalList<Future<?>> futures = new LocalList<>(nThreads);
    final LocalList<ImageWorker> workers = new LocalList<>(nThreads);
    final double[][] data = new double[subDirs.size() * 2][];
    double[] pixelOffset = null;
    double[] pixelVariance = null;
    Statistics statsOffset = null;
    Statistics statsVariance = null;
    // For each sub-directory compute the mean and variance
    final int nSubDirs = subDirs.size();
    boolean error = false;
    int width = 0;
    int height = 0;
    for (int n = 0; n < nSubDirs; n++) {
        ImageJUtils.showSlowProgress(n, nSubDirs);
        final SubDir sd = subDirs.unsafeGet(n);
        ImageJUtils.showStatus(() -> "Analysing " + sd.name);
        final StopWatch sw = StopWatch.createStarted();
        // Option to reuse data
        final File file = new File(settings.directory, "perPixel" + sd.name + ".tif");
        boolean found = false;
        if (settings.reuseProcessedData && file.exists()) {
            final Opener opener = new Opener();
            opener.setSilentMode(true);
            final ImagePlus imp = opener.openImage(file.getPath());
            if (imp != null && imp.getStackSize() == 2 && imp.getBitDepth() == 32) {
                if (n == 0) {
                    width = imp.getWidth();
                    height = imp.getHeight();
                } else if (width != imp.getWidth() || height != imp.getHeight()) {
                    error = true;
                    IJ.error(TITLE, "Image width/height mismatch in image series: " + file.getPath() + String.format("\n \nExpected %dx%d, Found %dx%d", width, height, imp.getWidth(), imp.getHeight()));
                    break;
                }
                final ImageStack stack = imp.getImageStack();
                data[2 * n] = SimpleArrayUtils.toDouble((float[]) stack.getPixels(1));
                data[2 * n + 1] = SimpleArrayUtils.toDouble((float[]) stack.getPixels(2));
                found = true;
            }
        }
        if (!found) {
            // Open the series
            final SeriesImageSource source = new SeriesImageSource(sd.name, sd.path.getPath());
            if (!source.open()) {
                error = true;
                IJ.error(TITLE, "Failed to open image series: " + sd.path.getPath());
                break;
            }
            if (n == 0) {
                width = source.getWidth();
                height = source.getHeight();
            } else if (width != source.getWidth() || height != source.getHeight()) {
                error = true;
                IJ.error(TITLE, "Image width/height mismatch in image series: " + sd.path.getPath() + String.format("\n \nExpected %dx%d, Found %dx%d", width, height, source.getWidth(), source.getHeight()));
                break;
            }
            // So the bar remains at 99% when workers have finished use frames + 1
            final Ticker ticker = ImageJUtils.createTicker(source.getFrames() + 1L, nThreads);
            // Open the first frame to get the bit depth.
            // Assume the first pixels are not empty as the source is open.
            Object pixels = source.nextRaw();
            final int bitDepth = ImageJUtils.getBitDepth(pixels);
            ArrayMoment moment;
            if (settings.rollingAlgorithm) {
                moment = new RollingArrayMoment();
            // We assume 16-bit camera at the maximum
            } else if (bitDepth <= 16 && IntegerArrayMoment.isValid(IntegerType.UNSIGNED_16, source.getFrames())) {
                moment = new IntegerArrayMoment();
            } else {
                moment = new SimpleArrayMoment();
            }
            final BlockingQueue<Object> jobs = new ArrayBlockingQueue<>(nThreads * 2);
            for (int i = 0; i < nThreads; i++) {
                final ImageWorker worker = new ImageWorker(ticker, jobs, moment);
                workers.add(worker);
                futures.add(executor.submit(worker));
            }
            // Process the raw pixel data
            long lastTime = 0;
            while (pixels != null) {
                final long time = System.currentTimeMillis();
                if (time - lastTime > 150) {
                    if (ImageJUtils.isInterrupted()) {
                        error = true;
                        break;
                    }
                    lastTime = time;
                    IJ.showStatus("Analysing " + sd.name + " Frame " + source.getStartFrameNumber());
                }
                put(jobs, pixels);
                pixels = source.nextRaw();
            }
            source.close();
            if (error) {
                // Kill the workers
                workers.stream().forEach(worker -> worker.finished = true);
                // Clear the queue
                jobs.clear();
                // Signal any waiting workers
                workers.stream().forEach(worker -> jobs.add(ImageWorker.STOP_SIGNAL));
                // Cancel by interruption. We set the finished flag so the ImageWorker should
                // ignore the interrupt.
                futures.stream().forEach(future -> future.cancel(true));
                break;
            }
            // Finish all the worker threads cleanly
            workers.stream().forEach(worker -> jobs.add(ImageWorker.STOP_SIGNAL));
            // Wait for all to finish
            ConcurrencyUtils.waitForCompletionUnchecked(futures);
            // Create the final aggregate statistics
            for (final ImageWorker w : workers) {
                moment.add(w.moment);
            }
            data[2 * n] = moment.getMean();
            data[2 * n + 1] = moment.getVariance();
            // Get the processing speed.
            sw.stop();
            // ticker holds the number of number of frames processed
            final double bits = (double) bitDepth * source.getFrames() * source.getWidth() * source.getHeight();
            final double bps = bits / sw.getTime(TimeUnit.SECONDS);
            final SiPrefix prefix = SiPrefix.getSiPrefix(bps);
            ImageJUtils.log("Processed %d frames. Time = %s. Rate = %s %sbits/s", moment.getN(), sw.toString(), MathUtils.rounded(prefix.convert(bps)), prefix.getPrefix());
            // Reset
            futures.clear();
            workers.clear();
            final ImageStack stack = new ImageStack(width, height);
            stack.addSlice("Mean", SimpleArrayUtils.toFloat(data[2 * n]));
            stack.addSlice("Variance", SimpleArrayUtils.toFloat(data[2 * n + 1]));
            IJ.save(new ImagePlus("PerPixel", stack), file.getPath());
        }
        final Statistics s = Statistics.create(data[2 * n]);
        if (pixelOffset != null) {
            // Compute mean ADU
            final Statistics signal = new Statistics();
            final double[] mean = data[2 * n];
            for (int i = 0; i < pixelOffset.length; i++) {
                signal.add(mean[i] - pixelOffset[i]);
            }
            ImageJUtils.log("%s Mean = %s +/- %s. Signal = %s +/- %s ADU", sd.name, MathUtils.rounded(s.getMean()), MathUtils.rounded(s.getStandardDeviation()), MathUtils.rounded(signal.getMean()), MathUtils.rounded(signal.getStandardDeviation()));
        } else {
            // Set the offset assuming the first sub-directory is the bias image
            pixelOffset = data[0];
            pixelVariance = data[1];
            statsOffset = s;
            statsVariance = Statistics.create(pixelVariance);
            ImageJUtils.log("%s Offset = %s +/- %s. Variance = %s +/- %s", sd.name, MathUtils.rounded(s.getMean()), MathUtils.rounded(s.getStandardDeviation()), MathUtils.rounded(statsVariance.getMean()), MathUtils.rounded(statsVariance.getStandardDeviation()));
        }
        IJ.showProgress(1);
    }
    ImageJUtils.clearSlowProgress();
    if (error) {
        executor.shutdownNow();
        IJ.showStatus(TITLE + " cancelled");
        return;
    }
    executor.shutdown();
    if (pixelOffset == null || pixelVariance == null) {
        IJ.showStatus(TITLE + " error: no bias image");
        return;
    }
    // Compute the gain
    ImageJUtils.showStatus("Computing gain");
    final double[] pixelGain = new double[pixelOffset.length];
    final double[] bibiT = new double[pixelGain.length];
    final double[] biaiT = new double[pixelGain.length];
    // Ignore first as this is the 0 exposure image
    for (int n = 1; n < nSubDirs; n++) {
        // Use equation 2.5 from the Huang et al paper.
        final double[] b = data[2 * n];
        final double[] a = data[2 * n + 1];
        for (int i = 0; i < pixelGain.length; i++) {
            final double bi = b[i] - pixelOffset[i];
            final double ai = a[i] - pixelVariance[i];
            bibiT[i] += bi * bi;
            biaiT[i] += bi * ai;
        }
    }
    for (int i = 0; i < pixelGain.length; i++) {
        pixelGain[i] = biaiT[i] / bibiT[i];
    }
    final Statistics statsGain = Statistics.create(pixelGain);
    ImageJUtils.log("Gain Mean = %s +/- %s", MathUtils.rounded(statsGain.getMean()), MathUtils.rounded(statsGain.getStandardDeviation()));
    // Histogram of offset, variance and gain
    final int bins = 2 * HistogramPlot.getBinsSturgesRule(pixelGain.length);
    final WindowOrganiser wo = new WindowOrganiser();
    showHistogram("Offset (ADU)", pixelOffset, bins, statsOffset, wo);
    showHistogram("Variance (ADU^2)", pixelVariance, bins, statsVariance, wo);
    showHistogram("Gain (ADU/e)", pixelGain, bins, statsGain, wo);
    wo.tile();
    // Save
    final float[] bias = SimpleArrayUtils.toFloat(pixelOffset);
    final float[] variance = SimpleArrayUtils.toFloat(pixelVariance);
    final float[] gain = SimpleArrayUtils.toFloat(pixelGain);
    measuredStack = new ImageStack(width, height);
    measuredStack.addSlice("Offset", bias);
    measuredStack.addSlice("Variance", variance);
    measuredStack.addSlice("Gain", gain);
    final ExtendedGenericDialog egd = new ExtendedGenericDialog(TITLE);
    egd.addMessage("Save the sCMOS camera model?");
    if (settings.modelDirectory == null) {
        settings.modelDirectory = settings.directory;
        settings.modelName = "sCMOS Camera";
    }
    egd.addStringField("Model_name", settings.modelName, 30);
    egd.addDirectoryField("Model_directory", settings.modelDirectory);
    egd.showDialog();
    if (!egd.wasCanceled()) {
        settings.modelName = egd.getNextString();
        settings.modelDirectory = egd.getNextString();
        saveCameraModel(width, height, bias, gain, variance);
    }
    // Remove the status from the ij.io.ImageWriter class
    IJ.showStatus("");
    ImageJUtils.log("Analysis time = " + TextUtils.millisToString(System.currentTimeMillis() - start));
}
Also used : SiPrefix(uk.ac.sussex.gdsc.core.data.SiPrefix) RollingArrayMoment(uk.ac.sussex.gdsc.core.math.RollingArrayMoment) RollingArrayMoment(uk.ac.sussex.gdsc.core.math.RollingArrayMoment) ArrayMoment(uk.ac.sussex.gdsc.core.math.ArrayMoment) IntegerArrayMoment(uk.ac.sussex.gdsc.core.math.IntegerArrayMoment) SimpleArrayMoment(uk.ac.sussex.gdsc.core.math.SimpleArrayMoment) LocalList(uk.ac.sussex.gdsc.core.utils.LocalList) ArrayBlockingQueue(java.util.concurrent.ArrayBlockingQueue) SimpleArrayMoment(uk.ac.sussex.gdsc.core.math.SimpleArrayMoment) IntegerArrayMoment(uk.ac.sussex.gdsc.core.math.IntegerArrayMoment) ImageStack(ij.ImageStack) SeriesImageSource(uk.ac.sussex.gdsc.smlm.ij.SeriesImageSource) Ticker(uk.ac.sussex.gdsc.core.logging.Ticker) WindowOrganiser(uk.ac.sussex.gdsc.core.ij.plugin.WindowOrganiser) ExtendedGenericDialog(uk.ac.sussex.gdsc.core.ij.gui.ExtendedGenericDialog) Statistics(uk.ac.sussex.gdsc.core.utils.Statistics) ImagePlus(ij.ImagePlus) StopWatch(org.apache.commons.lang3.time.StopWatch) ExecutorService(java.util.concurrent.ExecutorService) Future(java.util.concurrent.Future) File(java.io.File) Opener(ij.io.Opener)

Example 4 with SeriesImageSource

use of uk.ac.sussex.gdsc.smlm.ij.SeriesImageSource in project GDSC-SMLM by aherbert.

the class TiffSeriesViewer method run.

@Override
public void run(String arg) {
    SmlmUsageTracker.recordPlugin(this.getClass(), arg);
    settings = Settings.load();
    final ExtendedGenericDialog gd = new ExtendedGenericDialog(TITLE);
    gd.addChoice("Mode", Settings.MODE, settings.inputMode, new OptionListener<Integer>() {

        @Override
        public boolean collectOptions(Integer value) {
            settings.inputMode = value;
            return collectOptions(false);
        }

        @Override
        public boolean collectOptions() {
            return collectOptions(true);
        }

        private boolean collectOptions(boolean silent) {
            // This has limited silent support to fake running in a macro
            if (settings.inputMode == 0) {
                String dir = null;
                final String title = "Select image series ...";
                if (silent) {
                    final String macroOptions = Macro.getOptions();
                    if (macroOptions != null) {
                        dir = Macro.getValue(macroOptions, title, null);
                    }
                } else {
                    dir = ImageJUtils.getDirectory(title, settings.inputDirectory);
                }
                if (TextUtils.isNullOrEmpty(dir)) {
                    return false;
                }
                settings.inputDirectory = dir;
            } else {
                String file = null;
                final String title = "Select image ...";
                if (silent) {
                    final String macroOptions = Macro.getOptions();
                    if (macroOptions != null) {
                        file = Macro.getValue(macroOptions, title, null);
                    }
                } else {
                    file = ImageJUtils.getFilename(title, settings.inputFile);
                }
                if (TextUtils.isNullOrEmpty(file)) {
                    return false;
                }
                settings.inputFile = file;
            }
            updateLabel();
            return true;
        }
    });
    gd.addMessage("");
    label = gd.getLastLabel();
    if (ImageJUtils.isShowGenericDialog()) {
        final Choice choice = gd.getLastChoice();
        choice.addItemListener(event -> {
            settings.inputMode = choice.getSelectedIndex();
            updateLabel();
        });
        updateLabel();
    }
    gd.addCheckbox("Log_progress", settings.logProgress);
    gd.addChoice("Output_mode", Settings.OUTPUT_MODE, settings.outputMode, new OptionListener<Integer>() {

        @Override
        public boolean collectOptions(Integer value) {
            settings.outputMode = value;
            return collectOptions(false);
        }

        @Override
        public boolean collectOptions() {
            return collectOptions(true);
        }

        private boolean collectOptions(boolean silent) {
            if (settings.outputMode == 0) {
                // Nothing to do
                return false;
            }
            final ExtendedGenericDialog egd = new ExtendedGenericDialog("Output Options");
            egd.addNumericField("Slices_per_image", settings.imageCount, 0);
            egd.addDirectoryField("Output_directory", settings.outputDirectory);
            egd.setSilent(silent);
            egd.showDialog(true, gd);
            if (egd.wasCanceled()) {
                return false;
            }
            settings.imageCount = (int) egd.getNextNumber();
            settings.outputDirectory = egd.getNextString();
            updateLabel2();
            return true;
        }
    });
    gd.addMessage("");
    label2 = gd.getLastLabel();
    if (ImageJUtils.isShowGenericDialog()) {
        final Choice choice = gd.getLastChoice();
        choice.addItemListener(event -> {
            settings.outputMode = choice.getSelectedIndex();
            updateLabel2();
        });
        updateLabel2();
    }
    gd.addHelp(HelpUrls.getUrl("tiff-series-viewer"));
    gd.showDialog();
    if (gd.wasCanceled()) {
        return;
    }
    settings.inputMode = gd.getNextChoiceIndex();
    settings.logProgress = gd.getNextBoolean();
    settings.outputMode = gd.getNextChoiceIndex();
    settings.save();
    SeriesImageSource source;
    if (settings.inputMode == 0) {
        final SeriesOpener series = new SeriesOpener(settings.inputDirectory);
        if (series.getNumberOfImages() == 0) {
            IJ.error(TITLE, "No images in the selected directory:\n" + settings.inputDirectory);
            return;
        }
        source = new SeriesImageSource(PeakFit.getName(series.getImageList()), series);
    } else {
        source = new SeriesImageSource(FileUtils.getName(settings.inputFile), new String[] { settings.inputFile });
    }
    // No memory buffer
    source.setBufferLimit(0);
    source.setReadHint(ReadHint.NONSEQUENTIAL);
    if (!source.isTiffSeries) {
        IJ.error(TITLE, "Not a TIFF image");
        return;
    }
    ImageJUtils.showStatus("Opening TIFF ...");
    final TrackProgressAdaptor progress = new TrackProgressAdaptor() {

        @Override
        public void progress(double fraction) {
            IJ.showProgress(fraction);
        }

        @Override
        public void progress(long position, long total) {
            IJ.showProgress((double) position / total);
        }

        @Override
        public void log(String format, Object... args) {
            if (settings.logProgress) {
                ImageJUtils.log(format, args);
            }
        }

        @Override
        public void status(String format, Object... args) {
            ImageJUtils.showStatus(() -> String.format(format, args));
        }

        @Override
        public boolean isLog() {
            return settings.logProgress;
        }
    };
    source.setTrackProgress(progress);
    if (!source.open()) {
        IJ.error(TITLE, "Cannot open the image");
        return;
    }
    ImageJUtils.showStatus("");
    // Create a virtual stack
    final TiffSeriesVirtualStack stack = new TiffSeriesVirtualStack(source);
    if (settings.outputMode == 0) {
        stack.show();
    } else {
        final int nImages = Math.max(1, settings.imageCount);
        final ImagePlus imp = stack.createImp();
        // The calibration only has the offset so ignore for speed.
        // Calibration cal = imp.getCalibration();
        final int size = stack.getSize();
        // Create the format string
        final int digits = String.format("%d", size).length();
        final String format = new File(settings.outputDirectory, imp.getShortTitle() + "%0" + digits + "d.tif").getPath();
        IJ.showStatus("Saving image ...");
        try {
            for (int i = 1; i <= size; i += nImages) {
                if (ImageJUtils.isInterrupted()) {
                    break;
                }
                ImageJUtils.showSlowProgress(i, size);
                final String path = String.format(format, i);
                final ImageStack out = new ImageStack(source.getWidth(), source.getHeight());
                for (int j = 0, k = i; j < nImages && k <= size; j++, k++) {
                    out.addSlice(null, stack.getPixels(k));
                }
                final ImagePlus outImp = new ImagePlus(path, out);
                // outImp.setCalibration(cal);
                saveAsTiff(outImp, path);
            }
            IJ.showStatus("Saved image");
        } catch (final IOException ex) {
            IJ.log(ExceptionUtils.getStackTrace(ex));
            IJ.error(TITLE, "Failed to save image: " + ex.getMessage());
            IJ.showStatus("Failed to save image");
        } finally {
            ImageJUtils.clearSlowProgress();
        }
    }
}
Also used : Choice(java.awt.Choice) ImageStack(ij.ImageStack) SeriesImageSource(uk.ac.sussex.gdsc.smlm.ij.SeriesImageSource) ExtendedGenericDialog(uk.ac.sussex.gdsc.core.ij.gui.ExtendedGenericDialog) SeriesOpener(uk.ac.sussex.gdsc.core.ij.SeriesOpener) IOException(java.io.IOException) ImagePlus(ij.ImagePlus) ReadHint(uk.ac.sussex.gdsc.smlm.results.ImageSource.ReadHint) TrackProgressAdaptor(uk.ac.sussex.gdsc.core.logging.TrackProgressAdaptor) File(java.io.File)

Aggregations

ImagePlus (ij.ImagePlus)4 SeriesImageSource (uk.ac.sussex.gdsc.smlm.ij.SeriesImageSource)4 File (java.io.File)3 ImageStack (ij.ImageStack)2 SeriesOpener (uk.ac.sussex.gdsc.core.ij.SeriesOpener)2 ExtendedGenericDialog (uk.ac.sussex.gdsc.core.ij.gui.ExtendedGenericDialog)2 TrackProgressAdaptor (uk.ac.sussex.gdsc.core.logging.TrackProgressAdaptor)2 IJImageSource (uk.ac.sussex.gdsc.smlm.ij.IJImageSource)2 ImageSource (uk.ac.sussex.gdsc.smlm.results.ImageSource)2 YesNoCancelDialog (ij.gui.YesNoCancelDialog)1 Opener (ij.io.Opener)1 Choice (java.awt.Choice)1 IOException (java.io.IOException)1 ArrayBlockingQueue (java.util.concurrent.ArrayBlockingQueue)1 ExecutorService (java.util.concurrent.ExecutorService)1 Future (java.util.concurrent.Future)1 Matcher (java.util.regex.Matcher)1 Pattern (java.util.regex.Pattern)1 StopWatch (org.apache.commons.lang3.time.StopWatch)1 SiPrefix (uk.ac.sussex.gdsc.core.data.SiPrefix)1