Search in sources :

Example 1 with TimeUnit

use of uk.ac.sussex.gdsc.smlm.data.config.UnitProtos.TimeUnit in project GDSC-SMLM by aherbert.

the class TimeUnitTest method check.

private static void check(double msPerFrame, ExpectedUnit<TimeUnit>... expectedUnits) {
    final int n = expectedUnits.length;
    TypeConverter<TimeUnit> conv;
    for (int i = 0; i < n; i++) {
        final TimeUnit u1 = expectedUnits[i].unit;
        final double v1 = expectedUnits[i].value;
        for (int j = 0; j < n; j++) {
            final TimeUnit u2 = expectedUnits[j].unit;
            conv = UnitConverterUtils.createConverter(u1, u2, msPerFrame);
            final double o = conv.convert(v1);
            Assertions.assertEquals(expectedUnits[j].value, o, 1e-5, () -> u1 + " to " + u2);
        }
    }
}
Also used : TimeUnit(uk.ac.sussex.gdsc.smlm.data.config.UnitProtos.TimeUnit)

Example 2 with TimeUnit

use of uk.ac.sussex.gdsc.smlm.data.config.UnitProtos.TimeUnit in project GDSC-SMLM by aherbert.

the class TraceExporter method exportSpotOn.

private void exportSpotOn(MemoryPeakResults results) {
    try (BufferedWriter out = Files.newBufferedWriter(Paths.get(settings.directory, results.getName() + ".csv"))) {
        out.write("frame,t,trajectory,x,y");
        out.newLine();
        final TypeConverter<TimeUnit> converter = UnitConverterUtils.createConverter(TimeUnit.FRAME, TimeUnit.SECOND, results.getCalibrationReader().getExposureTime());
        @SuppressWarnings("resource") final BufferedWriter writer = out;
        results.forEach(DistanceUnit.UM, (XyrResultProcedure) (x, y, result) -> {
            try {
                if (result.hasEndFrame()) {
                    final String sId = Integer.toString(result.getId());
                    final String sx = Float.toString(x);
                    final String sy = Float.toString(y);
                    for (int t = result.getFrame(); t <= result.getEndFrame(); t++) {
                        writer.write(Integer.toString(t));
                        writer.write(",");
                        writer.write(Float.toString(converter.convert(t)));
                        writer.write(",");
                        writer.write(sId);
                        writer.write(",");
                        writer.write(sx);
                        writer.write(",");
                        writer.write(sy);
                        writer.newLine();
                    }
                } else {
                    writer.write(Integer.toString(result.getFrame()));
                    writer.write(",");
                    writer.write(Float.toString(converter.convert(result.getFrame())));
                    writer.write(",");
                    writer.write(Integer.toString(result.getId()));
                    writer.write(",");
                    writer.write(Float.toString(x));
                    writer.write(",");
                    writer.write(Float.toString(y));
                    writer.newLine();
                }
            } catch (final IOException ex) {
                throw new RuntimeException(ex);
            }
        });
    } catch (final IOException | RuntimeException ex) {
        handleException(ex);
    }
}
Also used : MemoryResultsList(uk.ac.sussex.gdsc.smlm.ij.plugins.ResultsManager.MemoryResultsList) Cell(us.hebi.matlab.mat.types.Cell) UnitConverterUtils(uk.ac.sussex.gdsc.smlm.data.config.UnitConverterUtils) IdFramePeakResultComparator(uk.ac.sussex.gdsc.smlm.results.sort.IdFramePeakResultComparator) FrameCounter(uk.ac.sussex.gdsc.smlm.results.count.FrameCounter) PeakResult(uk.ac.sussex.gdsc.smlm.results.PeakResult) MatFile(us.hebi.matlab.mat.types.MatFile) AtomicReference(java.util.concurrent.atomic.AtomicReference) Matrix(us.hebi.matlab.mat.types.Matrix) ArrayList(java.util.ArrayList) Level(java.util.logging.Level) MultiDialog(uk.ac.sussex.gdsc.core.ij.gui.MultiDialog) MemoryPeakResults(uk.ac.sussex.gdsc.smlm.results.MemoryPeakResults) PeakResultProcedure(uk.ac.sussex.gdsc.smlm.results.procedures.PeakResultProcedure) SettingsManager(uk.ac.sussex.gdsc.smlm.ij.settings.SettingsManager) XyrResultProcedure(uk.ac.sussex.gdsc.smlm.results.procedures.XyrResultProcedure) UniformRandomProvider(org.apache.commons.rng.UniformRandomProvider) Files(java.nio.file.Files) BufferedWriter(java.io.BufferedWriter) ExtendedGenericDialog(uk.ac.sussex.gdsc.core.ij.gui.ExtendedGenericDialog) IOException(java.io.IOException) NamedObject(uk.ac.sussex.gdsc.smlm.data.NamedObject) DistanceUnit(uk.ac.sussex.gdsc.smlm.data.config.UnitProtos.DistanceUnit) Logger(java.util.logging.Logger) SamplerUtils(uk.ac.sussex.gdsc.core.utils.rng.SamplerUtils) AttributePeakResult(uk.ac.sussex.gdsc.smlm.results.AttributePeakResult) TextUtils(uk.ac.sussex.gdsc.core.utils.TextUtils) Plot(ij.gui.Plot) TIntHashSet(gnu.trove.set.hash.TIntHashSet) TimeUnit(uk.ac.sussex.gdsc.smlm.data.config.UnitProtos.TimeUnit) XyzrResultProcedure(uk.ac.sussex.gdsc.smlm.results.procedures.XyzrResultProcedure) List(java.util.List) Counter(uk.ac.sussex.gdsc.smlm.results.count.Counter) Paths(java.nio.file.Paths) ImageJUtils(uk.ac.sussex.gdsc.core.ij.ImageJUtils) IJ(ij.IJ) SimpleArrayUtils(uk.ac.sussex.gdsc.core.utils.SimpleArrayUtils) Mat5(us.hebi.matlab.mat.format.Mat5) PlugIn(ij.plugin.PlugIn) NormalizedGaussianSampler(org.apache.commons.rng.sampling.distribution.NormalizedGaussianSampler) TypeConverter(uk.ac.sussex.gdsc.core.data.utils.TypeConverter) LocalList(uk.ac.sussex.gdsc.core.utils.LocalList) UniformRandomProviders(uk.ac.sussex.gdsc.core.utils.rng.UniformRandomProviders) TimeUnit(uk.ac.sussex.gdsc.smlm.data.config.UnitProtos.TimeUnit) IOException(java.io.IOException) BufferedWriter(java.io.BufferedWriter)

