Example #1
0
  /**
   * Creates the meshes of one single phase and adds it to the ArrayList of 4D meshes.
   *
   * @param phase
   * @param parameters
   * @param info
   * @param splines
   */
  private void createPhantom(
      int phase, double[] parameters, CONRADCardiacModelConfig info, ArrayList<Mesh4D> splines) {
    String pcaFile = heartBase + "\\CardiacModel\\phase_" + phase + ".ccm";
    ActiveShapeModel asm = new ActiveShapeModel(pcaFile);
    Mesh allComp = asm.getModel(parameters);

    if (phase == 0) {
      for (int i = 0; i < info.numAnatComp; i++) {
        splines.add(new Mesh4D());
      }
    }

    int count = 0;
    for (heartComponents hc : heartComponents.values()) {
      Mesh comp = new Mesh();
      SimpleMatrix pts =
          allComp
              .getPoints()
              .getSubMatrix(info.vertexOffs[count], 0, hc.getNumVertices(), info.vertexDim);
      // rotate and translate points
      for (int i = 0; i < pts.getRows(); i++) {
        SimpleVector row = SimpleOperators.multiply(rot, pts.getRow(i));
        row.add(trans);
        pts.setRowValue(i, row);
      }
      comp.setPoints(pts);
      comp.setConnectivity(
          allComp
              .getConnectivity()
              .getSubMatrix(info.triangleOffs[count], 0, hc.getNumTriangles(), 3));
      splines.get(count).addMesh(comp);
      count++;
    }
  }
  public void setData(int x, int y, int z, DarkFieldPCA myPCA) {

    SimpleMatrix eigenVectors = myPCA.getEigenVectors();
    SimpleVector eigenValues = myPCA.getEigenValues();

    for (int i = 0; i < fieldList.size(); i++) {
      SimpleVector eigenVec = eigenVectors.getCol(i);
      double eigenVal = eigenValues.getElement(i);
      eigenVec = eigenVec.multipliedBy(eigenVal);
      fieldList.get(i).setVector(x, y, z, eigenVec);
    }

    //		/**
    //		 * Threshold that checks, if 3 component of eigenvalues is too small
    //		 * If 3 component is too small, don't consider it as a fiber orientation
    //		 * and ignore it
    //		 */
    //		double th = 1E-10;

    //		SimpleVector fiberDir;
    //		if(myPCA.getEigenValues().getElement(2)<th){
    //			fiberDir = new SimpleVector(3);
    //		}else{
    //			fiberDir = myPCA.getEigenVectors().getCol(2).normalizedL2();
    //			fiberDir.multiplyBy(myPCA.getEigenValues().getElement(2));
    //		}

  }
  public static void printSimpleMatrix(SimpleMatrix A) {
    int n = A.getRows();
    int m = A.getCols();

    for (int i = 0; i < n; i++) {
      for (int j = 0; j < m; j++) {
        System.out.print(A.getElement(i, j) + "\t");
      }
      System.out.print("\n");
    }
  }
Example #4
0
    /**
     * 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));
    }
Example #5
0
  /**
   * method to calculate a mapping K from two source positions C0, C1 to a plane C0 (C1) is the
   * source position from the first (second) view
   */
  public void createMappingToEpipolarPlane() {

    // set up source matrices //
    SimpleVector C0 = this.view1.C;
    SimpleVector C1 = this.view2.C;

    // compute Pluecker coordinates //
    double L01 = C0.getElement(0) * C1.getElement(1) - C0.getElement(1) * C1.getElement(0);
    double L02 = C0.getElement(0) * C1.getElement(2) - C0.getElement(2) * C1.getElement(0);
    double L03 = C0.getElement(0) * C1.getElement(3) - C0.getElement(3) * C1.getElement(0);
    double L12 = C0.getElement(1) * C1.getElement(2) - C0.getElement(2) * C1.getElement(1);
    double L13 = C0.getElement(1) * C1.getElement(3) - C0.getElement(3) * C1.getElement(1);
    double L23 = C0.getElement(2) * C1.getElement(3) - C0.getElement(3) * C1.getElement(2);

    // construct B (6x1) //
    SimpleVector B = new SimpleVector(L01, L02, L03, L12, L13, L23);

    // compute infinity point in direction of B //
    SimpleVector N = new SimpleVector(-L03, -L13, -L23, 0);

    // compute plane E0 containing B and X0=(0,0,0,1) //
    SimpleVector E0 = SimpleOperators.getPlueckerJoin(B, new SimpleVector(0, 0, 0, 1));

    // find othonormal basis from plane normals //
    // (vectors are of 3x1)
    SimpleVector a2 = new SimpleVector(E0.getElement(0), E0.getElement(1), E0.getElement(2));
    SimpleVector a3 = new SimpleVector(N.getElement(0), N.getElement(1), N.getElement(2));
    // set vectors to unit length
    a2.normalizeL2();
    a3.normalizeL2();

    // calculate cross product to get the last basis vector //
    SimpleVector a1 = General.crossProduct(a2, a3).negated();
    // (a1 is already of unit length -> no normalization needed)

    // set up assembly matrix A (4x3) //
    SimpleMatrix A = new SimpleMatrix(4, 3);
    A.setSubColValue(0, 0, a1);
    A.setSubColValue(0, 1, a2);
    A.setSubColValue(0, 2, C0);

    // store mapping matrix K (4x3 = 4x4 * 4x3) //
    this.K = SimpleOperators.multiplyMatrixProd(SimpleOperators.getPlueckerMatrixDual(B), A);
  }
