Sentinel-2 L2A negative band reflectance values

Hello,

We are working on S2 L2A images collected via eo-learn SentinelHubInputTask function. This function is described in the documentation as following : “Process API input task that loads 16bit integer data and converts it to a 32bit float feature”. As we are not passing any evalscript argument that may be overriding the default generated one, according to this article the DN to reflectance conversion should be correctly done.

However, we are observing distributions of band reflectance values that are significantly below 0 (down to -.5 in some cases). This doesn’t seem to be an isolated problem as this happens consistently on all images of a time-series. However this doesn’t affect all the bands equally.

Here is the frequency histogram of reflectances values coming from all the pixels of a time-series. We are observing agricultural lands, on a 2km x 2km area. Band number is expressed as band index of eo-patch ([‘B01’, ‘B02’, ‘B03’, ‘B04’, ‘B05’, ‘B06’, ‘B07’, ‘B08’,‘B8A’, ‘B09’, ‘B11’, ‘B12’]).

image
image
image
image
image
image
image
image
image
image
image
image

How could we explain these negative reflectance values ? Are we missing something obvious here ?
Thanks in advance,
Best,
J.

Hi @jlavarenne,

this is indeed a bit strange. I quickly checked histograms for the image in our documentation and did not get any negative values.

Could you please share a code snippet so that we can reproduce your results.

Hello @avrecko ,
Sure thing, here is the code we use:

band_names = ['B01', 'B02', 'B03', 'B04', 'B05', 'B06', 'B07', 'B08','B8A', 'B09', 'B11', 'B12']
# TASK DEFINITION
# définition de la tâche de téléchargement de la scène 
download_task = SentinelHubInputTask(data_collection=DataCollection.SENTINEL2_L2A, 
                                     bands_feature=(FeatureType.DATA, 'BANDS'),
                                     resolution=10, 
                                     maxcc=1, 
                                     bands=band_names, 
                                     time_difference=datetime.timedelta(hours=2),
                                     additional_data=[(FeatureType.MASK, 'dataMask'), #data mask
                                        (FeatureType.MASK, 'SCL'), #sen2cor scene classification
                                        (FeatureType.MASK, 'CLD'), #sen2cor cloud probability 
                                        (FeatureType.MASK, 'CLM'), #cloud mask
                                        (FeatureType.DATA, 'CLP'), #cloud probability S2cloudless
                                        (FeatureType.DATA, 'sunAzimuthAngles'), #satellite view geometry
                                        (FeatureType.DATA, 'sunZenithAngles'),
                                        (FeatureType.DATA, 'viewAzimuthMean'),
                                        (FeatureType.DATA, 'viewZenithMean')]
                                    )

filter_clouds = SimpleFilterTask((FeatureType.MASK, 'CLM'), MaxCCPredicate(maxcc=0.05))
add_valmask = AddValidDataMaskTask(predicate=ValidDataPredicate(), valid_data_feature='VALID_DATA')
save = SaveTask(patch_dir, overwrite_permission=2, compress_level=1)

timelapse = LinearWorkflow(download_task, filter_clouds, add_valmask, save)
result = timelapse.execute({
    download_task: {
        'bbox': bbox,
        'time_interval': time_interval
    },
    save : {'eopatch_folder': patch_name}
})
eopatch_clean = [result[key] for key in result.keys()][0]

Now that you mention it, we subsequently perform a coregistration step using eolearn.coregistration.coregistration.ECCRegistration, followed by a gapfilling step performed by eolearn.features.interpolation.LinearInterpolation on the pixels flagged by high cloud cover. We’ll be investigating at what step the problem seem to occur and will get back to you.

Your snippet looks ok, I still could not reproduce your issue with negative values. It would be interesting to know if you figured out what the problem was.
It must either be something related to how you further process the data or something related to your aoi.

Hello @jlavarenne,

I have exactly the same issue and stumbled across this thread. Since it has been some time I am wondering if you ever found an answer to why the values fall in that range?
Thanks in advance,

Max