@Override
  public void workOnSlice(int sliceNumber) {
    PrioritizableScene phantomScene = phantom;
    if (phantom instanceof AnalyticPhantom4D) {
      AnalyticPhantom4D scene4D = (AnalyticPhantom4D) phantom;
      phantomScene = scene4D.getScene(((double) sliceNumber) / trajectory.getProjectionStackSize());

      String disableAutoCenterBoolean =
          Configuration.getGlobalConfiguration()
              .getRegistryEntry(RegKeys.DISABLE_CENTERING_4DPHANTOM_PROJECTION_RENDERING);
      boolean disableAutoCenter = false;
      if (disableAutoCenterBoolean != null) {
        disableAutoCenter = Boolean.parseBoolean(disableAutoCenterBoolean);
      }

      Translation centerTranslation = new Translation(new SimpleVector(0, 0, 0));
      if (!disableAutoCenter) {
        SimpleVector center =
            SimpleOperators.add(
                    phantom.getMax().getAbstractVector(), phantom.getMin().getAbstractVector())
                .dividedBy(2);
        centerTranslation = new Translation(center.negated());
      }

      for (PhysicalObject o : phantomScene) {
        o.getShape().applyTransform(centerTranslation);
        // System.out.println(o.getShape().getMax() + " " + o.getShape().getMin());

        // Translate a part of XCAT to the center of source & detector for 2D projection (e.g. knee
        // at the center of the 2d projection)
        String translationString =
            Configuration.getGlobalConfiguration()
                .getRegistryEntry(RegKeys.GLOBAL_TRANSLATION_4DPHANTOM_PROJECTION_RENDERING);
        if (translationString != null) {
          // Center b/w RKJC & LKJC: -292.6426  211.7856  440.7783 (subj 5, static60),-401.1700
          // 165.9885  478.5600 (subj 2, static60)
          // XCAT Center by min & max: -177.73999504606988, 179.8512744259873, 312.19713254613583
          // translationVector = (XCAT Center by min & max) - (Center b/w RKJC & LKJC)=>
          // 114.9026, -31.9343, -128.5811 (subj5),  120, 3, -110(subj2) Try 114.0568    2.4778
          // -106.2550
          String[] values = translationString.split(", ");
          SimpleVector translationVector =
              new SimpleVector(
                  Double.parseDouble(values[0]),
                  Double.parseDouble(values[1]),
                  Double.parseDouble(values[2]));
          Translation translationToRotationCenter = new Translation(translationVector);
          o.getShape().applyTransform(translationToRotationCenter);
        }
      }
      // System.out.println(phantomScene.getMax() + " " + phantomScene.getMin());
    }
    Grid2D slice = raytraceScene(phantomScene, trajectory.getProjectionMatrix(sliceNumber));
    this.imageBuffer.add(slice, sliceNumber);
  }
예제 #2
0
  public DefrisePhantom() {

    Trajectory trajectory = Configuration.getGlobalConfiguration().getGeometry();

    double sourceAxisDistance = trajectory.getSourceToAxisDistance();
    double sourceDetectorDistance = trajectory.getSourceToDetectorDistance();
    double detectorYAxis = trajectory.getDetectorHeight() * trajectory.getPixelDimensionY();
    double detectorXAxis = trajectory.getDetectorWidth() * trajectory.getPixelDimensionX();

    double fovRadius = detectorXAxis * sourceAxisDistance / sourceDetectorDistance / 2 * 0.95;
    double diskRadius = 4.0 / 5.0 * fovRadius;
    double fovHeight = detectorYAxis * sourceAxisDistance / sourceDetectorDistance;
    double diskHeight = fovHeight / 15.0;
    double diskSpacing = fovHeight / 15.0;
    int numDisks = 5;
    double diskStart =
        -(fovHeight / 2.0)
            + ((fovHeight - (numDisks * diskHeight + diskSpacing * (numDisks - 1))) / 2.0)
            + diskHeight / 2.0;

    // Water Body
    Cylinder cyl = new Cylinder(fovRadius, fovRadius, fovHeight);
    cyl.setName("Water-like body of the phantom");
    PhysicalObject po = new PhysicalObject();
    po.setMaterial(MaterialsDB.getMaterialWithName("Water")); // D = 1.0
    po.setShape(cyl);
    add(po);

    // Disk Inserts
    for (int i = 0; i < numDisks; i++) {
      cyl = new Cylinder(diskRadius, diskRadius, diskHeight);
      cyl.setName("Disk");
      cyl.applyTransform(
          new Translation(new SimpleVector(0, 0, diskStart + (diskSpacing + diskHeight) * i)));
      po = new PhysicalObject();
      po.setMaterial(MaterialsDB.getMaterialWithName("Plexiglass")); // D = 1.95
      po.setShape(cyl);
      add(po);
    }
  }
  public Grid2D raytraceScene(PrioritizableScene phantomScene, Projection projection) {
    Trajectory geom = Configuration.getGlobalConfiguration().getGeometry();
    // Grid2D slice = new Grid2D(geom.getDetectorWidth(), geom.getDetectorHeight());
    Grid2D slice =
        detector.createDetectorGrid(geom.getDetectorWidth(), geom.getDetectorHeight(), projection);
    rayTracer.setScene(phantomScene);
    // Second rule of optimization is: Optimize later.
    PointND raySource = new PointND(0, 0, 0);
    raySource.setCoordinates(projection.computeCameraCenter());
    StraightLine castLine = new StraightLine(raySource, new SimpleVector(0, 0, 0));

    SimpleVector centerPixDir = null;
    if (accurate) {
      centerPixDir = projection.computePrincipalAxis();
    }
    // SimpleVector prinpoint = trajectory.getProjectionMatrix(sliceNumber).getPrincipalPoint();

    double xcorr = 0; // trajectory.getDetectorWidth()/2 - prinpoint.getElement(0);
    double ycorr = 0; // trajectory.getDetectorHeight()/2 - prinpoint.getElement(1);

    double length = trajectory.getSourceToDetectorDistance();
    Edge environmentEdge = new Edge(new PointND(0), new PointND(length));

    ArrayList<PhysicalObject> fallBackBackground = new ArrayList<PhysicalObject>(1);
    SimpleVector pixel = new SimpleVector(0, 0);
    boolean negate = false;
    for (int y = 0; y < trajectory.getDetectorHeight(); y++) {
      for (int x = 0; x < trajectory.getDetectorWidth(); x++) {
        pixel.setElementValue(0, x - xcorr);
        pixel.setElementValue(1, y - ycorr);
        SimpleVector dir = projection.computeRayDirection(pixel);
        if ((y == 0) && (x == 0)) {
          // Check that ray direction is towards origin.
          double max = 0;
          int index = 0;
          for (int i = 0; i < 3; i++) {
            if (Math.abs(dir.getElement(i)) > max) {
              max = Math.abs(dir.getElement(i));
              index = i;
            }
          }
          double t = -raySource.get(index) / dir.getElement(index);
          if (t < 0) negate = true;
        }
        if (negate) dir.negate();
        castLine.setDirection(dir);

        ArrayList<PhysicalObject> segments = rayTracer.castRay(castLine);
        if (accurate) {
          double dirCosine = SimpleOperators.multiplyInnerProd(centerPixDir, dir);
          length = trajectory.getSourceToDetectorDistance() / dirCosine;
        }

        if (segments == null) {
          fallBackBackground.clear();
          segments = fallBackBackground;
        } else {
          if (accurate) {
            environmentEdge =
                new Edge(new PointND(0), new PointND(length - getTotalSegmentsLength(segments)));
          }
        }
        environment.setShape(environmentEdge);
        segments.add(environment);
        /* old code:
        double integral = absorptionModel.evaluateLineIntegral(segments);

        slice.putPixelValue(x, y, integral);
         */
        detector.writeToDetector(slice, x, y, segments);
      }
    }
    return slice;
  }