Example #6
0
  private void CreatePhantom() {

    // Iterate over all pixels and sum up intensity values of all corresponding ellipses
    double sizeX = (double) super.getSize()[0];
    double sizeY = (double) super.getSize()[1];

    for (int i = 0; i < super.getSize()[0]; ++i) {
      double x = ((double) i - (sizeX - 1) / 2.0) / ((sizeX - 1) / 2.0);
      for (int j = 0; j < super.getSize()[1]; ++j) {
        double y = ((double) j - (sizeY - 1) / 2.0) / ((sizeY - 1) / 2.0);
        super.setAtIndex(i, super.getSize()[1] - j - 1, 0.f);
        for (int k = 0; k < Ellipses.getRows(); ++k) {
          // Extract the ellipse properties here
          double xc = x - Ellipses.getElement(k, 3);
          double yc = y - Ellipses.getElement(k, 4);
          double phi = Ellipses.getElement(k, 5) * Math.PI / 180.0;
          double cos = Math.cos(phi);
          double sin = Math.sin(phi);
          double asq = Ellipses.getElement(k, 1) * Ellipses.getElement(k, 1);
          double bsq = Ellipses.getElement(k, 2) * Ellipses.getElement(k, 2);
          double Val = Ellipses.getElement(k, 0);

          // Check if this pixel is part of the ellipse, if yes, add the given intensity value to it
          double help = Math.pow((xc * cos + yc * sin), 2.0);
          double help2 = Math.pow((yc * cos - xc * sin), 2.0);
          if (help / asq + help2 / bsq <= 1.0)
            super.setAtIndex(
                i,
                super.getSize()[1] - j - 1,
                super.getAtIndex(i, super.getSize()[1] - j - 1) + (float) Val);
        }
      }
    }
  }
Example #7
0
  private SimpleMatrix ShepMod() {
    // Modified (better contrast) Shepp-Logan Phantom according
    // to P. A. Toft, "The Radon Transform, Theory and Implementation"
    // (unpublished dissertation), p. 199.

    // One row describes properties for a single ellipse
    // Colum Values: A    a     b    x0    y0    phi

    SimpleMatrix Shep = new SimpleMatrix(10, 6);

    Shep.setRowValue(0, new SimpleVector(new double[] {1.0, 0.69, 0.92, 0, 0, 0}));
    Shep.setRowValue(1, new SimpleVector(new double[] {-0.8, 0.6624, 0.8740, 0, -0.0184, 0}));
    Shep.setRowValue(2, new SimpleVector(new double[] {-0.2, 0.1100, 0.3100, 0.22, 0.0, -18.0}));
    Shep.setRowValue(3, new SimpleVector(new double[] {-0.2, 0.1600, 0.4100, -0.22, 0.0, 18.0}));
    Shep.setRowValue(4, new SimpleVector(new double[] {0.1, 0.2100, 0.2500, 0, 0.35, 0}));
    Shep.setRowValue(5, new SimpleVector(new double[] {0.1, 0.0460, 0.0460, 0, 0.1, 0}));
    Shep.setRowValue(6, new SimpleVector(new double[] {0.1, 0.0460, 0.0460, 0, -0.1, 0}));
    Shep.setRowValue(7, new SimpleVector(new double[] {0.1, 0.0460, 0.0230, -0.08, -0.605, 0}));
    Shep.setRowValue(8, new SimpleVector(new double[] {0.1, 0.0230, 0.0230, 0, -0.606, 0}));
    Shep.setRowValue(9, new SimpleVector(new double[] {0.1, 0.0230, 0.0460, 0.06, -0.605, 0}));
    return Shep;
  }
  private synchronized void initProjectionMatrix(int projectionNumber) {
    // load projection Matrix for current Projection.
    SimpleMatrix pMat = getGeometry().getProjectionMatrix(projectionNumber).computeP();

    float[] pMatFloat = new float[pMat.getCols() * pMat.getRows()];
    for (int j = 0; j < pMat.getRows(); j++) {
      for (int i = 0; i < pMat.getCols(); i++) {
        pMatFloat[(j * pMat.getCols()) + i] = (float) pMat.getElement(j, i);
      }
    }
    JCudaDriver.cuMemcpyHtoD(
        projectionMatrix, Pointer.to(pMatFloat), Sizeof.FLOAT * pMatFloat.length);
  }
