Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
umr-tetis
scenes
Commits
6f5832f0
Commit
6f5832f0
authored
Apr 19, 2022
by
Cresson Remi
Browse files
Merge branch '14-codes_examples' into 'develop'
DOC: add examples Closes
#10
,
#8
, and
#14
See merge request
!33
parents
a3ee5f87
5120ae72
Pipeline
#35125
passed with stages
in 4 minutes and 47 seconds
Changes
8
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
scenes/core.py
View file @
6f5832f0
...
...
@@ -78,7 +78,7 @@ class Source(pyotb.Output):
"""
for
new_app
in
args
:
self
.
_app_stack
.
append
(
new_app
)
return
Source
(
root_imagery
=
self
.
root_imagery
,
out
=
self
.
_app_stack
[
-
1
],
parent
=
self
)
return
self
.
__class__
(
root_imagery
=
self
.
root_imagery
,
out
=
self
.
_app_stack
[
-
1
],
parent
=
self
)
def
drilled
(
self
,
msk_vec_file
,
inside
=
True
,
nodata
=
0
):
"""
...
...
scenes/dates.py
View file @
6f5832f0
# -*- coding: utf-8 -*-
"""
This module aims to deal with dates
This module aims to deal with dates.
---
The `datetime.datetime` class is used as internal date type.
```
#!python
dt = datetime.datetime(year=2020, month=12, day=2)
```
Is equivalent to:
```
dt = str2datetime("02-12-2020")
dt = str2datetime("2020-12-02")
dt = str2datetime("02/12/2020")
```
The `any2datetime` method returns a `datetime.datetime` instance, whatever the input is (`str` or
`datetime.datetime`).
```
dt1 = datetime.datetime(year=2020, month=12, day=2)
dt2 = str2datetime("02-12-2020")
dt1_2 = any2datetime(dt1) # same
dt2_2 = any2datetime("02-12-2020") # same
```
The `get_timestamp` method converts a `datetime.datetime` instance into a number of seconds (int).
```
ts = get_timestamp(dt) # 1606780800.0
```
"""
import
datetime
...
...
scenes/deepnets.py
View file @
6f5832f0
"""
This module provides tools to easily interact with deep learning models.
It is based on OTBTF.
OTBTF is needed to use this module.
---
# Super-resolution
The SR4RS model can be applied over any `scenes.core.Source` instance.
We recall that this model is intended to be used over Sentinel-2 optical images.
For example, here is how we perform the super-resolution of a Theia S2 product.
```
#!python
import scenes
archive = "SENTINEL2B_..._T31TEJ_D_V1-8.zip"
s2_scene = scenes.sentinel.Sentinel22AScene(archive)
s2_image = s2_scene.get_imagery().get_10m_bands()
sr = scenes.deepnets.sr4rs(s2_image) # pyotb.core.otbObject
sr.write("sr.tif")
```
"""
import
os
import
zipfile
...
...
scenes/download.py
View file @
6f5832f0
# -*- coding: utf-8 -*-
"""
This module handles the download of Sentinel-2 images from Theia (L2A or L3A).
The `scenes.download.TheiaDownloader` uses Theia credentials.
Those must be stored in a file looking like this:
```
serveur = https://theia.cnes.fr/atdistrib
resto = resto2
token_type = text
login_theia = remi.cresson@irstea.fr
password_theia = thisisnotmyrealpassword
```
To instantiate the `scenes.download.TheiaDownloader`:
```
#!python
import scenes
cfg_file = "config.txt" # Theia config file
theia = scenes.download.TheiaDownloader(cfg_file)
```
# Bounding box + temporal range
The following example shows how to use the `scenes.download.TheiaDownloader` to search
or download all Sentinel-2 images in a bounding box within a temporal range.
## Search
When the `download_dir` is not set, the download is not performed, and only the search results
are returned from the function.
```
bbox = scenes.spatial.BoundingBox(43.706, 43.708, 4.317, 4.420)
trange = ("01/01/2020", "O1/O1/2022")
results = theia.download_in_range(bbox, trange, level="LEVEL2A")
print(results)
```
## Download
To download the files, the `download_dir` must be specified:
```
theia.download_in_range(bbox, trange, "/tmp/download/", "LEVEL2A")
```
When files already exist, the md5sum is computed and compared with the one in the catalog,
in order to determine if it has to be downloaded again. If the file is already downloaded and
is complete according to the md5sum, its download is skipped.
# Bounding box + single date
In the same manner, the downloader can search or download the closest images from a specific date.
The returned dict from the function is updated with a "delta" key storing the value of the number of
days from the specific date.
```
# For searching only
results = theia.download_in_range(bbox, trange, "LEVEL2A")
# For downloading
theia.download_in_range(bbox, trange, "/tmp/download/", "LEVEL2A")
```
"""
import
datetime
import
hashlib
...
...
scenes/indexation.py
View file @
6f5832f0
"""
This module contains stuff for the spatio-temporal indexation of scenes
This module contains stuff for the spatio-temporal indexation of scenes.
The `scenes.indexation.Index` uses an R-Tree to perform the indexation of objects in the (x, y, t) domain.
---
Example: spatio-temporal indexation of multiple `scenes.core.Scene` instances.
# Build a spatio temporal index
```
#!python
import scenes
scenes_list = [...] # a list of various `scenes.core.Scene` instances.
index = scenes.indexation.Index(scenes_list) # build the index
```
# Search from a `BoundingBox`
The `find_indices()` method returns the indices of the indexed `scenes.core.Scene` instances matching
the query.
The `find()` method returns the indexed `scenes.core.Scene` instances matching the query.
```
bbox = BoundingBox(43.706, 43.708, 4.317, 4.420)
indices_results = index.find_indices(bbox) # spatial query returning scenes indices
scenes_results = index.find(bbox) # spatial query returning scenes instances
```
# Spatio-temporal search
A date min and/or a date max can be added in the query.
```
scenes_results = index.find(bbox, "01/01/2020" "01/01/2022")
```
# Search from a vector data file
The search can also be performed with a vector data file.
```
vec = "/path/to/vector.gpkg"
scenes_results = index.find(vec, "01/01/2020" "01/01/2022")
```
"""
import
datetime
import
rtree
...
...
@@ -27,7 +69,8 @@ def _bbox(bbox_wgs84, date_min, date_max):
class
Index
:
"""
Stores an indexation structures for a list of Scenes"""
Stores an indexation structure for a list of Scenes
"""
def
__init__
(
self
,
scenes_list
):
"""
Args:
...
...
scenes/sentinel.py
View file @
6f5832f0
...
...
@@ -2,6 +2,97 @@
This module contains Sentinel-2 classes (sources, imagery, and scenes).
Right now everything is ready to use THEIA L2A and L3A products.
# Scene
The `Sentinel22AScene` and `Sentinel23AScene` classes carry metadata and imagery
respectively for Sentinel-2 Level 2A and Level 3A products. They both inherit from
the generic abstract `Sentinel2SceneBase` class.
## Instantiation
`Sentinel22AScene` and `Sentinel23AScene` are instantiated from the archive (.zip file)
or the product folder.
```
#!python
import scenes
sc_2a = scenes.sentinel.Sentinel22AScene("SENTINEL2B_..._T31TEJ_D_V1-8.zip")
sc_3a = scenes.sentinel.Sentinel23AScene("SENTINEL2X_...L3A_T31TEJ_D_V1-0.zip")
```
## Metadata
The scene metadata can be accessed with the `get_metadata()` method, like any
`scenes.core.Scene` instance.
```
md_dict = sc_2a.get_metadata()
for key, value in md_dict.items():
print(f"{key}: {value}")
```
## Imagery
The imagery can be accessed with the `get_imagery()` method, which returns a
`Sentinel22AImagery` or a `Sentinel23AImagery` instance.
There is a single kind of imagery in `Sentinel22AScene` and `Sentinel23AScene`.
```
imagery_2a = sc_2a.get_imagery()
imagery_3a = sc_3a.get_imagery()
```
## Sources
The `Sentinel22AImagery` (and `Sentinel23AImagery`) both deliver two kind of `Sentinel22ASource`
(and `Sentinel23ASource`) instances:
- The 10m spacing channels, in the following order: 4, 3, 2, 8
- The 20m spacing channels, in the following order: 5, 6, 7, 8a, 11, 12
```
bands_10m_2a = imagery_2a.get_10m_bands()
bands_20m_2a = imagery_2a.get_20m_bands()
bands_10m_3a = imagery_3a.get_10m_bands()
bands_20m_3a = imagery_3a.get_20m_bands()
```
The `Sentinel22ASource` implements the `Sentinel22ASource.cld_msk_drilled` method, that
enable to mask the cloud masks over the root source, with the specified
no-data value (default is 0).
The following example show how to derive a child source replacing the
pixels that are in the clouds with pixels at -10000 (which is the no-data
value in Theia products):
```
drilled = bands_10m_2a.cld_msk_drilled()
```
The `Sentinel23ASource` implements the `Sentinel23ASource.flg_msk_drilled` method, that
enable to mask the pixels on a selection of labels of the quality mask.
The following example shows how to mask pixels of anything other that land with -10000:
```
drilled = bands_10m_3a.flg_msk_drilled(keep_flags_values=(4,))
```
`Sentinel22ASource` and `Sentinel23ASource` inherit from `scenes.core.Source`,
hence implemented sources transformations (e.g. `scenes.core.Source.masked`,
`scenes.core.Source.clip_over_img`, `scenes.core.Source.resample_over`,
`scenes.core.Source.reproject`, etc.
```
clipped = drilled.clip_over_img(roi)
reprojected = clipped.reproject(epsg=4328)
```
Note that the resulting transformed `Sentinel22ASource` and `Sentinel23ASource` are still
instances of `Sentinel22ASource` and `Sentinel23ASource` even after generic operations
implemented in `scenes.core.Source`.
# Usage with pyotb
As `scenes.core.Source`, it also can be used like any `pyotb.core.otbObject`.
The following example show how to use an OTB application with a source at input.
```
rgb_nice = pyotb.DynamicConvert(reprojected)
rgb_nice.write("image.tif", pixel_type="uint8")
```
"""
import
datetime
from
abc
import
abstractmethod
...
...
@@ -60,12 +151,13 @@ class Sentinel23ASource(Sentinel2Source):
Args:
keep_flags_values: flags values to keep (Default value = (3, 4)). Can be:
0 = No data
1 = Cloud
2 = Snow
3 = Water
4 = Land
(source: https://labo.obs-mip.fr/multitemp/theias-l3a-product-format/)
- 0 = No data
- 1 = Cloud
- 2 = Snow
- 3 = Water
- 4 = Land
(source: https://labo.obs-mip.fr/multitemp/theias-l3a-product-format/)
nodata: nodata value inside holes (Default value = -10000)
Returns:
...
...
scenes/spatial.py
View file @
6f5832f0
"""
This module provides classes and functions to help with light geospatial objects (projections, bounding boxes, etc)
This module provides classes and functions to help with light geospatial objects
(projections, bounding boxes, etc).
"""
import
math
from
osgeo
import
osr
,
ogr
...
...
scenes/spot.py
View file @
6f5832f0
"""
This module contains Spot 6/7 classes. It implements sources, imagery and scene.
This module contains classes to work with Spot 6/7 products.
In particular, it specializes `scenes.core.Source`, `scenes.core.Imagery`
and `scenes.core.Scene` for Spot 6/7 products.
---
# Scene
The `Spot67Scene` class carries metadata and imagery for Spot-6/7 sensors.
## Instantiation
A `Spot67Scene` is instantiated from the .XML DIMAP files of PAN and XS:
```
#!python
import scenes
sc = scenes.spot.Spot67Scene(dimap_file_xs="DIM_SPOT6_MS..._1.XML",
dimap_file_pan="DIM_SPOT6_P..._1.XML")
```
## Metadata
The scene metadata can be accessed with the `get_metadata()` method, like any
`scenes.core.Scene` instance.
```
md_dict = sc.get_metadata()
for key, value in md_dict.items():
print(f"{key}: {value}")
```
## Imagery
The imagery can be accessed with the `get_imagery()` method, which returns a
`Spot67Imagery` instance.
Two kind of imagery exist:
- DN (Digital Number): raw sensor values
- TOA (Top Of Atmosphere): calibrated reflectance
```
imagery_dn = sc.get_imagery(reflectance="dn") # uncalibrated
imagery_toa = sc.get_imagery(reflectance="toa") # TOA reflectance
```
## Sources
The `Spot67Imagery` delivers three kind of `Spot67Source` instances:
- The multispectral image
- The Panchromatic image
- The pansharpenend image
```
xs = imagery.get_xs() # Multispectral image Source
pan = imagery.get_pan() # Panchromatic image Source
pxs = imagery.get_pxs(method="bayes") # Pansharpened Source
```
The `Spot67Source` implements the `Spot67Source.cld_msk_drilled` method, that
enable to mask the cloud masks over the root source, with the specified
no-data value (default is 0).
The following example show how to derive a child source replacing the
pixels that are in the clouds with zero-valued pixels:
```
pxs_drilled = pxs.cld_msk_drilled()
```
The `Spot67Source` inherits from `scenes.core.Source`, hence implemented
sources transformations (e.g. `scenes.core.Source.masked()`, `scenes.core.Source.clip_over_img()`,
`scenes.core.Source.resample_over()`, `scenes.core.Source.reproject()`, etc.
```
clipped = pxs_drilled.clip_over_img(roi)
reprojected = clipped.reproject(epsg=4328)
```
Note that the resulting transformed `Spot67Source` is still an instance of
`Spot67Source` even after generic operations implemented in `scenes.core.Source`.
# Usage with pyotb
As `scenes.core.Source`, it also can be used like any `pyotb.core.otbObject`.
The following example show how to use an OTB application with a source at input.
```
rgb_nice = pyotb.DynamicConvert(reprojected)
rgb_nice.write("image.tif", pixel_type="uint8")
```
"""
import
datetime
import
xml.etree.ElementTree
as
ET
...
...
@@ -13,13 +96,13 @@ from scenes.spatial import extent_overlap
def
find_all_dimaps
(
pth
):
"""
Return the list of DIMAPS that are inside all subdirectories of the root directory
Return the list of DIMAPS
XML files
that are inside all subdirectories of the root directory
.
Args:
pth: root directory
Returns:
list of DIMAPS
list of DIMAPS
XML files
"""
return
utils
.
find_files_in_all_subdirs
(
pth
=
pth
,
pattern
=
"DIM_*.XML"
)
...
...
@@ -27,7 +110,8 @@ def find_all_dimaps(pth):
def
get_spot67_scenes
(
root_dir
):
"""
Return the list of pairs of PAN/XS DIMAPS
Return the list of scenes that can be instantiated from a root directory containing
a "PAN" and a "MS" subdirectories.
Args:
root_dir: directory containing "MS" and "PAN" subdirectories
...
...
@@ -100,7 +184,11 @@ class Spot67Imagery(Imagery):
"""
Spot 6/7 imagery class.
This class carry the base image source, which can be radiometrically or geometrically corrected.
A `Spot67Imagery` instance carries the following `Spot67Source` instances:
- xs: the multispectral channels (Red, Gree, Blue, Near infrared @ 6.0 meters spacing)
- pan: the panchromatic channel (Visible domain @ 1.5 meters spacing)
- pxs: the pansharpened channels (Red, Gree, Blue, Near infrared @ 1.5 meters spacing)
"""
...
...
@@ -126,20 +214,34 @@ class Spot67Imagery(Imagery):
self
.
pan
=
_toa
(
self
.
pan
)
def
get_xs
(
self
):
"""Returns XS source"""
"""
Returns the MS source
Returns:
A Spot67Source instance for the MS image
"""
return
Spot67Source
(
self
,
self
.
xs
)
def
get_pan
(
self
):
"""Returns PAN source"""
"""
Returns PAN source
Returns:
A Spot67Source instance for the PAN image
"""
return
Spot67Source
(
self
,
self
.
pan
)
def
get_pxs
(
self
,
method
=
"bayes"
):
"""
Returns the pansharpened source
Args:
method: one of rcs, lmvm, bayes (Default value = "bayes")
Returns:
P
ansharpened
XS sourc
e
A Spot67Source instance for the p
ansharpened
imag
e
"""
xs
=
self
.
get_xs
()
...
...
@@ -153,7 +255,8 @@ class Spot67Scene(Scene):
"""
Spot 6/7 root_scene class.
The class carries all the metadata from the root_scene, and can be used to retrieve its imagery.
The Spot67Scene class carries all metadata and imagery from the scene.
A Spot67Scene object can be instantiated from the XS and PAN DIMAPS (.XML) file.
"""
PXS_OVERLAP_THRESH
=
0.995
...
...
@@ -161,8 +264,9 @@ class Spot67Scene(Scene):
def
__init__
(
self
,
dimap_file_xs
,
dimap_file_pan
):
"""
Args:
dimap_file_xs: DIMAP file for XS
dimap_file_pan: DIMAP file for PAN
dimap_file_xs: XML DIMAP file for the XS product
dimap_file_pan: XML DIMAP file for the PAN product
"""
# DIMAP files
...
...
@@ -298,7 +402,9 @@ class Spot67Scene(Scene):
def
get_metadata
(
self
):
"""
Get metadata
Get metadata.
The metadata is stored in a dict().
Returns:
metadata: dict
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment