Search in sources :

Example 11 with WindowOrganiser

use of uk.ac.sussex.gdsc.core.ij.plugin.WindowOrganiser in project GDSC-SMLM by aherbert.

the class TcPalmAnalysis method reportAnalysis.

/**
 * Report statistics on the analysis results.
 *
 * @param settings the settings
 * @param clusters the clusters
 * @param calibration the data calibration
 */
private static void reportAnalysis(TcPalmAnalysisSettings settings, LocalList<ClusterData> clusters, DataCalibration calibration) {
    final WindowOrganiser wo = new WindowOrganiser();
    final Consumer<HistogramPlotBuilder> action = builder -> {
    /* noop. */
    };
    plotHistogram(settings.getShowSizeHistogram(), wo, clusters, "Size", c -> c.results.size(), null, action);
    plotHistogram(settings.getShowDurationHistogram(), wo, clusters, "Duration (" + calibration.getTimeUnitName() + ")", c -> calibration.timeConverter.convert(c.getDuration()), null, action);
    plotHistogram(settings.getShowAreaHistogram(), wo, clusters, "Area (" + calibration.getDistanceUnitName() + "^2)", c -> calibration.convertArea(c.getArea()), null, action);
    plotHistogram(settings.getShowDensityHistogram(), wo, clusters, "Density (" + calibration.getDistanceUnitName() + "^-2)", c -> c.results.size() / calibration.convertArea(c.getArea()), Double::isFinite, action);
    wo.tile();
}
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) HistogramPlotBuilder(uk.ac.sussex.gdsc.core.ij.HistogramPlot.HistogramPlotBuilder) WindowOrganiser(uk.ac.sussex.gdsc.core.ij.plugin.WindowOrganiser)

Example 12 with WindowOrganiser

use of uk.ac.sussex.gdsc.core.ij.plugin.WindowOrganiser in project GDSC-SMLM by aherbert.

the class TraceLengthAnalysis method run.

