@Test
  public void testProcessNoNoise() {

    int width = 100;
    int height = 100;
    final int nspots = 4;

    long[] dimensions = new long[] {width, height};
    ArrayImg<UnsignedByteType, ByteArray> img = ArrayImgs.unsignedBytes(dimensions);

    final double[] A0 = new double[nspots];
    final double[] x0 = new double[nspots];
    final double[] y0 = new double[nspots];
    final double[] sigma_x = new double[nspots];
    final double[] sigma_y = new double[nspots];

    Random rangen = new Random(1);
    for (int i = 0; i < nspots; i++) {

      A0[i] = 100 + 10 * rangen.nextGaussian();
      x0[i] = 20 + (width - 20) * rangen.nextDouble();
      y0[i] = 20 + (height - 20) * rangen.nextDouble();
      sigma_x[i] = 2 + 0.5 * rangen.nextGaussian();
      sigma_y[i] = 2 + 0.5 * rangen.nextGaussian();

      double[] params =
          new double[] {
            A0[i], x0[i], y0[i], 1 / sigma_x[i] / sigma_x[i], 1 / sigma_y[i] / sigma_y[i]
          };
      LocalizationUtils.addGaussianSpotToImage(img, params);
    }

    // Instantiate fitter once
    final GaussianPeakFitterND<UnsignedByteType> fitter =
        new GaussianPeakFitterND<UnsignedByteType>(img);

    // No multithreading in the test
    for (int j = 0; j < nspots; j++) {

      Localizable point = new Point(new int[] {(int) x0[j], (int) y0[j]});
      double[] results = fitter.process(point, new double[] {sigma_x[j], sigma_y[j]});

      double A = results[0];
      double x = results[1];
      double y = results[2];
      double sx = 1 / Math.sqrt(results[3]);
      double sy = 1 / Math.sqrt(results[4]);

      assertEq("x", x0[j], x, LOCALIZATION_TOLERANCE_NO_NOISE);
      assertEq("y", y0[j], y, LOCALIZATION_TOLERANCE_NO_NOISE);
      assertEq("σx", sigma_x[j], sx, SIGMA_TOLERANCE_NO_NOISE);
      assertEq("σy", sigma_y[j], sy, SIGMA_TOLERANCE_NO_NOISE);
      assertEq("A", A0[j], A, 20d);
    }
  }
  @Test
  public void testSymetricGaussian() {

    int width = 200;
    int height = 200;
    final int nspots = 10;

    long[] dimensions = new long[] {width, height};
    ArrayImg<UnsignedByteType, ByteArray> img = ArrayImgs.unsignedBytes(dimensions);

    Collection<Localizable> peaks = new HashSet<Localizable>(nspots);
    Map<Localizable, double[]> groundTruth = new HashMap<Localizable, double[]>(nspots);

    for (int i = 1; i < nspots; i++) {

      for (int j = 1; j < nspots; j++) {

        double A = 100;
        double x0 = width / (double) nspots * i * 1.02d;
        double y0 = width / (double) nspots * j * 1.02d;
        double sigma = 2 - (double) i / nspots + (double) i / nspots;

        Localizable peak = new Point((long) x0, (long) y0);
        peaks.add(peak);

        double[] params = new double[] {x0, y0, A, 1 / sigma / sigma};
        LocalizationUtils.addGaussianSpotToImage(img, params);
        groundTruth.put(peak, params);
      }
    }

    // Instantiate fitter once
    PeakFitter<UnsignedByteType> fitter =
        new PeakFitter<UnsignedByteType>(
            img,
            peaks,
            new LevenbergMarquardtSolver(),
            new Gaussian(),
            new MLGaussianEstimator(2d, 2));

    if (!fitter.checkInput() || !fitter.process()) {
      fail("Problem with peak fitting: " + fitter.getErrorMessage());
      return;
    }

    Map<Localizable, double[]> results = fitter.getResult();

    for (Localizable peak : peaks) {
      double[] params = results.get(peak);
      double[] truth = groundTruth.get(peak);

      // Pedestrian assertion
      assertEquals(
          "Bad accuracy on amplitude parameter A: ", truth[2], params[2], TOLERANCE * truth[2]);
      assertEquals(
          "Bad accuracy on peak location x0: ", truth[0], params[0], LOCALIZATION_TOLERANCE);
      assertEquals(
          "Bad accuracy on peak location y0: ", truth[1], params[1], LOCALIZATION_TOLERANCE);
      assertEquals("Bad accuracy on peak paramter b: ", truth[3], params[3], TOLERANCE * truth[3]);
    }
  }
  @Test
  public void testEllipticGaussian() {

    int width = 200;
    int height = 200;
    final int nspots = 10;

    long[] dimensions = new long[] {width, height};
    ArrayImg<UnsignedByteType, ByteArray> img = ArrayImgs.unsignedBytes(dimensions);

    Collection<Localizable> peaks = new HashSet<Localizable>(nspots);
    Map<Localizable, double[]> groundTruth = new HashMap<Localizable, double[]>(nspots);

    for (int i = 1; i < nspots; i++) {

      for (int j = 1; j < nspots; j++) {

        double A = 100;
        double x0 = width / (double) nspots * i * 1.02d;
        double y0 = width / (double) nspots * j * 1.02d;
        double sigma_x = 2 - (double) i / nspots;
        double sigma_y = 2 - (double) j / nspots;

        Localizable peak = new Point((long) x0, (long) y0);
        peaks.add(peak);

        double[] params = new double[] {x0, y0, A, 1 / sigma_x / sigma_x, 1 / sigma_y / sigma_y};
        LocalizationUtils.addEllipticGaussianSpotToImage(img, params);
        groundTruth.put(peak, params);
      }
    }

    // Instantiate fitter once
    PeakFitter<UnsignedByteType> fitter =
        new PeakFitter<UnsignedByteType>(
            img,
            peaks,
            new LevenbergMarquardtSolver(),
            new EllipticGaussianOrtho(),
            new MLEllipticGaussianEstimator(new double[] {2d, 2d}));

    if (!fitter.checkInput() || !fitter.process()) {
      fail("Problem with peak fitting: " + fitter.getErrorMessage());
      return;
    }

    Map<Localizable, double[]> results = fitter.getResult();

    for (Localizable peak : peaks) {
      double[] params = results.get(peak);
      double[] truth = groundTruth.get(peak);

      // Pedestrian assertion
      assertEquals(
          "Bad accuracy on amplitude parameter A: ", truth[2], params[2], TOLERANCE * truth[2]);
      assertEquals(
          "Bad accuracy on peak location x0: ", truth[0], params[0], LOCALIZATION_TOLERANCE);
      assertEquals(
          "Bad accuracy on peak location y0: ", truth[1], params[1], LOCALIZATION_TOLERANCE);
      assertEquals("Bad accuracy on peak paramter bx: ", truth[3], params[3], TOLERANCE * truth[3]);
      assertEquals("Bad accuracy on peak paramter by: ", truth[4], params[4], TOLERANCE * truth[4]);

      //			System.out.println(String.format("- For " + peak + "\n - Found      : " +
      //					"A = %6.2f, x0 = %6.2f, y0 = %6.2f, sx = %5.2f, sy = %5.2f",
      //					params[0], params[1], params[2], 1 / Math.sqrt(params[3]), 1/Math.sqrt(params[4])));
      //			System.out.println(String.format(" - Real values: " +
      //					"A = %6.2f, x0 = %6.2f, y0 = %6.2f, sx = %5.2f, sy = %5.2f",
      //					truth[0], truth[1], truth[2], 1 / Math.sqrt(truth[3]), 1 / Math.sqrt(truth[4]) ));

    }
  }