Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.8", "3.9", "3.10"]
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
steps:
- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }}
Expand Down
15 changes: 8 additions & 7 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ help:

venv: $(VIRTUAL_ENV)/timestamp

$(VIRTUAL_ENV)/timestamp: pyproject.toml setup.cfg
$(VIRTUAL_ENV)/timestamp: pyproject.toml
pip install --upgrade pip
pip install -e ".[dev,docs]"
ifneq ($(wildcard requirements/extra.txt),)
Expand All @@ -31,15 +31,16 @@ endif
touch $(VIRTUAL_ENV)/timestamp

format: venv
isort $(PROJECTNAME)
docformatter -i -r $(PROJECTNAME)
black $(PROJECTNAME)
ruff check $(PROJECTNAME) tests --fix

lint: venv
flake8 --show-source $(PROJECTNAME) tests
ruff check $(PROJECTNAME) tests

test: venv
pytest -v
pytest -v -m "not slow"

test-slow: venv
pytest -v -m "slow"

docs: venv
cd docs && sphinx-apidoc -o source/ ../$(PROJECTNAME) && make html
cd docs && sphinx-apidoc -o source/ ../$(PROJECTNAME) && make clean html
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
<p align="center">
<img src="docs/source/_static/GeoGrapher.png" alt="GeoGrapher Logo" width="70"><br>
</p>
<p align="center">
<a href="https://firstdonoharm.dev/version/3/0/cl-eco-mil.html">
<img src="https://img.shields.io/static/v1?label=Hippocratic%20License&message=HL3-CL-ECO-MIL&labelColor=5e2751&color=bc8c3d" alt="Hippocratic License">
</a>
</p>

# GeoGrapher

*GeoGrapher* is a Python library for building remote sensing
Expand All @@ -11,7 +20,7 @@ utility functions.

# Installation
This package has two external dependencies:
- Python 3.8 or newer.
- Python 3.9 or newer.
- The geopandas and rasterio libraries might depend on GDAL base C libraries.
See [https://geopandas.org/en/stable/getting_started/install.html#dependencies](https://geopandas.org/en/stable/getting_started/install.html#dependencies)
and [https://pypi.org/project/rasterio/](https://pypi.org/project/rasterio/)
Expand Down
Binary file added docs/source/_static/GeoGrapher.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion docs/source/_templates/custom-module-template.rst
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,4 @@
{{ item }}
{%- endfor %}
{% endif %}
{% endblock %}
{% endblock %}
2 changes: 1 addition & 1 deletion docs/source/advanced_cutting.rst
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ You can write a custom ``RasterFilterPredicate`` to do this::
target_assoc: Connector,
new_raster_dict: dict,
source_assoc: Connector,
cut_rasters: List[str],
cut_rasters: list[str],
) -> bool:

local_timestamp: str = rasters.loc[raster_name, 'local_timestamp']
Expand Down
2 changes: 1 addition & 1 deletion docs/source/basic_cutting.rst
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ cutouts around vector features from 10980 × 10980 Sentinel-2 tiles)::
source_data_dir=<SOURCE_DATA_DIR>,
target_data_dir=<TARGET_DATA_DIR>,
name=<OPTIONAL_NAME_FOR_SAVING>
new_raster_size: Optional[RasterSize]
new_raster_size: RasterSize | None
new_raster_size=512,
target_raster_count=2,
mode: "random")
Expand Down
2 changes: 1 addition & 1 deletion docs/source/cluster_rasters.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ train/validation split to avoid data leakage use the
.. code-block::

