/**
   * The template method which is called by the {@link
   * org.esa.snap.framework.dataio.AbstractProductReader#readBandRasterDataImpl(int, int, int, int,
   * int, int, org.esa.snap.framework.datamodel.Band, int, int, int, int,
   * org.esa.snap.framework.datamodel.ProductData, com.bc.ceres.core.ProgressMonitor)} } method
   * after an optional spatial subset has been applied to the input parameters.
   *
   * <p>The destination band, buffer and region parameters are exactly the ones passed to the
   * original {@link org.esa.snap.framework.dataio.AbstractProductReader#readBandRasterDataImpl}
   * call. Since the <code>destOffsetX</code> and <code>destOffsetY</code> parameters are already
   * taken into acount in the <code>sourceOffsetX</code> and <code>sourceOffsetY</code> parameters,
   * an implementor of this method is free to ignore them.
   *
   * @param sourceOffsetX the absolute X-offset in source raster co-ordinates
   * @param sourceOffsetY the absolute Y-offset in source raster co-ordinates
   * @param sourceWidth the width of region providing samples to be read given in source raster
   *     co-ordinates
   * @param sourceHeight the height of region providing samples to be read given in source raster
   *     co-ordinates
   * @param sourceStepX the sub-sampling in X direction within the region providing samples to be
   *     read
   * @param sourceStepY the sub-sampling in Y direction within the region providing samples to be
   *     read
   * @param destBand the destination band which identifies the data source from which to read the
   *     sample values
   * @param destBuffer the destination buffer which receives the sample values to be read
   * @param destOffsetX the X-offset in the band's raster co-ordinates
   * @param destOffsetY the Y-offset in the band's raster co-ordinates
   * @param destWidth the width of region to be read given in the band's raster co-ordinates
   * @param destHeight the height of region to be read given in the band's raster co-ordinates
   * @param pm a monitor to inform the user about progress
   * @throws java.io.IOException if an I/O error occurs
   * @see #getSubsetDef
   */
  @Override
  protected void readBandRasterDataImpl(
      int sourceOffsetX,
      int sourceOffsetY,
      int sourceWidth,
      int sourceHeight,
      int sourceStepX,
      int sourceStepY,
      Band destBand,
      int destOffsetX,
      int destOffsetY,
      int destWidth,
      int destHeight,
      ProductData destBuffer,
      ProgressMonitor pm)
      throws IOException {
    final int sourceMinX = sourceOffsetX;
    final int sourceMinY = sourceOffsetY;
    final int sourceMaxX = sourceOffsetX + sourceWidth - 1;
    final int sourceMaxY = sourceOffsetY + sourceHeight - 1;

    final File dataFile = bandDataFiles.get(destBand);
    final ImageInputStream inputStream = getOrCreateImageInputStream(destBand, dataFile);
    if (inputStream == null) {
      return;
    }

    int destPos = 0;

    pm.beginTask("Reading band '" + destBand.getName() + "'...", sourceMaxY - sourceMinY);
    // For each scan in the data source
    try {
      synchronized (inputStream) {
        for (int sourceY = sourceMinY; sourceY <= sourceMaxY; sourceY += sourceStepY) {
          if (pm.isCanceled()) {
            break;
          }
          final long sourcePosY = (long) sourceY * destBand.getRasterWidth();
          if (sourceStepX == 1) {
            long inputPos = sourcePosY + sourceMinX;
            destBuffer.readFrom(destPos, destWidth, inputStream, inputPos);
            destPos += destWidth;
          } else {
            for (int sourceX = sourceMinX; sourceX <= sourceMaxX; sourceX += sourceStepX) {
              long inputPos = sourcePosY + sourceX;
              destBuffer.readFrom(destPos, 1, inputStream, inputPos);
              destPos++;
            }
          }
        }
        pm.worked(1);
      }
    } finally {
      pm.done();
    }
  }
  /**
   * Reads raster data from the data source specified by the given destination band into the given
   * in-memory buffer and region.
   *
   * <p>For a complete description, please refer to the {@link
   * ProductReader#readBandRasterData(org.esa.snap.framework.datamodel.Band, int, int, int, int,
   * org.esa.snap.framework.datamodel.ProductData, com.bc.ceres.core.ProgressMonitor)} interface
   * definition} of this method.
   *
   * <p>The <code>AbstractProductReader</code> implements this method using the <i>Template
   * Method</i> pattern. The template method in this case is the abstract method to which the call
   * is delegated after an optional spatial subset given by {@link #getSubsetDef()} has been applied
   * to the input parameters.
   *
   * @param destBand the destination band which identifies the data source from which to read the
   *     sample values
   * @param destOffsetX the X-offset in the band's raster co-ordinates
   * @param destOffsetY the Y-offset in the band's raster co-ordinates
   * @param destWidth the width of region to be read given in the band's raster co-ordinates
   * @param destHeight the height of region to be read given in the band's raster co-ordinates
   * @param destBuffer the destination buffer which receives the sample values to be read
   * @param pm a monitor to inform the user about progress
   * @throws IOException if an I/O error occurs
   * @throws IllegalArgumentException if the number of elements destination buffer not equals <code>
   *     destWidth *
   *                                  destHeight</code> or the destination region is out of the
   *     band's raster
   * @see #readBandRasterDataImpl(int, int, int, int, int, int,
   *     org.esa.snap.framework.datamodel.Band, int, int, int, int,
   *     org.esa.snap.framework.datamodel.ProductData, com.bc.ceres.core.ProgressMonitor)
   * @see #getSubsetDef()
   * @see ProductReader#readBandRasterData(org.esa.snap.framework.datamodel.Band, int, int, int,
   *     int, org.esa.snap.framework.datamodel.ProductData, com.bc.ceres.core.ProgressMonitor)
   * @see org.esa.snap.framework.datamodel.Band#getRasterWidth()
   * @see org.esa.snap.framework.datamodel.Band#getRasterHeight()
   */
  public void readBandRasterData(
      Band destBand,
      int destOffsetX,
      int destOffsetY,
      int destWidth,
      int destHeight,
      ProductData destBuffer,
      ProgressMonitor pm)
      throws IOException {

    Guardian.assertNotNull("destBand", destBand);
    Guardian.assertNotNull("destBuffer", destBuffer);

    if (destBuffer.getNumElems() < destWidth * destHeight) {
      throw new IllegalArgumentException("destination buffer too small");
    }
    if (destBuffer.getNumElems() > destWidth * destHeight) {
      throw new IllegalArgumentException("destination buffer too big");
    }

    int sourceOffsetX = 0;
    int sourceOffsetY = 0;
    int sourceStepX = 1;
    int sourceStepY = 1;
    if (getSubsetDef() != null) {
      sourceStepX = getSubsetDef().getSubSamplingX();
      sourceStepY = getSubsetDef().getSubSamplingY();
      if (getSubsetDef().getRegion() != null) {
        sourceOffsetX = getSubsetDef().getRegion().x;
        sourceOffsetY = getSubsetDef().getRegion().y;
      }
    }
    sourceOffsetX += sourceStepX * destOffsetX;
    sourceOffsetY += sourceStepY * destOffsetY;
    int sourceWidth = sourceStepX * (destWidth - 1) + 1;
    int sourceHeight = sourceStepY * (destHeight - 1) + 1;

    readBandRasterDataImpl(
        sourceOffsetX,
        sourceOffsetY,
        sourceWidth,
        sourceHeight,
        sourceStepX,
        sourceStepY,
        destBand,
        destOffsetX,
        destOffsetY,
        destWidth,
        destHeight,
        destBuffer,
        pm);
  }
  private static Band[] createXYDisplacementBands(final Product product, ProgressMonitor pm) {
    final int width = product.getSceneRasterWidth();
    final int height = product.getSceneRasterHeight();

    ImageInfo blueToRedGrad =
        new ImageInfo(
            new ColorPaletteDef(
                new ColorPaletteDef.Point[] {
                  new ColorPaletteDef.Point(-1.0, Color.BLUE),
                  new ColorPaletteDef.Point(0.0, Color.WHITE),
                  new ColorPaletteDef.Point(1.0, Color.RED),
                }));
    ImageInfo amplGrad =
        new ImageInfo(
            new ColorPaletteDef(
                new ColorPaletteDef.Point[] {
                  new ColorPaletteDef.Point(0.0, Color.WHITE),
                  new ColorPaletteDef.Point(1.0, Color.RED),
                }));
    ImageInfo phaseGrad =
        new ImageInfo(
            new ColorPaletteDef(
                new ColorPaletteDef.Point[] {
                  new ColorPaletteDef.Point(-Math.PI, Color.WHITE),
                  new ColorPaletteDef.Point(0.0, Color.BLUE),
                  new ColorPaletteDef.Point(+Math.PI, Color.WHITE),
                }));

    final Band bandX = new Band("gc_displ_x", ProductData.TYPE_FLOAT64, width, height);
    configureBand(bandX, blueToRedGrad.clone(), "pixels", "Geo-coding X-displacement");

    final Band bandY = new Band("gc_displ_y", ProductData.TYPE_FLOAT64, width, height);
    configureBand(bandY, blueToRedGrad.clone(), "pixels", "Geo-coding Y-displacement");

    final Band bandAmpl =
        new VirtualBand(
            "gc_displ_ampl",
            ProductData.TYPE_FLOAT64,
            width,
            height,
            "ampl(gc_displ_x, gc_displ_y)");
    configureBand(bandAmpl, amplGrad.clone(), "pixels", "Geo-coding displacement amplitude");

    final Band bandPhase =
        new VirtualBand(
            "gc_displ_phase",
            ProductData.TYPE_FLOAT64,
            width,
            height,
            "phase(gc_displ_x, gc_displ_y)");
    configureBand(bandPhase, phaseGrad.clone(), "radians", "Geo-coding displacement phase");

    final double[] dataX = new double[width * height];
    final double[] dataY = new double[width * height];

    bandX.setRasterData(ProductData.createInstance(dataX));
    bandY.setRasterData(ProductData.createInstance(dataY));

    pm.beginTask(
        "Computing geo-coding displacements for product '" + product.getName() + "'...", height);
    try {
      final GeoPos geoPos = new GeoPos();
      final PixelPos pixelPos1 = new PixelPos();
      final PixelPos pixelPos2 = new PixelPos();
      for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
          double maxX = 0;
          double maxY = 0;
          double valueX = 0;
          double valueY = 0;
          for (float[] offset : OFFSETS) {
            pixelPos1.setLocation(x + offset[0], y + offset[1]);
            product.getGeoCoding().getGeoPos(pixelPos1, geoPos);
            product.getGeoCoding().getPixelPos(geoPos, pixelPos2);
            double dx = pixelPos2.x - pixelPos1.x;
            double dy = pixelPos2.y - pixelPos1.y;
            if (Math.abs(dx) > maxX) {
              maxX = Math.abs(dx);
              valueX = dx;
            }
            if (Math.abs(dy) > maxY) {
              maxY = Math.abs(dy);
              valueY = dy;
            }
          }
          dataX[y * width + x] = valueX;
          dataY[y * width + x] = valueY;
        }
        if (pm.isCanceled()) {
          return null;
        }
        pm.worked(1);
      }
    } finally {
      pm.done();
    }

    return new Band[] {bandX, bandY, bandAmpl, bandPhase};
  }
  private void readBandRasterDataImplGlobalShifted180(
      int sourceOffsetX,
      int sourceOffsetY,
      int sourceWidth,
      int sourceHeight,
      int sourceStepX,
      int sourceStepY,
      Band destBand,
      int destOffsetX,
      int destOffsetY,
      int destWidth,
      int destHeight,
      ProductData destBuffer,
      ProgressMonitor pm)
      throws IOException {
    final int destSize = destWidth * destHeight;
    pm.beginTask("Reading data...", 3);
    try {

      final Raster dataLeft =
          readRect(
              sourceOffsetX,
              sourceOffsetY,
              sourceStepX,
              sourceStepY,
              destOffsetX,
              destOffsetY,
              destWidth / 2,
              destHeight);
      final Raster dataRight =
          readRect(
              sourceOffsetX,
              sourceOffsetY,
              sourceStepX,
              sourceStepY,
              destOffsetX + destWidth / 2,
              destOffsetY,
              destWidth / 2,
              destHeight);
      pm.worked(1);

      double[] dArrayLeft = new double[destSize / 2];
      double[] dArrayRight = new double[destSize / 2];
      Integer bandIdx = bandMap.get(destBand);
      if (bandIdx == null) {
        bandIdx = 0;
      }
      final DataBuffer dataBufferLeft = dataLeft.getDataBuffer();
      final DataBuffer dataBufferRight = dataRight.getDataBuffer();
      final SampleModel sampleModelLeft = dataLeft.getSampleModel();
      final SampleModel sampleModelRight = dataRight.getSampleModel();
      sampleModelLeft.getSamples(
          0, 0, dataLeft.getWidth(), dataLeft.getHeight(), bandIdx, dArrayLeft, dataBufferLeft);
      sampleModelRight.getSamples(
          0, 0, dataRight.getWidth(), dataRight.getHeight(), bandIdx, dArrayRight, dataBufferRight);
      pm.worked(1);

      int dArrayIndex = 0;
      for (int y = 0; y < destHeight; y++) {
        for (int x = 0; x < destWidth / 2; x++) {
          destBuffer.setElemDoubleAt(dArrayIndex++, dArrayRight[y * destWidth / 2 + x]);
        }
        for (int x = 0; x < destWidth / 2; x++) {
          destBuffer.setElemDoubleAt(dArrayIndex++, dArrayLeft[y * destWidth / 2 + x]);
        }
      }

      pm.worked(1);

    } finally {
      pm.done();
    }
  }
  @Override
  protected void readBandRasterDataImpl(
      int sourceOffsetX,
      int sourceOffsetY,
      int sourceWidth,
      int sourceHeight,
      int sourceStepX,
      int sourceStepY,
      Band destBand,
      int destOffsetX,
      int destOffsetY,
      int destWidth,
      int destHeight,
      ProductData destBuffer,
      ProgressMonitor pm)
      throws IOException {

    if (isGlobalShifted180) {
      // SPECIAL CASE of a global geographic lat/lon with lon from 0..360 instead of -180..180
      readBandRasterDataImplGlobalShifted180(
          sourceOffsetX,
          sourceOffsetY,
          sourceWidth,
          sourceHeight,
          sourceStepX,
          sourceStepY,
          destBand,
          destOffsetX,
          destOffsetY,
          destWidth,
          destHeight,
          destBuffer,
          pm);
    } else {
      // the normal case!!
      final int destSize = destWidth * destHeight;
      pm.beginTask("Reading data...", 3);
      try {
        final Raster data =
            readRect(
                sourceOffsetX,
                sourceOffsetY,
                sourceStepX,
                sourceStepY,
                destOffsetX,
                destOffsetY,
                destWidth,
                destHeight);
        pm.worked(1);

        Integer bandIdx = bandMap.get(destBand);
        if (bandIdx == null) {
          bandIdx = 0;
        }
        final DataBuffer dataBuffer = data.getDataBuffer();
        final SampleModel sampleModel = data.getSampleModel();
        final int dataBufferType = dataBuffer.getDataType();

        boolean isInteger =
            dataBufferType == DataBuffer.TYPE_SHORT
                || dataBufferType == DataBuffer.TYPE_USHORT
                || dataBufferType == DataBuffer.TYPE_INT;
        boolean isIntegerTarget = destBuffer.getElems() instanceof int[];
        if (isInteger && isIntegerTarget) {
          sampleModel.getSamples(
              0,
              0,
              data.getWidth(),
              data.getHeight(),
              bandIdx,
              (int[]) destBuffer.getElems(),
              dataBuffer);
        } else if (dataBufferType == DataBuffer.TYPE_FLOAT
            && destBuffer.getElems() instanceof float[]) {
          sampleModel.getSamples(
              0,
              0,
              data.getWidth(),
              data.getHeight(),
              bandIdx,
              (float[]) destBuffer.getElems(),
              dataBuffer);
        } else {
          final double[] dArray = new double[destSize];
          sampleModel.getSamples(
              0, 0, data.getWidth(), data.getHeight(), bandIdx, dArray, dataBuffer);

          if (destBuffer.getElems() instanceof double[]) {
            //noinspection SuspiciousSystemArraycopy
            System.arraycopy(dArray, 0, destBuffer.getElems(), 0, dArray.length);
          } else {
            int i = 0;
            for (double value : dArray) {
              destBuffer.setElemDoubleAt(i++, value);
            }
          }
        }
        pm.worked(1);
      } finally {
        pm.done();
      }
    }
  }