Example 3 with TimeUnit

use of uk.ac.sussex.gdsc.smlm.data.config.UnitProtos.TimeUnit in project GDSC-SMLM by aherbert.

the class LoadLocalisations method getFields.

private static boolean getFields(LoadLocalisationsSettings.Builder settings) {
    settings.getLocalisationsFilename();
    final ExtendedGenericDialog gd = new ExtendedGenericDialog(TITLE);
    gd.addMessage("Load delimited localisations");
    // Show a preview of the file in a text area
    final List<String> preview = loadLines(settings, 100);
    if (!preview.isEmpty()) {
        // Add a TextArea. This cannot add scroll bars after the constructor so we put up
        // with this. But we can use a monospaced font and size the text area nicely.
        gd.addTextAreas(preview.stream().collect(Collectors.joining("\n")), null, Math.min(10, preview.size()), Math.min(80, preview.stream().mapToInt(String::length).max().getAsInt()));
        final TextArea ta = gd.getTextArea1();
        final Font font = new Font(Font.MONOSPACED, Font.PLAIN, (int) (10 * Prefs.getGuiScale()));
        ta.setFont(font);
        ta.setEditable(false);
    }
    if (!settings.getHideFieldDatasetName()) {
        gd.addStringField("Dataset_name", settings.getName(), 30);
    }
    gd.addMessage("Calibration:");
    // Allow the full camera type top be captured
    final Calibration.Builder calibrationBuilder = settings.getCalibrationBuilder();
    final CalibrationWriter cw = new CalibrationWriter(calibrationBuilder);
    PeakFit.addCameraOptions(gd, 0, cw);
    // Only primitive support for other calibration
    gd.addNumericField("Pixel_size", cw.getNmPerPixel(), 3, 8, "nm");
    gd.addNumericField("Exposure_time", cw.getExposureTime(), 3, 8, "");
    // This is the unit for the exposure time (used to convert the exposure time to milliseconds).
    // Use the name as the list is a truncated list of the full enum.
    final TimeUnit t = calibrationBuilder.getTimeCalibration().getTimeUnit();
    gd.addChoice("Time_unit", TimeUnitLoader.getTimeUnits(), SettingsManager.getName(UnitHelper.getName(t), UnitHelper.getShortName(t)));
    gd.addMessage("Records:");
    gd.addNumericField("Header_lines", settings.getHeaderLines(), 0);
    gd.addStringField("Comment", settings.getComment());
    gd.addStringField("Delimiter", settings.getDelimiter());
    gd.addChoice("Distance_unit", SettingsManager.getDistanceUnitNames(), cw.getDistanceUnitValue());
    gd.addChoice("Intensity_unit", SettingsManager.getIntensityUnitNames(), cw.getIntensityUnitValue());
    gd.addMessage("Define the fields:");
    gd.addNumericField("Frame", settings.getFieldT(), 0);
    gd.addNumericField("ID", settings.getFieldId(), 0);
    gd.addNumericField("Category", settings.getFieldCategory(), 0);
    gd.addNumericField("X", settings.getFieldX(), 0);
    gd.addNumericField("Y", settings.getFieldY(), 0);
    gd.addNumericField("Z", settings.getFieldZ(), 0);
    gd.addNumericField("Intensity", settings.getFieldI(), 0);
    gd.addNumericField("Sx", settings.getFieldSx(), 0);
    gd.addNumericField("Sy", settings.getFieldSy(), 0);
    gd.addNumericField("Precision", settings.getFieldPrecision(), 0);
    gd.addChoice("Precision_method", SettingsManager.getPrecisionMethodNames(), cw.getPrecisionMethodValue());
    gd.addHelp(HelpUrls.getUrl("load-localisations"));
    gd.showDialog();
    if (gd.wasCanceled()) {
        return false;
    }
    if (!settings.getHideFieldDatasetName()) {
        settings.setName(getNextString(gd, settings.getName()));
    }
    cw.setCameraType(SettingsManager.getCameraTypeValues()[gd.getNextChoiceIndex()]);
    cw.setNmPerPixel(gd.getNextNumber());
    cw.setExposureTime(gd.getNextNumber());
    // The time units used a truncated list so look-up the value from the index
    calibrationBuilder.getTimeCalibrationBuilder().setTimeUnit(TimeUnitLoader.getTimeUnitValues()[gd.getNextChoiceIndex()]);
    settings.setHeaderLines((int) gd.getNextNumber());
    settings.setComment(gd.getNextString());
    settings.setDelimiter(getNextString(gd, settings.getDelimiter()));
    cw.setDistanceUnit(DistanceUnit.forNumber(gd.getNextChoiceIndex()));
    cw.setIntensityUnit(IntensityUnit.forNumber(gd.getNextChoiceIndex()));
    final int[] columns = new int[10];
    for (int i = 0; i < columns.length; i++) {
        columns[i] = (int) gd.getNextNumber();
    }
    int index = 0;
    settings.setFieldT(columns[index++]);
    settings.setFieldId(columns[index++]);
    settings.setFieldCategory(columns[index++]);
    settings.setFieldX(columns[index++]);
    settings.setFieldY(columns[index++]);
    settings.setFieldZ(columns[index++]);
    settings.setFieldI(columns[index++]);
    settings.setFieldSx(columns[index++]);
    settings.setFieldSy(columns[index++]);
    settings.setFieldPrecision(columns[index]);
    cw.setPrecisionMethod(PrecisionMethod.forNumber(gd.getNextChoiceIndex()));
    // Collect the camera calibration
    gd.collectOptions();
    // Validate after reading the dialog (so we store the last entered values)
    if (gd.invalidNumber()) {
        IJ.error(TITLE, "Invalid number in input fields");
        return false;
    }
    for (int i = 0; i < columns.length; i++) {
        if (columns[i] < 0) {
            continue;
        }
        for (int j = i + 1; j < columns.length; j++) {
            if (columns[j] < 0) {
                continue;
            }
            if (columns[i] == columns[j]) {
                IJ.error(TITLE, "Duplicate indicies: " + columns[i]);
                return false;
            }
        }
    }
    if (cw.getNmPerPixel() <= 0) {
        IJ.error(TITLE, "Require positive pixel pitch");
        return false;
    }
    if (cw.isCcdCamera()) {
        if (!cw.hasCountPerPhoton()) {
            IJ.error(TITLE, "Require positive count/photon for CCD camera type");
            return false;
        }
    } else {
    // Q.Validate other camera types?
    }
    if (settings.getFieldX() < 0 || settings.getFieldY() < 0) {
        IJ.error(TITLE, "Require valid X and Y indices");
        return false;
    }
    return true;
}
Also used : TextArea(java.awt.TextArea) CalibrationWriter(uk.ac.sussex.gdsc.smlm.data.config.CalibrationWriter) TimeUnit(uk.ac.sussex.gdsc.smlm.data.config.UnitProtos.TimeUnit) ExtendedGenericDialog(uk.ac.sussex.gdsc.core.ij.gui.ExtendedGenericDialog) Calibration(uk.ac.sussex.gdsc.smlm.data.config.CalibrationProtos.Calibration) Font(java.awt.Font)

