Introduction to EOReader
le 4 novembre 2022
As one of the Copernicus Emergency Management Service Rapid Mapping and Risk and Recovery Mapping operators, SERTIT needs to deliver geoinformation (such as flood or fire delineation, landslides mapping, etc.) based on multiple EO constellations.
In rapid mapping, it is always important to have access to various sensor types, resolutions, and satellites. Indeed, SAR sensors are able to detect through clouds and during nighttime (which is particularly useful during flood and storm events), while optical sensors benefit from of multi spectral bands to better analyze and classify the crisis information.
As every minute counts in the production of geoinformation in an emergency mode, it seemed crucial to harmonize the ground on which are built our production tools, in order to make them as sensor-agnostic as possible.
This is why SERTIT decided to decouple the sensor handling from the extraction algorithms: the latter should be able to ingest semantic bands (i.e. RED or VV) without worrying about how to load the specific sensor band or in what unit it is. The assumption was made that all the spectral bands from optical sensors could be mapped between each other (see Figure 2), in addition to the natural mapping between SAR bands.
This brings a lot of benefits:
✅ the algorithm (and its developer) can focus on its core tasks (such as extraction) without taking into account the sensor characteristics (how to load a band, which band correspond to which band number, …)
✅ new sensor addition is effortless and requires no algorithm modification
✅ maintenance is simplified and the code quality is significantly improved
✅ testing is also simplified as the sensor-related parts are tested in EOReader library
What is EOReader?
EOReader is a remote-sensing open source Python library. It has been designed according to the previous principles. EOReader handles both optical and SAR sensors, loads and stacks spectral and radar bands, cloud bands, Digital Elevation Model (DEM), and spectral indices in a sensor-agnostic way. We already mentionned it in this blogpost.
Of course, this library follows also software engineering best practices such as code documentation, code reviews, python coding standards and unit testing.
EOReader has been presented in an ESA Success Story and had a talk in GeoPython 2022. EOReader has also been mentioned in [Live+]SIG 2022 by ESRI France (in French) and in the following technical note: Maxant, J.; Braun, R.; Caspard, M.; Clandillon, S. ExtractEO, a Pipeline for Disaster Extent Mapping in the Context of Emergency Management. Remote Sens. 2022, 14, 5253.
Last but not least, EOReader has been granted over 130 stars on Github (Figure 3), which means it is now an endorsed part of the remote-sensing opensource community.
EOReader has been designed to:
✅ simplify and harmonize the use of satellite data
➡️load data sensor-agnostically
➡️wide range of supported sensors
➡️make algorithms easy to update with new sensors
➡️automatic preprocessing and spectral index computation
✅ increase the reliability of the production tools
✅ be opensource and comunity friendly
Currently, a large set of constellations is supported:
|Sentinel-2 and Sentinel-2 Theia|
Sentinel-3 OLCI and SLSTR
Landsat 1 to 9
PlanetScope, SkySat and RapidEye
Pleiades and Pleiades-Neo
Maxar (WorldViews, GeoEye)
COSMO-Skymed 1st and 2nd Generation
TerraSAR-X, TanDEM-X and PAZ SAR
RADARSAT-2 and RADARSAT-Constellation
Let’s illustrate this with an example.
We will load a NIR band in reflectance from different products: an archived Landsat-9, a Pléiades and an archived Sentinel-2.
?Note this example is from a more complete notebook you can find here, comparing EOReader and rasterio on these satellite products.
import os from eoreader.reader import Reader from eoreader.bands import NIR from matplotlib import pyplot as plt
Link the paths of the three different products:
# Base folder prod_folder = os.path.join("/home", "data", "eoreader", "optical") # Landsat-9 OLI-TIRS collection 2 (archived in a tar file) l9_path = os.path.join(prod_folder, "LC09_L1TP_200030_20220201_20220201_02_T1.tar") # Pléiades, as a folder (extracted data) pld_path = os.path.join(prod_folder, "IMG_PHR1A_PMS_001") # Sentinel-2 L2A (archived in a zip file) s2_path = os.path.join(prod_folder, "S2A_MSIL1C_20200824T110631_N0209_R137_T30TTK_20200824T150432.SAFE.zip") # Group all these paths paths = [l9_path, pld_path, s2_path]
With EOReader, you can easily access archived and extracted data, without paying attention at where everything is stored.
By default, your band nodata is set and the data converted to reflectance.
Everything is done with xarray, so you can easily access the plot function.
And last but not least, you just can loop over the paths, like if they were of the same kind!
reader = Reader() for path in paths: # Open the product prod = reader.open(path) # Load NIR nir = prod.load(NIR)[NIR] # Plot nir[:, ::5, ::5].plot(cmap="Reds") plt.show()