private void raytrace(double energyEV, int numRays) {
    Grid2D grid = new Grid2D(600, 500);
    FloatProcessor imp;
    imp = new FloatProcessor(grid.getWidth(), grid.getHeight());
    imp.setPixels(grid.getBuffer());

    //		 SimpleVector startPosition = new SimpleVector(40,grid.getHeight()/2/scale, 0);
    SimpleVector startPosition = new SimpleVector(0, 0, 0);

    for (int i = 0; i < numRays; ++i) {
      followRay(startPosition.clone(), new SimpleVector(1, 0, 0), energyEV, imp, 0, 0);
    }
    imp.drawString(
        grid.getWidth() / scale + "cm",
        grid.getWidth() / 2 - 20,
        grid.getHeight() - 10,
        Color.WHITE);

    grid.show("Energy: " + energyEV + "eV, Material: " + material.getName());

    System.out.println(
        "Rejection sampling: average misses per draw: " + (float) sumMisses / (float) numDraws);

    numDraws = 0;
    sumMisses = 0;
  }
  private void followRay(
      SimpleVector pos,
      SimpleVector dir,
      double energyEV,
      FloatProcessor imp,
      int scatterCount,
      double totalDistance) {
    if (energyEV <= 1 || scatterCount > 20000) {
      System.out.println("energy low, times scattered: " + scatterCount);
      return;
    }
    // follow ray until next interaction point
    SimpleVector oldPos = pos.clone();
    double dist = sampler.getDistanceUntilNextInteractionCm(material, energyEV);
    pos.add(dir.multipliedBy(dist));
    pathlengths.add(dist);
    // draw the entire path
    // imp.drawLine((int)(scale*oldPos.getElement(0)), (int)(scale*oldPos.getElement(1)),
    // (int)(scale*pos.getElement(0)), (int)(scale*pos.getElement(1)));
    // draw interaction points only
    imp.drawDot((int) (scale * pos.getElement(0)), (int) (scale * pos.getElement(1)));

    // choose compton or photoelectric effect
    double photo =
        material.getAttenuation(energyEV / 1000, AttenuationType.PHOTOELECTRIC_ABSORPTION);
    double compton =
        material.getAttenuation(energyEV / 1000, AttenuationType.INCOHERENT_ATTENUATION);

    if (sampler.random() * (photo + compton) <= photo) {
      // photoelectric absorption
      energyEV = 0;
      // System.out.println("absorbed after " + scatterCount + " collisions");
      xs.add(pos.getElement(0));
      ys.add(pos.getElement(1));
      zs.add(pos.getElement(2));

      return;
    } else {
      // compton scattering

      energyEV = sampler.sampleComptonScattering(energyEV, dir);

      // send new ray
      followRay(pos, dir, energyEV, imp, scatterCount + 1, totalDistance + dist);
    }
  }