Example 4 with TimeUnit

use of uk.ac.sussex.gdsc.smlm.data.config.UnitProtos.TimeUnit in project GDSC-SMLM by aherbert.

the class TraceMolecules method runOptimiser.

private void runOptimiser(TraceManager manager) {
    // Get an estimate of the number of molecules without blinking
    final Statistics stats = new Statistics();
    final double nmPerPixel = this.results.getNmPerPixel();
    final PrecisionResultProcedure pp = new PrecisionResultProcedure(results);
    pp.getPrecision();
    stats.add(pp.precisions);
    // Use twice the precision to get the initial distance threshold
    // Use 2.5x sigma as per the PC-PALM protocol in Sengupta, et al (2013) Nature Protocols 8, 345
    final double dEstimate = stats.getMean() * 2.5 / nmPerPixel;
    final int traceCount = manager.traceMolecules(dEstimate, 1);
    if (!getParameters(traceCount, dEstimate)) {
        return;
    }
    // TODO - Convert the distance threshold to use nm instead of pixels?
    final List<double[]> results = runTracing(manager, settings.getMinDistanceThreshold(), settings.getMaxDistanceThreshold(), settings.getMinTimeThreshold(), settings.getMaxTimeThreshold(), settings.getOptimiserSteps());
    // Compute fractional difference from the true value:
    // Use blinking rate directly or the estimated number of molecules
    double reference;
    int statistic;
    if (optimiseBlinkingRate) {
        reference = settings.getBlinkingRate();
        statistic = 3;
        IJ.log(String.format("Estimating blinking rate: %.2f", reference));
    } else {
        reference = traceCount / settings.getBlinkingRate();
        statistic = 2;
        IJ.log(String.format("Estimating number of molecules: %d / %.2f = %.2f", traceCount, settings.getBlinkingRate(), reference));
    }
    for (final double[] result : results) {
        if (optimiseBlinkingRate) {
            result[2] = (reference - result[statistic]) / reference;
        } else {
            result[2] = (result[statistic] - reference) / reference;
        }
    }
    // Locate the optimal parameters with a fit of the zero contour
    final boolean found = findOptimalParameters(results);
    createPlotResults(results);
    if (!found) {
        return;
    }
    // Make fractional difference absolute so that lowest is best
    for (final double[] result : results) {
        result[2] = Math.abs(result[2]);
    }
    // Set the optimal thresholds using the lowest value
    double[] best = new double[] { 0, 0, Double.MAX_VALUE };
    for (final double[] result : results) {
        if (best[2] > result[2]) {
            best = result;
        }
    }
    settings.setDistanceThreshold(best[0]);
    // The optimiser works using frames so convert back to the correct units
    final TypeConverter<TimeUnit> convert = UnitConverterUtils.createConverter(TimeUnit.FRAME, settings.getTimeUnit(), getExposureTimeInMilliSeconds());
    settings.setTimeThreshold(convert.convert(best[1]));
    IJ.log(String.format("Optimal fractional difference @ D-threshold=%g nm, T-threshold=%f s (%d frames)", settings.getDistanceThreshold(), timeThresholdInSeconds(), timeThresholdInFrames()));
    writeSettings();
}
Also used : TimeUnit(uk.ac.sussex.gdsc.smlm.data.config.UnitProtos.TimeUnit) PrecisionResultProcedure(uk.ac.sussex.gdsc.smlm.results.procedures.PrecisionResultProcedure) 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 5 with TimeUnit

