BERATools 0.2.0__py3-none-any.whl → 0.2.1__py3-none-any.whl
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.
- beratools/__init__.py +1 -7
- beratools/core/algo_centerline.py +491 -351
- beratools/core/algo_common.py +497 -0
- beratools/core/algo_cost.py +192 -0
- beratools/core/{dijkstra_algorithm.py → algo_dijkstra.py} +503 -460
- beratools/core/algo_footprint_rel.py +577 -0
- beratools/core/algo_line_grouping.py +944 -0
- beratools/core/algo_merge_lines.py +214 -0
- beratools/core/algo_split_with_lines.py +304 -0
- beratools/core/algo_tiler.py +428 -0
- beratools/core/algo_vertex_optimization.py +469 -0
- beratools/core/constants.py +52 -86
- beratools/core/logger.py +76 -85
- beratools/core/tool_base.py +196 -133
- beratools/gui/__init__.py +11 -15
- beratools/gui/{beratools.json → assets/beratools.json} +2185 -2300
- beratools/gui/batch_processing_dlg.py +513 -463
- beratools/gui/bt_data.py +481 -487
- beratools/gui/bt_gui_main.py +710 -691
- beratools/gui/main.py +26 -0
- beratools/gui/map_window.py +162 -146
- beratools/gui/tool_widgets.py +725 -493
- beratools/tools/Beratools_r_script.r +1120 -1120
- beratools/tools/Ht_metrics.py +116 -116
- beratools/tools/__init__.py +7 -7
- beratools/tools/batch_processing.py +136 -132
- beratools/tools/canopy_threshold_relative.py +672 -670
- beratools/tools/canopycostraster.py +222 -222
- beratools/tools/centerline.py +136 -176
- beratools/tools/common.py +857 -885
- beratools/tools/fl_regen_csf.py +428 -428
- beratools/tools/forest_line_attributes.py +408 -408
- beratools/tools/line_footprint_absolute.py +213 -363
- beratools/tools/line_footprint_fixed.py +436 -282
- beratools/tools/line_footprint_functions.py +733 -720
- beratools/tools/line_footprint_relative.py +73 -64
- beratools/tools/line_grouping.py +45 -0
- beratools/tools/ln_relative_metrics.py +615 -615
- beratools/tools/r_cal_lpi_elai.r +24 -24
- beratools/tools/r_generate_pd_focalraster.r +100 -100
- beratools/tools/r_interface.py +79 -79
- beratools/tools/r_point_density.r +8 -8
- beratools/tools/rpy_chm2trees.py +86 -86
- beratools/tools/rpy_dsm_chm_by.py +81 -81
- beratools/tools/rpy_dtm_by.py +63 -63
- beratools/tools/rpy_find_cellsize.py +43 -43
- beratools/tools/rpy_gnd_csf.py +74 -74
- beratools/tools/rpy_hummock_hollow.py +85 -85
- beratools/tools/rpy_hummock_hollow_raster.py +71 -71
- beratools/tools/rpy_las_info.py +51 -51
- beratools/tools/rpy_laz2las.py +40 -40
- beratools/tools/rpy_lpi_elai_lascat.py +466 -466
- beratools/tools/rpy_normalized_lidar_by.py +56 -56
- beratools/tools/rpy_percent_above_dbh.py +80 -80
- beratools/tools/rpy_points2trees.py +88 -88
- beratools/tools/rpy_vegcoverage.py +94 -94
- beratools/tools/tiler.py +48 -206
- beratools/tools/tool_template.py +69 -54
- beratools/tools/vertex_optimization.py +61 -620
- beratools/tools/zonal_threshold.py +144 -144
- beratools-0.2.1.dist-info/METADATA +109 -0
- beratools-0.2.1.dist-info/RECORD +74 -0
- {beratools-0.2.0.dist-info → beratools-0.2.1.dist-info}/WHEEL +1 -1
- {beratools-0.2.0.dist-info → beratools-0.2.1.dist-info}/licenses/LICENSE +22 -22
- beratools/gui/cli.py +0 -18
- beratools/gui/gui.json +0 -8
- beratools/gui_tk/ASCII Banners.txt +0 -248
- beratools/gui_tk/__init__.py +0 -20
- beratools/gui_tk/beratools_main.py +0 -515
- beratools/gui_tk/bt_widgets.py +0 -442
- beratools/gui_tk/cli.py +0 -18
- beratools/gui_tk/img/BERALogo.png +0 -0
- beratools/gui_tk/img/closed.gif +0 -0
- beratools/gui_tk/img/closed.png +0 -0
- beratools/gui_tk/img/open.gif +0 -0
- beratools/gui_tk/img/open.png +0 -0
- beratools/gui_tk/img/tool.gif +0 -0
- beratools/gui_tk/img/tool.png +0 -0
- beratools/gui_tk/main.py +0 -14
- beratools/gui_tk/map_window.py +0 -144
- beratools/gui_tk/runner.py +0 -1481
- beratools/gui_tk/tooltip.py +0 -55
- beratools/third_party/pyqtlet2/__init__.py +0 -9
- beratools/third_party/pyqtlet2/leaflet/__init__.py +0 -26
- beratools/third_party/pyqtlet2/leaflet/control/__init__.py +0 -6
- beratools/third_party/pyqtlet2/leaflet/control/control.py +0 -59
- beratools/third_party/pyqtlet2/leaflet/control/draw.py +0 -52
- beratools/third_party/pyqtlet2/leaflet/control/layers.py +0 -20
- beratools/third_party/pyqtlet2/leaflet/core/Parser.py +0 -24
- beratools/third_party/pyqtlet2/leaflet/core/__init__.py +0 -2
- beratools/third_party/pyqtlet2/leaflet/core/evented.py +0 -180
- beratools/third_party/pyqtlet2/leaflet/layer/__init__.py +0 -5
- beratools/third_party/pyqtlet2/leaflet/layer/featuregroup.py +0 -34
- beratools/third_party/pyqtlet2/leaflet/layer/icon/__init__.py +0 -1
- beratools/third_party/pyqtlet2/leaflet/layer/icon/icon.py +0 -30
- beratools/third_party/pyqtlet2/leaflet/layer/imageoverlay.py +0 -18
- beratools/third_party/pyqtlet2/leaflet/layer/layer.py +0 -105
- beratools/third_party/pyqtlet2/leaflet/layer/layergroup.py +0 -45
- beratools/third_party/pyqtlet2/leaflet/layer/marker/__init__.py +0 -1
- beratools/third_party/pyqtlet2/leaflet/layer/marker/marker.py +0 -91
- beratools/third_party/pyqtlet2/leaflet/layer/tile/__init__.py +0 -2
- beratools/third_party/pyqtlet2/leaflet/layer/tile/gridlayer.py +0 -4
- beratools/third_party/pyqtlet2/leaflet/layer/tile/tilelayer.py +0 -16
- beratools/third_party/pyqtlet2/leaflet/layer/vector/__init__.py +0 -5
- beratools/third_party/pyqtlet2/leaflet/layer/vector/circle.py +0 -15
- beratools/third_party/pyqtlet2/leaflet/layer/vector/circlemarker.py +0 -18
- beratools/third_party/pyqtlet2/leaflet/layer/vector/path.py +0 -5
- beratools/third_party/pyqtlet2/leaflet/layer/vector/polygon.py +0 -14
- beratools/third_party/pyqtlet2/leaflet/layer/vector/polyline.py +0 -18
- beratools/third_party/pyqtlet2/leaflet/layer/vector/rectangle.py +0 -14
- beratools/third_party/pyqtlet2/leaflet/map/__init__.py +0 -1
- beratools/third_party/pyqtlet2/leaflet/map/map.py +0 -220
- beratools/third_party/pyqtlet2/mapwidget.py +0 -45
- beratools/third_party/pyqtlet2/web/custom.js +0 -43
- beratools/third_party/pyqtlet2/web/map.html +0 -23
- beratools/third_party/pyqtlet2/web/modules/leaflet_193/images/layers-2x.png +0 -0
- beratools/third_party/pyqtlet2/web/modules/leaflet_193/images/layers.png +0 -0
- beratools/third_party/pyqtlet2/web/modules/leaflet_193/images/marker-icon-2x.png +0 -0
- beratools/third_party/pyqtlet2/web/modules/leaflet_193/images/marker-icon.png +0 -0
- beratools/third_party/pyqtlet2/web/modules/leaflet_193/images/marker-shadow.png +0 -0
- beratools/third_party/pyqtlet2/web/modules/leaflet_193/leaflet.css +0 -656
- beratools/third_party/pyqtlet2/web/modules/leaflet_193/leaflet.js +0 -6
- beratools/third_party/pyqtlet2/web/modules/leaflet_draw_414/.codeclimate.yml +0 -14
- beratools/third_party/pyqtlet2/web/modules/leaflet_draw_414/.editorconfig +0 -4
- beratools/third_party/pyqtlet2/web/modules/leaflet_draw_414/.gitattributes +0 -22
- beratools/third_party/pyqtlet2/web/modules/leaflet_draw_414/.travis.yml +0 -43
- beratools/third_party/pyqtlet2/web/modules/leaflet_draw_414/LICENSE +0 -20
- beratools/third_party/pyqtlet2/web/modules/leaflet_draw_414/images/layers-2x.png +0 -0
- beratools/third_party/pyqtlet2/web/modules/leaflet_draw_414/images/layers.png +0 -0
- beratools/third_party/pyqtlet2/web/modules/leaflet_draw_414/images/marker-icon-2x.png +0 -0
- beratools/third_party/pyqtlet2/web/modules/leaflet_draw_414/images/marker-icon.png +0 -0
- beratools/third_party/pyqtlet2/web/modules/leaflet_draw_414/images/marker-shadow.png +0 -0
- beratools/third_party/pyqtlet2/web/modules/leaflet_draw_414/images/spritesheet-2x.png +0 -0
- beratools/third_party/pyqtlet2/web/modules/leaflet_draw_414/images/spritesheet.png +0 -0
- beratools/third_party/pyqtlet2/web/modules/leaflet_draw_414/images/spritesheet.svg +0 -156
- beratools/third_party/pyqtlet2/web/modules/leaflet_draw_414/leaflet.draw.css +0 -10
- beratools/third_party/pyqtlet2/web/modules/leaflet_draw_414/leaflet.draw.js +0 -10
- beratools/third_party/pyqtlet2/web/modules/leaflet_rotatedMarker_020/LICENSE +0 -22
- beratools/third_party/pyqtlet2/web/modules/leaflet_rotatedMarker_020/leaflet.rotatedMarker.js +0 -57
- beratools/tools/forest_line_ecosite.py +0 -216
- beratools/tools/lapis_all.py +0 -103
- beratools/tools/least_cost_path_from_chm.py +0 -152
- beratools-0.2.0.dist-info/METADATA +0 -63
- beratools-0.2.0.dist-info/RECORD +0 -142
- /beratools/gui/{img → assets}/BERALogo.png +0 -0
- /beratools/gui/{img → assets}/closed.gif +0 -0
- /beratools/gui/{img → assets}/closed.png +0 -0
- /beratools/{gui_tk → gui/assets}/gui.json +0 -0
- /beratools/gui/{img → assets}/open.gif +0 -0
- /beratools/gui/{img → assets}/open.png +0 -0
- /beratools/gui/{img → assets}/tool.gif +0 -0
- /beratools/gui/{img → assets}/tool.png +0 -0
- {beratools-0.2.0.dist-info → beratools-0.2.1.dist-info}/entry_points.txt +0 -0
beratools/gui/bt_data.py
CHANGED
|
@@ -1,487 +1,481 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
import
|
|
16
|
-
import
|
|
17
|
-
|
|
18
|
-
import
|
|
19
|
-
from
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
def default_callback(value):
|
|
28
|
-
"""
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
An object for interfacing with the BERA Tools executable.
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
self.
|
|
48
|
-
|
|
49
|
-
self.
|
|
50
|
-
self.
|
|
51
|
-
self.
|
|
52
|
-
self.
|
|
53
|
-
self.
|
|
54
|
-
self.
|
|
55
|
-
self.
|
|
56
|
-
self.
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
self.
|
|
65
|
-
self.
|
|
66
|
-
self.
|
|
67
|
-
self.
|
|
68
|
-
self.
|
|
69
|
-
self.
|
|
70
|
-
self.
|
|
71
|
-
self.
|
|
72
|
-
self.
|
|
73
|
-
self.
|
|
74
|
-
|
|
75
|
-
self.
|
|
76
|
-
|
|
77
|
-
self.
|
|
78
|
-
self.
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
self.load_saved_tool_info()
|
|
83
|
-
self.load_gui_data()
|
|
84
|
-
self.get_tool_history()
|
|
85
|
-
|
|
86
|
-
self.default_callback = default_callback
|
|
87
|
-
self.start_minimized = False
|
|
88
|
-
|
|
89
|
-
def set_bera_dir(self, path_str):
|
|
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
|
-
def
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
self.
|
|
163
|
-
|
|
164
|
-
def set_max_procs(self, val=-1):
|
|
165
|
-
"""
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
Returns
|
|
181
|
-
Returns
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
tool_type
|
|
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
|
-
|
|
295
|
-
self.
|
|
296
|
-
|
|
297
|
-
def
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
if self.settings:
|
|
301
|
-
if
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
def
|
|
335
|
-
self.
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
elif param['type'] == '
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
return
|
|
455
|
-
|
|
456
|
-
def
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
tool_name
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
tool_api
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
tool_type
|
|
482
|
-
for toolbox in self.bera_tools['toolbox']:
|
|
483
|
-
for tool in toolbox['tools']:
|
|
484
|
-
if tool_name == tool['name']:
|
|
485
|
-
tool_type = tool['tool_type']
|
|
486
|
-
|
|
487
|
-
return tool_type
|
|
1
|
+
"""
|
|
2
|
+
Copyright (C) 2025 Applied Geospatial Research Group.
|
|
3
|
+
|
|
4
|
+
This script is licensed under the GNU General Public License v3.0.
|
|
5
|
+
See <https://gnu.org/licenses/gpl-3.0> for full license details.
|
|
6
|
+
|
|
7
|
+
Author: Richard Zeng
|
|
8
|
+
|
|
9
|
+
Description:
|
|
10
|
+
This script is part of the BERA Tools.
|
|
11
|
+
Webpage: https://github.com/appliedgrg/beratools
|
|
12
|
+
|
|
13
|
+
The purpose of this script is to provide main interface for GUI related settings.
|
|
14
|
+
"""
|
|
15
|
+
import json
|
|
16
|
+
import os
|
|
17
|
+
import platform
|
|
18
|
+
from collections import OrderedDict
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
|
|
21
|
+
import beratools.core.constants as bt_const
|
|
22
|
+
|
|
23
|
+
running_windows = platform.system() == 'Windows'
|
|
24
|
+
BT_SHOW_ADVANCED_OPTIONS = False
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def default_callback(value):
|
|
28
|
+
"""
|
|
29
|
+
Define default callback that outputs using the print function.
|
|
30
|
+
|
|
31
|
+
When tools are called without providing a custom callback, this function
|
|
32
|
+
will be used to print to standard output.
|
|
33
|
+
"""
|
|
34
|
+
print(value)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class BTData(object):
|
|
38
|
+
"""An object for interfacing with the BERA Tools executable."""
|
|
39
|
+
|
|
40
|
+
def __init__(self):
|
|
41
|
+
if running_windows:
|
|
42
|
+
self.ext = '.exe'
|
|
43
|
+
else:
|
|
44
|
+
self.ext = ''
|
|
45
|
+
self.current_file_path = Path(__file__).resolve().parent
|
|
46
|
+
|
|
47
|
+
self.work_dir = ""
|
|
48
|
+
self.user_folder = Path('')
|
|
49
|
+
self.data_folder = Path('')
|
|
50
|
+
self.verbose = True
|
|
51
|
+
self.show_advanced = BT_SHOW_ADVANCED_OPTIONS
|
|
52
|
+
self.max_procs = -1
|
|
53
|
+
self.recent_tool = None
|
|
54
|
+
self.ascii_art = None
|
|
55
|
+
self.get_working_dir()
|
|
56
|
+
self.get_user_folder()
|
|
57
|
+
|
|
58
|
+
# set maximum available cpu core for tools
|
|
59
|
+
self.max_cpu_cores = os.cpu_count()
|
|
60
|
+
|
|
61
|
+
# load bera tools
|
|
62
|
+
self.tool_history = []
|
|
63
|
+
self.settings = {}
|
|
64
|
+
self.bera_tools = None
|
|
65
|
+
self.tools_list = []
|
|
66
|
+
self.sorted_tools = []
|
|
67
|
+
self.upper_toolboxes = []
|
|
68
|
+
self.lower_toolboxes = []
|
|
69
|
+
self.toolbox_list = []
|
|
70
|
+
self.get_bera_tools()
|
|
71
|
+
self.get_bera_tool_list()
|
|
72
|
+
self.get_bera_toolboxes()
|
|
73
|
+
self.sort_toolboxes()
|
|
74
|
+
|
|
75
|
+
self.setting_file = None
|
|
76
|
+
self.get_data_folder()
|
|
77
|
+
self.get_setting_file()
|
|
78
|
+
self.gui_setting_file = Path(self.current_file_path).joinpath(
|
|
79
|
+
bt_const.ASSETS_PATH, r"gui.json"
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
self.load_saved_tool_info()
|
|
83
|
+
self.load_gui_data()
|
|
84
|
+
self.get_tool_history()
|
|
85
|
+
|
|
86
|
+
self.default_callback = default_callback
|
|
87
|
+
self.start_minimized = False
|
|
88
|
+
|
|
89
|
+
def set_bera_dir(self, path_str):
|
|
90
|
+
"""Set the directory to the BERA Tools executable file."""
|
|
91
|
+
self.current_file_path = path_str
|
|
92
|
+
|
|
93
|
+
def add_tool_history(self, tool, params):
|
|
94
|
+
if 'tool_history' not in self.settings:
|
|
95
|
+
self.settings['tool_history'] = OrderedDict()
|
|
96
|
+
|
|
97
|
+
self.settings['tool_history'][tool] = params
|
|
98
|
+
self.settings['tool_history'].move_to_end(tool, last=False)
|
|
99
|
+
|
|
100
|
+
def remove_tool_history_item(self, index):
|
|
101
|
+
key = list(self.settings['tool_history'].keys())[index]
|
|
102
|
+
self.settings['tool_history'].pop(key)
|
|
103
|
+
self.save_tool_info()
|
|
104
|
+
|
|
105
|
+
def remove_tool_history_all(self):
|
|
106
|
+
self.settings.pop("tool_history")
|
|
107
|
+
self.save_tool_info()
|
|
108
|
+
|
|
109
|
+
def save_tool_info(self):
|
|
110
|
+
if self.recent_tool:
|
|
111
|
+
if 'gui_parameters' not in self.settings.keys():
|
|
112
|
+
self.settings['gui_parameters'] = {}
|
|
113
|
+
|
|
114
|
+
self.settings['gui_parameters']['recent_tool'] = self.recent_tool
|
|
115
|
+
|
|
116
|
+
with open(self.setting_file, 'w') as file_setting:
|
|
117
|
+
try:
|
|
118
|
+
json.dump(self.settings, file_setting, indent=4)
|
|
119
|
+
except json.decoder.JSONDecodeError:
|
|
120
|
+
pass
|
|
121
|
+
|
|
122
|
+
def save_setting(self, key, value):
|
|
123
|
+
# check setting directory existence
|
|
124
|
+
data_path = Path(self.setting_file).resolve().parent
|
|
125
|
+
if not data_path.exists():
|
|
126
|
+
data_path.mkdir()
|
|
127
|
+
|
|
128
|
+
self.load_saved_tool_info()
|
|
129
|
+
|
|
130
|
+
if value is not None:
|
|
131
|
+
if 'gui_parameters' not in self.settings.keys():
|
|
132
|
+
self.settings['gui_parameters'] = {}
|
|
133
|
+
|
|
134
|
+
self.settings['gui_parameters'][key] = value
|
|
135
|
+
|
|
136
|
+
with open(self.setting_file, 'w') as write_settings_file:
|
|
137
|
+
json.dump(self.settings, write_settings_file, indent=4)
|
|
138
|
+
|
|
139
|
+
def get_working_dir(self):
|
|
140
|
+
current_file = Path(__file__).resolve()
|
|
141
|
+
btool_dir = current_file.parents[1]
|
|
142
|
+
self.work_dir = btool_dir
|
|
143
|
+
|
|
144
|
+
def get_user_folder(self):
|
|
145
|
+
self.user_folder = Path.home().joinpath('.beratools')
|
|
146
|
+
if not self.user_folder.exists():
|
|
147
|
+
self.user_folder.mkdir()
|
|
148
|
+
|
|
149
|
+
def get_data_folder(self):
|
|
150
|
+
self.data_folder = self.user_folder.joinpath('.data')
|
|
151
|
+
if not self.data_folder.exists():
|
|
152
|
+
self.data_folder.mkdir()
|
|
153
|
+
|
|
154
|
+
def get_logger_file_name(self, name):
|
|
155
|
+
if not name:
|
|
156
|
+
name = 'beratools'
|
|
157
|
+
|
|
158
|
+
logger_file_name = self.user_folder.joinpath(name).with_suffix('.log')
|
|
159
|
+
return logger_file_name.as_posix()
|
|
160
|
+
|
|
161
|
+
def get_setting_file(self):
|
|
162
|
+
self.setting_file = self.data_folder.joinpath('saved_tool_parameters.json')
|
|
163
|
+
|
|
164
|
+
def set_max_procs(self, val=-1):
|
|
165
|
+
"""Set the maximum cores to use."""
|
|
166
|
+
self.max_procs = val
|
|
167
|
+
self.save_setting('max_procs', val)
|
|
168
|
+
|
|
169
|
+
def get_max_procs(self):
|
|
170
|
+
return self.max_procs
|
|
171
|
+
|
|
172
|
+
def get_max_cpu_cores(self):
|
|
173
|
+
return self.max_cpu_cores
|
|
174
|
+
|
|
175
|
+
def run_tool(self, tool_api, args, callback=None):
|
|
176
|
+
"""
|
|
177
|
+
Run a tool and specifies tool arguments.
|
|
178
|
+
|
|
179
|
+
Returns 0 if completes without error.
|
|
180
|
+
Returns 1 if error encountered (details are sent to callback).
|
|
181
|
+
Returns 2 if process is cancelled by user.
|
|
182
|
+
"""
|
|
183
|
+
try:
|
|
184
|
+
if callback is None:
|
|
185
|
+
callback = self.default_callback
|
|
186
|
+
except Exception as err:
|
|
187
|
+
callback(str(err))
|
|
188
|
+
return 1
|
|
189
|
+
|
|
190
|
+
# Call script using new process to make GUI responsive
|
|
191
|
+
try:
|
|
192
|
+
# convert to valid json string
|
|
193
|
+
args_string = str(args).replace("'", '"')
|
|
194
|
+
args_string = args_string.replace('True', 'true')
|
|
195
|
+
args_string = args_string.replace('False', 'false')
|
|
196
|
+
|
|
197
|
+
tool_name = self.get_bera_tool_name(tool_api)
|
|
198
|
+
tool_type = self.get_bera_tool_type(tool_name)
|
|
199
|
+
tool_args = None
|
|
200
|
+
|
|
201
|
+
if tool_type == 'python':
|
|
202
|
+
tool_args = [self.work_dir.joinpath(f'tools/{tool_api}.py').as_posix(),
|
|
203
|
+
'-i', args_string, '-p', str(self.get_max_procs()),
|
|
204
|
+
'-v', str(self.verbose)]
|
|
205
|
+
elif tool_type == 'executable':
|
|
206
|
+
print(globals().get(tool_api))
|
|
207
|
+
tool_args = globals()[tool_api](args_string)
|
|
208
|
+
lapis_path = self.work_dir.joinpath('./third_party/Lapis_0_8')
|
|
209
|
+
os.chdir(lapis_path.as_posix())
|
|
210
|
+
except Exception as err:
|
|
211
|
+
callback(str(err))
|
|
212
|
+
return 1
|
|
213
|
+
|
|
214
|
+
return tool_type, tool_args
|
|
215
|
+
|
|
216
|
+
def about(self):
|
|
217
|
+
"""Retrieve the description for BERA Tools."""
|
|
218
|
+
try:
|
|
219
|
+
about_text = 'BERA Tools provide a series of tools developed by AppliedGRG lab.\n\n'
|
|
220
|
+
about_text += self.ascii_art
|
|
221
|
+
return about_text
|
|
222
|
+
except (OSError, ValueError) as err:
|
|
223
|
+
return err
|
|
224
|
+
|
|
225
|
+
def license(self):
|
|
226
|
+
"""Retrieve the license information for BERA Tools."""
|
|
227
|
+
try:
|
|
228
|
+
with open(Path(self.current_file_path).joinpath(r'..\..\LICENSE.txt'), 'r') as f:
|
|
229
|
+
ret = f.read()
|
|
230
|
+
|
|
231
|
+
return ret
|
|
232
|
+
except (OSError, ValueError) as err:
|
|
233
|
+
return err
|
|
234
|
+
|
|
235
|
+
def load_saved_tool_info(self):
|
|
236
|
+
data_path = Path(self.setting_file).parent
|
|
237
|
+
if not data_path.exists():
|
|
238
|
+
data_path.mkdir()
|
|
239
|
+
|
|
240
|
+
saved_parameters = {}
|
|
241
|
+
json_file = Path(self.setting_file)
|
|
242
|
+
if not json_file.exists():
|
|
243
|
+
return
|
|
244
|
+
|
|
245
|
+
with open(json_file) as open_file:
|
|
246
|
+
try:
|
|
247
|
+
saved_parameters = json.load(open_file, object_pairs_hook=OrderedDict)
|
|
248
|
+
except json.decoder.JSONDecodeError:
|
|
249
|
+
pass
|
|
250
|
+
|
|
251
|
+
self.settings = saved_parameters
|
|
252
|
+
|
|
253
|
+
# parse file
|
|
254
|
+
if 'gui_parameters' in self.settings.keys():
|
|
255
|
+
gui_settings = self.settings['gui_parameters']
|
|
256
|
+
|
|
257
|
+
if 'max_procs' in gui_settings.keys():
|
|
258
|
+
self.max_procs = gui_settings['max_procs']
|
|
259
|
+
|
|
260
|
+
if 'recent_tool' in gui_settings.keys():
|
|
261
|
+
self.recent_tool = gui_settings['recent_tool']
|
|
262
|
+
if not self.get_bera_tool_api(self.recent_tool):
|
|
263
|
+
self.recent_tool = None
|
|
264
|
+
|
|
265
|
+
def load_gui_data(self):
|
|
266
|
+
gui_settings = {}
|
|
267
|
+
if not self.gui_setting_file.exists():
|
|
268
|
+
print("gui.json not exist.")
|
|
269
|
+
else:
|
|
270
|
+
# read the settings.json file if it exists
|
|
271
|
+
with open(self.gui_setting_file, 'r') as file_gui:
|
|
272
|
+
try:
|
|
273
|
+
gui_settings = json.load(file_gui)
|
|
274
|
+
except json.decoder.JSONDecodeError:
|
|
275
|
+
pass
|
|
276
|
+
|
|
277
|
+
# parse file
|
|
278
|
+
if 'ascii_art' in gui_settings.keys():
|
|
279
|
+
bera_art = ''
|
|
280
|
+
for line_of_art in gui_settings['ascii_art']:
|
|
281
|
+
bera_art += line_of_art
|
|
282
|
+
self.ascii_art = bera_art
|
|
283
|
+
|
|
284
|
+
def get_tool_history(self):
|
|
285
|
+
tool_history = []
|
|
286
|
+
self.load_saved_tool_info()
|
|
287
|
+
if self.settings:
|
|
288
|
+
if 'tool_history' in self.settings:
|
|
289
|
+
tool_history = self.settings['tool_history']
|
|
290
|
+
|
|
291
|
+
if tool_history:
|
|
292
|
+
self.tool_history = []
|
|
293
|
+
for item in tool_history:
|
|
294
|
+
item = self.get_bera_tool_name(item)
|
|
295
|
+
self.tool_history.append(item)
|
|
296
|
+
|
|
297
|
+
def get_saved_tool_params(self, tool_api, variable=None):
|
|
298
|
+
self.load_saved_tool_info()
|
|
299
|
+
|
|
300
|
+
if 'tool_history' in self.settings:
|
|
301
|
+
if tool_api in list(self.settings['tool_history']):
|
|
302
|
+
tool_params = self.settings['tool_history'][tool_api]
|
|
303
|
+
if tool_params:
|
|
304
|
+
if variable:
|
|
305
|
+
if variable in tool_params.keys():
|
|
306
|
+
saved_value = tool_params[variable]
|
|
307
|
+
return saved_value
|
|
308
|
+
else: # return all params
|
|
309
|
+
return tool_params
|
|
310
|
+
|
|
311
|
+
return None
|
|
312
|
+
|
|
313
|
+
def get_bera_tools(self):
|
|
314
|
+
tool_json = Path(self.current_file_path).joinpath(bt_const.ASSETS_PATH, r'beratools.json')
|
|
315
|
+
if tool_json.exists():
|
|
316
|
+
tool_json = open(Path(self.current_file_path).joinpath(bt_const.ASSETS_PATH, r'beratools.json'))
|
|
317
|
+
self.bera_tools = json.load(tool_json)
|
|
318
|
+
else:
|
|
319
|
+
print('Tool configuration file not exists')
|
|
320
|
+
|
|
321
|
+
def get_bera_tool_list(self):
|
|
322
|
+
self.tools_list = []
|
|
323
|
+
self.sorted_tools = []
|
|
324
|
+
|
|
325
|
+
for toolbox in self.bera_tools['toolbox']:
|
|
326
|
+
category = []
|
|
327
|
+
for item in toolbox['tools']:
|
|
328
|
+
if item['name']:
|
|
329
|
+
category.append(item['name'])
|
|
330
|
+
self.tools_list.append(item['name']) # add tool to list
|
|
331
|
+
|
|
332
|
+
self.sorted_tools.append(category)
|
|
333
|
+
|
|
334
|
+
def sort_toolboxes(self):
|
|
335
|
+
for toolbox in self.toolbox_list:
|
|
336
|
+
# Does not contain a sub toolbox, i.e. does not contain '/'
|
|
337
|
+
if toolbox.find('/') == (-1):
|
|
338
|
+
# add to both upper toolbox list and lower toolbox list
|
|
339
|
+
self.upper_toolboxes.append(toolbox)
|
|
340
|
+
self.lower_toolboxes.append(toolbox)
|
|
341
|
+
else: # Contains a sub toolbox
|
|
342
|
+
self.lower_toolboxes.append(toolbox) # add to the lower toolbox list
|
|
343
|
+
|
|
344
|
+
def get_bera_toolboxes(self):
|
|
345
|
+
toolboxes = []
|
|
346
|
+
for toolbox in self.bera_tools['toolbox']:
|
|
347
|
+
tb = toolbox['category']
|
|
348
|
+
toolboxes.append(tb)
|
|
349
|
+
|
|
350
|
+
self.toolbox_list = toolboxes
|
|
351
|
+
|
|
352
|
+
def get_bera_tool_params(self, tool_name):
|
|
353
|
+
new_param_whole = {'parameters': []}
|
|
354
|
+
tool = {}
|
|
355
|
+
batch_tool_list = []
|
|
356
|
+
for toolbox in self.bera_tools['toolbox']:
|
|
357
|
+
for single_tool in toolbox['tools']:
|
|
358
|
+
if single_tool['batch_processing']:
|
|
359
|
+
batch_tool_list.append(single_tool['name'])
|
|
360
|
+
|
|
361
|
+
if tool_name == single_tool['name']:
|
|
362
|
+
tool = single_tool
|
|
363
|
+
|
|
364
|
+
for key, value in tool.items():
|
|
365
|
+
if key != 'parameters':
|
|
366
|
+
new_param_whole[key] = value
|
|
367
|
+
|
|
368
|
+
# convert json format for parameters
|
|
369
|
+
if 'parameters' not in tool.keys():
|
|
370
|
+
print('issue')
|
|
371
|
+
|
|
372
|
+
for param in tool['parameters']:
|
|
373
|
+
single_param = {'name': param['parameter']}
|
|
374
|
+
if 'variable' in param.keys():
|
|
375
|
+
single_param['flag'] = param['variable']
|
|
376
|
+
# restore saved parameters
|
|
377
|
+
saved_value = self.get_saved_tool_params(tool['tool_api'], param['variable'])
|
|
378
|
+
if saved_value is not None:
|
|
379
|
+
single_param['saved_value'] = saved_value
|
|
380
|
+
else:
|
|
381
|
+
single_param['flag'] = 'FIXME'
|
|
382
|
+
|
|
383
|
+
single_param['output'] = param['output']
|
|
384
|
+
if not param['output']:
|
|
385
|
+
if param['type'] == 'list':
|
|
386
|
+
if tool_name == 'Batch Processing':
|
|
387
|
+
single_param['parameter_type'] = {'OptionList': batch_tool_list}
|
|
388
|
+
single_param['data_type'] = 'String'
|
|
389
|
+
else:
|
|
390
|
+
single_param['parameter_type'] = {'OptionList': param['data']}
|
|
391
|
+
single_param['data_type'] = 'String'
|
|
392
|
+
if param['typelab'] == 'text':
|
|
393
|
+
single_param['data_type'] = 'String'
|
|
394
|
+
elif param['typelab'] == 'int':
|
|
395
|
+
single_param['data_type'] = 'Integer'
|
|
396
|
+
elif param['typelab'] == 'float':
|
|
397
|
+
single_param['data_type'] = 'Float'
|
|
398
|
+
elif param['typelab'] == 'bool':
|
|
399
|
+
single_param['data_type'] = 'Boolean'
|
|
400
|
+
elif param['type'] == 'text':
|
|
401
|
+
single_param['parameter_type'] = 'String'
|
|
402
|
+
elif param['type'] == 'number':
|
|
403
|
+
if param['typelab'] == 'int':
|
|
404
|
+
single_param['parameter_type'] = 'Integer'
|
|
405
|
+
else:
|
|
406
|
+
single_param['parameter_type'] = 'Float'
|
|
407
|
+
elif param['type'] == 'file':
|
|
408
|
+
single_param['parameter_type'] = {'ExistingFile': [param['typelab']]}
|
|
409
|
+
else:
|
|
410
|
+
single_param['parameter_type'] = {'ExistingFile': ''}
|
|
411
|
+
else:
|
|
412
|
+
single_param["parameter_type"] = {'NewFile': [param['typelab']]}
|
|
413
|
+
|
|
414
|
+
single_param['description'] = param['description']
|
|
415
|
+
|
|
416
|
+
if param['type'] == 'raster':
|
|
417
|
+
for i in single_param["parameter_type"].keys():
|
|
418
|
+
single_param['parameter_type'][i] = 'Raster'
|
|
419
|
+
elif param['type'] == 'lidar':
|
|
420
|
+
for i in single_param["parameter_type"].keys():
|
|
421
|
+
single_param['parameter_type'][i] = 'Lidar'
|
|
422
|
+
elif param['type'] == 'vector':
|
|
423
|
+
for i in single_param["parameter_type"].keys():
|
|
424
|
+
single_param['parameter_type'][i] = 'Vector'
|
|
425
|
+
if 'layer' in param.keys():
|
|
426
|
+
layer_value = self.get_saved_tool_params(tool['tool_api'], param['layer'])
|
|
427
|
+
single_param['layer'] = {'layer_name': param['layer'], 'layer_value': layer_value}
|
|
428
|
+
|
|
429
|
+
elif param['type'] == 'Directory':
|
|
430
|
+
single_param['parameter_type'] = {'Directory': [param['typelab']]}
|
|
431
|
+
|
|
432
|
+
single_param['default_value'] = param['default']
|
|
433
|
+
if "optional" in param.keys():
|
|
434
|
+
single_param['optional'] = param['optional']
|
|
435
|
+
else:
|
|
436
|
+
single_param['optional'] = False
|
|
437
|
+
|
|
438
|
+
new_param_whole['parameters'].append(single_param)
|
|
439
|
+
|
|
440
|
+
return new_param_whole
|
|
441
|
+
|
|
442
|
+
def get_bera_tool_parameters_list(self, tool_name):
|
|
443
|
+
params = self.get_bera_tool_params(tool_name)
|
|
444
|
+
param_list = {}
|
|
445
|
+
for item in params['parameters']:
|
|
446
|
+
param_list[item['flag']] = item['default_value']
|
|
447
|
+
|
|
448
|
+
return param_list
|
|
449
|
+
|
|
450
|
+
def get_bera_tool_args(self, tool_name):
|
|
451
|
+
params = self.get_bera_tool_params(tool_name)
|
|
452
|
+
tool_args = params['parameters']
|
|
453
|
+
|
|
454
|
+
return tool_args
|
|
455
|
+
|
|
456
|
+
def get_bera_tool_name(self, tool_api):
|
|
457
|
+
tool_name = None
|
|
458
|
+
for toolbox in self.bera_tools['toolbox']:
|
|
459
|
+
for tool in toolbox['tools']:
|
|
460
|
+
if tool_api == tool['tool_api']:
|
|
461
|
+
tool_name = tool['name']
|
|
462
|
+
|
|
463
|
+
return tool_name
|
|
464
|
+
|
|
465
|
+
def get_bera_tool_api(self, tool_name):
|
|
466
|
+
tool_api = None
|
|
467
|
+
for toolbox in self.bera_tools['toolbox']:
|
|
468
|
+
for tool in toolbox['tools']:
|
|
469
|
+
if tool_name == tool['name']:
|
|
470
|
+
tool_api = tool['tool_api']
|
|
471
|
+
|
|
472
|
+
return tool_api
|
|
473
|
+
|
|
474
|
+
def get_bera_tool_type(self, tool_name):
|
|
475
|
+
tool_type = None
|
|
476
|
+
for toolbox in self.bera_tools['toolbox']:
|
|
477
|
+
for tool in toolbox['tools']:
|
|
478
|
+
if tool_name == tool['name']:
|
|
479
|
+
tool_type = tool['tool_type']
|
|
480
|
+
|
|
481
|
+
return tool_type
|