Search in sources :

Example 16 with Plot

use of ij.gui.Plot in project GDSC-SMLM by aherbert.

the class TcPalmAnalysis method analyseRois.

/**
 * Analyses all the ROIs in the ROI manager.
 *
 * @param event the event
 */
private void analyseRois(ActionEvent event) {
    final RoiManager manager = RoiManager.getInstance();
    if (manager == null) {
        IJ.error(TITLE, "ROI manager is not open");
        return;
    }
    final LocalList<Roi> rois = Arrays.stream(manager.getRoisAsArray()).filter(Roi::isArea).collect(LocalCollectors.toLocalList());
    if (rois.isEmpty()) {
        IJ.error(TITLE, "No area ROIs");
        return;
    }
    // Check for overlaps.
    if (!settings.getDisableOverlapCheck() && anyOverlap(rois)) {
        final GenericDialog gd = new GenericDialog(TITLE);
        gd.addMessage(TextUtils.wrap("WARNING - Bounding rectangles of ROIs overlap. You can verify " + "the ROIs on the image using the ROI manager 'Show all' function.", 80));
        gd.setOKLabel("Continue");
        gd.showDialog();
        if (gd.wasCanceled()) {
            return;
        }
    }
    // For each ROI:
    // - Extract the current groups
    // - Build the cumulative count plot
    // - Identify the bursts
    // - Extract ClusterData for each burst
    final TcPalmAnalysisSettings settings = this.settings.build();
    final LocalList<ClusterData> allClusters = rois.parallelStream().map(roi -> {
        final Rectangle2D scaledBounds = createScaledBounds(roi);
        final BiPredicate<ClusterData, Rectangle2D> filter = createSelectionFilter(roi, settings);
        // Filter all cluster groups
        final LocalList<ClusterData> clusters = new LocalList<>();
        clusterData.forEach(c -> {
            if (filter.test(c, scaledBounds)) {
                clusters.add(c);
            }
        });
        // Extract activation bursts
        final CumulativeCountData countData = createCumulativeCountData(clusters, false);
        final LocalList<int[]> bursts = runBurstAnalysis(settings, countData);
        final LocalList<LocalList<PeakResult>> burstLocalisations = createBurstLocalisations(clusters, bursts);
        clusters.clear();
        burstLocalisations.forEach(list -> {
            final ClusterData d = new ClusterData(clusters.size() + 1, list);
            // Save this for analysis
            d.sourceRoi = roi;
            d.getArea();
            clusters.add(d);
        });
        return clusters;
    }).collect(LocalList::new, LocalList::addAll, LocalList::addAll);
    // Reorder
    final Counter count = new Counter();
    allClusters.forEach(c -> c.id = count.incrementAndGet());
    // Display in a table
    final ClusterDataTableModelFrame frame = createAllClustersTable();
    frame.getModel().setData(allClusters, dataCalibration);
    // Allow the results to be repeated
    frame.selectedAction = clusters -> {
        // Expecting a single cluster. No clusters occurs when the table (and selection) is cleared.
        if (clusters.size() == 1) {
            final ClusterData c = clusters.get(0);
            // Push the correct ROI and settings to the analysis action.
            // We do not directly update the ROI or dialog settings as
            // these trigger events that are processed to add work with a delay.
            // Updating them at the end should generate events that are
            // ignored when finally executed as the ROI/settings should be the same.
            addWork(0, c.sourceRoi, settings, () -> {
                // When analysis has finished update the settings and image ROI.
                image.getImagePlus().setRoi(c.sourceRoi);
                darkTimeToleranceTextField.setText(Integer.toString(settings.getDarkTimeTolerance()));
                minClusterSizeTextField.setText(Integer.toString(settings.getMinClusterSize()));
                // When analysis has finished the cluster should be selected in the
                // current clusters table.
                final ClusterDataTableModelFrame currentClusters = currentClustersTable.get();
                if (currentClusters != null) {
                    currentClusters.select(c);
                }
            });
        }
    };
    // Show histogram of cluster size/duration
    reportAnalysis(settings, allClusters, dataCalibration);
    // Save clusters to memory
    final Trace[] traces = allClusters.stream().map(c -> {
        final Trace t = new Trace();
        t.setId(c.id);
        c.results.forEach(t::add);
        return t;
    }).toArray(Trace[]::new);
    TraceMolecules.saveResults(results, traces, "TC PALM");
    IJ.showStatus(TITLE + ": " + TextUtils.pleural(allClusters.size(), "cluster"));
}
Also used : Color(java.awt.Color) Arrays(java.util.Arrays) Calibration(uk.ac.sussex.gdsc.smlm.data.config.CalibrationProtos.Calibration) IntUnaryOperator(java.util.function.IntUnaryOperator) Rectangle2D(java.awt.geom.Rectangle2D) HistogramPlotBuilder(uk.ac.sussex.gdsc.core.ij.HistogramPlot.HistogramPlotBuilder) IdFramePeakResultComparator(uk.ac.sussex.gdsc.smlm.results.sort.IdFramePeakResultComparator) UnaryOperator(java.util.function.UnaryOperator) Hull(uk.ac.sussex.gdsc.core.math.hull.Hull) TableCellRenderer(javax.swing.table.TableCellRenderer) ResultsSettings(uk.ac.sussex.gdsc.smlm.data.config.ResultsProtos.ResultsSettings) FloatUnaryOperator(uk.ac.sussex.gdsc.core.utils.function.FloatUnaryOperator) MemoryPeakResults(uk.ac.sussex.gdsc.smlm.results.MemoryPeakResults) RoiManager(ij.plugin.frame.RoiManager) RowSorter(javax.swing.RowSorter) SoftLock(uk.ac.sussex.gdsc.core.utils.SoftLock) JFrame(javax.swing.JFrame) LutHelper(uk.ac.sussex.gdsc.core.ij.process.LutHelper) KeyStroke(javax.swing.KeyStroke) TableModelEvent(javax.swing.event.TableModelEvent) InputSource(uk.ac.sussex.gdsc.smlm.ij.plugins.ResultsManager.InputSource) DistanceUnit(uk.ac.sussex.gdsc.smlm.data.config.UnitProtos.DistanceUnit) KeyEvent(java.awt.event.KeyEvent) WindowAdapter(java.awt.event.WindowAdapter) ConcurrencyUtils(uk.ac.sussex.gdsc.core.utils.concurrent.ConcurrencyUtils) Component(java.awt.Component) Hull2d(uk.ac.sussex.gdsc.core.math.hull.Hull2d) TextUtils(uk.ac.sussex.gdsc.core.utils.TextUtils) Plot(ij.gui.Plot) Executors(java.util.concurrent.Executors) CalibrationHelper(uk.ac.sussex.gdsc.smlm.data.config.CalibrationHelper) ImagePlus(ij.ImagePlus) DefaultTableCellRenderer(javax.swing.table.DefaultTableCellRenderer) ToDoubleFunction(java.util.function.ToDoubleFunction) TcPalmAnalysisSettings(uk.ac.sussex.gdsc.smlm.ij.settings.GUIProtos.TcPalmAnalysisSettings) FileUtils(uk.ac.sussex.gdsc.core.utils.FileUtils) PlugIn(ij.plugin.PlugIn) ListSelectionModel(javax.swing.ListSelectionModel) ActionListener(java.awt.event.ActionListener) PolygonRoi(ij.gui.PolygonRoi) StoredData(uk.ac.sussex.gdsc.core.utils.StoredData) FrameCounter(uk.ac.sussex.gdsc.smlm.results.count.FrameCounter) WindowManager(ij.WindowManager) ConvexHull2d(uk.ac.sussex.gdsc.core.math.hull.ConvexHull2d) PeakResult(uk.ac.sussex.gdsc.smlm.results.PeakResult) PointRoi(ij.gui.PointRoi) Trace(uk.ac.sussex.gdsc.smlm.results.Trace) GenericDialog(ij.gui.GenericDialog) AbstractTableModel(javax.swing.table.AbstractTableModel) SortUtils(uk.ac.sussex.gdsc.core.utils.SortUtils) RounderUtils(uk.ac.sussex.gdsc.core.data.utils.RounderUtils) Overlay(ij.gui.Overlay) Files(java.nio.file.Files) BufferedWriter(java.io.BufferedWriter) Window(java.awt.Window) IOException(java.io.IOException) JScrollPane(javax.swing.JScrollPane) RoiListener(ij.gui.RoiListener) Paths(java.nio.file.Paths) ConcurrentMonoStack(uk.ac.sussex.gdsc.core.utils.concurrent.ConcurrentMonoStack) ListSelectionListener(javax.swing.event.ListSelectionListener) TIntArrayList(gnu.trove.list.array.TIntArrayList) IdentityTypeConverter(uk.ac.sussex.gdsc.core.data.utils.IdentityTypeConverter) Point(java.awt.Point) CoordinatePredicateUtils(uk.ac.sussex.gdsc.core.ij.roi.CoordinatePredicateUtils) ResultsImageSettings(uk.ac.sussex.gdsc.smlm.data.config.ResultsProtos.ResultsImageSettings) ImageJPluginLoggerHelper(uk.ac.sussex.gdsc.core.ij.ImageJPluginLoggerHelper) LocalCollectors(uk.ac.sussex.gdsc.core.utils.LocalCollectors) ImageJImagePeakResults(uk.ac.sussex.gdsc.smlm.ij.results.ImageJImagePeakResults) NonBlockingExtendedGenericDialog(uk.ac.sussex.gdsc.core.ij.gui.NonBlockingExtendedGenericDialog) ScreenDimensionHelper(uk.ac.sussex.gdsc.core.ij.gui.ScreenDimensionHelper) PlotWindow(ij.gui.PlotWindow) ListSelectionEvent(javax.swing.event.ListSelectionEvent) SettingsManager(uk.ac.sussex.gdsc.smlm.ij.settings.SettingsManager) JMenuBar(javax.swing.JMenuBar) CoordinatePredicate(uk.ac.sussex.gdsc.core.ij.roi.CoordinatePredicate) ExtendedGenericDialog(uk.ac.sussex.gdsc.core.ij.gui.ExtendedGenericDialog) PeakResultsList(uk.ac.sussex.gdsc.smlm.results.PeakResultsList) JMenu(javax.swing.JMenu) TIntIntHashMap(gnu.trove.map.hash.TIntIntHashMap) OffsetPointRoi(uk.ac.sussex.gdsc.core.ij.gui.OffsetPointRoi) WindowEvent(java.awt.event.WindowEvent) DoubleStream(java.util.stream.DoubleStream) Objects(java.util.Objects) List(java.util.List) SimpleArrayUtils(uk.ac.sussex.gdsc.core.utils.SimpleArrayUtils) JTable(javax.swing.JTable) LUT(ij.process.LUT) TypeConverter(uk.ac.sussex.gdsc.core.data.utils.TypeConverter) Roi(ij.gui.Roi) Rectangle(java.awt.Rectangle) WindowOrganiser(uk.ac.sussex.gdsc.core.ij.plugin.WindowOrganiser) AtomicReference(java.util.concurrent.atomic.AtomicReference) SwingConstants(javax.swing.SwingConstants) TextField(java.awt.TextField) Level(java.util.logging.Level) AWTEvent(java.awt.AWTEvent) BiPredicate(java.util.function.BiPredicate) SwingUtilities(javax.swing.SwingUtilities) JMenuItem(javax.swing.JMenuItem) ImagePeakResultsFactory(uk.ac.sussex.gdsc.smlm.ij.results.ImagePeakResultsFactory) UnitHelper(uk.ac.sussex.gdsc.smlm.data.config.UnitHelper) ExecutorService(java.util.concurrent.ExecutorService) LutColour(uk.ac.sussex.gdsc.core.ij.process.LutHelper.LutColour) ActionEvent(java.awt.event.ActionEvent) Rounder(uk.ac.sussex.gdsc.core.data.utils.Rounder) TimeUnit(uk.ac.sussex.gdsc.smlm.data.config.UnitProtos.TimeUnit) Consumer(java.util.function.Consumer) Counter(uk.ac.sussex.gdsc.smlm.results.count.Counter) ImageJUtils(uk.ac.sussex.gdsc.core.ij.ImageJUtils) TableColumnAdjuster(uk.ac.sussex.gdsc.smlm.ij.gui.TableColumnAdjuster) IJ(ij.IJ) DoublePredicate(java.util.function.DoublePredicate) Collections(java.util.Collections) LocalList(uk.ac.sussex.gdsc.core.utils.LocalList) Rectangle2D(java.awt.geom.Rectangle2D) PolygonRoi(ij.gui.PolygonRoi) PointRoi(ij.gui.PointRoi) OffsetPointRoi(uk.ac.sussex.gdsc.core.ij.gui.OffsetPointRoi) Roi(ij.gui.Roi) RoiManager(ij.plugin.frame.RoiManager) PeakResult(uk.ac.sussex.gdsc.smlm.results.PeakResult) Trace(uk.ac.sussex.gdsc.smlm.results.Trace) LocalList(uk.ac.sussex.gdsc.core.utils.LocalList) FrameCounter(uk.ac.sussex.gdsc.smlm.results.count.FrameCounter) Counter(uk.ac.sussex.gdsc.smlm.results.count.Counter) GenericDialog(ij.gui.GenericDialog) NonBlockingExtendedGenericDialog(uk.ac.sussex.gdsc.core.ij.gui.NonBlockingExtendedGenericDialog) ExtendedGenericDialog(uk.ac.sussex.gdsc.core.ij.gui.ExtendedGenericDialog) TcPalmAnalysisSettings(uk.ac.sussex.gdsc.smlm.ij.settings.GUIProtos.TcPalmAnalysisSettings) BiPredicate(java.util.function.BiPredicate)

