pydtmdl 0.0.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.
Files changed (42) hide show
  1. pydtmdl-0.0.1/PKG-INFO +233 -0
  2. pydtmdl-0.0.1/README.md +211 -0
  3. pydtmdl-0.0.1/pydtmdl/__init__.py +3 -0
  4. pydtmdl-0.0.1/pydtmdl/base/__init__.py +0 -0
  5. pydtmdl-0.0.1/pydtmdl/base/dtm.py +544 -0
  6. pydtmdl-0.0.1/pydtmdl/base/wcs.py +79 -0
  7. pydtmdl-0.0.1/pydtmdl/base/wms.py +70 -0
  8. pydtmdl-0.0.1/pydtmdl/providers/__init__.py +27 -0
  9. pydtmdl-0.0.1/pydtmdl/providers/arctic.py +72 -0
  10. pydtmdl-0.0.1/pydtmdl/providers/baden.py +27 -0
  11. pydtmdl-0.0.1/pydtmdl/providers/bavaria.py +110 -0
  12. pydtmdl-0.0.1/pydtmdl/providers/canada.py +34 -0
  13. pydtmdl-0.0.1/pydtmdl/providers/czech.py +32 -0
  14. pydtmdl-0.0.1/pydtmdl/providers/denmark.py +49 -0
  15. pydtmdl-0.0.1/pydtmdl/providers/england.py +27 -0
  16. pydtmdl-0.0.1/pydtmdl/providers/finland.py +55 -0
  17. pydtmdl-0.0.1/pydtmdl/providers/flanders.py +31 -0
  18. pydtmdl-0.0.1/pydtmdl/providers/france.py +68 -0
  19. pydtmdl-0.0.1/pydtmdl/providers/hessen.py +28 -0
  20. pydtmdl-0.0.1/pydtmdl/providers/italy.py +36 -0
  21. pydtmdl-0.0.1/pydtmdl/providers/lithuania.py +63 -0
  22. pydtmdl-0.0.1/pydtmdl/providers/mv.py +42 -0
  23. pydtmdl-0.0.1/pydtmdl/providers/niedersachsen.py +35 -0
  24. pydtmdl-0.0.1/pydtmdl/providers/norway.py +37 -0
  25. pydtmdl-0.0.1/pydtmdl/providers/nrw.py +27 -0
  26. pydtmdl-0.0.1/pydtmdl/providers/rema.py +72 -0
  27. pydtmdl-0.0.1/pydtmdl/providers/sachsenanhalt.py +33 -0
  28. pydtmdl-0.0.1/pydtmdl/providers/scotland.py +116 -0
  29. pydtmdl-0.0.1/pydtmdl/providers/spain.py +30 -0
  30. pydtmdl-0.0.1/pydtmdl/providers/srtm.py +114 -0
  31. pydtmdl-0.0.1/pydtmdl/providers/switzerland.py +107 -0
  32. pydtmdl-0.0.1/pydtmdl/providers/thuringia.py +60 -0
  33. pydtmdl-0.0.1/pydtmdl/providers/usgs_wcs.py +31 -0
  34. pydtmdl-0.0.1/pydtmdl/providers/wales.py +121 -0
  35. pydtmdl-0.0.1/pydtmdl/utils.py +61 -0
  36. pydtmdl-0.0.1/pydtmdl.egg-info/PKG-INFO +233 -0
  37. pydtmdl-0.0.1/pydtmdl.egg-info/SOURCES.txt +40 -0
  38. pydtmdl-0.0.1/pydtmdl.egg-info/dependency_links.txt +1 -0
  39. pydtmdl-0.0.1/pydtmdl.egg-info/requires.txt +7 -0
  40. pydtmdl-0.0.1/pydtmdl.egg-info/top_level.txt +1 -0
  41. pydtmdl-0.0.1/pyproject.toml +36 -0
  42. pydtmdl-0.0.1/setup.cfg +4 -0
