Search in sources :

Example 36 with Percentile

use of org.apache.commons.math3.stat.descriptive.rank.Percentile in project OpenTripPlanner by opentripplanner.

the class PropagatedTimesStore method setFromArray.

/**
 * @param times for search (varying departure time), an array of travel times to each destination.
 * @param includeInAverages for each iteration, whether that iteration should be included in average calculations.
 *                          In RaptorWorker's Monte Carlo code we also include minima and maxima, which should
 *                          not be included in averages.
 *                          Iterations that are not included in averages are still used to determine extrema.
 */
public void setFromArray(int[][] times, boolean[] includeInAverages, ConfidenceCalculationMethod confidenceCalculationMethod) {
    if (times.length == 0)
        // nothing to do
        return;
    // assume array is rectangular
    int nTargets = times[0].length;
    // cache random numbers. This should be fine as we're mixing it with the number of minutes
    // at which each destination is accessible, which is sometimes not 120, as well as the stop
    // position in the list (note that we have cleverly chosen a number which is a prime
    // so is not divisible by the number of iterations on the bootstrap). Finally recall that
    // the maximum number of times we're sampling from is generally 120 and we modulo this,
    // so the pigeonhole principle applies.
    // this is effectively a "random number generator" with phase 10007
    int[] randomNumbers = random.ints().limit(10007).map(Math::abs).toArray();
    int nextRandom = 0;
    int effectiveIterations = 0;
    for (int i = 0; i < includeInAverages.length; i++) {
        if (includeInAverages[i])
            effectiveIterations++;
    }
    // loop over targets on the outside so we can bootstrap
    TARGETS: for (int target = 0; target < nTargets; target++) {
        // compute the average
        int sum = 0;
        int count = 0;
        TIntList timeList = new TIntArrayList();
        TIntList avgList = new TIntArrayList();
        ITERATIONS: for (int i = 0; i < times.length; i++) {
            if (times[i][target] == RaptorWorker.UNREACHED)
                continue ITERATIONS;
            if (includeInAverages[i]) {
                avgList.add(times[i][target]);
                sum += times[i][target];
                count++;
            }
            timeList.add(times[i][target]);
        }
        // never reachable
        if (count == 0)
            continue TARGETS;
        // wait times as well.
        if (count >= effectiveIterations * req.reachabilityThreshold)
            avgs[target] = sum / count;
        // TODO: correctly handle partial accessibility for bootstrap and percentile options.
        switch(confidenceCalculationMethod) {
            case BOOTSTRAP:
                // now bootstrap out a 95% confidence interval on the time
                int[] bootMeans = new int[N_BOOTSTRAPS];
                // prevent overflow
                nextRandom += N_BOOTSTRAPS * count % randomNumbers.length;
                final int randOff = nextRandom;
                final int finalCount = count;
                IntStream.range(0, N_BOOTSTRAPS).parallel().forEach(boot -> {
                    int bsum = 0;
                    // sample from the Monte Carlo distribution with replacement
                    for (int iter = 0; iter < finalCount; iter++) {
                        bsum += avgList.get(randomNumbers[(randOff + boot * iter) % randomNumbers.length] % avgList.size());
                    // bsum += timeList.get(random.nextInt(count));
                    }
                    bootMeans[boot] = bsum / finalCount;
                });
                Arrays.sort(bootMeans);
                // 2.5 percentile of distribution of means
                mins[target] = bootMeans[N_BOOTSTRAPS / 40];
                // 97.5 percentile of distribution of means
                maxs[target] = bootMeans[N_BOOTSTRAPS - N_BOOTSTRAPS / 40];
                break;
            case PERCENTILE:
                timeList.sort();
                mins[target] = timeList.get(timeList.size() / 40);
                maxs[target] = timeList.get(39 * timeList.size() / 40);
                break;
            case NONE:
                mins[target] = maxs[target] = avgs[target];
                break;
            case MIN_MAX:
            default:
                mins[target] = timeList.min();
                // NB not using count here as it doesn't count iterations that are not included in averages
                if (timeList.size() == times.length)
                    maxs[target] = timeList.max();
                break;
        }
    }
}
Also used : IntStream(java.util.stream.IntStream) Arrays(java.util.Arrays) TIntArrayList(gnu.trove.list.array.TIntArrayList) WTWD(org.opentripplanner.analyst.request.SampleGridRenderer.WTWD) LoggerFactory(org.slf4j.LoggerFactory) Random(java.util.Random) IsochroneData(org.opentripplanner.analyst.core.IsochroneData) SphericalDistanceLibrary(org.opentripplanner.common.geometry.SphericalDistanceLibrary) ArrayList(java.util.ArrayList) WTWDAccumulativeMetric(org.opentripplanner.analyst.request.SampleGridRenderer.WTWDAccumulativeMetric) Graph(org.opentripplanner.routing.graph.Graph) FastMath.toRadians(org.apache.commons.math3.util.FastMath.toRadians) DelaunayIsolineBuilder(org.opentripplanner.common.geometry.DelaunayIsolineBuilder) AccumulativeGridSampler(org.opentripplanner.common.geometry.AccumulativeGridSampler) Coordinate(com.vividsolutions.jts.geom.Coordinate) TIntList(gnu.trove.list.TIntList) Logger(org.slf4j.Logger) ResultSet(org.opentripplanner.analyst.ResultSet) Vertex(org.opentripplanner.routing.graph.Vertex) TimeSurface(org.opentripplanner.analyst.TimeSurface) FastMath(org.apache.commons.math3.util.FastMath) SparseMatrixZSampleGrid(org.opentripplanner.common.geometry.SparseMatrixZSampleGrid) SampleGridRenderer(org.opentripplanner.analyst.request.SampleGridRenderer) List(java.util.List) Stream(java.util.stream.Stream) SampleSet(org.opentripplanner.analyst.SampleSet) ResultEnvelope(org.opentripplanner.analyst.cluster.ResultEnvelope) TIntList(gnu.trove.list.TIntList) TIntArrayList(gnu.trove.list.array.TIntArrayList)