Example 17 with Plot

use of ij.gui.Plot in project GDSC-SMLM by aherbert.

the class TcPalmAnalysis method runBurstPlotSelection.

/**
 * Select the activation bursts on the cumulative activations plot. Also stores the bursts in the
 * class property for future plot updates with the same selection.
 *
 * <p>This is synchronized so that the table selection events do not clash with the background
 * analysis jobs.
 *
 * @param bursts the bursts
 */
private synchronized void runBurstPlotSelection(LocalList<int[]> bursts) {
    this.bursts = bursts;
    final Plot plot = activationsPlotData.plot;
    plot.restorePlotObjects();
    if (!bursts.isEmpty()) {
        final int[] plotFrames = activationsPlotData.data.plotFrames;
        final int[] plotCounts = activationsPlotData.data.plotCounts;
        // For each cluster add to the plot.
        final TIntArrayList tmpFrames = new TIntArrayList();
        final TIntArrayList tmpCounts = new TIntArrayList();
        for (int i = 0; i < bursts.size(); i++) {
            // Find the start and end points on the plotted data.
            final int[] range = bursts.unsafeGet(i);
            final int is = Arrays.binarySearch(plotFrames, range[0]);
            final int ie = Arrays.binarySearch(plotFrames, range[1]);
            // Pad the line with zeros at the end
            tmpFrames.resetQuick();
            tmpCounts.resetQuick();
            int[] frames = Arrays.copyOfRange(plotFrames, is, ie + 1);
            tmpFrames.add(frames[0]);
            tmpFrames.add(frames);
            tmpFrames.add(frames[frames.length - 1]);
            tmpCounts.add(0);
            int[] counts = Arrays.copyOfRange(plotCounts, is, ie + 1);
            tmpCounts.add(counts);
            tmpCounts.add(0);
            frames = tmpFrames.toArray();
            counts = tmpCounts.toArray();
            // Add to the plot.
            plot.setColor(colourMap.getColour(i));
            plot.addPoints(activationsPlotData.timeConverter.apply(SimpleArrayUtils.toFloat(frames)), SimpleArrayUtils.toFloat(counts), Plot.LINE);
        }
    }
    plot.updateImage();
}
Also used : Plot(ij.gui.Plot) TIntArrayList(gnu.trove.list.array.TIntArrayList) Point(java.awt.Point)

