Reading MTD_MSIL2A.xml and manifest.safe file of Sentinel-2 with python esa_snappy module?

Is it possible to read all bands, metadata, and ancillary data of Sentinel-2 by reading its manifest.safe or MTD_MSIL2A.xml?

Example:

  1. For reading MTD_MSIL2A.xml file
import esa_snappy
from esa_snappy import ProductIO

data = ProductIO.readProduct('D:/S2A_MSIL2A_20240811T103031_N0511_R108_T32UMA_20240811T164252.SAFE/MTD_MSIL2A.xml')

RuntimeError: java.lang.NoClassDefFoundError: Could not initialize class org.gdal.gdalconst.gdalconstConstants
  1. For reading manifest.safe file, its read without any error but as an empty object
import esa_snappy
from esa_snappy import ProductIO

data = ProductIO.readProduct('D:/S2A_MSIL2A_20240811T103031_N0511_R108_T32UMA_20240811T164252.SAFE/manifest.safe')
bands = list(data.getBandNames())
bands

AttributeError: 'NoneType' object has no attribute 'getBandNames'
  1. After converting the product into BEAM-DIMAP format, e.g.,
import os
import esa_snappy
from esa_snappy import ProductIO

product = ProductIO.readProduct("D:/S2A_MSIL2A_20240811T103031_N0511_R108_T32UMA_20240811T164252.SAFE")
output = ProductIO.writeProduct(product, "D:/S2A_MSIL2A_20240811T103031_N0511_R108_T32UMA_20240811T164252.dim", "BEAM-DIMAP")

esa_snappy module can list all data

data = ProductIO.readProduct('D:/S2A_MSIL2A_20240811T103031_N0511_R108_T32UMA_20240811T164252.dim')

bands = list(dataSEN2L2.getBandNames())
bands

[Output:
 'B1',
 'B2',
 'B3',
 'B4',
 'B5',
 'B6',
 'B7',
 'B8',
 'B8A',
 'B9',
 'B11',
 'B12',
 'quality_aot',
 'quality_wvp',
 'quality_cloud_confidence',
 'quality_snow_confidence',
 'quality_scene_classification',
 'B_detector_footprint_B1',
 'B_detector_footprint_B2',
 'B_detector_footprint_B3',
 'B_detector_footprint_B4',
 'B_detector_footprint_B5',
 'B_detector_footprint_B6',
 'B_detector_footprint_B7',
 'B_detector_footprint_B8',
 'B_detector_footprint_B8A',
 'B_detector_footprint_B9',
 'B_detector_footprint_B11',
 'B_detector_footprint_B12',
 'B_ancillary_lost_B1',
 'B_ancillary_degraded_B1',
 'B_msi_lost_B1',
 'B_msi_degraded_B1',
 'B_defective_B1',
 'B_nodata_B1',
 'B_partially_corrected_crosstalk_B1',
 'B_saturated_l1a_B1',
 'B_ancillary_lost_B2',
 'B_ancillary_degraded_B2',
 'B_msi_lost_B2',
 'B_msi_degraded_B2',
 'B_defective_B2',
 'B_nodata_B2',
 'B_partially_corrected_crosstalk_B2',
 'B_saturated_l1a_B2',
 'B_ancillary_lost_B3',
 'B_ancillary_degraded_B3',
 'B_msi_lost_B3',
 'B_msi_degraded_B3',
 'B_defective_B3',
 'B_nodata_B3',
 'B_partially_corrected_crosstalk_B3',
 'B_saturated_l1a_B3',
 'B_ancillary_lost_B4',
 'B_ancillary_degraded_B4',
 'B_msi_lost_B4',
 'B_msi_degraded_B4',
 'B_defective_B4',
 'B_nodata_B4',
 'B_partially_corrected_crosstalk_B4',
 'B_saturated_l1a_B4',
 'B_ancillary_lost_B5',
 'B_ancillary_degraded_B5',
 'B_msi_lost_B5',
 'B_msi_degraded_B5',
 'B_defective_B5',
 'B_nodata_B5',
 'B_partially_corrected_crosstalk_B5',
 'B_saturated_l1a_B5',
 'B_ancillary_lost_B6',
 'B_ancillary_degraded_B6',
 'B_msi_lost_B6',
 'B_msi_degraded_B6',
 'B_defective_B6',
 'B_nodata_B6',
 'B_partially_corrected_crosstalk_B6',
 'B_saturated_l1a_B6',
 'B_ancillary_lost_B7',
 'B_ancillary_degraded_B7',
 'B_msi_lost_B7',
 'B_msi_degraded_B7',
 'B_defective_B7',
 'B_nodata_B7',
 'B_partially_corrected_crosstalk_B7',
 'B_saturated_l1a_B7',
 'B_ancillary_lost_B8',
 'B_ancillary_degraded_B8',
 'B_msi_lost_B8',
 'B_msi_degraded_B8',
 'B_defective_B8',
 'B_nodata_B8',
 'B_partially_corrected_crosstalk_B8',
 'B_saturated_l1a_B8',
 'B_ancillary_lost_B8A',
 'B_ancillary_degraded_B8A',
 'B_msi_lost_B8A',
 'B_msi_degraded_B8A',
 'B_defective_B8A',
 'B_nodata_B8A',
 'B_partially_corrected_crosstalk_B8A',
 'B_saturated_l1a_B8A',
 'B_ancillary_lost_B9',
 'B_ancillary_degraded_B9',
 'B_msi_lost_B9',
 'B_msi_degraded_B9',
 'B_defective_B9',
 'B_nodata_B9',
 'B_partially_corrected_crosstalk_B9',
 'B_saturated_l1a_B9',
 'B_ancillary_lost_B11',
 'B_ancillary_degraded_B11',
 'B_msi_lost_B11',
 'B_msi_degraded_B11',
 'B_defective_B11',
 'B_nodata_B11',
 'B_partially_corrected_crosstalk_B11',
 'B_saturated_l1a_B11',
 'B_ancillary_lost_B12',
 'B_ancillary_degraded_B12',
 'B_msi_lost_B12',
 'B_msi_degraded_B12',
 'B_defective_B12',
 'B_nodata_B12',
 'B_partially_corrected_crosstalk_B12',
 'B_saturated_l1a_B12',
 'B_opaque_clouds',
 'B_cirrus_clouds',
 'B_snow_and_ice_areas',
 'view_zenith_mean',
 'view_azimuth_mean',
 'sun_zenith',
 'sun_azimuth',
 'view_zenith_B1',
 'view_azimuth_B1',
 'view_zenith_B2',
 'view_azimuth_B2',
 'view_zenith_B3',
 'view_azimuth_B3',
 'view_zenith_B4',
 'view_azimuth_B4',
 'view_zenith_B5',
 'view_azimuth_B5',
 'view_zenith_B6',
 'view_azimuth_B6',
 'view_zenith_B7',
 'view_azimuth_B7',
 'view_zenith_B8',
 'view_azimuth_B8',
 'view_zenith_B8A',
 'view_azimuth_B8A',
 'view_zenith_B9',
 'view_azimuth_B9',
 'view_zenith_B10',
 'view_azimuth_B10',
 'view_zenith_B11',
 'view_azimuth_B11',
 'view_zenith_B12',
 'view_azimuth_B12']

