BERATools 0.2.3__py3-none-any.whl → 0.2.4__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.
Files changed (78) hide show
  1. beratools/__init__.py +8 -3
  2. beratools/core/{algo_footprint_rel.py → algo_canopy_footprint_exp.py} +176 -139
  3. beratools/core/algo_centerline.py +61 -77
  4. beratools/core/algo_common.py +48 -57
  5. beratools/core/algo_cost.py +18 -25
  6. beratools/core/algo_dijkstra.py +37 -45
  7. beratools/core/algo_line_grouping.py +100 -100
  8. beratools/core/algo_merge_lines.py +40 -8
  9. beratools/core/algo_split_with_lines.py +289 -304
  10. beratools/core/algo_vertex_optimization.py +25 -46
  11. beratools/core/canopy_threshold_relative.py +755 -0
  12. beratools/core/constants.py +8 -9
  13. beratools/{tools → core}/line_footprint_functions.py +411 -258
  14. beratools/core/logger.py +18 -2
  15. beratools/core/tool_base.py +17 -75
  16. beratools/gui/assets/BERALogo.ico +0 -0
  17. beratools/gui/assets/BERA_Splash.gif +0 -0
  18. beratools/gui/assets/BERA_WizardImage.png +0 -0
  19. beratools/gui/assets/beratools.json +475 -2171
  20. beratools/gui/bt_data.py +585 -234
  21. beratools/gui/bt_gui_main.py +129 -91
  22. beratools/gui/main.py +4 -7
  23. beratools/gui/tool_widgets.py +530 -354
  24. beratools/tools/__init__.py +0 -7
  25. beratools/tools/{line_footprint_absolute.py → canopy_footprint_absolute.py} +81 -56
  26. beratools/tools/canopy_footprint_exp.py +113 -0
  27. beratools/tools/centerline.py +30 -37
  28. beratools/tools/check_seed_line.py +127 -0
  29. beratools/tools/common.py +65 -586
  30. beratools/tools/{line_footprint_fixed.py → ground_footprint.py} +140 -117
  31. beratools/tools/line_footprint_relative.py +64 -35
  32. beratools/tools/tool_template.py +48 -40
  33. beratools/tools/vertex_optimization.py +20 -34
  34. beratools/utility/env_checks.py +53 -0
  35. beratools/utility/spatial_common.py +210 -0
  36. beratools/utility/tool_args.py +138 -0
  37. beratools-0.2.4.dist-info/METADATA +134 -0
  38. beratools-0.2.4.dist-info/RECORD +50 -0
  39. {beratools-0.2.3.dist-info → beratools-0.2.4.dist-info}/WHEEL +1 -1
  40. beratools-0.2.4.dist-info/entry_points.txt +3 -0
  41. beratools-0.2.4.dist-info/licenses/LICENSE +674 -0
  42. beratools/core/algo_tiler.py +0 -428
  43. beratools/gui/__init__.py +0 -11
  44. beratools/gui/batch_processing_dlg.py +0 -513
  45. beratools/gui/map_window.py +0 -162
  46. beratools/tools/Beratools_r_script.r +0 -1120
  47. beratools/tools/Ht_metrics.py +0 -116
  48. beratools/tools/batch_processing.py +0 -136
  49. beratools/tools/canopy_threshold_relative.py +0 -672
  50. beratools/tools/canopycostraster.py +0 -222
  51. beratools/tools/fl_regen_csf.py +0 -428
  52. beratools/tools/forest_line_attributes.py +0 -408
  53. beratools/tools/line_grouping.py +0 -45
  54. beratools/tools/ln_relative_metrics.py +0 -615
  55. beratools/tools/r_cal_lpi_elai.r +0 -25
  56. beratools/tools/r_generate_pd_focalraster.r +0 -101
  57. beratools/tools/r_interface.py +0 -80
  58. beratools/tools/r_point_density.r +0 -9
  59. beratools/tools/rpy_chm2trees.py +0 -86
  60. beratools/tools/rpy_dsm_chm_by.py +0 -81
  61. beratools/tools/rpy_dtm_by.py +0 -63
  62. beratools/tools/rpy_find_cellsize.py +0 -43
  63. beratools/tools/rpy_gnd_csf.py +0 -74
  64. beratools/tools/rpy_hummock_hollow.py +0 -85
  65. beratools/tools/rpy_hummock_hollow_raster.py +0 -71
  66. beratools/tools/rpy_las_info.py +0 -51
  67. beratools/tools/rpy_laz2las.py +0 -40
  68. beratools/tools/rpy_lpi_elai_lascat.py +0 -466
  69. beratools/tools/rpy_normalized_lidar_by.py +0 -56
  70. beratools/tools/rpy_percent_above_dbh.py +0 -80
  71. beratools/tools/rpy_points2trees.py +0 -88
  72. beratools/tools/rpy_vegcoverage.py +0 -94
  73. beratools/tools/tiler.py +0 -48
  74. beratools/tools/zonal_threshold.py +0 -144
  75. beratools-0.2.3.dist-info/METADATA +0 -108
  76. beratools-0.2.3.dist-info/RECORD +0 -74
  77. beratools-0.2.3.dist-info/entry_points.txt +0 -2
  78. beratools-0.2.3.dist-info/licenses/LICENSE +0 -22
