Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Re-structure modules in preparation for accessors #624

Merged
merged 3 commits into from
Nov 14, 2024
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
33 changes: 19 additions & 14 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ ci:
autoupdate_schedule: quarterly
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.3.0
rev: v5.0.0
hooks:
- id: check-yaml
- id: end-of-file-fixer
Expand All @@ -12,10 +12,14 @@ repos:
- id: check-merge-conflict
# Fix common spelling mistakes
- repo: https://github.com/codespell-project/codespell
rev: v2.2.1
rev: v2.3.0
hooks:
- id: codespell
args: [--ignore-words-list=alos, --ignore-regex=\bnin\b]
args: [
'--ignore-words-list', 'alos,inout,vor',
'--ignore-regex', '\bnin\b',
'--'
]
types_or: [python, rst, markdown]
files: ^(geoutils|doc|tests)/

Expand All @@ -27,23 +31,24 @@ repos:

# Format the code aggressively using black
- repo: https://github.com/psf/black
rev: 22.10.0
rev: 24.10.0
hooks:
- id: black
args: [--line-length=120]

# Lint the code using flake8
- repo: https://github.com/pycqa/flake8
rev: 3.9.2
rev: 7.1.1
hooks:
- id: flake8
args: [
--max-line-length=120,
--extend-ignore=E203, # flake8 disagrees with black, so this should be ignored.
'--max-line-length', '120', # we can write dicts however we want
'--extend-ignore', 'E203,B028', # flake8 disagrees with black, so this should be ignored.
'--'
]
additional_dependencies:
- flake8-comprehensions==3.1.0
- flake8-bugbear==21.3.2
- flake8-comprehensions
- flake8-bugbear
files: ^(geoutils|tests)
# Lint the code using mypy
- repo: https://github.com/pre-commit/mirrors-mypy
Expand All @@ -63,26 +68,26 @@ repos:
--disable-error-code=var-annotated,
--disable-error-code=no-any-return
]
additional_dependencies: [tokenize-rt==3.2.0, numpy==1.22]
additional_dependencies: [tokenize-rt==3.2.0, numpy==1.26]
files: ^(geoutils|tests)

# Sort imports using isort
- repo: https://github.com/PyCQA/isort
rev: 5.12.0
rev: 5.13.2
hooks:
- id: isort
args: [ "--profile", "black" ]

# Automatically upgrade syntax to a minimum version
- repo: https://github.com/asottile/pyupgrade
rev: v3.1.0
rev: v3.19.0
hooks:
- id: pyupgrade
args: [--py37-plus]

# Various formattings
- repo: https://github.com/pre-commit/pygrep-hooks
rev: v1.9.0
rev: v1.10.0
hooks:
# Single backticks should apparently not be used
- id: rst-backticks
Expand All @@ -101,7 +106,7 @@ repos:

# Add custom regex lints (see .relint.yml)
- repo: https://github.com/codingjoe/relint
rev: 2.0.0
rev: 3.3.1
hooks:
- id: relint
- repo: local
Expand Down
2 changes: 1 addition & 1 deletion doc/source/background.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ In details, those mean:

- **Reproducibility:** all code is version-controlled and release-based, to ensure consistency of dependent packages and works;

- **Open-source:** all code is accessible and re-usable to anyone in the community, for transparency and open governance.
- **Open-source:** all code is accessible and reusable to anyone in the community, for transparency and open governance.

```{note}
:class: margin
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
ma2 = rast2.read(masked=True)
ma_result = (1 + ma2) / (ma1_reproj)


# Equivalent of saving
# (requires to define a logical
# nodata for the data type)
Expand Down
2 changes: 1 addition & 1 deletion doc/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ def setup(app):
'to update your code see <a href="https://github.com/GlacioHack/geoutils/releases/tag/v0.1.0">here</a>. ⚠️'
"<br>Future changes will come with deprecation warnings! 🙂"
),
"show_toc_level": 3
"show_toc_level": 3,
# "logo_only": True,
# "icon_links": [
# {
Expand Down
2 changes: 1 addition & 1 deletion doc/source/core_array_funcs.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ matching georeferencing or shape, respectively.
These functions inherently support the casting of different {attr}`~geoutils.Raster.dtype` and values masked by {attr}`~geoutils.Raster.nodata` in the
{class}`~numpy.ma.MaskedArray`.

Below, we re-use the same example created in {ref}`core-py-ops`.
Below, we reuse the same example created in {ref}`core-py-ops`.

```{code-cell} ipython3
:tags: [hide-input, hide-output]
Expand Down
2 changes: 1 addition & 1 deletion doc/source/georeferencing.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ vect.get_footprint_projected(vect.crs).plot()
### Grid (only for rasters)

