rusterize 0.1.0__tar.gz → 0.1.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of rusterize might be problematic. Click here for more details.
- {rusterize-0.1.0 → rusterize-0.1.1}/.github/workflows/CI.yml +0 -3
- rusterize-0.1.1/.github/workflows/test-compile.yml +148 -0
- {rusterize-0.1.0 → rusterize-0.1.1}/Cargo.lock +90 -67
- {rusterize-0.1.0 → rusterize-0.1.1}/Cargo.toml +1 -1
- {rusterize-0.1.0 → rusterize-0.1.1}/PKG-INFO +38 -29
- {rusterize-0.1.0 → rusterize-0.1.1}/README.md +30 -21
- rusterize-0.1.1/img/plot.png +0 -0
- {rusterize-0.1.0 → rusterize-0.1.1}/pyproject.toml +1 -1
- rusterize-0.1.1/python/rusterize/core.py +107 -0
- {rusterize-0.1.0 → rusterize-0.1.1}/src/geo_validate.rs +8 -3
- {rusterize-0.1.0 → rusterize-0.1.1}/src/structs/raster.rs +33 -17
- rusterize-0.1.0/python/rusterize/core.py +0 -80
- {rusterize-0.1.0 → rusterize-0.1.1}/.gitignore +0 -0
- {rusterize-0.1.0 → rusterize-0.1.1}/LICENSE +0 -0
- {rusterize-0.1.0 → rusterize-0.1.1}/python/rusterize/__init__.py +0 -0
- {rusterize-0.1.0 → rusterize-0.1.1}/rust-toolchain.toml +0 -0
- {rusterize-0.1.0 → rusterize-0.1.1}/src/allocator.rs +0 -0
- {rusterize-0.1.0 → rusterize-0.1.1}/src/edgelist.rs +0 -0
- {rusterize-0.1.0 → rusterize-0.1.1}/src/lib.rs +0 -0
- {rusterize-0.1.0 → rusterize-0.1.1}/src/pixel_functions.rs +0 -0
- {rusterize-0.1.0 → rusterize-0.1.1}/src/rasterize_polygon.rs +0 -0
- {rusterize-0.1.0 → rusterize-0.1.1}/src/structs/edge.rs +0 -0
- {rusterize-0.1.0 → rusterize-0.1.1}/src/structs/xarray.rs +0 -0
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- compile
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
linux:
|
|
13
|
+
runs-on: ${{ matrix.platform.runner }}
|
|
14
|
+
strategy:
|
|
15
|
+
fail-fast: false
|
|
16
|
+
matrix:
|
|
17
|
+
platform:
|
|
18
|
+
- runner: ubuntu-22.04
|
|
19
|
+
target: x86_64
|
|
20
|
+
# - runner: ubuntu-22.04
|
|
21
|
+
# target: x86
|
|
22
|
+
- runner: ubuntu-22.04
|
|
23
|
+
target: aarch64
|
|
24
|
+
- runner: ubuntu-22.04
|
|
25
|
+
target: armv7
|
|
26
|
+
# - runner: ubuntu-22.04
|
|
27
|
+
# target: s390x
|
|
28
|
+
- runner: ubuntu-22.04
|
|
29
|
+
target: ppc64le
|
|
30
|
+
steps:
|
|
31
|
+
- uses: actions/checkout@v4
|
|
32
|
+
- uses: actions/setup-python@v5
|
|
33
|
+
with:
|
|
34
|
+
python-version: 3.x
|
|
35
|
+
- name: Build wheels
|
|
36
|
+
uses: PyO3/maturin-action@v1
|
|
37
|
+
with:
|
|
38
|
+
target: ${{ matrix.platform.target }}
|
|
39
|
+
args: --profile dist-release --out dist --find-interpreter
|
|
40
|
+
sccache: "true"
|
|
41
|
+
manylinux: auto
|
|
42
|
+
- name: Upload wheels
|
|
43
|
+
uses: actions/upload-artifact@v4
|
|
44
|
+
with:
|
|
45
|
+
name: wheels-linux-${{ matrix.platform.target }}
|
|
46
|
+
path: dist
|
|
47
|
+
|
|
48
|
+
musllinux:
|
|
49
|
+
runs-on: ${{ matrix.platform.runner }}
|
|
50
|
+
strategy:
|
|
51
|
+
fail-fast: false
|
|
52
|
+
matrix:
|
|
53
|
+
platform:
|
|
54
|
+
- runner: ubuntu-22.04
|
|
55
|
+
target: x86_64
|
|
56
|
+
# - runner: ubuntu-22.04
|
|
57
|
+
# target: x86
|
|
58
|
+
- runner: ubuntu-22.04
|
|
59
|
+
target: aarch64
|
|
60
|
+
- runner: ubuntu-22.04
|
|
61
|
+
target: armv7
|
|
62
|
+
steps:
|
|
63
|
+
- uses: actions/checkout@v4
|
|
64
|
+
- uses: actions/setup-python@v5
|
|
65
|
+
with:
|
|
66
|
+
python-version: 3.x
|
|
67
|
+
- name: Build wheels
|
|
68
|
+
uses: PyO3/maturin-action@v1
|
|
69
|
+
with:
|
|
70
|
+
target: ${{ matrix.platform.target }}
|
|
71
|
+
args: --profile dist-release --out dist --find-interpreter
|
|
72
|
+
sccache: "true"
|
|
73
|
+
manylinux: musllinux_1_2
|
|
74
|
+
- name: Upload wheels
|
|
75
|
+
uses: actions/upload-artifact@v4
|
|
76
|
+
with:
|
|
77
|
+
name: wheels-musllinux-${{ matrix.platform.target }}
|
|
78
|
+
path: dist
|
|
79
|
+
|
|
80
|
+
windows:
|
|
81
|
+
runs-on: ${{ matrix.platform.runner }}
|
|
82
|
+
strategy:
|
|
83
|
+
fail-fast: false
|
|
84
|
+
matrix:
|
|
85
|
+
platform:
|
|
86
|
+
- runner: windows-latest
|
|
87
|
+
target: x64
|
|
88
|
+
# - runner: windows-latest
|
|
89
|
+
# target: x86
|
|
90
|
+
steps:
|
|
91
|
+
- uses: actions/checkout@v4
|
|
92
|
+
- uses: actions/setup-python@v5
|
|
93
|
+
with:
|
|
94
|
+
python-version: 3.x
|
|
95
|
+
architecture: ${{ matrix.platform.target }}
|
|
96
|
+
- name: Build wheels
|
|
97
|
+
uses: PyO3/maturin-action@v1
|
|
98
|
+
with:
|
|
99
|
+
target: ${{ matrix.platform.target }}
|
|
100
|
+
args: --profile dist-release --out dist --find-interpreter
|
|
101
|
+
sccache: "true"
|
|
102
|
+
- name: Upload wheels
|
|
103
|
+
uses: actions/upload-artifact@v4
|
|
104
|
+
with:
|
|
105
|
+
name: wheels-windows-${{ matrix.platform.target }}
|
|
106
|
+
path: dist
|
|
107
|
+
|
|
108
|
+
macos:
|
|
109
|
+
runs-on: ${{ matrix.platform.runner }}
|
|
110
|
+
strategy:
|
|
111
|
+
fail-fast: false
|
|
112
|
+
matrix:
|
|
113
|
+
platform:
|
|
114
|
+
- runner: macos-13
|
|
115
|
+
target: x86_64
|
|
116
|
+
- runner: macos-14
|
|
117
|
+
target: aarch64
|
|
118
|
+
steps:
|
|
119
|
+
- uses: actions/checkout@v4
|
|
120
|
+
- uses: actions/setup-python@v5
|
|
121
|
+
with:
|
|
122
|
+
python-version: 3.x
|
|
123
|
+
- name: Build wheels
|
|
124
|
+
uses: PyO3/maturin-action@v1
|
|
125
|
+
with:
|
|
126
|
+
target: ${{ matrix.platform.target }}
|
|
127
|
+
args: --profile dist-release --out dist --find-interpreter
|
|
128
|
+
sccache: "true"
|
|
129
|
+
- name: Upload wheels
|
|
130
|
+
uses: actions/upload-artifact@v4
|
|
131
|
+
with:
|
|
132
|
+
name: wheels-macos-${{ matrix.platform.target }}
|
|
133
|
+
path: dist
|
|
134
|
+
|
|
135
|
+
sdist:
|
|
136
|
+
runs-on: ubuntu-latest
|
|
137
|
+
steps:
|
|
138
|
+
- uses: actions/checkout@v4
|
|
139
|
+
- name: Build sdist
|
|
140
|
+
uses: PyO3/maturin-action@v1
|
|
141
|
+
with:
|
|
142
|
+
command: sdist
|
|
143
|
+
args: --out dist
|
|
144
|
+
- name: Upload sdist
|
|
145
|
+
uses: actions/upload-artifact@v4
|
|
146
|
+
with:
|
|
147
|
+
name: wheels-sdist
|
|
148
|
+
path: dist
|
|
@@ -24,7 +24,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
|
24
24
|
checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
|
|
25
25
|
dependencies = [
|
|
26
26
|
"cfg-if",
|
|
27
|
-
"getrandom",
|
|
27
|
+
"getrandom 0.2.15",
|
|
28
28
|
"once_cell",
|
|
29
29
|
"version_check",
|
|
30
30
|
"zerocopy",
|
|
@@ -130,7 +130,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d"
|
|
|
130
130
|
dependencies = [
|
|
131
131
|
"proc-macro2",
|
|
132
132
|
"quote",
|
|
133
|
-
"syn 2.0.
|
|
133
|
+
"syn 2.0.98",
|
|
134
134
|
]
|
|
135
135
|
|
|
136
136
|
[[package]]
|
|
@@ -141,7 +141,7 @@ checksum = "644dd749086bf3771a2fbc5f256fdb982d53f011c7d5d560304eafeecebce79d"
|
|
|
141
141
|
dependencies = [
|
|
142
142
|
"proc-macro2",
|
|
143
143
|
"quote",
|
|
144
|
-
"syn 2.0.
|
|
144
|
+
"syn 2.0.98",
|
|
145
145
|
]
|
|
146
146
|
|
|
147
147
|
[[package]]
|
|
@@ -267,7 +267,7 @@ checksum = "3fa76293b4f7bb636ab88fd78228235b5248b4d05cc589aed610f954af5d7c7a"
|
|
|
267
267
|
dependencies = [
|
|
268
268
|
"proc-macro2",
|
|
269
269
|
"quote",
|
|
270
|
-
"syn 2.0.
|
|
270
|
+
"syn 2.0.98",
|
|
271
271
|
]
|
|
272
272
|
|
|
273
273
|
[[package]]
|
|
@@ -278,9 +278,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
|
|
278
278
|
|
|
279
279
|
[[package]]
|
|
280
280
|
name = "bytes"
|
|
281
|
-
version = "1.
|
|
281
|
+
version = "1.10.0"
|
|
282
282
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
283
|
-
checksum = "
|
|
283
|
+
checksum = "f61dac84819c6588b558454b194026eb1f09c293b9036ae9b159e74e73ab6cf9"
|
|
284
284
|
|
|
285
285
|
[[package]]
|
|
286
286
|
name = "castaway"
|
|
@@ -293,9 +293,9 @@ dependencies = [
|
|
|
293
293
|
|
|
294
294
|
[[package]]
|
|
295
295
|
name = "cc"
|
|
296
|
-
version = "1.2.
|
|
296
|
+
version = "1.2.13"
|
|
297
297
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
298
|
-
checksum = "
|
|
298
|
+
checksum = "c7777341816418c02e033934a09f20dc0ccaf65a5201ef8a450ae0105a573fda"
|
|
299
299
|
dependencies = [
|
|
300
300
|
"jobserver",
|
|
301
301
|
"libc",
|
|
@@ -378,13 +378,12 @@ dependencies = [
|
|
|
378
378
|
|
|
379
379
|
[[package]]
|
|
380
380
|
name = "comfy-table"
|
|
381
|
-
version = "7.1.
|
|
381
|
+
version = "7.1.4"
|
|
382
382
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
383
|
-
checksum = "
|
|
383
|
+
checksum = "4a65ebfec4fb190b6f90e944a817d60499ee0744e582530e2c9900a22e591d9a"
|
|
384
384
|
dependencies = [
|
|
385
385
|
"crossterm",
|
|
386
|
-
"
|
|
387
|
-
"strum_macros",
|
|
386
|
+
"unicode-segmentation",
|
|
388
387
|
"unicode-width",
|
|
389
388
|
]
|
|
390
389
|
|
|
@@ -544,7 +543,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
|
|
|
544
543
|
dependencies = [
|
|
545
544
|
"proc-macro2",
|
|
546
545
|
"quote",
|
|
547
|
-
"syn 2.0.
|
|
546
|
+
"syn 2.0.98",
|
|
548
547
|
]
|
|
549
548
|
|
|
550
549
|
[[package]]
|
|
@@ -587,7 +586,7 @@ dependencies = [
|
|
|
587
586
|
"once_cell",
|
|
588
587
|
"proc-macro2",
|
|
589
588
|
"quote",
|
|
590
|
-
"syn 2.0.
|
|
589
|
+
"syn 2.0.98",
|
|
591
590
|
]
|
|
592
591
|
|
|
593
592
|
[[package]]
|
|
@@ -736,7 +735,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
|
|
|
736
735
|
dependencies = [
|
|
737
736
|
"proc-macro2",
|
|
738
737
|
"quote",
|
|
739
|
-
"syn 2.0.
|
|
738
|
+
"syn 2.0.98",
|
|
740
739
|
]
|
|
741
740
|
|
|
742
741
|
[[package]]
|
|
@@ -828,10 +827,22 @@ dependencies = [
|
|
|
828
827
|
"cfg-if",
|
|
829
828
|
"js-sys",
|
|
830
829
|
"libc",
|
|
831
|
-
"wasi",
|
|
830
|
+
"wasi 0.11.0+wasi-snapshot-preview1",
|
|
832
831
|
"wasm-bindgen",
|
|
833
832
|
]
|
|
834
833
|
|
|
834
|
+
[[package]]
|
|
835
|
+
name = "getrandom"
|
|
836
|
+
version = "0.3.1"
|
|
837
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
838
|
+
checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8"
|
|
839
|
+
dependencies = [
|
|
840
|
+
"cfg-if",
|
|
841
|
+
"libc",
|
|
842
|
+
"wasi 0.13.3+wasi-0.2.2",
|
|
843
|
+
"windows-targets",
|
|
844
|
+
]
|
|
845
|
+
|
|
835
846
|
[[package]]
|
|
836
847
|
name = "gimli"
|
|
837
848
|
version = "0.31.1"
|
|
@@ -1245,7 +1256,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6"
|
|
|
1245
1256
|
dependencies = [
|
|
1246
1257
|
"proc-macro2",
|
|
1247
1258
|
"quote",
|
|
1248
|
-
"syn 2.0.
|
|
1259
|
+
"syn 2.0.98",
|
|
1249
1260
|
]
|
|
1250
1261
|
|
|
1251
1262
|
[[package]]
|
|
@@ -1471,9 +1482,9 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
|
|
|
1471
1482
|
|
|
1472
1483
|
[[package]]
|
|
1473
1484
|
name = "miniz_oxide"
|
|
1474
|
-
version = "0.8.
|
|
1485
|
+
version = "0.8.4"
|
|
1475
1486
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1476
|
-
checksum = "
|
|
1487
|
+
checksum = "b3b1c9bd4fe1f0f8b387f6eb9eb3b4a1aa26185e5750efb9140301703f62cd1b"
|
|
1477
1488
|
dependencies = [
|
|
1478
1489
|
"adler2",
|
|
1479
1490
|
]
|
|
@@ -1485,7 +1496,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
|
1485
1496
|
checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd"
|
|
1486
1497
|
dependencies = [
|
|
1487
1498
|
"libc",
|
|
1488
|
-
"wasi",
|
|
1499
|
+
"wasi 0.11.0+wasi-snapshot-preview1",
|
|
1489
1500
|
"windows-sys 0.52.0",
|
|
1490
1501
|
]
|
|
1491
1502
|
|
|
@@ -1637,9 +1648,9 @@ dependencies = [
|
|
|
1637
1648
|
|
|
1638
1649
|
[[package]]
|
|
1639
1650
|
name = "once_cell"
|
|
1640
|
-
version = "1.20.
|
|
1651
|
+
version = "1.20.3"
|
|
1641
1652
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1642
|
-
checksum = "
|
|
1653
|
+
checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e"
|
|
1643
1654
|
|
|
1644
1655
|
[[package]]
|
|
1645
1656
|
name = "openssl-probe"
|
|
@@ -1756,7 +1767,7 @@ version = "0.44.2"
|
|
|
1756
1767
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1757
1768
|
checksum = "f65c6aa86d991a64c95416a61202f7952da2f8cccefa448f9a23c1b8f2301ecc"
|
|
1758
1769
|
dependencies = [
|
|
1759
|
-
"getrandom",
|
|
1770
|
+
"getrandom 0.2.15",
|
|
1760
1771
|
"polars-arrow",
|
|
1761
1772
|
"polars-core",
|
|
1762
1773
|
"polars-error",
|
|
@@ -1786,7 +1797,7 @@ dependencies = [
|
|
|
1786
1797
|
"either",
|
|
1787
1798
|
"ethnum",
|
|
1788
1799
|
"fast-float",
|
|
1789
|
-
"getrandom",
|
|
1800
|
+
"getrandom 0.2.15",
|
|
1790
1801
|
"hashbrown 0.15.2",
|
|
1791
1802
|
"itoa",
|
|
1792
1803
|
"itoap",
|
|
@@ -2373,7 +2384,7 @@ dependencies = [
|
|
|
2373
2384
|
"proc-macro2",
|
|
2374
2385
|
"pyo3-macros-backend",
|
|
2375
2386
|
"quote",
|
|
2376
|
-
"syn 2.0.
|
|
2387
|
+
"syn 2.0.98",
|
|
2377
2388
|
]
|
|
2378
2389
|
|
|
2379
2390
|
[[package]]
|
|
@@ -2386,7 +2397,7 @@ dependencies = [
|
|
|
2386
2397
|
"proc-macro2",
|
|
2387
2398
|
"pyo3-build-config",
|
|
2388
2399
|
"quote",
|
|
2389
|
-
"syn 2.0.
|
|
2400
|
+
"syn 2.0.98",
|
|
2390
2401
|
]
|
|
2391
2402
|
|
|
2392
2403
|
[[package]]
|
|
@@ -2435,7 +2446,7 @@ dependencies = [
|
|
|
2435
2446
|
"pin-project-lite",
|
|
2436
2447
|
"quinn-proto",
|
|
2437
2448
|
"quinn-udp",
|
|
2438
|
-
"rustc-hash 2.1.
|
|
2449
|
+
"rustc-hash 2.1.1",
|
|
2439
2450
|
"rustls",
|
|
2440
2451
|
"socket2",
|
|
2441
2452
|
"thiserror 2.0.11",
|
|
@@ -2450,10 +2461,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
|
2450
2461
|
checksum = "a2fe5ef3495d7d2e377ff17b1a8ce2ee2ec2a18cde8b6ad6619d65d0701c135d"
|
|
2451
2462
|
dependencies = [
|
|
2452
2463
|
"bytes",
|
|
2453
|
-
"getrandom",
|
|
2464
|
+
"getrandom 0.2.15",
|
|
2454
2465
|
"rand",
|
|
2455
2466
|
"ring",
|
|
2456
|
-
"rustc-hash 2.1.
|
|
2467
|
+
"rustc-hash 2.1.1",
|
|
2457
2468
|
"rustls",
|
|
2458
2469
|
"rustls-pki-types",
|
|
2459
2470
|
"slab",
|
|
@@ -2513,7 +2524,7 @@ version = "0.6.4"
|
|
|
2513
2524
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2514
2525
|
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
|
2515
2526
|
dependencies = [
|
|
2516
|
-
"getrandom",
|
|
2527
|
+
"getrandom 0.2.15",
|
|
2517
2528
|
]
|
|
2518
2529
|
|
|
2519
2530
|
[[package]]
|
|
@@ -2578,7 +2589,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
|
2578
2589
|
checksum = "76009fbe0614077fc1a2ce255e3a1881a2e3a3527097d5dc6d8212c585e7e38b"
|
|
2579
2590
|
dependencies = [
|
|
2580
2591
|
"quote",
|
|
2581
|
-
"syn 2.0.
|
|
2592
|
+
"syn 2.0.98",
|
|
2582
2593
|
]
|
|
2583
2594
|
|
|
2584
2595
|
[[package]]
|
|
@@ -2607,7 +2618,7 @@ checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6"
|
|
|
2607
2618
|
dependencies = [
|
|
2608
2619
|
"proc-macro2",
|
|
2609
2620
|
"quote",
|
|
2610
|
-
"syn 2.0.
|
|
2621
|
+
"syn 2.0.98",
|
|
2611
2622
|
]
|
|
2612
2623
|
|
|
2613
2624
|
[[package]]
|
|
@@ -2693,7 +2704,7 @@ checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d"
|
|
|
2693
2704
|
dependencies = [
|
|
2694
2705
|
"cc",
|
|
2695
2706
|
"cfg-if",
|
|
2696
|
-
"getrandom",
|
|
2707
|
+
"getrandom 0.2.15",
|
|
2697
2708
|
"libc",
|
|
2698
2709
|
"spin",
|
|
2699
2710
|
"untrusted",
|
|
@@ -2731,13 +2742,13 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
|
|
2731
2742
|
|
|
2732
2743
|
[[package]]
|
|
2733
2744
|
name = "rustc-hash"
|
|
2734
|
-
version = "2.1.
|
|
2745
|
+
version = "2.1.1"
|
|
2735
2746
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2736
|
-
checksum = "
|
|
2747
|
+
checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
|
|
2737
2748
|
|
|
2738
2749
|
[[package]]
|
|
2739
2750
|
name = "rusterize"
|
|
2740
|
-
version = "0.1.
|
|
2751
|
+
version = "0.1.1"
|
|
2741
2752
|
dependencies = [
|
|
2742
2753
|
"dict_derive",
|
|
2743
2754
|
"geo",
|
|
@@ -2769,9 +2780,9 @@ dependencies = [
|
|
|
2769
2780
|
|
|
2770
2781
|
[[package]]
|
|
2771
2782
|
name = "rustls"
|
|
2772
|
-
version = "0.23.
|
|
2783
|
+
version = "0.23.23"
|
|
2773
2784
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2774
|
-
checksum = "
|
|
2785
|
+
checksum = "47796c98c480fce5406ef69d1c76378375492c3b0a0de587be0c1d9feb12f395"
|
|
2775
2786
|
dependencies = [
|
|
2776
2787
|
"once_cell",
|
|
2777
2788
|
"ring",
|
|
@@ -2898,7 +2909,7 @@ checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0"
|
|
|
2898
2909
|
dependencies = [
|
|
2899
2910
|
"proc-macro2",
|
|
2900
2911
|
"quote",
|
|
2901
|
-
"syn 2.0.
|
|
2912
|
+
"syn 2.0.98",
|
|
2902
2913
|
]
|
|
2903
2914
|
|
|
2904
2915
|
[[package]]
|
|
@@ -2938,7 +2949,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
|
2938
2949
|
checksum = "aa2bcf6c6e164e81bc7a5d49fc6988b3d515d9e8c07457d7b74ffb9324b9cd40"
|
|
2939
2950
|
dependencies = [
|
|
2940
2951
|
"ahash",
|
|
2941
|
-
"getrandom",
|
|
2952
|
+
"getrandom 0.2.15",
|
|
2942
2953
|
"halfbrown",
|
|
2943
2954
|
"once_cell",
|
|
2944
2955
|
"ref-cast",
|
|
@@ -3057,9 +3068,9 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
|
|
|
3057
3068
|
|
|
3058
3069
|
[[package]]
|
|
3059
3070
|
name = "stacker"
|
|
3060
|
-
version = "0.1.
|
|
3071
|
+
version = "0.1.18"
|
|
3061
3072
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
3062
|
-
checksum = "
|
|
3073
|
+
checksum = "1d08feb8f695b465baed819b03c128dc23f57a694510ab1f06c77f763975685e"
|
|
3063
3074
|
dependencies = [
|
|
3064
3075
|
"cc",
|
|
3065
3076
|
"cfg-if",
|
|
@@ -3095,12 +3106,6 @@ version = "0.2.4"
|
|
|
3095
3106
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
3096
3107
|
checksum = "fe895eb47f22e2ddd4dabc02bce419d2e643c8e3b585c78158b349195bc24d82"
|
|
3097
3108
|
|
|
3098
|
-
[[package]]
|
|
3099
|
-
name = "strum"
|
|
3100
|
-
version = "0.26.3"
|
|
3101
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
3102
|
-
checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06"
|
|
3103
|
-
|
|
3104
3109
|
[[package]]
|
|
3105
3110
|
name = "strum_macros"
|
|
3106
3111
|
version = "0.26.4"
|
|
@@ -3111,7 +3116,7 @@ dependencies = [
|
|
|
3111
3116
|
"proc-macro2",
|
|
3112
3117
|
"quote",
|
|
3113
3118
|
"rustversion",
|
|
3114
|
-
"syn 2.0.
|
|
3119
|
+
"syn 2.0.98",
|
|
3115
3120
|
]
|
|
3116
3121
|
|
|
3117
3122
|
[[package]]
|
|
@@ -3133,9 +3138,9 @@ dependencies = [
|
|
|
3133
3138
|
|
|
3134
3139
|
[[package]]
|
|
3135
3140
|
name = "syn"
|
|
3136
|
-
version = "2.0.
|
|
3141
|
+
version = "2.0.98"
|
|
3137
3142
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
3138
|
-
checksum = "
|
|
3143
|
+
checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1"
|
|
3139
3144
|
dependencies = [
|
|
3140
3145
|
"proc-macro2",
|
|
3141
3146
|
"quote",
|
|
@@ -3159,7 +3164,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
|
|
|
3159
3164
|
dependencies = [
|
|
3160
3165
|
"proc-macro2",
|
|
3161
3166
|
"quote",
|
|
3162
|
-
"syn 2.0.
|
|
3167
|
+
"syn 2.0.98",
|
|
3163
3168
|
]
|
|
3164
3169
|
|
|
3165
3170
|
[[package]]
|
|
@@ -3213,7 +3218,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
|
|
|
3213
3218
|
dependencies = [
|
|
3214
3219
|
"proc-macro2",
|
|
3215
3220
|
"quote",
|
|
3216
|
-
"syn 2.0.
|
|
3221
|
+
"syn 2.0.98",
|
|
3217
3222
|
]
|
|
3218
3223
|
|
|
3219
3224
|
[[package]]
|
|
@@ -3224,7 +3229,7 @@ checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2"
|
|
|
3224
3229
|
dependencies = [
|
|
3225
3230
|
"proc-macro2",
|
|
3226
3231
|
"quote",
|
|
3227
|
-
"syn 2.0.
|
|
3232
|
+
"syn 2.0.98",
|
|
3228
3233
|
]
|
|
3229
3234
|
|
|
3230
3235
|
[[package]]
|
|
@@ -3296,7 +3301,7 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8"
|
|
|
3296
3301
|
dependencies = [
|
|
3297
3302
|
"proc-macro2",
|
|
3298
3303
|
"quote",
|
|
3299
|
-
"syn 2.0.
|
|
3304
|
+
"syn 2.0.98",
|
|
3300
3305
|
]
|
|
3301
3306
|
|
|
3302
3307
|
[[package]]
|
|
@@ -3368,7 +3373,7 @@ checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d"
|
|
|
3368
3373
|
dependencies = [
|
|
3369
3374
|
"proc-macro2",
|
|
3370
3375
|
"quote",
|
|
3371
|
-
"syn 2.0.
|
|
3376
|
+
"syn 2.0.98",
|
|
3372
3377
|
]
|
|
3373
3378
|
|
|
3374
3379
|
[[package]]
|
|
@@ -3456,11 +3461,11 @@ checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
|
|
|
3456
3461
|
|
|
3457
3462
|
[[package]]
|
|
3458
3463
|
name = "uuid"
|
|
3459
|
-
version = "1.
|
|
3464
|
+
version = "1.13.1"
|
|
3460
3465
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
3461
|
-
checksum = "
|
|
3466
|
+
checksum = "ced87ca4be083373936a67f8de945faa23b6b42384bd5b64434850802c6dccd0"
|
|
3462
3467
|
dependencies = [
|
|
3463
|
-
"getrandom",
|
|
3468
|
+
"getrandom 0.3.1",
|
|
3464
3469
|
]
|
|
3465
3470
|
|
|
3466
3471
|
[[package]]
|
|
@@ -3506,6 +3511,15 @@ version = "0.11.0+wasi-snapshot-preview1"
|
|
|
3506
3511
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
3507
3512
|
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
|
3508
3513
|
|
|
3514
|
+
[[package]]
|
|
3515
|
+
name = "wasi"
|
|
3516
|
+
version = "0.13.3+wasi-0.2.2"
|
|
3517
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
3518
|
+
checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2"
|
|
3519
|
+
dependencies = [
|
|
3520
|
+
"wit-bindgen-rt",
|
|
3521
|
+
]
|
|
3522
|
+
|
|
3509
3523
|
[[package]]
|
|
3510
3524
|
name = "wasm-bindgen"
|
|
3511
3525
|
version = "0.2.100"
|
|
@@ -3528,7 +3542,7 @@ dependencies = [
|
|
|
3528
3542
|
"log",
|
|
3529
3543
|
"proc-macro2",
|
|
3530
3544
|
"quote",
|
|
3531
|
-
"syn 2.0.
|
|
3545
|
+
"syn 2.0.98",
|
|
3532
3546
|
"wasm-bindgen-shared",
|
|
3533
3547
|
]
|
|
3534
3548
|
|
|
@@ -3563,7 +3577,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
|
|
|
3563
3577
|
dependencies = [
|
|
3564
3578
|
"proc-macro2",
|
|
3565
3579
|
"quote",
|
|
3566
|
-
"syn 2.0.
|
|
3580
|
+
"syn 2.0.98",
|
|
3567
3581
|
"wasm-bindgen-backend",
|
|
3568
3582
|
"wasm-bindgen-shared",
|
|
3569
3583
|
]
|
|
@@ -3680,7 +3694,7 @@ checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7"
|
|
|
3680
3694
|
dependencies = [
|
|
3681
3695
|
"proc-macro2",
|
|
3682
3696
|
"quote",
|
|
3683
|
-
"syn 2.0.
|
|
3697
|
+
"syn 2.0.98",
|
|
3684
3698
|
]
|
|
3685
3699
|
|
|
3686
3700
|
[[package]]
|
|
@@ -3691,7 +3705,7 @@ checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7"
|
|
|
3691
3705
|
dependencies = [
|
|
3692
3706
|
"proc-macro2",
|
|
3693
3707
|
"quote",
|
|
3694
|
-
"syn 2.0.
|
|
3708
|
+
"syn 2.0.98",
|
|
3695
3709
|
]
|
|
3696
3710
|
|
|
3697
3711
|
[[package]]
|
|
@@ -3815,6 +3829,15 @@ version = "0.52.6"
|
|
|
3815
3829
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
3816
3830
|
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
|
3817
3831
|
|
|
3832
|
+
[[package]]
|
|
3833
|
+
name = "wit-bindgen-rt"
|
|
3834
|
+
version = "0.33.0"
|
|
3835
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
3836
|
+
checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c"
|
|
3837
|
+
dependencies = [
|
|
3838
|
+
"bitflags",
|
|
3839
|
+
]
|
|
3840
|
+
|
|
3818
3841
|
[[package]]
|
|
3819
3842
|
name = "write16"
|
|
3820
3843
|
version = "1.0.0"
|
|
@@ -3853,7 +3876,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154"
|
|
|
3853
3876
|
dependencies = [
|
|
3854
3877
|
"proc-macro2",
|
|
3855
3878
|
"quote",
|
|
3856
|
-
"syn 2.0.
|
|
3879
|
+
"syn 2.0.98",
|
|
3857
3880
|
"synstructure",
|
|
3858
3881
|
]
|
|
3859
3882
|
|
|
@@ -3875,7 +3898,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
|
|
|
3875
3898
|
dependencies = [
|
|
3876
3899
|
"proc-macro2",
|
|
3877
3900
|
"quote",
|
|
3878
|
-
"syn 2.0.
|
|
3901
|
+
"syn 2.0.98",
|
|
3879
3902
|
]
|
|
3880
3903
|
|
|
3881
3904
|
[[package]]
|
|
@@ -3895,7 +3918,7 @@ checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808"
|
|
|
3895
3918
|
dependencies = [
|
|
3896
3919
|
"proc-macro2",
|
|
3897
3920
|
"quote",
|
|
3898
|
-
"syn 2.0.
|
|
3921
|
+
"syn 2.0.98",
|
|
3899
3922
|
"synstructure",
|
|
3900
3923
|
]
|
|
3901
3924
|
|
|
@@ -3924,7 +3947,7 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6"
|
|
|
3924
3947
|
dependencies = [
|
|
3925
3948
|
"proc-macro2",
|
|
3926
3949
|
"quote",
|
|
3927
|
-
"syn 2.0.
|
|
3950
|
+
"syn 2.0.98",
|
|
3928
3951
|
]
|
|
3929
3952
|
|
|
3930
3953
|
[[package]]
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: rusterize
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.1
|
|
4
4
|
Classifier: License :: OSI Approved :: MIT License
|
|
5
5
|
Classifier: Operating System :: OS Independent
|
|
6
6
|
Classifier: Programming Language :: Rust
|
|
7
7
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
8
8
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
9
|
-
Requires-Dist: geopandas
|
|
10
|
-
Requires-Dist: pandas
|
|
11
|
-
Requires-Dist: pyarrow
|
|
12
|
-
Requires-Dist: polars
|
|
13
|
-
Requires-Dist: xarray
|
|
14
|
-
Requires-Dist: rioxarray
|
|
9
|
+
Requires-Dist: geopandas>=1.0.1
|
|
10
|
+
Requires-Dist: pandas>=2.2.3
|
|
11
|
+
Requires-Dist: pyarrow>=18.1.0
|
|
12
|
+
Requires-Dist: polars>=1.19.0
|
|
13
|
+
Requires-Dist: xarray>=2025.1.1
|
|
14
|
+
Requires-Dist: rioxarray>=0.18.2
|
|
15
15
|
License-File: LICENSE
|
|
16
|
-
Summary: High performance rasterization tool for Python
|
|
16
|
+
Summary: High performance rasterization tool for Python built in Rust
|
|
17
17
|
Keywords: fast,raster
|
|
18
18
|
Requires-Python: >=3.10
|
|
19
19
|
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
|
|
@@ -21,9 +21,9 @@ Project-URL: repository, https://github.com/ttrotto/rusterize
|
|
|
21
21
|
|
|
22
22
|
# rusterize
|
|
23
23
|
|
|
24
|
-
High performance rasterization tool for
|
|
25
|
-
repository is heavily based on the [
|
|
26
|
-
for R. This version ports it to Python with a Rust backend.
|
|
24
|
+
High performance rasterization tool for Python built in Rust. This
|
|
25
|
+
repository is heavily based on the [fasterize](https://github.com/ecohealthalliance/fasterize.git) package built in C++
|
|
26
|
+
for R. This version ports it to Python with a Rust backend, with some useful improvements.
|
|
27
27
|
|
|
28
28
|
Functionally, it takes an input [geopandas](https://geopandas.org/en/stable/)
|
|
29
29
|
dataframes and returns a [xarray](https://docs.xarray.dev/en/stable/). It
|
|
@@ -34,7 +34,7 @@ tighly mirrors the processing routine of fasterize, so it works only on
|
|
|
34
34
|
|
|
35
35
|
Install the current version with pip:
|
|
36
36
|
|
|
37
|
-
```
|
|
37
|
+
``` shell
|
|
38
38
|
pip install rusterize
|
|
39
39
|
```
|
|
40
40
|
|
|
@@ -46,7 +46,7 @@ package. For this to work, you’ll need to have [Rust](https://www.rust-lang.or
|
|
|
46
46
|
[cargo](https://doc.rust-lang.org/cargo/getting-started/installation.html)
|
|
47
47
|
installed.
|
|
48
48
|
|
|
49
|
-
```
|
|
49
|
+
``` shell
|
|
50
50
|
# Clone repo
|
|
51
51
|
git clone https://github.com/<username>/rusterize.git
|
|
52
52
|
cd rusterize
|
|
@@ -65,22 +65,26 @@ maturin develop --profile dist-release
|
|
|
65
65
|
|
|
66
66
|
This function has a simple API:
|
|
67
67
|
|
|
68
|
-
```
|
|
68
|
+
``` python
|
|
69
69
|
from rusterize.core import rusterize
|
|
70
70
|
|
|
71
71
|
# gdf = <import datasets as needed>
|
|
72
72
|
|
|
73
73
|
# rusterize
|
|
74
74
|
rusterize(gdf,
|
|
75
|
-
(30, 30),
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
"
|
|
79
|
-
|
|
75
|
+
res=(30, 30),
|
|
76
|
+
out_shape=(10, 10)
|
|
77
|
+
extent=(0, 300, 0, 300)
|
|
78
|
+
field="field",
|
|
79
|
+
by="by",
|
|
80
|
+
fun="sum",
|
|
81
|
+
background=0)
|
|
80
82
|
```
|
|
81
83
|
|
|
82
84
|
- `gdf`: geopandas dataframe to rasterize
|
|
83
|
-
- `res`: tuple of (xres, yres) for
|
|
85
|
+
- `res`: tuple of (xres, yres) for desired resolution
|
|
86
|
+
- `out_shape`: tuple of (nrows, ncols) for desired output shape
|
|
87
|
+
- `extent`: tuple of (xmin, ymin, xmax, ymax) for desired output extent
|
|
84
88
|
- `field`: field to rasterize. Default is None (a value of `1` is rasterized).
|
|
85
89
|
- `by`: column to rasterize. Assigns each group to a band in the
|
|
86
90
|
stack. Values are taken from `field`. Default is None
|
|
@@ -88,10 +92,16 @@ rusterize(gdf,
|
|
|
88
92
|
`last`. Available options are `sum`, `first`, `last`, `min`, `max`, `count`, or `any`
|
|
89
93
|
- `background`: background value in final raster. Default is None (NaN)
|
|
90
94
|
|
|
95
|
+
Note that control over the desired extent is not as strict as for resolution and shape. That is,
|
|
96
|
+
when resolution, output shape, and extent are specified, priority is given to resolution and shape.
|
|
97
|
+
So, extent is not guaranteed, but resolution and shape are. If extent is not given, it is taken
|
|
98
|
+
from the polygons and is not modified, unless you specify a resolution value. If you only specify an output
|
|
99
|
+
shape, the extent is maintained. This mimics the logics of `gdal_rasterize`.
|
|
100
|
+
|
|
91
101
|
# Usage
|
|
92
102
|
|
|
93
103
|
**rusterize** consists of a single function `rusterize()`. The Rust implementation
|
|
94
|
-
returns an array that is
|
|
104
|
+
returns an array that is converted to a xarray on the Python side
|
|
95
105
|
for simpliicty.
|
|
96
106
|
|
|
97
107
|
``` python
|
|
@@ -127,12 +137,11 @@ output.plot.imshow(ax=ax)
|
|
|
127
137
|
plt.show()
|
|
128
138
|
```
|
|
129
139
|
|
|
130
|
-

|
|
131
141
|
|
|
132
142
|
# Benchmarks
|
|
133
143
|
|
|
134
|
-
**
|
|
135
|
-
datasets.
|
|
144
|
+
**rusterize** is fast! Let’s try it on small and large datasets.
|
|
136
145
|
|
|
137
146
|
``` python
|
|
138
147
|
from rusterize.core import rusterize
|
|
@@ -167,7 +176,7 @@ Then you can run it with [pytest](https://docs.pytest.org/en/stable/)
|
|
|
167
176
|
and
|
|
168
177
|
[pytest-benchmark](https://pytest-benchmark.readthedocs.io/en/stable/):
|
|
169
178
|
|
|
170
|
-
```
|
|
179
|
+
```
|
|
171
180
|
pytest <python file> --benchmark-min-rounds=20 --benchmark-time-unit='s'
|
|
172
181
|
|
|
173
182
|
--------------------------------------------- benchmark: 1 tests --------------------------------------------
|
|
@@ -180,7 +189,7 @@ test_small 0.5083 0.6416 0.5265 0.0393 0.5120 0.0108 2;
|
|
|
180
189
|
|
|
181
190
|
And fasterize:
|
|
182
191
|
|
|
183
|
-
```
|
|
192
|
+
``` r
|
|
184
193
|
large <- st_read("Mammals_Terrestrial/Mammals_Terrestrial.shp", quiet = TRUE)
|
|
185
194
|
small <- large[1:1000, ]
|
|
186
195
|
fn <- function(v) {
|
|
@@ -195,7 +204,7 @@ microbenchmark(
|
|
|
195
204
|
)
|
|
196
205
|
```
|
|
197
206
|
|
|
198
|
-
```
|
|
207
|
+
```
|
|
199
208
|
Unit: seconds
|
|
200
209
|
expr min lq mean median uq max neval
|
|
201
210
|
fasterize_large 9.565781 9.815375 10.02838 9.984965 10.18532 10.66656 20
|
|
@@ -207,7 +216,7 @@ And on even
|
|
|
207
216
|
datasets? This is a benchmark with 350K+ geometries rasterized at 30
|
|
208
217
|
meters (20 rounds) with no field value and pixel function `sum`.
|
|
209
218
|
|
|
210
|
-
```
|
|
219
|
+
```
|
|
211
220
|
# rusterize
|
|
212
221
|
--------------------------------------------- benchmark: 1 tests --------------------------------------------
|
|
213
222
|
Name (time in s) Min Max Mean StdDev Median IQR Outliers OPS Rounds Iterations
|
|
@@ -223,7 +232,7 @@ Unit: seconds
|
|
|
223
232
|
|
|
224
233
|
# Comparison with other tools
|
|
225
234
|
|
|
226
|
-
While `rusterize` is fast, there are other very fast solutions out there, including
|
|
235
|
+
While `rusterize` is fast, there are other very fast solutions out there, including:
|
|
227
236
|
- `GDAL`
|
|
228
237
|
- `rasterio`
|
|
229
238
|
- `geocube`
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# rusterize
|
|
2
2
|
|
|
3
|
-
High performance rasterization tool for
|
|
4
|
-
repository is heavily based on the [
|
|
5
|
-
for R. This version ports it to Python with a Rust backend.
|
|
3
|
+
High performance rasterization tool for Python built in Rust. This
|
|
4
|
+
repository is heavily based on the [fasterize](https://github.com/ecohealthalliance/fasterize.git) package built in C++
|
|
5
|
+
for R. This version ports it to Python with a Rust backend, with some useful improvements.
|
|
6
6
|
|
|
7
7
|
Functionally, it takes an input [geopandas](https://geopandas.org/en/stable/)
|
|
8
8
|
dataframes and returns a [xarray](https://docs.xarray.dev/en/stable/). It
|
|
@@ -13,7 +13,7 @@ tighly mirrors the processing routine of fasterize, so it works only on
|
|
|
13
13
|
|
|
14
14
|
Install the current version with pip:
|
|
15
15
|
|
|
16
|
-
```
|
|
16
|
+
``` shell
|
|
17
17
|
pip install rusterize
|
|
18
18
|
```
|
|
19
19
|
|
|
@@ -25,7 +25,7 @@ package. For this to work, you’ll need to have [Rust](https://www.rust-lang.or
|
|
|
25
25
|
[cargo](https://doc.rust-lang.org/cargo/getting-started/installation.html)
|
|
26
26
|
installed.
|
|
27
27
|
|
|
28
|
-
```
|
|
28
|
+
``` shell
|
|
29
29
|
# Clone repo
|
|
30
30
|
git clone https://github.com/<username>/rusterize.git
|
|
31
31
|
cd rusterize
|
|
@@ -44,22 +44,26 @@ maturin develop --profile dist-release
|
|
|
44
44
|
|
|
45
45
|
This function has a simple API:
|
|
46
46
|
|
|
47
|
-
```
|
|
47
|
+
``` python
|
|
48
48
|
from rusterize.core import rusterize
|
|
49
49
|
|
|
50
50
|
# gdf = <import datasets as needed>
|
|
51
51
|
|
|
52
52
|
# rusterize
|
|
53
53
|
rusterize(gdf,
|
|
54
|
-
(30, 30),
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
"
|
|
58
|
-
|
|
54
|
+
res=(30, 30),
|
|
55
|
+
out_shape=(10, 10)
|
|
56
|
+
extent=(0, 300, 0, 300)
|
|
57
|
+
field="field",
|
|
58
|
+
by="by",
|
|
59
|
+
fun="sum",
|
|
60
|
+
background=0)
|
|
59
61
|
```
|
|
60
62
|
|
|
61
63
|
- `gdf`: geopandas dataframe to rasterize
|
|
62
|
-
- `res`: tuple of (xres, yres) for
|
|
64
|
+
- `res`: tuple of (xres, yres) for desired resolution
|
|
65
|
+
- `out_shape`: tuple of (nrows, ncols) for desired output shape
|
|
66
|
+
- `extent`: tuple of (xmin, ymin, xmax, ymax) for desired output extent
|
|
63
67
|
- `field`: field to rasterize. Default is None (a value of `1` is rasterized).
|
|
64
68
|
- `by`: column to rasterize. Assigns each group to a band in the
|
|
65
69
|
stack. Values are taken from `field`. Default is None
|
|
@@ -67,10 +71,16 @@ rusterize(gdf,
|
|
|
67
71
|
`last`. Available options are `sum`, `first`, `last`, `min`, `max`, `count`, or `any`
|
|
68
72
|
- `background`: background value in final raster. Default is None (NaN)
|
|
69
73
|
|
|
74
|
+
Note that control over the desired extent is not as strict as for resolution and shape. That is,
|
|
75
|
+
when resolution, output shape, and extent are specified, priority is given to resolution and shape.
|
|
76
|
+
So, extent is not guaranteed, but resolution and shape are. If extent is not given, it is taken
|
|
77
|
+
from the polygons and is not modified, unless you specify a resolution value. If you only specify an output
|
|
78
|
+
shape, the extent is maintained. This mimics the logics of `gdal_rasterize`.
|
|
79
|
+
|
|
70
80
|
# Usage
|
|
71
81
|
|
|
72
82
|
**rusterize** consists of a single function `rusterize()`. The Rust implementation
|
|
73
|
-
returns an array that is
|
|
83
|
+
returns an array that is converted to a xarray on the Python side
|
|
74
84
|
for simpliicty.
|
|
75
85
|
|
|
76
86
|
``` python
|
|
@@ -106,12 +116,11 @@ output.plot.imshow(ax=ax)
|
|
|
106
116
|
plt.show()
|
|
107
117
|
```
|
|
108
118
|
|
|
109
|
-

|
|
110
120
|
|
|
111
121
|
# Benchmarks
|
|
112
122
|
|
|
113
|
-
**
|
|
114
|
-
datasets.
|
|
123
|
+
**rusterize** is fast! Let’s try it on small and large datasets.
|
|
115
124
|
|
|
116
125
|
``` python
|
|
117
126
|
from rusterize.core import rusterize
|
|
@@ -146,7 +155,7 @@ Then you can run it with [pytest](https://docs.pytest.org/en/stable/)
|
|
|
146
155
|
and
|
|
147
156
|
[pytest-benchmark](https://pytest-benchmark.readthedocs.io/en/stable/):
|
|
148
157
|
|
|
149
|
-
```
|
|
158
|
+
```
|
|
150
159
|
pytest <python file> --benchmark-min-rounds=20 --benchmark-time-unit='s'
|
|
151
160
|
|
|
152
161
|
--------------------------------------------- benchmark: 1 tests --------------------------------------------
|
|
@@ -159,7 +168,7 @@ test_small 0.5083 0.6416 0.5265 0.0393 0.5120 0.0108 2;
|
|
|
159
168
|
|
|
160
169
|
And fasterize:
|
|
161
170
|
|
|
162
|
-
```
|
|
171
|
+
``` r
|
|
163
172
|
large <- st_read("Mammals_Terrestrial/Mammals_Terrestrial.shp", quiet = TRUE)
|
|
164
173
|
small <- large[1:1000, ]
|
|
165
174
|
fn <- function(v) {
|
|
@@ -174,7 +183,7 @@ microbenchmark(
|
|
|
174
183
|
)
|
|
175
184
|
```
|
|
176
185
|
|
|
177
|
-
```
|
|
186
|
+
```
|
|
178
187
|
Unit: seconds
|
|
179
188
|
expr min lq mean median uq max neval
|
|
180
189
|
fasterize_large 9.565781 9.815375 10.02838 9.984965 10.18532 10.66656 20
|
|
@@ -186,7 +195,7 @@ And on even
|
|
|
186
195
|
datasets? This is a benchmark with 350K+ geometries rasterized at 30
|
|
187
196
|
meters (20 rounds) with no field value and pixel function `sum`.
|
|
188
197
|
|
|
189
|
-
```
|
|
198
|
+
```
|
|
190
199
|
# rusterize
|
|
191
200
|
--------------------------------------------- benchmark: 1 tests --------------------------------------------
|
|
192
201
|
Name (time in s) Min Max Mean StdDev Median IQR Outliers OPS Rounds Iterations
|
|
@@ -202,7 +211,7 @@ Unit: seconds
|
|
|
202
211
|
|
|
203
212
|
# Comparison with other tools
|
|
204
213
|
|
|
205
|
-
While `rusterize` is fast, there are other very fast solutions out there, including
|
|
214
|
+
While `rusterize` is fast, there are other very fast solutions out there, including:
|
|
206
215
|
- `GDAL`
|
|
207
216
|
- `rasterio`
|
|
208
217
|
- `geocube`
|
|
Binary file
|
|
@@ -4,7 +4,7 @@ build-backend = "maturin"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "rusterize"
|
|
7
|
-
description = "High performance rasterization tool for Python
|
|
7
|
+
description = "High performance rasterization tool for Python built in Rust"
|
|
8
8
|
readme = "README.md"
|
|
9
9
|
requires-python = ">=3.10"
|
|
10
10
|
license = {file = "LICENSE"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from types import NoneType
|
|
4
|
+
from typing import Any, Dict, Optional, Tuple, Union
|
|
5
|
+
|
|
6
|
+
import polars as pl
|
|
7
|
+
from pandas import DataFrame
|
|
8
|
+
import rioxarray
|
|
9
|
+
from xarray import DataArray
|
|
10
|
+
from .rusterize import _rusterize
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def rusterize(gdf: DataFrame,
|
|
14
|
+
res: Optional[Union[Tuple[int, ...], Tuple[float, ...]]] = None,
|
|
15
|
+
out_shape: Optional[Union[Tuple[int, ...]]] = None,
|
|
16
|
+
extent: Optional[Union[Tuple[int, ...], Tuple[float, ...]]] = None,
|
|
17
|
+
field: Optional[str] = None,
|
|
18
|
+
by: Optional[str] = None,
|
|
19
|
+
fun: str = "last",
|
|
20
|
+
background: Optional[Union[int, float]] = None,
|
|
21
|
+
) -> Dict[str, Any]:
|
|
22
|
+
"""
|
|
23
|
+
Fast geopandas rasterization into xarray.DataArray
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
:param gdf: geopandas dataframe to rasterize.
|
|
27
|
+
:param res: tuple of (xres, yres) for rasterized data.
|
|
28
|
+
:param out_shape: tuple of (nrows, ncols) for regularized output shape.
|
|
29
|
+
:param extent: tuple of (xmin, xmax, ymin, ymax) for regularized extent.
|
|
30
|
+
:param field: field to rasterize. Default is None.
|
|
31
|
+
:param by: column to rasterize, assigns each unique value to a layer in the stack based on field. Default is None.
|
|
32
|
+
:param fun: pixel function to use, see fasterize for options. Default is `last`.
|
|
33
|
+
:param background: background value in final raster. Default is None.
|
|
34
|
+
|
|
35
|
+
Returns:
|
|
36
|
+
Rasterized xarray.DataArray.
|
|
37
|
+
|
|
38
|
+
Note:
|
|
39
|
+
When any of `res`, `out_shape`, or `extent` is not provided, it is inferred from the other arguments when applicable.
|
|
40
|
+
Unless `extent` is specified, a half-pixel buffer is applied to avoid missing points on the border.
|
|
41
|
+
The logics dictating the final spatial properties of the rasterized geometries follow those of GDAL.
|
|
42
|
+
"""
|
|
43
|
+
# type checks
|
|
44
|
+
if not isinstance(gdf, DataFrame):
|
|
45
|
+
raise TypeError("Must pass a valid geopandas dataframe.")
|
|
46
|
+
if not isinstance(res, (tuple, NoneType)):
|
|
47
|
+
raise TypeError("Must pass a valid resolution tuple (x, y).")
|
|
48
|
+
if not isinstance(out_shape, (tuple, NoneType)):
|
|
49
|
+
raise TypeError("Must pass a valid output shape tuple (nrows, ncols).")
|
|
50
|
+
if not isinstance(extent, (tuple, NoneType)):
|
|
51
|
+
raise TypeError("Must pass a valid extent tuple (xmin, ymin, xmax, ymax).")
|
|
52
|
+
if not isinstance(field, (str, NoneType)):
|
|
53
|
+
raise TypeError("Must pass a valid string to field.")
|
|
54
|
+
if not isinstance(by, (str, NoneType)):
|
|
55
|
+
raise TypeError("Must pass a valid string to by.")
|
|
56
|
+
if not isinstance(fun, str):
|
|
57
|
+
raise TypeError("Must pass a valid string to pixel_fn. Select only of sum, first, last, min, max, count, or any.")
|
|
58
|
+
if not isinstance(background, (int, float, NoneType)):
|
|
59
|
+
raise TypeError("Must pass a valid background type.")
|
|
60
|
+
|
|
61
|
+
# value check
|
|
62
|
+
if not res and not out_shape and not extent:
|
|
63
|
+
raise ValueError("One of `res`, `out_shape`, or `extent` must be provided.")
|
|
64
|
+
if extent and not res and not out_shape:
|
|
65
|
+
raise ValueError("Must also specify `res` or `out_shape` with extent.")
|
|
66
|
+
if res and (len(res) != 2 or any(r <= 0 for r in res) or any(not isinstance(r, (int, float)) for r in res)):
|
|
67
|
+
raise ValueError("Resolution must be 2 positive numbers.")
|
|
68
|
+
if out_shape and (len(out_shape) != 2 or any(s <= 0 for s in out_shape) or any(not isinstance(s, int) for s in out_shape)):
|
|
69
|
+
raise ValueError("Output shape must be 2 positive integers.")
|
|
70
|
+
if extent and len(extent) != 4:
|
|
71
|
+
raise ValueError("Extent must be 4 numbers (xmin, ymin, xmax, ymax).")
|
|
72
|
+
if by and not field:
|
|
73
|
+
raise ValueError("If by is specified, field must also be specified.")
|
|
74
|
+
|
|
75
|
+
# defaults
|
|
76
|
+
_res = res if res else (0, 0)
|
|
77
|
+
_shape = out_shape if out_shape else (0, 0)
|
|
78
|
+
(_bounds, has_extent) = (extent, True) if extent else (gdf.total_bounds, False)
|
|
79
|
+
|
|
80
|
+
# RasterInfo
|
|
81
|
+
raster_info = {
|
|
82
|
+
"xmin": _bounds[0],
|
|
83
|
+
"ymin": _bounds[1],
|
|
84
|
+
"xmax": _bounds[2],
|
|
85
|
+
"ymax": _bounds[3],
|
|
86
|
+
"xres": _res[0],
|
|
87
|
+
"yres": _res[1],
|
|
88
|
+
"nrows": _shape[0],
|
|
89
|
+
"ncols": _shape[1],
|
|
90
|
+
"has_extent": has_extent
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
# extract columns of interest and convert to polars
|
|
94
|
+
cols = list(set([col for col in (field, by) if col]))
|
|
95
|
+
df = pl.from_pandas(gdf[cols]) if cols else None
|
|
96
|
+
|
|
97
|
+
# rusterize
|
|
98
|
+
r = _rusterize(
|
|
99
|
+
gdf.geometry,
|
|
100
|
+
raster_info,
|
|
101
|
+
fun,
|
|
102
|
+
df,
|
|
103
|
+
field,
|
|
104
|
+
by,
|
|
105
|
+
background
|
|
106
|
+
)
|
|
107
|
+
return DataArray.from_dict(r).rio.write_crs(gdf.crs, inplace=True)
|
|
@@ -79,10 +79,15 @@ pub fn validate_geometries(
|
|
|
79
79
|
.ok();
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
// update
|
|
83
|
-
|
|
84
|
-
|
|
82
|
+
// update RasterInfo spatial properties
|
|
83
|
+
if !raster_info.has_extent {
|
|
84
|
+
let bbox = bounding_rect(&geometry).unwrap();
|
|
85
|
+
println!("{:?}", bbox);
|
|
86
|
+
raster_info.update_bounds(bbox);
|
|
87
|
+
}
|
|
85
88
|
}
|
|
86
89
|
|
|
90
|
+
// update RasterInfo spatial properties
|
|
91
|
+
raster_info.update_dims();
|
|
87
92
|
(geometry, df)
|
|
88
93
|
}
|
|
@@ -20,26 +20,47 @@ pub struct RasterInfo {
|
|
|
20
20
|
pub ymax: f64,
|
|
21
21
|
pub xres: f64,
|
|
22
22
|
pub yres: f64,
|
|
23
|
+
pub has_extent: bool,
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
impl RasterInfo {
|
|
26
|
-
// map PyAny to RasterInfo
|
|
27
27
|
pub fn from(pyinfo: &Bound<PyAny>) -> Self {
|
|
28
|
+
// map PyAny to RasterInfo
|
|
28
29
|
let raster_info: RasterInfo = pyinfo
|
|
29
30
|
.extract()
|
|
30
31
|
.expect("Wrong mapping passed to RasterInfo struct");
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
32
|
+
|
|
33
|
+
raster_info
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
pub fn update_dims(&mut self) {
|
|
37
|
+
// extend bounds by half pixel to avoid missing points on the border
|
|
38
|
+
if !self.has_extent && self.xres != 0.0 {
|
|
39
|
+
self.xmin -= self.xres / 2.0;
|
|
40
|
+
self.xmax += self.xres / 2.0;
|
|
41
|
+
self.ymin -= self.yres / 2.0;
|
|
42
|
+
self.ymax += self.yres / 2.0;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// calculate resolution
|
|
46
|
+
if self.xres == 0.0 {
|
|
47
|
+
self.resolution();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// calculate shape
|
|
51
|
+
if self.nrows == 0 {
|
|
52
|
+
self.shape();
|
|
36
53
|
}
|
|
37
54
|
}
|
|
38
55
|
|
|
39
|
-
fn shape(&self)
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
56
|
+
fn shape(&mut self) {
|
|
57
|
+
self.nrows = ((self.ymax - self.ymin) / self.yres).round() as usize;
|
|
58
|
+
self.ncols = ((self.xmax - self.xmin) / self.xres).round() as usize;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
fn resolution(&mut self) {
|
|
62
|
+
self.xres = (self.xmax - self.xmin) / self.ncols as f64;
|
|
63
|
+
self.yres = (self.ymax - self.ymin) / self.nrows as f64;
|
|
43
64
|
}
|
|
44
65
|
|
|
45
66
|
pub fn update_bounds(&mut self, rect: Rect) {
|
|
@@ -48,11 +69,6 @@ impl RasterInfo {
|
|
|
48
69
|
self.xmax = rect.max().x;
|
|
49
70
|
self.ymin = rect.min().y;
|
|
50
71
|
self.ymax = rect.max().y;
|
|
51
|
-
|
|
52
|
-
// recalculate shape
|
|
53
|
-
let (nrows, ncols) = self.shape();
|
|
54
|
-
self.nrows = nrows;
|
|
55
|
-
self.ncols = ncols;
|
|
56
72
|
}
|
|
57
73
|
|
|
58
74
|
pub fn build_raster(&self, bands: usize, background: f64) -> Array3<f64> {
|
|
@@ -66,13 +82,13 @@ impl RasterInfo {
|
|
|
66
82
|
) -> (Bound<'py, PyArray1<f64>>, Bound<'py, PyArray1<f64>>) {
|
|
67
83
|
let y_coords = Array::range(
|
|
68
84
|
self.ymax - self.yres / 2.0,
|
|
69
|
-
self.ymax - self.nrows as f64 * self.yres
|
|
85
|
+
self.ymax - self.nrows as f64 * self.yres,
|
|
70
86
|
-self.yres,
|
|
71
87
|
)
|
|
72
88
|
.into_pyarray_bound(py);
|
|
73
89
|
let x_coords = Array::range(
|
|
74
90
|
self.xmin + self.xres / 2.0,
|
|
75
|
-
self.xmin + self.ncols as f64 * self.xres
|
|
91
|
+
self.xmin + self.ncols as f64 * self.xres,
|
|
76
92
|
self.xres,
|
|
77
93
|
)
|
|
78
94
|
.into_pyarray_bound(py);
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from typing import Any, Dict, Optional, Tuple, Union
|
|
4
|
-
|
|
5
|
-
import polars as pl
|
|
6
|
-
from pandas import DataFrame
|
|
7
|
-
import rioxarray
|
|
8
|
-
from xarray import DataArray
|
|
9
|
-
from .rusterize import _rusterize
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
def rusterize(gdf: DataFrame,
|
|
13
|
-
res: Union[Tuple[int, ...], Tuple[float, ...]],
|
|
14
|
-
field: Optional[str] = None,
|
|
15
|
-
by: Optional[str] = None,
|
|
16
|
-
fun: str = "last",
|
|
17
|
-
background: Optional[Union[int, float]] = None,
|
|
18
|
-
) -> Dict[str, Any]:
|
|
19
|
-
"""
|
|
20
|
-
Fast geopandas rasterization into xarray.DataArray
|
|
21
|
-
|
|
22
|
-
Args:
|
|
23
|
-
:param gdf: geopandas dataframe to rasterize.
|
|
24
|
-
:param res: tuple of (xres, yres) for rasterized data.
|
|
25
|
-
:param field: field to rasterize. Default is None.
|
|
26
|
-
:param by: column to rasterize, assigns each unique value to a layer in the stack based on field. Default is None.
|
|
27
|
-
:param fun: pixel function to use, see fasterize for options. Default is `last`.
|
|
28
|
-
:param background: background value in final raster. Default is None.
|
|
29
|
-
|
|
30
|
-
Returns:
|
|
31
|
-
Dictionary containing rasterized geometries and spatial attributes to build a xarray.DataArray.
|
|
32
|
-
"""
|
|
33
|
-
# type checks
|
|
34
|
-
if not isinstance(gdf, DataFrame):
|
|
35
|
-
raise TypeError("Must pass a valid geopandas dataframe.")
|
|
36
|
-
if not isinstance(field, (str, type(None))):
|
|
37
|
-
raise TypeError("Must pass a valid string to field.")
|
|
38
|
-
if not isinstance(by, (str, type(None))):
|
|
39
|
-
raise TypeError("Must pass a valid string to by.")
|
|
40
|
-
if not isinstance(res, tuple):
|
|
41
|
-
raise TypeError("Must pass a valid resolution tuple (x, y).")
|
|
42
|
-
if not isinstance(fun, str):
|
|
43
|
-
raise TypeError("Must pass a valid string to pixel_fn. Select only of sum, first, last, min, max, count, or any.")
|
|
44
|
-
if not isinstance(background, (int, float, type(None))):
|
|
45
|
-
raise TypeError("Must pass a valid background type.")
|
|
46
|
-
|
|
47
|
-
# value check
|
|
48
|
-
if by and not field:
|
|
49
|
-
raise ValueError("If by is specified, field must also be specified.")
|
|
50
|
-
if len(res) != 2 or any((res[0], res[1])) <= 0 or not isinstance(res[0], type(res[1])):
|
|
51
|
-
raise ValueError("Must pass valid resolution tuple of values of consistent dtype.")
|
|
52
|
-
|
|
53
|
-
# RasterInfo
|
|
54
|
-
bounds = gdf.total_bounds
|
|
55
|
-
raster_info = {
|
|
56
|
-
"xmin": bounds[0],
|
|
57
|
-
"ymin": bounds[1],
|
|
58
|
-
"xmax": bounds[2],
|
|
59
|
-
"ymax": bounds[3],
|
|
60
|
-
"xres": res[0],
|
|
61
|
-
"yres": res[1],
|
|
62
|
-
"nrows": 0,
|
|
63
|
-
"ncols": 0
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
# extract columns of interest and convert to polars
|
|
67
|
-
cols = list(set([col for col in (field, by) if col]))
|
|
68
|
-
df = pl.from_pandas(gdf[cols]) if cols else None
|
|
69
|
-
|
|
70
|
-
# rusterize
|
|
71
|
-
r = _rusterize(
|
|
72
|
-
gdf.geometry,
|
|
73
|
-
raster_info,
|
|
74
|
-
fun,
|
|
75
|
-
df,
|
|
76
|
-
field,
|
|
77
|
-
by,
|
|
78
|
-
background
|
|
79
|
-
)
|
|
80
|
-
return DataArray.from_dict(r).rio.write_crs(gdf.crs, inplace=True)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|