/**
     * constructor to create a view
     *
     * @param projection: projection image as Grid2D
     * @param radon: radon transformed and derived image as Grid2D
     * @param projMatrix: projection matrix as Projection
     */
    public View(Grid2D projection, Grid2D radon, Projection projMatrix) {

      // Initialize center matrix //
      CENTER = new SimpleMatrix(3, 4);
      CENTER.setDiagValue(new SimpleVector(1.0, 1.0, 1.0));

      // get data out of projection //
      this.projectionWidth = projection.getWidth();
      this.projectionHeight = projection.getHeight();

      // get data out of radon transformed image //
      this.radonWidth = radon.getWidth();
      this.radonHeight = radon.getHeight();
      this.projectionDiag =
          Math.sqrt(projectionWidth * projectionWidth + projectionHeight * projectionHeight);
      this.lineIncrement = radonWidth / projectionDiag;
      this.angleIncrement = radonHeight / Math.PI;

      // store radon transformed image //
      this.radon = radon;

      // get projection matrix P (3x4) //
      this.P = SimpleOperators.multiplyMatrixProd(projMatrix.getK(), CENTER);
      this.P = SimpleOperators.multiplyMatrixProd(this.P, projMatrix.getRt());

      // get source position C (nullspace of the projection) //
      DecompositionSVD decoP = new DecompositionSVD(this.P);
      this.C = decoP.getV().getCol(3);

      // normalize source vectors by last component //
      // it is important that the last component is positive to have a positive center
      // as it is defined in oriented projective geometry
      this.C = this.C.dividedBy(this.C.getElement(3));
    }
  /**
   * method to compute the squared radon transformed and derived image for one view the derivation
   * is done in t-direction (distance to origin)
   *
   * @param data: Grid2D which represents the projection
   * @param radonSize: value to determine the size of the squared radon transformed and derived
   *     image
   * @return: radon transformed image as Grid2D (its size is radonSize x radonSize)
   */
  public static Grid2D computeRadonTrafoAndDerive(Grid2D data, int radonSize) {

    Grid2D radon = null;

    // optional: preprocessing can be done here
    // for example:
    /*
    float value;
    for (int i = 0; i < data.getWidth(); i++) {
    	for (int j = 0; j < data.getHeight(); j++) {
    		if (j < 10 || j > data.getHeight() - 11) {
    			// set border to zero
    			value = 0.0f;
    		} else {
    			value = (float)(-Math.log(data.getAtIndex(i, j) / 0.842f));
    		}
    		data.setAtIndex(i, j, value);
    	}
    }

    data.show("preprocessed image");
    */

    // * get some dimensions out of data (projection) *//
    int projSizeX = data.getWidth();
    int projSizeY = data.getHeight();
    double projectionDiag = Math.sqrt(projSizeX * projSizeX + projSizeY * projSizeY);

    double deltaS = projectionDiag / radonSize;
    double deltaTheta = Math.PI / radonSize;

    // * create a parallel projector in order to compute the radon transformation *//
    ParallelProjector2D projector =
        new ParallelProjector2D(Math.PI, deltaTheta, projectionDiag, deltaS);

    // * create radon transformation *//
    radon = projector.projectRayDriven(data);
    // for a faster GPU implementation use: (possibly not working):
    // radon = projector.projectRayDrivenCL(data);

    // * derivative by Sobel operator in t-direction *//
    final int size = 1024;
    SobelKernel1D kernel = new SobelKernel1D(size, 9);
    kernel.applyToGrid(radon);

    // * optional: save file in tiff-format *//
    /*
    FileSaver saveRadon = new FileSaver(ImageUtil.wrapGrid(radon, ""));
    saveRadon.saveAsTiff();
    */

    return radon;
  }
    /**
     * Method to calculate alpha and t as indices from the radon transformed image of a view.
     * Neccessary are the inverse projection image (as SimpleMatrix) and the epipolar plane E
     *
     * @param E: epipolar plane E as SimpleVector (4 entries)
     * @return: line integral value as double
     */
    private double getValueByAlphaAndT(SimpleVector E) {

      // compute corresponding epipolar lines //
      // (epipolar lines are of 3x1 = 3x4 * 4x1)
      SimpleVector l_kappa = SimpleOperators.multiply(this.P_Inverse.transposed(), E);

      // init the coordinate shift //
      int t_u = this.projectionWidth / 2;
      int t_v = this.projectionHeight / 2;

      // compute angle alpha and distance to origin t //
      double l0 = l_kappa.getElement(0);
      double l1 = l_kappa.getElement(1);
      double l2 = l_kappa.getElement(2);

      double alpha_kappa_RAD = Math.atan2(-l0, l1) + Math.PI / 2;

      double t_kappa = -l2 / Math.sqrt(l0 * l0 + l1 * l1);
      // correct the coordinate shift //
      t_kappa -= t_u * Math.cos(alpha_kappa_RAD) + t_v * Math.sin(alpha_kappa_RAD);

      // correct some alpha falling out of the radon window //
      if (alpha_kappa_RAD < 0) {
        alpha_kappa_RAD *= -1.0;
      } else if (alpha_kappa_RAD > Math.PI) {
        alpha_kappa_RAD = 2.0 * Math.PI - alpha_kappa_RAD;
      }

      // write back to l_kappa //
      l_kappa.setElementValue(0, Math.cos(alpha_kappa_RAD));
      l_kappa.setElementValue(1, Math.sin(alpha_kappa_RAD));
      l_kappa.setElementValue(2, -t_kappa);

      // calculate x and y coordinates for derived radon transformed image //
      double x = t_kappa * this.lineIncrement + 0.5 * this.radonWidth;
      double y = alpha_kappa_RAD * this.angleIncrement;

      // get intensity value out of radon transformed image //
      // (interpolation needed)
      return InterpolationOperators.interpolateLinear(this.radon, x, y);
    }