A raster's grid origin and resolution are defined by its geotransform attribute, {attr}`~geoutils.Raster.transform`.
Comined with the 2D shape of the data array {attr}`~geoutils.Raster.shape` (and independently of the number of
Combined with the 2D shape of the data array {attr}`~geoutils.Raster.shape` (and independently of the number of
bands {attr}`~geoutils.Raster.bands`), these two attributes define the georeferenced grid of a raster.

From it are derived the resolution {attr}`~geoutils.Raster.res`, and {attr}`~geoutils.Raster.height` and
Expand Down
2 changes: 2 additions & 0 deletions doc/source/sphinxext.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
"""Functions for documentation configuration only, importable by sphinx"""


# To reset resolution setting for each sphinx-gallery example
def reset_mpl(gallery_conf, fname):
# To get a good resolution for displayed figures
Expand Down
1 change: 1 addition & 0 deletions examples/analysis/array_numerics/numpy_interfacing.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

This example demonstrates NumPy interfacing with rasters on :class:`Rasters<geoutils.Raster>`. See :ref:`core-array-funcs` for more details.
"""

# %%
# We open a raster.

Expand Down
1 change: 1 addition & 0 deletions examples/analysis/array_numerics/python_arithmetic.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

This example demonstrates arithmetic operations using raster arithmetic on :class:`Rasters<geoutils.Raster>`. See :ref:`core-py-ops` for more details.
"""

# %%
# We open a raster

Expand Down
1 change: 1 addition & 0 deletions examples/analysis/geospatial/buffer_voronoi.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

This example demonstrates the metric buffering of a vector using :func:`~geoutils.Vector.buffer_metric` and :func:`~geoutils.Vector.buffer_without_overlap`.
"""

# %%
# We open an example vector

Expand Down
1 change: 1 addition & 0 deletions examples/analysis/geospatial/proximity_metric.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

This example demonstrates the calculation of proximity distances to a raster or vector using :func:`~geoutils.Raster.proximity`.
"""

# %%
# We open an example raster, and a vector for which we select a single feature

Expand Down
1 change: 1 addition & 0 deletions examples/analysis/point_extraction/interpolation.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

This example demonstrates the 2D interpolation of raster values to points using :func:`~geoutils.Raster.interp_points`.
"""

# %%
# We open an example raster, a digital elevation model in South America.

Expand Down
1 change: 1 addition & 0 deletions examples/analysis/point_extraction/reduction.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

This example demonstrates the reduction of windowed raster values around a point using :func:`~geoutils.Raster.value_at_coords`.
"""

# %%
# We open an example raster, a digital elevation model in South America.

Expand Down
1 change: 1 addition & 0 deletions examples/handling/georeferencing/crop_raster.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

This example demonstrates the cropping of a raster using :func:`geoutils.Raster.crop`.
"""

# %%
# We open a raster and vector, and subset the latter.

Expand Down
1 change: 1 addition & 0 deletions examples/handling/georeferencing/crop_vector.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

This example demonstrates the cropping of a vector using :func:`geoutils.Vector.crop`.
"""

# %%
# We open a raster and vector.

Expand Down
1 change: 1 addition & 0 deletions examples/handling/georeferencing/reproj_raster.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

This example demonstrates the reprojection of a raster using :func:`geoutils.Raster.reproject`.
"""

# %%
# We open two example rasters.

Expand Down
1 change: 1 addition & 0 deletions examples/handling/georeferencing/reproj_vector.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

This example demonstrates the reprojection of a vector using :func:`geoutils.Vector.reproject`.
"""

# %%
# We open a raster and vector.

Expand Down
1 change: 1 addition & 0 deletions examples/handling/interface/create_mask.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

This example demonstrates the creation of a mask from a vector using :func:`geoutils.Vector.create_mask`.
"""

# %%
# We open a raster and vector.

Expand Down
1 change: 1 addition & 0 deletions examples/handling/interface/polygonize.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

This example demonstrates the polygonizing of a raster using :func:`geoutils.Raster.polygonize` and :func:`geoutils.Mask.polygonize`.
"""

# %%
# We open a raster.

Expand Down
1 change: 1 addition & 0 deletions examples/handling/interface/rasterize.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

This example demonstrates the rasterizing of a vector using :func:`geoutils.Vector.rasterize`.
"""

# %%
# We open a raster and vector.

Expand Down
1 change: 1 addition & 0 deletions examples/handling/interface/topoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

This example demonstrates the conversion of a raster to point vector using :func:`geoutils.Raster.to_points`.
"""

# %%
# We open a raster.

Expand Down
1 change: 1 addition & 0 deletions geoutils/_config.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Setup of runtime-compile configuration of GeoUtils."""

from __future__ import annotations

import configparser
Expand Down
1 change: 1 addition & 0 deletions geoutils/_typing.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Typing aliases for internal use."""

from __future__ import annotations

import sys
Expand Down
1 change: 1 addition & 0 deletions geoutils/examples.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Utility functions to download and find example data."""

import os
import tarfile
import tempfile
Expand Down
5 changes: 5 additions & 0 deletions geoutils/interface/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from geoutils.interface.distance import * # noqa
from geoutils.interface.gridding import * # noqa
from geoutils.interface.interpolate import * # noqa
from geoutils.interface.raster_point import * # noqa
from geoutils.interface.raster_vector import * # noqa
88 changes: 88 additions & 0 deletions geoutils/interface/distance.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
"""Functionalities related to distance operations."""

from __future__ import annotations

import warnings
from typing import Literal

import geopandas as gpd
import numpy as np
from scipy.ndimage import distance_transform_edt

import geoutils as gu
from geoutils._typing import NDArrayNum


def _proximity_from_vector_or_raster(
raster: gu.Raster,
vector: gu.Vector | None = None,
target_values: list[float] | None = None,
geometry_type: str = "boundary",
in_or_out: Literal["in"] | Literal["out"] | Literal["both"] = "both",
distance_unit: Literal["pixel"] | Literal["georeferenced"] = "georeferenced",
) -> NDArrayNum:
"""
(This function is defined here as mostly raster-based, but used in a class method for both Raster and Vector)
Proximity to a Raster's target values if no Vector is provided, otherwise to a Vector's geometry type
rasterized on the Raster.

:param raster: Raster to burn the proximity grid on.
:param vector: Vector for which to compute the proximity to geometry,
if not provided computed on the Raster target pixels.
:param target_values: (Only with a Raster) List of target values to use for the proximity,
defaults to all non-zero values.
:param geometry_type: (Only with a Vector) Type of geometry to use for the proximity, defaults to 'boundary'.
:param in_or_out: (Only with a Vector) Compute proximity only 'in' or 'out'-side the geometry, or 'both'.
:param distance_unit: Distance unit, either 'georeferenced' or 'pixel'.
"""

# 1/ First, if there is a vector input, we rasterize the geometry type
# (works with .boundary that is a LineString (.exterior exists, but is a LinearRing)
if vector is not None:

# TODO: Only when using centroid... Maybe we should leave this operation to the user anyway?
warnings.filterwarnings("ignore", message="Geometry is in a geographic CRS.*")

# We create a geodataframe with the geometry type
boundary_shp = gpd.GeoDataFrame(geometry=vector.ds.__getattr__(geometry_type), crs=vector.crs)
# We mask the pixels that make up the geometry type
mask_boundary = gu.Vector(boundary_shp).create_mask(raster, as_array=True)

else:
# We mask target pixels
if target_values is not None:
mask_boundary = np.logical_or.reduce([raster.get_nanarray() == target_val for target_val in target_values])
# Otherwise, all non-zero values are considered targets
else:
mask_boundary = raster.get_nanarray().astype(bool)

# 2/ Now, we compute the distance matrix relative to the masked geometry type
if distance_unit.lower() == "georeferenced":
sampling: int | tuple[float | int, float | int] = raster.res
elif distance_unit.lower() == "pixel":
sampling = 1
else:
raise ValueError('Distance unit must be either "georeferenced" or "pixel".')

# If not all pixels are targets, then we compute the distance
non_targets = np.count_nonzero(mask_boundary)
if non_targets > 0:
proximity = distance_transform_edt(~mask_boundary, sampling=sampling)
# Otherwise, pass an array full of nodata
else:
proximity = np.ones(np.shape(mask_boundary)) * np.nan

# 3/ If there was a vector input, apply the in_and_out argument to optionally mask inside/outside
if vector is not None:
if in_or_out == "both":
pass
elif in_or_out in ["in", "out"]:
mask_polygon = gu.Vector(vector.ds).create_mask(raster, as_array=True)
if in_or_out == "in":
proximity[~mask_polygon] = 0
else:
proximity[mask_polygon] = 0
else:
raise ValueError('The type of proximity must be one of "in", "out" or "both".')

return proximity
2 changes: 1 addition & 1 deletion geoutils/pointcloud.py → geoutils/interface/gridding.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""Module for point cloud manipulation."""
"""Functionalities for gridding points (point cloud to raster)."""

import warnings
from typing import Literal
Expand Down
Loading
Loading