Example 37 with Percentile

use of org.apache.commons.math3.stat.descriptive.rank.Percentile 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 38 with Percentile

use of org.apache.commons.math3.stat.descriptive.rank.Percentile in project GDSC-SMLM by aherbert.

the class PcPalmMolecules method runSimulation.

private void runSimulation(boolean resultsAvailable) {
    if (resultsAvailable && !showSimulationDialog()) {
        return;
    }
    startLog();
    log("Simulation parameters");
    if (settings.blinkingDistribution == 3) {
        log("  - Clusters = %d", settings.numberOfMolecules);
        log("  - Simulation size = %s um", MathUtils.rounded(settings.simulationSize, 4));
        log("  - Molecules/cluster = %s", MathUtils.rounded(settings.blinkingRate, 4));
        log("  - Blinking distribution = %s", Settings.BLINKING_DISTRIBUTION[settings.blinkingDistribution]);
        log("  - p-Value = %s", MathUtils.rounded(settings.pvalue, 4));
    } else {
        log("  - Molecules = %d", settings.numberOfMolecules);
        log("  - Simulation size = %s um", MathUtils.rounded(settings.simulationSize, 4));
        log("  - Blinking rate = %s", MathUtils.rounded(settings.blinkingRate, 4));
        log("  - Blinking distribution = %s", Settings.BLINKING_DISTRIBUTION[settings.blinkingDistribution]);
    }
    log("  - Average precision = %s nm", MathUtils.rounded(settings.sigmaS, 4));
    log("  - Clusters simulation = " + Settings.CLUSTER_SIMULATION[settings.clusterSimulation]);
    if (settings.clusterSimulation > 0) {
        log("  - Cluster number = %s +/- %s", MathUtils.rounded(settings.clusterNumber, 4), MathUtils.rounded(settings.clusterNumberStdDev, 4));
        log("  - Cluster radius = %s nm", MathUtils.rounded(settings.clusterRadius, 4));
    }
    final double nmPerPixel = 100;
    final double width = settings.simulationSize * 1000.0;
    final UniformRandomProvider rng = UniformRandomProviders.create();
    final UniformDistribution dist = new UniformDistribution(null, new double[] { width, width, 0 }, rng.nextInt());
    final NormalizedGaussianSampler gauss = SamplerUtils.createNormalizedGaussianSampler(rng);
    settings.molecules = new ArrayList<>(settings.numberOfMolecules);
    // Create some dummy results since the calibration is required for later analysis
    settings.results = new MemoryPeakResults(PsfHelper.create(PSFType.CUSTOM));
    settings.results.setCalibration(CalibrationHelper.create(nmPerPixel, 1, 100));
    settings.results.setSource(new NullSource("Molecule Simulation"));
    settings.results.begin();
    int count = 0;
    // Generate a sequence of coordinates
    final ArrayList<double[]> xyz = new ArrayList<>((int) (settings.numberOfMolecules * 1.1));
    final Statistics statsRadius = new Statistics();
    final Statistics statsSize = new Statistics();
    final String maskTitle = TITLE + " Cluster Mask";
    ByteProcessor bp = null;
    double maskScale = 0;
    if (settings.clusterSimulation > 0) {
        // Simulate clusters.
        // Note: In the Veatch et al. paper (Plos 1, e31457) correlation functions are built using
        // circles with small radii of 4-8 Arbitrary Units (AU) or large radii of 10-30 AU. A
        // fluctuations model is created at T = 1.075 Tc. It is not clear exactly how the particles
        // are distributed.
        // It may be that a mask is created first using the model. The particles are placed on the
        // mask using a specified density. This simulation produces a figure to show either a damped
        // cosine function (circles) or an exponential (fluctuations). The number of particles in
        // each circle may be randomly determined just by density. The figure does not discuss the
        // derivation of the cluster size statistic.
        // 
        // If this plugin simulation is run with a uniform distribution and blinking rate of 1 then
        // the damped cosine function is reproduced. The curve crosses g(r)=1 at a value equivalent
        // to the average distance to the centre-of-mass of each drawn cluster, not the input cluster
        // radius parameter (which is a hard upper limit on the distance to centre).
        final int maskSize = settings.lowResolutionImageSize;
        int[] mask = null;
        // scale is in nm/pixel
        maskScale = width / maskSize;
        final ArrayList<double[]> clusterCentres = new ArrayList<>();
        int totalSteps = 1 + (int) Math.ceil(settings.numberOfMolecules / settings.clusterNumber);
        if (settings.clusterSimulation == 2 || settings.clusterSimulation == 3) {
            // Clusters are non-overlapping circles
            // Ensure the circles do not overlap by using an exclusion mask that accumulates
            // out-of-bounds pixels by drawing the last cluster (plus some border) on an image. When no
            // more pixels are available then stop generating molecules.
            // This is done by cumulatively filling a mask and using the MaskDistribution to select
            // a new point. This may be slow but it works.
            // TODO - Allow clusters of different sizes...
            mask = new int[maskSize * maskSize];
            Arrays.fill(mask, 255);
            MaskDistribution maskDistribution = new MaskDistribution(mask, maskSize, maskSize, 0, maskScale, maskScale, rng);
            double[] centre;
            IJ.showStatus("Computing clusters mask");
            final int roiRadius = (int) Math.round((settings.clusterRadius * 2) / maskScale);
            if (settings.clusterSimulation == 3) {
                // Generate a mask of circles then sample from that.
                // If we want to fill the mask completely then adjust the total steps to be the number of
                // circles that can fit inside the mask.
                totalSteps = (int) (maskSize * maskSize / (Math.PI * MathUtils.pow2(settings.clusterRadius / maskScale)));
            }
            while ((centre = maskDistribution.next()) != null && clusterCentres.size() < totalSteps) {
                IJ.showProgress(clusterCentres.size(), totalSteps);
                // The mask returns the coordinates with the centre of the image at 0,0
                centre[0] += width / 2;
                centre[1] += width / 2;
                clusterCentres.add(centre);
                // Fill in the mask around the centre to exclude any more circles that could overlap
                final double cx = centre[0] / maskScale;
                final double cy = centre[1] / maskScale;
                fillMask(mask, maskSize, (int) cx, (int) cy, roiRadius, 0);
                try {
                    maskDistribution = new MaskDistribution(mask, maskSize, maskSize, 0, maskScale, maskScale, rng);
                } catch (final IllegalArgumentException ex) {
                    // This can happen when there are no more non-zero pixels
                    log("WARNING: No more room for clusters on the mask area (created %d of estimated %d)", clusterCentres.size(), totalSteps);
                    break;
                }
            }
            ImageJUtils.finished();
        } else {
            // Pick centres randomly from the distribution
            while (clusterCentres.size() < totalSteps) {
                clusterCentres.add(dist.next());
            }
        }
        final double scaledRadius = settings.clusterRadius / maskScale;
        if (settings.showClusterMask || settings.clusterSimulation == 3) {
            // Show the mask for the clusters
            if (mask == null) {
                mask = new int[maskSize * maskSize];
            } else {
                Arrays.fill(mask, 0);
            }
            final int roiRadius = (int) Math.round(scaledRadius);
            for (final double[] c : clusterCentres) {
                final double cx = c[0] / maskScale;
                final double cy = c[1] / maskScale;
                fillMask(mask, maskSize, (int) cx, (int) cy, roiRadius, 1);
            }
            if (settings.clusterSimulation == 3) {
                // We have the mask. Now pick points at random from the mask.
                final MaskDistribution maskDistribution = new MaskDistribution(mask, maskSize, maskSize, 0, maskScale, maskScale, rng);
                // Allocate each molecule position to a parent circle so defining clusters.
                final int[][] clusters = new int[clusterCentres.size()][];
                final int[] clusterSize = new int[clusters.length];
                for (int i = 0; i < settings.numberOfMolecules; i++) {
                    final double[] centre = maskDistribution.next();
                    // The mask returns the coordinates with the centre of the image at 0,0
                    centre[0] += width / 2;
                    centre[1] += width / 2;
                    xyz.add(centre);
                    // Output statistics on cluster size and number.
                    // TODO - Finding the closest cluster could be done better than an all-vs-all comparison
                    double max = distance2(centre, clusterCentres.get(0));
                    int cluster = 0;
                    for (int j = 1; j < clusterCentres.size(); j++) {
                        final double d2 = distance2(centre, clusterCentres.get(j));
                        if (d2 < max) {
                            max = d2;
                            cluster = j;
                        }
                    }
                    // Assign point i to cluster
                    centre[2] = cluster;
                    if (clusterSize[cluster] == 0) {
                        clusters[cluster] = new int[10];
                    }
                    if (clusters[cluster].length <= clusterSize[cluster]) {
                        clusters[cluster] = Arrays.copyOf(clusters[cluster], (int) (clusters[cluster].length * 1.5));
                    }
                    clusters[cluster][clusterSize[cluster]++] = i;
                }
                // Generate real cluster size statistics
                for (int j = 0; j < clusterSize.length; j++) {
                    final int size = clusterSize[j];
                    if (size == 0) {
                        continue;
                    }
                    statsSize.add(size);
                    if (size == 1) {
                        statsRadius.add(0);
                        continue;
                    }
                    // Find centre of cluster and add the distance to each point
                    final double[] com = new double[2];
                    for (int n = 0; n < size; n++) {
                        final double[] xy = xyz.get(clusters[j][n]);
                        for (int k = 0; k < 2; k++) {
                            com[k] += xy[k];
                        }
                    }
                    for (int k = 0; k < 2; k++) {
                        com[k] /= size;
                    }
                    for (int n = 0; n < size; n++) {
                        final double dx = xyz.get(clusters[j][n])[0] - com[0];
                        final double dy = xyz.get(clusters[j][n])[1] - com[1];
                        statsRadius.add(Math.sqrt(dx * dx + dy * dy));
                    }
                }
            }
            if (settings.showClusterMask) {
                bp = new ByteProcessor(maskSize, maskSize);
                for (int i = 0; i < mask.length; i++) {
                    if (mask[i] != 0) {
                        bp.set(i, 128);
                    }
                }
                ImageJUtils.display(maskTitle, bp);
            }
        }
        // Use the simulated cluster centres to create clusters of the desired size
        if (settings.clusterSimulation == 1 || settings.clusterSimulation == 2) {
            for (final double[] clusterCentre : clusterCentres) {
                final int clusterN = (int) Math.round((settings.clusterNumberStdDev > 0) ? settings.clusterNumber + gauss.sample() * settings.clusterNumberStdDev : settings.clusterNumber);
                if (clusterN < 1) {
                    continue;
                }
                if (clusterN == 1) {
                    // No need for a cluster around a point
                    xyz.add(clusterCentre);
                    statsRadius.add(0);
                    statsSize.add(1);
                } else {
                    // Generate N random points within a circle of the chosen cluster radius.
                    // Locate the centre-of-mass and the average distance to the centre.
                    final double[] com = new double[3];
                    int size = 0;
                    while (size < clusterN) {
                        // Generate a random point within a circle uniformly
                        // http://stackoverflow.com/questions/5837572/generate-a-random-point-within-a-circle-uniformly
                        final double t = 2.0 * Math.PI * rng.nextDouble();
                        final double u = rng.nextDouble() + rng.nextDouble();
                        final double r = settings.clusterRadius * ((u > 1) ? 2 - u : u);
                        final double x = r * Math.cos(t);
                        final double y = r * Math.sin(t);
                        final double[] xy = new double[] { clusterCentre[0] + x, clusterCentre[1] + y };
                        xyz.add(xy);
                        for (int k = 0; k < 2; k++) {
                            com[k] += xy[k];
                        }
                        size++;
                    }
                    // Add the distance of the points from the centre of the cluster.
                    // Note this does not account for the movement due to precision.
                    statsSize.add(size);
                    if (size == 1) {
                        statsRadius.add(0);
                    } else {
                        for (int k = 0; k < 2; k++) {
                            com[k] /= size;
                        }
                        while (size > 0) {
                            final double dx = xyz.get(xyz.size() - size)[0] - com[0];
                            final double dy = xyz.get(xyz.size() - size)[1] - com[1];
                            statsRadius.add(Math.sqrt(dx * dx + dy * dy));
                            size--;
                        }
                    }
                }
            }
        }
    } else {
        // Random distribution
        for (int i = 0; i < settings.numberOfMolecules; i++) {
            xyz.add(dist.next());
        }
    }
    // The Gaussian sigma should be applied so the overall distance from the centre
    // ( sqrt(x^2+y^2) ) has a standard deviation of sigmaS?
    final double sigma1D = settings.sigmaS / Math.sqrt(2);
    // Show optional histograms
    StoredDataStatistics intraDistances = null;
    StoredData blinks = null;
    if (settings.showHistograms) {
        final int capacity = (int) (xyz.size() * settings.blinkingRate);
        intraDistances = new StoredDataStatistics(capacity);
        blinks = new StoredData(capacity);
    }
    final Statistics statsSigma = new Statistics();
    for (int i = 0; i < xyz.size(); i++) {
        int occurrences = getBlinks(rng, settings.blinkingRate);
        if (blinks != null) {
            blinks.add(occurrences);
        }
        final int size = settings.molecules.size();
        // Get coordinates in nm
        final double[] moleculeXyz = xyz.get(i);
        if (bp != null && occurrences > 0) {
            bp.putPixel((int) Math.round(moleculeXyz[0] / maskScale), (int) Math.round(moleculeXyz[1] / maskScale), 255);
        }
        while (occurrences-- > 0) {
            final double[] localisationXy = Arrays.copyOf(moleculeXyz, 2);
            // Add random precision
            if (sigma1D > 0) {
                final double dx = gauss.sample() * sigma1D;
                final double dy = gauss.sample() * sigma1D;
                localisationXy[0] += dx;
                localisationXy[1] += dy;
                if (!dist.isWithinXy(localisationXy)) {
                    continue;
                }
                // Calculate mean-squared displacement
                statsSigma.add(dx * dx + dy * dy);
            }
            final double x = localisationXy[0];
            final double y = localisationXy[1];
            settings.molecules.add(new Molecule(x, y, i, 1));
            // Store in pixels
            final float xx = (float) (x / nmPerPixel);
            final float yy = (float) (y / nmPerPixel);
            final float[] params = PeakResult.createParams(0, 0, xx, yy, 0);
            settings.results.add(i + 1, (int) xx, (int) yy, 0, 0, 0, 0, params, null);
        }
        if (settings.molecules.size() > size) {
            count++;
            if (intraDistances != null) {
                final int newCount = settings.molecules.size() - size;
                if (newCount == 1) {
                    // No intra-molecule distances
                    continue;
                }
                // Get the distance matrix between these molecules
                final double[][] matrix = new double[newCount][newCount];
                for (int ii = size, x = 0; ii < settings.molecules.size(); ii++, x++) {
                    for (int jj = size + 1, y = 1; jj < settings.molecules.size(); jj++, y++) {
                        final double d2 = settings.molecules.get(ii).distance2(settings.molecules.get(jj));
                        matrix[x][y] = matrix[y][x] = d2;
                    }
                }
                // Get the maximum distance for particle linkage clustering of this molecule
                double max = 0;
                for (int x = 0; x < newCount; x++) {
                    // Compare to all-other molecules and get the minimum distance
                    // needed to join at least one
                    double linkDistance = Double.POSITIVE_INFINITY;
                    for (int y = 0; y < newCount; y++) {
                        if (x == y) {
                            continue;
                        }
                        if (matrix[x][y] < linkDistance) {
                            linkDistance = matrix[x][y];
                        }
                    }
                    // Check if this is larger
                    if (max < linkDistance) {
                        max = linkDistance;
                    }
                }
                intraDistances.add(Math.sqrt(max));
            }
        }
    }
    settings.results.end();
    if (bp != null) {
        final ImagePlus imp = ImageJUtils.display(maskTitle, bp);
        final Calibration cal = imp.getCalibration();
        cal.setUnit("nm");
        cal.pixelWidth = cal.pixelHeight = maskScale;
    }
    log("Simulation results");
    log("  * Molecules = %d (%d activated)", xyz.size(), count);
    log("  * Blinking rate = %s", MathUtils.rounded((double) settings.molecules.size() / xyz.size(), 4));
    log("  * Precision (Mean-displacement) = %s nm", (statsSigma.getN() > 0) ? MathUtils.rounded(Math.sqrt(statsSigma.getMean()), 4) : "0");
    if (intraDistances != null) {
        if (intraDistances.getN() == 0) {
            log("  * Mean Intra-Molecule particle linkage distance = 0 nm");
            log("  * Fraction of inter-molecule particle linkage @ 0 nm = 0 %%");
        } else {
            plot(blinks, "Blinks/Molecule", true);
            final double[][] intraHist = plot(intraDistances, "Intra-molecule particle linkage distance", false);
            // Determine 95th and 99th percentile
            // Will not be null as we requested a non-integer histogram.
            int p99 = intraHist[0].length - 1;
            final double limit1 = 0.99 * intraHist[1][p99];
            final double limit2 = 0.95 * intraHist[1][p99];
            while (intraHist[1][p99] > limit1 && p99 > 0) {
                p99--;
            }
            int p95 = p99;
            while (intraHist[1][p95] > limit2 && p95 > 0) {
                p95--;
            }
            log("  * Mean Intra-Molecule particle linkage distance = %s nm" + " (95%% = %s, 99%% = %s, 100%% = %s)", MathUtils.rounded(intraDistances.getMean(), 4), MathUtils.rounded(intraHist[0][p95], 4), MathUtils.rounded(intraHist[0][p99], 4), MathUtils.rounded(intraHist[0][intraHist[0].length - 1], 4));
            if (settings.distanceAnalysis) {
                performDistanceAnalysis(intraHist, p99);
            }
        }
    }
    if (settings.clusterSimulation > 0) {
        log("  * Cluster number = %s +/- %s", MathUtils.rounded(statsSize.getMean(), 4), MathUtils.rounded(statsSize.getStandardDeviation(), 4));
        log("  * Cluster radius = %s +/- %s nm (mean distance to centre-of-mass)", MathUtils.rounded(statsRadius.getMean(), 4), MathUtils.rounded(statsRadius.getStandardDeviation(), 4));
    }
}
Also used : ByteProcessor(ij.process.ByteProcessor) TDoubleArrayList(gnu.trove.list.array.TDoubleArrayList) ArrayList(java.util.ArrayList) MaskDistribution(uk.ac.sussex.gdsc.smlm.model.MaskDistribution) MemoryPeakResults(uk.ac.sussex.gdsc.smlm.results.MemoryPeakResults) NullSource(uk.ac.sussex.gdsc.smlm.results.NullSource) UniformDistribution(uk.ac.sussex.gdsc.smlm.model.UniformDistribution) StoredDataStatistics(uk.ac.sussex.gdsc.core.utils.StoredDataStatistics) Calibration(ij.measure.Calibration) StoredDataStatistics(uk.ac.sussex.gdsc.core.utils.StoredDataStatistics) Statistics(uk.ac.sussex.gdsc.core.utils.Statistics) DescriptiveStatistics(org.apache.commons.math3.stat.descriptive.DescriptiveStatistics) ImagePlus(ij.ImagePlus) WeightedObservedPoint(org.apache.commons.math3.fitting.WeightedObservedPoint) ClusterPoint(uk.ac.sussex.gdsc.core.clustering.ClusterPoint) StoredData(uk.ac.sussex.gdsc.core.utils.StoredData) UniformRandomProvider(org.apache.commons.rng.UniformRandomProvider) NormalizedGaussianSampler(org.apache.commons.rng.sampling.distribution.NormalizedGaussianSampler)

