Skip to content

Commit 90c3406

Browse files
authored
Rasterization improvements (#38)
1 parent 20ed76a commit 90c3406

15 files changed

+964
-114
lines changed

.pre-commit-config.yaml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,11 @@ repos:
3131
- mdformat-black
3232
- mdformat-myst
3333

34-
# - repo: https://github.com/kynan/nbstripout
35-
# rev: 0.8.1
36-
# hooks:
37-
# - id: nbstripout
38-
# args: [--extra-keys=metadata.kernelspec metadata.language_info.version]
34+
- repo: https://github.com/kynan/nbstripout
35+
rev: 0.8.1
36+
hooks:
37+
- id: nbstripout
38+
args: [--extra-keys=metadata.kernelspec metadata.language_info.version]
3939

4040
- repo: https://github.com/codespell-project/codespell
4141
rev: v2.4.1

docs/api.rst

Lines changed: 0 additions & 21 deletions
This file was deleted.

docs/conf.py

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,19 +28,31 @@
2828

2929
# -- General configuration -----------------------------------------------------
3030
extensions = [
31-
"sphinx.ext.autodoc",
3231
"sphinx.ext.viewcode",
33-
"sphinx.ext.autosummary",
3432
"sphinx.ext.intersphinx",
3533
"sphinx.ext.extlinks",
3634
"numpydoc",
3735
"sphinx.ext.napoleon",
3836
"myst_nb",
37+
"autoapi.extension",
3938
"sphinx_codeautolink",
4039
"sphinx_remove_toctrees",
4140
"sphinxext.opengraph",
4241
]
4342

43+
autoapi_dirs = ["../src/rasterix/"]
44+
autoapi_options = [
45+
"members",
46+
"undoc-members",
47+
"show-inheritance",
48+
# "show-module-summary",
49+
"special-members",
50+
# "imported-members",
51+
]
52+
autoapi_ignore = ["*compat*", "*util*"]
53+
autoapi_add_toctree_entry = False
54+
55+
autodoc_typehints = "none"
4456
codeautolink_concat_default = True
4557

4658
extlinks = {
@@ -127,10 +139,11 @@
127139
"xarray": ("https://docs.xarray.dev/en/stable/", None),
128140
"xproj": ("https://xproj.readthedocs.io/en/stable/", None),
129141
"pyproj": ("https://pyproj4.github.io/pyproj/stable/", None),
142+
"exactextract": ("https://isciences.github.io/exactextract/", None),
143+
"rasterio": ("https://rasterio.readthedocs.io/en/stable/", None),
130144
}
131145

132146
autosummary_generate = True
133-
autodoc_typehints = "none"
134147

135148
# Napoleon configurations
136149
napoleon_google_docstring = False

docs/index.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,15 @@ raster_index/combining
1616
caption: Rasterizing
1717
hidden:
1818
---
19+
rasterize/rasterio
20+
rasterize/geometry_mask
21+
rasterize/exactextract
1922
```
2023

2124
```{toctree}
2225
---
2326
caption: Reference
2427
hidden:
2528
---
26-
api.rst
29+
autoapi/rasterix/index
2730
```

docs/rasterize/exactextract.ipynb

Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"id": "0",
6+
"metadata": {},
7+
"source": [
8+
"# With `exactextract`\n",
9+
"\n",
10+
"Rasterix includes dask-aware wrappers for `exactextract.exact_extract`'s coverage estimation."
11+
]
12+
},
13+
{
14+
"cell_type": "markdown",
15+
"id": "1",
16+
"metadata": {},
17+
"source": [
18+
"## Read data\n",
19+
"\n",
20+
"### Read in some raster data"
21+
]
22+
},
23+
{
24+
"cell_type": "code",
25+
"execution_count": null,
26+
"id": "2",
27+
"metadata": {},
28+
"outputs": [],
29+
"source": [
30+
"import xarray as xr\n",
31+
"\n",
32+
"ds = xr.tutorial.open_dataset(\"eraint_uvz\")\n",
33+
"ds = ds.rio.write_crs(\"epsg:4326\")\n",
34+
"ds"
35+
]
36+
},
37+
{
38+
"cell_type": "markdown",
39+
"id": "3",
40+
"metadata": {},
41+
"source": [
42+
"### Read in example geometries"
43+
]
44+
},
45+
{
46+
"cell_type": "code",
47+
"execution_count": null,
48+
"id": "4",
49+
"metadata": {},
50+
"outputs": [],
51+
"source": [
52+
"import geodatasets\n",
53+
"import geopandas as gpd\n",
54+
"\n",
55+
"world = gpd.read_file(geodatasets.get_path(\"naturalearth land\"))\n",
56+
"world"
57+
]
58+
},
59+
{
60+
"cell_type": "markdown",
61+
"id": "5",
62+
"metadata": {},
63+
"source": [
64+
"## Calculate coverage"
65+
]
66+
},
67+
{
68+
"cell_type": "code",
69+
"execution_count": null,
70+
"id": "6",
71+
"metadata": {},
72+
"outputs": [],
73+
"source": [
74+
"from rasterix.rasterize.exact import coverage\n",
75+
"\n",
76+
"n = coverage(ds, world[[\"geometry\"]], xdim=\"longitude\", ydim=\"latitude\")\n",
77+
"n"
78+
]
79+
},
80+
{
81+
"cell_type": "code",
82+
"execution_count": null,
83+
"id": "7",
84+
"metadata": {},
85+
"outputs": [],
86+
"source": [
87+
"n.isel(geometry=112).plot()"
88+
]
89+
},
90+
{
91+
"cell_type": "markdown",
92+
"id": "8",
93+
"metadata": {},
94+
"source": [
95+
"Optionally clip to the `total_bounds` of the geometries passed in"
96+
]
97+
},
98+
{
99+
"cell_type": "code",
100+
"execution_count": null,
101+
"id": "9",
102+
"metadata": {},
103+
"outputs": [],
104+
"source": [
105+
"from rasterix.rasterize.exact import coverage\n",
106+
"\n",
107+
"coverage(\n",
108+
" ds,\n",
109+
" world[[\"geometry\"]].iloc[slice(112, 113)],\n",
110+
" xdim=\"longitude\",\n",
111+
" ydim=\"latitude\",\n",
112+
" clip=True,\n",
113+
").plot()"
114+
]
115+
},
116+
{
117+
"cell_type": "markdown",
118+
"id": "10",
119+
"metadata": {},
120+
"source": [
121+
"Notice that the output data is a `sparse.COO` array with a new dimension `geometry`. The input geometries are propagated as a coordinate variable named `geometry`.\n",
122+
"\n",
123+
"Different coverage weights are supported. Extra attributes `units` and `long_name` are assigned as appropriate."
124+
]
125+
},
126+
{
127+
"cell_type": "code",
128+
"execution_count": null,
129+
"id": "11",
130+
"metadata": {},
131+
"outputs": [],
132+
"source": [
133+
"from rasterix.rasterize.exact import coverage\n",
134+
"\n",
135+
"n = coverage(ds, world[[\"geometry\"]], xdim=\"longitude\", ydim=\"latitude\", coverage_weight=\"fraction\")\n",
136+
"n"
137+
]
138+
},
139+
{
140+
"cell_type": "markdown",
141+
"id": "12",
142+
"metadata": {},
143+
"source": [
144+
"## Out-of-core support\n",
145+
"\n",
146+
"As with other rasterization code, various combinations of chunked and in-memory arrays and geometries are supported."
147+
]
148+
},
149+
{
150+
"cell_type": "code",
151+
"execution_count": null,
152+
"id": "13",
153+
"metadata": {},
154+
"outputs": [],
155+
"source": [
156+
"chunked = ds.chunk({\"latitude\": -1, \"longitude\": 120})\n",
157+
"d = coverage(chunked, world[[\"geometry\"]], xdim=\"longitude\", ydim=\"latitude\")\n",
158+
"d"
159+
]
160+
},
161+
{
162+
"cell_type": "code",
163+
"execution_count": null,
164+
"id": "14",
165+
"metadata": {},
166+
"outputs": [],
167+
"source": [
168+
"xr.testing.assert_identical(d, n)"
169+
]
170+
},
171+
{
172+
"cell_type": "code",
173+
"execution_count": null,
174+
"id": "15",
175+
"metadata": {},
176+
"outputs": [],
177+
"source": [
178+
"import dask_geopandas as dgpd\n",
179+
"\n",
180+
"dd = coverage(\n",
181+
" ds.chunk({\"latitude\": -1, \"longitude\": 240}),\n",
182+
" dgpd.from_geopandas(world[[\"geometry\"]], npartitions=3),\n",
183+
" xdim=\"longitude\",\n",
184+
" ydim=\"latitude\",\n",
185+
")\n",
186+
"dd"
187+
]
188+
},
189+
{
190+
"cell_type": "code",
191+
"execution_count": null,
192+
"id": "16",
193+
"metadata": {},
194+
"outputs": [],
195+
"source": [
196+
"xr.testing.assert_identical(dd, n)"
197+
]
198+
}
199+
],
200+
"metadata": {
201+
"language_info": {
202+
"codemirror_mode": {
203+
"name": "ipython",
204+
"version": 3
205+
},
206+
"file_extension": ".py",
207+
"mimetype": "text/x-python",
208+
"name": "python",
209+
"nbconvert_exporter": "python",
210+
"pygments_lexer": "ipython3"
211+
}
212+
},
213+
"nbformat": 4,
214+
"nbformat_minor": 5
215+
}

0 commit comments

Comments
 (0)