Example #9
0
  private SimpleMatrix ShepOrig() {
    // Original Shepp-Logan Phantom according to:

    // Shepp, L. A., & Logan, B. F. (1974).
    // The Fourier reconstruction of a head section-LA Shepp.
    // IEEE Transactions on Nuclear Science, NS-21, 21�43.

    // One row describes properties for a single ellipse
    // Colum Values: A    a     b    x0    y0    phi

    SimpleMatrix Shep = new SimpleMatrix(10, 6);

    Shep.setRowValue(0, new SimpleVector(new double[] {2.0, 0.69, 0.92, 0, 0, 0}));
    Shep.setRowValue(1, new SimpleVector(new double[] {-0.98, 0.6624, 0.8740, 0, -0.0184, 0}));
    Shep.setRowValue(2, new SimpleVector(new double[] {-0.02, 0.1100, 0.3100, 0.22, 0.0, -18.0}));
    Shep.setRowValue(3, new SimpleVector(new double[] {-0.02, 0.1600, 0.4100, -0.22, 0.0, 18.0}));
    Shep.setRowValue(4, new SimpleVector(new double[] {0.01, 0.2100, 0.2500, 0, 0.35, 0}));
    Shep.setRowValue(5, new SimpleVector(new double[] {0.01, 0.0460, 0.0460, 0, 0.1, 0}));
    Shep.setRowValue(6, new SimpleVector(new double[] {0.01, 0.0460, 0.0460, 0, -0.1, 0}));
    Shep.setRowValue(7, new SimpleVector(new double[] {0.01, 0.0460, 0.0230, -0.08, -0.605, 0}));
    Shep.setRowValue(8, new SimpleVector(new double[] {0.01, 0.0230, 0.0230, 0, -0.606, 0}));
    Shep.setRowValue(9, new SimpleVector(new double[] {0.01, 0.0230, 0.0460, 0.06, -0.605, 0}));
    return Shep;
  }
  private synchronized void initProjectionMatrix(int projectionNumber) {
    // load projection Matrix for current Projection.
    SimpleMatrix pMat = getGeometry().getProjectionMatrix(projectionNumber).computeP();
    float[] pMatFloat = new float[pMat.getCols() * pMat.getRows()];
    for (int j = 0; j < pMat.getRows(); j++) {
      for (int i = 0; i < pMat.getCols(); i++) {

        pMatFloat[(j * pMat.getCols()) + i] = (float) pMat.getElement(j, i);
      }
    }

    // Obtain the global pointer to the view matrix from
    // the module
    if (projectionMatrix == null)
      projectionMatrix = context.createFloatBuffer(pMatFloat.length, Mem.READ_ONLY);

    projectionMatrix.getBuffer().put(pMatFloat);
    projectionMatrix.getBuffer().rewind();
    commandQueue.putWriteBuffer(projectionMatrix, true).finish();
  }