pydtmdl-0.0.1/PKG-INFO ADDED
@@ -0,0 +1,233 @@
1
+ Metadata-Version: 2.4
2
+ Name: pydtmdl
3
+ Version: 0.0.1
4
+ Summary: Python library to download DTM data from various providers.
5
+ Author-email: iwatkot <iwatkot@gmail.com>
6
+ License: Apache License 2.0
7
+ Project-URL: Homepage, https://github.com/iwatkot/pydtmdl
8
+ Project-URL: Repository, https://github.com/iwatkot/pydtmdl
9
+ Keywords: dtm,digital terrain model,elevation,geospatial
10
+ Classifier: Programming Language :: Python :: 3.11
11
+ Classifier: Programming Language :: Python :: 3.12
12
+ Classifier: License :: OSI Approved :: Apache Software License
13
+ Classifier: Operating System :: OS Independent
14
+ Description-Content-Type: text/markdown
15
+ Requires-Dist: numpy
16
+ Requires-Dist: rasterio
17
+ Requires-Dist: requests
18
+ Requires-Dist: pydantic
19
+ Requires-Dist: tqdm
20
+ Requires-Dist: osmnx
21
+ Requires-Dist: owslib
22
+
23
+ <div align="center" markdown>
24
+ <img src="">
25
+ </a>
26
+
27
+ <p align="center">
28
+ <a href="#Quick-Start">Quick Start</a> โ€ข
29
+ <a href="#Overview">Overview</a> โ€ข
30
+ <a href="#What-is-a-DTM?">What is a DTM?</a> โ€ข
31
+ <a href="#Supported-DTM-providers">Supported DTM providers</a> โ€ข
32
+ <a href="#Contributing">Contributing</a>
33
+ </p>
34
+
35
+ [![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/iwatkot/pydtmdl)](https://github.com/iwatkot/pydtmdl/releases)
36
+ [![PyPI - Version](https://img.shields.io/pypi/v/pydtmdl)](https://pypi.org/project/pydtmdl)
37
+ [![GitHub issues](https://img.shields.io/github/issues/iwatkot/pydtmdl)](https://github.com/iwatkot/pydtmdl/issues)
38
+ [![PyPI - Downloads](https://img.shields.io/pypi/dm/pydtmdl)](https://pypi.org/project/pydtmdl)
39
+ [![Checked with mypy](https://www.mypy-lang.org/static/mypy_badge.svg)](https://mypy-lang.org/)
40
+ [![Build Status](https://github.com/iwatkot/pydtmdl/actions/workflows/checks.yml/badge.svg)](https://github.com/iwatkot/pydtmdl/actions)
41
+ [![GitHub Repo stars](https://img.shields.io/github/stars/iwatkot/pydtmdl)](https://github.com/iwatkot/pydtmdl/stargazers)<br>
42
+
43
+ </div>
44
+
45
+ ## Quick Start
46
+ Install the package using pip:
47
+
48
+ ```bash
49
+ pip install pydtmdl
50
+ ```
51
+
52
+ Then, you can use it in your Python scripts:
53
+
54
+ ```python
55
+ from pydtmdl import DTMProvider
56
+
57
+ # Prepare coordinates of the center point and size (in meters).
58
+ coords = 45.285460396731374, 20.237491178279715 # Center point of the region of interest.
59
+ size = 2048 # Size of the region in meters (2048x2048 m).
60
+
61
+ # Get the best provider for the given coordinates.
62
+ best_provider = DTMProvider.get_best(coords)
63
+ print(f"Best provider: {best_provider.name()}")
64
+
65
+ # Create an instance of the provider with the given coordinates and size.
66
+ provider = best_provider(coords, size=size)
67
+
68
+ # Get the DTM data as a numpy array.
69
+ np_data = provider.image
70
+ ```
71
+
72
+ ## Overview
73
+ `pydtmdl` is a Python library designed to provide access to Digital Terrain Models (DTMs) from various providers. It supports multiple providers, each with its own resolution and data format. The library allows users to easily retrieve DTM data for specific geographic coordinates and sizes.
74
+
75
+ Note, that some providers may require additional settings, such as API keys or selection of a specific dataset. More details can be found in the demo script and in the providers source code.
76
+
77
+ The library will retrieve all the required tiles, merge them, window them and return the result as a numpy array. If additional processing is required, such as normalization or resizing, it can be done using OpenCV or other libraries (example code is provided in the demo script).
78
+
79
+ ## What is a DTM?
80
+
81
+ First of all, it's important to understand what a DTM is.
82
+ There are two main types of elevation models: Digital Terrain Model (DTM) and Digital Surface Model (DSM). The DTM represents the bare earth surface without any objects like buildings or vegetation. The DSM, on the other hand, represents the earth's surface including all objects.
83
+
84
+ ![DTM vs DSM, example 1](https://github.com/user-attachments/assets/0bf691f3-6737-4663-86ca-c17a525ecda4)
85
+
86
+ ![DTM vs DSM, example 2](https://github.com/user-attachments/assets/3ae1082c-1117-4073-ac98-a2bc1e22c1ba)
87
+
88
+ The library is focused on the DTM data and the DSM sources are not supported and will not be added in the future. The reason for this is that the DTM data is more suitable for terrain generation in games, as it provides a more accurate representation of the earth's surface without any objects.
89
+
90
+ ## Supported DTM providers
91
+
92
+ ![coverage map](https://github.com/user-attachments/assets/be5c5ce1-7318-4352-97eb-efba7ec587cd)
93
+
94
+ In addition to SRTM 30m, which provides global coverage, the map above highlights all countries and/or regions where higher resolution coverage is provided by one of the DTM providers.
95
+
96
+ | Provider Name | Resolution | Developer |
97
+ | ---------------------------------- | ------------ | ------------------------------------------- |
98
+ | ๐ŸŒŽ SRTM30 | 30 meters | [iwatkot](https://github.com/iwatkot) |
99
+ | ๐ŸŒŽ ArcticDEM | 2 meters | [kbrandwijk](https://github.com/kbrandwijk) |
100
+ | ๐ŸŒŽ REMA Antarctica | 2 meters | [kbrandwijk](https://github.com/kbrandwijk) |
101
+ | ๐Ÿ‡บ๐Ÿ‡ธ USGS | 1-90 meters | [ZenJakey](https://github.com/ZenJakey) |
102
+ | ๐Ÿด๓ ง๓ ข๓ ฅ๓ ฎ๓ ง๓ ฟ England | 1 meter | [kbrandwijk](https://github.com/kbrandwijk) |
103
+ | ๐Ÿด๓ ง๓ ข๓ ณ๓ ฃ๓ ด๓ ฟ Scotland | 0.25-1 meter | [kbrandwijk](https://github.com/kbrandwijk) |
104
+ | ๐Ÿด๓ ง๓ ข๓ ท๓ ฌ๓ ณ๓ ฟ๓ ง๓ ข๓ ท๓ ฌ๓ ณ๓ ฟ Wales | 1 meter | [garnwenshared](https://github.com/garnshared) |
105
+ | ๐Ÿ‡ฉ๐Ÿ‡ช Hessen, Germany | 1 meter | [kbrandwijk](https://github.com/kbrandwijk) |
106
+ | ๐Ÿ‡ฉ๐Ÿ‡ช Niedersachsen, Germany | 1 meter | [kbrandwijk](https://github.com/kbrandwijk) |
107
+ | ๐Ÿ‡ฉ๐Ÿ‡ช Bayern, Germany | 1 meter | [H4rdB4se](https://github.com/H4rdB4se) |
108
+ | ๐Ÿ‡ฉ๐Ÿ‡ช Nordrhein-Westfalen, Germany | 1 meter | [kbrandwijk](https://github.com/kbrandwijk) |
109
+ | ๐Ÿ‡ฉ๐Ÿ‡ช Mecklenburg-Vorpommern, Germany | 1-25 meter | [kbrandwijk](https://github.com/kbrandwijk) |
110
+ | ๐Ÿ‡ฉ๐Ÿ‡ช Baden-Wรผrttemberg, Germany | 1 meter | [kbrandwijk](https://github.com/kbrandwijk) |
111
+ | ๐Ÿ‡ฉ๐Ÿ‡ช Sachsen-Anhalt, Germany | 1 meter | [kbrandwijk](https://github.com/kbrandwijk) |
112
+ | ๐Ÿ‡ฉ๐Ÿ‡ช Thรผringen, Germany | 1 meter | [H4rdB4se](https://github.com/H4rdB4se) |
113
+ | ๐Ÿ‡จ๐Ÿ‡ฆ Canada | 1 meter | [kbrandwijk](https://github.com/kbrandwijk) |
114
+ | ๐Ÿ‡ง๐Ÿ‡ช Flanders, Belgium | 1 meter | [kbrandwijk](https://github.com/kbrandwijk) |
115
+ | ๐Ÿ‡ซ๐Ÿ‡ท France | 1 meter | [kbrandwijk](https://github.com/kbrandwijk) |
116
+ | ๐Ÿ‡ฎ๐Ÿ‡น Italy | 10 meter | [kbrandwijk](https://github.com/kbrandwijk) |
117
+ | ๐Ÿ‡ณ๐Ÿ‡ด Norway | 1 meter | [kbrandwijk](https://github.com/kbrandwijk) |
118
+ | ๐Ÿ‡ช๐Ÿ‡ธ Spain | 5 meter | [kbrandwijk](https://github.com/kbrandwijk) |
119
+ | ๐Ÿ‡ซ๐Ÿ‡ฎ Finland | 2 meter | [kbrandwijk](https://github.com/kbrandwijk) |
120
+ | ๐Ÿ‡ฉ๐Ÿ‡ฐ Denmark | 0.4 meter | [kbrandwijk](https://github.com/kbrandwijk) |
121
+ | ๐Ÿ‡จ๐Ÿ‡ญ Switzerland | 0.5-2 meter | [kbrandwijk](https://github.com/kbrandwijk) |
122
+ | ๐Ÿ‡จ๐Ÿ‡ฟ Czech Republic | 5 meter | [kbrandwijk](https://github.com/kbrandwijk) |
123
+ | ๐Ÿ‡ฑ๐Ÿ‡น Lithuania | 1 meter | [Tox3](https://github.com/Tox3) |
124
+
125
+
126
+ ## Contributing
127
+
128
+ Contributions are welcome! If you want to add your own DTM provider, please follow this guide.
129
+ You can also contribute by reporting issues, suggesting improvements, or helping with documentation.
130
+ ### What a DTM provider does?
131
+
132
+ A DTM provider is a service that provides elevation data for a given location. While there's plenty of DTM providers available, only the ones that provide a free and open access to their data can be used in this library.
133
+
134
+ The base provider class, [DTMProvider](pydtmdl/base/dtm.py) that all DTM providers inherit from, is responsible for all processing of DEM data. Individual DTM providers are responsible only for downloading the DTM tile(s) for the area.
135
+
136
+ The process for generating the elevation data is:
137
+
138
+ - Download all DTM tiles for the desired map area (implemented by each DTM provider)
139
+ - If the DTM provider downloaded multiple tiles, merge these tiles into one
140
+ - If the tile uses a different projection, reproject it to EPSG:4326, which is used for all other data (like OSM)
141
+ - Extract the map area from the tile (some providers, like SRTM, return big tiles that are larger than just the desired area)
142
+
143
+ ### How to implement a DTM provider?
144
+
145
+ So the DTM provider is a simple class, that receives coordinate of the center point, the size of the region of interest and should download all the needed DTM tiles and return a numpy array with the elevation data.
146
+
147
+ ### Example of a DTM provider
148
+
149
+ โžก๏ธ Existing providers can be found in the [providers](pydtmdl/providers/) folder.
150
+
151
+ Let's take a look at an example of a DTM provider implementation.
152
+
153
+ **Step 1:** define description of the provider.
154
+
155
+ ```python
156
+ class SRTM30Provider(DTMProvider):
157
+ """Provider of Shuttle Radar Topography Mission (SRTM) 30m data."""
158
+
159
+ _code = "srtm30"
160
+ _name = "SRTM 30 m"
161
+ _region = "Global"
162
+ _icon = "๐ŸŒŽ"
163
+ _resolution = 30.0
164
+
165
+ _url = "https://elevation-tiles-prod.s3.amazonaws.com/skadi/{latitude_band}/{tile_name}.hgt.gz"
166
+
167
+ _instructions = "When working with SRTM provider..."
168
+ ```
169
+
170
+ So, we inherit from the `DTMProvider` class, add some properties to identify the Provider (such as code and region). The most important part is the `_url` property, which is a template for the URL to download the elevation data. But if your provider uses some other approach, you can reimplement related methods.
171
+
172
+ If you want some additional information or guides you can set the `_instructions` property.
173
+
174
+ **Step 2 (optional):** use the `DTMProviderSetting` class to define your own settings (if needed).
175
+
176
+ ```python
177
+ class SRTM30ProviderSettings(DTMProviderSettings):
178
+ """Settings for the SRTM 30 m provider."""
179
+
180
+ enable_something: bool = True
181
+ input_something: int = 255
182
+ ```
183
+
184
+ Also, you will need to add a new `_settings` property to the provider class.
185
+
186
+ ```python
187
+ class SRTM30Provider(DTMProvider):
188
+ ...
189
+ _settings = SRTM30ProviderSettings
190
+ ```
191
+
192
+ If those are provided you'll later be able to use the `user_settings` property to access the settings. In the example it would look like this:
193
+
194
+ ```python
195
+ enable_something = self.user_settings.enable_something
196
+ input_something = self.user_settings.input_something
197
+ ```
198
+
199
+ **Step 3:** implement the `download_tiles` method.
200
+
201
+ ```python
202
+ def download_tiles(self):
203
+ """Download SRTM tiles."""
204
+ north, south, east, west = self.get_bbox()
205
+
206
+ tiles = []
207
+ # Look at each corner of the bbox in case the bbox spans across multiple tiles
208
+ for pair in [(north, east), (south, west), (south, east), (north, west)]:
209
+ tile_parameters = self.get_tile_parameters(*pair)
210
+ tile_name = tile_parameters["tile_name"]
211
+ decompressed_tile_path = os.path.join(self.hgt_directory, f"{tile_name}.hgt")
212
+
213
+ if not os.path.isfile(decompressed_tile_path):
214
+ compressed_tile_path = os.path.join(self.gz_directory, f"{tile_name}.hgt.gz")
215
+ if not self.get_or_download_tile(compressed_tile_path, **tile_parameters):
216
+ raise FileNotFoundError(f"Tile {tile_name} not found.")
217
+
218
+ with gzip.open(compressed_tile_path, "rb") as f_in:
219
+ with open(decompressed_tile_path, "wb") as f_out:
220
+ shutil.copyfileobj(f_in, f_out)
221
+ tiles.append(decompressed_tile_path)
222
+
223
+ return tiles
224
+ ```
225
+
226
+ This method uses the helper method `get_bbox` to get the coordinates of the bounding box of the map area. If your DTM provider requires you to provide the coordinates in a different projection, you need to make sure you convert. For an example of this, see the `transform_bbox` method in [nrw.py](../maps4fs/generator/dtm/nrw.py).
227
+ Then, it determines which tiles are needed, downloads them all to a temporary folder and extracts them. The base class provides a `_tile_directory` property for convenience that points to a temp folder for your provider.
228
+ Finally, it returns a list of file paths to the downloaded tiles.
229
+
230
+ As you can see, it's pretty simple to implement a DTM provider. You can use any source of elevation data, as long as it's free and open.
231
+ NOTE: If a DTM Provider requires an API key, paid subscription, or any other form of payment, you will be fully responsible for setting up your own access to the provider. The provider in the library will expose the settings needed to provide your authentication key or other required information.
232
+
233
+
@@ -0,0 +1,211 @@
1
+ <div align="center" markdown>
2
+ <img src="">
3
+ </a>
4
+
5
+ <p align="center">
6
+ <a href="#Quick-Start">Quick Start</a> โ€ข
7
+ <a href="#Overview">Overview</a> โ€ข
8
+ <a href="#What-is-a-DTM?">What is a DTM?</a> โ€ข
9
+ <a href="#Supported-DTM-providers">Supported DTM providers</a> โ€ข
10
+ <a href="#Contributing">Contributing</a>
11
+ </p>
12
+
13
+ [![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/iwatkot/pydtmdl)](https://github.com/iwatkot/pydtmdl/releases)
14
+ [![PyPI - Version](https://img.shields.io/pypi/v/pydtmdl)](https://pypi.org/project/pydtmdl)
15
+ [![GitHub issues](https://img.shields.io/github/issues/iwatkot/pydtmdl)](https://github.com/iwatkot/pydtmdl/issues)
16
+ [![PyPI - Downloads](https://img.shields.io/pypi/dm/pydtmdl)](https://pypi.org/project/pydtmdl)
17
+ [![Checked with mypy](https://www.mypy-lang.org/static/mypy_badge.svg)](https://mypy-lang.org/)
18
+ [![Build Status](https://github.com/iwatkot/pydtmdl/actions/workflows/checks.yml/badge.svg)](https://github.com/iwatkot/pydtmdl/actions)
19
+ [![GitHub Repo stars](https://img.shields.io/github/stars/iwatkot/pydtmdl)](https://github.com/iwatkot/pydtmdl/stargazers)<br>
20
+
21
+ </div>
22
+
23
+ ## Quick Start
24
+ Install the package using pip:
25
+
26
+ ```bash
27
+ pip install pydtmdl
28
+ ```
29
+
30
+ Then, you can use it in your Python scripts:
31
+
32
+ ```python
33
+ from pydtmdl import DTMProvider
34
+
35
+ # Prepare coordinates of the center point and size (in meters).
36
+ coords = 45.285460396731374, 20.237491178279715 # Center point of the region of interest.
37
+ size = 2048 # Size of the region in meters (2048x2048 m).
38
+
39
+ # Get the best provider for the given coordinates.
40
+ best_provider = DTMProvider.get_best(coords)
41
+ print(f"Best provider: {best_provider.name()}")
42
+
43
+ # Create an instance of the provider with the given coordinates and size.
44
+ provider = best_provider(coords, size=size)
45
+
46
+ # Get the DTM data as a numpy array.
47
+ np_data = provider.image
48
+ ```
49
+
50
+ ## Overview
51
+ `pydtmdl` is a Python library designed to provide access to Digital Terrain Models (DTMs) from various providers. It supports multiple providers, each with its own resolution and data format. The library allows users to easily retrieve DTM data for specific geographic coordinates and sizes.
52
+
53
+ Note, that some providers may require additional settings, such as API keys or selection of a specific dataset. More details can be found in the demo script and in the providers source code.
54
+
55
+ The library will retrieve all the required tiles, merge them, window them and return the result as a numpy array. If additional processing is required, such as normalization or resizing, it can be done using OpenCV or other libraries (example code is provided in the demo script).
56
+
57
+ ## What is a DTM?
58
+
59
+ First of all, it's important to understand what a DTM is.
60
+ There are two main types of elevation models: Digital Terrain Model (DTM) and Digital Surface Model (DSM). The DTM represents the bare earth surface without any objects like buildings or vegetation. The DSM, on the other hand, represents the earth's surface including all objects.
61
+
62
+ ![DTM vs DSM, example 1](https://github.com/user-attachments/assets/0bf691f3-6737-4663-86ca-c17a525ecda4)
63
+
64
+ ![DTM vs DSM, example 2](https://github.com/user-attachments/assets/3ae1082c-1117-4073-ac98-a2bc1e22c1ba)
65
+
66
+ The library is focused on the DTM data and the DSM sources are not supported and will not be added in the future. The reason for this is that the DTM data is more suitable for terrain generation in games, as it provides a more accurate representation of the earth's surface without any objects.
67
+
68
+ ## Supported DTM providers
69
+
70
+ ![coverage map](https://github.com/user-attachments/assets/be5c5ce1-7318-4352-97eb-efba7ec587cd)
71
+
72
+ In addition to SRTM 30m, which provides global coverage, the map above highlights all countries and/or regions where higher resolution coverage is provided by one of the DTM providers.
73
+
74
+ | Provider Name | Resolution | Developer |
75
+ | ---------------------------------- | ------------ | ------------------------------------------- |
76
+ | ๐ŸŒŽ SRTM30 | 30 meters | [iwatkot](https://github.com/iwatkot) |
77
+ | ๐ŸŒŽ ArcticDEM | 2 meters | [kbrandwijk](https://github.com/kbrandwijk) |
78
+ | ๐ŸŒŽ REMA Antarctica | 2 meters | [kbrandwijk](https://github.com/kbrandwijk) |
79
+ | ๐Ÿ‡บ๐Ÿ‡ธ USGS | 1-90 meters | [ZenJakey](https://github.com/ZenJakey) |
80
+ | ๐Ÿด๓ ง๓ ข๓ ฅ๓ ฎ๓ ง๓ ฟ England | 1 meter | [kbrandwijk](https://github.com/kbrandwijk) |
81
+ | ๐Ÿด๓ ง๓ ข๓ ณ๓ ฃ๓ ด๓ ฟ Scotland | 0.25-1 meter | [kbrandwijk](https://github.com/kbrandwijk) |
82
+ | ๐Ÿด๓ ง๓ ข๓ ท๓ ฌ๓ ณ๓ ฟ๓ ง๓ ข๓ ท๓ ฌ๓ ณ๓ ฟ Wales | 1 meter | [garnwenshared](https://github.com/garnshared) |
83
+ | ๐Ÿ‡ฉ๐Ÿ‡ช Hessen, Germany | 1 meter | [kbrandwijk](https://github.com/kbrandwijk) |
84
+ | ๐Ÿ‡ฉ๐Ÿ‡ช Niedersachsen, Germany | 1 meter | [kbrandwijk](https://github.com/kbrandwijk) |
85
+ | ๐Ÿ‡ฉ๐Ÿ‡ช Bayern, Germany | 1 meter | [H4rdB4se](https://github.com/H4rdB4se) |
86
+ | ๐Ÿ‡ฉ๐Ÿ‡ช Nordrhein-Westfalen, Germany | 1 meter | [kbrandwijk](https://github.com/kbrandwijk) |
87
+ | ๐Ÿ‡ฉ๐Ÿ‡ช Mecklenburg-Vorpommern, Germany | 1-25 meter | [kbrandwijk](https://github.com/kbrandwijk) |
88
+ | ๐Ÿ‡ฉ๐Ÿ‡ช Baden-Wรผrttemberg, Germany | 1 meter | [kbrandwijk](https://github.com/kbrandwijk) |
89
+ | ๐Ÿ‡ฉ๐Ÿ‡ช Sachsen-Anhalt, Germany | 1 meter | [kbrandwijk](https://github.com/kbrandwijk) |
90
+ | ๐Ÿ‡ฉ๐Ÿ‡ช Thรผringen, Germany | 1 meter | [H4rdB4se](https://github.com/H4rdB4se) |
91
+ | ๐Ÿ‡จ๐Ÿ‡ฆ Canada | 1 meter | [kbrandwijk](https://github.com/kbrandwijk) |
92
+ | ๐Ÿ‡ง๐Ÿ‡ช Flanders, Belgium | 1 meter | [kbrandwijk](https://github.com/kbrandwijk) |
93
+ | ๐Ÿ‡ซ๐Ÿ‡ท France | 1 meter | [kbrandwijk](https://github.com/kbrandwijk) |
94
+ | ๐Ÿ‡ฎ๐Ÿ‡น Italy | 10 meter | [kbrandwijk](https://github.com/kbrandwijk) |
95
+ | ๐Ÿ‡ณ๐Ÿ‡ด Norway | 1 meter | [kbrandwijk](https://github.com/kbrandwijk) |
96
+ | ๐Ÿ‡ช๐Ÿ‡ธ Spain | 5 meter | [kbrandwijk](https://github.com/kbrandwijk) |
97
+ | ๐Ÿ‡ซ๐Ÿ‡ฎ Finland | 2 meter | [kbrandwijk](https://github.com/kbrandwijk) |
98
+ | ๐Ÿ‡ฉ๐Ÿ‡ฐ Denmark | 0.4 meter | [kbrandwijk](https://github.com/kbrandwijk) |
99
+ | ๐Ÿ‡จ๐Ÿ‡ญ Switzerland | 0.5-2 meter | [kbrandwijk](https://github.com/kbrandwijk) |
100
+ | ๐Ÿ‡จ๐Ÿ‡ฟ Czech Republic | 5 meter | [kbrandwijk](https://github.com/kbrandwijk) |
101
+ | ๐Ÿ‡ฑ๐Ÿ‡น Lithuania | 1 meter | [Tox3](https://github.com/Tox3) |
102
+
103
+
104
+ ## Contributing
105
+
106
+ Contributions are welcome! If you want to add your own DTM provider, please follow this guide.
107
+ You can also contribute by reporting issues, suggesting improvements, or helping with documentation.
108
+ ### What a DTM provider does?
109
+
110
+ A DTM provider is a service that provides elevation data for a given location. While there's plenty of DTM providers available, only the ones that provide a free and open access to their data can be used in this library.
111
+
112
+ The base provider class, [DTMProvider](pydtmdl/base/dtm.py) that all DTM providers inherit from, is responsible for all processing of DEM data. Individual DTM providers are responsible only for downloading the DTM tile(s) for the area.
113
+
114
+ The process for generating the elevation data is:
115
+
116
+ - Download all DTM tiles for the desired map area (implemented by each DTM provider)
117
+ - If the DTM provider downloaded multiple tiles, merge these tiles into one
118
+ - If the tile uses a different projection, reproject it to EPSG:4326, which is used for all other data (like OSM)
119
+ - Extract the map area from the tile (some providers, like SRTM, return big tiles that are larger than just the desired area)
120
+
121
+ ### How to implement a DTM provider?
122
+
123
+ So the DTM provider is a simple class, that receives coordinate of the center point, the size of the region of interest and should download all the needed DTM tiles and return a numpy array with the elevation data.
124
+
125
+ ### Example of a DTM provider
126
+
127
+ โžก๏ธ Existing providers can be found in the [providers](pydtmdl/providers/) folder.
128
+
129
+ Let's take a look at an example of a DTM provider implementation.
130
+
131
+ **Step 1:** define description of the provider.
132
+
133
+ ```python
134
+ class SRTM30Provider(DTMProvider):
135
+ """Provider of Shuttle Radar Topography Mission (SRTM) 30m data."""
136
+
137
+ _code = "srtm30"
138
+ _name = "SRTM 30 m"
139
+ _region = "Global"
140
+ _icon = "๐ŸŒŽ"
141
+ _resolution = 30.0
142
+
143
+ _url = "https://elevation-tiles-prod.s3.amazonaws.com/skadi/{latitude_band}/{tile_name}.hgt.gz"
144
+
145
+ _instructions = "When working with SRTM provider..."
146
+ ```
147
+
148
+ So, we inherit from the `DTMProvider` class, add some properties to identify the Provider (such as code and region). The most important part is the `_url` property, which is a template for the URL to download the elevation data. But if your provider uses some other approach, you can reimplement related methods.
149
+
150
+ If you want some additional information or guides you can set the `_instructions` property.
151
+
152
+ **Step 2 (optional):** use the `DTMProviderSetting` class to define your own settings (if needed).
153
+
154
+ ```python
155
+ class SRTM30ProviderSettings(DTMProviderSettings):
156
+ """Settings for the SRTM 30 m provider."""
157
+
158
+ enable_something: bool = True
159
+ input_something: int = 255
160
+ ```
161
+
162
+ Also, you will need to add a new `_settings` property to the provider class.
163
+
164
+ ```python
165
+ class SRTM30Provider(DTMProvider):
166
+ ...
167
+ _settings = SRTM30ProviderSettings
168
+ ```
169
+
170
+ If those are provided you'll later be able to use the `user_settings` property to access the settings. In the example it would look like this:
171
+
172
+ ```python
173
+ enable_something = self.user_settings.enable_something
174
+ input_something = self.user_settings.input_something
175
+ ```
176
+
177
+ **Step 3:** implement the `download_tiles` method.
178
+
179
+ ```python
180
+ def download_tiles(self):
181
+ """Download SRTM tiles."""
182
+ north, south, east, west = self.get_bbox()
183
+
184
+ tiles = []
185
+ # Look at each corner of the bbox in case the bbox spans across multiple tiles
186
+ for pair in [(north, east), (south, west), (south, east), (north, west)]:
187
+ tile_parameters = self.get_tile_parameters(*pair)
188
+ tile_name = tile_parameters["tile_name"]
189
+ decompressed_tile_path = os.path.join(self.hgt_directory, f"{tile_name}.hgt")
190
+
191
+ if not os.path.isfile(decompressed_tile_path):
192
+ compressed_tile_path = os.path.join(self.gz_directory, f"{tile_name}.hgt.gz")
193
+ if not self.get_or_download_tile(compressed_tile_path, **tile_parameters):
194
+ raise FileNotFoundError(f"Tile {tile_name} not found.")
195
+
196
+ with gzip.open(compressed_tile_path, "rb") as f_in:
197
+ with open(decompressed_tile_path, "wb") as f_out:
198
+ shutil.copyfileobj(f_in, f_out)
199
+ tiles.append(decompressed_tile_path)
200
+
201
+ return tiles
202
+ ```
203
+
204
+ This method uses the helper method `get_bbox` to get the coordinates of the bounding box of the map area. If your DTM provider requires you to provide the coordinates in a different projection, you need to make sure you convert. For an example of this, see the `transform_bbox` method in [nrw.py](../maps4fs/generator/dtm/nrw.py).
205
+ Then, it determines which tiles are needed, downloads them all to a temporary folder and extracts them. The base class provides a `_tile_directory` property for convenience that points to a temp folder for your provider.
206
+ Finally, it returns a list of file paths to the downloaded tiles.
207
+
208
+ As you can see, it's pretty simple to implement a DTM provider. You can use any source of elevation data, as long as it's free and open.
209
+ NOTE: If a DTM Provider requires an API key, paid subscription, or any other form of payment, you will be fully responsible for setting up your own access to the provider. The provider in the library will expose the settings needed to provide your authentication key or other required information.
210
+
211
+
@@ -0,0 +1,3 @@
1
+ # pylint: disable=missing-module-docstring
2
+ import pydtmdl.providers
3
+ from pydtmdl.base.dtm import DTMProvider, DTMProviderSettings
File without changes