/**
   * Get the standard deviation (sigma) of an image only using values clipped by 3*sigma from a
   * first estimate of sigma
   *
   * @param img input image
   * @return 3*sigma clipped std dev
   */
  protected double get3SigClippedStdDev(MTBImage img) {

    int sizeStack = img.getSizeStack();
    int sizeX = img.getSizeX();
    int sizeY = img.getSizeY();

    double val;
    double mu = 0.0;
    double mu2 = 0.0;
    double N = 0.0;
    double sigma;

    for (int i = 0; i < sizeStack; i++) {
      img.setCurrentSliceIndex(i);

      for (int y = 0; y < sizeY; y++) {
        for (int x = 0; x < sizeX; x++) {
          val = img.getValueDouble(x, y);
          mu += val;
          mu2 += val * val;
          N++;
        }
      }
    }

    mu /= N;
    mu2 /= N;
    sigma = Math.sqrt(mu2 - mu * mu);

    mu = 0.0;
    mu2 = 0.0;
    N = 0.0;

    for (int i = 0; i < sizeStack; i++) {
      img.setCurrentSliceIndex(i);

      for (int y = 0; y < sizeY; y++) {
        for (int x = 0; x < sizeX; x++) {
          val = img.getValueDouble(x, y);
          if (Math.abs(val - mu) <= 3.0 * sigma) {
            mu += val;
            mu2 += val * val;
            N++;
          }
        }
      }
    }
    img.setCurrentSliceIndex(0);

    mu /= N;
    mu2 /= N;
    sigma = Math.sqrt(mu2 - mu * mu);

    return sigma;
  }
  /**
   * Denoise wavelet coefficients using Jeffrey's noninformative prior for a given sigma of noise
   *
   * @param img input image
   * @param sigma sigma of noise
   */
  protected void denoise(MTBImage img, double sigma) {
    int sizeStack = img.getSizeStack();
    int sizeX = img.getSizeX();
    int sizeY = img.getSizeY();

    double s2 = 3.0 * sigma * sigma;
    double val, val2;
    for (int i = 0; i < sizeStack; i++) {
      img.setCurrentSliceIndex(i);

      for (int y = 0; y < sizeY; y++) {
        for (int x = 0; x < sizeX; x++) {
          val = img.getValueDouble(x, y);

          val2 = (val * val - s2);

          if (val2 < 0.0) val2 = 0.0;

          if (val != 0.0) img.putValueDouble(x, y, val2 / val);
          else img.putValueDouble(x, y, 0.0);
        }
      }
    }
    img.setCurrentSliceIndex(0);
  }