Example 18 with Plot

use of ij.gui.Plot in project GDSC-SMLM by aherbert.

the class PulseActivationAnalysis method runCrosstalkAnalysis.

private void runCrosstalkAnalysis() {
    if (!showCrossTalkAnalysisDialog()) {
        return;
    }
    final double[] crosstalk = computeCrosstalk(counts, settings.targetChannel - 1);
    // Store the cross talk.
    // Crosstalk from M into N is defined as the number of times the molecule that should be
    // activated by a pulse from channel M is activated by a pulse from channel N.
    // targetChannel = M
    // activationChannel = N
    int index1;
    int index2 = -1;
    if (settings.channels == 2) {
        if (settings.targetChannel == 1) {
            index1 = setCrosstalk(Settings.C12, crosstalk[1]);
        } else {
            index1 = setCrosstalk(Settings.C21, crosstalk[0]);
        }
    // 3-channel
    } else if (settings.targetChannel == 1) {
        index1 = setCrosstalk(Settings.C12, crosstalk[1]);
        index2 = setCrosstalk(Settings.C13, crosstalk[2]);
    } else if (settings.targetChannel == 2) {
        index1 = setCrosstalk(Settings.C21, crosstalk[0]);
        index2 = setCrosstalk(Settings.C23, crosstalk[2]);
    } else {
        index1 = setCrosstalk(Settings.C31, crosstalk[0]);
        index2 = setCrosstalk(Settings.C32, crosstalk[1]);
    }
    // Show fraction activations histogram. So we have to set the sum to 1
    final double sum = MathUtils.sum(crosstalk);
    for (int i = 0; i < crosstalk.length; i++) {
        crosstalk[i] /= sum;
    }
    // Plot a histogram
    final double[] x = SimpleArrayUtils.newArray(settings.channels, 1.0, 1);
    final double[] y = crosstalk;
    final Plot plot = new Plot(title, "Channel", "Fraction activations");
    plot.setLimits(0, settings.channels + 1.0, 0, 1);
    plot.setXMinorTicks(false);
    plot.addPoints(x, y, Plot.BAR);
    String label = String.format("Crosstalk %s = %s", Settings.ctNames[index1], MathUtils.round(settings.ct[index1]));
    if (index2 > -1) {
        label += String.format(", %s = %s", Settings.ctNames[index2], MathUtils.round(settings.ct[index2]));
    }
    plot.addLabel(0, 0, label);
    ImageJUtils.display(title, plot);
}
Also used : Plot(ij.gui.Plot)

