Program: 149540
Project: 149540
Buggy source:
private void summariseResults(HashMap<Integer,FilterCandidates> filterCandidates,long runTime,PreprocessedPeakResult[] preprocessedPeakResults){
  createTable();
  StoredDataStatistics distanceStats=new StoredDataStatistics();
  StoredDataStatistics depthStats=new StoredDataStatistics();
  createFilterCriteria();
  StoredDataStatistics[][] stats=new StoredDataStatistics[3][filterCriteria.length];
  for (int i=0; i < stats.length; i++)   for (int j=0; j < stats[i].length; j++)   stats[i][j]=new StoredDataStatistics();
  final double nmPerPixel=simulationParameters.a;
  double tp=0, fp=0;
  int failcTP=0, failcFP=0;
  int cTP=0, cFP=0;
  int[] singleStatus=null, multiStatus=null, doubletStatus=null, multiDoubletStatus=null;
  singleStatus=new int[FitStatus.values().length];
  multiStatus=new int[singleStatus.length];
  doubletStatus=new int[singleStatus.length];
  multiDoubletStatus=new int[singleStatus.length];
  for (  FilterCandidates result : filterCandidates.values()) {
    tp+=result.tp;
    fp+=result.fp;
    for (int i=0; i < result.fitResult.length; i++) {
      if (result.spots[i].match)       cTP++;
 else       cFP++;
      final MultiPathFitResult fitResult=result.fitResult[i];
      if (singleStatus != null && result.spots[i].match) {
        addStatus(singleStatus,fitResult.getSingleFitResult());
        addStatus(multiStatus,fitResult.getMultiFitResult());
        addStatus(doubletStatus,fitResult.getDoubletFitResult());
        addStatus(multiDoubletStatus,fitResult.getMultiDoubletFitResult());
      }
      if (noMatch(fitResult)) {
        if (result.spots[i].match)         failcTP++;
 else         failcFP++;
      }
      addToStats(fitResult.getSingleFitResult(),stats);
      addToStats(fitResult.getMultiFitResult(),stats);
      addToStats(fitResult.getDoubletFitResult(),stats);
      addToStats(fitResult.getMultiDoubletFitResult(),stats);
    }
    for (int i=0; i < result.match.length; i++) {
      if (!result.match[i].isFitResult())       continue;
      FitMatch fitMatch=(FitMatch)result.match[i];
      distanceStats.add(fitMatch.d * nmPerPixel);
      depthStats.add(fitMatch.z * nmPerPixel);
    }
  }
  double[] i1=new double[depthStats.getN()];
  double[] i2=new double[i1.length];
  double[] is=new double[i1.length];
  int ci=0;
  for (  FilterCandidates result : filterCandidates.values()) {
    for (int i=0; i < result.match.length; i++) {
      if (!result.match[i].isFitResult())       continue;
      FitMatch fitMatch=(FitMatch)result.match[i];
      ScoredSpot spot=result.spots[fitMatch.i];
      i1[ci]=fitMatch.predictedSignal;
      i2[ci]=fitMatch.actualSignal;
      is[ci]=spot.spot.intensity;
      ci++;
    }
  }
  ArrayList<MultiPathFitResults> multiPathResults=new ArrayList<MultiPathFitResults>(filterCandidates.size());
  for (  Entry<Integer,FilterCandidates> entry : filterCandidates.entrySet()) {
    int frame=entry.getKey();
    MultiPathFitResult[] multiPathFitResults=entry.getValue().fitResult;
    int totalCandidates=multiPathFitResults.length;
    int nActual=actualCoordinates.get(frame).size();
    multiPathResults.add(new MultiPathFitResults(frame,multiPathFitResults,totalCandidates,nActual));
  }
  List<FractionalAssignment[]> assignments=new ArrayList<FractionalAssignment[]>();
  final Set<Integer> set=new TreeSet<Integer>();
  FractionScoreStore scoreStore=new FractionScoreStore(){
    public void add(    int uniqueId){
      set.add(uniqueId);
    }
  }
;
  MultiPathFitResults[] multiResults=multiPathResults.toArray(new MultiPathFitResults[multiPathResults.size()]);
  MultiPathFilter mpf=new MultiPathFilter(new SignalFilter(0),null,multiFilter.residualsThreshold);
  FractionClassificationResult fractionResult=mpf.fractionScoreSubset(multiResults,Integer.MAX_VALUE,this.results.size(),assignments,scoreStore);
  double nPredicted=fractionResult.getTP() + fractionResult.getFP();
  double[][] matchScores=new double[set.size()][];
  int count=0;
  for (int i=0; i < assignments.size(); i++) {
    FractionalAssignment[] a=assignments.get(i);
    if (a == null)     continue;
    for (int j=0; j < a.length; j++) {
      final PreprocessedPeakResult r=((PeakFractionalAssignment)a[j]).peakResult;
      set.remove(r.getUniqueId());
      final double precision=Math.sqrt(r.getLocationVariance());
      final double signal=r.getSignal();
      final double snr=r.getSNR();
      final double width=r.getXSDFactor();
      final double xShift=r.getXRelativeShift2();
      final double yShift=r.getYRelativeShift2();
      final double shift=(xShift > yShift) ? Math.sqrt(xShift) : Math.sqrt(yShift);
      final double eshift=Math.sqrt(xShift + yShift);
      final double[] score=new double[8];
      score[FILTER_SIGNAL]=signal;
      score[FILTER_SNR]=snr;
      score[FILTER_MIN_WIDTH]=width;
      score[FILTER_MAX_WIDTH]=width;
      score[FILTER_SHIFT]=shift;
      score[FILTER_ESHIFT]=eshift;
      score[FILTER_PRECISION]=precision;
      score[FILTER_PRECISION + 1]=a[j].getScore();
      matchScores[count++]=score;
    }
  }
  for (  int uniqueId : set.toArray(new Integer[0])) {
    PreprocessedPeakResult r=preprocessedPeakResults[uniqueId];
    if (r == null)     throw new RuntimeException("String_Node_Str" + uniqueId);
    final double precision=Math.sqrt(r.getLocationVariance());
    final double signal=r.getSignal();
    final double snr=r.getSNR();
    final double width=r.getXSDFactor();
    final double xShift=r.getXRelativeShift2();
    final double yShift=r.getYRelativeShift2();
    final double shift=(xShift > yShift) ? Math.sqrt(xShift) : Math.sqrt(yShift);
    final double eshift=Math.sqrt(xShift + yShift);
    final double[] score=new double[8];
    score[FILTER_SIGNAL]=signal;
    score[FILTER_SNR]=snr;
    score[FILTER_MIN_WIDTH]=width;
    score[FILTER_MAX_WIDTH]=width;
    score[FILTER_SHIFT]=shift;
    score[FILTER_ESHIFT]=eshift;
    score[FILTER_PRECISION]=precision;
    matchScores[count++]=score;
  }
  if (singleStatus != null) {
    String name=PeakFit.getSolverName(fitConfig);
    if (fitConfig.getFitSolver() == FitSolver.MLE && fitConfig.isModelCamera())     name+="String_Node_Str";
    System.out.println("String_Node_Str" + name);
    printFailures("String_Node_Str",singleStatus);
    printFailures("String_Node_Str",multiStatus);
    printFailures("String_Node_Str",doubletStatus);
    printFailures("String_Node_Str",multiDoubletStatus);
  }
  StringBuilder sb=new StringBuilder();
  final double signal=simulationParameters.signalPerFrame;
  final int n=results.size();
  sb.append(imp.getStackSize()).append("String_Node_Str");
  final int w=imp.getWidth();
  final int h=imp.getHeight();
  sb.append(w).append("String_Node_Str");
  sb.append(h).append("String_Node_Str");
  sb.append(n).append("String_Node_Str");
  double density=((double)n / imp.getStackSize()) / (w * h) / (simulationParameters.a * simulationParameters.a / 1e6);
  sb.append(Utils.rounded(density)).append("String_Node_Str");
  sb.append(Utils.rounded(signal)).append("String_Node_Str");
  sb.append(Utils.rounded(simulationParameters.s)).append("String_Node_Str");
  sb.append(Utils.rounded(simulationParameters.a)).append("String_Node_Str");
  sb.append(Utils.rounded(simulationParameters.depth)).append("String_Node_Str");
  sb.append(simulationParameters.fixedDepth).append("String_Node_Str");
  sb.append(Utils.rounded(simulationParameters.gain)).append("String_Node_Str");
  sb.append(Utils.rounded(simulationParameters.readNoise)).append("String_Node_Str");
  sb.append(Utils.rounded(simulationParameters.b)).append("String_Node_Str");
  sb.append(Utils.rounded(simulationParameters.b2)).append("String_Node_Str");
  double noise=simulationParameters.b2;
  if (simulationParameters.emCCD) {
    final double readVariance=noise - simulationParameters.b;
    noise=simulationParameters.b * 2 + readVariance;
  }
  if (simulationParameters.fullSimulation) {
  }
  sb.append(Utils.rounded(signal / Math.sqrt(noise))).append("String_Node_Str");
  sb.append(Utils.rounded(simulationParameters.s / simulationParameters.a)).append("String_Node_Str");
  sb.append(spotFilter.getDescription());
  addCount(sb,nP + nN);
  addCount(sb,nP);
  addCount(sb,nN);
  addCount(sb,fP);
  addCount(sb,fN);
  String name=PeakFit.getSolverName(fitConfig);
  if (fitConfig.getFitSolver() == FitSolver.MLE && fitConfig.isModelCamera())   name+="String_Node_Str";
  add(sb,name);
  add(sb,config.getFitting());
  resultPrefix=sb.toString();
  add(sb,(100.0 * cTP) / nP);
  add(sb,(100.0 * cFP) / nN);
  add(sb,cTP + cFP);
  add(sb,cTP);
  add(sb,cFP);
  FractionClassificationResult m=new FractionClassificationResult(cTP,cFP,0,simulationParameters.molecules - cTP);
  add(sb,m.getRecall());
  add(sb,m.getPrecision());
  add(sb,m.getF1Score());
  add(sb,m.getJaccard());
  add(sb,failcTP);
  add(sb,failcFP);
  add(sb,tp);
  add(sb,fp);
  m=new FractionClassificationResult(tp,fp,0,simulationParameters.molecules - tp);
  add(sb,m.getRecall());
  add(sb,m.getPrecision());
  add(sb,m.getF1Score());
  add(sb,m.getJaccard());
  m=new FractionClassificationResult(tp,0,0,simulationParameters.molecules - tp);
  add(sb,m.getF1Score());
  add(sb,m.getJaccard());
  double median=distanceStats.getMedian();
  add(sb,median);
  WindowOrganiser wo=new WindowOrganiser();
  String label=String.format("String_Node_Str",Utils.rounded(m.getRecall()),distanceStats.getN(),Utils.rounded(median),Utils.rounded(distanceStats.getStandardDeviation()));
  int id=Utils.showHistogram(TITLE,distanceStats,"String_Node_Str",0,0,0,label);
  if (Utils.isNewWindow())   wo.add(id);
  median=depthStats.getMedian();
  add(sb,median);
  int[] indices=Utils.newArray(i1.length,0,1);
  if (showCorrelation)   Sort.sort(indices,is,rankByIntensity);
  double[] r=(showCorrelation) ? new double[i1.length] : null;
  double[] sr=(showCorrelation) ? new double[i1.length] : null;
  double[] rank=(showCorrelation) ? new double[i1.length] : null;
  ci=0;
  FastCorrelator fastCorrelator=new FastCorrelator();
  ArrayList<Ranking> pc1=new ArrayList<Ranking>();
  ArrayList<Ranking> pc2=new ArrayList<Ranking>();
  for (  int ci2 : indices) {
    fastCorrelator.add((long)Math.round(i1[ci2]),(long)Math.round(i2[ci2]));
    pc1.add(new Ranking(i1[ci2],ci));
    pc2.add(new Ranking(i2[ci2],ci));
    if (showCorrelation) {
      r[ci]=fastCorrelator.getCorrelation();
      sr[ci]=Correlator.correlation(rank(pc1),rank(pc2));
      if (rankByIntensity)       rank[ci]=is[0] - is[ci];
 else       rank[ci]=ci;
    }
    ci++;
  }
  final double pearsonCorr=fastCorrelator.getCorrelation();
  final double rankedCorr=Correlator.correlation(rank(pc1),rank(pc2));
  SimpleRegression regression=new SimpleRegression(false);
  for (int i=0; i < pc1.size(); i++)   regression.addData(pc1.get(i).value,pc2.get(i).value);
  final double slope=regression.getSlope();
  if (showCorrelation) {
    String title=TITLE + "String_Node_Str";
    Plot plot=new Plot(title,"String_Node_Str","String_Node_Str");
    double[] limits1=Maths.limits(i1);
    double[] limits2=Maths.limits(i2);
    plot.setLimits(limits1[0],limits1[1],limits2[0],limits2[1]);
    label=String.format("String_Node_Str",Utils.rounded(pearsonCorr),Utils.rounded(rankedCorr),Utils.rounded(slope));
    plot.addLabel(0,0,label);
    plot.setColor(Color.red);
    plot.addPoints(i1,i2,Plot.DOT);
    if (slope > 1)     plot.drawLine(limits1[0],limits1[0] * slope,limits1[1],limits1[1] * slope);
 else     plot.drawLine(limits2[0] / slope,limits2[0],limits2[1] / slope,limits2[1]);
    PlotWindow pw=Utils.display(title,plot);
    if (Utils.isNewWindow())     wo.add(pw);
    title=TITLE + "String_Node_Str";
    plot=new Plot(title,"String_Node_Str","String_Node_Str");
    double[] xlimits=Maths.limits(rank);
    double[] ylimits=Maths.limits(r);
    ylimits=Maths.limits(ylimits,sr);
    plot.setLimits(xlimits[0],xlimits[1],ylimits[0],ylimits[1]);
    plot.setColor(Color.red);
    plot.addPoints(rank,r,Plot.LINE);
    plot.setColor(Color.blue);
    plot.addPoints(rank,sr,Plot.LINE);
    plot.setColor(Color.black);
    plot.addLabel(0,0,label);
    pw=Utils.display(title,plot);
    if (Utils.isNewWindow())     wo.add(pw);
  }
  add(sb,pearsonCorr);
  add(sb,rankedCorr);
  add(sb,slope);
  label=String.format("String_Node_Str",depthStats.getN(),Utils.rounded(median));
  id=Utils.showHistogram(TITLE,depthStats,"String_Node_Str",0,1,0,label);
  if (Utils.isNewWindow())   wo.add(id);
  double[] lower=new double[filterCriteria.length];
  double[] upper=new double[lower.length];
  double[] min=new double[lower.length];
  double[] max=new double[lower.length];
  for (int i=0; i < stats[0].length; i++) {
    double[] limits=showDoubleHistogram(stats,i,wo,matchScores,nPredicted);
    lower[i]=limits[0];
    upper[i]=limits[1];
    min[i]=limits[2];
    max[i]=limits[3];
  }
  upper[FILTER_SIGNAL]*=2;
  upper[FILTER_SNR]*=2;
  double factor=0.25;
  if (lower[FILTER_MIN_WIDTH] != 0)   upper[FILTER_MIN_WIDTH]=1 - Math.max(0,factor * (1 - lower[FILTER_MIN_WIDTH]));
  if (upper[FILTER_MIN_WIDTH] != 0)   lower[FILTER_MAX_WIDTH]=1 + Math.max(0,factor * (upper[FILTER_MAX_WIDTH] - 1));
  final double[] interval=new double[stats[0].length];
  interval[FILTER_SIGNAL]=SignalFilter.DEFAULT_INCREMENT;
  interval[FILTER_SNR]=SNRFilter.DEFAULT_INCREMENT;
  interval[FILTER_MIN_WIDTH]=WidthFilter2.DEFAULT_MIN_INCREMENT;
  interval[FILTER_MAX_WIDTH]=WidthFilter.DEFAULT_INCREMENT;
  interval[FILTER_SHIFT]=ShiftFilter.DEFAULT_INCREMENT;
  interval[FILTER_ESHIFT]=EShiftFilter.DEFAULT_INCREMENT;
  interval[FILTER_PRECISION]=PrecisionFilter.DEFAULT_INCREMENT;
  interval[FILTER_ITERATIONS]=0.1;
  interval[FILTER_EVALUATIONS]=0.1;
  double[] increment=new double[lower.length];
  for (int i=0; i < increment.length; i++) {
    lower[i]=Maths.floor(lower[i],interval[i]);
    upper[i]=Maths.ceil(upper[i],interval[i]);
    double range=upper[i] - lower[i];
    double multiples=range / interval[i];
    if (multiples < 9) {
      multiples=Math.ceil(multiples);
    }
 else     multiples=9;
    increment[i]=Maths.ceil(range / multiples,interval[i]);
    if (i == FILTER_MIN_WIDTH)     lower[i]=upper[i] - increment[i] * multiples;
 else     upper[i]=lower[i] + increment[i] * multiples;
  }
  for (int i=0; i < stats[0].length; i++) {
    lower[i]=Maths.round(lower[i]);
    upper[i]=Maths.round(upper[i]);
    min[i]=Maths.round(min[i]);
    max[i]=Maths.round(max[i]);
    increment[i]=Maths.round(increment[i]);
    sb.append("String_Node_Str").append(min[i]).append(':').append(lower[i]).append('-').append(upper[i]).append(':').append(max[i]);
  }
  increment[FILTER_SIGNAL]=Double.POSITIVE_INFINITY;
  increment[FILTER_ESHIFT]=Double.POSITIVE_INFINITY;
  wo.tile();
  sb.append("String_Node_Str").append(Utils.timeToString(runTime / 1000000.0));
  summaryTable.append(sb.toString());
  if (saveFilterRange) {
    GlobalSettings gs=SettingsManager.loadSettings();
    FilterSettings filterSettings=gs.getFilterSettings();
    String filename=Utils.getFilename("String_Node_Str",filterSettings.filterSetFilename);
    if (filename == null)     return;
    filename=Utils.removeExtension(filename);
    filterSettings.filterSetFilename=filename;
    ArrayList<Filter> filters=new ArrayList<Filter>(3);
    filters.add(new MultiFilter2(lower[0],(float)lower[1],lower[2],lower[3],lower[4],lower[5],lower[6]));
    filters.add(new MultiFilter2(upper[0],(float)upper[1],upper[2],upper[3],upper[4],upper[5],upper[6]));
    filters.add(new MultiFilter2(increment[0],(float)increment[1],increment[2],increment[3],increment[4],increment[5],increment[6]));
    if (saveFilters(filename + "String_Node_Str",filters))     SettingsManager.saveSettings(gs);
    min[FILTER_SIGNAL]=Math.max(min[FILTER_SIGNAL],30);
    max[FILTER_PRECISION]=Math.min(min[FILTER_PRECISION],100);
    final boolean[] limitToLower=new boolean[min.length];
    limitToLower[FILTER_SIGNAL]=true;
    limitToLower[FILTER_SNR]=true;
    limitToLower[FILTER_MIN_WIDTH]=true;
    limitToLower[FILTER_MAX_WIDTH]=false;
    limitToLower[FILTER_SHIFT]=false;
    limitToLower[FILTER_ESHIFT]=false;
    limitToLower[FILTER_PRECISION]=true;
    for (int i=0; i < limitToLower.length; i++) {
      final double range=(upper[i] - lower[i]) / 2;
      if (limitToLower[i])       upper[i]=lower[i] + range;
 else       lower[i]=upper[i] - range;
    }
    filters=new ArrayList<Filter>(4);
    filters.add(new MultiFilter2(min[0],(float)min[1],min[2],min[3],min[4],min[5],min[6]));
    filters.add(new MultiFilter2(lower[0],(float)lower[1],lower[2],lower[3],lower[4],lower[5],lower[6]));
    filters.add(new MultiFilter2(upper[0],(float)upper[1],upper[2],upper[3],upper[4],upper[5],upper[6]));
    filters.add(new MultiFilter2(max[0],(float)max[1],max[2],max[3],max[4],max[5],max[6]));
    saveFilters(filename + "String_Node_Str",filters);
  }
}