@Override
public void run(String arg) {
    SmlmUsageTracker.recordPlugin(this.getClass(), arg);
    if (MemoryPeakResults.isMemoryEmpty()) {
        IJ.error(TITLE, "No localisations in memory");
        return;
    }
    if (!showDialog()) {
        return;
    }
    // Load the results
    MemoryPeakResults results = ResultsManager.loadInputResults(settings.inputOption, false, null, null);
    if (MemoryPeakResults.isEmpty(results)) {
        IJ.error(TITLE, "No results could be loaded");
        return;
    }
    try {
        distanceConverter = results.getDistanceConverter(DistanceUnit.UM);
        timeConverter = results.getTimeConverter(TimeUnit.SECOND);
    } catch (final Exception ex) {
        IJ.error(TITLE, "Cannot convert units to um or seconds: " + ex.getMessage());
        return;
    }
    // Get the localisation error (4s^2) in raw units^2
    double precision = 0;
    try {
        final PrecisionResultProcedure p = new PrecisionResultProcedure(results);
        p.getPrecision();
        // Precision in nm using the median
        precision = new Percentile().evaluate(p.precisions, 50);
        // Convert from nm to um to raw units
        final double rawPrecision = distanceConverter.convertBack(precision / 1e3);
        // Get the localisation error (4s^2) in units^2
        error = 4 * rawPrecision * rawPrecision;
    } catch (final Exception ex) {
        ImageJUtils.log(TITLE + " - Unable to compute precision: " + ex.getMessage());
    }
    // Analyse the track lengths
    results = results.copy();
    results.sort(IdFramePeakResultComparator.INSTANCE);
    // Ensure the first result triggers an id change
    lastid = results.getFirst().getId() - 1;
    results.forEach(this::processTrackLength);
    // For the final track
    store();
    msds = msdList.toArray();
    lengths = lengthList.toArray();
    ids = idList.toArray();
    final int[] limits = MathUtils.limits(lengths);
    h1 = new int[limits[1] + 1];
    h2 = new int[h1.length];
    x1 = SimpleArrayUtils.newArray(h1.length, 0, 1f);
    y1 = new float[x1.length];
    y2 = new float[x1.length];
    // Sort by MSD
    final int[] indices = SimpleArrayUtils.natural(msds.length);
    SortUtils.sortIndices(indices, msds, false);
    final double[] msds2 = msds.clone();
    final int[] lengths2 = lengths.clone();
    final int[] ids2 = ids.clone();
    for (int i = 0; i < indices.length; i++) {
        msds[i] = msds2[indices[i]];
        lengths[i] = lengths2[indices[i]];
        ids[i] = ids2[indices[i]];
    }
    // Interactive analysis
    final NonBlockingExtendedGenericDialog gd = new NonBlockingExtendedGenericDialog(TITLE);
    ImageJUtils.addMessage(gd, "Split traces into fixed or moving using the track diffusion coefficient (D).\n" + "Localisation error has been subtracted from jumps (%s nm).", MathUtils.rounded(precision));
    final Statistics s = Statistics.create(msds);
    final double av = s.getMean();
    final String msg = String.format("Average D per track = %s um^2/s", MathUtils.rounded(av));
    gd.addMessage(msg);
    // Histogram the diffusion coefficients
    final WindowOrganiser wo = new WindowOrganiser();
    final HistogramPlot histogramPlot = new HistogramPlotBuilder("Trace diffusion coefficient", StoredData.create(msds), "D (um^2/s)").setRemoveOutliersOption(1).setPlotLabel(msg).build();
    histogramPlot.show(wo);
    final double[] xvalues = histogramPlot.getPlotXValues();
    final double min = xvalues[0];
    final double max = xvalues[xvalues.length - 1];
    // see if we can build a nice slider range from the histogram limits
    if (max - min < 5) {
        // Because sliders are used when the range is <5 and floating point
        gd.addSlider("D_threshold", min, max, settings.msdThreshold);
    } else {
        gd.addNumericField("D_threshold", settings.msdThreshold, 2, 6, "um^2/s");
    }
    gd.addCheckbox("Normalise", settings.normalise);
    gd.addDialogListener((gd1, event) -> {
        settings.msdThreshold = gd1.getNextNumber();
        settings.normalise = gd1.getNextBoolean();
        update();
        return true;
    });
    if (ImageJUtils.isShowGenericDialog()) {
        draw(wo);
        wo.tile();
    }
    gd.setOKLabel("Save datasets");
    gd.setCancelLabel("Close");
    gd.addHelp(HelpUrls.getUrl("trace-length-analysis"));
    gd.showDialog();
    if (gd.wasCanceled()) {
        return;
    }
    // Sort by ID
    final PeakResult[] list = results.toArray();
    Arrays.sort(list, IdFramePeakResultComparator.INSTANCE);
    createResults(results, "Fixed", 0, lastIndex, list);
    createResults(results, "Moving", lastIndex, msds.length, list);
}
Also used : Percentile(org.apache.commons.math3.stat.descriptive.rank.Percentile) NonBlockingExtendedGenericDialog(uk.ac.sussex.gdsc.core.ij.gui.NonBlockingExtendedGenericDialog) HistogramPlotBuilder(uk.ac.sussex.gdsc.core.ij.HistogramPlot.HistogramPlotBuilder) WindowOrganiser(uk.ac.sussex.gdsc.core.ij.plugin.WindowOrganiser) PrecisionResultProcedure(uk.ac.sussex.gdsc.smlm.results.procedures.PrecisionResultProcedure) Statistics(uk.ac.sussex.gdsc.core.utils.Statistics) PeakResult(uk.ac.sussex.gdsc.smlm.results.PeakResult) HistogramPlot(uk.ac.sussex.gdsc.core.ij.HistogramPlot) MemoryPeakResults(uk.ac.sussex.gdsc.smlm.results.MemoryPeakResults)

Example 13 with WindowOrganiser

use of uk.ac.sussex.gdsc.core.ij.plugin.WindowOrganiser in project GDSC-SMLM by aherbert.

the class TraceMolecules method summarise.

