diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 572bb7f6b9b325c98869c0cda25ff449af25f321..8cf3d432a2b739d0dd56dfe493efed6ea9142a73 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -40,10 +40,11 @@ pages: - sudo apt update && sudo apt install python3-pycurl - sudo python3 -m pip install pytest pytest-cov pyotb rtree tqdm - sudo pip3 install pdoc3 - - pdoc3 --html scenes --output-dir public/ + - pdoc3 --html scenes --output-dir /tmp/doc && cp -r /tmp/doc/scenes public artifacts: paths: - public + # ------------------------------------------------------ Test ---------------------------------------------------------- .test_base: diff --git a/scenes/bbox.py b/scenes/bbox.py index a023382d73366c5d3b326fa61087c45e224f2472..43eaddd7783d3699c95256eca9ead68080b36636 100644 --- a/scenes/bbox.py +++ b/scenes/bbox.py @@ -1,5 +1,5 @@ """ -This module provides bounding box class +This module provides the bounding box class. """ diff --git a/scenes/core.py b/scenes/core.py index 4630e047a68096b181ebeda1e48486e27e96144a..8ac4a84075dde3d63c0c31fa87449947a61487b9 100644 --- a/scenes/core.py +++ b/scenes/core.py @@ -1,5 +1,6 @@ """ -This module provides the Source class, which aims to handle the access to the rasters delivered by EO products +This module provides the core classes of the library, which aims to handle the access to the rasters delivered by +different EO products (Spot-6/7, Sentinel-2, ...) """ import pickle from abc import ABC, abstractmethod @@ -20,7 +21,7 @@ def save_scenes(scenes_list, pickle_file): def load_scenes(pickle_file): - """Use pickle to save Spot-6/7 scenes + """Use pickle to load scenes Args: pickle_file: pickle file @@ -36,6 +37,7 @@ class Source(pyotb.Output): """Source class. Holds common operations on image sources (e.g. drill, resample, extract an ROI, etc.) + Inherits from pyotb.Output """ @@ -235,7 +237,12 @@ class Scene(ABC): """ def get_metadata(self): - """Enable one instance to be used with print()""" + """Enable one instance to be used with print() + + Returns: + metadata dict + + """ return { "Acquisition date": self.acquisition_date, "Bounding box (WGS84)": self.bbox_wgs84, @@ -249,5 +256,9 @@ class Scene(ABC): def __repr__(self): """ Enable one instance to be used with print() + + Returns: + a string summarizing the metadata + """ return "\n".join(["{}: {}".format(key, value) for key, value in self.get_metadata().items()]) diff --git a/scenes/download.py b/scenes/download.py index cf950ffaf8b91fc1dd1faef4bd6e275e70abd1a3..2800d0b008c1c7c83e8b7a42f69e2f6495e79ae7 100644 --- a/scenes/download.py +++ b/scenes/download.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- """ -Download Sentinel-2 images from Theia +This module handles the download of Sentinel-2 images from Theia (L2A or L3A). """ import os import hashlib @@ -13,10 +13,14 @@ import tqdm def bbox2str(bbox): - """ - Return a str containing the bounding box - :param bbox: the bounding box (BoundingBox instance) - :return: a str + """Return a str containing the bounding box + + Args: + bbox: the bounding box (BoundingBox instance) + + Returns: + a string + """ return '{},{},{},{}'.format(bbox.ymin, bbox.xmin, bbox.ymax, bbox.xmax) @@ -114,12 +118,21 @@ def curl_url(url, postdata, verbose=False, fp=None, header=None): class TheiaDownloader: - """THEIA downloader""" + """The TheiaDownloader class enables to download L2A and L3A Theia products""" def __init__(self, config_file, max_records=500): """ Args: config_file: Theia configuration file + The file contents should look like this: + ``` + serveur = https://theia.cnes.fr/atdistrib + resto = resto2 + token_type = text + login_theia = remi.cresson@irstea.fr + password_theia = thisisnotmyrealpassword + ``` max_records: Maximum number of records + """ # Read the Theia config file @@ -250,7 +263,8 @@ class TheiaDownloader: level: LEVEL2A, LEVEL3A, ... (Default value = "LEVEL3A") Returns: - # TODO + search results / downloaded files (dict) + """ start_date, end_date = dates_range dict_query = { @@ -280,7 +294,7 @@ class TheiaDownloader: level: LEVEL2A, LEVEL3A, ... (Default value = "LEVEL3A") Returns: - downloaded files + search results / downloaded files (dict) """ diff --git a/scenes/indexation.py b/scenes/indexation.py index c10cd0e42b87ac675c1d27cc18b5b9c98769a7ff..63578ec306114e274ee8fdc181732c4a765d92f7 100644 --- a/scenes/indexation.py +++ b/scenes/indexation.py @@ -1,5 +1,5 @@ """ -Indexation of scenes +This module contains stuff for the spatio-temporal indexation of scenes. """ import datetime import rtree diff --git a/scenes/raster_manips.py b/scenes/raster_manips.py deleted file mode 100644 index c97199ab5c87fc95ec645a100decf7cd23e52e13..0000000000000000000000000000000000000000 --- a/scenes/raster_manips.py +++ /dev/null @@ -1,67 +0,0 @@ -""" -Raster manipulation -""" -import osr -from scenes import utils -import pyotb - - -def align_on_raster(in_image, ref_image, spacing_ratio, interpolator="nn", nodata=0): - """Return a raster which is aligned on the reference, with the given spacing ratio - - Args: - in_image: input image - ref_image: reference image - spacing_ratio: spacing ratio. When > 1, the output has larger pixel. When < 1, the output has smaller pixels. - interpolator: interpolator (nn/bco/linear) (Default value = "nn") - nodata: no data value outside image (Default value = 0) - - Returns: - output aligned image - - """ - - def _get_gt(image): - info = pyotb.ReadImageInfo({"in": image}) - ori_x = info.GetParameterFloat("originx") - ori_y = info.GetParameterFloat("originy") - spc_x = info.GetParameterFloat("spacingx") - spc_y = info.GetParameterFloat("spacingy") - proj_ref = info.GetParameterString('projectionref') - try: - srs = osr.SpatialReference(wkt=proj_ref) - epsg_code = srs.GetAttrValue("PROJCS|AUTHORITY", 1) - if epsg_code is None: - epsg_code = srs.GetAttrValue("AUTHORITY", 1) - epsg = int(epsg_code) - except Exception as exp: # pylint: disable=broad-except - raise Exception("Unable to return EPSG code. Projection is {}. Returning None. ({})".format(proj_ref, exp)) - - xmin = ori_x - spc_x - ymax = ori_y + spc_y - return xmin, ymax, spc_x, spc_y, epsg, srs - - ref_ul_x, ref_ul_y, ref_spc_x, ref_spc_y, ref_epsg, ref_srs = _get_gt(ref_image) - - def _aligned(value, origin, spacing): - return value - (value - origin) % abs(spacing) - - ul_x, ul_y, _, _, _, src_srs = _get_gt(in_image) - aligned_ul_x = _aligned(ul_x, ref_ul_x, ref_spc_x) - aligned_ul_y = _aligned(ul_y, ref_ul_y, ref_spc_y) - reprojected_coods = utils.reproject_coords([(aligned_ul_x, aligned_ul_y)], src_srs=src_srs, tgt_srs=ref_srs) - (new_ul_x, new_ul_y) = reprojected_coods[0] - new_spc_x = ref_spc_x * spacing_ratio - new_spc_y = ref_spc_y * spacing_ratio - - return pyotb.Orthorectification({"io.in": in_image, - "map": "epsg", - "map.epsg.code": ref_epsg, - "interpolator": interpolator, - "outputs.mode": "autosize", - "outputs.ulx": new_ul_x, - "outputs.uly": new_ul_y, - "outputs.spacingx": new_spc_x, - "outputs.spacingy": new_spc_y, - "opt.gridspacing": 10.0 * new_spc_x, - "outputs.default": nodata}) diff --git a/scenes/sentinel.py b/scenes/sentinel.py index 1774733f9315dadaa824cf1cb6e5791db63ed8e7..666e3644206bd758eb42bc431f526a4183e0bac9 100644 --- a/scenes/sentinel.py +++ b/scenes/sentinel.py @@ -1,5 +1,7 @@ """ -Sentinel-2 root_scene class +This module contains Sentinel-2 classes (sources, imagery, and scenes). + +Right now everything is ready to use THEIA L2A and L3A products. """ import datetime from abc import abstractmethod diff --git a/scenes/spot.py b/scenes/spot.py index 0a573c5d8c0bd36519ea1f74b570e6b1502e0809..609d56da00ded25fccc1338a63e17bdb2fc26f40 100644 --- a/scenes/spot.py +++ b/scenes/spot.py @@ -1,5 +1,5 @@ """ -Spot 6/7 root_scene class +This module contains Spot 6/7 classes. It implements sources, imagery and scene. """ import datetime import xml.etree.ElementTree as ET diff --git a/scenes/utils.py b/scenes/utils.py index 0f7a544c643639799d93f76f5d702feab0b24c02..622668bc7ec68bab3b2c2808c7eb21fde64afd12 100644 --- a/scenes/utils.py +++ b/scenes/utils.py @@ -1,5 +1,5 @@ """ -A set of helpers for generic purpose +This module contains a set of generic purpose helpers """ import os import glob