Fixed version (ground truth):
private void summariseResults(HashMap<Integer,FilterCandidates> filterCandidates,long runTime,PreprocessedPeakResult[] preprocessedPeakResults){
  createTable();
  StoredDataStatistics distanceStats=new StoredDataStatistics();
  StoredDataStatistics depthStats=new StoredDataStatistics();
  createFilterCriteria();
  StoredDataStatistics[][] stats=new StoredDataStatistics[3][filterCriteria.length];
  for (int i=0; i < stats.length; i++)   for (int j=0; j < stats[i].length; j++)   stats[i][j]=new StoredDataStatistics();
  final double nmPerPixel=simulationParameters.a;
  double tp=0, fp=0;
  int failcTP=0, failcFP=0;
  int cTP=0, cFP=0;
  int[] singleStatus=null, multiStatus=null, doubletStatus=null, multiDoubletStatus=null;
  singleStatus=new int[FitStatus.values().length];
  multiStatus=new int[singleStatus.length];
  doubletStatus=new int[singleStatus.length];
  multiDoubletStatus=new int[singleStatus.length];
  for (  FilterCandidates result : filterCandidates.values()) {
    tp+=result.tp;
    fp+=result.fp;
    for (int i=0; i < result.fitResult.length; i++) {
      if (result.spots[i].match)       cTP++;
 else       cFP++;
      final MultiPathFitResult fitResult=result.fitResult[i];
      if (singleStatus != null && result.spots[i].match) {
        addStatus(singleStatus,fitResult.getSingleFitResult());
        addStatus(multiStatus,fitResult.getMultiFitResult());
        addStatus(doubletStatus,fitResult.getDoubletFitResult());
        addStatus(multiDoubletStatus,fitResult.getMultiDoubletFitResult());
      }
      if (noMatch(fitResult)) {
        if (result.spots[i].match)         failcTP++;
 else         failcFP++;
      }
      addToStats(fitResult.getSingleFitResult(),stats);
      addToStats(fitResult.getMultiFitResult(),stats);
      addToStats(fitResult.getDoubletFitResult(),stats);
      addToStats(fitResult.getMultiDoubletFitResult(),stats);
    }
    for (int i=0; i < result.match.length; i++) {
      if (!result.match[i].isFitResult())       continue;
      FitMatch fitMatch=(FitMatch)result.match[i];
      distanceStats.add(fitMatch.d * nmPerPixel);
      depthStats.add(fitMatch.z * nmPerPixel);
    }
  }
  double[] i1=new double[depthStats.getN()];
  double[] i2=new double[i1.length];
  double[] is=new double[i1.length];
  int ci=0;
  for (  FilterCandidates result : filterCandidates.values()) {
    for (int i=0; i < result.match.length; i++) {
      if (!result.match[i].isFitResult())       continue;
      FitMatch fitMatch=(FitMatch)result.match[i];
      ScoredSpot spot=result.spots[fitMatch.i];
      i1[ci]=fitMatch.predictedSignal;
      i2[ci]=fitMatch.actualSignal;
      is[ci]=spot.spot.intensity;
      ci++;
    }
  }
  ArrayList<MultiPathFitResults> multiPathResults=new ArrayList<MultiPathFitResults>(filterCandidates.size());
  for (  Entry<Integer,FilterCandidates> entry : filterCandidates.entrySet()) {
    int frame=entry.getKey();
    MultiPathFitResult[] multiPathFitResults=entry.getValue().fitResult;
    int totalCandidates=multiPathFitResults.length;
    int nActual=actualCoordinates.get(frame).size();
    multiPathResults.add(new MultiPathFitResults(frame,multiPathFitResults,totalCandidates,nActual));
  }
  List<FractionalAssignment[]> assignments=new ArrayList<FractionalAssignment[]>();
  final Set<Integer> set=new TreeSet<Integer>();
  FractionScoreStore scoreStore=new FractionScoreStore(){
    public void add(    int uniqueId){
      set.add(uniqueId);
    }
  }
;
  MultiPathFitResults[] multiResults=multiPathResults.toArray(new MultiPathFitResults[multiPathResults.size()]);
  MultiPathFilter mpf=new MultiPathFilter(new SignalFilter(0),null,multiFilter.residualsThreshold);
  FractionClassificationResult fractionResult=mpf.fractionScoreSubset(multiResults,Integer.MAX_VALUE,this.results.size(),assignments,scoreStore);
  double nPredicted=fractionResult.getTP() + fractionResult.getFP();
  double[][] matchScores=new double[set.size()][];
  int count=0;
  for (int i=0; i < assignments.size(); i++) {
    FractionalAssignment[] a=assignments.get(i);
    if (a == null)     continue;
    for (int j=0; j < a.length; j++) {
      final PreprocessedPeakResult r=((PeakFractionalAssignment)a[j]).peakResult;
      set.remove(r.getUniqueId());
      final double precision=Math.sqrt(r.getLocationVariance());
      final double signal=r.getSignal();
      final double snr=r.getSNR();
      final double width=r.getXSDFactor();
      final double xShift=r.getXRelativeShift2();
      final double yShift=r.getYRelativeShift2();
      final double shift=(xShift > yShift) ? Math.sqrt(xShift) : Math.sqrt(yShift);
      final double eshift=Math.sqrt(xShift + yShift);
      final double[] score=new double[8];
      score[FILTER_SIGNAL]=signal;
      score[FILTER_SNR]=snr;
      score[FILTER_MIN_WIDTH]=width;
      score[FILTER_MAX_WIDTH]=width;
      score[FILTER_SHIFT]=shift;
      score[FILTER_ESHIFT]=eshift;
      score[FILTER_PRECISION]=precision;
      score[FILTER_PRECISION + 1]=a[j].getScore();
      matchScores[count++]=score;
    }
  }
  for (  int uniqueId : set.toArray(new Integer[0])) {
    PreprocessedPeakResult r=preprocessedPeakResults[uniqueId];
    if (r == null)     throw new RuntimeException("String_Node_Str" + uniqueId);
    final double precision=Math.sqrt(r.getLocationVariance());
    final double signal=r.getSignal();
    final double snr=r.getSNR();
    final double width=r.getXSDFactor();
    final double xShift=r.getXRelativeShift2();
    final double yShift=r.getYRelativeShift2();
    final double shift=(xShift > yShift) ? Math.sqrt(xShift) : Math.sqrt(yShift);
    final double eshift=Math.sqrt(xShift + yShift);
    final double[] score=new double[8];
    score[FILTER_SIGNAL]=signal;
    score[FILTER_SNR]=snr;
    score[FILTER_MIN_WIDTH]=width;
    score[FILTER_MAX_WIDTH]=width;
    score[FILTER_SHIFT]=shift;
    score[FILTER_ESHIFT]=eshift;
    score[FILTER_PRECISION]=precision;
    matchScores[count++]=score;
  }
  if (singleStatus != null) {
    String name=PeakFit.getSolverName(fitConfig);
    if (fitConfig.getFitSolver() == FitSolver.MLE && fitConfig.isModelCamera())     name+="String_Node_Str";
    System.out.println("String_Node_Str" + name);
    printFailures("String_Node_Str",singleStatus);
    printFailures("String_Node_Str",multiStatus);
    printFailures("String_Node_Str",doubletStatus);
    printFailures("String_Node_Str",multiDoubletStatus);
  }
  StringBuilder sb=new StringBuilder();
  final double signal=simulationParameters.signalPerFrame;
  final int n=results.size();
  sb.append(imp.getStackSize()).append("String_Node_Str");
  final int w=imp.getWidth();
  final int h=imp.getHeight();
  sb.append(w).append("String_Node_Str");
  sb.append(h).append("String_Node_Str");
  sb.append(n).append("String_Node_Str");
  double density=((double)n / imp.getStackSize()) / (w * h) / (simulationParameters.a * simulationParameters.a / 1e6);
  sb.append(Utils.rounded(density)).append("String_Node_Str");
  sb.append(Utils.rounded(signal)).append("String_Node_Str");
  sb.append(Utils.rounded(simulationParameters.s)).append("String_Node_Str");
  sb.append(Utils.rounded(simulationParameters.a)).append("String_Node_Str");
  sb.append(Utils.rounded(simulationParameters.depth)).append("String_Node_Str");
  sb.append(simulationParameters.fixedDepth).append("String_Node_Str");
  sb.append(Utils.rounded(simulationParameters.gain)).append("String_Node_Str");
  sb.append(Utils.rounded(simulationParameters.readNoise)).append("String_Node_Str");
  sb.append(Utils.rounded(simulationParameters.b)).append("String_Node_Str");
  sb.append(Utils.rounded(simulationParameters.b2)).append("String_Node_Str");
  double noise=simulationParameters.b2;
  if (simulationParameters.emCCD) {
    final double readVariance=noise - simulationParameters.b;
    noise=simulationParameters.b * 2 + readVariance;
  }
  if (simulationParameters.fullSimulation) {
  }
  sb.append(Utils.rounded(signal / Math.sqrt(noise))).append("String_Node_Str");
  sb.append(Utils.rounded(simulationParameters.s / simulationParameters.a)).append("String_Node_Str");
  sb.append(spotFilter.getDescription());
  addCount(sb,nP + nN);
  addCount(sb,nP);
  addCount(sb,nN);
  addCount(sb,fP);
  addCount(sb,fN);
  String name=PeakFit.getSolverName(fitConfig);
  if (fitConfig.getFitSolver() == FitSolver.MLE && fitConfig.isModelCamera())   name+="String_Node_Str";
  add(sb,name);
  add(sb,config.getFitting());
  resultPrefix=sb.toString();
  add(sb,(100.0 * cTP) / nP);
  add(sb,(100.0 * cFP) / nN);
  add(sb,cTP + cFP);
  add(sb,cTP);
  add(sb,cFP);
  FractionClassificationResult m=new FractionClassificationResult(cTP,cFP,0,simulationParameters.molecules - cTP);
  add(sb,m.getRecall());
  add(sb,m.getPrecision());
  add(sb,m.getF1Score());
  add(sb,m.getJaccard());
  add(sb,failcTP);
  add(sb,failcFP);
  add(sb,tp);
  add(sb,fp);
  m=new FractionClassificationResult(tp,fp,0,simulationParameters.molecules - tp);
  add(sb,m.getRecall());
  add(sb,m.getPrecision());
  add(sb,m.getF1Score());
  add(sb,m.getJaccard());
  m=new FractionClassificationResult(tp,0,0,simulationParameters.molecules - tp);
  add(sb,m.getF1Score());
  add(sb,m.getJaccard());
  double median=distanceStats.getMedian();
  add(sb,median);
  WindowOrganiser wo=new WindowOrganiser();
  String label=String.format("String_Node_Str",Utils.rounded(m.getRecall()),distanceStats.getN(),Utils.rounded(median),Utils.rounded(distanceStats.getStandardDeviation()));
  int id=Utils.showHistogram(TITLE,distanceStats,"String_Node_Str",0,0,0,label);
  if (Utils.isNewWindow())   wo.add(id);
  median=depthStats.getMedian();
  add(sb,median);
  int[] indices=Utils.newArray(i1.length,0,1);
  if (showCorrelation)   Sort.sort(indices,is,rankByIntensity);
  double[] r=(showCorrelation) ? new double[i1.length] : null;
  double[] sr=(showCorrelation) ? new double[i1.length] : null;
  double[] rank=(showCorrelation) ? new double[i1.length] : null;
  ci=0;
  FastCorrelator fastCorrelator=new FastCorrelator();
  ArrayList<Ranking> pc1=new ArrayList<Ranking>();
  ArrayList<Ranking> pc2=new ArrayList<Ranking>();
  for (  int ci2 : indices) {
    fastCorrelator.add((long)Math.round(i1[ci2]),(long)Math.round(i2[ci2]));
    pc1.add(new Ranking(i1[ci2],ci));
    pc2.add(new Ranking(i2[ci2],ci));
    if (showCorrelation) {
      r[ci]=fastCorrelator.getCorrelation();
      sr[ci]=Correlator.correlation(rank(pc1),rank(pc2));
      if (rankByIntensity)       rank[ci]=is[0] - is[ci];
 else       rank[ci]=ci;
    }
    ci++;
  }
  final double pearsonCorr=fastCorrelator.getCorrelation();
  final double rankedCorr=Correlator.correlation(rank(pc1),rank(pc2));
  SimpleRegression regression=new SimpleRegression(false);
  for (int i=0; i < pc1.size(); i++)   regression.addData(pc1.get(i).value,pc2.get(i).value);
  final double slope=regression.getSlope();
  if (showCorrelation) {
    String title=TITLE + "String_Node_Str";
    Plot plot=new Plot(title,"String_Node_Str","String_Node_Str");
    double[] limits1=Maths.limits(i1);
    double[] limits2=Maths.limits(i2);
    plot.setLimits(limits1[0],limits1[1],limits2[0],limits2[1]);
    label=String.format("String_Node_Str",Utils.rounded(pearsonCorr),Utils.rounded(rankedCorr),Utils.rounded(slope));
    plot.addLabel(0,0,label);
    plot.setColor(Color.red);
    plot.addPoints(i1,i2,Plot.DOT);
    if (slope > 1)     plot.drawLine(limits1[0],limits1[0] * slope,limits1[1],limits1[1] * slope);
 else     plot.drawLine(limits2[0] / slope,limits2[0],limits2[1] / slope,limits2[1]);
    PlotWindow pw=Utils.display(title,plot);
    if (Utils.isNewWindow())     wo.add(pw);
    title=TITLE + "String_Node_Str";
    plot=new Plot(title,"String_Node_Str","String_Node_Str");
    double[] xlimits=Maths.limits(rank);
    double[] ylimits=Maths.limits(r);
    ylimits=Maths.limits(ylimits,sr);
    plot.setLimits(xlimits[0],xlimits[1],ylimits[0],ylimits[1]);
    plot.setColor(Color.red);
    plot.addPoints(rank,r,Plot.LINE);
    plot.setColor(Color.blue);
    plot.addPoints(rank,sr,Plot.LINE);
    plot.setColor(Color.black);
    plot.addLabel(0,0,label);
    pw=Utils.display(title,plot);
    if (Utils.isNewWindow())     wo.add(pw);
  }
  add(sb,pearsonCorr);
  add(sb,rankedCorr);
  add(sb,slope);
  label=String.format("String_Node_Str",depthStats.getN(),Utils.rounded(median));
  id=Utils.showHistogram(TITLE,depthStats,"String_Node_Str",0,1,0,label);
  if (Utils.isNewWindow())   wo.add(id);
  double[] lower=new double[filterCriteria.length];
  double[] upper=new double[lower.length];
  double[] min=new double[lower.length];
  double[] max=new double[lower.length];
  for (int i=0; i < stats[0].length; i++) {
    double[] limits=showDoubleHistogram(stats,i,wo,matchScores,nPredicted);
    lower[i]=limits[0];
    upper[i]=limits[1];
    min[i]=limits[2];
    max[i]=limits[3];
  }
  upper[FILTER_SIGNAL]*=2;
  upper[FILTER_SNR]*=2;
  double factor=0.25;
  if (lower[FILTER_MIN_WIDTH] != 0)   upper[FILTER_MIN_WIDTH]=1 - Math.max(0,factor * (1 - lower[FILTER_MIN_WIDTH]));
  if (upper[FILTER_MIN_WIDTH] != 0)   lower[FILTER_MAX_WIDTH]=1 + Math.max(0,factor * (upper[FILTER_MAX_WIDTH] - 1));
  final double[] interval=new double[stats[0].length];
  interval[FILTER_SIGNAL]=SignalFilter.DEFAULT_INCREMENT;
  interval[FILTER_SNR]=SNRFilter.DEFAULT_INCREMENT;
  interval[FILTER_MIN_WIDTH]=WidthFilter2.DEFAULT_MIN_INCREMENT;
  interval[FILTER_MAX_WIDTH]=WidthFilter.DEFAULT_INCREMENT;
  interval[FILTER_SHIFT]=ShiftFilter.DEFAULT_INCREMENT;
  interval[FILTER_ESHIFT]=EShiftFilter.DEFAULT_INCREMENT;
  interval[FILTER_PRECISION]=PrecisionFilter.DEFAULT_INCREMENT;
  interval[FILTER_ITERATIONS]=0.1;
  interval[FILTER_EVALUATIONS]=0.1;
  double[] increment=new double[lower.length];
  for (int i=0; i < increment.length; i++) {
    lower[i]=Maths.floor(lower[i],interval[i]);
    upper[i]=Maths.ceil(upper[i],interval[i]);
    double range=upper[i] - lower[i];
    double multiples=range / interval[i];
    if (multiples < 9) {
      multiples=Math.ceil(multiples);
    }
 else     multiples=9;
    increment[i]=Maths.ceil(range / multiples,interval[i]);
    if (i == FILTER_MIN_WIDTH)     lower[i]=upper[i] - increment[i] * multiples;
 else     upper[i]=lower[i] + increment[i] * multiples;
  }
  for (int i=0; i < stats[0].length; i++) {
    lower[i]=Maths.round(lower[i]);
    upper[i]=Maths.round(upper[i]);
    min[i]=Maths.round(min[i]);
    max[i]=Maths.round(max[i]);
    increment[i]=Maths.round(increment[i]);
    sb.append("String_Node_Str").append(min[i]).append(':').append(lower[i]).append('-').append(upper[i]).append(':').append(max[i]);
  }
  increment[FILTER_SIGNAL]=Double.POSITIVE_INFINITY;
  increment[FILTER_ESHIFT]=Double.POSITIVE_INFINITY;
  wo.tile();
  sb.append("String_Node_Str").append(Utils.timeToString(runTime / 1000000.0));
  summaryTable.append(sb.toString());
  if (saveFilterRange) {
    GlobalSettings gs=SettingsManager.loadSettings();
    FilterSettings filterSettings=gs.getFilterSettings();
    String filename=Utils.getFilename("String_Node_Str",filterSettings.filterSetFilename);
    if (filename == null)     return;
    filename=Utils.removeExtension(filename);
    filterSettings.filterSetFilename=filename;
    ArrayList<Filter> filters=new ArrayList<Filter>(3);
    filters.add(new MultiFilter2(lower[0],(float)lower[1],lower[2],lower[3],lower[4],lower[5],lower[6]));
    filters.add(new MultiFilter2(upper[0],(float)upper[1],upper[2],upper[3],upper[4],upper[5],upper[6]));
    filters.add(new MultiFilter2(increment[0],(float)increment[1],increment[2],increment[3],increment[4],increment[5],increment[6]));
    if (saveFilters(filename + "String_Node_Str",filters))     SettingsManager.saveSettings(gs);
    min[FILTER_SIGNAL]=Math.max(min[FILTER_SIGNAL],30);
    max[FILTER_PRECISION]=Math.min(max[FILTER_PRECISION],100);
    final boolean[] limitToLower=new boolean[min.length];
    limitToLower[FILTER_SIGNAL]=true;
    limitToLower[FILTER_SNR]=true;
    limitToLower[FILTER_MIN_WIDTH]=true;
    limitToLower[FILTER_MAX_WIDTH]=false;
    limitToLower[FILTER_SHIFT]=false;
    limitToLower[FILTER_ESHIFT]=false;
    limitToLower[FILTER_PRECISION]=true;
    for (int i=0; i < limitToLower.length; i++) {
      final double range=(upper[i] - lower[i]) / 2;
      if (limitToLower[i])       upper[i]=lower[i] + range;
 else       lower[i]=upper[i] - range;
    }
    filters=new ArrayList<Filter>(4);
    filters.add(new MultiFilter2(min[0],(float)min[1],min[2],min[3],min[4],min[5],min[6]));
    filters.add(new MultiFilter2(lower[0],(float)lower[1],lower[2],lower[3],lower[4],lower[5],lower[6]));
    filters.add(new MultiFilter2(upper[0],(float)upper[1],upper[2],upper[3],upper[4],upper[5],upper[6]));
    filters.add(new MultiFilter2(max[0],(float)max[1],max[2],max[3],max[4],max[5],max[6]));
    saveFilters(filename + "String_Node_Str",filters);
  }
}