Example 39 with Percentile

use of org.apache.commons.math3.stat.descriptive.rank.Percentile in project GDSC-SMLM by aherbert.

the class PcPalmMolecules method performDistanceAnalysis.

private void performDistanceAnalysis(double[][] intraHist, int p99) {
    // We want to know the fraction of distances between molecules at the 99th percentile
    // that are intra- rather than inter-molecule.
    // Do single linkage clustering of closest pair at this distance and count the number of
    // links that are inter and intra.
    // Convert molecules for clustering
    final ArrayList<ClusterPoint> points = new ArrayList<>(settings.molecules.size());
    for (final Molecule m : settings.molecules) {
        // Precision was used to store the molecule ID
        points.add(ClusterPoint.newClusterPoint((int) m.precision, m.x, m.y, m.photons));
    }
    final ClusteringEngine engine = new ClusteringEngine(Prefs.getThreads(), ClusteringAlgorithm.PARTICLE_SINGLE_LINKAGE, SimpleImageJTrackProgress.getInstance());
    IJ.showStatus("Clustering to check inter-molecule distances");
    engine.setTrackJoins(true);
    final List<Cluster> clusters = engine.findClusters(points, intraHist[0][p99]);
    IJ.showStatus("");
    if (clusters != null) {
        final double[] intraIdDistances = engine.getIntraIdDistances();
        final double[] interIdDistances = engine.getInterIdDistances();
        final int all = interIdDistances.length + intraIdDistances.length;
        log("  * Fraction of inter-molecule particle linkage @ %s nm = %s %%", MathUtils.rounded(intraHist[0][p99], 4), (all > 0) ? MathUtils.rounded(100.0 * interIdDistances.length / all, 4) : "0");
        // Show a double cumulative histogram plot
        final double[][] intraIdHist = MathUtils.cumulativeHistogram(intraIdDistances, false);
        final double[][] interIdHist = MathUtils.cumulativeHistogram(interIdDistances, false);
        // Plot
        final String title = TITLE + " molecule linkage distance";
        final Plot plot = new Plot(title, "Distance", "Frequency");
        plot.addPoints(intraIdHist[0], intraIdHist[1], Plot.LINE);
        double max = (intraIdHist[1].length > 0) ? intraIdHist[1][intraIdHist[1].length - 1] : 0;
        if (interIdHist[1].length > 0) {
            max = Math.max(max, interIdHist[1][interIdHist[1].length - 1]);
        }
        plot.setLimits(0, intraIdHist[0][intraIdHist[0].length - 1], 0, max);
        plot.setColor(Color.blue);
        plot.addPoints(interIdHist[0], interIdHist[1], Plot.LINE);
        plot.setColor(Color.black);
        plot.addLegend("Intra-molecule\nInter-molecule");
        ImageJUtils.display(title, plot);
    } else {
        log("Aborted clustering to check inter-molecule distances");
    }
}
Also used : Plot(ij.gui.Plot) HistogramPlot(uk.ac.sussex.gdsc.core.ij.HistogramPlot) TDoubleArrayList(gnu.trove.list.array.TDoubleArrayList) ArrayList(java.util.ArrayList) Cluster(uk.ac.sussex.gdsc.core.clustering.Cluster) WeightedObservedPoint(org.apache.commons.math3.fitting.WeightedObservedPoint) ClusterPoint(uk.ac.sussex.gdsc.core.clustering.ClusterPoint) ClusteringEngine(uk.ac.sussex.gdsc.core.clustering.ClusteringEngine) ClusterPoint(uk.ac.sussex.gdsc.core.clustering.ClusterPoint)

