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
1 change: 1 addition & 0 deletions examples/benchmark.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
1bc8711 130.93s MacBook Pro (Retina, 15-inch, Mid 2014) 2.2GHz i7, 16GB RAM
2277962 80.68s MacBook Pro (Retina, 15-inch, Mid 2014) 2.2GHz i7, 16GB RAM
"""

import time

from rasterstats import zonal_stats
Expand Down
25 changes: 21 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ dependencies = [
progress = [
"tqdm"
]
docs = [
"numpydoc",
"sphinx",
"sphinx-rtd-theme",
]
test = [
"coverage",
"geopandas",
Expand All @@ -52,7 +57,7 @@ test = [
]
dev = [
"rasterstats[test]",
"numpydoc",
"ruff",
"twine",
]

Expand Down Expand Up @@ -81,6 +86,18 @@ version = {attr = "rasterstats._version.__version__"}
[tool.hatch.version]
path = "src/rasterstats/_version.py"

[tool.isort]
profile = "black"
known_first_party = ["rasterstats"]
[tool.ruff.lint]
select = [
"E", # pycodestyle
"F", # Pyflakes
"I", # isort
"RUF", # Ruff-specific rules
"UP", # pyupgrade
]
ignore = [
"RUF005", # Consider iterable unpacking instead of concatenation
]

[tool.ruff]
# TODO: files in docs/notebooks/ use old versions and are incompatible with modern tools
extend-exclude = ["*.ipynb"]
6 changes: 3 additions & 3 deletions src/rasterstats/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@

__all__ = [
"__version__",
"gen_zonal_stats",
"cli",
"gen_point_query",
"gen_zonal_stats",
"point_query",
"raster_stats",
"zonal_stats",
"point_query",
"cli",
]
5 changes: 3 additions & 2 deletions src/rasterstats/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,9 @@ def zonalstats(

The input arguments to zonalstats should be valid GeoJSON Features. (see cligj)

The output GeoJSON will be mostly unchanged but have additional properties per feature
describing the summary statistics (min, max, mean, etc.) of the underlying raster dataset.
The output GeoJSON will be mostly unchanged but have additional properties per
feature describing the summary statistics (min, max, mean, etc.) of the underlying
raster dataset.

The raster is specified by the required -r/--raster argument.

Expand Down
4 changes: 2 additions & 2 deletions src/rasterstats/io.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ def parse_feature(obj):
except (AssertionError, TypeError):
pass

raise ValueError("Can't parse %s as a geojson Feature object" % obj)
raise ValueError(f"Can't parse {obj} as a geojson Feature object")


def read_features(obj, layer=0):
Expand Down Expand Up @@ -302,7 +302,7 @@ def read(self, bounds=None, window=None, masked=False, boundless=True):
masked: boolean
return a masked numpy array, default: False
boundless: boolean
allow window/bounds that extend beyond the datasets extent, default: True
allow window/bounds that extend beyond the dataset's extent, default: True
partially or completely filled arrays will be returned as appropriate.

Returns
Expand Down
8 changes: 5 additions & 3 deletions src/rasterstats/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
def raster_stats(*args, **kwargs):
"""Deprecated. Use zonal_stats instead."""
warnings.warn(
"'raster_stats' is an alias to 'zonal_stats'" " and will disappear in 1.0",
"'raster_stats' is an alias to 'zonal_stats' and will disappear in 1.0",
DeprecationWarning,
)
return zonal_stats(*args, **kwargs)
Expand All @@ -43,7 +43,9 @@ def zonal_stats(*args, **kwargs):
if progress:
if tqdm is None:
raise ValueError(
"You specified progress=True, but tqdm is not installed in the environment. You can do pip install rasterstats[progress] to install tqdm!"
"You specified progress=True, but tqdm is not installed in "
"the environment. "
"You can do pip install rasterstats[progress] to install tqdm!"
)
stats = gen_zonal_stats(*args, **kwargs)
total = len(args[0])
Expand Down Expand Up @@ -140,7 +142,7 @@ def gen_zonal_stats(
Use with `prefix` to ensure unique and meaningful property names.

boundless: boolean
Allow features that extend beyond the raster datasets extent, default: True
Allow features that extend beyond the raster dataset's extent, default: True
Cells outside dataset extents are treated as nodata.

Returns
Expand Down
6 changes: 3 additions & 3 deletions src/rasterstats/point.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def point_window_unitxy(x, y, affine):
((row1, row2), (col1, col2)), (unitx, unity)
"""
fcol, frow = ~affine * (x, y)
r, c = int(round(frow)), int(round(fcol))
r, c = round(frow), round(fcol)

