diff --git a/pom.xml b/pom.xml index 2cb672d..69d855c 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.airbus.snap snap-novasar-reader - 1.1.1 + 1.2.0 nbm NovaSAR Product Reader @@ -23,48 +23,102 @@ org.esa.snap ceres-core ${snap.version} + + + com.sun + tools + + org.esa.snap ceres-jai ${snap.version} + + + com.sun + tools + + org.esa.snap ceres-glayer ${snap.version} + + + com.sun + tools + + org.esa.snap ceres-binio ${snap.version} + + + com.sun + tools + + org.esa.snap snap-core ${snap.version} + + + com.sun + tools + + org.esa.snap snap-engine-utilities ${snap.version} + + + com.sun + tools + + org.esa.s1tbx s1tbx-commons ${s1tbx.version} + + + com.sun + tools + + org.esa.s1tbx s1tbx-io ${s1tbx.version} + + + com.sun + tools + + junit junit - 4.13.1 + 4.12 + + + com.sun + tools + + diff --git a/src/main/java/com/airbus/snap/dataio/novasar/NovaSARProductDirectory.java b/src/main/java/com/airbus/snap/dataio/novasar/NovaSARProductDirectory.java index b8f529e..6f62c1c 100644 --- a/src/main/java/com/airbus/snap/dataio/novasar/NovaSARProductDirectory.java +++ b/src/main/java/com/airbus/snap/dataio/novasar/NovaSARProductDirectory.java @@ -58,6 +58,7 @@ import java.util.Set; import java.util.StringTokenizer; + //======================================================================================================================================================================================== // Class to represent a NovaSAR Product Directory //======================================================================================================================================================================================== @@ -72,6 +73,7 @@ public class NovaSARProductDirectory extends XMLProductDirectory private static final DateFormat standardDateFormat = ProductData.UTC.createDateFormat("yyyy-MM-dd HH:mm:ss"); + // doesn't seem to amount to anything, I assume it's part of the RS2 loader that's not included for NovaSAR private static final boolean flipToSARGeometry = System.getProperty(SystemUtils.getApplicationContextId() + ".flip.to.sar.geometry", "false").equals("true"); private final transient Map polarizationMap = new HashMap<>(4); @@ -102,7 +104,8 @@ protected void addImageFile(final String imgPath, final MetadataElement newRoot) { boolean valid = false; int dataType = ProductData.TYPE_INT32; - if (name.startsWith("image")) { + // AFAIK, these are the only three names of files which are valid. + if (name.equals("image_HH.tif") || name.equals("image_VV.tif") || name.equals("image_HV.tif") || name.equals("image_VH.tif")) { valid = true; } else if (name.startsWith("rh") || name.startsWith("rv")) { @@ -185,13 +188,19 @@ protected void addBands(final Product product) { String bandName; + String betaBandName; boolean real = true; Band lastRealBand = null; String unit; + final String defStr = AbstractMetadata.NO_METADATA_STRING; final MetadataElement absRoot = AbstractMetadata.getAbstractedMetadata(product); + final MetadataElement origProdRoot = AbstractMetadata.getOriginalProductMetadata(product); + final MetadataElement productElem = origProdRoot.getElement("metadata"); final int width = absRoot.getAttributeInt(AbstractMetadata.num_samples_per_line); final int height = absRoot.getAttributeInt(AbstractMetadata.num_output_lines); + final MetadataElement imageGenerationParameters = productElem.getElement("Image_Generation_Parameters"); + final String radScaling = imageGenerationParameters.getAttributeString("RadiometricScaling"); final Set keys = bandImageFileMap.keySet(); // The set of keys in the map. for (String key : keys) @@ -228,7 +237,8 @@ protected void addBands(final Product product) } else { - ReaderUtils.createVirtualIntensityBand(product, lastRealBand, band, '_' + getPol(imgName)); + betaBandName = radScaling + "_Intensity_"; + ReaderUtils.createVirtualIntensityBand(product, lastRealBand, band, betaBandName, getPol(imgName)); } real = !real; } @@ -244,8 +254,11 @@ protected void addBands(final Product product) product.addBand(band); bandMap.put(band, new ImageIOFile.BandInfo(band, img, i, b)); - - SARReader.createVirtualIntensityBand(product, band, '_' + getPol(imgName)); + betaBandName = radScaling + "_Amplitude_" + getPol(imgName); + SARReader.createVirtualIntensityBand(product, band, getPol(imgName)); + final String snapBandName = "Intensity" + getPol(imgName); + Band snapBand = product.getBand(snapBandName); + snapBand.setName(betaBandName); } } } @@ -476,7 +489,7 @@ protected void addAbstractedMetadataHeader(final MetadataElement root) throws IO // Verify Product Format (e.g. GEOTIFF) final String pf = imageAttributes.getAttributeString("ProductFormat", defStr); - verifyProductFormat(pf); + // verifyProductFormat(pf); // removed as wasn't really useful // Extract Number of Lines in Image AbstractMetadata.setAttribute(absRoot, AbstractMetadata.num_output_lines, imageAttributes.getAttributeInt("NumberOfLinesInImage", defInt)); @@ -756,6 +769,7 @@ protected void addGeoCoding(final Product product) MetadataElement absRoot = AbstractMetadata.getAbstractedMetadata(product); final boolean isAscending = absRoot.getAttributeString(AbstractMetadata.PASS).equals("ASCENDING"); + // final boolean isAscending = false; final boolean isAntennaPointingRight = absRoot.getAttributeString(AbstractMetadata.antenna_pointing).equals("right"); final MetadataElement origProdRoot = AbstractMetadata.getOriginalProductMetadata(product); @@ -795,67 +809,6 @@ protected void addGeoCoding(final Product product) } } - if (flipToSARGeometry) - { - float[] flippedLatList = new float[numberOfTiepoints]; - float[] flippedLonList = new float[numberOfTiepoints]; - int is, id; - if (isAscending) - { - if (isAntennaPointingRight) - { // flip upside down - for (int r = 0; r < gridHeight; r++) - { - is = r * gridWidth; - id = (gridHeight - r - 1) * gridWidth; - for (int c = 0; c < gridWidth; c++) - { - flippedLatList[id + c] = latList[is + c]; - flippedLonList[id + c] = lngList[is + c]; - } - } - } - else - { // flip upside down then left to right - for (int r = 0; r < gridHeight; r++) - { - is = r * gridWidth; - id = (gridHeight - r) * gridWidth; - for (int c = 0; c < gridWidth; c++) - { - flippedLatList[id - c - 1] = latList[is + c]; - flippedLonList[id - c - 1] = lngList[is + c]; - } - } - } - - } - else - { // descending - - if (isAntennaPointingRight) { // flip left to right - for (int r = 0; r < gridHeight; r++) - { - is = r * gridWidth; - id = r * gridWidth + gridWidth; - for (int c = 0; c < gridWidth; c++) - { - flippedLatList[id - c - 1] = latList[is + c]; - flippedLonList[id - c - 1] = lngList[is + c]; - } - } - } - else - { // no flipping is needed - flippedLatList = latList; - flippedLonList = lngList; - } - } - - latList = flippedLatList; - lngList = flippedLonList; - } - double subSamplingX = (double) (product.getSceneRasterWidth() - 1) / (gridWidth - 1); double subSamplingY = (double) (product.getSceneRasterHeight() - 1) / (gridHeight - 1); @@ -901,6 +854,7 @@ private static void setLatLongMetadata(Product product, TiePointGrid latGrid, Ti //======================================================================================================================================================================================== // Function to //======================================================================================================================================================================================== + @Override protected void addTiePointGrids(final Product product) { @@ -970,11 +924,6 @@ protected void addTiePointGrids(final Product product) if (i % subSamplingX == 0) { int index = k++; - - if (!flipToSARGeometry && (isDescending && isAntennaPointingRight || (!isDescending && !isAntennaPointingRight))) {// flip - index = gridWidth - 1 - index; - } - incidenceAngles[index] = (float) (alpha * Constants.RTOD); } @@ -986,6 +935,7 @@ protected void addTiePointGrids(final Product product) } float[] incidenceAngleList = new float[gridWidth * gridHeight]; + for (int j = 0; j < gridHeight; j++) { System.arraycopy(incidenceAngles, 0, incidenceAngleList, j * gridWidth, gridWidth); @@ -1086,11 +1036,7 @@ class coefList // get slant range time in nanoseconds from range distance in meters for (int i = 0; i < rangeDist.length; i++) { - int index = i; - if (!flipToSARGeometry && (isDescending && isAntennaPointingRight || !isDescending && !isAntennaPointingRight)) // flip for descending RS2 - index = rangeDist.length - 1 - i; - - rangeTime[index] = (float) (rangeDist[i] / Constants.halfLightSpeed * Constants.oneBillion); // in ns + rangeTime[i] = (float) (rangeDist[i] / Constants.halfLightSpeed * Constants.oneBillion); // in ns } final TiePointGrid slantRangeGrid = new TiePointGrid(OperatorUtils.TPG_SLANT_RANGE_TIME,gridWidth, gridHeight, 0, 0, subSamplingX, subSamplingY, rangeTime); diff --git a/src/main/java/com/airbus/snap/dataio/novasar/NovaSARProductReader.java b/src/main/java/com/airbus/snap/dataio/novasar/NovaSARProductReader.java index 24ee1ea..fb87a83 100644 --- a/src/main/java/com/airbus/snap/dataio/novasar/NovaSARProductReader.java +++ b/src/main/java/com/airbus/snap/dataio/novasar/NovaSARProductReader.java @@ -57,9 +57,9 @@ public class NovaSARProductReader extends SARReader { private static final String lutgamma = "lutGamma"; private static final String lutbeta = "lutBeta"; - private boolean isAscending; - private boolean isAntennaPointingRight; + private String polarisation; + // Doesn't seem to lead anywhere? Assume only ever returns FALSE private static final boolean flipToSARGeometry = System.getProperty(SystemUtils.getApplicationContextId() + ".flip.to.sar.geometry", "false").equals("true"); @@ -111,15 +111,14 @@ protected Product readProductNodesImpl() throws IOException { final Product product = dataDir.createProduct(); final MetadataElement absMeta = AbstractMetadata.getAbstractedMetadata(product); - isAscending = absMeta.getAttributeString(AbstractMetadata.PASS).equals("ASCENDING"); - isAntennaPointingRight = absMeta.getAttributeString(AbstractMetadata.antenna_pointing).equals("right"); + polarisation = absMeta.getAttributeString(AbstractMetadata.mds1_tx_rx_polar); addCalibrationLUT(product); product.getGcpGroup(); product.setFileLocation(fileFromInput); product.setProductReader(this); setQuicklookBandName(product); - addQuicklook(product, Quicklook.DEFAULT_QUICKLOOK_NAME, getQuicklookFile()); + addQuicklook(product, Quicklook.DEFAULT_QUICKLOOK_NAME, getQuicklookFile(polarisation)); addPauliQuicklooks(product); return product; @@ -133,10 +132,11 @@ private NovaSARProductDirectory createDirectory(final File fileFromInput) { return new NovaSARProductDirectory(fileFromInput); } - private File getQuicklookFile() { + private File getQuicklookFile(final String polarisation) { try { - if(dataDir.exists(dataDir.getRootFolder() + "BrowseImage.tif")) { - return dataDir.getFile(dataDir.getRootFolder() + "BrowseImage.tif"); + final String fname = "QL_image_" + polarisation + ".tif"; + if(dataDir.exists(dataDir.getRootFolder() + fname)) { + return dataDir.getFile(dataDir.getRootFolder() + fname); } } catch (IOException e) { SystemUtils.LOG.severe("Unable to load quicklook " + dataDir.getProductName()); @@ -182,17 +182,14 @@ private static Band[] pauliVirtualBands(final Product product) { * @throws IOException if can't read lut */ private void addCalibrationLUT(final Product product) throws IOException { - - final boolean flipLUT = flipToSARGeometry && ((isAscending && !isAntennaPointingRight) || (!isAscending && isAntennaPointingRight)); final MetadataElement origProdRoot = AbstractMetadata.getOriginalProductMetadata(product); - readCalibrationLUT(lutsigma, origProdRoot, flipLUT); - readCalibrationLUT(lutgamma, origProdRoot, flipLUT); - readCalibrationLUT(lutbeta, origProdRoot, flipLUT); + readCalibrationLUT(lutsigma, origProdRoot); + readCalibrationLUT(lutgamma, origProdRoot); + readCalibrationLUT(lutbeta, origProdRoot); } - private void readCalibrationLUT(final String lutName, final MetadataElement root, - final boolean flipLUT) throws IOException { + private void readCalibrationLUT(final String lutName, final MetadataElement root) throws IOException { InputStream is; if(dataDir.exists(dataDir.getRootFolder() + lutName + ".xml")) { is = dataDir.getInputStream(dataDir.getRootFolder() + lutsigma + ".xml"); @@ -211,14 +208,6 @@ private void readCalibrationLUT(final String lutName, final MetadataElement root final Element gainsElem = rootElement.getChild("gains"); final String gainsValue = gainsElem.getValue().trim().replace(" ", " "); final double[] gainsArray = toDoubleArray(gainsValue, " "); - if (flipLUT) { - double tmp; - for (int i = 0; i < gainsArray.length / 2; i++) { - tmp = gainsArray[i]; - gainsArray[i] = gainsArray[gainsArray.length - i - 1]; - gainsArray[gainsArray.length - i - 1] = tmp; - } - } final MetadataElement lut = new MetadataElement(lutName); root.addElement(lut); @@ -258,154 +247,61 @@ protected void readBandRasterDataImpl(int sourceOffsetX, int sourceOffsetY, int final ImageIOFile.BandInfo bandInfo = dataDir.getBandInfo(destBand); if (bandInfo != null && bandInfo.img != null) { - if (isAscending) { - readAscendingRasterBand(sourceOffsetX, sourceOffsetY, sourceStepX, sourceStepY, - destBuffer, destOffsetX, destOffsetY, destWidth, destHeight, - 0, bandInfo.img, bandInfo.bandSampleOffset, isAntennaPointingRight); - } else { - readDescendingRasterBand(sourceOffsetX, sourceOffsetY, sourceStepX, sourceStepY, - destBuffer, destOffsetX, destOffsetY, destWidth, destHeight, - 0, bandInfo.img, bandInfo.bandSampleOffset, isAntennaPointingRight); - } + readRasterBand(sourceOffsetX, sourceOffsetY, sourceStepX, sourceStepY, + destBuffer, destOffsetX, destOffsetY, destWidth, destHeight, + 0, bandInfo.img, bandInfo.bandSampleOffset); } } - private void readAscendingRasterBand(final int sourceOffsetX, final int sourceOffsetY, - final int sourceStepX, final int sourceStepY, - final ProductData destBuffer, - final int destOffsetX, final int destOffsetY, - final int destWidth, final int destHeight, - final int imageID, final ImageIOFile img, - final int bandSampleOffset, - final boolean isAntennaPointingRight) throws IOException { + private void readRasterBand(final int sourceOffsetX, final int sourceOffsetY, + final int sourceStepX, final int sourceStepY, + final ProductData destBuffer, + final int destOffsetX, final int destOffsetY, + final int destWidth, final int destHeight, + final int imageID, final ImageIOFile img, + final int bandSampleOffset) throws IOException { + /* + This function takes a strip of data and reads it into the result. + image.getdata reads from the source data (TIFF in our case) to give the input strip. + destbuffer.setElem writes that strip to the output (destination buffer) + */ final Raster data; - synchronized (dataDir) { - final ImageReader reader = img.getReader(); - final ImageReadParam param = reader.getDefaultReadParam(); - param.setSourceSubsampling(sourceStepX, sourceStepY, - sourceOffsetX % sourceStepX, - sourceOffsetY % sourceStepY); - - final RenderedImage image = reader.readAsRenderedImage(0, param); - if (flipToSARGeometry) { - if (isAntennaPointingRight) { // flip the image up side down - data = image.getData(new Rectangle(destOffsetX, - Math.max(0, img.getSceneHeight() - destOffsetY - destHeight), - destWidth, destHeight)); - } else { // flip the image upside down, then flip it left to right - data = image.getData(new Rectangle(Math.max(0, img.getSceneWidth() - destOffsetX - destWidth), - Math.max(0, img.getSceneHeight() - destOffsetY - destHeight), - destWidth, destHeight)); - } - } else { - data = image.getData(new Rectangle(destOffsetX, destOffsetY, destWidth, destHeight)); - } - } - - final int w = data.getWidth(); - final int h = data.getHeight(); - final DataBuffer dataBuffer = data.getDataBuffer(); - final SampleModel sampleModel = data.getSampleModel(); - final int sampleOffset = imageID + bandSampleOffset; - - if (flipToSARGeometry) { - final int[] dArray = new int[dataBuffer.getSize()]; - sampleModel.getSamples(0, 0, w, h, imageID + bandSampleOffset, dArray, dataBuffer); - - int srcStride, destStride; - if (isAntennaPointingRight) { // flip the image upside down - for (int r = 0; r < h; r++) { - srcStride = r * w; - destStride = (h - r - 1) * w; - for (int c = 0; c < w; c++) { - destBuffer.setElemIntAt(destStride + c, dArray[srcStride + c]); - } - } - } else { // flip the image upside down, then flip it left to right - for (int r = 0; r < h; r++) { - srcStride = r * w; - destStride = (h - r) * w; - for (int c = 0; c < w; c++) { - destBuffer.setElemIntAt(destStride - c - 1, dArray[srcStride + c]); - } - } - } - } else { // no flipping is needed - sampleModel.getSamples(0, 0, w, h, sampleOffset, (int[]) destBuffer.getElems(), dataBuffer); - } - } - - private void readDescendingRasterBand(final int sourceOffsetX, final int sourceOffsetY, - final int sourceStepX, final int sourceStepY, - final ProductData destBuffer, - final int destOffsetX, final int destOffsetY, - final int destWidth, final int destHeight, - final int imageID, final ImageIOFile img, - final int bandSampleOffset, - final boolean isAntennaPointingRight) throws IOException { - - final Raster data; - try { - synchronized (dataDir) { - final ImageReader reader = img.getReader(); - final ImageReadParam param = reader.getDefaultReadParam(); - param.setSourceSubsampling(sourceStepX, sourceStepY, - sourceOffsetX % sourceStepX, - sourceOffsetY % sourceStepY); - - final RenderedImage image = reader.readAsRenderedImage(0, param); - if (flipToSARGeometry && isAntennaPointingRight) { // flip the image left to right - data = image.getData(new Rectangle(Math.max(0, img.getSceneWidth() - destOffsetX - destWidth), - destOffsetY, destWidth, destHeight)); - } else { - data = image.getData(new Rectangle(destOffsetX, destOffsetY, destWidth, destHeight)); - } - } - - final int w = data.getWidth(); - final int h = data.getHeight(); - final DataBuffer dataBuffer = data.getDataBuffer(); - final SampleModel sampleModel = data.getSampleModel(); - final int sampleOffset = imageID + bandSampleOffset; - - if(destBuffer.getType() == ProductData.TYPE_FLOAT32) { - if (flipToSARGeometry && isAntennaPointingRight) { // flip the image left to right - final float[] dArray = new float[dataBuffer.getSize()]; - sampleModel.getSamples(0, 0, w, h, sampleOffset, dArray, dataBuffer); - - int srcStride, destStride; - for (int r = 0; r < h; r++) { - srcStride = r * w; - destStride = r * w + w; - for (int c = 0; c < w; c++) { - destBuffer.setElemFloatAt(destStride - c - 1, dArray[srcStride + c]); - } - } - } else { // no flipping is needed - sampleModel.getSamples(0, 0, w, h, sampleOffset, (float[]) destBuffer.getElems(), dataBuffer); - } - } else { - if (flipToSARGeometry && isAntennaPointingRight) { // flip the image left to right - final int[] dArray = new int[dataBuffer.getSize()]; - sampleModel.getSamples(0, 0, w, h, sampleOffset, dArray, dataBuffer); - - int srcStride, destStride; - for (int r = 0; r < h; r++) { - srcStride = r * w; - destStride = r * w + w; - for (int c = 0; c < w; c++) { - destBuffer.setElemIntAt(destStride - c - 1, dArray[srcStride + c]); - } - } - } else { // no flipping is needed - sampleModel.getSamples(0, 0, w, h, sampleOffset, (int[]) destBuffer.getElems(), dataBuffer); - } - } - } catch (Exception e) { + try { + // synchronized block, only one thread can read from the source data at a time (why?) + // gets used a lot, subsamples when zoomed out. + synchronized (dataDir) { + final ImageReader reader = img.getReader(); + final ImageReadParam param = reader.getDefaultReadParam(); + param.setSourceSubsampling(sourceStepX, sourceStepY, + sourceOffsetX % sourceStepX, + sourceOffsetY % sourceStepY); + + final RenderedImage image = reader.readAsRenderedImage(0, param); + + data = image.getData(new Rectangle(destOffsetX, + destOffsetY, + destWidth, destHeight)); + } + + final int width = data.getWidth(); + final int height = data.getHeight(); + final DataBuffer dataBuffer = data.getDataBuffer(); + final SampleModel sampleModel = data.getSampleModel(); + final int sampleOffset = imageID + bandSampleOffset; + + if(destBuffer.getType() == ProductData.TYPE_FLOAT32) { + sampleModel.getSamples(0, 0, width, height, sampleOffset, (float[]) destBuffer.getElems(), dataBuffer); + } else { + sampleModel.getSamples(0, 0, width, height, sampleOffset, (int[]) destBuffer.getElems(), dataBuffer); + } + + + } catch (Exception e) { e.printStackTrace(); - } + // throw e; + } } -} +} // End of class definition