Example 19 with Plot

use of ij.gui.Plot in project GDSC-SMLM by aherbert.

the class SpotFinderPreview method run.

private void run(ImageProcessor ip, MaximaSpotFilter filter) {
    if (refreshing) {
        return;
    }
    currentSlice = imp.getCurrentSlice();
    final Rectangle bounds = ip.getRoi();
    // Crop to the ROI
    FloatProcessor fp = ip.crop().toFloat(0, null);
    float[] data = (float[]) fp.getPixels();
    final int width = fp.getWidth();
    final int height = fp.getHeight();
    // Store the mean bias and gain of the region data.
    // This is used to correctly overlay the filtered data on the original image.
    double bias = 0;
    double gain = 1;
    boolean adjust = false;
    // Set weights
    final CameraModel cameraModel = fitConfig.getCameraModel();
    if (!(cameraModel instanceof FakePerPixelCameraModel)) {
        // This should be done on the normalised data
        final float[] w = cameraModel.getNormalisedWeights(bounds);
        filter.setWeights(w, width, height);
        data = data.clone();
        if (data.length < ip.getPixelCount()) {
            adjust = true;
            bias = MathUtils.sum(cameraModel.getBias(bounds)) / data.length;
            gain = MathUtils.sum(cameraModel.getGain(bounds)) / data.length;
        }
        cameraModel.removeBiasAndGain(bounds, data);
    }
    final Spot[] spots = filter.rank(data, width, height);
    data = filter.getPreprocessedData();
    final int size = spots.length;
    if (topNScrollBar != null) {
        topNScrollBar.setMaximum(size);
        selectScrollBar.setMaximum(size);
    }
    fp = new FloatProcessor(width, height, data);
    final FloatProcessor out = new FloatProcessor(ip.getWidth(), ip.getHeight());
    out.copyBits(ip, 0, 0, Blitter.COPY);
    if (adjust) {
        fp.multiply(gain);
        fp.add(bias);
    }
    out.insert(fp, bounds.x, bounds.y);
    final double min = fp.getMin();
    final double max = fp.getMax();
    out.setMinAndMax(min, max);
    final Overlay o = new Overlay();
    o.add(new ImageRoi(0, 0, out));
    if (label != null) {
        // Get results for frame
        final Coordinate[] actual = ResultsMatchCalculator.getCoordinates(actualCoordinates, imp.getCurrentSlice());
        final Coordinate[] predicted = new Coordinate[size];
        for (int i = 0; i < size; i++) {
            predicted[i] = new BasePoint(spots[i].x + bounds.x, spots[i].y + bounds.y);
        }
        // Compute assignments
        final LocalList<FractionalAssignment> fractionalAssignments = new LocalList<>(3 * predicted.length);
        final double matchDistance = settings.distance * fitConfig.getInitialPeakStdDev();
        final RampedScore score = RampedScore.of(matchDistance, matchDistance * settings.lowerDistance / 100, false);
        final double dmin = matchDistance * matchDistance;
        final int nActual = actual.length;
        final int nPredicted = predicted.length;
        for (int j = 0; j < nPredicted; j++) {
            // Centre in the middle of the pixel
            final float x = predicted[j].getX() + 0.5f;
            final float y = predicted[j].getY() + 0.5f;
            // Any spots that match
            for (int i = 0; i < nActual; i++) {
                final double dx = (x - actual[i].getX());
                final double dy = (y - actual[i].getY());
                final double d2 = dx * dx + dy * dy;
                if (d2 <= dmin) {
                    final double d = Math.sqrt(d2);
                    final double s = score.score(d);
                    if (s == 0) {
                        continue;
                    }
                    double distance = 1 - s;
                    if (distance == 0) {
                        // In the case of a match below the distance thresholds
                        // the distance will be 0. To distinguish between candidates all below
                        // the thresholds just take the closest.
                        // We know d2 is below dmin so we subtract the delta.
                        distance -= (dmin - d2);
                    }
                    // Store the match
                    fractionalAssignments.add(new ImmutableFractionalAssignment(i, j, distance, s));
                }
            }
        }
        final FractionalAssignment[] assignments = fractionalAssignments.toArray(new FractionalAssignment[0]);
        // Compute matches
        final RankedScoreCalculator calc = RankedScoreCalculator.create(assignments, nActual - 1, nPredicted - 1);
        final boolean save = settings.showTP || settings.showFP;
        final double[] calcScore = calc.score(nPredicted, settings.multipleMatches, save);
        final ClassificationResult result = RankedScoreCalculator.toClassificationResult(calcScore, nActual);
        // Compute AUC and max jaccard (and plot)
        final double[][] curve = RankedScoreCalculator.getPrecisionRecallCurve(assignments, nActual, nPredicted);
        final double[] precision = curve[0];
        final double[] recall = curve[1];
        final double[] jaccard = curve[2];
        final double auc = AucCalculator.auc(precision, recall);
        // Show scores
        final String scoreLabel = String.format("Slice=%d, AUC=%s, R=%s, Max J=%s", imp.getCurrentSlice(), MathUtils.rounded(auc), MathUtils.rounded(result.getRecall()), MathUtils.rounded(MathUtils.maxDefault(0, jaccard)));
        setLabel(scoreLabel);
        // Plot
        String title = TITLE + " Performance";
        Plot plot = new Plot(title, "Spot Rank", "");
        final double[] rank = SimpleArrayUtils.newArray(precision.length, 0, 1.0);
        plot.setLimits(0, nPredicted, 0, 1.05);
        plot.setColor(Color.blue);
        plot.addPoints(rank, precision, Plot.LINE);
        plot.setColor(Color.red);
        plot.addPoints(rank, recall, Plot.LINE);
        plot.setColor(Color.black);
        plot.addPoints(rank, jaccard, Plot.LINE);
        plot.setColor(Color.black);
        plot.addLabel(0, 0, scoreLabel);
        final WindowOrganiser windowOrganiser = new WindowOrganiser();
        ImageJUtils.display(title, plot, 0, windowOrganiser);
        title = TITLE + " Precision-Recall";
        plot = new Plot(title, "Recall", "Precision");
        plot.setLimits(0, 1, 0, 1.05);
        plot.setColor(Color.red);
        plot.addPoints(recall, precision, Plot.LINE);
        plot.drawLine(recall[recall.length - 1], precision[recall.length - 1], recall[recall.length - 1], 0);
        plot.setColor(Color.black);
        plot.addLabel(0, 0, scoreLabel);
        ImageJUtils.display(title, plot, 0, windowOrganiser);
        windowOrganiser.tile();
        // Create Rois for TP and FP
        if (save) {
            final double[] matchScore = RankedScoreCalculator.getMatchScore(calc.getScoredAssignments(), nPredicted);
            int matches = 0;
            for (int i = 0; i < matchScore.length; i++) {
                if (matchScore[i] != 0) {
                    matches++;
                }
            }
            if (settings.showTP) {
                final float[] x = new float[matches];
                final float[] y = new float[x.length];
                int count = 0;
                for (int i = 0; i < matchScore.length; i++) {
                    if (matchScore[i] != 0) {
                        final BasePoint p = (BasePoint) predicted[i];
                        x[count] = p.getX() + 0.5f;
                        y[count] = p.getY() + 0.5f;
                        count++;
                    }
                }
                addRoi(0, o, x, y, count, Color.green);
            }
            if (settings.showFP) {
                final float[] x = new float[nPredicted - matches];
                final float[] y = new float[x.length];
                int count = 0;
                for (int i = 0; i < matchScore.length; i++) {
                    if (matchScore[i] == 0) {
                        final BasePoint p = (BasePoint) predicted[i];
                        x[count] = p.getX() + 0.5f;
                        y[count] = p.getY() + 0.5f;
                        count++;
                    }
                }
                addRoi(0, o, x, y, count, Color.red);
            }
        }
    } else {
        final WindowOrganiser wo = new WindowOrganiser();
        // Option to show the number of neighbours within a set pixel box radius
        final int[] count = spotFilterHelper.countNeighbours(spots, width, height, settings.neighbourRadius);
        // Show as histogram the totals...
        new HistogramPlotBuilder(TITLE, StoredData.create(count), "Neighbours").setIntegerBins(true).setPlotLabel("Radius = " + settings.neighbourRadius).show(wo);
        // TODO - Draw n=0, n=1 on the image overlay
        final LUT lut = LutHelper.createLut(LutColour.FIRE_LIGHT);
        // These are copied by the ROI
        final float[] x = new float[1];
        final float[] y = new float[1];
        // Plot the intensity
        final double[] intensity = new double[size];
        final double[] rank = SimpleArrayUtils.newArray(size, 1, 1.0);
        final int top = (settings.topN > 0) ? settings.topN : size;
        final int size_1 = size - 1;
        for (int i = 0; i < size; i++) {
            intensity[i] = spots[i].intensity;
            if (i < top) {
                x[0] = spots[i].x + bounds.x + 0.5f;
                y[0] = spots[i].y + bounds.y + 0.5f;
                final Color c = LutHelper.getColour(lut, size_1 - i, size);
                addRoi(0, o, x, y, 1, c, 2, 1);
            }
        }
        final String title = TITLE + " Intensity";
        final Plot plot = new Plot(title, "Rank", "Intensity");
        plot.setColor(Color.blue);
        plot.addPoints(rank, intensity, Plot.LINE);
        if (settings.topN > 0 && settings.topN < size) {
            plot.setColor(Color.magenta);
            plot.drawLine(settings.topN, 0, settings.topN, intensity[settings.topN - 1]);
        }
        if (settings.select > 0 && settings.select < size) {
            plot.setColor(Color.yellow);
            final int index = settings.select - 1;
            final double in = intensity[index];
            plot.drawLine(settings.select, 0, settings.select, in);
            x[0] = spots[index].x + bounds.x + 0.5f;
            y[0] = spots[index].y + bounds.y + 0.5f;
            final Color c = LutHelper.getColour(lut, size_1 - settings.select, size);
            addRoi(0, o, x, y, 1, c, 3, 3);
            plot.setColor(Color.black);
            plot.addLabel(0, 0, "Selected spot intensity = " + MathUtils.rounded(in));
        }
        ImageJUtils.display(title, plot, 0, wo);
        wo.tile();
    }
    imp.setOverlay(o);
}
Also used : FakePerPixelCameraModel(uk.ac.sussex.gdsc.smlm.model.camera.FakePerPixelCameraModel) CameraModel(uk.ac.sussex.gdsc.smlm.model.camera.CameraModel) Spot(uk.ac.sussex.gdsc.smlm.filters.Spot) BasePoint(uk.ac.sussex.gdsc.core.match.BasePoint) Rectangle(java.awt.Rectangle) HistogramPlotBuilder(uk.ac.sussex.gdsc.core.ij.HistogramPlot.HistogramPlotBuilder) RankedScoreCalculator(uk.ac.sussex.gdsc.core.match.RankedScoreCalculator) ImageRoi(ij.gui.ImageRoi) LocalList(uk.ac.sussex.gdsc.core.utils.LocalList) FractionalAssignment(uk.ac.sussex.gdsc.core.match.FractionalAssignment) ImmutableFractionalAssignment(uk.ac.sussex.gdsc.core.match.ImmutableFractionalAssignment) ImmutableFractionalAssignment(uk.ac.sussex.gdsc.core.match.ImmutableFractionalAssignment) Overlay(ij.gui.Overlay) FloatProcessor(ij.process.FloatProcessor) Plot(ij.gui.Plot) Color(java.awt.Color) ClassificationResult(uk.ac.sussex.gdsc.core.match.ClassificationResult) LUT(ij.process.LUT) WindowOrganiser(uk.ac.sussex.gdsc.core.ij.plugin.WindowOrganiser) BasePoint(uk.ac.sussex.gdsc.core.match.BasePoint) FakePerPixelCameraModel(uk.ac.sussex.gdsc.smlm.model.camera.FakePerPixelCameraModel) Coordinate(uk.ac.sussex.gdsc.core.match.Coordinate) RampedScore(uk.ac.sussex.gdsc.core.utils.RampedScore)