# The new source window for our 2x2 array
new_win = ((r - 1, r + 1), (c - 1, c + 1))
Expand Down Expand Up @@ -50,7 +50,7 @@ def bilinear(arr, x, y):
if hasattr(arr, "count") and arr.count() != 4:
# a masked array with at least one nodata
# fall back to nearest neighbor
val = arr[int(round(1 - y)), int(round(x))]
val = arr[round(1 - y), round(x)]
if val is masked:
return None
else:
Expand Down Expand Up @@ -158,7 +158,7 @@ def gen_point_query(
point query values appended as additional properties.

boundless: boolean
Allow features that extend beyond the raster datasets extent, default: True
Allow features that extend beyond the raster dataset's extent, default: True
Cells outside dataset extents are treated as nodata.

Returns
Expand Down
4 changes: 1 addition & 3 deletions src/rasterstats/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,7 @@ def check_stats(stats, categorical):
if x.startswith("percentile_"):
get_percentile(x)
elif x not in VALID_STATS:
raise ValueError(
"Stat `%s` not valid; " "must be one of \n %r" % (x, VALID_STATS)
)
raise ValueError(f"Stat {x!r} not valid; must be one of \n {VALID_STATS}")

run_count = False
if categorical or "majority" in stats or "minority" in stats or "unique" in stats:
Expand Down
1 change: 1 addition & 0 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

data_dir = Path(__file__).parent / "data"


def test_cli_feature():
raster = str(data_dir / "slope.tif")
vector = str(data_dir / "feature.geojson")
Expand Down
12 changes: 6 additions & 6 deletions tests/test_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
from shapely.geometry import shape

from rasterstats.io import ( # todo parse_feature
fiona_generator,
Raster,
boundless_array,
bounds_window,
fiona_generator,
read_featurecollection,
read_features,
rowcol,
Expand Down Expand Up @@ -47,7 +47,7 @@ def _test_read_features(indata):

def _test_read_features_single(indata):
# single (first target geom)
geom = shape(list(read_features(indata))[0]["geometry"])
geom = shape(next(iter(read_features(indata)))["geometry"])
assert geom.equals_exact(target_geoms[0], eps)


Expand Down Expand Up @@ -280,9 +280,9 @@ def test_Raster():
r2 = Raster(arr, affine, nodata, band=1).read(bounds)

with pytest.raises(ValueError):
r3 = Raster(arr, affine, nodata, band=1).read()
Raster(arr, affine, nodata, band=1).read()
with pytest.raises(ValueError):
r4 = Raster(arr, affine, nodata, band=1).read(bounds=1, window=1)
Raster(arr, affine, nodata, band=1).read(bounds=1, window=1)

# If the abstraction is correct, the arrays are equal
assert np.array_equal(r1.array, r2.array)
Expand All @@ -301,7 +301,7 @@ def test_Raster_boundless_disabled():

# rasterio src fails outside extent
with pytest.raises(ValueError):
r1 = Raster(raster, band=1).read(outside_bounds, boundless=False)
Raster(raster, band=1).read(outside_bounds, boundless=False)

# rasterio src works inside extent
r2 = Raster(raster, band=1).read(bounds, boundless=False)
Expand All @@ -316,7 +316,7 @@ def test_Raster_boundless_disabled():

# ndarray src fails outside extent
with pytest.raises(ValueError):
r4 = Raster(arr, affine, nodata, band=1).read(outside_bounds, boundless=False)
Raster(arr, affine, nodata, band=1).read(outside_bounds, boundless=False)

# If the abstraction is correct, the arrays are equal
assert np.array_equal(r2.array, r3.array)
Expand Down
5 changes: 4 additions & 1 deletion tests/test_zonal.py
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,7 @@ def mymean_prop(x, prop):
for i in range(len(stats)):
assert stats[i]["mymean_prop"] == stats[i]["mean"] * (i + 1)


def test_add_stats_prop_and_array():
polygons = data_dir / "polygons.shp"

Expand All @@ -315,7 +316,9 @@ def mymean_prop_and_array(x, prop, rv_array):
assert rv_array is not None
return np.ma.mean(x) * prop["id"]

stats = zonal_stats(polygons, raster, add_stats={"mymean_prop_and_array": mymean_prop_and_array})
stats = zonal_stats(
polygons, raster, add_stats={"mymean_prop_and_array": mymean_prop_and_array}
)
for i in range(len(stats)):
assert stats[i]["mymean_prop_and_array"] == stats[i]["mean"] * (i + 1)

Expand Down