package gdsc.smlm.engine.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.fitting.FitResult; import gdsc.smlm.results.PeakResult; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.TreeSet; /** * Filter the results using the distance to a set of coordinates. Positions must be within the distance threshold. * Fitted peaks are selected first and in the event of multiple results the peak with the strongest signal is * selected. Otherwise failed starting positions are selected and in the event of multiple results the closest * position will be chosen. */ public class OptimumDistanceResultFilter extends ResultFilter { private FitResult[] bestFitResults; private int[] bestIndices; private float[] bestD2; private float[] bestSignal; private PeakResult[] bestPeakResults; public OptimumDistanceResultFilter(List<float[]> filter, float d, int nMaxima) { super(filter, d, nMaxima); bestFitResults = new FitResult[filter.size()]; bestIndices = new int[filter.size()]; bestD2 = new float[filter.size()]; Arrays.fill(bestD2, d2); bestSignal = new float[filter.size()]; bestPeakResults = new PeakResult[filter.size()]; } /* * (non-Javadoc) * * @see gdsc.smlm.engine.filter.ResultFilter#filter(gdsc.smlm.fitting.FitResult, int, * gdsc.smlm.results.PeakResult[]) */ @Override public void filter(FitResult fitResult, int maxIndex, PeakResult... results) { for (PeakResult r : results) { if (r == null) continue; for (int i = 0; i < filter.size(); i++) { float[] coord = filter.get(i); final float dx = r.getXPosition() - coord[0]; final float dy = r.getYPosition() - coord[1]; // Only check if within the distance threshold if (dx * dx + dy * dy < d2) { // Then filter by signal strength float s = r.getSignal(); if (s < bestSignal[i]) continue; bestFitResults[i] = fitResult; bestIndices[i] = maxIndex; bestSignal[i] = s; bestPeakResults[i] = r; } } } } /* * (non-Javadoc) * * @see gdsc.smlm.engine.filter.ResultFilter#filter(gdsc.smlm.fitting.FitResult, int, float, float) */ @Override public void filter(FitResult fitResult, int maxIndex, float x, float y) { for (int i = 0; i < filter.size(); i++) { // Skip if there is a peak result for this target coordinate if (bestPeakResults[i] != null) continue; float[] coord = filter.get(i); final float dx = x - coord[0]; final float dy = y - coord[1]; final float dd = dx * dx + dy * dy; // Check if this starting position is the closest if (dd < bestD2[i]) { bestFitResults[i] = fitResult; bestIndices[i] = maxIndex; bestD2[i] = dd; } } } /* * (non-Javadoc) * * @see gdsc.smlm.engine.filter.ResultFilter#finalise() */ @Override public void finalise() { // Note that there could be the same result allocated to two target positions // so find the unique results int[] uniqueIndices = new int[bestIndices.length]; int unique = 0; for (int i = 0; i < bestIndices.length; i++) { if (bestFitResults[i] == null) continue; boolean found = false; for (int j = unique; j-- > 0;) { if (bestIndices[uniqueIndices[j]] == bestIndices[i]) { found = true; break; } } if (!found) uniqueIndices[unique++] = i; } // The fit results and the indices must match so preserve the same order filteredCount = unique; filteredFitResults = new FitResult[unique]; filteredIndices = new int[unique]; for (int i = 0; i < unique; i++) { filteredFitResults[i] = bestFitResults[uniqueIndices[i]]; filteredIndices[i] = bestIndices[uniqueIndices[i]]; } // The peak results can be in any order so use a set to find the unique results if (unique > 0) { TreeSet<PeakResult> set = new TreeSet<PeakResult>(); for (PeakResult r : bestPeakResults) { if (r != null) set.add(r); } peakResults = new ArrayList<PeakResult>(set.size()); peakResults.addAll(set); } else { peakResults = new ArrayList<PeakResult>(); } } }