From 1a761a35ad2c3b9274d863b23a35b653a7aacc96 Mon Sep 17 00:00:00 2001 From: Scartography Date: Fri, 9 Jan 2026 11:54:22 +0100 Subject: [PATCH 1/6] docs init commit --- .github/workflows/docs.yml | 37 ++++++++++++ docs/source/api.rst | 37 ++++++++++++ docs/source/conf.py | 13 +++- docs/source/examples.rst | 36 ++++++++++- .../generated/mapchete_eo.array.buffer.rst | 12 ++++ .../generated/mapchete_eo.array.color.rst | 14 +++++ .../generated/mapchete_eo.array.convert.rst | 15 +++++ docs/source/generated/mapchete_eo.base.rst | 14 +++++ ...te_eo.image_operations.blend_functions.rst | 26 ++++++++ ...e_eo.image_operations.color_correction.rst | 12 ++++ ...pchete_eo.image_operations.compositing.rst | 36 +++++++++++ .../mapchete_eo.image_operations.filters.rst | 25 ++++++++ ....image_operations.linear_normalization.rst | 6 ++ .../generated/mapchete_eo.io.assets.rst | 25 ++++++++ .../source/generated/mapchete_eo.io.items.rst | 15 +++++ .../mapchete_eo.io.levelled_cubes.rst | 13 ++++ .../generated/mapchete_eo.io.products.rst | 22 +++++++ ...mapchete_eo.platforms.sentinel2.driver.rst | 13 ++++ .../mapchete_eo.platforms.sentinel2.masks.rst | 17 ++++++ ...latforms.sentinel2.preprocessing_tasks.rst | 12 ++++ ...apchete_eo.platforms.sentinel2.product.rst | 19 ++++++ ...mapchete_eo.platforms.sentinel2.source.rst | 18 ++++++ .../mapchete_eo.processes.dtype_scale.rst | 12 ++++ .../mapchete_eo.processes.eo_to_xarray.rst | 12 ++++ .../mapchete_eo.processes.merge_rasters.rst | 21 +++++++ docs/source/generated/mapchete_eo.product.rst | 21 +++++++ .../generated/mapchete_eo.search.base.rst | 20 +++++++ .../mapchete_eo.search.stac_search.rst | 13 ++++ .../mapchete_eo.search.stac_static.rst | 12 ++++ .../mapchete_eo.search.utm_search.rst | 20 +++++++ docs/source/generated/mapchete_eo.sort.rst | 21 +++++++ docs/source/generated/mapchete_eo.source.rst | 12 ++++ docs/source/generated/mapchete_eo.time.rst | 15 +++++ docs/source/generated/mapchete_eo.types.rst | 15 +++++ docs/source/index.rst | 8 +-- docs/source/usage.rst | 60 +++++++++++++++++++ examples/ndvi.mapchete | 21 +++++++ examples/ndvi_process.py | 44 ++++++++++++++ examples/temporal_mean.mapchete | 23 +++++++ examples/temporal_mean_process.py | 47 +++++++++++++++ mapchete_eo/base.py | 52 ++++++++++++++-- mapchete_eo/image_operations/compositing.py | 12 ++++ mapchete_eo/platforms/sentinel2/driver.py | 5 +- mapchete_eo/platforms/sentinel2/masks.py | 8 ++- .../sentinel2/preprocessing_tasks.py | 5 +- mapchete_eo/platforms/sentinel2/product.py | 14 ++++- mapchete_eo/product.py | 46 +++++++++++++- mapchete_eo/search/base.py | 26 +++++++- mapchete_eo/search/stac_search.py | 6 ++ mapchete_eo/search/stac_static.py | 3 + mapchete_eo/search/utm_search.py | 3 + mapchete_eo/sort.py | 4 +- mapchete_eo/source.py | 4 +- mapchete_eo/time.py | 15 ++++- mapchete_eo/types.py | 9 ++- 55 files changed, 1010 insertions(+), 36 deletions(-) create mode 100644 .github/workflows/docs.yml create mode 100644 docs/source/api.rst create mode 100644 docs/source/generated/mapchete_eo.array.buffer.rst create mode 100644 docs/source/generated/mapchete_eo.array.color.rst create mode 100644 docs/source/generated/mapchete_eo.array.convert.rst create mode 100644 docs/source/generated/mapchete_eo.base.rst create mode 100644 docs/source/generated/mapchete_eo.image_operations.blend_functions.rst create mode 100644 docs/source/generated/mapchete_eo.image_operations.color_correction.rst create mode 100644 docs/source/generated/mapchete_eo.image_operations.compositing.rst create mode 100644 docs/source/generated/mapchete_eo.image_operations.filters.rst create mode 100644 docs/source/generated/mapchete_eo.image_operations.linear_normalization.rst create mode 100644 docs/source/generated/mapchete_eo.io.assets.rst create mode 100644 docs/source/generated/mapchete_eo.io.items.rst create mode 100644 docs/source/generated/mapchete_eo.io.levelled_cubes.rst create mode 100644 docs/source/generated/mapchete_eo.io.products.rst create mode 100644 docs/source/generated/mapchete_eo.platforms.sentinel2.driver.rst create mode 100644 docs/source/generated/mapchete_eo.platforms.sentinel2.masks.rst create mode 100644 docs/source/generated/mapchete_eo.platforms.sentinel2.preprocessing_tasks.rst create mode 100644 docs/source/generated/mapchete_eo.platforms.sentinel2.product.rst create mode 100644 docs/source/generated/mapchete_eo.platforms.sentinel2.source.rst create mode 100644 docs/source/generated/mapchete_eo.processes.dtype_scale.rst create mode 100644 docs/source/generated/mapchete_eo.processes.eo_to_xarray.rst create mode 100644 docs/source/generated/mapchete_eo.processes.merge_rasters.rst create mode 100644 docs/source/generated/mapchete_eo.product.rst create mode 100644 docs/source/generated/mapchete_eo.search.base.rst create mode 100644 docs/source/generated/mapchete_eo.search.stac_search.rst create mode 100644 docs/source/generated/mapchete_eo.search.stac_static.rst create mode 100644 docs/source/generated/mapchete_eo.search.utm_search.rst create mode 100644 docs/source/generated/mapchete_eo.sort.rst create mode 100644 docs/source/generated/mapchete_eo.source.rst create mode 100644 docs/source/generated/mapchete_eo.time.rst create mode 100644 docs/source/generated/mapchete_eo.types.rst create mode 100644 docs/source/usage.rst create mode 100644 examples/ndvi.mapchete create mode 100644 examples/ndvi_process.py create mode 100644 examples/temporal_mean.mapchete create mode 100644 examples/temporal_mean_process.py diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 00000000..19dc69ea --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,37 @@ +name: Deploy Documentation + +on: + push: + branches: + - main + workflow_dispatch: + +permissions: + contents: write + +jobs: + build-and-deploy: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install uv + uses: astral-sh/setup-uv@v5 + + - name: Set up Python + run: uv python install + + - name: Install dependencies + run: | + uv sync --all-extras + + - name: Build documentation + run: | + uv run sphinx-build -b html docs/source docs/build/html + + - name: Deploy to GitHub Pages + uses: peaceiris/actions-gh-pages@v4 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: ./docs/build/html diff --git a/docs/source/api.rst b/docs/source/api.rst new file mode 100644 index 00000000..2b365fd6 --- /dev/null +++ b/docs/source/api.rst @@ -0,0 +1,37 @@ +API Reference +============= + +.. autosummary:: + :toctree: generated + :recursive: + + mapchete_eo.base + mapchete_eo.product + mapchete_eo.source + mapchete_eo.search.base + mapchete_eo.search.stac_search + mapchete_eo.search.stac_static + mapchete_eo.search.utm_search + mapchete_eo.platforms.sentinel2.driver + mapchete_eo.platforms.sentinel2.source + mapchete_eo.platforms.sentinel2.product + mapchete_eo.platforms.sentinel2.preprocessing_tasks + mapchete_eo.platforms.sentinel2.masks + mapchete_eo.image_operations.compositing + mapchete_eo.image_operations.blend_functions + mapchete_eo.image_operations.color_correction + mapchete_eo.image_operations.filters + mapchete_eo.image_operations.linear_normalization + mapchete_eo.processes.merge_rasters + mapchete_eo.processes.dtype_scale + mapchete_eo.processes.eo_to_xarray + mapchete_eo.io.products + mapchete_eo.io.levelled_cubes + mapchete_eo.io.assets + mapchete_eo.io.items + mapchete_eo.array.convert + mapchete_eo.array.color + mapchete_eo.array.buffer + mapchete_eo.time + mapchete_eo.types + mapchete_eo.sort diff --git a/docs/source/conf.py b/docs/source/conf.py index 7362f570..71a8bc53 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -41,12 +41,9 @@ def get_metadata(): version, author = get_metadata() project = "mapchete-eo" -author = author release = version -version, author = get_metadata() - rst_prolog = f""" .. |author| replace:: {author} .. |version| replace:: {version} @@ -58,8 +55,18 @@ def get_metadata(): "sphinx.ext.napoleon", "sphinx.ext.viewcode", "sphinx.ext.autosummary", + "sphinx.ext.intersphinx", ] +intersphinx_mapping = { + "python": ("https://docs.python.org/3", None), + "numpy": ("https://numpy.org/doc/stable/", None), + "matplotlib": ("https://matplotlib.org/stable/", None), + "rasterio": ("https://rasterio.readthedocs.io/en/latest/", None), + "xarray": ("https://docs.xarray.dev/en/stable/", None), + "mapchete": ("https://mapchete.readthedocs.io/en/latest/", None), +} + autosummary_generate = True # Optional: include tests folder on path (if you want to import tests modules) diff --git a/docs/source/examples.rst b/docs/source/examples.rst index 8b2c8eba..d5b52451 100644 --- a/docs/source/examples.rst +++ b/docs/source/examples.rst @@ -3,10 +3,40 @@ Examples Examples can be found in the `examples` directory of this repository. -List of available examples: +List of available Examples +======== -1) `sentinel-2_2025-may-june_first-pixel.mapchete` -2) *placeholder* +Mapchete-EO Drivers +------------------- + +You can execute mapchete-eo drivers as any other mapchete processes. + + +Sentinel-2 First Pixel +----------------------- + +This example uses Sentinel-2 data and picks the first available cloud-free pixel from a time range. + +* `Config `_ +* `Process `_ + + +Sentinel-2 NDVI +--------------- + +Calculate the Normalized Difference Vegetation Index (NDVI) from Sentinel-2 data. + +* `Config `_ +* `Process `_ + + +Sentinel-2 Temporal Mean +------------------------ + +Create a temporal mean composite of cloud-free pixels over a given time range. + +* `Config `_ +* `Process `_ Usage ----- diff --git a/docs/source/generated/mapchete_eo.array.buffer.rst b/docs/source/generated/mapchete_eo.array.buffer.rst new file mode 100644 index 00000000..da104aa4 --- /dev/null +++ b/docs/source/generated/mapchete_eo.array.buffer.rst @@ -0,0 +1,12 @@ +mapchete\_eo.array.buffer +========================= + +.. automodule:: mapchete_eo.array.buffer + + + .. rubric:: Functions + + .. autosummary:: + + buffer_array + \ No newline at end of file diff --git a/docs/source/generated/mapchete_eo.array.color.rst b/docs/source/generated/mapchete_eo.array.color.rst new file mode 100644 index 00000000..d6f54a8f --- /dev/null +++ b/docs/source/generated/mapchete_eo.array.color.rst @@ -0,0 +1,14 @@ +mapchete\_eo.array.color +======================== + +.. automodule:: mapchete_eo.array.color + + + .. rubric:: Functions + + .. autosummary:: + + color_array + hex_to_rgb + outlier_pixels + \ No newline at end of file diff --git a/docs/source/generated/mapchete_eo.array.convert.rst b/docs/source/generated/mapchete_eo.array.convert.rst new file mode 100644 index 00000000..b54efa67 --- /dev/null +++ b/docs/source/generated/mapchete_eo.array.convert.rst @@ -0,0 +1,15 @@ +mapchete\_eo.array.convert +========================== + +.. automodule:: mapchete_eo.array.convert + + + .. rubric:: Functions + + .. autosummary:: + + to_bands_mask + to_dataarray + to_dataset + to_masked_array + \ No newline at end of file diff --git a/docs/source/generated/mapchete_eo.base.rst b/docs/source/generated/mapchete_eo.base.rst new file mode 100644 index 00000000..20839521 --- /dev/null +++ b/docs/source/generated/mapchete_eo.base.rst @@ -0,0 +1,14 @@ +mapchete\_eo.base +================= + +.. automodule:: mapchete_eo.base + + + .. rubric:: Classes + + .. autosummary:: + + BaseDriverConfig + EODataCube + InputData + \ No newline at end of file diff --git a/docs/source/generated/mapchete_eo.image_operations.blend_functions.rst b/docs/source/generated/mapchete_eo.image_operations.blend_functions.rst new file mode 100644 index 00000000..2b1ad91c --- /dev/null +++ b/docs/source/generated/mapchete_eo.image_operations.blend_functions.rst @@ -0,0 +1,26 @@ +mapchete\_eo.image\_operations.blend\_functions +=============================================== + +.. automodule:: mapchete_eo.image_operations.blend_functions + + + .. rubric:: Functions + + .. autosummary:: + + addition + darken_only + difference + divide + dodge + grain_extract + grain_merge + hard_light + lighten_only + multiply + normal + overlay + screen + soft_light + subtract + \ No newline at end of file diff --git a/docs/source/generated/mapchete_eo.image_operations.color_correction.rst b/docs/source/generated/mapchete_eo.image_operations.color_correction.rst new file mode 100644 index 00000000..2b55c30d --- /dev/null +++ b/docs/source/generated/mapchete_eo.image_operations.color_correction.rst @@ -0,0 +1,12 @@ +mapchete\_eo.image\_operations.color\_correction +================================================ + +.. automodule:: mapchete_eo.image_operations.color_correction + + + .. rubric:: Functions + + .. autosummary:: + + color_correct + \ No newline at end of file diff --git a/docs/source/generated/mapchete_eo.image_operations.compositing.rst b/docs/source/generated/mapchete_eo.image_operations.compositing.rst new file mode 100644 index 00000000..9711bf15 --- /dev/null +++ b/docs/source/generated/mapchete_eo.image_operations.compositing.rst @@ -0,0 +1,36 @@ +mapchete\_eo.image\_operations.compositing +========================================== + +.. automodule:: mapchete_eo.image_operations.compositing + + + .. rubric:: Functions + + .. autosummary:: + + addition + composite + darken_only + difference + divide + dodge + fuzzy_alpha_mask + fuzzy_mask + grain_extract + grain_merge + hard_light + lighten_only + multiply + normal + overlay + screen + soft_light + subtract + to_rgba + + .. rubric:: Classes + + .. autosummary:: + + GradientPosition + \ No newline at end of file diff --git a/docs/source/generated/mapchete_eo.image_operations.filters.rst b/docs/source/generated/mapchete_eo.image_operations.filters.rst new file mode 100644 index 00000000..07a14de9 --- /dev/null +++ b/docs/source/generated/mapchete_eo.image_operations.filters.rst @@ -0,0 +1,25 @@ +mapchete\_eo.image\_operations.filters +====================================== + +.. automodule:: mapchete_eo.image_operations.filters + + + .. rubric:: Functions + + .. autosummary:: + + blur + contour + detail + edge_enhance + edge_enhance_more + emboss + find_edges + gaussian_blur + median + sharpen + sharpen_16bit + smooth + smooth_more + unsharp_mask + \ No newline at end of file diff --git a/docs/source/generated/mapchete_eo.image_operations.linear_normalization.rst b/docs/source/generated/mapchete_eo.image_operations.linear_normalization.rst new file mode 100644 index 00000000..661982cf --- /dev/null +++ b/docs/source/generated/mapchete_eo.image_operations.linear_normalization.rst @@ -0,0 +1,6 @@ +mapchete\_eo.image\_operations.linear\_normalization +==================================================== + +.. currentmodule:: mapchete_eo.image_operations + +.. autofunction:: linear_normalization \ No newline at end of file diff --git a/docs/source/generated/mapchete_eo.io.assets.rst b/docs/source/generated/mapchete_eo.io.assets.rst new file mode 100644 index 00000000..2484d85d --- /dev/null +++ b/docs/source/generated/mapchete_eo.io.assets.rst @@ -0,0 +1,25 @@ +mapchete\_eo.io.assets +====================== + +.. automodule:: mapchete_eo.io.assets + + + .. rubric:: Functions + + .. autosummary:: + + asset_to_np_array + convert_asset + convert_raster + copy_asset + get_assets + get_metadata_assets + read_mask_as_raster + should_be_converted + + .. rubric:: Classes + + .. autosummary:: + + STACRasterBandProperties + \ No newline at end of file diff --git a/docs/source/generated/mapchete_eo.io.items.rst b/docs/source/generated/mapchete_eo.io.items.rst new file mode 100644 index 00000000..3d9f64a2 --- /dev/null +++ b/docs/source/generated/mapchete_eo.io.items.rst @@ -0,0 +1,15 @@ +mapchete\_eo.io.items +===================== + +.. automodule:: mapchete_eo.io.items + + + .. rubric:: Functions + + .. autosummary:: + + expand_params + get_item_property + item_fix_footprint + item_to_np_array + \ No newline at end of file diff --git a/docs/source/generated/mapchete_eo.io.levelled_cubes.rst b/docs/source/generated/mapchete_eo.io.levelled_cubes.rst new file mode 100644 index 00000000..cd53e2de --- /dev/null +++ b/docs/source/generated/mapchete_eo.io.levelled_cubes.rst @@ -0,0 +1,13 @@ +mapchete\_eo.io.levelled\_cubes +=============================== + +.. automodule:: mapchete_eo.io.levelled_cubes + + + .. rubric:: Functions + + .. autosummary:: + + read_levelled_cube_to_np_array + read_levelled_cube_to_xarray + \ No newline at end of file diff --git a/docs/source/generated/mapchete_eo.io.products.rst b/docs/source/generated/mapchete_eo.io.products.rst new file mode 100644 index 00000000..54048bff --- /dev/null +++ b/docs/source/generated/mapchete_eo.io.products.rst @@ -0,0 +1,22 @@ +mapchete\_eo.io.products +======================== + +.. automodule:: mapchete_eo.io.products + + + .. rubric:: Functions + + .. autosummary:: + + generate_slice_dataarrays + merge_products + products_to_np_array + products_to_slices + products_to_xarray + + .. rubric:: Classes + + .. autosummary:: + + Slice + \ No newline at end of file diff --git a/docs/source/generated/mapchete_eo.platforms.sentinel2.driver.rst b/docs/source/generated/mapchete_eo.platforms.sentinel2.driver.rst new file mode 100644 index 00000000..96bb56d0 --- /dev/null +++ b/docs/source/generated/mapchete_eo.platforms.sentinel2.driver.rst @@ -0,0 +1,13 @@ +mapchete\_eo.platforms.sentinel2.driver +======================================= + +.. automodule:: mapchete_eo.platforms.sentinel2.driver + + + .. rubric:: Classes + + .. autosummary:: + + InputData + Sentinel2Cube + \ No newline at end of file diff --git a/docs/source/generated/mapchete_eo.platforms.sentinel2.masks.rst b/docs/source/generated/mapchete_eo.platforms.sentinel2.masks.rst new file mode 100644 index 00000000..297e2d62 --- /dev/null +++ b/docs/source/generated/mapchete_eo.platforms.sentinel2.masks.rst @@ -0,0 +1,17 @@ +mapchete\_eo.platforms.sentinel2.masks +====================================== + +.. automodule:: mapchete_eo.platforms.sentinel2.masks + + + .. rubric:: Functions + + .. autosummary:: + + generate_masks + generate_slice_masks_dataarrays + masks_to_xarray + merge_products_masks + product_masks_to_slices + read_masks + \ No newline at end of file diff --git a/docs/source/generated/mapchete_eo.platforms.sentinel2.preprocessing_tasks.rst b/docs/source/generated/mapchete_eo.platforms.sentinel2.preprocessing_tasks.rst new file mode 100644 index 00000000..89fc677b --- /dev/null +++ b/docs/source/generated/mapchete_eo.platforms.sentinel2.preprocessing_tasks.rst @@ -0,0 +1,12 @@ +mapchete\_eo.platforms.sentinel2.preprocessing\_tasks +===================================================== + +.. automodule:: mapchete_eo.platforms.sentinel2.preprocessing_tasks + + + .. rubric:: Functions + + .. autosummary:: + + parse_s2_product + \ No newline at end of file diff --git a/docs/source/generated/mapchete_eo.platforms.sentinel2.product.rst b/docs/source/generated/mapchete_eo.platforms.sentinel2.product.rst new file mode 100644 index 00000000..a29d0ee9 --- /dev/null +++ b/docs/source/generated/mapchete_eo.platforms.sentinel2.product.rst @@ -0,0 +1,19 @@ +mapchete\_eo.platforms.sentinel2.product +======================================== + +.. automodule:: mapchete_eo.platforms.sentinel2.product + + + .. rubric:: Functions + + .. autosummary:: + + asset_name_to_l2a_band + + .. rubric:: Classes + + .. autosummary:: + + Cache + S2Product + \ No newline at end of file diff --git a/docs/source/generated/mapchete_eo.platforms.sentinel2.source.rst b/docs/source/generated/mapchete_eo.platforms.sentinel2.source.rst new file mode 100644 index 00000000..4bc28ed8 --- /dev/null +++ b/docs/source/generated/mapchete_eo.platforms.sentinel2.source.rst @@ -0,0 +1,18 @@ +mapchete\_eo.platforms.sentinel2.source +======================================= + +.. automodule:: mapchete_eo.platforms.sentinel2.source + + + .. rubric:: Functions + + .. autosummary:: + + known_collection_to_url + + .. rubric:: Classes + + .. autosummary:: + + Sentinel2Source + \ No newline at end of file diff --git a/docs/source/generated/mapchete_eo.processes.dtype_scale.rst b/docs/source/generated/mapchete_eo.processes.dtype_scale.rst new file mode 100644 index 00000000..ae8a26ab --- /dev/null +++ b/docs/source/generated/mapchete_eo.processes.dtype_scale.rst @@ -0,0 +1,12 @@ +mapchete\_eo.processes.dtype\_scale +=================================== + +.. automodule:: mapchete_eo.processes.dtype_scale + + + .. rubric:: Functions + + .. autosummary:: + + execute + \ No newline at end of file diff --git a/docs/source/generated/mapchete_eo.processes.eo_to_xarray.rst b/docs/source/generated/mapchete_eo.processes.eo_to_xarray.rst new file mode 100644 index 00000000..bcb15226 --- /dev/null +++ b/docs/source/generated/mapchete_eo.processes.eo_to_xarray.rst @@ -0,0 +1,12 @@ +mapchete\_eo.processes.eo\_to\_xarray +===================================== + +.. automodule:: mapchete_eo.processes.eo_to_xarray + + + .. rubric:: Functions + + .. autosummary:: + + execute + \ No newline at end of file diff --git a/docs/source/generated/mapchete_eo.processes.merge_rasters.rst b/docs/source/generated/mapchete_eo.processes.merge_rasters.rst new file mode 100644 index 00000000..f06035e3 --- /dev/null +++ b/docs/source/generated/mapchete_eo.processes.merge_rasters.rst @@ -0,0 +1,21 @@ +mapchete\_eo.processes.merge\_rasters +===================================== + +.. automodule:: mapchete_eo.processes.merge_rasters + + + .. rubric:: Functions + + .. autosummary:: + + execute + fillnodata_merge + gradient_merge + merge_rasters + + .. rubric:: Classes + + .. autosummary:: + + MergeMethod + \ No newline at end of file diff --git a/docs/source/generated/mapchete_eo.product.rst b/docs/source/generated/mapchete_eo.product.rst new file mode 100644 index 00000000..2b02e724 --- /dev/null +++ b/docs/source/generated/mapchete_eo.product.rst @@ -0,0 +1,21 @@ +mapchete\_eo.product +==================== + +.. automodule:: mapchete_eo.product + + + .. rubric:: Functions + + .. autosummary:: + + add_to_blacklist + blacklist_products + eo_bands_to_band_locations + find_eo_band + + .. rubric:: Classes + + .. autosummary:: + + EOProduct + \ No newline at end of file diff --git a/docs/source/generated/mapchete_eo.search.base.rst b/docs/source/generated/mapchete_eo.search.base.rst new file mode 100644 index 00000000..5fe4692e --- /dev/null +++ b/docs/source/generated/mapchete_eo.search.base.rst @@ -0,0 +1,20 @@ +mapchete\_eo.search.base +======================== + +.. automodule:: mapchete_eo.search.base + + + .. rubric:: Functions + + .. autosummary:: + + filter_items + + .. rubric:: Classes + + .. autosummary:: + + CollectionSearcher + FSSpecStacIO + StaticCollectionWriterMixin + \ No newline at end of file diff --git a/docs/source/generated/mapchete_eo.search.stac_search.rst b/docs/source/generated/mapchete_eo.search.stac_search.rst new file mode 100644 index 00000000..f6f6e96f --- /dev/null +++ b/docs/source/generated/mapchete_eo.search.stac_search.rst @@ -0,0 +1,13 @@ +mapchete\_eo.search.stac\_search +================================ + +.. automodule:: mapchete_eo.search.stac_search + + + .. rubric:: Classes + + .. autosummary:: + + STACSearchCollection + SpatialSearchChunks + \ No newline at end of file diff --git a/docs/source/generated/mapchete_eo.search.stac_static.rst b/docs/source/generated/mapchete_eo.search.stac_static.rst new file mode 100644 index 00000000..f1a82455 --- /dev/null +++ b/docs/source/generated/mapchete_eo.search.stac_static.rst @@ -0,0 +1,12 @@ +mapchete\_eo.search.stac\_static +================================ + +.. automodule:: mapchete_eo.search.stac_static + + + .. rubric:: Classes + + .. autosummary:: + + STACStaticCollection + \ No newline at end of file diff --git a/docs/source/generated/mapchete_eo.search.utm_search.rst b/docs/source/generated/mapchete_eo.search.utm_search.rst new file mode 100644 index 00000000..10854b31 --- /dev/null +++ b/docs/source/generated/mapchete_eo.search.utm_search.rst @@ -0,0 +1,20 @@ +mapchete\_eo.search.utm\_search +=============================== + +.. automodule:: mapchete_eo.search.utm_search + + + .. rubric:: Functions + + .. autosummary:: + + find_items + items_from_directories + items_from_static_index + + .. rubric:: Classes + + .. autosummary:: + + UTMSearchCatalog + \ No newline at end of file diff --git a/docs/source/generated/mapchete_eo.sort.rst b/docs/source/generated/mapchete_eo.sort.rst new file mode 100644 index 00000000..dffaa432 --- /dev/null +++ b/docs/source/generated/mapchete_eo.sort.rst @@ -0,0 +1,21 @@ +mapchete\_eo.sort +================= + +.. automodule:: mapchete_eo.sort + + + .. rubric:: Functions + + .. autosummary:: + + sort_objects_by_cloud_cover + sort_objects_by_target_date + + .. rubric:: Classes + + .. autosummary:: + + CloudCoverSort + SortMethodConfig + TargetDateSort + \ No newline at end of file diff --git a/docs/source/generated/mapchete_eo.source.rst b/docs/source/generated/mapchete_eo.source.rst new file mode 100644 index 00000000..4f7c0217 --- /dev/null +++ b/docs/source/generated/mapchete_eo.source.rst @@ -0,0 +1,12 @@ +mapchete\_eo.source +=================== + +.. automodule:: mapchete_eo.source + + + .. rubric:: Classes + + .. autosummary:: + + Source + \ No newline at end of file diff --git a/docs/source/generated/mapchete_eo.time.rst b/docs/source/generated/mapchete_eo.time.rst new file mode 100644 index 00000000..28886d46 --- /dev/null +++ b/docs/source/generated/mapchete_eo.time.rst @@ -0,0 +1,15 @@ +mapchete\_eo.time +================= + +.. automodule:: mapchete_eo.time + + + .. rubric:: Functions + + .. autosummary:: + + day_range + time_ranges_intersect + timedelta + to_datetime + \ No newline at end of file diff --git a/docs/source/generated/mapchete_eo.types.rst b/docs/source/generated/mapchete_eo.types.rst new file mode 100644 index 00000000..10c7be64 --- /dev/null +++ b/docs/source/generated/mapchete_eo.types.rst @@ -0,0 +1,15 @@ +mapchete\_eo.types +================== + +.. automodule:: mapchete_eo.types + + + .. rubric:: Classes + + .. autosummary:: + + BandLocation + GeodataType + MergeMethod + TimeRange + \ No newline at end of file diff --git a/docs/source/index.rst b/docs/source/index.rst index 3343e9e6..2eb3ff39 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -12,20 +12,20 @@ cloud masking, temporal compositing, BRDF, etc. With STAC API and catalogs handling for data sources. -CLI ---- +Generic Info +------------ .. toctree:: :maxdepth: 2 - :caption: Generic Info + usage cli + api Example Usage ------------- .. toctree:: :maxdepth: 2 - :caption: Basic Examples examples diff --git a/docs/source/usage.rst b/docs/source/usage.rst new file mode 100644 index 00000000..28009f7c --- /dev/null +++ b/docs/source/usage.rst @@ -0,0 +1,60 @@ +Usage Guide +=========== + +Introduction +------------ + +**mapchete-eo** extends Mapchete with Earth Observation specific capabilities. This guide covers common patterns for data discovery and processing. + +Data Discovery (Search) +----------------------- + +Search for data using `Source` objects. + +.. code-block:: python + + from mapchete_eo.source import Source + + source = Source( + collection="sentinel-2-l2a", + catalog_type="stac", + # ... other config + ) + + # Search for items + items = list(source.search(area=roi, time="2023-01-01/2023-01-31")) + +Reading Data +------------ + +Products are used to read data into `xarray` or `numpy` cubes. + +.. code-block:: python + + # Inside a mapchete process + def execute(mp, **kwargs): + with mp.open("sentinel-2") as s2: + # Read as xarray + ds = s2.read(eo_bands=["red", "green", "blue"]) + + # Read as MaskedArray + arr = s2.read_np_array(eo_bands=["nir"]) + +Compositing and Blending +------------------------ + +You can use various blending methods to combine overlapping products. + +.. code-block:: python + + from mapchete_eo.image_operations.compositing import composite + + # Composite foreground and background using 'multiply' + blended = composite("multiply", bg_arr, fg_arr) + +Example Workflow +---------------- + +1. Define your tileset and process area in a `.mapchete` file. +2. Use `mapchete-eo` drivers (e.g., `sentinel2`) to declare inputs. +3. Access and process Earth Observation data with high-level API functions. diff --git a/examples/ndvi.mapchete b/examples/ndvi.mapchete new file mode 100644 index 00000000..e9140319 --- /dev/null +++ b/examples/ndvi.mapchete @@ -0,0 +1,21 @@ +process: ndvi_process.py +input: + element84_sentinel2: + format: Sentinel-2 + level: L2A + max_cloud_percent: 5 + time: + start: 2025-06-01 + end: 2025-06-30 +output: + format: GTiff + bands: 1 + path: sentinel-2_ndvi + dtype: float32 +pyramid: + grid: geodetic + metatiling: 8 +zoom_levels: + min: 8 + max: 13 +bounds: [16.20, 48.00, 16.75, 48.5] diff --git a/examples/ndvi_process.py b/examples/ndvi_process.py new file mode 100644 index 00000000..701e6181 --- /dev/null +++ b/examples/ndvi_process.py @@ -0,0 +1,44 @@ +import logging +import numpy as np +import numpy.ma as ma +from rasterio.enums import Resampling + +from mapchete_eo.platforms.sentinel2.driver import Sentinel2Cube + + +logger = logging.getLogger(__name__) + + +def execute( + element84_sentinel2: Sentinel2Cube, + resampling: str = "bilinear", + nodata: float = 0.0, +) -> ma.MaskedArray: + """ + Calculate NDVI (Normalized Difference Vegetation Index). + """ + logger.debug("Reading Sentinel-2 NIR and Red bands.") + + # Read the first available cloud-free pixel for NIR and Red + # (Simplified for example purposes) + data = element84_sentinel2.read_np_array( + assets=["red", "nir"], + resampling=Resampling[resampling], + nodatavals=nodata, + ) + + red = data[0].astype(float) + nir = data[1].astype(float) + + # Calculate NDVI: (NIR - Red) / (NIR + Red) + with np.errstate(divide="ignore", invalid="ignore"): + ndvi = (nir - red) / (nir + red) + ndvi[np.isnan(ndvi)] = nodata + + # NDVI is typically in range [-1, 1]. + # For visualization, we could scale it to 0-255 or just return the float array. + # Here we return it as a single-band float32 array. + return ma.masked_array( + data=ndvi.astype(np.float32), + mask=data.mask[0] + ) diff --git a/examples/temporal_mean.mapchete b/examples/temporal_mean.mapchete new file mode 100644 index 00000000..af44d77f --- /dev/null +++ b/examples/temporal_mean.mapchete @@ -0,0 +1,23 @@ +process: temporal_mean_process.py +input: + element84_sentinel2: + format: Sentinel-2 + level: L2A + max_cloud_percent: 20 + time: + start: 2025-06-01 + end: 2025-08-31 +output: + format: GTiff + bands: 3 + path: sentinel-2_temporal_mean + dtype: uint16 +pyramid: + grid: geodetic + metatiling: 8 +zoom_levels: + min: 8 + max: 13 +bounds: [16.20, 48.00, 16.75, 48.5] +process_parameters: + assets: [red, green, blue] diff --git a/examples/temporal_mean_process.py b/examples/temporal_mean_process.py new file mode 100644 index 00000000..73bb27ed --- /dev/null +++ b/examples/temporal_mean_process.py @@ -0,0 +1,47 @@ +import logging +import numpy as np +import numpy.ma as ma +from rasterio.enums import Resampling +from typing import List + +from mapchete_eo.platforms.sentinel2.driver import Sentinel2Cube + + +logger = logging.getLogger(__name__) + + +def execute( + element84_sentinel2: Sentinel2Cube, + assets: List[str], + resampling: str = "bilinear", + nodata: float = 0.0, +) -> ma.MaskedArray: + """ + Create a temporal mean composite of cloud-free pixels. + """ + logger.debug("Reading Sentinel-2 time series.") + + # Read all available products into an xarray dataset + ds = element84_sentinel2.read( + assets=assets, + resampling=Resampling[resampling], + nodatavals=nodata, + ) + + # Calculate mean over the time dimension + # (Assuming xarray handle mask/nodata correctly via _FillValue) + mean_composite = ds.mean(dim="time", skipna=True) + + # Convert back to numpy masked array + # This is a simplified conversion for the example + out_data = [] + out_mask = [] + for asset in assets: + arr = mean_composite[asset].values + out_data.append(arr) + out_mask.append(np.isnan(arr)) + + return ma.masked_array( + data=np.stack(out_data).astype(np.uint16), + mask=np.stack(out_mask) + ) diff --git a/mapchete_eo/base.py b/mapchete_eo/base.py index 7f611880..dba335fa 100644 --- a/mapchete_eo/base.py +++ b/mapchete_eo/base.py @@ -44,6 +44,9 @@ class BaseDriverConfig(BaseModel): + """ + Configuration for mapchete-eo drivers. + """ format: str source: Sequence[Source] time: Optional[Union[TimeRange, List[TimeRange]]] = None @@ -114,6 +117,9 @@ def __init__( @cached_property def products(self) -> IndexedFeatures[EOProductProtocol]: + """ + Indexed products. + """ # during task graph processing, the products have to be fetched as preprocessing task results if self._products is None: # pragma: no cover return IndexedFeatures( @@ -158,11 +164,7 @@ def read( **kwargs, ) -> xr.Dataset: """ - Read reprojected & resampled input data. - - Returns - ------- - data : xarray.Dataset + Read input data into an xarray.Dataset. """ return products_to_xarray( products=self.filter_products( @@ -201,6 +203,9 @@ def read_np_array( raise_empty: bool = True, **kwargs, ) -> ma.MaskedArray: + """ + Read input data as a MaskedArray. + """ return products_to_np_array( products=self.filter_products( start_time=start_time, @@ -286,6 +291,27 @@ def read_levelled_np_array( raise_empty: bool = True, **kwargs, ) -> ma.MaskedArray: + """ + Read levelled data (cubes with depth) as a MaskedArray. + + Args: + target_height: Target stack height. + assets: List of asset names. + eo_bands: List of EO bands. + start_time: Start time. + end_time: End time. + timestamps: List of timestamps. + time_pattern: Time pattern. + resampling: Resampling method. + nodatavals: Nodata values. + merge_products_by: Property to merge by. + merge_method: Merge method. + sort: Sorting configuration. + raise_empty: Raise error if no data found. + + Returns: + ma.MaskedArray: Output data array. + """ return read_levelled_cube_to_np_array( products=self.filter_products( start_time=start_time, @@ -317,6 +343,19 @@ def read_masks( nodatavals: NodataVals = None, **kwargs, ): + """ + Read product masks. + + Args: + start_time: Start time. + end_time: End time. + timestamps: List of timestamps. + time_pattern: Time pattern. + nodatavals: Nodata values. + + Returns: + ma.MaskedArray: Mask data. + """ from mapchete_eo.platforms.sentinel2.masks import read_masks return read_masks( @@ -423,6 +462,9 @@ def get_read_mask(self) -> np.ndarray: class InputData(base.InputData): + """ + Main driver class used by mapchete to handle input data discovery and indexing. + """ default_preprocessing_task: Callable = staticmethod(EOProduct.from_stac_item) driver_config_model: Type[BaseDriverConfig] = BaseDriverConfig params: BaseDriverConfig diff --git a/mapchete_eo/image_operations/compositing.py b/mapchete_eo/image_operations/compositing.py index 9cec1a4b..e70b713c 100644 --- a/mapchete_eo/image_operations/compositing.py +++ b/mapchete_eo/image_operations/compositing.py @@ -153,6 +153,18 @@ def overlay(bg: np.ndarray, fg: np.ndarray, opacity: float = 1) -> ma.MaskedArra def composite( method: str, bg: np.ndarray, fg: np.ndarray, opacity: float = 1 ) -> ma.MaskedArray: + """ + Composite two image arrays using a named blending method. + + Args: + method: Blending method name (e.g., 'multiply', 'screen'). + bg: Background image array (channels-first). + fg: Foreground image array (channels-first). + opacity: Opacity of the foreground layer (0-1). + + Returns: + ma.MaskedArray: Blended RGBA result. + """ return METHODS[method](bg, fg, opacity) diff --git a/mapchete_eo/platforms/sentinel2/driver.py b/mapchete_eo/platforms/sentinel2/driver.py index 8d84c341..79c1b661 100644 --- a/mapchete_eo/platforms/sentinel2/driver.py +++ b/mapchete_eo/platforms/sentinel2/driver.py @@ -17,6 +17,9 @@ class Sentinel2Cube(base.EODataCube): + """ + Sentinel-2 data cube for Mapchete. + """ # Sentinel-2 driver specific default values: default_read_merge_method: MergeMethod = MergeMethod.average default_read_merge_products_by: Optional[str] = "s2:datastrip_id" @@ -29,7 +32,7 @@ class Sentinel2Cube(base.EODataCube): class InputData(base.InputData): """ - Main driver class used by mapchete. + Sentinel-2 driver for Mapchete. """ # Sentinel-2 driver specific parameters: diff --git a/mapchete_eo/platforms/sentinel2/masks.py b/mapchete_eo/platforms/sentinel2/masks.py index 6aee5d3e..0357fb0f 100644 --- a/mapchete_eo/platforms/sentinel2/masks.py +++ b/mapchete_eo/platforms/sentinel2/masks.py @@ -61,7 +61,9 @@ def masks_to_xarray( raise_empty: bool = True, product_read_kwargs: dict = {}, ) -> xr.Dataset: - """Read grid window of EOProducts and merge into a 4D xarray.""" + """ + Read masks of products and merge into an xarray.Dataset. + """ data_vars = [ s for s in generate_slice_masks_dataarrays( @@ -307,7 +309,9 @@ def product_masks_to_slices( group_by_property: Optional[str] = None, sort: Optional[SortMethodConfig] = None, ) -> List[Slice]: - """Group products per given property into Slice objects and optionally sort slices.""" + """ + Group products by a property into Slices and optionally sort. + """ if group_by_property: grouped = defaultdict(list) for product in products: diff --git a/mapchete_eo/platforms/sentinel2/preprocessing_tasks.py b/mapchete_eo/platforms/sentinel2/preprocessing_tasks.py index 6ade0028..15735f87 100644 --- a/mapchete_eo/platforms/sentinel2/preprocessing_tasks.py +++ b/mapchete_eo/platforms/sentinel2/preprocessing_tasks.py @@ -19,7 +19,10 @@ def parse_s2_product( cache_config: Optional[CacheConfig] = None, cache_all: bool = False, ) -> Union[S2Product, CorruptedProductMetadata]: - # use mapper from source if applickable + """ + Parse a Sentinel-2 STAC Item into an S2Product. + """ + # use mapper from source if applicable source: Union[Sentinel2Source, None] = item.properties.pop( "mapchete_eo:source", None ) diff --git a/mapchete_eo/platforms/sentinel2/product.py b/mapchete_eo/platforms/sentinel2/product.py index d85a4224..6c149af1 100644 --- a/mapchete_eo/platforms/sentinel2/product.py +++ b/mapchete_eo/platforms/sentinel2/product.py @@ -143,6 +143,9 @@ def get_brdf_grid(self, band: L2ABand): class S2Product(EOProduct, EOProductProtocol): + """ + Sentinel-2 specific EOProduct implementation. + """ _item_dict: Optional[dict] = None cache: Optional[Cache] = None _scl_cache: Dict[GridProtocol, np.ndarray] @@ -245,6 +248,9 @@ def read_np_array( read_mask: Optional[np.ndarray] = None, **kwargs, ) -> ma.MaskedArray: + """ + Read Sentinel-2 assets into a MaskedArray with masks and BRDF. + """ assets = assets or [] eo_bands = eo_bands or [] apply_offset = apply_offset and not self.metadata.boa_offset_applied @@ -451,7 +457,9 @@ def read_scl( grid: Union[GridProtocol, Resolution] = Resolution["20m"], cached_read: bool = False, ) -> ReferencedRaster: - """Return SCL mask.""" + """ + Read Scene Classification Layer mask. + """ grid = ( self.metadata.grid(grid) if isinstance(grid, Resolution) @@ -519,7 +527,9 @@ def get_mask( mask_config: MaskConfig = MaskConfig(), target_mask: Optional[np.ndarray] = None, ) -> ReferencedRaster: - """Merge masks into one 2D array.""" + """ + Merge all configured masks into one. + """ grid = ( self.metadata.grid(grid) if isinstance(grid, Resolution) diff --git a/mapchete_eo/product.py b/mapchete_eo/product.py index 32392c0c..9dce9232 100644 --- a/mapchete_eo/product.py +++ b/mapchete_eo/product.py @@ -26,7 +26,9 @@ class EOProduct(EOProductProtocol): - """Wrapper class around a Item which provides read functions.""" + """ + Wrapper class around a STAC Item which provides data reading capabilities. + """ id: str default_dtype: DTypeLike = np.uint16 @@ -70,7 +72,22 @@ def read( raise_empty: bool = True, **kwargs, ) -> xr.Dataset: - """Read bands and assets into xarray.""" + """ + Read bands and assets into an xarray.Dataset. + + Args: + assets: List of asset names. + eo_bands: List of EO band names. + grid: Target grid protocol. + resampling: Resampling algorithm. + nodatavals: Custom nodata values. + x_axis_name: Name of X axis in output. + y_axis_name: Name of Y axis in output. + raise_empty: Raise exception if no data is found. + + Returns: + xr.Dataset: Dataset with assets as data variables. + """ # developer info: all fancy stuff for special platforms like Sentinel-2 # should be implemented in the respective read_np_array() methods which get # called by this method. No need to apply masks etc. here too. @@ -121,6 +138,21 @@ def read_np_array( apply_offset: bool = True, **kwargs, ) -> ma.MaskedArray: + """ + Read assets or EO bands into a MaskedArray. + + Args: + assets: List of asset names. + eo_bands: List of EO band names. + grid: Target grid. + resampling: Resampling method. + nodatavals: Nodata values. + raise_empty: Raise if empty. + apply_offset: Apply offset/scale metadata if present. + + Returns: + ma.MaskedArray: Output array. + """ assets = assets or [] eo_bands = eo_bands or [] bands = assets or eo_bands @@ -182,7 +214,15 @@ def eo_bands_to_band_locations( role: Literal["data", "reflectance", "visual"] = "data", ) -> List[BandLocation]: """ - Find out location (asset and band index) of EO band. + Map EO band names to asset locations. + + Args: + item: STAC Item. + eo_bands: List of common band names. + role: Functional role of the assets. + + Returns: + List[BandLocation]: List of location objects. """ return [find_eo_band(item, eo_band, role=role) for eo_band in eo_bands] diff --git a/mapchete_eo/search/base.py b/mapchete_eo/search/base.py index 782ef996..9d8dbf2c 100644 --- a/mapchete_eo/search/base.py +++ b/mapchete_eo/search/base.py @@ -50,7 +50,7 @@ def save_json(dest: MPathLike, json_dict: dict, *args, **kwargs) -> None: class CollectionSearcher(ABC): """ - This class serves as a bridge between an Archive and a catalog implementation. + Bridge between a Source and a catalog implementation. """ config_cls: Type[BaseModel] @@ -129,7 +129,29 @@ def write_static_catalog( stac_io: DefaultStacIO = FSSpecStacIO(), progress_callback: Optional[Callable] = None, ) -> MPath: - """Dump static version of current items.""" + """ + Export a static STAC catalog from the search results. + + Args: + output_path: Destination directory for the static catalog. + bounds: Spatial filter bounds. + area: Spatial filter geometry. + time: Temporal filter range. + search_kwargs: Additional search arguments. + name: Catalog name. + description: Catalog description. + assets: List of assets to download. + assets_dst_resolution: Sub-sampling resolution for assets. + assets_convert_profile: Output profile for assets (e.g. for COG conversion). + copy_metadata: Whether to copy sidecar metadata files. + metadata_parser_classes: Custom parser classes for metadata. + overwrite: Overwrite existing files. + stac_io: Custom STAC IO implementation. + progress_callback: Optional function for progress reporting. + + Returns: + MPath: Path to the generated catalog.json. + """ output_path = MPath.from_inp(output_path) assets = assets or [] # initialize catalog diff --git a/mapchete_eo/search/stac_search.py b/mapchete_eo/search/stac_search.py index 8fd144a4..e6676237 100644 --- a/mapchete_eo/search/stac_search.py +++ b/mapchete_eo/search/stac_search.py @@ -21,6 +21,9 @@ class STACSearchCollection(StaticCollectionWriterMixin, CollectionSearcher): + """ + Search implementation for STAC APIs. + """ collection: str config_cls = StacSearchConfig @@ -206,6 +209,9 @@ def _search( class SpatialSearchChunks: + """ + Split spatial search areas into smaller chunks for large queries. + """ bounds: Bounds area: BaseGeometry search_kw: str diff --git a/mapchete_eo/search/stac_static.py b/mapchete_eo/search/stac_static.py index 9e020ea8..0f9ef322 100644 --- a/mapchete_eo/search/stac_static.py +++ b/mapchete_eo/search/stac_static.py @@ -29,6 +29,9 @@ class STACStaticCollection(StaticCollectionWriterMixin, CollectionSearcher): + """ + Search implementation for static STAC collections. + """ config_cls = StacStaticConfig @cached_property diff --git a/mapchete_eo/search/utm_search.py b/mapchete_eo/search/utm_search.py index 46e16533..0549a195 100644 --- a/mapchete_eo/search/utm_search.py +++ b/mapchete_eo/search/utm_search.py @@ -28,6 +28,9 @@ class UTMSearchCatalog(StaticCollectionWriterMixin, CollectionSearcher): + """ + Search implementation for UTM-grid based catalogs (e.g. Sentinel-2 on AWS). + """ config_cls = UTMSearchConfig @cached_property diff --git a/mapchete_eo/sort.py b/mapchete_eo/sort.py index 8b5e30ad..cba9c7ea 100644 --- a/mapchete_eo/sort.py +++ b/mapchete_eo/sort.py @@ -22,9 +22,7 @@ def sort_objects_by_target_date( **kwargs, ) -> List[DateTimeProtocol]: """ - Return sorted list of objects according to their distance to the target_date. - - Default for target date is the middle between the objects start date and end date. + Sort objects by their distance to a target date. """ if len(objects) == 0: return objects diff --git a/mapchete_eo/source.py b/mapchete_eo/source.py index 9c3c8464..1b40d9e2 100644 --- a/mapchete_eo/source.py +++ b/mapchete_eo/source.py @@ -17,7 +17,9 @@ class Source(BaseModel): - """All information required to consume EO products.""" + """ + All information required to consume EO products. + """ collection: str catalog_crs: Optional[CRSLike] = mapchete_eo_settings.default_catalog_crs diff --git a/mapchete_eo/time.py b/mapchete_eo/time.py index 8d2b391f..152bdb1c 100644 --- a/mapchete_eo/time.py +++ b/mapchete_eo/time.py @@ -9,7 +9,9 @@ def to_datetime(t: DateTimeLike, append_time="min") -> datetime.datetime: - """Convert input into datetime object.""" + """ + Convert input into datetime object. + """ if isinstance(t, datetime.datetime): return t elif isinstance(t, datetime.date): @@ -22,7 +24,9 @@ def time_ranges_intersect( t1: Tuple[DateTimeLike, DateTimeLike], t2: Tuple[DateTimeLike, DateTimeLike], ) -> bool: - """Check if two time ranges intersect.""" + """ + Check if two time ranges intersect. + """ t1_start = to_datetime(t1[0], "min").replace(tzinfo=None) t1_end = to_datetime(t1[1], "max").replace(tzinfo=None) t2_start = to_datetime(t2[0], "min").replace(tzinfo=None) @@ -31,7 +35,9 @@ def time_ranges_intersect( def timedelta(date: DateTimeLike, target: DateTimeLike, seconds: bool = True): - """Return difference between two time stamps.""" + """ + Return difference between two time stamps in seconds or days. + """ delta = to_datetime(date) - to_datetime(target) if seconds: return abs(delta.total_seconds()) @@ -43,6 +49,9 @@ def day_range( start_date: Union[datetime.datetime, datetime.date], end_date: Union[datetime.datetime, datetime.date], ) -> List[datetime.date]: + """ + Return a list of dates between start and end. + """ start_date = ( start_date.date() if isinstance(start_date, datetime.datetime) else start_date ) diff --git a/mapchete_eo/types.py b/mapchete_eo/types.py index 3bd7325d..4a640262 100644 --- a/mapchete_eo/types.py +++ b/mapchete_eo/types.py @@ -10,8 +10,9 @@ class GeodataType(str, Enum): - vector = "vector" - raster = "raster" + """ + Type of geodata (vector or raster). + """ class MergeMethod(str, Enum): @@ -42,12 +43,14 @@ class BandLocation: roles: List[str] = field(default_factory=list) eo_band_name: Optional[str] = None - @staticmethod def from_asset( asset: Asset, name: str, band_index: PositiveInt, ) -> BandLocation: + """ + Extract band location info from STAC Asset. + """ try: bands_info = asset.extra_fields.get( "eo:bands", asset.extra_fields.get("bands", []) From e8dfe0fffafcd8af1aacb90e4e41425ed5cca3fb Mon Sep 17 00:00:00 2001 From: Scartography Date: Fri, 9 Jan 2026 14:02:06 +0100 Subject: [PATCH 2/6] merge curreent main into init docs commit --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 1dae2d6b..6daab4ae 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ build/ .coverage .coverage.* dist/ +docs/build/html *.egg-info .eggs examples/sentinel-2*/ From 124eb1b5d2b4337734772ff55c57ca1f370a8d3f Mon Sep 17 00:00:00 2001 From: Scartography Date: Fri, 9 Jan 2026 14:03:27 +0100 Subject: [PATCH 3/6] do not push .venv --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 6daab4ae..70b19631 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,4 @@ __pycache__ .pytest* .ruff_cache .vscode/ +.venv \ No newline at end of file From 8105b403870f8691e3b1bbd0554b0afb51262b27 Mon Sep 17 00:00:00 2001 From: Scartography Date: Fri, 9 Jan 2026 14:04:29 +0100 Subject: [PATCH 4/6] lint this version --- examples/ndvi_process.py | 13 +++++-------- examples/temporal_mean_process.py | 11 +++++------ mapchete_eo/base.py | 2 ++ mapchete_eo/platforms/sentinel2/driver.py | 1 + mapchete_eo/platforms/sentinel2/product.py | 3 ++- mapchete_eo/search/stac_search.py | 2 ++ mapchete_eo/search/stac_static.py | 1 + mapchete_eo/search/utm_search.py | 1 + 8 files changed, 19 insertions(+), 15 deletions(-) diff --git a/examples/ndvi_process.py b/examples/ndvi_process.py index 701e6181..1ba8ccb9 100644 --- a/examples/ndvi_process.py +++ b/examples/ndvi_process.py @@ -18,7 +18,7 @@ def execute( Calculate NDVI (Normalized Difference Vegetation Index). """ logger.debug("Reading Sentinel-2 NIR and Red bands.") - + # Read the first available cloud-free pixel for NIR and Red # (Simplified for example purposes) data = element84_sentinel2.read_np_array( @@ -26,19 +26,16 @@ def execute( resampling=Resampling[resampling], nodatavals=nodata, ) - + red = data[0].astype(float) nir = data[1].astype(float) - + # Calculate NDVI: (NIR - Red) / (NIR + Red) with np.errstate(divide="ignore", invalid="ignore"): ndvi = (nir - red) / (nir + red) ndvi[np.isnan(ndvi)] = nodata - + # NDVI is typically in range [-1, 1]. # For visualization, we could scale it to 0-255 or just return the float array. # Here we return it as a single-band float32 array. - return ma.masked_array( - data=ndvi.astype(np.float32), - mask=data.mask[0] - ) + return ma.masked_array(data=ndvi.astype(np.float32), mask=data.mask[0]) diff --git a/examples/temporal_mean_process.py b/examples/temporal_mean_process.py index 73bb27ed..1c1933a0 100644 --- a/examples/temporal_mean_process.py +++ b/examples/temporal_mean_process.py @@ -20,18 +20,18 @@ def execute( Create a temporal mean composite of cloud-free pixels. """ logger.debug("Reading Sentinel-2 time series.") - + # Read all available products into an xarray dataset ds = element84_sentinel2.read( assets=assets, resampling=Resampling[resampling], nodatavals=nodata, ) - + # Calculate mean over the time dimension # (Assuming xarray handle mask/nodata correctly via _FillValue) mean_composite = ds.mean(dim="time", skipna=True) - + # Convert back to numpy masked array # This is a simplified conversion for the example out_data = [] @@ -40,8 +40,7 @@ def execute( arr = mean_composite[asset].values out_data.append(arr) out_mask.append(np.isnan(arr)) - + return ma.masked_array( - data=np.stack(out_data).astype(np.uint16), - mask=np.stack(out_mask) + data=np.stack(out_data).astype(np.uint16), mask=np.stack(out_mask) ) diff --git a/mapchete_eo/base.py b/mapchete_eo/base.py index dba335fa..eb9bdec4 100644 --- a/mapchete_eo/base.py +++ b/mapchete_eo/base.py @@ -47,6 +47,7 @@ class BaseDriverConfig(BaseModel): """ Configuration for mapchete-eo drivers. """ + format: str source: Sequence[Source] time: Optional[Union[TimeRange, List[TimeRange]]] = None @@ -465,6 +466,7 @@ class InputData(base.InputData): """ Main driver class used by mapchete to handle input data discovery and indexing. """ + default_preprocessing_task: Callable = staticmethod(EOProduct.from_stac_item) driver_config_model: Type[BaseDriverConfig] = BaseDriverConfig params: BaseDriverConfig diff --git a/mapchete_eo/platforms/sentinel2/driver.py b/mapchete_eo/platforms/sentinel2/driver.py index 79c1b661..6a576dc6 100644 --- a/mapchete_eo/platforms/sentinel2/driver.py +++ b/mapchete_eo/platforms/sentinel2/driver.py @@ -20,6 +20,7 @@ class Sentinel2Cube(base.EODataCube): """ Sentinel-2 data cube for Mapchete. """ + # Sentinel-2 driver specific default values: default_read_merge_method: MergeMethod = MergeMethod.average default_read_merge_products_by: Optional[str] = "s2:datastrip_id" diff --git a/mapchete_eo/platforms/sentinel2/product.py b/mapchete_eo/platforms/sentinel2/product.py index 6c149af1..88ea3a84 100644 --- a/mapchete_eo/platforms/sentinel2/product.py +++ b/mapchete_eo/platforms/sentinel2/product.py @@ -146,6 +146,7 @@ class S2Product(EOProduct, EOProductProtocol): """ Sentinel-2 specific EOProduct implementation. """ + _item_dict: Optional[dict] = None cache: Optional[Cache] = None _scl_cache: Dict[GridProtocol, np.ndarray] @@ -250,7 +251,7 @@ def read_np_array( ) -> ma.MaskedArray: """ Read Sentinel-2 assets into a MaskedArray with masks and BRDF. - """ + """ assets = assets or [] eo_bands = eo_bands or [] apply_offset = apply_offset and not self.metadata.boa_offset_applied diff --git a/mapchete_eo/search/stac_search.py b/mapchete_eo/search/stac_search.py index e6676237..4cec37e9 100644 --- a/mapchete_eo/search/stac_search.py +++ b/mapchete_eo/search/stac_search.py @@ -24,6 +24,7 @@ class STACSearchCollection(StaticCollectionWriterMixin, CollectionSearcher): """ Search implementation for STAC APIs. """ + collection: str config_cls = StacSearchConfig @@ -212,6 +213,7 @@ class SpatialSearchChunks: """ Split spatial search areas into smaller chunks for large queries. """ + bounds: Bounds area: BaseGeometry search_kw: str diff --git a/mapchete_eo/search/stac_static.py b/mapchete_eo/search/stac_static.py index 0f9ef322..15b45f34 100644 --- a/mapchete_eo/search/stac_static.py +++ b/mapchete_eo/search/stac_static.py @@ -32,6 +32,7 @@ class STACStaticCollection(StaticCollectionWriterMixin, CollectionSearcher): """ Search implementation for static STAC collections. """ + config_cls = StacStaticConfig @cached_property diff --git a/mapchete_eo/search/utm_search.py b/mapchete_eo/search/utm_search.py index 0549a195..ca271a20 100644 --- a/mapchete_eo/search/utm_search.py +++ b/mapchete_eo/search/utm_search.py @@ -31,6 +31,7 @@ class UTMSearchCatalog(StaticCollectionWriterMixin, CollectionSearcher): """ Search implementation for UTM-grid based catalogs (e.g. Sentinel-2 on AWS). """ + config_cls = UTMSearchConfig @cached_property From d9339349ab3434bb849216491f37f5c0805234d2 Mon Sep 17 00:00:00 2001 From: Scartography Date: Fri, 9 Jan 2026 14:11:51 +0100 Subject: [PATCH 5/6] be nitpicky --- docs/source/conf.py | 7 ++ docs/source/generated/mapchete_eo.array.rst | 37 ++++++ docs/source/generated/mapchete_eo.cli.rst | 101 +++++++++++++++++ .../mapchete_eo.image_operations.rst | 77 +++++++++++++ docs/source/generated/mapchete_eo.io.rst | 61 ++++++++++ .../generated/mapchete_eo.processes.rst | 45 ++++++++ docs/source/generated/mapchete_eo.rst | 106 ++++++++++++++++++ docs/source/generated/mapchete_eo.search.rst | 61 ++++++++++ docs/source/generated/modules.rst | 7 ++ 9 files changed, 502 insertions(+) create mode 100644 docs/source/generated/mapchete_eo.array.rst create mode 100644 docs/source/generated/mapchete_eo.cli.rst create mode 100644 docs/source/generated/mapchete_eo.image_operations.rst create mode 100644 docs/source/generated/mapchete_eo.io.rst create mode 100644 docs/source/generated/mapchete_eo.processes.rst create mode 100644 docs/source/generated/mapchete_eo.rst create mode 100644 docs/source/generated/mapchete_eo.search.rst create mode 100644 docs/source/generated/modules.rst diff --git a/docs/source/conf.py b/docs/source/conf.py index 71a8bc53..1f6c770b 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -78,3 +78,10 @@ def get_metadata(): html_theme = "sphinx_rtd_theme" html_static_path = ["_static"] +# docs/source/conf.py + +# Tells Sphinx to be strict, but ignore these specific ambiguous targets +nitpicky = True +nitpick_ignore = [ + ('py:class', 'MergeMethod'), +] \ No newline at end of file diff --git a/docs/source/generated/mapchete_eo.array.rst b/docs/source/generated/mapchete_eo.array.rst new file mode 100644 index 00000000..712e9394 --- /dev/null +++ b/docs/source/generated/mapchete_eo.array.rst @@ -0,0 +1,37 @@ +mapchete\_eo.array package +========================== + +Submodules +---------- + +mapchete\_eo.array.buffer module +-------------------------------- + +.. automodule:: mapchete_eo.array.buffer + :members: + :show-inheritance: + :undoc-members: + +mapchete\_eo.array.color module +------------------------------- + +.. automodule:: mapchete_eo.array.color + :members: + :show-inheritance: + :undoc-members: + +mapchete\_eo.array.convert module +--------------------------------- + +.. automodule:: mapchete_eo.array.convert + :members: + :show-inheritance: + :undoc-members: + +Module contents +--------------- + +.. automodule:: mapchete_eo.array + :members: + :show-inheritance: + :undoc-members: diff --git a/docs/source/generated/mapchete_eo.cli.rst b/docs/source/generated/mapchete_eo.cli.rst new file mode 100644 index 00000000..0f11ad89 --- /dev/null +++ b/docs/source/generated/mapchete_eo.cli.rst @@ -0,0 +1,101 @@ +mapchete\_eo.cli package +======================== + +Submodules +---------- + +mapchete\_eo.cli.bounds module +------------------------------ + +.. automodule:: mapchete_eo.cli.bounds + :members: + :show-inheritance: + :undoc-members: + +mapchete\_eo.cli.options\_arguments module +------------------------------------------ + +.. automodule:: mapchete_eo.cli.options_arguments + :members: + :show-inheritance: + :undoc-members: + +mapchete\_eo.cli.s2\_brdf module +-------------------------------- + +.. automodule:: mapchete_eo.cli.s2_brdf + :members: + :show-inheritance: + :undoc-members: + +mapchete\_eo.cli.s2\_cat\_results module +---------------------------------------- + +.. automodule:: mapchete_eo.cli.s2_cat_results + :members: + :show-inheritance: + :undoc-members: + +mapchete\_eo.cli.s2\_find\_broken\_products module +-------------------------------------------------- + +.. automodule:: mapchete_eo.cli.s2_find_broken_products + :members: + :show-inheritance: + :undoc-members: + +mapchete\_eo.cli.s2\_jp2\_static\_catalog module +------------------------------------------------ + +.. automodule:: mapchete_eo.cli.s2_jp2_static_catalog + :members: + :show-inheritance: + :undoc-members: + +mapchete\_eo.cli.s2\_mask module +-------------------------------- + +.. automodule:: mapchete_eo.cli.s2_mask + :members: + :show-inheritance: + :undoc-members: + +mapchete\_eo.cli.s2\_mgrs module +-------------------------------- + +.. automodule:: mapchete_eo.cli.s2_mgrs + :members: + :show-inheritance: + :undoc-members: + +mapchete\_eo.cli.s2\_rgb module +------------------------------- + +.. automodule:: mapchete_eo.cli.s2_rgb + :members: + :show-inheritance: + :undoc-members: + +mapchete\_eo.cli.s2\_verify module +---------------------------------- + +.. automodule:: mapchete_eo.cli.s2_verify + :members: + :show-inheritance: + :undoc-members: + +mapchete\_eo.cli.static\_catalog module +--------------------------------------- + +.. automodule:: mapchete_eo.cli.static_catalog + :members: + :show-inheritance: + :undoc-members: + +Module contents +--------------- + +.. automodule:: mapchete_eo.cli + :members: + :show-inheritance: + :undoc-members: diff --git a/docs/source/generated/mapchete_eo.image_operations.rst b/docs/source/generated/mapchete_eo.image_operations.rst new file mode 100644 index 00000000..b804a5af --- /dev/null +++ b/docs/source/generated/mapchete_eo.image_operations.rst @@ -0,0 +1,77 @@ +mapchete\_eo.image\_operations package +====================================== + +Submodules +---------- + +mapchete\_eo.image\_operations.blend\_functions module +------------------------------------------------------ + +.. automodule:: mapchete_eo.image_operations.blend_functions + :members: + :show-inheritance: + :undoc-members: + +mapchete\_eo.image\_operations.color\_correction module +------------------------------------------------------- + +.. automodule:: mapchete_eo.image_operations.color_correction + :members: + :show-inheritance: + :undoc-members: + +mapchete\_eo.image\_operations.compositing module +------------------------------------------------- + +.. automodule:: mapchete_eo.image_operations.compositing + :members: + :show-inheritance: + :undoc-members: + +mapchete\_eo.image\_operations.dtype\_scale module +-------------------------------------------------- + +.. automodule:: mapchete_eo.image_operations.dtype_scale + :members: + :show-inheritance: + :undoc-members: + +mapchete\_eo.image\_operations.fillnodata module +------------------------------------------------ + +.. automodule:: mapchete_eo.image_operations.fillnodata + :members: + :show-inheritance: + :undoc-members: + +mapchete\_eo.image\_operations.filters module +--------------------------------------------- + +.. automodule:: mapchete_eo.image_operations.filters + :members: + :show-inheritance: + :undoc-members: + +mapchete\_eo.image\_operations.linear\_normalization module +----------------------------------------------------------- + +.. automodule:: mapchete_eo.image_operations.linear_normalization + :members: + :show-inheritance: + :undoc-members: + +mapchete\_eo.image\_operations.sigmoidal module +----------------------------------------------- + +.. automodule:: mapchete_eo.image_operations.sigmoidal + :members: + :show-inheritance: + :undoc-members: + +Module contents +--------------- + +.. automodule:: mapchete_eo.image_operations + :members: + :show-inheritance: + :undoc-members: diff --git a/docs/source/generated/mapchete_eo.io.rst b/docs/source/generated/mapchete_eo.io.rst new file mode 100644 index 00000000..feab1664 --- /dev/null +++ b/docs/source/generated/mapchete_eo.io.rst @@ -0,0 +1,61 @@ +mapchete\_eo.io package +======================= + +Submodules +---------- + +mapchete\_eo.io.assets module +----------------------------- + +.. automodule:: mapchete_eo.io.assets + :members: + :show-inheritance: + :undoc-members: + +mapchete\_eo.io.items module +---------------------------- + +.. automodule:: mapchete_eo.io.items + :members: + :show-inheritance: + :undoc-members: + +mapchete\_eo.io.levelled\_cubes module +-------------------------------------- + +.. automodule:: mapchete_eo.io.levelled_cubes + :members: + :show-inheritance: + :undoc-members: + +mapchete\_eo.io.path module +--------------------------- + +.. automodule:: mapchete_eo.io.path + :members: + :show-inheritance: + :undoc-members: + +mapchete\_eo.io.products module +------------------------------- + +.. automodule:: mapchete_eo.io.products + :members: + :show-inheritance: + :undoc-members: + +mapchete\_eo.io.profiles module +------------------------------- + +.. automodule:: mapchete_eo.io.profiles + :members: + :show-inheritance: + :undoc-members: + +Module contents +--------------- + +.. automodule:: mapchete_eo.io + :members: + :show-inheritance: + :undoc-members: diff --git a/docs/source/generated/mapchete_eo.processes.rst b/docs/source/generated/mapchete_eo.processes.rst new file mode 100644 index 00000000..3cb6ecbc --- /dev/null +++ b/docs/source/generated/mapchete_eo.processes.rst @@ -0,0 +1,45 @@ +mapchete\_eo.processes package +============================== + +Submodules +---------- + +mapchete\_eo.processes.config module +------------------------------------ + +.. automodule:: mapchete_eo.processes.config + :members: + :show-inheritance: + :undoc-members: + +mapchete\_eo.processes.dtype\_scale module +------------------------------------------ + +.. automodule:: mapchete_eo.processes.dtype_scale + :members: + :show-inheritance: + :undoc-members: + +mapchete\_eo.processes.eo\_to\_xarray module +-------------------------------------------- + +.. automodule:: mapchete_eo.processes.eo_to_xarray + :members: + :show-inheritance: + :undoc-members: + +mapchete\_eo.processes.merge\_rasters module +-------------------------------------------- + +.. automodule:: mapchete_eo.processes.merge_rasters + :members: + :show-inheritance: + :undoc-members: + +Module contents +--------------- + +.. automodule:: mapchete_eo.processes + :members: + :show-inheritance: + :undoc-members: diff --git a/docs/source/generated/mapchete_eo.rst b/docs/source/generated/mapchete_eo.rst new file mode 100644 index 00000000..df6a704b --- /dev/null +++ b/docs/source/generated/mapchete_eo.rst @@ -0,0 +1,106 @@ +mapchete\_eo package +==================== + +Subpackages +----------- + +.. toctree:: + :maxdepth: 4 + + mapchete_eo.array + mapchete_eo.cli + mapchete_eo.image_operations + mapchete_eo.io + mapchete_eo.processes + mapchete_eo.search + +Submodules +---------- + +mapchete\_eo.base module +------------------------ + +.. automodule:: mapchete_eo.base + :members: + :show-inheritance: + :undoc-members: + +mapchete\_eo.eostac module +-------------------------- + +.. automodule:: mapchete_eo.eostac + :members: + :show-inheritance: + :undoc-members: + +mapchete\_eo.exceptions module +------------------------------ + +.. automodule:: mapchete_eo.exceptions + :members: + :show-inheritance: + :undoc-members: + +mapchete\_eo.product module +--------------------------- + +.. automodule:: mapchete_eo.product + :members: + :show-inheritance: + :undoc-members: + +mapchete\_eo.protocols module +----------------------------- + +.. automodule:: mapchete_eo.protocols + :members: + :show-inheritance: + :undoc-members: + +mapchete\_eo.settings module +---------------------------- + +.. automodule:: mapchete_eo.settings + :members: + :show-inheritance: + :undoc-members: + +mapchete\_eo.sort module +------------------------ + +.. automodule:: mapchete_eo.sort + :members: + :show-inheritance: + :undoc-members: + +mapchete\_eo.source module +-------------------------- + +.. automodule:: mapchete_eo.source + :members: + :show-inheritance: + :undoc-members: + +mapchete\_eo.time module +------------------------ + +.. automodule:: mapchete_eo.time + :members: + :show-inheritance: + :undoc-members: + +mapchete\_eo.types module +------------------------- + +.. automodule:: mapchete_eo.types + :members: + :show-inheritance: + :undoc-members: + +Module contents +--------------- + +.. automodule:: mapchete_eo + :members: + :show-inheritance: + :undoc-members: diff --git a/docs/source/generated/mapchete_eo.search.rst b/docs/source/generated/mapchete_eo.search.rst new file mode 100644 index 00000000..b61cea0c --- /dev/null +++ b/docs/source/generated/mapchete_eo.search.rst @@ -0,0 +1,61 @@ +mapchete\_eo.search package +=========================== + +Submodules +---------- + +mapchete\_eo.search.base module +------------------------------- + +.. automodule:: mapchete_eo.search.base + :members: + :show-inheritance: + :undoc-members: + +mapchete\_eo.search.config module +--------------------------------- + +.. automodule:: mapchete_eo.search.config + :members: + :show-inheritance: + :undoc-members: + +mapchete\_eo.search.s2\_mgrs module +----------------------------------- + +.. automodule:: mapchete_eo.search.s2_mgrs + :members: + :show-inheritance: + :undoc-members: + +mapchete\_eo.search.stac\_search module +--------------------------------------- + +.. automodule:: mapchete_eo.search.stac_search + :members: + :show-inheritance: + :undoc-members: + +mapchete\_eo.search.stac\_static module +--------------------------------------- + +.. automodule:: mapchete_eo.search.stac_static + :members: + :show-inheritance: + :undoc-members: + +mapchete\_eo.search.utm\_search module +-------------------------------------- + +.. automodule:: mapchete_eo.search.utm_search + :members: + :show-inheritance: + :undoc-members: + +Module contents +--------------- + +.. automodule:: mapchete_eo.search + :members: + :show-inheritance: + :undoc-members: diff --git a/docs/source/generated/modules.rst b/docs/source/generated/modules.rst new file mode 100644 index 00000000..76b29553 --- /dev/null +++ b/docs/source/generated/modules.rst @@ -0,0 +1,7 @@ +mapchete_eo +=========== + +.. toctree:: + :maxdepth: 4 + + mapchete_eo From 860cc32f6a812984544b665665b5acdcdefd1b25 Mon Sep 17 00:00:00 2001 From: Scartography Date: Fri, 9 Jan 2026 14:14:10 +0100 Subject: [PATCH 6/6] lint that one change --- docs/source/conf.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index 1f6c770b..9a2db7d2 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -83,5 +83,5 @@ def get_metadata(): # Tells Sphinx to be strict, but ignore these specific ambiguous targets nitpicky = True nitpick_ignore = [ - ('py:class', 'MergeMethod'), -] \ No newline at end of file + ("py:class", "MergeMethod"), +]