Module eoreader.products.optical.l7_product
Landsat-7 products
Expand source code
# -*- coding: utf-8 -*-
# Copyright 2021, SERTIT-ICube - France, https://sertit.unistra.fr/
# This file is part of eoreader project
# https://github.com/sertit/eoreader
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
""" Landsat-7 products """
import logging
import geopandas as gpd
from eoreader.products.optical.landsat_product import LandsatProduct
from eoreader.utils import EOREADER_NAME
from sertit import rasters
LOGGER = logging.getLogger(EOREADER_NAME)
class L7Product(LandsatProduct):
"""Class of Landsat-7 Products"""
def _set_resolution(self) -> float:
"""
Set product default resolution (in meters)
"""
# DO NOT TAKE INTO ACCOUNT PAN AND TIRS RES
return 30.0
def _set_product_type(self) -> None:
"""Get products type"""
self._set_etm_product_type()
def footprint(self) -> gpd.GeoDataFrame:
"""
Get real footprint of the products (without nodata, in french == emprise utile)
.. WARNING::
As Landsat 7 is broken (with nodata stripes all over the bands),
the footprint is not easily computed and may take some time to be delivered.
```python
>>> from eoreader.reader import Reader
>>> path = r"LC08_L1GT_023030_20200518_20200527_01_T2"
>>> prod = Reader().open(path)
>>> prod.footprint()
index geometry
0 0 POLYGON ((366165.000 4899735.000, 366165.000 4...
```
Overload of the generic function because landsat nodata seems to be different in QA than in regular bands.
Indeed, nodata pixels vary according to the band sensor footprint,
whereas QA nodata is where at least one band has nodata.
We chose to keep QA nodata values for the footprint in order to show where all bands are valid.
**TL;DR: We use the QA nodata value to determine the product's footprint**.
Returns:
gpd.GeoDataFrame: Footprint as a GeoDataFrame
"""
LOGGER.warning(
"Due to the Landsat-7 gaps, this function returns a rounded footprint on the corners. "
"Sorry for the inconvenience."
)
# Read the file with a very low resolution -> use raster_rio that is faster !
gap_msk = rasters.read(
self._get_path(self._nodata_band_id),
resolution=self.resolution * 50,
masked=False,
)
# Vectorize the nodata band
# Take the convex hull to discard the stripes of L7 to simplify the geometries
footprint = rasters.vectorize(
gap_msk, values=1, keep_values=False, dissolve=True
)
# Needs a dataframe to be dissolved
footprint = footprint.convex_hull
return gpd.GeoDataFrame(geometry=footprint.geometry, crs=footprint.crs)
Classes
class L7Product (product_path, archive_path=None, output_path=None)
-
Class of Landsat-7 Products
Expand source code
class L7Product(LandsatProduct): """Class of Landsat-7 Products""" def _set_resolution(self) -> float: """ Set product default resolution (in meters) """ # DO NOT TAKE INTO ACCOUNT PAN AND TIRS RES return 30.0 def _set_product_type(self) -> None: """Get products type""" self._set_etm_product_type() def footprint(self) -> gpd.GeoDataFrame: """ Get real footprint of the products (without nodata, in french == emprise utile) .. WARNING:: As Landsat 7 is broken (with nodata stripes all over the bands), the footprint is not easily computed and may take some time to be delivered. ```python >>> from eoreader.reader import Reader >>> path = r"LC08_L1GT_023030_20200518_20200527_01_T2" >>> prod = Reader().open(path) >>> prod.footprint() index geometry 0 0 POLYGON ((366165.000 4899735.000, 366165.000 4... ``` Overload of the generic function because landsat nodata seems to be different in QA than in regular bands. Indeed, nodata pixels vary according to the band sensor footprint, whereas QA nodata is where at least one band has nodata. We chose to keep QA nodata values for the footprint in order to show where all bands are valid. **TL;DR: We use the QA nodata value to determine the product's footprint**. Returns: gpd.GeoDataFrame: Footprint as a GeoDataFrame """ LOGGER.warning( "Due to the Landsat-7 gaps, this function returns a rounded footprint on the corners. " "Sorry for the inconvenience." ) # Read the file with a very low resolution -> use raster_rio that is faster ! gap_msk = rasters.read( self._get_path(self._nodata_band_id), resolution=self.resolution * 50, masked=False, ) # Vectorize the nodata band # Take the convex hull to discard the stripes of L7 to simplify the geometries footprint = rasters.vectorize( gap_msk, values=1, keep_values=False, dissolve=True ) # Needs a dataframe to be dissolved footprint = footprint.convex_hull return gpd.GeoDataFrame(geometry=footprint.geometry, crs=footprint.crs)
Ancestors
Instance variables
var output
-
Inherited from:
LandsatProduct
.output
Output directory of the product, to write orthorectified data for example.
var name
-
Inherited from:
LandsatProduct
.name
Product name (its filename without any extension).
var split_name
-
Inherited from:
LandsatProduct
.split_name
Split name, to retrieve every information from its filename (dates, tile, product type…).
var archive_path
-
Inherited from:
LandsatProduct
.archive_path
Archive path, same as the product path if not specified. Useful when you want to know where both the extracted and archived version of your product …
var path
-
Inherited from:
LandsatProduct
.path
Usable path to the product, either extracted or archived path, according to the satellite.
var is_archived
-
Inherited from:
LandsatProduct
.is_archived
Is the archived product is processed (a products is considered as archived if its products path is a directory).
var needs_extraction
-
Inherited from:
LandsatProduct
.needs_extraction
Does this products needs to be extracted to be processed ? (
True
by default). var date
-
Inherited from:
LandsatProduct
.date
Acquisition date.
var datetime
-
Inherited from:
LandsatProduct
.datetime
Acquisition datetime.
var tile_name
-
Inherited from:
LandsatProduct
.tile_name
Tile if possible (for data that can be piled, for example S2 and Landsats).
var sensor_type
-
Inherited from:
LandsatProduct
.sensor_type
Sensor type, SAR or optical.
var product_type
-
Inherited from:
LandsatProduct
.product_type
Product type, satellite-related field, such as L1C or L2A for Sentinel-2 data.
var band_names
-
Inherited from:
LandsatProduct
.band_names
Band mapping between band wrapping names such as
GREEN
and band real number such as03
for Sentinel-2. var is_reference
-
Inherited from:
LandsatProduct
.is_reference
If the product is a reference, used for algorithms that need pre and post data, such as fire detection.
var corresponding_ref
-
Inherited from:
LandsatProduct
.corresponding_ref
The corresponding reference products to the current one (if the product is not a reference but has a reference data corresponding to it). A list …
var nodata
-
Inherited from:
LandsatProduct
.nodata
Product nodata, set to 0 by default. Please do not touch this or all index will fail.
var platform
-
Inherited from:
LandsatProduct
.platform
Product platform, such as Sentinel-2
var resolution
-
Inherited from:
LandsatProduct
.resolution
Default resolution in meters of the current product. For SAR product, we use Ground Range resolution as we will automatically orthorectify the tiles.
var condensed_name
-
Inherited from:
LandsatProduct
.condensed_name
Condensed name, the filename with only useful data to keep the name unique (ie.
20191215T110441_S2_30TXP_L2A_122756
). Used to shorten names and paths. var sat_id
-
Inherited from:
LandsatProduct
.sat_id
Satellite ID, i.e.
S2
for Sentinel-2
Methods
def footprint(
self)
-
Get real footprint of the products (without nodata, in french == emprise utile)
Warning
As Landsat 7 is broken (with nodata stripes all over the bands), the footprint is not easily computed and may take some time to be delivered.
>>> from eoreader.reader import Reader >>> path = r"LC08_L1GT_023030_20200518_20200527_01_T2" >>> prod = Reader().open(path) >>> prod.footprint() index geometry 0 0 POLYGON ((366165.000 4899735.000, 366165.000 4...
Overload of the generic function because landsat nodata seems to be different in QA than in regular bands. Indeed, nodata pixels vary according to the band sensor footprint, whereas QA nodata is where at least one band has nodata.
We chose to keep QA nodata values for the footprint in order to show where all bands are valid.
TL;DR: We use the QA nodata value to determine the product's footprint.
Returns
gpd.GeoDataFrame
- Footprint as a GeoDataFrame
Expand source code
def footprint(self) -> gpd.GeoDataFrame: """ Get real footprint of the products (without nodata, in french == emprise utile) .. WARNING:: As Landsat 7 is broken (with nodata stripes all over the bands), the footprint is not easily computed and may take some time to be delivered. ```python >>> from eoreader.reader import Reader >>> path = r"LC08_L1GT_023030_20200518_20200527_01_T2" >>> prod = Reader().open(path) >>> prod.footprint() index geometry 0 0 POLYGON ((366165.000 4899735.000, 366165.000 4... ``` Overload of the generic function because landsat nodata seems to be different in QA than in regular bands. Indeed, nodata pixels vary according to the band sensor footprint, whereas QA nodata is where at least one band has nodata. We chose to keep QA nodata values for the footprint in order to show where all bands are valid. **TL;DR: We use the QA nodata value to determine the product's footprint**. Returns: gpd.GeoDataFrame: Footprint as a GeoDataFrame """ LOGGER.warning( "Due to the Landsat-7 gaps, this function returns a rounded footprint on the corners. " "Sorry for the inconvenience." ) # Read the file with a very low resolution -> use raster_rio that is faster ! gap_msk = rasters.read( self._get_path(self._nodata_band_id), resolution=self.resolution * 50, masked=False, ) # Vectorize the nodata band # Take the convex hull to discard the stripes of L7 to simplify the geometries footprint = rasters.vectorize( gap_msk, values=1, keep_values=False, dissolve=True ) # Needs a dataframe to be dissolved footprint = footprint.convex_hull return gpd.GeoDataFrame(geometry=footprint.geometry, crs=footprint.crs)
def get_datetime(
self,
as_datetime=False)-
Inherited from:
LandsatProduct
.get_datetime
Get the product's acquisition datetime, with format
YYYYMMDDTHHMMSS
<->%Y%m%dT%H%M%S
… def get_band_paths(
self,
band_list,
resolution=None)-
Inherited from:
LandsatProduct
.get_band_paths
Return the paths of required bands …
def read_mtd(
self,
force_pd=False)-
Inherited from:
LandsatProduct
.read_mtd
Read Landsat metadata as: …
def get_mean_sun_angles(
self)
-
Inherited from:
LandsatProduct
.get_mean_sun_angles
Get Mean Sun angles (Azimuth and Zenith angles) …
def get_default_band(
self)
-
Inherited from:
LandsatProduct
.get_default_band
Get default band:
GREEN
for optical data as every optical satellite has a GREEN band … def get_default_band_path(
self)
-
Inherited from:
LandsatProduct
.get_default_band_path
Get default band (
GREEN
for optical data) path … def crs(
self)
-
Inherited from:
LandsatProduct
.crs
Get UTM projection of the tile …
def extent(
self)
-
Inherited from:
LandsatProduct
.extent
Get UTM extent of the tile …
def get_existing_bands(
self)
-
Inherited from:
LandsatProduct
.get_existing_bands
Return the existing band paths …
def get_existing_band_paths(
self)
-
Inherited from:
LandsatProduct
.get_existing_band_paths
Return the existing band paths …
def get_date(
self,
as_date=False)-
Inherited from:
LandsatProduct
.get_date
Get the product's acquisition date …
def load(
self,
bands,
resolution=None,
size=None)-
Inherited from:
LandsatProduct
.load
Open the bands and compute the wanted index …
def has_band(
self,
band)-
Inherited from:
LandsatProduct
.has_band
Does this products has the specified band ? …
def stack(
self,
bands,
resolution=None,
stack_path=None,
save_as_int=False)-
Inherited from:
LandsatProduct
.stack
Stack bands and index of a products …