protected void generateHistogramData(DataContainer<T> container) {
    double ch1BinWidth = getXBinWidth(container);
    double ch2BinWidth = getYBinWidth(container);

    // get the 2 images for the calculation of Pearson's
    final RandomAccessibleInterval<T> img1 = getImageCh1(container);
    final RandomAccessibleInterval<T> img2 = getImageCh2(container);
    final RandomAccessibleInterval<BitType> mask = container.getMask();

    // get the cursors for iterating through pixels in images
    TwinCursor<T> cursor =
        new TwinCursor<T>(
            img1.randomAccess(), img2.randomAccess(), Views.iterable(mask).localizingCursor());

    // create new image to put the scatter-plot in
    final ImgFactory<LongType> scatterFactory = new ArrayImgFactory<LongType>();
    plotImage = scatterFactory.create(new int[] {xBins, yBins}, new LongType());

    // create access cursors
    final RandomAccess<LongType> histogram2DCursor = plotImage.randomAccess();

    // iterate over images
    long[] pos = new long[plotImage.numDimensions()];
    while (cursor.hasNext()) {
      cursor.fwd();
      double ch1 = cursor.getFirst().getRealDouble();
      double ch2 = cursor.getSecond().getRealDouble();
      /* Scale values for both channels to fit in the range.
       * Moreover mirror the y value on the x axis.
       */
      pos[0] = getXValue(ch1, ch1BinWidth, ch2, ch2BinWidth);
      pos[1] = getYValue(ch1, ch1BinWidth, ch2, ch2BinWidth);
      // set position of input/output cursor
      histogram2DCursor.setPosition(pos);
      // get current value at position and increment it
      long count = histogram2DCursor.get().getIntegerLong();
      count++;

      histogram2DCursor.get().set(count);
    }

    xBinWidth = ch1BinWidth;
    yBinWidth = ch2BinWidth;
    xLabel = getLabelCh1();
    yLabel = getLabelCh2();
    xMin = getXMin(container);
    xMax = getXMax(container);
    yMin = getYMin(container);
    yMax = getYMax(container);
  }
 /**
  * Gets the minimum of channel two. Takes channel swapping into consideration and will return min
  * of channel one if swapped.
  *
  * @return The minimum of what is seen as channel two.
  */
 protected double getMinCh2(DataContainer<T> container) {
   return swapChannels ? container.getMinCh1() : container.getMinCh2();
 }
 /**
  * Gets the image of channel two. Takes channel swapping into consideration and will return image
  * of channel one if swapped.
  *
  * @return The image of what is seen as channel two.
  */
 protected RandomAccessibleInterval<T> getImageCh2(DataContainer<T> container) {
   return swapChannels ? container.getSourceImage1() : container.getSourceImage2();
 }