private void summarise(Consumer<String> output, Trace[] traces, int filtered, double distanceThreshold, double timeThreshold) {
    IJ.showStatus("Calculating summary ...");
    final Statistics[] stats = new Statistics[NAMES.length];
    for (int i = 0; i < stats.length; i++) {
        stats[i] = (settings.getShowHistograms() || settings.getSaveTraceData()) ? new StoredDataStatistics() : new Statistics();
    }
    int singles = 0;
    for (final Trace trace : traces) {
        final int nBlinks = trace.getBlinks() - 1;
        stats[BLINKS].add(nBlinks);
        final int[] onTimes = trace.getOnTimes();
        final int[] offTimes = trace.getOffTimes();
        double timeOn = 0;
        for (final int t : onTimes) {
            stats[T_ON].add(t * exposureTime);
            timeOn += t * exposureTime;
        }
        stats[TOTAL_T_ON].add(timeOn);
        if (offTimes != null) {
            double timeOff = 0;
            for (final int t : offTimes) {
                stats[T_OFF].add(t * exposureTime);
                timeOff += t * exposureTime;
            }
            stats[TOTAL_T_OFF].add(timeOff);
        }
        final double signal = trace.getSignal() / results.getGain();
        stats[TOTAL_SIGNAL].add(signal);
        stats[SIGNAL_PER_FRAME].add(signal / trace.size());
        stats[DWELL_TIME].add((trace.getTail().getEndFrame() - trace.getHead().getFrame() + 1) * exposureTime);
        if (trace.size() == 1) {
            singles++;
        }
    }
    // Add to the summary table
    final StringBuilder sb = new StringBuilder();
    sb.append(results.getName()).append('\t');
    sb.append(outputName.equals("Cluster") ? getClusteringAlgorithm(settings.getClusteringAlgorithm()) : getTraceMode(settings.getTraceMode())).append('\t');
    sb.append(MathUtils.rounded(getExposureTimeInMilliSeconds(), 3)).append('\t');
    sb.append(MathUtils.rounded(distanceThreshold, 3)).append('\t');
    sb.append(MathUtils.rounded(timeThreshold, 3));
    if (settings.getSplitPulses()) {
        sb.append(" *");
    }
    sb.append('\t');
    sb.append(convertSecondsToFrames(timeThreshold)).append('\t');
    sb.append(traces.length).append('\t');
    sb.append(filtered).append('\t');
    sb.append(singles).append('\t');
    sb.append(traces.length - singles).append('\t');
    for (int i = 0; i < stats.length; i++) {
        sb.append(MathUtils.rounded(stats[i].getMean(), 3)).append('\t');
    }
    if (java.awt.GraphicsEnvironment.isHeadless()) {
        IJ.log(sb.toString());
        return;
    }
    output.accept(sb.toString());
    if (settings.getShowHistograms()) {
        IJ.showStatus("Calculating histograms ...");
        final WindowOrganiser windowOrganiser = new WindowOrganiser();
        final HistogramPlotBuilder builder = new HistogramPlotBuilder(pluginTitle).setNumberOfBins(settings.getHistogramBins());
        for (int i = 0; i < NAMES.length; i++) {
            if (pluginSettings.displayHistograms[i]) {
                builder.setData((StoredDataStatistics) stats[i]).setName(NAMES[i]).setIntegerBins(integerDisplay[i]).setRemoveOutliersOption((settings.getRemoveOutliers() || alwaysRemoveOutliers[i]) ? 2 : 0).show(windowOrganiser);
            }
        }
        windowOrganiser.tile();
    }
    if (settings.getSaveTraceData()) {
        saveTraceData(stats);
    }
    IJ.showStatus("");
}
Also used : Trace(uk.ac.sussex.gdsc.smlm.results.Trace) StoredDataStatistics(uk.ac.sussex.gdsc.core.utils.StoredDataStatistics) HistogramPlotBuilder(uk.ac.sussex.gdsc.core.ij.HistogramPlot.HistogramPlotBuilder) WindowOrganiser(uk.ac.sussex.gdsc.core.ij.plugin.WindowOrganiser) StoredDataStatistics(uk.ac.sussex.gdsc.core.utils.StoredDataStatistics) Statistics(uk.ac.sussex.gdsc.core.utils.Statistics) SummaryStatistics(org.apache.commons.math3.stat.descriptive.SummaryStatistics) ClusterPoint(uk.ac.sussex.gdsc.core.clustering.ClusterPoint)

Example 14 with WindowOrganiser

use of uk.ac.sussex.gdsc.core.ij.plugin.WindowOrganiser in project GDSC-SMLM by aherbert.

the class SpotAnalysis method showSpot.

private static ImagePlus showSpot(String title, ImageStack spot) {
    final WindowOrganiser windowOrganiser = new WindowOrganiser();
    final ImagePlus imp = ImageJUtils.display(title, spot, windowOrganiser);
    if (windowOrganiser.isNotEmpty() || imp.getWindow().getCanvas().getMagnification() == 1) {
        for (int i = 9; i-- > 0; ) {
            imp.getWindow().getCanvas().zoomIn(imp.getWidth() / 2, imp.getHeight() / 2);
        }
    }
    return imp;
}
Also used : WindowOrganiser(uk.ac.sussex.gdsc.core.ij.plugin.WindowOrganiser) ImagePlus(ij.ImagePlus) Point(java.awt.Point)

Example 15 with WindowOrganiser

use of uk.ac.sussex.gdsc.core.ij.plugin.WindowOrganiser in project GDSC-SMLM by aherbert.

the class TrackPopulationAnalysis method run.

@Override
public void run(String arg) {
    SmlmUsageTracker.recordPlugin(this.getClass(), arg);
    if (MemoryPeakResults.isMemoryEmpty()) {
        IJ.error(TITLE, "No localisations in memory");
        return;
    }
    settings = Settings.load();
    // Saved by reference so just save now
    settings.save();
    // Read in multiple traced datasets
    // All datasets must have the same pixel pitch and exposure time
    // Get parameters
    // Convert datasets to tracks
    // For each track compute the 4 local track features using the configured window
    // 
    // Optional:
    // Fit a multi-variate Gaussian mixture model to the data
    // (using the configured number of components/populations)
    // Assign each point in the track using the model.
    // Smooth the assignments.
    // 
    // The alternative is to use the localisation category to assign populations.
    // 
    // Plot histograms of each track parameter, coloured by component
    final List<MemoryPeakResults> combinedResults = new LocalList<>();
    if (!showInputDialog(combinedResults)) {
        return;
    }
    final boolean hasCategory = showHasCategoryDialog(combinedResults);
    if (!showDialog(hasCategory)) {
        return;
    }
    ImageJUtils.log(TITLE + "...");
    final List<Trace> tracks = getTracks(combinedResults, settings.window, settings.minTrackLength);
    if (tracks.isEmpty()) {
        IJ.error(TITLE, "No tracks. Please check the input data and min track length setting.");
        return;
    }
    final Calibration cal = combinedResults.get(0).getCalibration();
    final CalibrationReader cr = new CalibrationReader(cal);
    // Use micrometer / second
    final TypeConverter<DistanceUnit> distanceConverter = cr.getDistanceConverter(DistanceUnit.UM);
    final double exposureTime = cr.getExposureTime() / 1000.0;
    final Pair<int[], double[][]> trackData = extractTrackData(tracks, distanceConverter, exposureTime, hasCategory);
    final double[][] data = trackData.getValue();
    // Histogram the raw data.
    final Array2DRowRealMatrix raw = new Array2DRowRealMatrix(data, false);
    final WindowOrganiser wo = new WindowOrganiser();
    // Store the histogram data for plotting the components
    final double[][] columns = new double[FEATURE_NAMES.length][];
    final double[][] limits = new double[FEATURE_NAMES.length][];
    // Get column data
    for (int i = 0; i < FEATURE_NAMES.length; i++) {
        columns[i] = raw.getColumn(i);
        if (i == FEATURE_D) {
            // Plot using a logarithmic scale
            SimpleArrayUtils.apply(columns[i], Math::log10);
        }
        limits[i] = MathUtils.limits(columns[i]);
    }
    // Compute histogram bins
    final int[] bins = new int[FEATURE_NAMES.length];
    if (settings.histogramBins > 0) {
        Arrays.fill(bins, settings.histogramBins);
    } else {
        for (int i = 0; i < FEATURE_NAMES.length; i++) {
            bins[i] = HistogramPlot.getBins(StoredData.create(columns[i]), BinMethod.FD);
        }
        // Use the maximum so all histograms look the same
        Arrays.fill(bins, MathUtils.max(bins));
    }
    // Compute plots
    final Plot[] plots = new Plot[FEATURE_NAMES.length];
    for (int i = 0; i < FEATURE_NAMES.length; i++) {
        final double[][] hist = HistogramPlot.calcHistogram(columns[i], limits[i][0], limits[i][1], bins[i]);
        plots[i] = new Plot(TITLE + " " + FEATURE_NAMES[i], getFeatureLabel(i, i == FEATURE_D), "Frequency");
        plots[i].addPoints(hist[0], hist[1], Plot.BAR);
        ImageJUtils.display(plots[i].getTitle(), plots[i], ImageJUtils.NO_TO_FRONT, wo);
    }
    wo.tile();
    // The component for each data point
    int[] component;
    // The number of components
    int numComponents;
    // Data used to fit the Gaussian mixture model
    double[][] fitData;
    // The fitted model
    MixtureMultivariateGaussianDistribution model;
    if (hasCategory) {
        // Use the category as the component.
        // No fit data and no output model
        fitData = null;
        model = null;
        // The component is stored at the end of the raw track data.
        final int end = data[0].length - 1;
        component = Arrays.stream(data).mapToInt(d -> (int) d[end]).toArray();
        numComponents = MathUtils.max(component) + 1;
        // In the EM algorithm the probability of each data point is computed and normalised to
        // sum to 1. The normalised probabilities are averaged to create the weights.
        // Note the probability of each data point uses the previous weight and the algorithm
        // iterates.
        // This is not a fitted model but the input model so use
        // zero weights to indicate no fitting was performed.
        final double[] weights = new double[numComponents];
        // Remove the trailing component to show the 'model' in a table.
        createModelTable(Arrays.stream(data).map(d -> Arrays.copyOf(d, end)).toArray(double[][]::new), weights, component);
    } else {
        // Multivariate Gaussian mixture EM
        // Provide option to not use the anomalous exponent in the population mix.
        int sortDimension = SORT_DIMENSION;
        if (settings.ignoreAlpha) {
            // Remove index 0. This shifts the sort dimension.
            sortDimension--;
            fitData = Arrays.stream(data).map(d -> Arrays.copyOfRange(d, 1, d.length)).toArray(double[][]::new);
        } else {
            fitData = SimpleArrayUtils.deepCopy(data);
        }
        final MultivariateGaussianMixtureExpectationMaximization mixed = fitGaussianMixture(fitData, sortDimension);
        if (mixed == null) {
            IJ.error(TITLE, "Failed to fit a mixture model");
            return;
        }
        model = sortComponents(mixed.getFittedModel(), sortDimension);
        // For the best model, assign to the most likely population.
        component = assignData(fitData, model);
        // Table of the final model using the original data (i.e. not normalised)
        final double[] weights = model.getWeights();
        numComponents = weights.length;
        createModelTable(data, weights, component);
    }
    // Output coloured histograms of the populations.
    final LUT lut = LutHelper.createLut(settings.lutIndex);
    IntFunction<Color> colourMap;
    if (LutHelper.getColour(lut, 0).equals(Color.BLACK)) {
        colourMap = i -> LutHelper.getNonZeroColour(lut, i, 0, numComponents - 1);
    } else {
        colourMap = i -> LutHelper.getColour(lut, i, 0, numComponents - 1);
    }
    for (int i = 0; i < FEATURE_NAMES.length; i++) {
        // Extract the data for each component
        final double[] col = columns[i];
        final Plot plot = plots[i];
        for (int n = 0; n < numComponents; n++) {
            final StoredData feature = new StoredData();
            for (int j = 0; j < component.length; j++) {
                if (component[j] == n) {
                    feature.add(col[j]);
                }
            }
            if (feature.size() == 0) {
                continue;
            }
            final double[][] hist = HistogramPlot.calcHistogram(feature.values(), limits[i][0], limits[i][1], bins[i]);
            // Colour the points
            plot.setColor(colourMap.apply(n));
            plot.addPoints(hist[0], hist[1], Plot.BAR);
        }
        plot.updateImage();
    }
    createTrackDataTable(tracks, trackData, fitData, model, component, cal, colourMap);
// Analysis.
// Assign the original localisations to their track component.
// Q. What about the start/end not covered by the window?
// Save tracks as a dataset labelled with the sub-track ID?
// Output for the bound component and free components track parameters.
// Compute dwell times.
// Other ...
// Track analysis plugin:
// Extract all continuous segments of the same component.
// Produce MSD plot with error bars.
// Fit using FBM model.
}
Also used : LocalList(uk.ac.sussex.gdsc.core.utils.LocalList) Array2DRowRealMatrix(org.apache.commons.math3.linear.Array2DRowRealMatrix) MixtureMultivariateGaussianDistribution(uk.ac.sussex.gdsc.smlm.math3.distribution.fitting.MultivariateGaussianMixtureExpectationMaximization.MixtureMultivariateGaussianDistribution) MemoryPeakResults(uk.ac.sussex.gdsc.smlm.results.MemoryPeakResults) DistanceUnit(uk.ac.sussex.gdsc.smlm.data.config.UnitProtos.DistanceUnit) Plot(ij.gui.Plot) HistogramPlot(uk.ac.sussex.gdsc.core.ij.HistogramPlot) Color(java.awt.Color) LUT(ij.process.LUT) Calibration(uk.ac.sussex.gdsc.smlm.data.config.CalibrationProtos.Calibration) WindowOrganiser(uk.ac.sussex.gdsc.core.ij.plugin.WindowOrganiser) CalibrationReader(uk.ac.sussex.gdsc.smlm.data.config.CalibrationReader) Trace(uk.ac.sussex.gdsc.smlm.results.Trace) MultivariateGaussianMixtureExpectationMaximization(uk.ac.sussex.gdsc.smlm.math3.distribution.fitting.MultivariateGaussianMixtureExpectationMaximization) StoredData(uk.ac.sussex.gdsc.core.utils.StoredData)