Example 20 with Plot

use of ij.gui.Plot in project GDSC-SMLM by aherbert.

the class PsfCreator method runUsingFitting.

private void runUsingFitting() {
    if (!showFittingDialog()) {
        return;
    }
    if (!loadConfiguration()) {
        return;
    }
    final BasePoint[] spots = getSpots(0, true);
    if (spots.length == 0) {
        IJ.error(TITLE, "No spots without neighbours within " + (boxRadius * 2) + "px");
        return;
    }
    final ImageStack stack = getImageStack();
    final int width = imp.getWidth();
    final int height = imp.getHeight();
    final int currentSlice = imp.getSlice();
    // Adjust settings for a single maxima
    config.setIncludeNeighbours(false);
    final ArrayList<double[]> centres = new ArrayList<>(spots.length);
    final int iterations = 1;
    final LoessInterpolator loess = new LoessInterpolator(settings.getSmoothing(), iterations);
    // TODO - The fitting routine may not produce many points. In this instance the LOESS
    // interpolator
    // fails to smooth the data very well. A higher bandwidth helps this but perhaps
    // try a different smoothing method.
    // For each spot
    ImageJUtils.log(TITLE + ": " + imp.getTitle());
    ImageJUtils.log("Finding spot locations...");
    ImageJUtils.log("  %d spot%s without neighbours within %dpx", spots.length, ((spots.length == 1) ? "" : "s"), (boxRadius * 2));
    final StoredDataStatistics averageSd = new StoredDataStatistics();
    final StoredDataStatistics averageA = new StoredDataStatistics();
    final Statistics averageRange = new Statistics();
    final MemoryPeakResults allResults = new MemoryPeakResults();
    allResults.setCalibration(fitConfig.getCalibration());
    allResults.setPsf(fitConfig.getPsf());
    allResults.setName(TITLE);
    allResults.setBounds(new Rectangle(0, 0, width, height));
    MemoryPeakResults.addResults(allResults);
    for (int n = 1; n <= spots.length; n++) {
        final BasePoint spot = spots[n - 1];
        final int x = (int) spot.getX();
        final int y = (int) spot.getY();
        final MemoryPeakResults results = fitSpot(stack, width, height, x, y);
        allResults.add(results);
        if (results.size() < 5) {
            ImageJUtils.log("  Spot %d: Not enough fit results %d", n, results.size());
            continue;
        }
        // Get the results for the spot centre and width
        final double[] z = new double[results.size()];
        final double[] xCoord = new double[z.length];
        final double[] yCoord = new double[z.length];
        final double[] sd;
        final double[] a;
        final Counter counter = new Counter();
        // We have fit the results so they will be in the preferred units
        results.forEach(new PeakResultProcedure() {

            @Override
            public void execute(PeakResult peak) {
                final int i = counter.getAndIncrement();
                z[i] = peak.getFrame();
                xCoord[i] = peak.getXPosition() - x;
                yCoord[i] = peak.getYPosition() - y;
            }
        });
        final WidthResultProcedure wp = new WidthResultProcedure(results, DistanceUnit.PIXEL);
        wp.getW();
        sd = SimpleArrayUtils.toDouble(wp.wx);
        final HeightResultProcedure hp = new HeightResultProcedure(results, IntensityUnit.COUNT);
        hp.getH();
        a = SimpleArrayUtils.toDouble(hp.heights);
        // Smooth the amplitude plot
        final double[] smoothA = loess.smooth(z, a);
        // Find the maximum amplitude
        int maximumIndex = findMaximumIndex(smoothA);
        // Find the range at a fraction of the max. This is smoothed to find the X/Y centre
        int start = 0;
        int stop = smoothA.length - 1;
        final double limit = smoothA[maximumIndex] * settings.getAmplitudeFraction();
        for (int j = 0; j < smoothA.length; j++) {
            if (smoothA[j] > limit) {
                start = j;
                break;
            }
        }
        for (int j = smoothA.length; j-- > 0; ) {
            if (smoothA[j] > limit) {
                stop = j;
                break;
            }
        }
        averageRange.add(stop - start + 1);
        // Extract xy centre coords and smooth
        double[] smoothX = new double[stop - start + 1];
        double[] smoothY = new double[smoothX.length];
        double[] smoothSd = new double[smoothX.length];
        final double[] newZ = new double[smoothX.length];
        for (int j = start, k = 0; j <= stop; j++, k++) {
            smoothX[k] = xCoord[j];
            smoothY[k] = yCoord[j];
            smoothSd[k] = sd[j];
            newZ[k] = z[j];
        }
        smoothX = loess.smooth(newZ, smoothX);
        smoothY = loess.smooth(newZ, smoothY);
        smoothSd = loess.smooth(newZ, smoothSd);
        // Since the amplitude is not very consistent move from this peak to the
        // lowest width which is the in-focus spot.
        maximumIndex = findMinimumIndex(smoothSd, maximumIndex - start);
        // Find the centre at the amplitude peak
        final double cx = smoothX[maximumIndex] + x;
        final double cy = smoothY[maximumIndex] + y;
        int cz = (int) newZ[maximumIndex];
        double csd = smoothSd[maximumIndex];
        double ca = smoothA[maximumIndex + start];
        // The average should weight the SD using the signal for each spot
        averageSd.add(smoothSd[maximumIndex]);
        averageA.add(ca);
        if (ignoreSpot(n, z, a, smoothA, xCoord, yCoord, sd, newZ, smoothX, smoothY, smoothSd, cx, cy, cz, csd)) {
            ImageJUtils.log("  Spot %d was ignored", n);
            continue;
        }
        // Store result - it may have been moved interactively
        maximumIndex += this.slice - cz;
        cz = (int) newZ[maximumIndex];
        csd = smoothSd[maximumIndex];
        ca = smoothA[maximumIndex + start];
        ImageJUtils.log("  Spot %d => x=%.2f, y=%.2f, z=%d, sd=%.2f, A=%.2f", n, cx, cy, cz, csd, ca);
        centres.add(new double[] { cx, cy, cz, csd, n });
    }
    if (settings.getInteractiveMode()) {
        imp.setSlice(currentSlice);
        imp.setOverlay(null);
        // Hide the amplitude and spot plots
        ImageJUtils.hide(TITLE_AMPLITUDE);
        ImageJUtils.hide(TITLE_PSF_PARAMETERS);
    }
    if (centres.isEmpty()) {
        final String msg = "No suitable spots could be identified";
        ImageJUtils.log(msg);
        IJ.error(TITLE, msg);
        return;
    }
    // Find the limits of the z-centre
    int minz = (int) centres.get(0)[2];
    int maxz = minz;
    for (final double[] centre : centres) {
        if (minz > centre[2]) {
            minz = (int) centre[2];
        } else if (maxz < centre[2]) {
            maxz = (int) centre[2];
        }
    }
    IJ.showStatus("Creating PSF image");
    // Create a stack that can hold all the data.
    final ImageStack psf = createStack(stack, minz, maxz, settings.getMagnification());
    // For each spot
    final Statistics stats = new Statistics();
    boolean ok = true;
    for (int i = 0; ok && i < centres.size(); i++) {
        final double increment = 1.0 / (stack.getSize() * centres.size());
        setProgress((double) i / centres.size());
        final double[] centre = centres.get(i);
        // Extract the spot
        final float[][] spot = new float[stack.getSize()][];
        Rectangle regionBounds = null;
        for (int slice = 1; slice <= stack.getSize(); slice++) {
            final ImageExtractor ie = ImageExtractor.wrap((float[]) stack.getPixels(slice), width, height);
            if (regionBounds == null) {
                regionBounds = ie.getBoxRegionBounds((int) centre[0], (int) centre[1], boxRadius);
            }
            spot[slice - 1] = ie.crop(regionBounds);
        }
        if (regionBounds == null) {
            // Empty stack
            continue;
        }
        final int n = (int) centre[4];
        final float b = getBackground(n, spot);
        if (!subtractBackgroundAndWindow(spot, b, regionBounds.width, regionBounds.height, centre, loess)) {
            ImageJUtils.log("  Spot %d was ignored", n);
            continue;
        }
        stats.add(b);
        // Adjust the centre using the crop
        centre[0] -= regionBounds.x;
        centre[1] -= regionBounds.y;
        // This takes a long time so this should track progress
        ok = addToPsf(maxz, settings.getMagnification(), psf, centre, spot, regionBounds, increment, settings.getCentreEachSlice());
    }
    if (settings.getInteractiveMode()) {
        ImageJUtils.hide(TITLE_INTENSITY);
    }
    IJ.showProgress(1);
    if (!ok || stats.getN() == 0) {
        return;
    }
    final double avSd = getAverage(averageSd, averageA, 2);
    ImageJUtils.log("  Average background = %.2f, Av. SD = %s px", stats.getMean(), MathUtils.rounded(avSd, 4));
    normalise(psf, maxz, avSd * settings.getMagnification(), false);
    IJ.showProgress(1);
    psfImp = ImageJUtils.display(TITLE_PSF, psf);
    psfImp.setSlice(maxz);
    psfImp.resetDisplayRange();
    psfImp.updateAndDraw();
    final double[][] fitCom = new double[2][psf.getSize()];
    Arrays.fill(fitCom[0], Double.NaN);
    Arrays.fill(fitCom[1], Double.NaN);
    final double fittedSd = fitPsf(psf, loess, maxz, averageRange.getMean(), fitCom);
    // Compute the drift in the PSF:
    // - Use fitted centre if available; otherwise find CoM for each frame
    // - express relative to the average centre
    final double[][] com = calculateCentreOfMass(psf, fitCom, nmPerPixel / settings.getMagnification());
    final double[] slice = SimpleArrayUtils.newArray(psf.getSize(), 1, 1.0);
    final String title = TITLE + " CoM Drift";
    final Plot plot = new Plot(title, "Slice", "Drift (nm)");
    plot.addLabel(0, 0, "Red = X; Blue = Y");
    // double[] limitsX = Maths.limits(com[0]);
    // double[] limitsY = Maths.limits(com[1]);
    final double[] limitsX = getLimits(com[0]);
    final double[] limitsY = getLimits(com[1]);
    plot.setLimits(1, psf.getSize(), Math.min(limitsX[0], limitsY[0]), Math.max(limitsX[1], limitsY[1]));
    plot.setColor(Color.red);
    plot.addPoints(slice, com[0], Plot.DOT);
    plot.addPoints(slice, loess.smooth(slice, com[0]), Plot.LINE);
    plot.setColor(Color.blue);
    plot.addPoints(slice, com[1], Plot.DOT);
    plot.addPoints(slice, loess.smooth(slice, com[1]), Plot.LINE);
    ImageJUtils.display(title, plot);
    // TODO - Redraw the PSF with drift correction applied.
    // This means that the final image should have no drift.
    // This is relevant when combining PSF images. It doesn't matter too much for simulations
    // unless the drift is large.
    // Add Image properties containing the PSF details
    final double fwhm = getFwhm(psf, maxz);
    psfImp.setProperty("Info", ImagePsfHelper.toString(ImagePsfHelper.create(maxz, nmPerPixel / settings.getMagnification(), settings.getNmPerSlice(), stats.getN(), fwhm, createNote())));
    ImageJUtils.log("%s : z-centre = %d, nm/Pixel = %s, nm/Slice = %s, %d images, " + "PSF SD = %s nm, FWHM = %s px\n", psfImp.getTitle(), maxz, MathUtils.rounded(nmPerPixel / settings.getMagnification(), 3), MathUtils.rounded(settings.getNmPerSlice(), 3), stats.getN(), MathUtils.rounded(fittedSd * nmPerPixel, 4), MathUtils.rounded(fwhm));
    createInteractivePlots(psf, maxz, nmPerPixel / settings.getMagnification(), fittedSd * nmPerPixel);
    IJ.showStatus("");
}
Also used : BasePoint(uk.ac.sussex.gdsc.core.match.BasePoint) ArrayList(java.util.ArrayList) Rectangle(java.awt.Rectangle) PeakResult(uk.ac.sussex.gdsc.smlm.results.PeakResult) LoessInterpolator(org.apache.commons.math3.analysis.interpolation.LoessInterpolator) Counter(uk.ac.sussex.gdsc.smlm.results.count.Counter) PeakResultProcedure(uk.ac.sussex.gdsc.smlm.results.procedures.PeakResultProcedure) MemoryPeakResults(uk.ac.sussex.gdsc.smlm.results.MemoryPeakResults) ImageExtractor(uk.ac.sussex.gdsc.core.utils.ImageExtractor) HeightResultProcedure(uk.ac.sussex.gdsc.smlm.results.procedures.HeightResultProcedure) ImageStack(ij.ImageStack) Plot(ij.gui.Plot) StoredDataStatistics(uk.ac.sussex.gdsc.core.utils.StoredDataStatistics) WidthResultProcedure(uk.ac.sussex.gdsc.smlm.results.procedures.WidthResultProcedure) DescriptiveStatistics(org.apache.commons.math3.stat.descriptive.DescriptiveStatistics) StoredDataStatistics(uk.ac.sussex.gdsc.core.utils.StoredDataStatistics) Statistics(uk.ac.sussex.gdsc.core.utils.Statistics) Point(java.awt.Point) BasePoint(uk.ac.sussex.gdsc.core.match.BasePoint)