from geographer.utils.cluster_rasters import get_raster_clusters
clusters : List[Set[str]] = get_raster_clusters(
clusters : list[Set[str]] = get_raster_clusters(
connector=connector,
clusters_defined_by='rasters_that_share_vectors',
preclustering_method='y then x-axis'
Expand Down
43 changes: 22 additions & 21 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,17 @@
import os
import sys

sys.path.insert(0, os.path.abspath('./geographer'))
sys.path.insert(0, os.path.abspath("./geographer"))


# -- Project information -----------------------------------------------------

project = 'GeoGrapher'
copyright = 'Open Source TBD'
author = 'Rustam Antia'
project = "GeoGrapher"
copyright = "Open Source TBD"
author = "Rustam Antia"

# The full version, including alpha/beta/rc tags
release = '0.1.0'
release = "0.1.0"


# -- General configuration ---------------------------------------------------
Expand All @@ -32,19 +32,19 @@
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
'nbsphinx',
'nbsphinx_link',
'sphinx.ext.autodoc',
'sphinx.ext.autosummary',
'sphinx_autodoc_typehints',
'sphinxcontrib.autodoc_pydantic',
'sphinx.ext.napoleon',
'sphinx.ext.todo',
'sphinx.ext.viewcode',
"nbsphinx",
"nbsphinx_link",
"sphinx.ext.autodoc",
"sphinx.ext.autosummary",
"sphinx_autodoc_typehints",
"sphinxcontrib.autodoc_pydantic",
"sphinx.ext.napoleon",
"sphinx.ext.todo",
"sphinx.ext.viewcode",
]

# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
templates_path = ["_templates"]

# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
Expand All @@ -56,12 +56,12 @@
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'alabaster'
html_theme = 'furo'

# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = []
html_static_path = ["_static"]

# HTML settings
html_theme_options = {
Expand All @@ -73,22 +73,23 @@

# autodoc settings
autodoc_default_options = {
'inherited-members': 'pydantic.BaseModel,BaseModel',
"inherited-members": "pydantic.BaseModel,BaseModel",
}

autodoc_typehints = "description" # or "signature"

# autodoc_pydantic settings
autodoc_pydantic_config_members = False
autodoc_pydantic_model_show_config_member = False
autodoc_pydantic_model_show_config_summary = False
autodoc_pydantic_model_show_validator_summary = False
autodoc_pydantic_model_show_validator_members = False
autodoc_pydantic_model_show_field_summary = False
autodoc_pydantic_model_hide_paramlist = False # change?
autodoc_pydantic_model_hide_paramlist = False # change?
autodoc_pydantic_model_signature_prefix = "class"
autodoc_pydantic_model_show_json = False
autodoc_pydantic_settings_show_json = False


# todo settings
todo_include_todos = True

Expand All @@ -106,4 +107,4 @@
napoleon_use_rtype = True
napoleon_preprocess_types = False
napoleon_type_aliases = None
napoleon_attr_annotations = True
napoleon_attr_annotations = True
114 changes: 68 additions & 46 deletions docs/source/downloaders.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,35 @@ Downloading rasters

To download rasters for vector features use ``RasterDownloaderForVectors``.

By plugging in different ``DownloaderForSingleVector`` and ``Processor``
components it can interface with different sources of remote sensing rasters.
Currently, it can interface with the Copernicus Open Access Hub for Sentinel-2
rasters, and JAXA for ALOS DEM (digital elevation model) data, and can easily
be extended to other data sources by writing custom
``DownloaderForSingleSingleVector`` and ``Processor`` classes.
A ``RasterDownloaderForVectors`` requires components that implement the
abstract base classes ``DownloaderForSingleVector`` and ``Processor``.

- ``DownloaderForSingleVector`` defines how to search for and download
a raster for a single vector from a provider.
- ``Processor`` how to process the downloaded file into a GeoTiff raster.

Available implementations
+++++++++++++++++++++++++

Currently, there are two concrete implementations of ``DownloaderForSingleVector``:

- ``EodagDownloaderForSingleVector``: Based on
the excellent `"eodag" <EODAG_>`_ package, this implementation supports downloading
over 50 product types from more than 10 providers.
- ``JAXADownloaderForSingleVector``: Designed for downloading DEM (digital elevation model)
data from the `"JAXA ALOS" <JAXA_ALOS_>`_ mission.

Additionally, there are two concrete implementations of the ``Processor`` class:

- ``Sentinel2SAFEProcessor``: Processes Level-2A Sentinel-2 SAFE files.
- ``JAXADownloadProcessor``: Processes JAXA DEM data.

To use the ``RasterDownloaderForVectors`` for a new provider or product type
you only need to write custom implementations of ``DownloaderForSingleVector``
or ``Processor``.

.. _EODAG: https://eodag.readthedocs.io/en/stable/
.. _JAXA_ALOS: https://www.eorc.jaxa.jp/ALOS/en/index_e.htm

Example usage
+++++++++++++
Expand All @@ -19,54 +42,46 @@ Example usage:

from geographer.downloaders import (
RasterDownloaderForVectors,
SentinelDownloaderForSingleVector,
Sentinel2Processor
EodagDownloaderForSingleVector,
Sentinel2SAFEProcessor,
)
downloader_for_single_vector=SentinelDownloaderForSingleVector()
download_processor=Sentinel2Processor()
download_processor = Sentinel2SAFEProcessor()
downloader_for_single_vector = EodagDownloaderForSingleVector()
downloader = RasterDownloaderForVectors(
downloader_for_single_vector=downloader_for_single_vector,
download_processor=download_processor,
)

# Parameters needed by the EodagDownloaderForSingleVector.download method
downloader_params = {
"search_kwargs": { # Keyword arguments for the eodag search_all method
"provider": "cop_dataspace", # Download from copernicus dataspace
"productType": "S2_MSI_L2A", # Search for Sentinel-2 L2A products
"start": "2024-11-01",
"end": "2024-12-01",
},
"filter_online": True, # Filter out products that are not online
"sort_by": ("cloudCover", "ASC"), # Prioritize search results with less cloud cover
"suffix_to_remove": ".SAFE", # Will strip .SAFE from the stem of the tif file names
}
# Parameters needed by the Sentinel2SAFEProcessor
processor_params = {
"resolution": 10, # Extract all 10m resolution bands
"delete_safe": True, # Delete the SAFE file after extracting a .tif file
}

downloader.download(
connector=my_connector,
vector_names=optional_list_of_vector_names,
target_raster_count=2,
producttype='L2A',
max_percent_cloud_coverage=10,
resolution=10,
date=('NOW-10DAYS', 'NOW'),
area_relation='Contains'
downloader_params=downloader_params, # Only needed the first time downloader.download is called
processor_params=processor_params, # Only needed the first time downoader.download is called
)

The raster counts for all vector features are updated after every download,
so that unnecessary downloads and an imbalance in the dataset due to clustering
of nearby vector features are avoided.

You can supply default values for dataset/data source specific ``download``
arguments (e.g. ``producttype``, ``max_percent_cloud_coverage`` for the
``SentinelDownloaderForSingleVector``) in the
``RasterDownloaderForVectors``'s ``kwarg_defaults`` arguments dict,
so that one doesn't have to pass them by hand to the ``download`` method,
for example:

.. code-block:: python

downloader = RasterDownloaderForVectors(
download_dir=<DOWNLOAD_DIR>,
downloader_for_single_vector=SentinelDownloaderForSingleVector(),
download_processor=Sentinel2Processor(),
kwarg_defaults={
'max_percent_cloud_coverage' = 10,
'producttype': L2A,
'resolution': 10,
'date': ('NOW-10DAYS', 'NOW'),
'area_relation': 'Contains'})
downloader.download(
connector=my_connector,
vector_names=optional_list_of_vector_names,
target_raster_count=2)

Data sources
++++++++++++

Expand All @@ -77,15 +92,22 @@ to GeoTiffs.
Sentinel-2
~~~~~~~~~~

For *Sentinel-2* data, use the ``SentinelDownloaderForSingleVector``
to download rasters from the Copernicus Open Access Hub and the ``Sentinel2Processor``.
For *Sentinel-2* data, use the ``EodagDownloaderForSingleVector`` with
``"productType": "S2_MSI_L2A"`` together with the ``Sentinel2SAFEProcessor`` as above.
Tested with cop_dataspace. Expected to work with other archive_depth=2 providers
(creodias, onda, sara). If archive_depth differs, you'll need to adapt the processor.
Please submit the adapted ``RasterDownloadProcessor`` as a merge request :)

Sentinel-1
~~~~~~~~~~
Sources/providers supported by `eodag`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The ``EodagDownloaderForSingleVector`` will work with any sources/providers
`supported by eodag <EODAG_PROVIDERS_>`_. For ``"productType"``s other than
``"S2_MSI_L2A"`` with ``archive_depth`` 2, you will need to write a custom
``RasterDownloadProcessor``. Please submit your custom ``RasterDownloadProcessor``
as a merge request :)

The ``SentinelDownloaderForSingleVector`` should work with slight modifications
for downloading Sentinel-1 data from Copernicus Open Access Hub as well. Feel free to
submit a pull request for this feature.
.. _EODAG_PROVIDERS: https://eodag.readthedocs.io/en/stable/getting_started_guide/providers.html

JAXA DEM data
~~~~~~~~~~~~~
Expand Down
17 changes: 11 additions & 6 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
######################################
Welcome to GeoGrapher's documentation!
######################################
|

.. image:: _static/GeoGrapher.png
:width: 80px
:align: center

GeoGrapher Documentation
========================

**GeoGrapher** is a Python library for building and handling remote sensing
computer vision datasets assembled from vector features and rasters.
Expand All @@ -11,7 +16,7 @@ provides highly general and customizable dataset cutting functionality
as well as other utility functions.

User guide
==================
-----------

.. toctree::
:maxdepth: 1
Expand All @@ -28,15 +33,15 @@ User guide
glossary

API Reference
=============
-------------

.. toctree::
:maxdepth: 1

geographer <modules>

Indices and tables
==================
------------------

* :ref:`genindex`
* :ref:`modindex`
Expand Down
Loading