@@ -1,71 +0,0 @@
1
- import math
2
- import os
3
- import time
4
-
5
- from beratools.tools.common import *
6
- from beratools.tools.r_interface import *
7
-
8
- def hh_raster(callback, in_raster, Min_ws, lawn_range, cell_size, out_folder, processes, verbose):
9
- rprocesses = r_processes(processes)
10
-
11
- in_raster = in_raster.replace("\\", "/")
12
- out_folder = out_folder.replace("\\", "/")
13
-
14
- # assign R script file to local variable
15
- Beratools_R_script = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'Beratools_r_script.r')
16
- # Defining the R script and loading the instance in Python
17
- r['source'](Beratools_R_script)
18
- # Loading the function defined in R script.
19
- r_hh_function = robjects.globalenv['hh_function_byraster']
20
-
21
- # Invoking the R function
22
- r_hh_function(in_raster, cell_size, Min_ws, lawn_range, out_folder, rprocesses)
23
-
24
-
25
- if __name__ == '__main__':
26
- start_time = time.time()
27
- print('Hummock and Hollow detection from DTM raster process.\n'
28
- '@ {}'.format(time.strftime("%d %b %Y %H:%M:%S", time.localtime())))
29
-
30
- packages = ['terra'] # ,'comprehenr','na.tools','sf','sp']#,'devtools','gdal']#,'fasterRaster']
31
- check_r_packages_installation(packages)
32
-
33
- print("Checking input parameters ...")
34
- in_args, in_verbose = check_arguments()
35
- in_raster = in_args.input["in_raster"]
36
- try:
37
- cell_size = float(in_args.input["cell_size"])
38
- in_args.input["cell_size"] = cell_size
39
- except ValueError:
40
- print("Invalid input of cell_size, default value will be used")
41
- in_args.input["cell_size"] = 1.0
42
-
43
- try:
44
- ws = float(in_args.input["Min_ws"])
45
- in_args.input["Min_ws"] = ws
46
- except ValueError:
47
- print("Invalid input of circular diameter, default value will be used")
48
- in_args.input["Min_ws"] = 3.0
49
- try:
50
- lawn_range = float(in_args.input["lawn_range"])
51
- in_args.input["lawn_range"] = lawn_range
52
- except ValueError:
53
- print("Invalid input of range height of lawns, default value will be used")
54
- in_args.input["lawn_range"] = 0.1
55
-
56
- out_folder = in_args.input["out_folder"]
57
-
58
- if not os.path.isfile(in_raster):
59
- print("Error! Cannot locate raster folder, please check.")
60
- exit()
61
-
62
- if not os.path.exists(out_folder):
63
- print("Warning! Cannot locate output folder, It will be created.")
64
- os.makedirs(out_folder)
65
-
66
- print("Checking input parameters ... Done")
67
-
68
- hh_raster(print, **in_args.input, processes=int(in_args.processes), verbose=in_verbose)
69
-
70
- print('Hummock and Hollow detection from DTM raster process is done in {} seconds)'
71
- .format(round(time.time() - start_time, 5)))
@@ -1,51 +0,0 @@
1
- import os
2
- import time
3
-
4
- from beratools.tools.common import *
5
- from beratools.tools.r_interface import *
6
-
7
- def las_info(callback, in_las_folder, processes, verbose):
8
- rprocesses = r_processes(processes)
9
- # assign R script file to local variable
10
- Beratools_R_script = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'Beratools_r_script.r')
11
- # Defining the R script and loading the instance in Python
12
- r['source'](Beratools_R_script)
13
- # Loading the function defined in R script.
14
- r_normalized_lidar = robjects.globalenv['las_info']
15
-
16
- # Invoking the R function
17
- r_normalized_lidar(in_las_folder, rprocesses)
18
-
19
-
20
- if __name__ == '__main__':
21
- start_time = time.time()
22
- print('LiDAR data information..\n @ {}'
23
- .format(time.strftime("%a, %d %b %Y %H:%M:%S", time.localtime())))
24
-
25
- packages = ['lidR', 'future']
26
- check_r_packages_installation(packages)
27
-
28
- print("Checking input parameters....")
29
- in_args, in_verbose = check_arguments()
30
-
31
- in_las_folder = in_args.input["in_las_folder"]
32
-
33
- if not os.path.exists(in_las_folder):
34
- print("Error! Cannot locate Las folder, please check.")
35
- exit()
36
- else:
37
- found = False
38
- for files in os.listdir(in_las_folder):
39
- if files.endswith(".las") or files.endswith(".laz"):
40
- found = True
41
- break
42
- if not found:
43
- print("Error! Cannot locate input LAS file(s), please check!")
44
- exit()
45
-
46
- print("Checking input parameters....Done")
47
-
48
- las_info(print, **in_args.input, processes=int(in_args.processes), verbose=in_verbose)
49
-
50
- print('Display LiDAR data information is done in {} seconds)'
51
- .format(round(time.time() - start_time, 5)))
@@ -1,40 +0,0 @@
1
- import os
2
- import time
3
-
4
- from beratools.tools.common import *
5
- from beratools.tools.r_interface import *
6
-
7
- def laz2las(callback, in_las_folder, out_folder, processes, verbose):
8
- rprocesses = r_processes(processes)
9
-
10
- # assign R script file to local variable
11
- Beratools_R_script = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'Beratools_r_script.r')
12
- # Defining the R script and loading the instance in Python
13
- r['source'](Beratools_R_script)
14
- # Loading the function defined in R script.
15
- r_laz2las = robjects.globalenv['laz2las']
16
-
17
- # Invoking the R function
18
- r_laz2las(in_las_folder, out_folder, rprocesses)
19
-
20
-
21
- if __name__ == '__main__':
22
- start_time = time.time()
23
- print('Unzip liDAR data processing..\n @ {}'
24
- .format(time.strftime("%a, %d %b %Y %H:%M:%S", time.localtime())))
25
-
26
- packages = ['lidR', 'future']
27
- check_r_packages_installation(packages)
28
-
29
- print("Checking input parameters....")
30
- in_args, in_verbose = check_arguments()
31
-
32
- in_las_folder = in_args.input["in_las_folder"]
33
- out_folder = in_args.input["out_folder"]
34
-
35
- check_las_files_existence(in_las_folder)
36
-
37
- print("Checking input parameters....Done")
38
- laz2las(print, **in_args.input, processes=int(in_args.processes), verbose=in_verbose)
39
- print('Unzip liDAR data processing is done in {} seconds)'
40
- .format(round(time.time() - start_time, 5)))
@@ -1,466 +0,0 @@
1
- import math
2
- import os
3
- import winreg
4
- import time
5
- import geopandas
6
- import sys
7
- import numpy
8
- import xrspatial.focal as focal
9
- from xrspatial import convolution
10
- import xarray as xr
11
-
12
- from multiprocessing.pool import Pool
13
- from beratools.tools.common import *
14
-
15
-
16
- class OperationCancelledException(Exception):
17
- pass
18
-
19
-
20
- try: # integrated R env
21
- # check R language within env
22
- current_env_path = os.environ['CONDA_PREFIX']
23
- # if os.path.isdir(current_env_path):
24
- os.environ['R_HOME'] = os.path.join(current_env_path, r"Lib\R")
25
- os.environ['R_USER'] = os.path.expanduser('~')
26
- os.environ['R_LIBS_USER'] = os.path.join(current_env_path, r"Lib\R\library")
27
-
28
- except FileNotFoundError:
29
- print("Warning: Please install R for this process!!")
30
- exit()
31
-
32
- import rpy2.robjects as robjects
33
- from rpy2.robjects.packages import importr, data
34
- from rpy2.robjects.vectors import StrVector
35
-
36
-
37
- def lpi_lai(arg):
38
- pdTotal = arg[0]
39
- pdGround = arg[1]
40
- out_folder = arg[2]
41
- filename = arg[3]
42
- scan_angle = float(arg[4])
43
-
44
- ##variable for not calling R
45
- cell_size = float(arg[5])
46
- radius = float(arg[6])
47
- tfocal_filename = filename + "_tfocal_py.tif"
48
- gfocal_filename = filename + "_gfocal_py.tif"
49
- # out_tfocal = os.path.join(out_folder, tfocal_filename)
50
- # out_gfocal = os.path.join(out_folder, gfocal_filename)
51
-
52
- ## output files variables
53
- out_lpi_fielname = filename + "_LPI_py.tif"
54
- out_elai_fielname = filename + "_eLAI_py.tif"
55
- LPI_folder = os.path.join(out_folder, "LPI")
56
- eLAI_folder = os.path.join(out_folder, "eLAI")
57
- out_lpi = os.path.join(LPI_folder, out_lpi_fielname)
58
- out_elai = os.path.join(eLAI_folder, out_elai_fielname)
59
-
60
- # Working out the searching radius
61
- # with rasterio.open(chm) as image:
62
- # ndarray = image.read(1)
63
- # ndarray[ndarray==image.nodata]=numpy.NaN
64
- # ndarray[ndarray <0.0] = numpy.NaN
65
- # radius = math.ceil(numpy.nanmean(ndarray) * 2)
66
-
67
- print("Calculating LPI and eLAI for {} ...".format(filename))
68
- with rasterio.open(pdTotal) as pd_total:
69
- with rasterio.open(pdGround) as pd_Ground:
70
- raster_profile = pd_total.profile
71
- pd_total_ndarray = pd_total.read(1, boundless=True)
72
- nodata = pd_total.nodata
73
- pd_total_ndarray[pd_total_ndarray == nodata] = numpy.nan
74
- kernel = convolution.circle_kernel(cell_size, cell_size, radius)
75
- total_focalsum = fs_raster_stdmean(pd_total_ndarray, kernel, nodata)
76
- write_total_focalsum = rasterio.open(tfocal_filename, 'w', **raster_profile)
77
- write_total_focalsum.write(total_focalsum, 1)
78
- write_total_focalsum.close()
79
- del write_total_focalsum
80
-
81
- pd_ground_ndarray = pd_Ground.read(1, boundless=True)
82
- nodata = pd_Ground.nodata
83
- pd_ground_ndarray[pd_ground_ndarray == nodata] = numpy.nan
84
- ground_focalsum = fs_raster_stdmean(pd_ground_ndarray, kernel, nodata)
85
- write_ground_focalsum = rasterio.open(gfocal_filename, 'w', **raster_profile)
86
- write_ground_focalsum.write(ground_focalsum, 1)
87
- write_ground_focalsum.close()
88
- del write_ground_focalsum
89
- del pd_total
90
-
91
- del pd_Ground
92
- lpi_array = numpy.divide(pd_ground_ndarray, pd_total_ndarray, out=numpy.zeros_like(pd_ground_ndarray),
93
- where=pd_total_ndarray != 0)
94
-
95
- print("Calculating LPI: {} ...".format(filename))
96
- write_lpi = rasterio.open(out_lpi, 'w', **raster_profile)
97
- write_lpi.write(lpi_array, 1)
98
- write_lpi.close()
99
- del write_lpi
100
- print('%{}'.format(80))
101
- print("Calculating LPI: {} ...Done".format(filename))
102
-
103
- print("Calculating eLAI: {} ...".format(filename))
104
- elai_array = ((math.cos(((scan_angle / 2.0) / 180.0) * math.pi)) / 0.5) * (numpy.log(lpi_array)) * -1
105
-
106
- write_elai = rasterio.open(out_elai, 'w', **raster_profile)
107
- write_elai.write(elai_array, 1)
108
- write_elai.close()
109
- del write_elai
110
- print("Calculating eLAI: {} ... Done".format(filename))
111
-
112
-
113
- def fs_raster_stdmean(in_ndarray, kernel, nodata):
114
- # This function uses xrspatial whcih can handle large data but slow
115
- in_ndarray[in_ndarray == nodata] = numpy.nan
116
- result_ndarray = focal.focal_stats(xr.DataArray(in_ndarray), kernel, stats_funcs=['sum'])
117
-
118
- # Flattening the array
119
- flatten_sum_result_ndarray = result_ndarray.data.reshape(-1)
120
-
121
- # Re-shaping the array
122
- reshape_sum_ndarray = flatten_sum_result_ndarray.reshape(in_ndarray.shape[0], in_ndarray.shape[1])
123
- return reshape_sum_ndarray
124
-
125
-
126
- def r_lpi_lai_with_focalR(arg):
127
- r = robjects.r
128
- pdTotal = arg[0]
129
- pdGround = arg[1]
130
- out_folder = arg[2]
131
- filename = arg[3]
132
- scan_angle = float(arg[4])
133
-
134
- ## output files variables
135
- out_lpi_fielname = filename + "_LPI_r.tif"
136
- out_elai_fielname = filename + "_eLAI_r.tif"
137
- LPI_folder = os.path.join(out_folder, "LPI")
138
- eLAI_folder = os.path.join(out_folder, "eLAI")
139
- out_lpi = os.path.join(LPI_folder, out_lpi_fielname)
140
- out_elai = os.path.join(eLAI_folder, out_elai_fielname)
141
-
142
- radius = float(arg[6])
143
- print("Calculating LPI and eLAI for {} ...".format(filename))
144
-
145
- # assign R script file to local variable
146
- rlpi_elai_script = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'r_cal_lpi_elai.r')
147
- # Defining the R script and loading the instance in Python
148
- r['source'](rlpi_elai_script)
149
- # Loading the function defined in R script.
150
- rlpi_elai = robjects.globalenv['rlpi_elai']
151
- # Invoking the R function
152
- rlpi_elai(pdTotal, pdGround, radius, scan_angle, out_lpi, out_elai)
153
-
154
- # At this stage no process for CHM
155
-
156
- print("Calculating LPI adn eLAI: {} ... Done".format(filename))
157
-
158
-
159
- def f_pulse_density(ctg, out_folder, rprocesses, verbose):
160
- r = robjects.r
161
- print('Calculate cell size from average point cloud density...')
162
- cache_folder = os.path.join(out_folder, "Cache")
163
- # assign R script file to local variable
164
- beratools_r_script = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'Beratools_r_script.r')
165
- # Defining the R script and loading the instance in Python
166
- r['source'](beratools_r_script)
167
- # Loading the function defined in R script.
168
- pd2cellsize = robjects.globalenv['pd2cellsize']
169
- # Invoking the R function
170
- cell_size = pd2cellsize(ctg, rprocesses)
171
-
172
- return (cell_size)
173
-
174
-
175
- def pd_raster(callback, in_polygon_file, in_las_folder, cut_ht, radius_fr_CHM, focal_radius, pulse_density,
176
- cell_size, mean_scanning_angle, out_folder, processes, verbose):
177
- r = robjects.r
178
- import psutil
179
- stats = psutil.virtual_memory()
180
- available = getattr(stats, 'available') / 1024000000
181
- if 2 < processes <= 8:
182
- if available <= 50:
183
- rprocesses = 2
184
- elif 50 < available <= 150:
185
- rprocesses = 4
186
- elif 150 < available <= 250:
187
- rprocesses = 8
188
- else:
189
- rprocesses = 8
190
-
191
- cache_folder = os.path.join(out_folder, "Cache")
192
- # dtm_folder=os.path.join(out_folder,"DTM")
193
- # dsm_folder=os.path.join(out_folder,"DSM")
194
- # chm_folder=os.path.join(out_folder,"CHM")
195
- PD_folder = os.path.join(out_folder, "PD")
196
- PD_Total_folder = os.path.join(PD_folder, "Total")
197
- PD_Ground_folder = os.path.join(PD_folder, "Ground")
198
- LPI_folder = os.path.join(out_folder, "LPI")
199
- eLAI_folder = os.path.join(out_folder, "eLAI")
200
-
201
- if not os.path.exists(cache_folder):
202
- os.makedirs(cache_folder)
203
-
204
- if not os.path.exists(PD_folder):
205
- os.makedirs(PD_folder)
206
- if not os.path.exists(PD_Total_folder):
207
- os.makedirs(PD_Total_folder)
208
- if not os.path.exists(PD_Ground_folder):
209
- os.makedirs(PD_Ground_folder)
210
- if not os.path.exists(LPI_folder):
211
- os.makedirs(LPI_folder)
212
- if not os.path.exists(eLAI_folder):
213
- os.makedirs(eLAI_folder)
214
-
215
- lascat = lidR.readLAScatalog(in_las_folder, filter="-drop_class 7")
216
- cache_folder = cache_folder.replace("\\", "/")
217
- # dtm_folder = dtm_folder.replace("\\", "/") + "/{*}_dtm"
218
- # chm_folder = chm_folder.replace("\\","/") + "/{*}_chm"
219
- PD_Total_folder = PD_folder.replace("\\", "/") + "/Total"
220
- PD_Ground_folder = PD_folder.replace("\\", "/") + "/Ground"
221
- LPI_folder = LPI_folder.replace("\\", "/")
222
- eLAI_folder = eLAI_folder.replace("\\", "/")
223
-
224
- if not in_polygon_file == "":
225
- try:
226
- r.vect(in_polygon_file)
227
- except FileNotFoundError:
228
- print("Could not locate shapefile, all area will be process")
229
-
230
- if cell_size <= 0:
231
- if pulse_density <= 0:
232
- cell_size = f_pulse_density(lascat, out_folder, rprocesses, verbose)
233
-
234
- # assign R script file to local variable
235
- Beratools_R_script = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'Beratools_r_script.r')
236
- # Defining the R script and loading the instance in Python
237
- r['source'](Beratools_R_script)
238
- # Loading the function defined in R script.
239
- generate_pd = robjects.globalenv['generate_pd']
240
- # Invoking the R function
241
- generate_pd(lascat, radius_fr_CHM, focal_radius, cell_size, cache_folder, cut_ht, PD_Ground_folder,
242
- PD_Total_folder, rprocesses)
243
-
244
- # At this stage no process for CHM
245
- # locate the point density raster for generating eLAI and LPI
246
- pd_total_filelist = []
247
- pd_ground_filelist = []
248
-
249
- # Get raster files lists
250
- for root, dirs, files in sorted(os.walk(os.path.join(out_folder, "PD\\Total"))):
251
- for file in files:
252
- if file.endswith("_PD_Tfocalsum.tif"):
253
- pd_total_filelist.append(os.path.join(root, file))
254
- del root, dirs, files
255
- for root, dirs, files in sorted(os.walk(os.path.join(out_folder, "PD\\Ground"))):
256
- for file in files:
257
- if file.endswith("_PD_Gfocalsum.tif"):
258
- pd_ground_filelist.append(os.path.join(root, file))
259
- del root, dirs, files
260
- args_list = []
261
-
262
- # At this stage no process for finding average cell size from all CHM
263
- radius_fr_CHM = False
264
- if radius_fr_CHM:
265
- pass
266
- # chm_filelist = []
267
- # for root, dirs, files in sorted(os.walk(os.path.join(out_folder, "CHM"))):
268
- # for file in files:
269
- # if file.endswith("_chm.tif"):
270
- # chm_filelist.append(os.path.join(root, file))
271
- # del root, dirs, files
272
- #
273
- # if len(pd_total_filelist) == len(pd_ground_filelist) == len(chm_filelist):
274
- # for i in range(0, len(pd_total_filelist)):
275
- # chm_filename = os.path.splitext(os.path.split(chm_filelist[i])[1])[0]
276
- # pdtotal_filename = os.path.splitext(os.path.split(pd_total_filelist[i])[1])[0]
277
- # pdGround_filename = os.path.splitext(os.path.split(pd_ground_filelist[i])[1])[0]
278
- # result_list = []
279
- # if chm_filename[0:-4] == pdtotal_filename[0:-13] == pdGround_filename[2:-13]:
280
- # result_list.append(chm_filelist[i])
281
- # result_list.append(pd_total_filelist[i])
282
- # result_list.append(pd_ground_filelist[i])
283
- # result_list.append(out_folder)
284
- # result_list.append(chm_filename[0:-4])
285
- # result_list.append(mean_scanning_angle)
286
- # result_list.append(cell_size)
287
- # result_list.append(focal_radius)
288
- # args_list.append(result_list)
289
- #
290
- # try:
291
- # total_steps = len(args_list)
292
- # features = []
293
- # with Pool(processes=int(processes)) as pool:
294
- # step = 0
295
- # # execute tasks in order, process results out of order
296
- # for result in pool.imap_unordered(lpi_lai, args_list):
297
- # if BT_DEBUGGING:
298
- # print('Got result: {}'.format(result), flush=True)
299
- # features.append(result)
300
- # step += 1
301
- # print('%{}'.format(step / total_steps * 100))
302
- #
303
- # except OperationCancelledException:
304
- # print("Operation cancelled")
305
- # exit()
306
- else:
307
- # processing LPI_eLAI
308
- # prepare arguments
309
- if len(pd_total_filelist) == len(pd_ground_filelist):
310
- for i in range(0, len(pd_total_filelist)):
311
-
312
- pdtotal_filename = os.path.splitext(os.path.split(pd_total_filelist[i])[1])[0]
313
- pdGround_filename = os.path.splitext(os.path.split(pd_ground_filelist[i])[1])[0]
314
- result_list = []
315
- if pdtotal_filename[0:-13] == pdGround_filename[2:-13]:
316
- result_list.append(pd_total_filelist[i])
317
- result_list.append(pd_ground_filelist[i])
318
- result_list.append(out_folder)
319
- result_list.append(pdtotal_filename[0:-13])
320
- result_list.append(mean_scanning_angle)
321
- result_list.append(cell_size)
322
- result_list.append(focal_radius)
323
- args_list.append(result_list)
324
-
325
- # Multiprocessing eLAI and LPI raster using R package.
326
- try:
327
- total_steps = len(args_list)
328
- if processes >= total_steps:
329
- processes = total_steps
330
-
331
- features = []
332
- with Pool(processes=int(processes)) as pool:
333
- step = 0
334
- # execute tasks in order, process results out of order
335
- for result in pool.imap_unordered(r_lpi_lai_with_focalR, args_list):
336
- if BT_DEBUGGING:
337
- print('Got result: {}'.format(result), flush=True)
338
- features.append(result)
339
- step += 1
340
- print('%{}'.format(step / total_steps * 100))
341
-
342
- except OperationCancelledException:
343
- print("Operation cancelled")
344
- exit()
345
-
346
-
347
- if __name__ == '__main__':
348
- start_time = time.time()
349
- print('Starting generating LPA and eLAI raster processing\n @ {}'
350
- .format(time.strftime("%d %b %Y %H:%M:%S", time.localtime())))
351
-
352
- r = robjects.r
353
- utils = importr('utils')
354
- base = importr('base')
355
- utils.chooseCRANmirror(ind=12) # select the 12th mirror in the list: Canada
356
- print("Checking R packages ...")
357
-
358
- CRANpacknames = ['lidR', 'rgrass', 'rlas', 'future', 'terra', 'na.tools', 'sf', 'sp'] # ,'fasterRaster']
359
- CRANnames_to_install = [x for x in CRANpacknames if not robjects.packages.isinstalled(x)]
360
- need_fasterRaster = False
361
- if len(CRANnames_to_install) > 0:
362
- if not 'fasterRaster' in CRANnames_to_install:
363
- utils.install_packages(StrVector(CRANnames_to_install))
364
- need_fasterRaster = False
365
- else:
366
- CRANnames_to_install.remove('fasterRaster')
367
- need_fasterRaster = True
368
- if len(CRANnames_to_install) > 0:
369
- utils.install_packages(StrVector(CRANnames_to_install))
370
-
371
- # if need_fasterRaster:
372
- # devtools=importr('devtools')
373
- # devtools.install_github("adamlilith/fasterRaster", dependencies=True)
374
-
375
- del CRANpacknames, CRANnames_to_install
376
-
377
- in_args, in_verbose = check_arguments()
378
- # loading R packages
379
- # utils = importr('utils')
380
- # base = importr('base')
381
- print("Loading R packages ...")
382
- na = importr('na.tools')
383
- terra = importr('terra')
384
- lidR = importr('lidR')
385
- sf = importr('sf')
386
- sp = importr('sp')
387
- future = importr('future')
388
-
389
- print("Checking input parameters ...")
390
-
391
- aoi_shapefile = in_args.input['in_polygon_file']
392
- in_las_folder = in_args.input['in_las_folder']
393
- cut_ht = float(in_args.input['cut_ht'])
394
- radius_fr_CHM = in_args.input['radius_fr_CHM']
395
- focal_radius = float(in_args.input['focal_radius'])
396
- pulse_density = int(in_args.input['pulse_density'])
397
- cell_size = float(in_args.input['cell_size'])
398
- mean_scanning_angle = float(in_args.input['mean_scanning_angle'])
399
- out_folder = in_args.input['out_folder']
400
-
401
- # if optional shapefile is empty, then do nothing, else verify shapefile
402
- if not aoi_shapefile == "":
403
- if not os.path.exists(os.path.dirname(aoi_shapefile)):
404
- print("Can't locate the input polygon folder. Please check.")
405
- exit()
406
- else:
407
- if not isinstance(geopandas.GeoDataFrame.from_file(aoi_shapefile), geopandas.GeoDataFrame):
408
- print("Error input file: Please check effective LiDAR data extend shapefile")
409
- exit()
410
- # check existence of input las/laz folder
411
- if not os.path.exists(in_las_folder):
412
- print("Error! Cannot locate LAS/LAZ folder, please check.")
413
- exit()
414
- else:
415
- found = False
416
- for files in os.listdir(in_las_folder):
417
- if files.endswith(".las") or files.endswith(".laz"):
418
- found = True
419
- break
420
- if not found:
421
- print("Error! Cannot locate input LAS file(s), please check!")
422
- exit()
423
-
424
- # if doing focal radius divided from point cloud CHM
425
- if radius_fr_CHM == True:
426
- pass
427
- # do nothing for now
428
- else:
429
- # check manual input for radius, check input
430
- if not isinstance(focal_radius, float) or focal_radius <= 0.0:
431
- print("Invalid search radius!!Default radius will be adopted (10m).")
432
- in_args.input['focal_radius'] = 10.0
433
- else:
434
- in_args.input['focal_radius'] = focal_radius
435
- # check manual input for cell size and pulse density
436
- if not isinstance(cell_size, float) or cell_size <= 0.00:
437
- if not isinstance(pulse_density, int) or pulse_density <= 0.00:
438
- print("Invalid cell size and average pulse density provided.\n"
439
- "Cell size will be calulated based on aveage point density.")
440
- in_args.input['cell_size'] = 0.0
441
- in_args.input['pulse_density'] = 0
442
- else:
443
- # mean_pd = (((math.pow(3 / pulse_density, 1 / 2)) + (math.pow(5 / pulse_density, 1 / 2))) / 2)
444
- mean_pd = math.pow(3 / pulse_density, 1 / 2)
445
- # mean_pd = math.pow(5 / pulse_density, 1 / 2)
446
- in_args.input['cell_size'] = round(0.05 * round(mean_pd / 0.05), 2)
447
- in_args.input['pulse_density'] = pulse_density
448
- else:
449
- in_args.input['cell_size'] = (cell_size)
450
- in_args.input['pulse_density'] = pulse_density
451
-
452
- # Check manual input for cutt off height
453
- if not isinstance(cut_ht, float) and cut_ht > 0.0:
454
- print("Invalid cut off height!! Default cut off height will be adopted (1m).")
455
- in_args.input["cut_ht"] = 1.0
456
-
457
- if not isinstance(mean_scanning_angle, float) and mean_scanning_angle > 0.00:
458
- print("Invalid sensor scanning angle.\n Default sensor scanning angle will size be adopted (30 degree).")
459
- in_args.input['mean_scanning_angle'] = 30.0
460
- else:
461
- in_args.input['mean_scanning_angle'] = mean_scanning_angle
462
-
463
- print("Checking input parameters ... Done")
464
-
465
- pd_raster(print, **in_args.input, processes=int(in_args.processes), verbose=in_verbose)
466
- print('Task is done in {} seconds)'.format(round(time.time() - start_time, 5)))
@@ -1,56 +0,0 @@
1
- import os
2
- import time
3
-
4
- from beratools.tools.common import *
5
- from beratools.tools.r_interface import *
6
-
7
- def normalized_lidar(callback, in_las_folder, out_folder, style, processes, verbose):
8
- rprocesses = r_processes(processes)
9
-
10
- # assign R script file to local variable
11
- Beratools_R_script = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'Beratools_r_script.r')
12
- # Defining the R script and loading the instance in Python
13
- r['source'](Beratools_R_script)
14
- # Loading the function defined in R script.
15
- if style == 'tin':
16
- r_normalized_lidar = robjects.globalenv['normalized_lidar_knnidw']
17
- elif style == 'knnidw':
18
- r_normalized_lidar = robjects.globalenv['normalized_lidar_tin']
19
- else:
20
- r_normalized_lidar = robjects.globalenv['normalized_lidar_kriging']
21
-
22
- # Invoking the R function
23
- r_normalized_lidar(in_las_folder, out_folder, rprocesses)
24
-
25
-
26
- if __name__ == '__main__':
27
- start_time = time.time()
28
- print('Normalize Lidar data processing\n @ {}'
29
- .format(time.strftime("%a, %d %b %Y %H:%M:%S", time.localtime())))
30
-
31
- packages = ['lidR', 'rgrass', 'rlas', 'future', 'terra', 'sp']
32
- check_r_packages_installation(packages)
33
-
34
- print("Checking input parameters....")
35
- in_args, in_verbose = check_arguments()
36
-
37
- if in_args.input["style"] in ["tin", "knnidw", "kriging"]:
38
- style = in_args.input["style"]
39
- else:
40
- print("Warning! invalid alogrithm, default algorthim will be used.")
41
- in_args.input["style"] = "tin"
42
-
43
- in_las_folder = in_args.input["in_las_folder"]
44
- out_folder = in_args.input["out_folder"]
45
- check_las_files_existence(in_las_folder)
46
-
47
- if not os.path.exists(out_folder):
48
- print("Warning! Cannot locate output folder, It will be created.")
49
- os.makedirs(out_folder)
50
-
51
- print("Checking input parameters....Done")
52
-
53
- normalized_lidar(print, **in_args.input, processes=int(in_args.processes), verbose=in_verbose)
54
-
55
- print('Normalize Lidar data processing is done in {} seconds)'
56
- .format(round(time.time() - start_time, 5)))