Example #11
0
  /**
   * Constructs the triangle corresponding to the i-th face in a mesh given the connectivity
   * information fcs and the vertices vtc and adds it to the CompoundShape.
   *
   * @param vtc The vertices of the mesh.
   * @param fcs The faces of the mesh, i.e connectivity information.
   * @param i The index of the face to be constructed.
   */
  private void addTriangleAtIndex(CompoundShape cs, SimpleMatrix vtc, SimpleMatrix fcs, int i) {
    SimpleVector face = fcs.getRow(i);

    SimpleVector dirU = vtc.getRow((int) face.getElement(1));
    dirU.subtract(vtc.getRow((int) face.getElement(0)));
    double l2 = dirU.normL2();
    SimpleVector dirV = vtc.getRow((int) face.getElement(2));
    dirV.subtract(vtc.getRow((int) face.getElement(0)));
    if (dirV.normL2() < l2) {
      l2 = dirV.normL2();
    }
    double nN = General.crossProduct(dirU.normalizedL2(), dirV.normalizedL2()).normL2();

    if (l2 < Math.sqrt(CONRAD.DOUBLE_EPSILON) || nN < Math.sqrt(CONRAD.DOUBLE_EPSILON)) {
    } else {
      Triangle t =
          new Triangle(
              new PointND(vtc.getRow((int) face.getElement(0))),
              new PointND(vtc.getRow((int) face.getElement(1))),
              new PointND(vtc.getRow((int) face.getElement(2))));
      cs.add(t);
    }
  }
  @Override
  public Grid2D applyToolToImage(Grid2D imageProcessor) {
    FloatProcessor imp = new FloatProcessor(imageProcessor.getWidth(), imageProcessor.getHeight());
    imp.setPixels(imageProcessor.getBuffer());

    if (!initBead) initializeBead();
    ImageProcessor imp1 = imp.duplicate(); // original

    double[][] beadMean3D = config.getBeadMeanPosition3D(); // [beadNo][x,y,z]
    double[] uv = new double[1];

    SimpleMatrix pMatrix = config.getGeometry().getProjectionMatrix(imageIndex).computeP();
    // [projection #][bead #][u, v, state[0: initial, 1: registered, 2: updated by hough searching]]
    double[][][] beadPosition2D = config.getBeadPosition2D();

    int noBeadRegistered = 0;

    double[][] xy1 = new double[WeightBearingBeadPositionBuilder.beadNo][2]; // original
    double[][] xy2 =
        new double[WeightBearingBeadPositionBuilder.beadNo]
            [2]; // warped	(mapped to the mean), control points, reference

    double[][] xy1_hat = new double[WeightBearingBeadPositionBuilder.beadNo][2]; // original
    double[][] xy2_hat = new double[WeightBearingBeadPositionBuilder.beadNo][2]; // original

    // double distanceReferenceToCurrentBead = 0;

    for (int i = WeightBearingBeadPositionBuilder.currentBeadNo; i >= 0; i--) {

      if (beadMean3D[i][0] != 0
          || beadMean3D[i][1] != 0
          || beadMean3D[i][2] != 0) { // assume bead 3d is registered.

        uv = compute2DCoordinates(beadMean3D[i], pMatrix);

        // find bead location if registered by txt: state 1
        if (beadPosition2D[imageIndex][i][2] == 1) {

          noBeadRegistered++;

          if (isDisplay) {
            imp1.setValue(2);
            imp1.drawLine(
                (int) Math.round(beadPosition2D[imageIndex][i][0] - 10),
                (int) Math.round(beadPosition2D[imageIndex][i][1] - 10),
                (int) Math.round(beadPosition2D[imageIndex][i][0] + 10),
                (int) Math.round(beadPosition2D[imageIndex][i][1] + 10));
            imp1.drawLine(
                (int) Math.round(beadPosition2D[imageIndex][i][0] - 10),
                (int) Math.round(beadPosition2D[imageIndex][i][1] + 10),
                (int) Math.round(beadPosition2D[imageIndex][i][0] + 10),
                (int) Math.round(beadPosition2D[imageIndex][i][1] - 10));
            imp1.drawString(
                "Bead " + i + " (state:" + (int) beadPosition2D[imageIndex][i][2] + ")",
                (int) beadPosition2D[imageIndex][i][0],
                (int) beadPosition2D[imageIndex][i][1] - 10);
          }

          xy1[noBeadRegistered - 1][0] = beadPosition2D[imageIndex][i][0];
          xy1[noBeadRegistered - 1][1] = beadPosition2D[imageIndex][i][1];

          xy2[noBeadRegistered - 1][0] = uv[0];
          xy2[noBeadRegistered - 1][1] = uv[1];

        } else if (imageIndex != 0
            && imageIndex != config.getGeometry().getNumProjectionMatrices() - 1) {

          if (beadPosition2D[imageIndex - 1][i][2] == 1
              && beadPosition2D[imageIndex + 1][i][2] == 1) {

            noBeadRegistered++;

            double xMean =
                (beadPosition2D[imageIndex - 1][i][0] + beadPosition2D[imageIndex - 1][i][0]) / 2;
            double yMean =
                (beadPosition2D[imageIndex + 1][i][1] + beadPosition2D[imageIndex + 1][i][1]) / 2;

            if (isDisplay) {
              imp1.setValue(2);
              imp1.drawLine(
                  (int) Math.round(xMean - 10),
                  (int) Math.round(yMean - 10),
                  (int) Math.round(xMean + 10),
                  (int) Math.round(yMean + 10));
              imp1.drawLine(
                  (int) Math.round(xMean - 10),
                  (int) Math.round(yMean + 10),
                  (int) Math.round(xMean + 10),
                  (int) Math.round(yMean - 10));
              imp1.drawString("Bead " + i + " (state:" + "M)", (int) xMean, (int) yMean - 10);
            }

            xy1[noBeadRegistered - 1][0] = xMean;
            xy1[noBeadRegistered - 1][1] = yMean;

            xy2[noBeadRegistered - 1][0] = uv[0];
            xy2[noBeadRegistered - 1][1] = uv[1];
          }
        }

        // mean projected bead
        //				imp1.drawLine((int) Math.round(uv[0]-10), (int) Math.round(uv[1]), (int)
        // Math.round(uv[0]+10), (int) Math.round(uv[1]));
        //				imp1.drawLine((int) Math.round(uv[0]), (int) Math.round(uv[1]-10), (int)
        // Math.round(uv[0]), (int) Math.round(uv[1]+10));
      }
    }

    if (isDisplay) {
      for (int x = 0; x < config.getGeometry().getDetectorWidth(); x += 50)
        imp1.drawLine(x, 0, x, config.getGeometry().getDetectorHeight());
      for (int y = 0; y < config.getGeometry().getDetectorHeight(); y += 50)
        imp1.drawLine(0, y, config.getGeometry().getDetectorWidth(), y);
    }

    if (isCornerIncluded) {
      xy1[noBeadRegistered + 0][0] = 0;
      xy1[noBeadRegistered + 0][1] = 0;
      xy2[noBeadRegistered + 0][0] = 0;
      xy2[noBeadRegistered + 0][1] = 0;

      xy1[noBeadRegistered + 1][0] = 0;
      xy1[noBeadRegistered + 1][1] = config.getGeometry().getDetectorHeight();
      xy2[noBeadRegistered + 1][0] = 0;
      xy2[noBeadRegistered + 1][1] = config.getGeometry().getDetectorHeight();

      xy1[noBeadRegistered + 2][0] = config.getGeometry().getDetectorWidth();
      xy1[noBeadRegistered + 2][1] = 0;
      xy2[noBeadRegistered + 2][0] = config.getGeometry().getDetectorWidth();
      xy2[noBeadRegistered + 2][1] = 0;

      xy1[noBeadRegistered + 3][0] = config.getGeometry().getDetectorWidth();
      xy1[noBeadRegistered + 3][1] = config.getGeometry().getDetectorHeight();
      xy2[noBeadRegistered + 3][0] = config.getGeometry().getDetectorWidth();
      xy2[noBeadRegistered + 3][1] = config.getGeometry().getDetectorHeight();

      noBeadRegistered = noBeadRegistered + 4;
    }

    boolean fScaling = true;

    double minX = Double.MAX_VALUE;
    double maxX = 0;
    double minY = Double.MAX_VALUE;
    double maxY = 0;
    double c = 0;
    if (fScaling) { // ----- scaling to reduce condition # of A matrix
      for (int i = 0; i < noBeadRegistered; i++) {
        minX = Math.min(minX, xy1[i][0]);
        maxX = Math.max(maxX, xy1[i][0]);
        minY = Math.min(minY, xy1[i][1]);
        maxY = Math.max(maxY, xy1[i][1]);
      }
      c = Math.max(maxX - minX, maxY - minY);

      for (int i = 0; i < noBeadRegistered; i++) {
        xy1_hat[i][0] = (xy1[i][0] - minX) / c;
        xy1_hat[i][1] = (xy1[i][1] - minY) / c;

        xy2_hat[i][0] = (xy2[i][0] - minX) / c;
        xy2_hat[i][1] = (xy2[i][1] - minY) / c;
      }
    } else {
      xy1_hat = xy1;
      xy2_hat = xy2;
    }

    ImageProcessor imp2 = imp1.duplicate(); // warped

    /*
     * A*x = b
     * Matrix A = (n + 3) * (n + 3);
     * n (noBeadRegistered + 4): # of control points + 4 corner points (assume corner points are static)
     */

    int n = noBeadRegistered + 3;

    SimpleMatrix A = new SimpleMatrix(n, n);
    SimpleVector x_x = new SimpleVector(n);
    SimpleVector x_y = new SimpleVector(n);
    SimpleVector b_x = new SimpleVector(n);
    SimpleVector b_y = new SimpleVector(n);

    double rij = 0;
    double valA = 0;
    double valb_x = 0;
    double valb_y = 0;

    // Matrix L formation
    // alpha: mean of distances between control points' xy-projections) is a constant only present
    // on the diagonal of K
    // lambda: TPS smoothing regularization coefficient

    double alpha = 0.0;
    double lambda = 1.6; // 1.6
    for (int i = 0; i < noBeadRegistered; i++) { // i= # of row
      for (int j = i; j < noBeadRegistered; j++) { // j= # of column
        alpha +=
            Math.sqrt(
                Math.pow(xy2_hat[i][0] - xy2_hat[j][0], 2)
                    + Math.pow(xy2_hat[i][1] - xy2_hat[j][1], 2));
      }
    }
    alpha = alpha / Math.pow(noBeadRegistered, 2);

    for (int i = 0; i < n; i++) { // i= # of row
      for (int j = i; j < n; j++) { // j= # of column
        if (i < 3 && j < 3) valA = 0;
        else if (i >= 3 && j >= 3 && i == j) {
          valA = Math.pow(alpha, 2) * lambda;
          // valA = lambda;
          if (imageIndex < 10)
            System.out.println("Regularization = " + valA + ", lambda= " + lambda);
        } else if (i == 0 && j >= 0) valA = 1;
        else if (i == 1 && j >= 3) valA = xy1_hat[j - 3][0];
        else if (i == 2 && j >= 3) valA = xy1_hat[j - 3][1];
        else {
          rij =
              Math.pow(xy1_hat[j - 3][0] - xy1_hat[i - 3][0], 2)
                  + Math.pow(xy1_hat[j - 3][1] - xy1_hat[i - 3][1], 2);
          if (rij == 0) valA = 0;
          else valA = rij * Math.log(rij);
        }

        A.setElementValue(i, j, valA);
        A.setElementValue(j, i, valA);
      }

      if (i < 3) {
        valb_x = 0;
        valb_y = 0;
      } else {
        //				valb_x = xy2_hat[i-3][0]-xy1_hat[i-3][0];
        //				valb_y = xy2_hat[i-3][1]-xy1_hat[i-3][1];
        valb_x = xy2[i - 3][0] - xy1[i - 3][0];
        valb_y = xy2[i - 3][1] - xy1[i - 3][1];
        //				if (imageIndex > 150 && imageIndex < 170)
        //					System.out.println("Idx" + imageIndex + ",Elevation" + (i-3) + ": " + valb_x + "---"
        // + valb_y);
      }

      b_x.setElementValue(i, valb_x);
      b_y.setElementValue(i, valb_y);
    }

    // System.out.println("A condition number=" + A.conditionNumber(MatrixNormType.MAT_NORM_L1));
    // System.out.println("A condition number=" + A.conditionNumber(MatrixNormType.MAT_NORM_LINF));

    x_x = Solvers.solveLinearSysytemOfEquations(A, b_x);
    x_y = Solvers.solveLinearSysytemOfEquations(A, b_y);

    if (fScaling) {
      // ----- pixel space coefficients a, b scaling back
      double tmpA0 =
          x_x.getElement(0) - x_x.getElement(1) * (minX / c) - x_x.getElement(2) * (minY / c);
      for (int j = 0; j < noBeadRegistered; j++) {
        tmpA0 -=
            Math.log(c)
                * 2
                * x_x.getElement(j + 3)
                * (Math.pow(xy1_hat[j][0], 2) + Math.pow(xy1_hat[j][1], 2));
      }
      x_x.setElementValue(0, tmpA0);
      tmpA0 = x_y.getElement(0) - x_y.getElement(1) * (minX / c) - x_y.getElement(2) * (minY / c);
      for (int j = 0; j < noBeadRegistered; j++) {
        tmpA0 -=
            Math.log(c)
                * 2
                * x_y.getElement(j + 3)
                * (Math.pow(xy1_hat[j][0], 2) + Math.pow(xy1_hat[j][1], 2));
      }
      x_y.setElementValue(0, tmpA0);

      x_x.setElementValue(1, x_x.getElement(1) / c);
      x_y.setElementValue(1, x_y.getElement(1) / c);
      x_x.setElementValue(2, x_x.getElement(2) / c);
      x_y.setElementValue(2, x_y.getElement(2) / c);

      for (int i = 3; i < n; i++) {
        x_x.setElementValue(i, x_x.getElement(i) / Math.pow(c, 2));
        x_y.setElementValue(i, x_y.getElement(i) / Math.pow(c, 2));
      }
      // ----- pixel space coefficients a, b scaling back end
    }

    double devU = 0;
    double devV = 0;
    // Do warping
    // if (imageIndex == 0) {
    for (int y = 0; y < config.getGeometry().getDetectorHeight(); y++) {
      // for (int y=252; y<253; y++) {
      for (int x = 0; x < config.getGeometry().getDetectorWidth(); x++) {
        // for (int x=606; x<607; x++) {
        devU = x_x.getElement(0) + x_x.getElement(1) * x + x_x.getElement(2) * y;
        devV = x_y.getElement(0) + x_y.getElement(1) * x + x_y.getElement(2) * y;
        for (int i = 0; i < noBeadRegistered; i++) {
          rij = Math.pow(xy1[i][0] - x, 2) + Math.pow(xy1[i][1] - y, 2);
          if (rij > 0) {
            devU += x_x.getElement(i + 3) * rij * Math.log(rij);
            devV += x_y.getElement(i + 3) * rij * Math.log(rij);
          }
        }

        //					devU = 0;
        //					devV = 0;

        imp2.setf(x, y, (float) imp1.getInterpolatedValue(x - devU, y - devV));

        // System.out.println("x, y=" + x + ", " + y + "\t" + devU + ", " + devV);
        // maxDevU = Math.max(maxDevU, devU);
        // maxDevV = Math.max(maxDevV, devV);
      }
    }

    // Error estimate after transformation
    //			for (int i=0; i<= WeightBearingBeadPositionBuilder.currentBeadNo; i++){
    //
    //				if (beadMean3D[i][0] != 0 || beadMean3D[i][1] != 0 || beadMean3D[i][2] != 0){ // assume
    // bead 3d is registered.
    //
    //					// find bead location if registered by txt: state 1
    //					if (beadPosition2D[imageIndex][i][2] == 1){
    //
    //						// Projected Reference
    //						uv = compute2DCoordinates(beadMean3D[i], pMatrix);
    //						double x = uv[0];
    //						double y = uv[1];
    //						// bead detected position in 2d
    //						// Transform to 2D coordinates, time variant position
    //						//beadPosition2D[imageIndex][i][0];
    //						//beadPosition2D[imageIndex][i][1];
    //
    //						devU = x_x.getElement(0) + x_x.getElement(1)*x + x_x.getElement(2)*y;
    //						devV = x_y.getElement(0) + x_y.getElement(1)*x + x_y.getElement(2)*y;
    //						for (int j=0; j<noBeadRegistered; j++){
    //							rij = Math.pow(xy1[j][0]-x, 2) + Math.pow(xy1[j][1]-y, 2);
    //							if (rij > 0) {
    //								devU += x_x.getElement(j+3)*rij*Math.log(rij);
    //								devV += x_y.getElement(j+3)*rij*Math.log(rij);
    //							}
    //						}
    //
    //						distanceReferenceToCurrentBead +=
    // Math.sqrt(Math.pow(uv[0]-(beadPosition2D[imageIndex][i][0]+devU),
    // 2)+Math.pow(uv[1]-(beadPosition2D[imageIndex][i][1]+devV), 2));
    //
    //					}
    //				}
    //			}
    //			System.out.println("Euclidean distance\t" + imageIndex + "\t" +
    // distanceReferenceToCurrentBead/noBeadRegistered);

    // }

    if (isDisplay) {
      for (int i = WeightBearingBeadPositionBuilder.currentBeadNo; i >= 0; i--) {

        if (beadMean3D[i][0] != 0
            || beadMean3D[i][1] != 0
            || beadMean3D[i][2] != 0) { // assume bead 3d is registered.

          uv = compute2DCoordinates(beadMean3D[i], pMatrix);

          imp2.setValue(2);
          // mean projected bead
          imp2.drawLine(
              (int) Math.round(uv[0] - 10),
              (int) Math.round(uv[1]),
              (int) Math.round(uv[0] + 10),
              (int) Math.round(uv[1]));
          imp2.drawLine(
              (int) Math.round(uv[0]),
              (int) Math.round(uv[1] - 10),
              (int) Math.round(uv[0]),
              (int) Math.round(uv[1] + 10));
        }
      }
    }
    Grid2D result = new Grid2D((float[]) imp2.getPixels(), imp2.getWidth(), imp2.getHeight());
    return result;
  }
  public void setTrajectory(
      int numProjectionMatrices,
      double sourceToAxisDistance,
      double averageAngularIncrement,
      double detectorOffsetX,
      double detectorOffsetY,
      CameraAxisDirection uDirection,
      CameraAxisDirection vDirection,
      SimpleVector rotationAxis,
      PointND rotationCenter,
      double angleFirstProjection) {
    this.projectionMatrices = new Projection[numProjectionMatrices];
    this.primaryAngles = new double[numProjectionMatrices];
    this.numProjectionMatrices = numProjectionMatrices;
    this.sourceToAxisDistance = sourceToAxisDistance;
    this.averageAngularIncrement = averageAngularIncrement;
    this.detectorOffsetU = detectorOffsetX;
    this.detectorOffsetV = detectorOffsetY;

    double cosPhi = Math.cos(General.toRadians(angleFirstProjection));
    double sinPhi = Math.sin(General.toRadians(angleFirstProjection));
    SimpleMatrix rotMat = new SimpleMatrix(3, 3);
    rotMat.setElementValue(0, 0, cosPhi);
    rotMat.setElementValue(0, 1, sinPhi);
    rotMat.setElementValue(1, 0, -sinPhi);
    rotMat.setElementValue(1, 1, cosPhi);
    rotMat.setElementValue(2, 2, 1);
    SimpleVector centerToCameraIdealAtInitialAngle =
        SimpleOperators.multiply(rotMat, new SimpleVector(sourceToAxisDistance, 0, 0));
    Plane3D trajPlane =
        new Plane3D(
            rotationAxis,
            SimpleOperators.multiplyInnerProd(rotationAxis, rotationCenter.getAbstractVector()));
    double distToPlane = trajPlane.computeDistance(new PointND(centerToCameraIdealAtInitialAngle));
    SimpleVector centerToCameraDir =
        SimpleOperators.subtract(
            SimpleOperators.add(
                rotationAxis.multipliedBy(-1 * distToPlane), centerToCameraIdealAtInitialAngle),
            rotationCenter.getAbstractVector());
    centerToCameraDir.divideBy(centerToCameraDir.normL2());
    SimpleVector centerToCameraInitialInPlane =
        centerToCameraDir.multipliedBy(sourceToAxisDistance);

    for (int i = 0; i < numProjectionMatrices; i++) {
      primaryAngles[i] = i * averageAngularIncrement + angleFirstProjection;
      // System.out.println(primaryAngles[i] + " " + averageAngularIncrement + " " +
      // this.reconDimensions[0] + " " + this.reconDimensions[1]);
      projectionMatrices[i] = new Projection();
      double rotationAngle = General.toRadians(primaryAngles[i]);
      projectionMatrices[i].setRtFromCircularTrajectory(
          rotationCenter.getAbstractVector(),
          rotationAxis,
          sourceToAxisDistance,
          centerToCameraInitialInPlane,
          uDirection,
          vDirection,
          rotationAngle);
      SimpleVector spacingUV = new SimpleVector(pixelDimensionX, pixelDimensionY);
      SimpleVector sizeUV = new SimpleVector(detectorWidth, detectorHeight);
      SimpleVector offset = new SimpleVector(detectorOffsetX, detectorOffsetY);
      projectionMatrices[i].setKFromDistancesSpacingsSizeOffset(
          sourceToDetectorDistance, spacingUV, sizeUV, offset, 1.0, 0);
    }
    this.projectionStackSize = numProjectionMatrices;
    // System.out.println("Defined geometry with SDD " +sourceToDetectorDistance);
  }