Generate view angles from metadata Sentinel-2

Hi,

I am trying to generate the view zenith and azimuth angles from the Sentinel-2 product. The data is stored as lists in the tile specific metadata file “product/S2A_MSIL1C…/GRANULE/MTD_TL.xml” as follows

When I try to make the “view angle” bands from the metadata, I iterate wrt. “detectorId” for all elements with same “bandId” and take the mean value for the arrays. My results are not entirely correct compared with the ESA Toolbox output, so I have a couple of questions:

  1. When I compare my result with what I get from using the ESA SNAP Toolbox, some (less than 5% in my case) of the “azimuth_angles” have different values. Have I misinterpreted how the data is stored in the metadata?

  2. And also, the list in “MTD_TL.xml” are 23x23, but the result in ESA SNAP Toolbox are 22x22. I don’t find the last column and row ESA Toolbox output.

Thank you in advance

Hi,

there are some comments about the angles in the SNAP help:

Firstly, they are read the pixels for every band. In the overlapped pixels, they are chosen the angles from the higher detector. Finally, the bands “view_zenith_mean” and “view_azimuth_mean” are computed as the mean of all the band angles.

About the last column and row, I think that the reader crops the image to eliminate the angles that are outside the scene.

Thank you for your answer and quick response, @obarrilero! It is much appreciated.

Regarding the last column and row: Are they systematically cropped, or does it vary which angles (i.e. row and column) that are outside the scene?

Hello,
I am also very interested in retrieving the proper angles values for each pixel; it is even a critical need for my applications.
For the moment, I apply the resampling function of snap (or snappy) to get angles information over the image. But the angle values are not that accurate due to the detector switch as you mentioned. See Sentinel 2 viewing angles interpolation (on per-pixel basis)
I know there is a specific code to compute angles from the new collection of Landsat. Is there any plans to do the same for Sentinel-2?
Thanks,
Tristan

Hi,

@evgyrt, it is checked which pixels are outside the image, but as far as I know, they are always the last column and row

@harmel, yes, an operator to calculate the angles in every pixel is planned, it should be available in the coming months.

Hello,

Regarding the last Tristan (harrmel)'s post above, is the code ready by any chance?
I would like to generate the files : view_zenith_mean , view_azimuth_mean , sun_zenith and sun_azimuth from the metadata.xml file

Thank you

Chloe

Hi,

I am sorry Chloe , but it is not ready yet.
Currently, the angle bands are already generated from the metadata, but at 5000m resolution. If you need them at a better resolution you could use the resampling operator in SNAP, but it is not going to be accurate in the detector’s border in the view_azimuth_mean.

Regards,
Omar.

Hi Omar,

Thank you for your answer. Actually I am just looking how to create a view_azimuth_mean.tif file from the metadata.xml file with Python.

Cheers

Chloe

Hello Chloe,
You can find a nice code to compute the S2 angles for each band at any desired resolution here:


Hope it can help,
Tristan

after https://forum.step.esa.int/t/c2rcc-problem-for-s2-msi/8279/10?u=harmel
a small piece of code for generating S2’msi angles with snappy:

def s2_resampler(product, resolution=20, upmethod=‘Bilinear’, downmethod=‘Mean’,
flag=‘FlagMedianAnd’, opt=False):

    '''Resampling operator dedicated to Sentinel2-msi characteristics (e.g., viewing angles)
    :param product: S2-msi product as provided by esasnappy ProductIO.readProduct()
    :param resolution: target resolution in meters (10, 20, 60)
    :param upmethod: interpolation method ('Nearest', 'Bilinear', 'Bicubic')
    :param downmethod: aggregation method ('First', 'Min', 'Max', 'Mean', 'Median')
    :param flag: method for flags aggregation ('First', 'FlagAnd', 'FlagOr', 'FlagMedianAnd', 'FlagMedianOr')
    :param opt: resample on pyramid levels (True/False)
    :return: interpolated target product'''

    res=str(resolution)

    resampler = jpy.get_type('org.esa.s2tbx.s2msi.resampler.S2ResamplingOp')

    op = resampler()
    op.setParameter('targetResolution', res)
    op.setParameter('upsampling', upmethod)
    op.setParameter('downsampling', downmethod)
    op.setParameter('flagDownsampling', flag)
    op.setParameter('resampleOnPyramidLevels', opt)
    op.setSourceProduct(product)

    return op.getTargetProduct()
2 Likes