openrelief 0.1.0__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.
@@ -0,0 +1,28 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Naveen
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
23
+ ---
24
+
25
+ The MIT license above covers the source code of this package only. It is not a
26
+ patent grant and makes no representation about third-party intellectual
27
+ property. See NOTICE for attribution and an intellectual-property note about
28
+ the red-relief visualization technique this software implements.
@@ -0,0 +1,6 @@
1
+ include LICENSE
2
+ include NOTICE
3
+ include README.md
4
+ include pyproject.toml
5
+ recursive-include src/openrelief *.py
6
+ include src/openrelief/py.typed
@@ -0,0 +1,50 @@
1
+ openrelief
2
+ ==========
3
+
4
+ This software is an independent, open-source implementation of a terrain
5
+ visualization technique that combines topographic slope with positive and
6
+ negative topographic openness, rendered as a red-shaded relief image. The
7
+ technique is commonly known as the "Red Relief Image Map" (RRIM).
8
+
9
+ Attribution
10
+ -----------
11
+ The red-relief image map method was developed by Tatsuro Chiba, Shin-ichi
12
+ Kaneta and Yusuke Suzuki at Asia Air Survey Co., Ltd. The topographic openness
13
+ measure it builds on was introduced by Ryuzo Yokoyama, Michio Shirasawa and
14
+ Richard J. Pike. This package reimplements those published methods from the
15
+ academic literature; it is not produced, endorsed by, or affiliated with Asia
16
+ Air Survey Co., Ltd.
17
+
18
+ Trademarks
19
+ ----------
20
+ "RRIM", "Red Relief Image Map", and "赤色立体地図" are used or claimed as
21
+ trademarks of Asia Air Survey Co., Ltd. Those names are referenced here only to
22
+ describe the method this software implements (nominative use). This package is
23
+ deliberately named "openrelief" and does not use those marks as its product
24
+ name or branding. Do not market derivatives of this software under those marks.
25
+
26
+ Intellectual-property note
27
+ --------------------------
28
+ The RRIM method was patented by Asia Air Survey Co., Ltd., with patent family
29
+ members filed in Japan, the United States, China and Taiwan (e.g. JP 3670274).
30
+ These patents derive from filings in the early 2000s and, based on the standard
31
+ ~20-year patent term, the relevant patents appear to have expired. Patent
32
+ status is jurisdiction-specific and time-sensitive, and nothing here is legal
33
+ advice. Before publishing, redistributing, or building a commercial product on
34
+ this software, independently verify the current legal status of the relevant
35
+ patents in every jurisdiction that matters to you (e.g. J-PlatPat for Japan,
36
+ the USPTO / Google Patents for the United States), and consult a qualified
37
+ intellectual-property attorney if anything material depends on it.
38
+
39
+ Citation
40
+ --------
41
+ If you use this software in academic work, please cite the original methods:
42
+
43
+ Chiba, T., Kaneta, S., & Suzuki, Y. (2008). Red relief image map: new
44
+ visualization method for three-dimensional data. International Archives of
45
+ the Photogrammetry, Remote Sensing and Spatial Information Sciences,
46
+ XXXVII(B2), 1071-1076.
47
+
48
+ Yokoyama, R., Shirasawa, M., & Pike, R. J. (2002). Visualizing topography by
49
+ openness: a new application of image processing to digital elevation models.
50
+ Photogrammetric Engineering & Remote Sensing, 68(3), 257-265.
@@ -0,0 +1,208 @@
1
+ Metadata-Version: 2.4
2
+ Name: openrelief
3
+ Version: 0.1.0
4
+ Summary: Red-shaded terrain relief (the Red Relief Image Map / RRIM technique) from Digital Elevation Models, with parallel CPU and optional GPU acceleration.
5
+ Author-email: Naveen <nvnsudharsan@gmail.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/nvnsudharsan/openrelief
8
+ Project-URL: Repository, https://github.com/nvnsudharsan/openrelief
9
+ Project-URL: Issues, https://github.com/nvnsudharsan/openrelief/issues
10
+ Keywords: red relief,RRIM,DEM,topographic openness,terrain,hillshade,lidar,GIS,raster,visualization
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Science/Research
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.9
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Topic :: Scientific/Engineering :: GIS
21
+ Classifier: Topic :: Scientific/Engineering :: Visualization
22
+ Requires-Python: >=3.9
23
+ Description-Content-Type: text/markdown
24
+ License-File: LICENSE
25
+ License-File: NOTICE
26
+ Requires-Dist: numpy>=1.21
27
+ Requires-Dist: rasterio>=1.3
28
+ Requires-Dist: scipy>=1.7
29
+ Requires-Dist: joblib>=1.4
30
+ Requires-Dist: Pillow>=9.0
31
+ Provides-Extra: gpu
32
+ Requires-Dist: cupy-cuda12x; extra == "gpu"
33
+ Provides-Extra: dev
34
+ Requires-Dist: pytest; extra == "dev"
35
+ Requires-Dist: build; extra == "dev"
36
+ Requires-Dist: twine; extra == "dev"
37
+ Dynamic: license-file
38
+
39
+ # openrelief — red-shaded terrain relief from DEMs
40
+
41
+ `openrelief` turns any Digital Elevation Model into a **red-shaded relief image**
42
+ that combines topographic slope with positive/negative **topographic openness** —
43
+ the visualization widely known as the *Red Relief Image Map* (RRIM). Give it a
44
+ DEM (or a folder/glob of DEM tiles) and it produces a seamless georeferenced RGB
45
+ GeoTIFF plus a PNG preview.
46
+
47
+ > **Note on naming and IP.** This is an independent, open-source reimplementation
48
+ > of a published method. The package is intentionally named `openrelief` and
49
+ > avoids the *RRIM* / *Red Relief Image Map* trademarks as branding. The RRIM
50
+ > method was developed and patented by Asia Air Survey Co., Ltd.; those patents
51
+ > appear to have expired, but you should verify this yourself before publishing
52
+ > or commercializing. See [NOTICE](NOTICE) for attribution, citation, trademark
53
+ > and patent details, and [LICENSE](LICENSE) for the code license.
54
+
55
+ * **Any DEM** rasterio can read: GeoTIFF, USGS `.dem`, ERDAS `.img`, ArcInfo
56
+ `.asc`, `.bil/.flt`, SRTM `.hgt`, `.vrt`, … — CRS, no-data, pixel size and
57
+ elevation unit are all read from the file, nothing is hard-coded.
58
+ * **Seamless mosaics** — multiple tiles are stitched through an in-memory VRT and
59
+ processed in overlapping windows (a halo equal to the openness radius), so
60
+ there are no seams at tile boundaries.
61
+ * **Parallel** across windows on the CPU (joblib) and **GPU-accelerated**
62
+ automatically when [CuPy](https://cupy.dev) + a CUDA device are present.
63
+ * **Fully tunable** — every visual knob (openness radius, slope clip, gammas,
64
+ blend opacity, …) is exposed, with defaults matching the classic look.
65
+
66
+ ---
67
+
68
+ ## How the image is built
69
+
70
+ For every cell the package computes:
71
+
72
+ 1. **Slope** (degrees) → red saturation. Flat = white `(255,255,255)`, steep =
73
+ pure red `(255,0,0)`.
74
+ 2. **Topographic openness** (Yokoyama et al., 2002) in `--directions` azimuths
75
+ out to `--radius` pixels: positive openness (high on ridges) and negative
76
+ openness (high in valleys).
77
+ 3. **Differential openness** `(positive − negative) / 2` → brightness. Ridges
78
+ render light, valleys dark — this gives the floating-3D relief.
79
+ 4. The grey openness layer is **multiply-blended** onto the red slope layer at
80
+ `--opacity` (0.5 by default). Method reference: Chiba, Kaneta & Suzuki (2008).
81
+
82
+ Horizontal distances are converted to **ground metres** automatically (linear
83
+ unit for projected CRSs; degrees→metres at the scene latitude for geographic
84
+ CRSs), so the relief is geometrically correct for any projection. If your
85
+ elevation unit differs from the horizontal unit, set `--z-factor` (e.g. `0.3048`
86
+ for feet-Z over metre-XY).
87
+
88
+ ---
89
+
90
+ ## Install
91
+
92
+ ```bash
93
+ pip install -e . # from this folder
94
+ ```
95
+
96
+ Core deps: `numpy`, `rasterio`, `scipy`, `joblib`, `Pillow`.
97
+
98
+ **GPU (optional):** install the CuPy wheel for your CUDA toolkit, e.g.
99
+
100
+ ```bash
101
+ pip install cupy-cuda12x # CUDA 12.x (or cupy-cuda11x)
102
+ ```
103
+
104
+ When CuPy and a GPU are present the GPU is used automatically. Check with:
105
+
106
+ ```bash
107
+ openrelief --check-gpu
108
+ ```
109
+
110
+ ---
111
+
112
+ ## Command line
113
+
114
+ ```bash
115
+ # Single DEM
116
+ openrelief dem.tif -o relief.tif
117
+
118
+ # A whole folder of tiles -> one seamless mosaic + preview
119
+ openrelief /path/to/dems/ -o area_relief.tif
120
+
121
+ # A glob, tuned for flat terrain, forced GPU
122
+ openrelief "tiles/*.dem" -o relief.tif --slope-max 15 --openness-range 12 --radius 40 --gpu
123
+ ```
124
+
125
+ Useful options (`openrelief -h` for all):
126
+
127
+ | Option | Meaning | Default |
128
+ |---|---|---|
129
+ | `--radius` | openness search length (px) | 30 |
130
+ | `--directions` | azimuths sampled (4/8/16) | 8 |
131
+ | `--openness-range` | diff-openness deg → black..white | 30 |
132
+ | `--slope-max` | slope deg → full red | 50 |
133
+ | `--slope-gamma` / `--openness-gamma` | tone curves | 1.0 |
134
+ | `--opacity` | openness layer blend (0..1) | 0.5 |
135
+ | `--z-factor` | elevation→ground unit multiplier | 1.0 |
136
+ | `--window` | processing window (px) | 2048 |
137
+ | `--jobs` | CPU workers (-1 = all cores) | -1 |
138
+ | `--auto-window` | size windows from the core count | off |
139
+ | `--tiles-per-core` | with `--auto-window`, tiles/core (1 = one tile per processor) | 4 |
140
+ | `--gpu` / `--cpu` | force a backend | auto |
141
+ | `--compress` | deflate/lzw/zstd/none | deflate |
142
+ | `--no-preview` / `--preview-size` | PNG quick-look | on / 4000 |
143
+
144
+ **Tuning tip:** flatter terrain wants smaller `--slope-max` and
145
+ `--openness-range` (more contrast); rugged terrain wants larger values. A larger
146
+ `--radius` broadens the relief but costs ~linearly more compute.
147
+
148
+ ---
149
+
150
+ ## Python API
151
+
152
+ ```python
153
+ from openrelief import ReliefConfig, relief_from_dems, relief_array
154
+
155
+ # High-level: DEM(s) -> GeoTIFF + PNG
156
+ relief_from_dems("tiles/", "out.tif",
157
+ ReliefConfig(openness_radius=40, slope_max=20))
158
+
159
+ # Low-level: a NumPy elevation array -> (3, H, W) uint8 relief
160
+ import numpy as np
161
+ rgb = relief_array(dem_array, res_x=1.0, res_y=1.0,
162
+ cfg=ReliefConfig(openness_radius=24))
163
+ ```
164
+
165
+ `ReliefConfig` carries every parameter above; `use_gpu=None/True/False` controls
166
+ the backend. You can also force a backend globally with the
167
+ `OPENRELIEF_BACKEND=cpu|gpu` environment variable.
168
+
169
+ ---
170
+
171
+ ## How it scales
172
+
173
+ Cost is roughly `O(8 · radius · pixels)`. The raster is split into independent
174
+ `--window`-sized tiles with a `radius`-pixel halo:
175
+
176
+ * **CPU:** windows are distributed over processes with joblib and streamed to the
177
+ output as they finish, so memory stays bounded regardless of mosaic size. By
178
+ default there are more windows than cores so a freed worker immediately picks
179
+ up the next one (dynamic load balancing). `--auto-window` instead sizes the
180
+ windows from the core count: `--tiles-per-core 1` gives one tile per
181
+ processor (simplest, but prone to stragglers and high per-worker memory),
182
+ while the default of 4 keeps every core fed. The pixels produced are identical
183
+ either way — only the scheduling changes.
184
+ * **GPU:** windows are streamed to the device sequentially; the per-window size
185
+ keeps GPU memory in check while still giving a large speed-up.
186
+
187
+ Output GeoTIFFs are tiled and compressed (`BIGTIFF=IF_SAFER`), so very large
188
+ mosaics are handled gracefully. Empty windows in a sparse mosaic are skipped.
189
+
190
+ ---
191
+
192
+ ## Attribution & citation
193
+
194
+ This package reimplements published methods. Please credit the original authors;
195
+ full details and references are in [NOTICE](NOTICE).
196
+
197
+ * Chiba, T., Kaneta, S., & Suzuki, Y. (2008). *Red relief image map: new
198
+ visualization method for three-dimensional data.* ISPRS Archives,
199
+ XXXVII(B2), 1071–1076.
200
+ * Yokoyama, R., Shirasawa, M., & Pike, R. J. (2002). *Visualizing topography by
201
+ openness.* PE&RS 68(3), 257–265.
202
+ * Asia Air Survey — https://www.rrim.jp/en/
203
+
204
+ ## License
205
+
206
+ Source code: MIT (see [LICENSE](LICENSE)). The MIT license covers this code only
207
+ and is not a patent grant; see [NOTICE](NOTICE) for the intellectual-property
208
+ note.
@@ -0,0 +1,170 @@
1
+ # openrelief — red-shaded terrain relief from DEMs
2
+
3
+ `openrelief` turns any Digital Elevation Model into a **red-shaded relief image**
4
+ that combines topographic slope with positive/negative **topographic openness** —
5
+ the visualization widely known as the *Red Relief Image Map* (RRIM). Give it a
6
+ DEM (or a folder/glob of DEM tiles) and it produces a seamless georeferenced RGB
7
+ GeoTIFF plus a PNG preview.
8
+
9
+ > **Note on naming and IP.** This is an independent, open-source reimplementation
10
+ > of a published method. The package is intentionally named `openrelief` and
11
+ > avoids the *RRIM* / *Red Relief Image Map* trademarks as branding. The RRIM
12
+ > method was developed and patented by Asia Air Survey Co., Ltd.; those patents
13
+ > appear to have expired, but you should verify this yourself before publishing
14
+ > or commercializing. See [NOTICE](NOTICE) for attribution, citation, trademark
15
+ > and patent details, and [LICENSE](LICENSE) for the code license.
16
+
17
+ * **Any DEM** rasterio can read: GeoTIFF, USGS `.dem`, ERDAS `.img`, ArcInfo
18
+ `.asc`, `.bil/.flt`, SRTM `.hgt`, `.vrt`, … — CRS, no-data, pixel size and
19
+ elevation unit are all read from the file, nothing is hard-coded.
20
+ * **Seamless mosaics** — multiple tiles are stitched through an in-memory VRT and
21
+ processed in overlapping windows (a halo equal to the openness radius), so
22
+ there are no seams at tile boundaries.
23
+ * **Parallel** across windows on the CPU (joblib) and **GPU-accelerated**
24
+ automatically when [CuPy](https://cupy.dev) + a CUDA device are present.
25
+ * **Fully tunable** — every visual knob (openness radius, slope clip, gammas,
26
+ blend opacity, …) is exposed, with defaults matching the classic look.
27
+
28
+ ---
29
+
30
+ ## How the image is built
31
+
32
+ For every cell the package computes:
33
+
34
+ 1. **Slope** (degrees) → red saturation. Flat = white `(255,255,255)`, steep =
35
+ pure red `(255,0,0)`.
36
+ 2. **Topographic openness** (Yokoyama et al., 2002) in `--directions` azimuths
37
+ out to `--radius` pixels: positive openness (high on ridges) and negative
38
+ openness (high in valleys).
39
+ 3. **Differential openness** `(positive − negative) / 2` → brightness. Ridges
40
+ render light, valleys dark — this gives the floating-3D relief.
41
+ 4. The grey openness layer is **multiply-blended** onto the red slope layer at
42
+ `--opacity` (0.5 by default). Method reference: Chiba, Kaneta & Suzuki (2008).
43
+
44
+ Horizontal distances are converted to **ground metres** automatically (linear
45
+ unit for projected CRSs; degrees→metres at the scene latitude for geographic
46
+ CRSs), so the relief is geometrically correct for any projection. If your
47
+ elevation unit differs from the horizontal unit, set `--z-factor` (e.g. `0.3048`
48
+ for feet-Z over metre-XY).
49
+
50
+ ---
51
+
52
+ ## Install
53
+
54
+ ```bash
55
+ pip install -e . # from this folder
56
+ ```
57
+
58
+ Core deps: `numpy`, `rasterio`, `scipy`, `joblib`, `Pillow`.
59
+
60
+ **GPU (optional):** install the CuPy wheel for your CUDA toolkit, e.g.
61
+
62
+ ```bash
63
+ pip install cupy-cuda12x # CUDA 12.x (or cupy-cuda11x)
64
+ ```
65
+
66
+ When CuPy and a GPU are present the GPU is used automatically. Check with:
67
+
68
+ ```bash
69
+ openrelief --check-gpu
70
+ ```
71
+
72
+ ---
73
+
74
+ ## Command line
75
+
76
+ ```bash
77
+ # Single DEM
78
+ openrelief dem.tif -o relief.tif
79
+
80
+ # A whole folder of tiles -> one seamless mosaic + preview
81
+ openrelief /path/to/dems/ -o area_relief.tif
82
+
83
+ # A glob, tuned for flat terrain, forced GPU
84
+ openrelief "tiles/*.dem" -o relief.tif --slope-max 15 --openness-range 12 --radius 40 --gpu
85
+ ```
86
+
87
+ Useful options (`openrelief -h` for all):
88
+
89
+ | Option | Meaning | Default |
90
+ |---|---|---|
91
+ | `--radius` | openness search length (px) | 30 |
92
+ | `--directions` | azimuths sampled (4/8/16) | 8 |
93
+ | `--openness-range` | diff-openness deg → black..white | 30 |
94
+ | `--slope-max` | slope deg → full red | 50 |
95
+ | `--slope-gamma` / `--openness-gamma` | tone curves | 1.0 |
96
+ | `--opacity` | openness layer blend (0..1) | 0.5 |
97
+ | `--z-factor` | elevation→ground unit multiplier | 1.0 |
98
+ | `--window` | processing window (px) | 2048 |
99
+ | `--jobs` | CPU workers (-1 = all cores) | -1 |
100
+ | `--auto-window` | size windows from the core count | off |
101
+ | `--tiles-per-core` | with `--auto-window`, tiles/core (1 = one tile per processor) | 4 |
102
+ | `--gpu` / `--cpu` | force a backend | auto |
103
+ | `--compress` | deflate/lzw/zstd/none | deflate |
104
+ | `--no-preview` / `--preview-size` | PNG quick-look | on / 4000 |
105
+
106
+ **Tuning tip:** flatter terrain wants smaller `--slope-max` and
107
+ `--openness-range` (more contrast); rugged terrain wants larger values. A larger
108
+ `--radius` broadens the relief but costs ~linearly more compute.
109
+
110
+ ---
111
+
112
+ ## Python API
113
+
114
+ ```python
115
+ from openrelief import ReliefConfig, relief_from_dems, relief_array
116
+
117
+ # High-level: DEM(s) -> GeoTIFF + PNG
118
+ relief_from_dems("tiles/", "out.tif",
119
+ ReliefConfig(openness_radius=40, slope_max=20))
120
+
121
+ # Low-level: a NumPy elevation array -> (3, H, W) uint8 relief
122
+ import numpy as np
123
+ rgb = relief_array(dem_array, res_x=1.0, res_y=1.0,
124
+ cfg=ReliefConfig(openness_radius=24))
125
+ ```
126
+
127
+ `ReliefConfig` carries every parameter above; `use_gpu=None/True/False` controls
128
+ the backend. You can also force a backend globally with the
129
+ `OPENRELIEF_BACKEND=cpu|gpu` environment variable.
130
+
131
+ ---
132
+
133
+ ## How it scales
134
+
135
+ Cost is roughly `O(8 · radius · pixels)`. The raster is split into independent
136
+ `--window`-sized tiles with a `radius`-pixel halo:
137
+
138
+ * **CPU:** windows are distributed over processes with joblib and streamed to the
139
+ output as they finish, so memory stays bounded regardless of mosaic size. By
140
+ default there are more windows than cores so a freed worker immediately picks
141
+ up the next one (dynamic load balancing). `--auto-window` instead sizes the
142
+ windows from the core count: `--tiles-per-core 1` gives one tile per
143
+ processor (simplest, but prone to stragglers and high per-worker memory),
144
+ while the default of 4 keeps every core fed. The pixels produced are identical
145
+ either way — only the scheduling changes.
146
+ * **GPU:** windows are streamed to the device sequentially; the per-window size
147
+ keeps GPU memory in check while still giving a large speed-up.
148
+
149
+ Output GeoTIFFs are tiled and compressed (`BIGTIFF=IF_SAFER`), so very large
150
+ mosaics are handled gracefully. Empty windows in a sparse mosaic are skipped.
151
+
152
+ ---
153
+
154
+ ## Attribution & citation
155
+
156
+ This package reimplements published methods. Please credit the original authors;
157
+ full details and references are in [NOTICE](NOTICE).
158
+
159
+ * Chiba, T., Kaneta, S., & Suzuki, Y. (2008). *Red relief image map: new
160
+ visualization method for three-dimensional data.* ISPRS Archives,
161
+ XXXVII(B2), 1071–1076.
162
+ * Yokoyama, R., Shirasawa, M., & Pike, R. J. (2002). *Visualizing topography by
163
+ openness.* PE&RS 68(3), 257–265.
164
+ * Asia Air Survey — https://www.rrim.jp/en/
165
+
166
+ ## License
167
+
168
+ Source code: MIT (see [LICENSE](LICENSE)). The MIT license covers this code only
169
+ and is not a patent grant; see [NOTICE](NOTICE) for the intellectual-property
170
+ note.
@@ -0,0 +1,55 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "openrelief"
7
+ version = "0.1.0"
8
+ description = "Red-shaded terrain relief (the Red Relief Image Map / RRIM technique) from Digital Elevation Models, with parallel CPU and optional GPU acceleration."
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ license = { text = "MIT" }
12
+ authors = [{ name = "Naveen", email = "nvnsudharsan@gmail.com" }]
13
+ keywords = ["red relief", "RRIM", "DEM", "topographic openness", "terrain",
14
+ "hillshade", "lidar", "GIS", "raster", "visualization"]
15
+ classifiers = [
16
+ "Development Status :: 4 - Beta",
17
+ "Intended Audience :: Science/Research",
18
+ "License :: OSI Approved :: MIT License",
19
+ "Operating System :: OS Independent",
20
+ "Programming Language :: Python :: 3",
21
+ "Programming Language :: Python :: 3.9",
22
+ "Programming Language :: Python :: 3.10",
23
+ "Programming Language :: Python :: 3.11",
24
+ "Programming Language :: Python :: 3.12",
25
+ "Topic :: Scientific/Engineering :: GIS",
26
+ "Topic :: Scientific/Engineering :: Visualization",
27
+ ]
28
+
29
+ dependencies = [
30
+ "numpy>=1.21",
31
+ "rasterio>=1.3",
32
+ "scipy>=1.7",
33
+ "joblib>=1.4",
34
+ "Pillow>=9.0",
35
+ ]
36
+
37
+ [project.optional-dependencies]
38
+ # Install the wheel that matches your CUDA toolkit, e.g. cupy-cuda12x
39
+ gpu = ["cupy-cuda12x"]
40
+ dev = ["pytest", "build", "twine"]
41
+
42
+ # NOTE: update nvnsudharsan to your GitHub handle before publishing.
43
+ [project.urls]
44
+ Homepage = "https://github.com/nvnsudharsan/openrelief"
45
+ Repository = "https://github.com/nvnsudharsan/openrelief"
46
+ Issues = "https://github.com/nvnsudharsan/openrelief/issues"
47
+
48
+ [project.scripts]
49
+ openrelief = "openrelief.cli:main"
50
+
51
+ [tool.setuptools.packages.find]
52
+ where = ["src"]
53
+
54
+ [tool.setuptools.package-data]
55
+ openrelief = ["py.typed"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,22 @@
1
+ """rrim - Red Relief Image Map generation from Digital Elevation Models.
2
+
3
+ Public API
4
+ ----------
5
+ from openrelief import ReliefConfig, relief_from_dems, relief_array
6
+
7
+ `relief_from_dems` is the high-level entry point: give it one or more DEM files
8
+ and it builds a seamless RRIM mosaic GeoTIFF (and optional PNG preview),
9
+ processing windows in parallel and using a GPU automatically when available.
10
+ """
11
+ from .config import ReliefConfig
12
+ from .backend import gpu_available
13
+ from .core import relief_from_dems, relief_array
14
+
15
+ __version__ = "0.1.0"
16
+ __all__ = [
17
+ "ReliefConfig",
18
+ "relief_from_dems",
19
+ "relief_array",
20
+ "gpu_available",
21
+ "__version__",
22
+ ]
@@ -0,0 +1,66 @@
1
+ """Array-backend selection: NumPy (CPU) or CuPy (GPU).
2
+
3
+ The rest of the package is written against a generic array module ``xp`` so the
4
+ exact same kernels run on CPU and GPU. GPU is used automatically when CuPy is
5
+ installed *and* a CUDA device is visible, unless the caller forces a backend.
6
+ """
7
+ from __future__ import annotations
8
+
9
+ import os
10
+ from typing import Any, Tuple
11
+
12
+ import numpy as np
13
+
14
+ _FORCE = os.environ.get("OPENRELIEF_BACKEND", "").lower() # "cpu", "gpu", or ""
15
+
16
+
17
+ def gpu_available() -> bool:
18
+ """True if CuPy is importable and at least one CUDA device is present."""
19
+ if _FORCE == "cpu":
20
+ return False
21
+ try:
22
+ import cupy as cp # noqa: F401
23
+
24
+ return cp.cuda.runtime.getDeviceCount() > 0
25
+ except Exception:
26
+ return False
27
+
28
+
29
+ def get_backend(use_gpu: bool | None = None) -> Tuple[Any, bool]:
30
+ """Return ``(xp, is_gpu)``.
31
+
32
+ Parameters
33
+ ----------
34
+ use_gpu : bool | None
35
+ None -> auto-detect (GPU if available)
36
+ True -> require GPU (raises if unavailable)
37
+ False -> force CPU / NumPy
38
+ """
39
+ if _FORCE == "gpu":
40
+ use_gpu = True
41
+ elif _FORCE == "cpu":
42
+ use_gpu = False
43
+
44
+ if use_gpu is None:
45
+ use_gpu = gpu_available()
46
+
47
+ if use_gpu:
48
+ try:
49
+ import cupy as cp
50
+
51
+ if cp.cuda.runtime.getDeviceCount() == 0:
52
+ raise RuntimeError("No CUDA device visible")
53
+ return cp, True
54
+ except Exception as exc: # pragma: no cover - depends on hardware
55
+ if _FORCE == "gpu" or use_gpu is True:
56
+ raise RuntimeError(f"GPU backend requested but unavailable: {exc}")
57
+ return np, False
58
+ return np, False
59
+
60
+
61
+ def to_cpu(arr: Any) -> "np.ndarray":
62
+ """Bring an array back to host memory as a NumPy array."""
63
+ get = getattr(arr, "get", None)
64
+ if callable(get):
65
+ return get()
66
+ return np.asarray(arr)