Commit ad8ed371 authored by Remi Cresson's avatar Remi Cresson
Browse files

Doc: fix reflectance

No related merge requests found
Showing with 53 additions and 135 deletions
+53 -135
......@@ -20,6 +20,9 @@ pip install https://gitlab.irstea.fr/umr-tetis/scenes/-/archive/develop/scenes-d
`Scene` instances have generic methods and attributes.
- **Imagery sources**: imagery sources can be accessed using `get_xxx()`
methods, where `xxx` is the name of the source to get. Any source can be used
in OTB, PyOTB pipelines, or with numpy directly.
- **Metadata**: metadata access with the `get_metadata()` method.
``` py
for key, value in sc.get_metadata():
......@@ -37,29 +40,36 @@ Spot 6/7 scenes are instantiated from XS and PAN XML files of DIMAPS products.
``` py
from scenes.spot import Spot67Scene
sc = Spot67Scene(dimap_file_xs="/path/to/DIM_SPOT7_MS_..._1.XML",
dimap_file_pan="/path/to/DIM_SPOT7_P_..._1.XML")
sc = Spot67Scene(
dimap_file_xs="/path/to/DIM_SPOT7_MS_..._1.XML",
dimap_file_pan="/path/to/DIM_SPOT7_P_..._1.XML"
)
```
### Image sources
Spot-6/7 scenes have 3 images sources.
Spot-6/7 scenes have 3 images sources: `xs`, `pan` and `pxs`.
| Source | `Scene` method | Description |
|--------|----------------|--------------------------------------------------------------------|
| XS | `get_xs()` | 4 channels (Red, Green, Blue, Near Infrared), ~6m physical spacing |
| Pan | `get_pan()` | 1 channel (visible domain), ~1.5m physical spacing |
| PXS | `get_pxs(method=...)` | 4 channels (same as XS), ~1.5m physical spacing |
| PXS | `get_pxs()` | 4 channels (same as XS), ~1.5m physical spacing |
Each source can be computed in DN/TOA/TOC reflectance.
``` py
xs_raw = sc.get_xs() # DN
xs_raw = sc.get_xs(reflectance="dn") # DN
xs_toa = sc.get_xs(reflectance="toa") # TOA
xs_toc = sc.get_xs(reflectance="toc") # TOC
xs_toa = sc.get_xs().reflectance(level="toa") # TOA
xs_toc = sc.get_xs().reflectance(level="toc") # TOC
```
!!! Warning
OTB version must be >= 8.1.0 to support optical calibration using source
`reflectance()` method.
kwargs of `reflectance()` are the same as `pyotb.OpticalCalibration`.
Each source can be masked with the cloud masks of the original product.
The no-data value can be chosen.
......@@ -67,21 +77,22 @@ The no-data value can be chosen.
xs_toa_cld = xs_toa.cld_msk_drilled() # (1)
```
1. To change the no-data inside the clouds mask: `masked_src = src.cld_msk_drilled(nodata=-999)`
1. To change the no-data inside the clouds mask:
`masked_src = src.cld_msk_drilled(nodata=-999)`
### Examples
Computing NDVI from XS image in TOA reflectance:
``` py
xs = toa.get_xs(reflectance="toa") # (1)
xs = toa.get_xs().reflectance(level="toa") # (1)
exp = "(im1b4-im1b1)/(im1b4+im1b1)"
ndvi = pyotb.bandmath(exp=exp, il=[xs]) # (2)
ndvi = pyotb.bandmath(exp=exp, il=[xs]) # (2)
ndvi.write("ndvi.tif")
```
1. `xs` is a `scenes.spot.Spot67Source` instance
2. `ndvi` is a `pyotb.app` that inputs `xs`
2. `ndvi` is a `pyotb.App` object that inputs `xs`
The next example is a set of preprocessing operations on a Spot-6/7 XS image:
......@@ -91,10 +102,10 @@ The next example is a set of preprocessing operations on a Spot-6/7 XS image:
4. clip the result over a reference raster
``` py
pxs = sc.get_pxs(reflectance="toa") # (1)
drilled = pxs.cld_msk_drilled() # (2)
pxs = sc.get_pxs().reflectance(level="toa") # (1)
drilled = pxs.cld_msk_drilled() # (2)
ref_img = "/tmp/S2A_2020...._FRE_10m.tif"
subset = drilled.clip_over_img(ref_img) # (3)
subset = drilled.clip_over_img(ref_img) # (3)
subset.write("subset.tif")
```
......@@ -112,14 +123,16 @@ Superimpose an image over a reference image.
In the example below, `ref_img` is another `scenes.core.Source` instance.
``` py
toa = sc.get_pxs(reflectance="toa")
toa = sc.get_pxs().reflectance(level="toa")
superimposed = toa.resample_over(ref_img)
superimposed.write("superimposed.tif")
```
## Sentinel-2
Currently, Level-2 and Level-3 products from the [Theia land data center](https://www.theia-land.fr/en/product/sentinel-2-surface-reflectance/) are supported.
Currently, Level-2 and Level-3 products from the
[Theia land data center](https://www.theia-land.fr/en/product/sentinel-2-surface-reflectance/)
and Level-2 products from Microsoft Planetary Computer are supported
### Instantiation
......@@ -131,9 +144,16 @@ sc_level2 = Sentinel22AScene("/path/to/SENTINEL2A_..._V1-8/.zip")
sc_level3 = Sentinel23AScene("/path/to/SENTINEL2X_...L3A_T31TEJ_D/.zip")
```
Note that you can also instanciate uncomplete products, e.g. only 10m spacing
bands. In this case, a warning will be displayed.
### Sources
Sentinel-2 images include 2 sources.
Sentinel-2 images include the following sources:
- single band, 10m spacing: `b4`, `b3`, `b2`, `b8`
- single band, 20m spacing: `b5`, `b6`, `b7`, `b8a`, `b11`, `b12`
- concatenated bands: `10m_bands`, `20m_bands`
- for Theia products, quality masks: `clm_r1`, `clm_r2`, `edg_r1`, `edg_r2`
| Source | `Scene` method | Description |
|-----------|-------------------|-----------------------------------------------------------|
......@@ -149,7 +169,8 @@ src = sc_level2.get_10m_bands()
masked_src = src.cld_msk_drilled() # (1)
```
1. To change the no-data inside the clouds mask: `masked_src = src.cld_msk_drilled(nodata=-999)`
1. To change the no-data inside the clouds mask:
`masked_src = src.cld_msk_drilled(nodata=-999)`
For Level 3 products, using the quality mask:
......@@ -158,16 +179,21 @@ src = sc_level3.get_10m_bands()
masked_src = src.flg_msk_drilled() # (1)
```
1. To change the no-data inside the clouds mask: `masked_src = src.flg_msk_drilled(nodata=-999)`.
Also, the `keep_flags_values` can be used to select the pixels to keep from a list of values in the quality mask (land, water, snow, ...).
1. To change the no-data inside the clouds mask:
`masked_src = src.flg_msk_drilled(nodata=-999)`.
Also, the `keep_flags_values` can be used to select the pixels to keep from a
list of values in the quality mask (land, water, snow, ...).
## Spatial and temporal indexation
Scenes includes a module to perform spatial and temporal indexation of `Scene` instances.
Scenes includes a module to perform spatial and temporal indexation of `Scene`
instances.
### Query in space
Perform a query in space (WGS84 bounding box) and time (optional) with an indexation structure.
Perform a query in space (WGS84 bounding box) and time (optional) with an
indexation structure.
``` py
from scenes import spot, indexation
scs = spot.get_spot67_scenes(root_dir) # (1)
......@@ -184,127 +210,19 @@ for sc in matches:
### Query in space and time
To perform searches in time:
``` py
matches1 = idx.find(bbox_wgs84=bbox, "01/02/2019", "01-12-2020") # (1)
matches2 = idx.find(bbox_wgs84=bbox, "01/02/2019") # (2)
matches3 = idx.find(bbox_wgs84=bbox, date_max="01/02/2019") # (3)
```
1. A few date formats are supported: "dd/mm/yyyy", "dd-mm-yyyy", and "yyyy-mm-dd"
1. A few date formats are supported: "dd/mm/yyyy", "dd-mm-yyyy", and
"yyyy-mm-dd"
2. Here we don't have upper bound
3. You can also specify only an upper bound, without lower bound (use the keywords `date_min` and `date_max`
## Architecture
### Scene class
The scene class handles all the metadata and the image sources.
``` mermaid
classDiagram
Scene <|-- Spot67Scene
Scene <|-- Sentinel2SceneBase
Sentinel2SceneBase <|-- Sentinel22AScene
Sentinel2SceneBase <|-- Sentinel23AScene
Scene --* Source: root_scene
class Scene{
+datetime acquisition_date
+int epsg
+bbox_wgs84
+get_metadata()
+__repr__()
}
class Spot67Scene{
+float azimuth_angle
+float azimuth_angle_across
+float azimuth_angle_along
+float incidence_angle
+float sun_azimuth_angle
+float sun_elev_angle
+get_metadata()
+Spot67Source get_xs()
+Spot67Source get_pan()
+Spot67Source get_pxs()
}
class Sentinel2SceneBase{
+__init__(archive, tag)
+get_file()
+get_band()
+get_metadata()
+Sentinel2Source get_10m_bands()
+Sentinel2Source get_20m_bands()
}
class Sentinel22AScene{
+__init__(archive)
+str clm_r1_msk_file
+str clm_r2_msk_file
+str edg_r1_msk_file
+str edg_r2_msk_file
+get_metadata()
}
class Sentinel23AScene{
+__init__(archive)
+str flg_r1_msk_file
+str flg_r2_msk_file
+get_metadata()
}
```
### Source class
The source stores the image pipeline that delivers the pixels.
3. You can also specify only an upper bound, without lower bound (use the
keywords `date_min` and `date_max`
``` mermaid
classDiagram
Source <|-- Spot67Source
Source <|-- Sentinel2Source
Sentinel2Source <|-- Sentinel22ASource
Sentinel2Source <|-- Sentinel23ASource
class Source{
+__init__(root_scene, out, parent=None)
+Scene root_scene
+Source parent
+Source drilled(msk_vec_file, nodata=0)
+Source cld_msk_drilled(nodata=0)
+Source resample_over(ref_img, interpolator="nn", nodata=0)
+Source clip_over_img(ref_img)
+Source clip_over_vec(ref_vec)
+Source new_source(*args)
}
class Spot67Source{
+Spot67Source cld_msk_drilled(nodata=0)
}
class Sentinel2Source{
+R1_SIZE
+R2_SIZE
+Sentinel2Source msk_drilled(msk_dict, exp, nodata=0)
}
class Sentinel22ASource{
+Sentinel22ASource cld_msk_drilled(nodata=0)
}
class Sentinel23ASource{
+Sentinel23ASource flg_msk_drilled(keep_flags_values=(3, 4), nodata=0)
}
```
### Implement a new sensor from scratch
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment