diff --git a/CHANGELOG.md b/CHANGELOG.md index 9308198..298b5af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +--- + +## [0.5.0] - 2026-10-05 + ### Added - **`sum` over vector sources**, with `params = {area = true}` for areal weighting: each polygon's attribute (e.g. census population) is shared among the cells in proportion to the intersected @@ -16,6 +20,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 touches (a point to its own cell). `params = {column = …}` picks the column (default: the target name). Vector sources are no longer clipped to the grid for `sum`, so a polygon crossing the border keeps its full denominator. +- **`network_cost` operator** (alias `gpm_network`): least transport cost over a road network, from + each cell to the nearest destination, by an exact multi-source Dijkstra over the line graph + (`scipy.sparse.csgraph`). Destinations come from `params = {targets = …}` (a vector file, found + in the download cache or as given, or a list of `[x, y]`; polygons count by their centroid). + The cost of a segment is its length times a factor: `cost_column` (a per-line multiplier), + or `status_column` with `inside_paved` / `inside_unpaved`; the legs from a cell to the network + cost `outside` times the distance. `entrance = "vertex"` joins a cell and a destination at the + nearest vertex, as TerraME's GPM does; `"segment"` (default) at the nearest point of the nearest + line. `unit_scale` rescales the result (`1e-3` for km) and `crs` measures in metres. Cells that + reach no destination are NaN, with a warning. Reproduces the regional pattern of TerraME's GPM + `Network` (generalized transport cost to ports, r = 0.996 on the 25 km Brazil grid); the two + methods do not agree cell by cell (`LambdaGeo/disscube-benchmark`, `connectivity`). Example: + `examples/04_network_connectivity.py`. First use: `e_connport`, the connectivity to ports of + LuccME-BR (`LambdaGeo/disscube-recipes`, `cases/luccme_br`). - **`median` operator**: per-cell median of the valid pixels, from the fine-aligned source. - **`std` `ddof` param** (`0` default, `1` for the sample estimate). The default is unchanged, so existing `spec_hash`es hold. @@ -41,6 +59,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 The notes saying TerraME measures from the cell polygon and divides by the whole cell were removed, and so was the "half a cell diagonal" remark in the `DistanceOperator` docstring. +### Fixed +- The CLI reports a missing optional extra (e.g. `disscube[dissmodel]`) as an error message, not a + traceback. + ## [0.4.0] - 2026-09-30 ### Changed diff --git a/CITATION.cff b/CITATION.cff index d4c895b..c53ee3b 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -6,8 +6,8 @@ authors: orcid: "https://orcid.org/0000-0002-0232-4549" title: "DisSCube: Declarative spatial data cubes" abstract: "An open-source, declarative engine for constructing cellular spatial data cubes for dynamic modeling, spatial simulation, and environmental analysis." -version: 0.4.0 -date-released: "2026-09-29" +version: 0.5.0 +date-released: "2026-10-05" url: "https://github.com/DisSModel/disscube" repository-code: "https://github.com/DisSModel/disscube" license: MIT diff --git a/README.md b/README.md index f4f1307..880ff66 100644 --- a/README.md +++ b/README.md @@ -303,7 +303,7 @@ If you use DisSCube in your research, dynamic modeling, or spatial data pipeline author = {Costa, S{\'e}rgio Souza}, title = {{DisSCube: Declarative spatial data cubes}}, year = {2026}, - version = {0.4.0}, + version = {0.5.0}, url = {https://github.com/DisSModel/disscube} } ``` diff --git a/docs/architecture/operators.md b/docs/architecture/operators.md index 78b7a80..7977d6b 100644 --- a/docs/architecture/operators.md +++ b/docs/architecture/operators.md @@ -69,6 +69,7 @@ The last three also produce `coverage_purity` and `dominance_purity` as coordina | `distance` | Exact Euclidean distance (CRS units) from each cell centre to the nearest feature; the source is not clipped to the grid. `params = {"crs": …}` measures in another CRS (metres in a projected one) | no | | `min_distance` | Raster approximation of the distance to the nearest feature inside the grid (NaN, with a warning, if none is inside) | no | | `count` | Number of features whose centroid falls in each cell | no | +| `network_cost` (alias `gpm_network`) | Least transport cost over a road network (exact multi-source Dijkstra) from each cell to the nearest destination: `targets` (file or `[x, y]` list), `cost_column` or `status_column` + `inside_paved` / `inside_unpaved`, `outside` (off-road factor), `entrance` (`segment` or `vertex`), `unit_scale`, `crs`. NaN where no destination is reachable | no | | `area` | Share (0..1) of each cell covered by polygons (intersection area / cell area; overlaps count once) — TerraME's `area` | no | ## The `compute()` contract diff --git a/pyproject.toml b/pyproject.toml index 567d243..4755bb9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "disscube" -version = "0.4.0" +version = "0.5.0" description = "Declarative spatial data cubes: describe sources, grid and derived variables in TOML; get a cataloged, reproducible cube." readme = "README.md" requires-python = ">=3.11"