package gdsc.smlm.results.filter;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
import com.thoughtworks.xstream.annotations.XStreamOmitField;
import gdsc.smlm.results.PeakResult;
/*-----------------------------------------------------------------------------
* 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;
/**
* Filter results using an amplitude-to-noise ratio (ANR) threshold and width range
*/
public class ANRFilter2 extends DirectFilter
{
@XStreamAsAttribute
final float anr;
@XStreamAsAttribute
final double minWidth;
@XStreamAsAttribute
final double maxWidth;
@XStreamOmitField
float lowerSigmaThreshold;
@XStreamOmitField
float upperSigmaThreshold;
@XStreamOmitField
boolean widthEnabled;
public ANRFilter2(float anr, double minWidth, double maxWidth)
{
this.anr = Math.max(0, anr);
// Only swap if max width is enabled
if (maxWidth != 0 && maxWidth < minWidth)
{
double f = maxWidth;
maxWidth = minWidth;
minWidth = f;
}
this.minWidth = Math.max(0, minWidth);
this.maxWidth = Math.max(0, maxWidth);
}
@Override
protected String generateName()
{
return "ANR " + anr + ", width " + minWidth + "-" + maxWidth;
}
@Override
public void setup(MemoryPeakResults peakResults)
{
// Set the width limit
lowerSigmaThreshold = 0;
upperSigmaThreshold = Float.POSITIVE_INFINITY;
Pattern pattern = Pattern.compile("initialSD0>([\\d\\.]+)");
Matcher match = pattern.matcher(peakResults.getConfiguration());
if (match.find())
{
double s = Double.parseDouble(match.group(1));
lowerSigmaThreshold = (float) (s * minWidth);
upperSigmaThreshold = (float) (s * maxWidth);
}
}
@Override
public void setup()
{
setup(true);
}
@Override
public void setup(int flags)
{
setup(!areSet(flags, DirectFilter.NO_WIDTH));
}
private void setup(final boolean widthEnabled)
{
this.widthEnabled = widthEnabled;
if (widthEnabled)
{
lowerSigmaThreshold = (float) minWidth;
upperSigmaThreshold = Filter.getUpperLimit(maxWidth);
}
}
@Override
public boolean accept(PeakResult peak)
{
return ANRFilter.getANR(peak) >= this.anr && peak.getSD() <= upperSigmaThreshold &&
peak.getSD() >= lowerSigmaThreshold;
}
@Override
public int validate(final PreprocessedPeakResult peak)
{
if (ANRFilter.getANR(peak) < this.anr)
return V_AMPLITUDE | V_NOISE;
if (widthEnabled)
{
if (peak.getXSDFactor() > upperSigmaThreshold && peak.getXSDFactor() < lowerSigmaThreshold)
return V_X_SD_FACTOR;
}
return 0;
}
/*
* (non-Javadoc)
*
* @see gdsc.smlm.results.filter.Filter#getDescription()
*/
@Override
public String getDescription()
{
return "Filter results using a lower ANR threshold and width range. (Width is relative to initial peak width.)";
}
/*
* (non-Javadoc)
*
* @see gdsc.smlm.results.filter.Filter#getNumberOfParameters()
*/
@Override
public int getNumberOfParameters()
{
return 3;
}
/*
* (non-Javadoc)
*
* @see gdsc.smlm.results.filter.Filter#getParameterValueInternal(int)
*/
@Override
protected double getParameterValueInternal(int index)
{
switch (index)
{
case 0:
return anr;
case 1:
return minWidth;
default:
return maxWidth;
}
}
/*
* (non-Javadoc)
*
* @see gdsc.smlm.results.filter.Filter#getParameterIncrement(int)
*/
@Override
public double getParameterIncrement(int index)
{
checkIndex(index);
switch (index)
{
case 0:
return SNRFilter.DEFAULT_INCREMENT;
case 1:
return WidthFilter2.DEFAULT_MIN_INCREMENT;
default:
return WidthFilter.DEFAULT_INCREMENT;
}
}
/*
* (non-Javadoc)
*
* @see gdsc.smlm.results.filter.Filter#getParameterType(int)
*/
@Override
public ParameterType getParameterType(int index)
{
checkIndex(index);
switch (index)
{
case 0:
return ParameterType.ANR;
case 1:
return ParameterType.MIN_WIDTH;
default:
return ParameterType.MAX_WIDTH;
}
}
/*
* (non-Javadoc)
*
* @see gdsc.smlm.results.filter.Filter#adjustParameter(int, double)
*/
@Override
public Filter adjustParameter(int index, double delta)
{
checkIndex(index);
switch (index)
{
case 0:
return new ANRFilter2(updateParameter(anr, delta, SNRFilter.DEFAULT_RANGE), minWidth, maxWidth);
case 1:
return new ANRFilter2(anr, updateParameter(minWidth, delta, WidthFilter2.DEFAULT_MIN_RANGE), maxWidth);
default:
return new ANRFilter2(anr, minWidth, updateParameter(maxWidth, delta, WidthFilter.DEFAULT_RANGE));
}
}
/*
* (non-Javadoc)
*
* @see gdsc.smlm.results.filter.Filter#create(double[])
*/
@Override
public Filter create(double... parameters)
{
return new ANRFilter2((float) parameters[0], parameters[1], parameters[2]);
}
/*
* (non-Javadoc)
*
* @see gdsc.smlm.results.filter.Filter#weakestParameters(double[])
*/
@Override
public void weakestParameters(double[] parameters)
{
setMin(parameters, 0, anr);
setMin(parameters, 1, minWidth);
setMax(parameters, 2, maxWidth);
}
/*
* (non-Javadoc)
*
* @see gdsc.smlm.results.filter.DirectFilter#lowerBoundOrientation(int)
*/
@Override
public int lowerBoundOrientation(int index)
{
return (index == 2) ? 1 : -1;
}
/*
* (non-Javadoc)
*
* @see gdsc.smlm.ga.Chromosome#mutationStepRange()
*/
public double[] mutationStepRange()
{
return new double[] { SNRFilter.DEFAULT_RANGE, WidthFilter2.DEFAULT_MIN_RANGE, WidthFilter.DEFAULT_RANGE };
}
}