use of uk.ac.sussex.gdsc.smlm.data.config.UnitProtos.TimeUnit in project GDSC-SMLM by aherbert.

the class TraceMolecules method findOptimalParameters.

/**
 * Find the contour that intersects zero on the fractional difference plot. Find the point on the
 * contour nearest the origin.
 *
 * @param results the results
 * @return true, if successful
 */
private boolean findOptimalParameters(List<double[]> results) {
    // This method only works if there are many results and if the results
    // cover enough of the search space to go from above zero (i.e. not enough traces)
    // to below zero (i.e. too many traces)
    final int maxx = timeThresholds.length;
    final int maxy = ddistanceThresholds.length;
    // --------
    // Find zero crossings using linear interpolation
    zeroCrossingPoints = new ArrayList<>();
    // --------
    // Pass across all time points
    boolean noZeroCrossingAtT0 = false;
    boolean noZeroCrossingAtTn = false;
    for (int x = 0; x < maxx; x++) {
        // Find zero crossings on distance points
        final double[] data = new double[maxy];
        for (int y = 0; y < maxy; y++) {
            final int i = y * maxx + x;
            final double[] result = results.get(i);
            data[y] = result[2];
        }
        final double zeroCrossing = findZeroCrossing(data, ddistanceThresholds);
        if (zeroCrossing > 0) {
            zeroCrossingPoints.add(new double[] { timeThresholds[x], zeroCrossing });
        } else if (x == 0) {
            noZeroCrossingAtT0 = true;
        } else if (x == maxx - 1) {
            noZeroCrossingAtTn = true;
        }
    }
    // If there were not enough zero crossings then the ranges are wrong
    if (zeroCrossingPoints.size() < 3) {
        IJ.log(String.format("Very few zero crossings (%d). Increase the optimisation space", zeroCrossingPoints.size()));
        return false;
    }
    // --------
    // Use relative distances to find the zero crossing with the smallest distance from origin
    // and set this as the optimal parameters
    // --------
    double minD = Double.MAX_VALUE;
    final double maxTimeThresholdInFrames = settings.getMaxTimeThreshold();
    // The optimiser works using frames so convert back to the correct units
    final TypeConverter<TimeUnit> convert = UnitConverterUtils.createConverter(TimeUnit.FRAME, settings.getTimeUnit(), getExposureTimeInMilliSeconds());
    for (final double[] point : zeroCrossingPoints) {
        final double dx = point[0] / maxTimeThresholdInFrames;
        final double dy = point[1] / settings.getMaxDistanceThreshold();
        final double d = dx * dx + dy * dy;
        if (d < minD) {
            minD = d;
            settings.setDistanceThreshold(point[1]);
            settings.setTimeThreshold(convert.convert(point[0]));
        }
    }
    // --------
    // Add more points to make the plotted line look better when showing the plot.
    // --------
    // Pass across all distance points
    boolean noZeroCrossingAtD0 = false;
    boolean noZeroCrossingAtDn = false;
    final double[] tThresholdsD = SimpleArrayUtils.toDouble(timeThresholds);
    for (int y = 0; y < maxy; y++) {
        // Find zero crossings on time points
        final double[] data = new double[maxx];
        for (int x = 0; x < maxx; x++) {
            final int i = y * maxx + x;
            final double[] result = results.get(i);
            data[x] = result[2];
        }
        final double zeroCrossing = findZeroCrossing(data, tThresholdsD);
        if (zeroCrossing > 0) {
            zeroCrossingPoints.add(new double[] { zeroCrossing, ddistanceThresholds[y] });
        } else if (y == 0) {
            noZeroCrossingAtD0 = true;
        } else if (y == maxy - 1) {
            noZeroCrossingAtDn = true;
        }
    }
    sortPoints();
    // --------
    // Output a message suggesting if the limits should be updated.
    // --------
    final StringBuilder sb = new StringBuilder();
    boolean reduceTime = false;
    boolean reduceDistance = false;
    if (noZeroCrossingAtDn && settings.getMinTimeThreshold() > 1) {
        sb.append(" * No zero crossing at max distance\n");
        reduceTime = true;
    }
    if (noZeroCrossingAtTn && settings.getMinDistanceThreshold() > 0) {
        sb.append(" * No zero crossing at max time\n");
        reduceDistance = true;
    }
    if (!noZeroCrossingAtD0 && settings.getMinDistanceThreshold() > 0) {
        sb.append(" * Zero crossing at min distance\n");
        reduceDistance = true;
    }
    if (!noZeroCrossingAtT0 && settings.getMinTimeThreshold() > 1) {
        sb.append(" * Zero crossing at min time\n");
        reduceTime = true;
    }
    if (reduceTime) {
        sb.append(" => Reduce the min time threshold\n");
    }
    if (reduceDistance) {
        sb.append(" => Reduce the min distance threshold\n");
    }
    if (sb.length() > 0) {
        sb.insert(0, "\nWarning:\n");
        sb.append("\n");
        IJ.log(sb.toString());
    }
    return true;
}
Also used : TimeUnit(uk.ac.sussex.gdsc.smlm.data.config.UnitProtos.TimeUnit) ClusterPoint(uk.ac.sussex.gdsc.core.clustering.ClusterPoint)

Aggregations

TimeUnit (uk.ac.sussex.gdsc.smlm.data.config.UnitProtos.TimeUnit)5 ClusterPoint (uk.ac.sussex.gdsc.core.clustering.ClusterPoint)2 ExtendedGenericDialog (uk.ac.sussex.gdsc.core.ij.gui.ExtendedGenericDialog)2 TIntHashSet (gnu.trove.set.hash.TIntHashSet)1 IJ (ij.IJ)1 Plot (ij.gui.Plot)1 PlugIn (ij.plugin.PlugIn)1 Font (java.awt.Font)1 TextArea (java.awt.TextArea)1 BufferedWriter (java.io.BufferedWriter)1 IOException (java.io.IOException)1 Files (java.nio.file.Files)1 Paths (java.nio.file.Paths)1 ArrayList (java.util.ArrayList)1 List (java.util.List)1 AtomicReference (java.util.concurrent.atomic.AtomicReference)1 Level (java.util.logging.Level)1 Logger (java.util.logging.Logger)1 SummaryStatistics (org.apache.commons.math3.stat.descriptive.SummaryStatistics)1 UniformRandomProvider (org.apache.commons.rng.UniformRandomProvider)1