package gdsc.smlm.results.filter; import com.thoughtworks.xstream.annotations.XStreamAsAttribute; import com.thoughtworks.xstream.annotations.XStreamOmitField; import gdsc.smlm.results.MemoryPeakResults; /*----------------------------------------------------------------------------- * GDSC SMLM Software * * Copyright (C) 2013 Alex Herbert * Genome Damage and Stability Centre * University of Sussex, UK * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. *---------------------------------------------------------------------------*/ import gdsc.smlm.results.PeakResult; /** * Filter results using a precision threshold. Calculates the precision using the true fitted background if a bias is * provided. */ public class PrecisionFilter2 extends DirectFilter implements IMultiFilter { @XStreamAsAttribute final double precision; @XStreamOmitField double variance; @XStreamOmitField double nmPerPixel = 100; @XStreamOmitField boolean emCCD = true; @XStreamOmitField double bias = -1; @XStreamOmitField double gain = 1; public PrecisionFilter2(double precision) { this.precision = Math.max(0, precision); } @Override public void setup(MemoryPeakResults peakResults) { variance = Filter.getDUpperSquaredLimit(precision); nmPerPixel = peakResults.getNmPerPixel(); gain = peakResults.getGain(); emCCD = peakResults.isEMCCD(); bias = -1; if (peakResults.getCalibration() != null) { bias = peakResults.getCalibration().getBias(); } } @Override public boolean accept(PeakResult peak) { final double s = nmPerPixel * peak.getSD(); final double N = peak.getSignal(); if (bias != -1) { // Use the estimated background for the peak return PeakResult.getVarianceX(nmPerPixel, s, N / gain, Math.max(0, peak.getBackground() - bias) / gain, emCCD) <= variance; } // Use the background noise to estimate precision return PeakResult.getVariance(nmPerPixel, s, N / gain, peak.getNoise() / gain, emCCD) <= variance; } @Override public int validate(final PreprocessedPeakResult peak) { if (peak.getLocationVariance2() > variance) return V_LOCATION_VARIANCE2; return 0; } /* * (non-Javadoc) * * @see gdsc.smlm.results.filter.Filter#getDescription() */ @Override public String getDescription() { return "Filter results using an upper precision threshold (uses fitted background to set noise)."; } /* * (non-Javadoc) * * @see gdsc.smlm.results.filter.Filter#getNumberOfParameters() */ @Override public int getNumberOfParameters() { return 1; } /* * (non-Javadoc) * * @see gdsc.smlm.results.filter.Filter#getParameterValueInternal(int) */ @Override protected double getParameterValueInternal(int index) { return precision; } /* * (non-Javadoc) * * @see gdsc.smlm.results.filter.Filter#getParameterIncrement(int) */ @Override public double getParameterIncrement(int index) { checkIndex(index); return PrecisionFilter.DEFAULT_INCREMENT; } /* * (non-Javadoc) * * @see gdsc.smlm.results.filter.Filter#getParameterType(int) */ @Override public ParameterType getParameterType(int index) { checkIndex(index); return ParameterType.PRECISION2; } /* * (non-Javadoc) * * @see gdsc.smlm.results.filter.Filter#adjustParameter(int, double) */ @Override public Filter adjustParameter(int index, double delta) { checkIndex(index); return new PrecisionFilter2(updateParameter(precision, delta, PrecisionFilter.DEFAULT_RANGE)); } /* * (non-Javadoc) * * @see gdsc.smlm.results.filter.Filter#create(double[]) */ @Override public Filter create(double... parameters) { return new PrecisionFilter2(parameters[0]); } /* * (non-Javadoc) * * @see gdsc.smlm.results.filter.Filter#weakestParameters(double[]) */ @Override public void weakestParameters(double[] parameters) { setMax(parameters, 0, precision); } /* * (non-Javadoc) * * @see gdsc.smlm.results.filter.DirectFilter#lowerBoundOrientation(int) */ @Override public int lowerBoundOrientation(int index) { return 1; } /* * (non-Javadoc) * * @see gdsc.smlm.results.filter.Filter#upperLimit() */ @Override public double[] upperLimit() { return new double[] { PrecisionFilter.UPPER_LIMIT }; } /* * (non-Javadoc) * * @see gdsc.smlm.ga.Chromosome#mutationStepRange() */ public double[] mutationStepRange() { return new double[] { PrecisionFilter.DEFAULT_RANGE }; } public double getSignal() { return 0; } public double getSNR() { return 0; } public double getMinWidth() { return 0; } public double getMaxWidth() { return 0; } public double getShift() { return 0; } public double getEShift() { return 0; } public double getPrecision() { return precision; } public boolean isPrecisionUsesLocalBackground() { return true; } }