Get Sentinel-2 Reflectance values from DN for mosaicking

Hi there, I’m having trouble figuring out the correct way to convert Digital Numbers (DN) to surface reflectance for Sentinel-2 images. I downloaded images from the Copernicus Data Space covering the period from 2018 to 2023, and I’m trying to create a mosaic from them.

Because of the introduction of Processing Baseline 04.00, I’m unsure how to handle the conversion consistently. My current approach is to extract the BOA_QUANTIFICATION_VALUE and BOA_ADD_OFFSET_VALUES_LIST from the metadata. If the offset list isn’t present, I assume the offset is 0.

For each image and band, I apply the following logic:

with rasterio.open(raster_path) as src:
    bands = src.read().astype(float)
    bands = (bands + BOA_ADD_OFFSET_VALUES_LIST) / BOA_QUANTIFICATION_VALUE

The issue is that this sometimes results in negative reflectance values. If I skip the offset, the values typically fall within the expected 0–1 range. However, based on what I’ve read about the baseline changes, I believe the offset should be applied for newer images—meaning I need a way to handle both cases correctly when working with data spanning multiple baselines. Is this right? Thank you!

Have a look at the FAQ number 4.
The “radiometric offset has been introduced in order to preserve/provide negative radiometric values.”

So I basically have to introduce the -1000 offset for images after 2022, right? Why are the reflectance values for images with the BOA_ADD_OFFSET coming out with negative values and without BOA_ADD_OFFSET between 0 and 1?

Because the offset is negative and the smallest DN value is zero. This results in negative reflectance values.

But my question is, should i introduce the offset or not when dealing with images from different years? Is leaving the offset off a bad practice?
Thank you btw!

Dear @eoasker,

What is important is the processing baseline of your product of interest, not necessarly its date of acquisition as the product may have been reprocessed with a newer processing baseline (e.g. Collection-1 products).

Thanks @Marco_EOM for your inputs, the FAQ #4 has been updated with:

Since Processing Baseline (PB) 04.00 (25/01/2022), a radiometric offset has been introduced in order to preserve/provide negative radiometric values.
For these products, please be sure to perform the correct conversion when moving from Digital Number (DN) to Surface Reflectance (SR):
L2A_SR = (L2A_DN + BOA_ADD_OFFSET) / QUANTIFICATION_VALUE

For PB 04.00, 05.00, 05.09, 05.10 & 05.11 the actual values are:
L2A_SR = (L2A_DN - 1000) / 10000

Please refer to the following links (section: Level-2A processing): Processing Baseline - Sentiwiki and Copernicus Dashboard - Processors Releases | ESA

1 Like