package gdsc.smlm.results.filter; /*----------------------------------------------------------------------------- * 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.MemoryPeakResults; import gdsc.smlm.results.PeakResult; import com.thoughtworks.xstream.annotations.XStreamAsAttribute; import com.thoughtworks.xstream.annotations.XStreamOmitField; /** * Filter results using a signal-to-background ratio (SBR) threshold. * <p> * Requires the bias to be configured at or above zero. If the background is below the configured bias or there is no * bias then the filter resorts to a signal-to-noise filter. If there is a background level above the bias then this is * assumed to be the variance of the photon shot noise and the noise is taken at the square root of the background * level. */ public class SBRFilter extends DirectFilter { @XStreamAsAttribute final float sbr; @XStreamOmitField double bias = -1; public SBRFilter(float sbr) { this.sbr = Math.max(0, sbr); } @Override public void setup(MemoryPeakResults peakResults) { bias = -1; if (peakResults.getCalibration() != null) { if (peakResults.getCalibration().getBias() >= 0) bias = peakResults.getCalibration().getBias(); } } @Override public boolean accept(PeakResult peak) { if (bias != -1) { final double background = peak.getBackground() - bias; if (background > 0) return peak.getSignal() / Math.sqrt(background) >= this.sbr; } return SNRFilter.getSNR(peak) >= this.sbr; } @Override public int validate(final PreprocessedPeakResult peak) { if (bias != -1) { // This is not preprocessed final double background = peak.getBackground() - bias; if (background > 0) { if (peak.getSignal() / Math.sqrt(background) < this.sbr) return V_PHOTONS | V_BACKGROUND; return 0; } } if (peak.getSNR() < this.sbr) return V_SNR; return 0; } /* * (non-Javadoc) * * @see gdsc.smlm.results.filter.Filter#getDescription() */ @Override public String getDescription() { return "Filter results using a lower SBR threshold."; } /* * (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 sbr; } /* * (non-Javadoc) * * @see gdsc.smlm.results.filter.Filter#getParameterIncrement(int) */ @Override public double getParameterIncrement(int index) { checkIndex(index); return SNRFilter.DEFAULT_INCREMENT; } /* * (non-Javadoc) * * @see gdsc.smlm.results.filter.Filter#getParameterType(int) */ @Override public ParameterType getParameterType(int index) { checkIndex(index); return ParameterType.SBR; } /* * (non-Javadoc) * * @see gdsc.smlm.results.filter.Filter#adjustParameter(int, double) */ @Override public Filter adjustParameter(int index, double delta) { checkIndex(index); return new SBRFilter(updateParameter(sbr, delta, SNRFilter.DEFAULT_RANGE)); } /* * (non-Javadoc) * * @see gdsc.smlm.results.filter.Filter#create(double[]) */ @Override public Filter create(double... parameters) { return new SBRFilter((float) parameters[0]); } /* * (non-Javadoc) * * @see gdsc.smlm.results.filter.Filter#weakestParameters(double[]) */ @Override public void weakestParameters(double[] parameters) { setMin(parameters, 0, sbr); } /* * (non-Javadoc) * * @see gdsc.smlm.ga.Chromosome#mutationStepRange() */ public double[] mutationStepRange() { return new double[] { SNRFilter.DEFAULT_RANGE }; } }