Aggregations

WindowOrganiser (uk.ac.sussex.gdsc.core.ij.plugin.WindowOrganiser)25 Plot (ij.gui.Plot)12 HistogramPlotBuilder (uk.ac.sussex.gdsc.core.ij.HistogramPlot.HistogramPlotBuilder)10 ImagePlus (ij.ImagePlus)8 Rectangle (java.awt.Rectangle)8 Statistics (uk.ac.sussex.gdsc.core.utils.Statistics)8 ImageStack (ij.ImageStack)7 Point (java.awt.Point)7 LocalList (uk.ac.sussex.gdsc.core.utils.LocalList)7 PlotWindow (ij.gui.PlotWindow)6 ExtendedGenericDialog (uk.ac.sussex.gdsc.core.ij.gui.ExtendedGenericDialog)6 StoredDataStatistics (uk.ac.sussex.gdsc.core.utils.StoredDataStatistics)6 MemoryPeakResults (uk.ac.sussex.gdsc.smlm.results.MemoryPeakResults)6 Color (java.awt.Color)5 ExecutorService (java.util.concurrent.ExecutorService)5 IJ (ij.IJ)4 PlugIn (ij.plugin.PlugIn)4 LUT (ij.process.LUT)4 Future (java.util.concurrent.Future)4 HistogramPlot (uk.ac.sussex.gdsc.core.ij.HistogramPlot)4