Example #6
0
  /**
   * Called by the framework in order to compute a tile for the given target band.
   *
   * <p>The default implementation throws a runtime exception with the message "not implemented".
   *
   * @param targetBand The target band.
   * @param targetTile The current tile associated with the target band to be computed.
   * @param pm A progress monitor which should be used to determine computation cancelation
   *     requests.
   * @throws org.esa.snap.framework.gpf.OperatorException If an error occurs during computation of
   *     the target raster.
   */
  public void computeTile(Band targetBand, Tile targetTile, ProgressMonitor pm)
      throws OperatorException {

    final Rectangle targetTileRectangle = targetTile.getRectangle();
    final int x0 = targetTileRectangle.x;
    final int y0 = targetTileRectangle.y;
    final int w = targetTileRectangle.width;
    final int h = targetTileRectangle.height;

    Tile sourceRaster1 = null;
    ProductData srcData1 = null;
    ProductData srcData2 = null;
    Band sourceBand1 = null;

    final String[] srcBandNames = targetBandNameToSourceBandName.get(targetBand.getName());
    if (srcBandNames.length == 1) {
      sourceBand1 = sourceProduct.getBand(srcBandNames[0]);
      sourceRaster1 = calibrationOp.getSourceTile(sourceBand1, targetTileRectangle);
      srcData1 = sourceRaster1.getDataBuffer();
    } else {
      sourceBand1 = sourceProduct.getBand(srcBandNames[0]);
      final Band sourceBand2 = sourceProduct.getBand(srcBandNames[1]);
      sourceRaster1 = calibrationOp.getSourceTile(sourceBand1, targetTileRectangle);
      final Tile sourceRaster2 = calibrationOp.getSourceTile(sourceBand2, targetTileRectangle);
      srcData1 = sourceRaster1.getDataBuffer();
      srcData2 = sourceRaster2.getDataBuffer();
    }

    final Unit.UnitType bandUnit = Unit.getUnitType(sourceBand1);

    // copy band if unit is phase
    if (bandUnit == Unit.UnitType.PHASE) {
      targetTile.setRawSamples(sourceRaster1.getRawSamples());
      return;
    }

    final ProductData trgData = targetTile.getDataBuffer();
    final TileIndex srcIndex = new TileIndex(sourceRaster1);
    final TileIndex tgtIndex = new TileIndex(targetTile);

    final int maxY = y0 + h;
    final int maxX = x0 + w;

    double dn = 0, dn2 = 0, sigma, i, q;
    int srcIdx, tgtIdx;

    for (int y = y0; y < maxY; ++y) {
      srcIndex.calculateStride(y);
      tgtIndex.calculateStride(y);

      for (int x = x0; x < maxX; ++x) {
        srcIdx = srcIndex.getIndex(x);
        tgtIdx = tgtIndex.getIndex(x);

        if (bandUnit == Unit.UnitType.AMPLITUDE) {
          dn = srcData1.getElemDoubleAt(srcIdx);
          dn2 = dn * dn;
        } else if (bandUnit == Unit.UnitType.INTENSITY) {
          dn2 = srcData1.getElemDoubleAt(srcIdx);
        } else if (bandUnit == Unit.UnitType.REAL || bandUnit == Unit.UnitType.IMAGINARY) {
          if (outputImageInComplex) {
            dn = srcData1.getElemDoubleAt(srcIdx);
          } else {
            i = srcData1.getElemDoubleAt(srcIdx);
            q = srcData2.getElemDoubleAt(srcIdx);
            dn2 = i * i + q * q;
          }
        } else {
          throw new OperatorException("ALOS Calibration: unhandled unit");
        }

        if (isComplex && outputImageInComplex) {
          sigma = dn * Math.sqrt(calibrationFactor);
        } else {
          sigma = dn2 * calibrationFactor;
        }

        if (outputImageScaleInDb) { // convert calibration result to dB
          if (sigma < underFlowFloat) {
            sigma = -underFlowFloat;
          } else {
            sigma = 10.0 * Math.log10(sigma);
          }
        }

        trgData.setElemDoubleAt(tgtIdx, sigma);
      }
    }
  }