Geometric Correction of ERS and Envisat data

Hi, we’re trying to use the snappy API to do geometric corrections on ERS and Envisat images. For Sentinel-1 the sequence of methods we’re using is:

  1. Subset
  2. Apply-Orbit-File
  3. Calibration
  4. Terrain-Flattening
  5. Ellipsoid-Correction-GG
  6. Update-Geo-Reference

And we’d like to be as consistent as we can with this for ERS and Envisat - however, it seems that some of these steps either don’t work or produce slightly different results when we apply it to ERS and Envisat data - Terrain-Flattening doesn’t seem to work, so we have tried using Terrain-Correction instead, but this seems to produce an error when trying to perform Ellipsoid-Correction-GG.

Our region of interest is within the area covered by the SRTM DEM, so I don’t think that’s part of the problem.

Does anyone have some experience doing this with ERS and Envisat? It would be nice to know what the suggested method is for doing geometric corrections for these satellites.

could you please clarify this?
Range Doppler Terrain Correction is not a substitute of Terrain Flattening. TC applies geometric correction while TF is a radiometric adjustment of SAR backscatter based on a DEM.
I have worked with both ENVISAT and ERS and could successfully apply both TF and TC afterwards.
Make sure to output Beta0 in the Calibration step because this is the required format for the later terrain flattening.
Applying Ellipsoid correction with subsequend GeoReferencing seems not practical to me.

Hi Andreas,

Thanks very much for your quick response. I’m sorry my post wasn’t very clear. It’s helpful already to know that TC isn’t a substitute for TF - evidently I don’t quite know what I’m doing, I really appreciate your help.

I’ve been trying to follow your advice but I seem to have a rather odd problem. When I try to perform Terrain-Flattening, I get this following error:

SEVERE: org.esa.snap.core.util.SystemUtils$SnapImagingListener: JAI error occurred: 'Problem occurs when computing a tile by the owner.' at com.sun.media.jai.util.SunTileScheduler@29147c12
org.esa.snap.core.gpf.OperatorException: TerrainFlattening requires beta0 or T3, C3, C2 as input
    at org.esa.snap.engine_utilities.gpf.OperatorUtils.catchOperatorException(OperatorUtils.java:415)
    at org.esa.s1tbx.sar.gpf.geometric.TerrainFlatteningOp.computeTileStack(TerrainFlatteningOp.java:511)
    at org.esa.snap.core.gpf.internal.OperatorImageTileStack.computeRect(OperatorImageTileStack.java:116)
    at org.esa.snap.core.gpf.internal.OperatorImageTileStack.computeTile(OperatorImageTileStack.java:85)
    at com.sun.media.jai.util.SunTileScheduler.scheduleTile(SunTileScheduler.java:904)
    at javax.media.jai.OpImage.getTile(OpImage.java:1129)
    at javax.media.jai.PlanarImage.getData(PlanarImage.java:2085)
    at com.bc.ceres.glevel.MultiLevelImage.getData(MultiLevelImage.java:64)
    at org.esa.snap.core.datamodel.Band.writeRasterDataFully(Band.java:384)
    at org.esa.snap.core.dataio.ProductIO.writeAllBands(ProductIO.java:448)
    at org.esa.snap.core.dataio.ProductIO.writeProduct(ProductIO.java:401)
    at org.esa.snap.core.dataio.ProductIO.writeProduct(ProductIO.java:306)
Caused by: org.esa.snap.core.gpf.OperatorException: TerrainFlattening requires beta0 or T3, C3, C2 as input
    at org.esa.s1tbx.sar.gpf.geometric.TerrainFlatteningOp.computeTileStack(TerrainFlatteningOp.java:474)
    ... 10 more

…which is clearly saying that the Beta0 band is missing - indeed, when I check the list of bands in the product, I only have Sigma0_VV. But I’m very confused by this because the parameters I am passing to the Calibration procedure are instructing snappy specifically to product Beta0 and not Sigma0. Here’s the code I’m using for this:

