private void computeCoefficientOfDetermination() {
    int numberOfItems = scatterpointsDataset.getSeries(0).getItemCount();
    double arithmeticMeanOfX = 0; // arithmetic mean of X
    double arithmeticMeanOfY = 0; // arithmetic mean of Y
    double varX = 0; // variance of X
    double varY = 0; // variance of Y
    double coVarXY = 0; // covariance of X and Y;
    // compute arithmetic means
    for (int i = 0; i < numberOfItems; i++) {
      arithmeticMeanOfX += scatterpointsDataset.getXValue(0, i);
      arithmeticMeanOfY += scatterpointsDataset.getYValue(0, i);
    }
    arithmeticMeanOfX /= numberOfItems;
    arithmeticMeanOfY /= numberOfItems;
    // compute variances and covariance
    for (int i = 0; i < numberOfItems; i++) {
      varX += Math.pow(scatterpointsDataset.getXValue(0, i) - arithmeticMeanOfX, 2);
      varY += Math.pow(scatterpointsDataset.getYValue(0, i) - arithmeticMeanOfY, 2);
      coVarXY +=
          (scatterpointsDataset.getXValue(0, i) - arithmeticMeanOfX)
              * (scatterpointsDataset.getYValue(0, i) - arithmeticMeanOfY);
    }
    // computation of coefficient of determination
    double r2 = Math.pow(coVarXY, 2) / (varX * varY);
    r2 = MathUtils.round(r2, Math.pow(10.0, 5));

    final double[] coefficients = Regression.getOLSRegression(scatterpointsDataset, 0);
    final double intercept = coefficients[0];
    final double slope = coefficients[1];
    final String linearEquation;
    if (intercept >= 0) {
      linearEquation = "y = " + (float) slope + "x + " + (float) intercept;
    } else {
      linearEquation = "y = " + (float) slope + "x - " + Math.abs((float) intercept);
    }

    TextTitle tt = new TextTitle(linearEquation + "\nRĀ² = " + r2);
    tt.setTextAlignment(HorizontalAlignment.RIGHT);
    tt.setFont(chart.getLegend().getItemFont());
    tt.setBackgroundPaint(new Color(200, 200, 255, 100));
    tt.setFrame(new BlockBorder(Color.white));
    tt.setPosition(RectangleEdge.BOTTOM);

    r2Annotation = new XYTitleAnnotation(0.98, 0.02, tt, RectangleAnchor.BOTTOM_RIGHT);
    r2Annotation.setMaxWidth(0.48);
    getPlot().addAnnotation(r2Annotation);
  }
  public static void getListInEvenlySpacedGrid(
      final int sceneRasterWidth,
      final int sceneRasterHeight,
      final int sourceGridWidth,
      final int sourceGridHeight,
      final int[] x,
      final int[] y,
      final double[] sourcePointList,
      final int targetGridWidth,
      final int targetGridHeight,
      final double subSamplingX,
      final double subSamplingY,
      final float[] targetPointList) {

    if (sourcePointList.length != sourceGridWidth * sourceGridHeight) {
      throw new IllegalArgumentException(
          "Original tie point array size does not match 'sourceGridWidth' x 'sourceGridHeight'");
    }

    if (targetPointList.length != targetGridWidth * targetGridHeight) {
      throw new IllegalArgumentException(
          "Target tie point array size does not match 'targetGridWidth' x 'targetGridHeight'");
    }

    int k = 0;
    for (int r = 0; r < targetGridHeight; r++) {

      double newY = r * subSamplingY;
      if (newY > sceneRasterHeight - 1) {
        newY = sceneRasterHeight - 1;
      }
      double oldY0 = 0, oldY1 = 0;
      int j0 = 0, j1 = 0;
      for (int rr = 1; rr < sourceGridHeight; rr++) {
        j0 = rr - 1;
        j1 = rr;
        oldY0 = y[j0 * sourceGridWidth];
        oldY1 = y[j1 * sourceGridWidth];
        if (oldY1 > newY) {
          break;
        }
      }

      final double wj = (newY - oldY0) / (oldY1 - oldY0);

      for (int c = 0; c < targetGridWidth; c++) {

        double newX = c * subSamplingX;
        if (newX > sceneRasterWidth - 1) {
          newX = sceneRasterWidth - 1;
        }
        double oldX0 = 0, oldX1 = 0;
        int i0 = 0, i1 = 0;
        for (int cc = 1; cc < sourceGridWidth; cc++) {
          i0 = cc - 1;
          i1 = cc;
          oldX0 = x[i0];
          oldX1 = x[i1];
          if (oldX1 > newX) {
            break;
          }
        }
        final double wi = (newX - oldX0) / (oldX1 - oldX0);

        targetPointList[k++] =
            (float)
                (MathUtils.interpolate2D(
                    wi,
                    wj,
                    sourcePointList[i0 + j0 * sourceGridWidth],
                    sourcePointList[i1 + j0 * sourceGridWidth],
                    sourcePointList[i0 + j1 * sourceGridWidth],
                    sourcePointList[i1 + j1 * sourceGridWidth]));
      }
    }
  }