Do you have the same error if you try to open the product from SNAP?

Could you also provide us with your OS version and the installed SNAP version ?

I am testing with ESA SNAP desktop (version 11.0.0) on Microsoft Windows 10 Home Version 10.0.19045.

Opening and reading MTD_MSIL2A.xml and listing all bands, including ancillary bands and Tie-Point grids, using ESA SNAP desktop have no problem. And all bands have valid values.

However, some of the ancillary bands are getting empty or None type after converting into BEAM-DIMAP format. Which is consistence for testing with both ESA SNAP desktop and esa_snappy python module. E.g., to read Sun Azimuth band

Using ESA SNAP desktop version 11
ESA_SNAP_desktop_SZA

Using esa_snappy module

data = ProductIO.readProduct('D:/S2A_MSIL2A_20240811T103031_N0511_R108_T32UMA_20240811T164252.dim')
bands = list(data.getBandNames())
bands

***It can list all the bands, though.

SZA = data.getBand('sun_zenith')
w = SZA.getRasterWidth()
h = SZA.getRasterHeight()
SZA_data = np.zeros(w * h, np.float32)
SZA.readPixels(0, 0, w, h, SZA_data)
dataSEN2L2.dispose()
SZA_data.shape = h, w
# Plot
imgplot = plt.imshow(SZA_data)

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Cell In[13], line 5
      3 h = 22 #SZA.getRasterHeight()
      4 SZA_data = np.zeros(w * h, np.float32)
----> 5 SZA.readPixels(0, 0, w, h, SZA_data)
      6 dataSEN2L2.dispose()
      7 SZA_data.shape = h, w

AttributeError: 'NoneType' object has no attribute 'readPixels'

So, in the contrast, reading xml using ESA SNAP desktop is ok but reading with its python module is having some issues and even after converting into .dim format some of the important ancillary bands get empty.

Here are the empty or None type ancillary bands’ list,

  1. sun
['sun_zenith',
 'sun_azimuth']
  1. view
['view_zenith_B1',
 'view_azimuth_B1',
 'view_zenith_B2',
 'view_azimuth_B2',
 'view_zenith_B3',
 'view_azimuth_B3',
 'view_zenith_B4',
 'view_azimuth_B4',
 'view_zenith_B5',
 'view_azimuth_B5',
 'view_zenith_B6',
 'view_azimuth_B6',
 'view_zenith_B7',
 'view_azimuth_B7',
 'view_zenith_B8',
 'view_azimuth_B8',
 'view_zenith_B8A',
 'view_azimuth_B8A',
 'view_zenith_B9',
 'view_azimuth_B9',
 'view_zenith_B10',
 'view_azimuth_B10',
 'view_zenith_B11',
 'view_azimuth_B11',
 'view_zenith_B12',
 'view_azimuth_B12']
  1. snow_and_ice_areas
['B_snow_and_ice_areas']
  1. opaque_clouds
['B_opaque_clouds']
  1. cirrus_clouds
['B_cirrus_clouds']