Aggregations

Plot (ij.gui.Plot)89 HistogramPlot (uk.ac.sussex.gdsc.core.ij.HistogramPlot)20 Point (java.awt.Point)19 PlotWindow (ij.gui.PlotWindow)17 Color (java.awt.Color)13 WindowOrganiser (uk.ac.sussex.gdsc.core.ij.plugin.WindowOrganiser)13 HistogramPlotBuilder (uk.ac.sussex.gdsc.core.ij.HistogramPlot.HistogramPlotBuilder)12 BasePoint (uk.ac.sussex.gdsc.core.match.BasePoint)12 ExtendedGenericDialog (uk.ac.sussex.gdsc.core.ij.gui.ExtendedGenericDialog)11 MemoryPeakResults (uk.ac.sussex.gdsc.smlm.results.MemoryPeakResults)11 Rectangle (java.awt.Rectangle)9 ArrayList (java.util.ArrayList)9 GenericDialog (ij.gui.GenericDialog)8 NonBlockingExtendedGenericDialog (uk.ac.sussex.gdsc.core.ij.gui.NonBlockingExtendedGenericDialog)7 LocalList (uk.ac.sussex.gdsc.core.utils.LocalList)7 Statistics (uk.ac.sussex.gdsc.core.utils.Statistics)7 StoredData (uk.ac.sussex.gdsc.core.utils.StoredData)7 StoredDataStatistics (uk.ac.sussex.gdsc.core.utils.StoredDataStatistics)7 ImagePlus (ij.ImagePlus)6 TDoubleArrayList (gnu.trove.list.array.TDoubleArrayList)5