parameters = HashMap()
parameters.put("outputSigmaBand", False)
parameters.put("outputBetaBand", True)
print(parameters) # prints: "{outputSigmaBand=false, outputBetaBand=true}"

cal_path = os.path.join(tmp_dir, "calibration")
calib_param = snappy.GPF.createProduct(
    "Calibration", parameters, ProductIO.readProduct(orbit_path + ".dim")
)
ProductIO.writeProduct(calib_param, cal_path, "BEAM-DIMAP")

cal_product = ProductIO.readProduct(cal_path+'.dim')
print(list(cal_product.getBandNames())) # prints: "['Sigma0_VV']"

I have re-checked this a few times and I can’t understand why this code is producing a product with only Sigma0 data. I’m sure there must be something simple that I’m missing. Do you have any idea what I might be doing wrong here?

Separately, could I please ask you to elaborate a little on your point about GeoReferencing being impractical? I added the GeoReferencing step because I wanted to produce GeoTIFF output to be ingested by some other code for onward analysis, and it seemed that GeoReferencing was the best way to ensure that the Affine matrix in the GeoTIFF file was accurate - if there’s a better way to do this, please let me know.

Since my last post I’ve checked a couple of things and made a little progress. It seems that I need to add

parameters.put("createBetaBand", True)

in order to have Beta0 in the output file. I guess I didn’t catch this before because it doesn’t seem to be required in order to produce Beta0 from Sentinel-1 data. Slightly strangely, I still have a Sigma0_VV band in the product despite setting outputSigmaBand to False, but this isn’t really a problem.

Hopefully this solves the problem with applying the Terrain Correction; I’m currently re-running my code to check this. Thanks again for your help :grinning:

EDIT:

This has indeed solved the main issue, I can now use the same procedure as we’ve been using for the Sentinel-1 data. Thanks again for your help and your patience.

If you have the chance to further explain your comment about GeoReferencing, I’d really appreciate it - clearly I don’t properly understand something here.

good job in debugging the code - especially as I haven’t used snappy very often so far so I’m glad that you managed to include the Beta0 product. In the SNAP GUI, Beta0 is only added as a virtual band (when checked in the calibration step), so maybe that is part of the reasons why it didn’t work in the first run.

On the georeferencing. To be honest, I have never used “Update Georeferencing” and wasn’t even aware that this operator exists (obviously quite a long time :innocent:).
All I can say is that the standard way of geocoding a SAR image on land areas is the Range Doppler Terrain Correction. It combines several steps: It uses a DEM to correct for geometric distortions caused by topographic variations (I suggest to use the SRTM 1Sec AutoDownload), it adds a selected coordinate reference system of your choice and resamples the raster to the square pixels at the smallest pixel size possible.

The EllipsoidCorrection is only used if the area you are working on is completely flat (I would never assume this), or no DEM data is avaiilable, for example over ocean areas. So you can basically replace steps 5 and 6 of your initial posts by RD Terrain Correction - this is why I considered it impractical.

But again, I cannot really tell what the Update Geo Referencing operator is actually good for - it is also very rarely discussed in here. Maybe it is a relic from earlier versions or especially suitable for specific sensors. Maybe @jun_lu can clarify here.

Let us know if you come closer to your goal of if you are experiencing any new issues. Sometimes it is even worth to compare the Sigma0 (after calibration) with the Gamma0 (after terrain flattening) because in some cases it introduced new patterns because of bad DEM quality (here, for example).

If your goal is just correct the geocoding of the ERS or Envisat image, you can do the following:

  1. Subset
  2. Apply Orbit File
  3. Update Geo Reference
    By doing this, you will get a subset image with a better pixel geocoding.
1 Like

can you tell the difference between Range Doppler Terrain Correction and Update Geo Reference?

Range Doppler Terrain Correction produces an image in map domain while the output of Update Geo Reference is your original image in SAR image domain with the geocoding being corrected (i.e. the lat/lon coordinate for each pixel is more “accurate”).

1 Like

oh, that is useful actually :smiley: I have never known of this…