forked from knwin/OpenTopography-DEM-Downloader-qgis-plugin
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathOpenTopography_DEMDownloader_algorithm.py
More file actions
294 lines (248 loc) · 11 KB
/
Copy pathOpenTopography_DEMDownloader_algorithm.py
File metadata and controls
294 lines (248 loc) · 11 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
# -*- coding: utf-8 -*-
"""
/***************************************************************************
OpenTopographyDEMDownloader
A QGIS plugin
This plugin downloads DEM from OpenTopography.org
Generated by Plugin Builder: http://g-sherman.github.io/Qgis-Plugin-Builder/
-------------------
begin : 2022-01-27
copyright : (C) 2022 by Kyaw Naing Win
email : kyawnaingwinknw@gmail.com
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
"""
__author__ = 'Kyaw Naing Win'
__date__ = '2022-01-27'
__copyright__ = '(C) 2022 by Kyaw Naing Win'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'
import os
import requests
from qgis.PyQt.QtCore import QCoreApplication
from qgis.PyQt.QtGui import QIcon
from qgis.core import (QgsProcessingAlgorithm,
QgsProcessingParameterString,
QgsProcessingParameterExtent,
QgsProcessingParameterEnum,
QgsProcessingException,
QgsProcessingParameterRasterDestination,
QgsCoordinateTransform,
QgsCoordinateReferenceSystem,
QgsProject,
QgsSettings)
import processing
class OpenTopographyDEMDownloaderAlgorithm(QgsProcessingAlgorithm):
OUTPUT = 'OUTPUT'
INPUT = 'INPUT'
def initAlgorithm(self, config):
settings = QgsSettings()
ot_auth_token = settings.value("OpenTopographyDEMDownloader/ot_api_key", "")
if not ot_auth_token:
auth_prompt = self.tr('Enter OpenTopography access key')
else:
auth_prompt = self.tr('Enter OpenTopography access key (or use existing one below)')
self.addParameter(
QgsProcessingParameterEnum(
'DEMs',
'Select DEM to download',
options=[
'Agência Nacional de Águas DEM (ANADEM) 30m',
'ALOS World 3D 30m',
'ALOS World 3D Ellipsoidal 30m',
'Copernicus Global DSM 30m',
'Copernicus Global DSM 90m',
'EU DTM 30m',
'GEBCOIceTopo Bathymetry 500m',
'GEBCOSubIceTopo Bathymetry 500m',
'GEDI L3 1km',
'Global Bathymetry SRTM15+ V2.55 500m',
'Global Ensemble Digital Terrain Model 30m',
'NASADEM Global DEM 30m',
'SRTM 30m',
'SRTM 90m',
'SRTM GL1 Ellipsoidal 30m'
],
allowMultiple=False,
defaultValue=[13]
)
)
self.addParameter(QgsProcessingParameterExtent('Extent', 'Define extent to download', defaultValue=None))
self.addParameter(QgsProcessingParameterString('OT_AUTH_TOKEN', auth_prompt, multiLine=False, defaultValue=ot_auth_token))
self.addParameter(QgsProcessingParameterRasterDestination(self.OUTPUT, self.tr('Output Raster')))
def processAlgorithm(self, parameters, context, feedback):
settings = QgsSettings()
outputs = {}
# process extent bbox information
crs = self.parameterAsExtentCrs(parameters, "Extent", context)
extent = self.parameterAsExtentGeometry(
parameters, "Extent", context
).boundingBox()
if crs.authid() != "EPSG:4326":
extent = QgsCoordinateTransform(
crs,
QgsCoordinateReferenceSystem("EPSG:4326"),
QgsProject.instance(),
).transformBoundingBox(extent)
dem_codes = [
'ANADEM',
'AW3D30',
'AW3D30_E',
'COP30',
'COP90',
'EU_DTM',
'GEBCOIceTopo',
'GEBCOSubIceTopo',
'GEDI_L3',
'SRTM15Plus',
'GEDTM30',
'NASADEM',
'SRTMGL1',
'SRTMGL3',
'SRTMGL1_E'
]
dem_code = dem_codes[parameters['DEMs']]
south = extent.yMinimum()
north = extent.yMaximum()
west = extent.xMinimum()
east = extent.xMaximum()
# check bounding box if ANADEM is selected
anadem_north = 14.07948
anadem_south = -56.51552
anadem_east= -34.72655
anadem_west= -82.51655
if dem_code == 'ANADEM':
# 1. Check if the extent INTERSECTS with ANADEM extent
intersects = (
west <= anadem_east and
east >= anadem_west and
south <= anadem_north and
north >= anadem_south
)
# 2. Check if the extent is COMPLETELY WITHIN ANADEM extent
is_within = (
west >= anadem_west and
east <= anadem_east and
south >= anadem_south and
north <= anadem_north
)
if not intersects:
feedback.reportError(
"Selected extent is completely outside the ANADEM coverage area_South Amearica. Process cancelled.",
fatalError=False
)
return {} #just waiting to correct the error
elif not is_within:
feedback.pushWarning("Selected extent extends beyond the ANADEM coverage area. But only avaiable data will be downloaded")
dem_url = (
f"https://portal.opentopography.org/API/globaldem?demtype={dem_code}"
f"&south={south}&north={north}&west={west}&east={east}&outputFormat=GTiff"
)
dem_url = dem_url + "&API_Key=" + parameters['OT_AUTH_TOKEN']
dem_file = self.parameterAsFileOutput(parameters, self.OUTPUT, context)
try:
# Download file
alg_params = {
'URL': dem_url,
'OUTPUT': dem_file
}
outputs['DownloadFile'] = processing.run(
'native:filedownloader',
alg_params,
context=context,
feedback=feedback,
is_child_algorithm=True
)
settings.setValue("OpenTopographyDEMDownloader/ot_api_key", parameters['OT_AUTH_TOKEN'])
except Exception:
response = requests.request("GET", dem_url, headers={}, data={})
raise QgsProcessingException(response.text.split('<error>')[1][:-8])
# Load layer into project
dem_file_name = os.path.basename(dem_file)
if dem_file_name == 'OUTPUT.tif':
alg_params = {
'INPUT': outputs['DownloadFile']['OUTPUT'],
'NAME': dem_code + "[Memory]"
}
else:
alg_params = {
'INPUT': dem_file,
'NAME': dem_file_name
}
outputs['LoadLayerIntoProject'] = processing.run(
'native:loadlayer',
alg_params,
context=context,
feedback=feedback,
is_child_algorithm=True
)
return {self.OUTPUT: outputs['DownloadFile']['OUTPUT']}
def name(self):
"""
Returns the algorithm name, used for identifying the algorithm. This
string should be fixed for the algorithm, and must not be localised.
The name should be unique within each provider. Names should contain
lowercase alphanumeric characters only and no spaces or other
formatting characters.
"""
return 'OpenTopography DEM Downloader'
def displayName(self):
"""
Returns the translated algorithm name, which should be used for any
user-visible display of the algorithm name.
"""
return self.tr(self.name())
def group(self):
"""
Returns the name of the group this algorithm belongs to. This string
should be localised.
"""
return self.tr(self.groupId())
def groupId(self):
"""
Returns the unique ID of the group this algorithm belongs to. This
string should be fixed for the algorithm, and must not be localised.
The group id should be unique within each provider. Group id should
contain lowercase alphanumeric characters only and no spaces or other
formatting characters.
"""
return 'DEM Downloader'
def tr(self, string):
return QCoreApplication.translate('Processing', string)
def icon(self):
cmd_folder = os.path.dirname(__file__)
icon_path = os.path.join(cmd_folder, 'icon.png')
return QIcon(icon_path)
def shortHelpString(self):
help_text = """
This tool will download DEM for the extent defined by user, from OpenTopography (https://opentopography.org/)
As of Jan 2022, an access key is required for all DEMs.
Read https://opentopography.org/blog/introducing-api-keys-access-opentopography-global-datasets how to get an access key.
Developed by: Kyaw Naing Win
Version: 4.2
Date: 2026-07-16
change log ver4.2:
- Agência Nacional de Águas DEM (ANADEM, 30m) for South America and Global Ensemble Digital Terrain Model (30m) are added into the DEM list
change log ver4.1:
- Fixed security warnings regarding API key keywords
change log ver4:
- Compatible with both QGIS 3.x and GIS 4.x versions
change log ver3:
- GEBCOIceTopo Bathymetry 500m and GEBCOSubIceTopo Bathymetry 500m datasets are added into the DEM list
change log ver2:
- EU DTM and GEDI L3 Grid are added into the DEM list
- Errors returned from the OpenTopography site are displayed
- Accept layer model input as extent input in Graphical Modeler (credit: Suricactus https://github.com/suricactus)
email: kyawnaingwinknw@gmail.com
read more: https://github.com/knwin/OpenTopography-DEM-Downloader-qgis-plugin
"""
return self.tr(help_text)
def createInstance(self):
return OpenTopographyDEMDownloaderAlgorithm()