@Override
  public final Array apply(Array sourceArray, Item sourceColumn) throws RuleException {
    final int[] shape = getContext().getTargetVariable().getShape();
    final int sizeY = shape[1];
    final int sizeX = shape[2];
    final Array targetArray = createTargetArray(sizeY, sizeX);

    final Reader observationReader = getContext().getObservationReader();
    if (observationReader == null) {
      return targetArray;
    }

    final int recordNo = getContext().getObservation().getRecordNo();
    final GeoCoding geoCoding;
    try {
      geoCoding = observationReader.getGeoCoding(recordNo);
    } catch (IOException ignored) {
      return targetArray;
    }

    final Point point =
        getContext().getMatchup().getRefObs().getPoint().getGeometry().getFirstPoint();
    final double lon = point.getX();
    final double lat = point.getY();
    final PixelLocator pixelLocator = new GeoCodingWrapper(geoCoding);
    final Point2D p = new Point2D.Double();
    final boolean found = pixelLocator.getPixelLocation(lon, lat, p);
    if (found) {
      final Watermask watermask = Container.WATERMASK;
      final Index index = targetArray.getIndex();
      final int minX = (int) Math.max(p.getX() - sizeX / 2, 0.0);
      final int maxX =
          (int) Math.min(p.getX() + sizeX / 2, observationReader.getElementCount() - 1);
      final int minY = (int) Math.max(p.getY() - sizeY / 2, 0.0);
      final int maxY =
          (int) Math.min(p.getY() + sizeY / 2, observationReader.getScanLineCount() - 1);
      for (int y = minY, yi = 0; y <= maxY; y++, yi++) {
        for (int x = minX, xi = 0; x <= maxX; x++, xi++) {
          final byte waterFraction =
              watermask.getWaterFraction(x, y, pixelLocator, stepCountX, stepCountY);
          targetArray.setByte(index.set(0, yi, xi), waterFraction);
        }
      }
    }
    return targetArray;
  }