Example 40 with Percentile

use of org.apache.commons.math3.stat.descriptive.rank.Percentile in project jmeter by apache.

the class DescriptiveStatisticsFactory method createDescriptiveStatistics.

public static DescriptiveStatistics createDescriptiveStatistics(int windowSize) {
    DescriptiveStatistics statistics = new DescriptiveStatistics(windowSize);
    statistics.setPercentileImpl(new Percentile().withEstimationType(ESTIMATION_TYPE));
    return statistics;
}
Also used : DescriptiveStatistics(org.apache.commons.math3.stat.descriptive.DescriptiveStatistics) Percentile(org.apache.commons.math3.stat.descriptive.rank.Percentile)

Aggregations

Percentile (org.apache.commons.math3.stat.descriptive.rank.Percentile)31 ArrayList (java.util.ArrayList)16 RealMatrix (org.apache.commons.math3.linear.RealMatrix)16 Array2DRowRealMatrix (org.apache.commons.math3.linear.Array2DRowRealMatrix)14 List (java.util.List)11 Collectors (java.util.stream.Collectors)11 IntStream (java.util.stream.IntStream)11 File (java.io.File)10 DoubleStream (java.util.stream.DoubleStream)10 Median (org.apache.commons.math3.stat.descriptive.rank.Median)10 Logger (org.apache.logging.log4j.Logger)10 Test (org.testng.annotations.Test)10 Random (java.util.Random)9 Stream (java.util.stream.Stream)9 DescriptiveStatistics (org.apache.commons.math3.stat.descriptive.DescriptiveStatistics)9 Level (org.apache.logging.log4j.Level)8 Marker (org.apache.logging.log4j.Marker)8 Message (org.apache.logging.log4j.message.Message)8 AbstractLogger (org.apache.logging.log4j.spi.AbstractLogger)8 SimpleInterval (org.broadinstitute.hellbender.utils.SimpleInterval)8