Generate view angles from metadata Sentinel-2


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

1 Like


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.

1 Like

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?

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?


@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.


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



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.


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.



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,

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'''


    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)

    return op.getTargetProduct()

I’ve read in the previous comments that a tool (or code) to generate view_zenith_mean , view_azimuth_mean , sun_zenith and sun_azimuth from the metadata.xml file was in development.
Is this code ready? Or does anyone have a script to generate these angle files?

Thank you


Dear Rennan,

I’m interested in generation of sum of Solar radiation per pixel at DTMs of Solar System bodies, for example - Moon. Did you have the same tasks or, maybe, heard something about it?

@adomanim unfortunatelly no :pensive:

@adomanim @marujore: Sorry for the late reply. We have created a tool for converting Sentinel-2 L1C products from SAFE to NetCDF/CF where we are adding the view and sun angles as raster layers in the NetCDF file. We are hence traversing the SAFE file and resampling/structuring these layers to fit with the highest spatial resolution in the product. The code is open source and can be found here:

If you search for Read sun and view angles and resample_angles, you find the locations in the code dealing with this. Hoping this was helpful.