From 7ee3fc498b92dc75609928c6469d1a0a9f4f8f93 Mon Sep 17 00:00:00 2001 From: Neuhauser Michael Date: Mon, 2 Oct 2023 10:02:11 +0200 Subject: [PATCH 1/5] implemented the gen_list --- flow_class.py | 2 +- flow_core.py | 118 +++++++++++++++++++++++++++++++------------------- main.py | 2 +- 3 files changed, 75 insertions(+), 47 deletions(-) diff --git a/flow_class.py b/flow_class.py index 0a74e4c..075b0be 100644 --- a/flow_class.py +++ b/flow_class.py @@ -209,4 +209,4 @@ def calc_distribution(self): row_local, col_local = np.where(self.dist > threshold) - return self.rowindex - 1 + row_local, self.colindex - 1 + col_local, self.dist[row_local, col_local], self.z_delta_neighbour[row_local, col_local] + return list(self.rowindex - 1 + row_local), list(self.colindex - 1 + col_local), list(self.dist[row_local, col_local]), list(self.z_delta_neighbour[row_local, col_local]) diff --git a/flow_core.py b/flow_core.py index 4a3951a..a328cc7 100644 --- a/flow_core.py +++ b/flow_core.py @@ -256,12 +256,11 @@ def calculation_effect(optTuple): z_delta_sum = np.zeros_like(dem, dtype=np.float32) flux_array = np.zeros_like(dem, dtype=np.float32) count_array = np.zeros_like(dem, dtype=np.int32) - #backcalc = np.zeros_like(dem, dtype=np.int32) fp_travelangle_array = np.zeros_like(dem, dtype=np.float32) # fp = Flow Path sl_travelangle_array = np.ones_like(dem, dtype=np.float32) * 90 # sl = Straight Line # Core - start = datetime.now().replace(microsecond=0) + start = datetime.now() row_list, col_list = get_start_idx(dem, release) startcell_idx = 0 @@ -270,8 +269,8 @@ def calculation_effect(optTuple): sys.stdout.write('\r' "Calculating Startcell: " + str(startcell_idx + 1) + " of " + str(len(row_list)) + " = " + str( round((startcell_idx + 1) / len(row_list) * 100, 2)) + "%" '\r') sys.stdout.flush() - - cell_list = [] + # init lists + row_idx = row_list[startcell_idx] col_idx = col_list[startcell_idx] dem_ng = dem[row_idx - 1:row_idx + 2, col_idx - 1:col_idx + 2] # neighbourhood DEM @@ -283,51 +282,80 @@ def calculation_effect(optTuple): alpha, exp, flux_threshold, max_z_delta, True) # If this is a startcell just give a Bool to startcell otherwise the object startcell - cell_list.append(startcell) - - for idx, cell in enumerate(cell_list): - row, col, flux, z_delta = cell.calc_distribution() - - if len(flux) > 0: - z_delta, flux, row, col = list(zip(*sorted(zip(z_delta, flux, row, col), reverse=False))) # reverse = True == descending - - for i in range(idx, len(cell_list)): # Check if Cell already exists - k = 0 - while k < len(row): - if row[k] == cell_list[i].rowindex and col[k] == cell_list[i].colindex: - cell_list[i].add_os(flux[k]) - cell_list[i].add_parent(cell) - if z_delta[k] > cell_list[i].z_delta: - cell_list[i].z_delta = z_delta[k] + cell_list = [startcell] + gen_list = [cell_list] + child_list = [] - row = np.delete(row, k) - col = np.delete(col, k) - flux = np.delete(flux, k) - z_delta = np.delete(z_delta, k) - else: - k += 1 - - for k in range(len(row)): - dem_ng = dem[row[k] - 1:row[k] + 2, col[k] - 1:col[k] + 2] # neighbourhood DEM - if (nodata in dem_ng) or np.size(dem_ng) < 9: - continue - cell_list.append( - Cell(row[k], col[k], dem_ng, cellsize, flux[k], z_delta[k], cell, alpha, exp, flux_threshold, max_z_delta, startcell)) - - for cell in cell_list: - z_delta_array[cell.rowindex, cell.colindex] = max(z_delta_array[cell.rowindex, cell.colindex], cell.z_delta) - flux_array[cell.rowindex, cell.colindex] = max(flux_array[cell.rowindex, cell.colindex], - cell.flux) - count_array[cell.rowindex, cell.colindex] += 1 - z_delta_sum[cell.rowindex, cell.colindex] += cell.z_delta - fp_travelangle_array[cell.rowindex, cell.colindex] = max(fp_travelangle_array[cell.rowindex, cell.colindex], - cell.max_gamma) - sl_travelangle_array[cell.rowindex, cell.colindex] = max(sl_travelangle_array[cell.rowindex, cell.colindex], - cell.sl_gamma) + for cell_list in gen_list: + for cell in cell_list: + + row, col, flux, z_delta = cell.calc_distribution() + + if len(flux) > 0: + z_delta, flux, row, col = list(zip(*sorted(zip(z_delta, flux, row, col), reverse=False))) # reverse = True == descending + + for i in range(len(cell_list)): # Check if Cell already exists + k = 0 + while k < len(row): + if row[k] == cell_list[i].rowindex and col[k] == cell_list[i].colindex: + cell_list[i].add_os(flux[k]) + cell_list[i].add_parent(cell) + if z_delta[k] > cell_list[i].z_delta: + cell_list[i].z_delta = z_delta[k] + + row = np.delete(row, k) + col = np.delete(col, k) + flux = np.delete(flux, k) + z_delta = np.delete(z_delta, k) + else: + k += 1 + + for i in range(len(child_list)): # Check if Cell already exists + k = 0 + while k < len(row): + if row[k] == child_list[i].rowindex and col[k] == child_list[i].colindex: + child_list[i].add_os(flux[k]) + child_list[i].add_parent(cell) + if z_delta[k] > child_list[i].z_delta: + child_list[i].z_delta = z_delta[k] + + row = np.delete(row, k) + col = np.delete(col, k) + flux = np.delete(flux, k) + z_delta = np.delete(z_delta, k) + else: + k += 1 + + for k in range(len(row)): + dem_ng = dem[row[k] - 1:row[k] + 2, col[k] - 1:col[k] + 2] # neighbourhood DEM + if (nodata in dem_ng) or np.size(dem_ng) < 9: + continue + child_list.append( + Cell(row[k], col[k], dem_ng, cellsize, flux[k], z_delta[k], cell, alpha, exp, flux_threshold, max_z_delta, startcell)) + #print(len(child_list)) + if len(child_list) > 0: + cell_list = child_list + gen_list.append(cell_list) + child_list = [] + #print(len(gen_list)) + + print("Saving arrays") + for cell_list in gen_list: + for cell in cell_list: + z_delta_array[cell.rowindex, cell.colindex] = max(z_delta_array[cell.rowindex, cell.colindex], cell.z_delta) + flux_array[cell.rowindex, cell.colindex] = max(flux_array[cell.rowindex, cell.colindex], + cell.flux) + count_array[cell.rowindex, cell.colindex] += 1 + z_delta_sum[cell.rowindex, cell.colindex] += cell.z_delta + fp_travelangle_array[cell.rowindex, cell.colindex] = max(fp_travelangle_array[cell.rowindex, cell.colindex], + cell.max_gamma) + sl_travelangle_array[cell.rowindex, cell.colindex] = max(sl_travelangle_array[cell.rowindex, cell.colindex], + cell.sl_gamma) startcell_idx += 1 # Save Calculated tiles + print("Saving Tiles...") np.save(temp_dir + "./res_z_delta_{}_{}".format(optTuple[0], optTuple[1]), z_delta_array) np.save(temp_dir + "./res_z_delta_sum_{}_{}".format(optTuple[0], optTuple[1]), z_delta_sum) np.save(temp_dir + "./res_flux_{}_{}".format(optTuple[0], optTuple[1]), flux_array) @@ -338,6 +366,6 @@ def calculation_effect(optTuple): logging.info("finished calculation {}_{}".format(optTuple[0], optTuple[1])) #ToDo! print("Finished calculation {}_{}".format(optTuple[0], optTuple[1])) - end = datetime.now().replace(microsecond=0) + end = datetime.now() print('\n Time needed: ' + str(end - start)) #return z_delta_array, flux_array, count_array, z_delta_sum, backcalc, fp_travelangle_array, sl_travelangle_array diff --git a/main.py b/main.py index 86a4b9e..5b0ae54 100755 --- a/main.py +++ b/main.py @@ -626,5 +626,5 @@ def main(args, kwargs): main(args, kwargs) -# example dam: python3 main.py 25 8 ./examples/dam/ ./examples/dam/dam_010m_standard_cr100_sw250_f2500.20.6_n0.asc ./examples/dam/release_dam.tif +# example dam: python main.py 25 8 ./examples/dam/ ./examples/dam/dam_010m_standard_cr100_sw250_f2500.20.6_n0.asc ./examples/dam/release_dam.tif # example dam: python3 main.py 25 8 ./examples/dam/ ./examples/dam/dam_010m_standard_cr100_sw250_f2500.20.6_n0.asc ./examples/dam/release_dam.tif infra=./examples/dam/infra.tif flux=0.0003 max_z=270 From 1719e35303562fdfc1393f3ee60f2f13b007c87a Mon Sep 17 00:00:00 2001 From: Neuhauser Michael Date: Mon, 2 Oct 2023 10:33:38 +0200 Subject: [PATCH 2/5] changed core functions for deleting element in list to pop, saving 1 second on dam example --- flow_core.py | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/flow_core.py b/flow_core.py index a328cc7..dd75f9a 100644 --- a/flow_core.py +++ b/flow_core.py @@ -291,9 +291,13 @@ def calculation_effect(optTuple): row, col, flux, z_delta = cell.calc_distribution() - if len(flux) > 0: - z_delta, flux, row, col = list(zip(*sorted(zip(z_delta, flux, row, col), reverse=False))) # reverse = True == descending - + if len(row) > 1: + z_delta, flux, row, col = zip(*sorted(zip(z_delta, flux, row, col), reverse=False)) # reverse = True == descending + row = list(row) + col = list(col) + flux = list(flux) + z_delta = list(z_delta) + for i in range(len(cell_list)): # Check if Cell already exists k = 0 while k < len(row): @@ -303,10 +307,10 @@ def calculation_effect(optTuple): if z_delta[k] > cell_list[i].z_delta: cell_list[i].z_delta = z_delta[k] - row = np.delete(row, k) - col = np.delete(col, k) - flux = np.delete(flux, k) - z_delta = np.delete(z_delta, k) + row.pop(k) + col.pop(k) + flux.pop(k) + z_delta.pop(k) else: k += 1 @@ -319,10 +323,10 @@ def calculation_effect(optTuple): if z_delta[k] > child_list[i].z_delta: child_list[i].z_delta = z_delta[k] - row = np.delete(row, k) - col = np.delete(col, k) - flux = np.delete(flux, k) - z_delta = np.delete(z_delta, k) + row.pop(k) + col.pop(k) + flux.pop(k) + z_delta.pop(k) else: k += 1 From cccaee5e6df25b653fa049d6479b307c088603bd Mon Sep 17 00:00:00 2001 From: Neuhauser Michael Date: Mon, 2 Oct 2023 12:09:41 +0200 Subject: [PATCH 3/5] erased mass distribution, big bug, works like charm --- flow_class.py | 13 ------------- flow_core.py | 11 +++++------ 2 files changed, 5 insertions(+), 19 deletions(-) diff --git a/flow_class.py b/flow_class.py index 075b0be..198a069 100644 --- a/flow_class.py +++ b/flow_class.py @@ -185,7 +185,6 @@ def calc_distribution(self): self.calc_persistence() self.persistence *= self.no_flow self.calc_tanbeta() - #print(self.persistence) if not self.is_start: self.calc_fp_travelangle() @@ -194,18 +193,6 @@ def calc_distribution(self): threshold = self.flux_threshold if np.sum(self.r_t) > 0: self.dist = (self.persistence * self.r_t) / np.sum(self.persistence * self.r_t) * self.flux - # This lines handle if a distribution to a neighbour cell is lower then the threshold, so we donĀ“t lose - # flux. - # The flux of this cells will then spread equally to all neighbour cells - count = ((0 < self.dist) & (self.dist < threshold)).sum() - mass_to_distribute = np.sum(self.dist[self.dist < threshold]) - '''Checking if flux is distributed to a field that isn't taking in account, when then distribute it equally to - the other fields''' - if mass_to_distribute > 0 and count > 0: - self.dist[self.dist > threshold] += mass_to_distribute / count - self.dist[self.dist < threshold] = 0 - if np.sum(self.dist) < self.flux and count > 0: - self.dist[self.dist > threshold] += (self.flux - np.sum(self.dist))/count row_local, col_local = np.where(self.dist > threshold) diff --git a/flow_core.py b/flow_core.py index dd75f9a..92b8e32 100644 --- a/flow_core.py +++ b/flow_core.py @@ -287,8 +287,9 @@ def calculation_effect(optTuple): child_list = [] for cell_list in gen_list: + mass = 0 for cell in cell_list: - + mass += cell.flux row, col, flux, z_delta = cell.calc_distribution() if len(row) > 1: @@ -336,14 +337,12 @@ def calculation_effect(optTuple): continue child_list.append( Cell(row[k], col[k], dem_ng, cellsize, flux[k], z_delta[k], cell, alpha, exp, flux_threshold, max_z_delta, startcell)) - #print(len(child_list)) + if len(child_list) > 0: cell_list = child_list gen_list.append(cell_list) child_list = [] - #print(len(gen_list)) - - print("Saving arrays") + for cell_list in gen_list: for cell in cell_list: z_delta_array[cell.rowindex, cell.colindex] = max(z_delta_array[cell.rowindex, cell.colindex], cell.z_delta) @@ -359,7 +358,7 @@ def calculation_effect(optTuple): startcell_idx += 1 # Save Calculated tiles - print("Saving Tiles...") + #print("Saving Tiles...") np.save(temp_dir + "./res_z_delta_{}_{}".format(optTuple[0], optTuple[1]), z_delta_array) np.save(temp_dir + "./res_z_delta_sum_{}_{}".format(optTuple[0], optTuple[1]), z_delta_sum) np.save(temp_dir + "./res_flux_{}_{}".format(optTuple[0], optTuple[1]), flux_array) From 734b16a072030668ac8ee2f6620a78859ba05dea Mon Sep 17 00:00:00 2001 From: Neuhauser Michael Date: Mon, 2 Oct 2023 14:16:32 +0200 Subject: [PATCH 4/5] changed flow_core, only one calculation function that checks if infra is there or not --- flow_core.py | 182 ++++++++++----------------------------------------- main.py | 23 ++----- 2 files changed, 41 insertions(+), 164 deletions(-) diff --git a/flow_core.py b/flow_core.py index 92b8e32..2f120fc 100644 --- a/flow_core.py +++ b/flow_core.py @@ -85,7 +85,7 @@ def back_calculation(back_cell): #end = time.time() #print('\n Backcalculation needed: ' + str(end - start) + ' seconds') return back_list - + def calculation(optTuple): """This is the core function where all the data handling and calculation is @@ -93,157 +93,27 @@ def calculation(optTuple): Input parameters: dem The digital elevation model - header The header of the elevation model - forest The forest layer - process Which process to calculate (Avalanche, Rockfall, SoilSlides) release The list of release arrays - alpha - exp - flux_threshold - max_z_delta + infra Infrastrucutre array [0 = NoInfra, 1 or greater = Infrastructure] Output parameters: - z_delta Array like DEM with the max. kinetic Energy Height for every + z_delta Array like DEM with the max. Energy Line Height for every pixel flux_array Array with max. concentration factor saved count_array Array with the number of hits for every pixel - elh_sum Array with the sum of Energy Line Height - back_calc Array with back calculation, still to do!!! - """ - temp_dir = optTuple[8] - - dem = np.load(temp_dir + "dem_{}_{}.npy".format(optTuple[0], optTuple[1])) - release = np.load(temp_dir + "init_{}_{}.npy".format(optTuple[0], optTuple[1])) - infra = np.load(temp_dir + "infra_{}_{}.npy".format(optTuple[0], optTuple[1])) - - alpha = float(optTuple[2]) - exp = float(optTuple[3]) - cellsize = float(optTuple[4]) - nodata = float(optTuple[5]) - flux_threshold = float(optTuple[6]) - max_z_delta = float(optTuple[7]) - - z_delta_array = np.zeros_like(dem, dtype=np.float32) - z_delta_sum = np.zeros_like(dem, dtype=np.float32) - flux_array = np.zeros_like(dem, dtype=np.float32) - count_array = np.zeros_like(dem, dtype=np.int32) - backcalc = np.zeros_like(dem, dtype=np.int32) - fp_travelangle_array = np.zeros_like(dem, dtype=np.float32) # fp = Flow Path - sl_travelangle_array = np.zeros_like(dem, dtype=np.float32) * 90 # sl = Straight Line - - back_list = [] - - # Core - start = datetime.now().replace(microsecond=0) - row_list, col_list = get_start_idx(dem, release) - - startcell_idx = 0 - while startcell_idx < len(row_list): - - sys.stdout.write('\r' "Calculating Startcell: " + str(startcell_idx + 1) + " of " + str(len(row_list)) + " = " + str( - round((startcell_idx + 1) / len(row_list) * 100, 2)) + "%" '\r') - sys.stdout.flush() - - cell_list = [] - row_idx = row_list[startcell_idx] - col_idx = col_list[startcell_idx] - dem_ng = dem[row_idx - 1:row_idx + 2, col_idx - 1:col_idx + 2] # neighbourhood DEM - if (nodata in dem_ng) or np.size(dem_ng) < 9: - startcell_idx += 1 - continue - - startcell = Cell(row_idx, col_idx, dem_ng, cellsize, 1, 0, None, - alpha, exp, flux_threshold, max_z_delta, startcell=True) - # If this is a startcell just give a Bool to startcell otherwise the object startcell - - cell_list.append(startcell) - - for idx, cell in enumerate(cell_list): - row, col, flux, z_delta = cell.calc_distribution() - - if len(flux) > 0: - # mass, row, col = list(zip(*sorted(zip( mass, row, col), reverse=False))) - - z_delta, flux, row, col = list(zip(*sorted(zip(z_delta, flux, row, col), reverse=False))) - # Sort this lists by elh, to start with the highest cell - - for i in range(idx, len(cell_list)): # Check if Cell already exists - k = 0 - while k < len(row): - if row[k] == cell_list[i].rowindex and col[k] == cell_list[i].colindex: - cell_list[i].add_os(flux[k]) - cell_list[i].add_parent(cell) - if z_delta[k] > cell_list[i].z_delta: - cell_list[i].z_delta = z_delta[k] - row = np.delete(row, k) - col = np.delete(col, k) - flux = np.delete(flux, k) - z_delta = np.delete(z_delta, k) - else: - k += 1 - - for k in range(len(row)): - dem_ng = dem[row[k] - 1:row[k] + 2, col[k] - 1:col[k] + 2] # neighbourhood DEM - if (nodata in dem_ng) or np.size(dem_ng) < 9: - continue - cell_list.append( - Cell(row[k], col[k], dem_ng, cellsize, flux[k], z_delta[k], cell, alpha, exp, flux_threshold, max_z_delta, startcell)) - - z_delta_array[cell.rowindex, cell.colindex] = max(z_delta_array[cell.rowindex, cell.colindex], cell.z_delta) - flux_array[cell.rowindex, cell.colindex] = max(flux_array[cell.rowindex, cell.colindex], cell.flux) - count_array[cell.rowindex, cell.colindex] += int(1) - z_delta_sum[cell.rowindex, cell.colindex] += cell.z_delta - fp_travelangle_array[cell.rowindex, cell.colindex] = max(fp_travelangle_array[cell.rowindex, cell.colindex], cell.max_gamma) - sl_travelangle_array[cell.rowindex, cell.colindex] = max(sl_travelangle_array[cell.rowindex, cell.colindex], cell.sl_gamma) - - #Backcalculation - if infra[cell.rowindex, cell.colindex] > 0: - #backlist = [] - back_list = back_calculation(cell) - - for back_cell in back_list: - backcalc[back_cell.rowindex, back_cell.colindex] = max(backcalc[back_cell.rowindex, back_cell.colindex], - infra[cell.rowindex, cell.colindex]) - release[z_delta_array > 0] = 0 - # Check if i hit a release Cell, if so set it to zero and get again the indexes of release cells - row_list, col_list = get_start_idx(dem, release) - startcell_idx += 1 - end = datetime.now().replace(microsecond=0) - - # Save Calculated tiles - np.save(temp_dir + "./res_z_delta_{}_{}".format(optTuple[0], optTuple[1]), z_delta_array) - np.save(temp_dir + "./res_z_delta_sum_{}_{}".format(optTuple[0], optTuple[1]), z_delta_sum) - np.save(temp_dir + "./res_flux_{}_{}".format(optTuple[0], optTuple[1]), flux_array) - np.save(temp_dir + "./res_count_{}_{}".format(optTuple[0], optTuple[1]), count_array) - np.save(temp_dir + "./res_fp_{}_{}".format(optTuple[0], optTuple[1]), fp_travelangle_array) - np.save(temp_dir + "./res_sl_{}_{}".format(optTuple[0], optTuple[1]), sl_travelangle_array) - np.save(temp_dir + "./res_backcalc_{}_{}".format(optTuple[0], optTuple[1]), backcalc) - - print('\n Time needed: ' + str(end - start)) - print("Finished calculation {}_{}".format(optTuple[0], optTuple[1])) - - -def calculation_effect(optTuple): - """This is the core function where all the data handling and calculation is - done. - - Input parameters: - dem The digital elevation model - release The list of release arrays - - Output parameters: - z_delta Array like DEM with the max. Energy Line Height for every - pixel - flux_array Array with max. concentration factor saved - count_array Array with the number of hits for every pixel - z_delta_sum Array with the sum of Energy Line Height + z_delta_sum Array with the sum of Energy Line Height back_calc Array with back calculation, still to do!!! + fp_travelangle ... + sl_travelangle ... """ temp_dir = optTuple[8] + infra_bool = optTuple[9] dem = np.load(temp_dir + "dem_{}_{}.npy".format(optTuple[0], optTuple[1])) release = np.load(temp_dir + "init_{}_{}.npy".format(optTuple[0], optTuple[1])) + if infra_bool: + infra = np.load(temp_dir + "infra_{}_{}.npy".format(optTuple[0], optTuple[1])) alpha = float(optTuple[2]) exp = float(optTuple[3]) @@ -258,7 +128,11 @@ def calculation_effect(optTuple): count_array = np.zeros_like(dem, dtype=np.int32) fp_travelangle_array = np.zeros_like(dem, dtype=np.float32) # fp = Flow Path sl_travelangle_array = np.ones_like(dem, dtype=np.float32) * 90 # sl = Straight Line - + + if infra_bool: + backcalc = np.zeros_like(dem, dtype=np.int32) + back_list = [] + # Core start = datetime.now() row_list, col_list = get_start_idx(dem, release) @@ -269,7 +143,6 @@ def calculation_effect(optTuple): sys.stdout.write('\r' "Calculating Startcell: " + str(startcell_idx + 1) + " of " + str(len(row_list)) + " = " + str( round((startcell_idx + 1) / len(row_list) * 100, 2)) + "%" '\r') sys.stdout.flush() - # init lists row_idx = row_list[startcell_idx] col_idx = col_list[startcell_idx] @@ -287,9 +160,7 @@ def calculation_effect(optTuple): child_list = [] for cell_list in gen_list: - mass = 0 for cell in cell_list: - mass += cell.flux row, col, flux, z_delta = cell.calc_distribution() if len(row) > 1: @@ -338,11 +209,11 @@ def calculation_effect(optTuple): child_list.append( Cell(row[k], col[k], dem_ng, cellsize, flux[k], z_delta[k], cell, alpha, exp, flux_threshold, max_z_delta, startcell)) - if len(child_list) > 0: + if len(child_list) > 0: cell_list = child_list gen_list.append(cell_list) child_list = [] - + for cell_list in gen_list: for cell in cell_list: z_delta_array[cell.rowindex, cell.colindex] = max(z_delta_array[cell.rowindex, cell.colindex], cell.z_delta) @@ -355,20 +226,35 @@ def calculation_effect(optTuple): sl_travelangle_array[cell.rowindex, cell.colindex] = max(sl_travelangle_array[cell.rowindex, cell.colindex], cell.sl_gamma) - startcell_idx += 1 + #Backcalculation + if infra_bool: + if infra[cell.rowindex, cell.colindex] > 0: + #backlist = [] + back_list = back_calculation(cell) + for back_cell in back_list: + backcalc[back_cell.rowindex, back_cell.colindex] = max(backcalc[back_cell.rowindex, back_cell.colindex], + infra[cell.rowindex, cell.colindex]) + + if infra_bool: + release[z_delta_array > 0] = 0 + """ Check if i hit a release Cell, if so set it to zero and get + again the indexes of release cells""" + row_list, col_list = get_start_idx(dem, release) + startcell_idx += 1 + # Save Calculated tiles - #print("Saving Tiles...") np.save(temp_dir + "./res_z_delta_{}_{}".format(optTuple[0], optTuple[1]), z_delta_array) np.save(temp_dir + "./res_z_delta_sum_{}_{}".format(optTuple[0], optTuple[1]), z_delta_sum) np.save(temp_dir + "./res_flux_{}_{}".format(optTuple[0], optTuple[1]), flux_array) np.save(temp_dir + "./res_count_{}_{}".format(optTuple[0], optTuple[1]), count_array) np.save(temp_dir + "./res_fp_{}_{}".format(optTuple[0], optTuple[1]), fp_travelangle_array) np.save(temp_dir + "./res_sl_{}_{}".format(optTuple[0], optTuple[1]), sl_travelangle_array) + if infra_bool: + np.save(temp_dir + "./res_backcalc_{}_{}".format(optTuple[0], optTuple[1]), backcalc) logging.info("finished calculation {}_{}".format(optTuple[0], optTuple[1])) #ToDo! print("Finished calculation {}_{}".format(optTuple[0], optTuple[1])) end = datetime.now() print('\n Time needed: ' + str(end - start)) - #return z_delta_array, flux_array, count_array, z_delta_sum, backcalc, fp_travelangle_array, sl_travelangle_array diff --git a/main.py b/main.py index 5b0ae54..0d0979a 100755 --- a/main.py +++ b/main.py @@ -358,7 +358,8 @@ def calculation(self): for i in range(nTiles[0]+1): for j in range(nTiles[1]+1): - optList.append((i, j, alpha, exp, cellsize, nodata, flux_threshold, max_z, temp_dir)) + optList.append((i, j, alpha, exp, cellsize, nodata, + flux_threshold, max_z, temp_dir, self.infra_bool)) # Calculation self.calc_class = Sim.Simulation(optList, self.infra_bool) @@ -410,13 +411,10 @@ def output(self): end = datetime.now().replace(microsecond=0) logging.info('Calculation needed: ' + str(end - self.start) + ' seconds') - # Handle GUI - #self.ui.progressBar.setValue(100) self.set_gui_bool(True) -def main(args, kwargs): - +def main(args, kwargs): alpha = args[0] exp = args[1] @@ -425,19 +423,16 @@ def main(args, kwargs): release_path = args[4] if 'infra' in kwargs: infra_path = kwargs.get('infra') - #print(infra_path) else: infra_path = None if 'flux' in kwargs: flux_threshold = float(kwargs.get('flux')) - #print(flux_threshold) else: flux_threshold = 3 * 10 ** -4 if 'max_z' in kwargs: max_z = kwargs.get('max_z') - #print(max_z) else: max_z = 8848 # Recomendet values: @@ -545,18 +540,14 @@ def main(args, kwargs): for i in range(nTiles[0]+1): for j in range(nTiles[1]+1): - optList.append((i, j, alpha, exp, cellsize, nodata, flux_threshold, max_z, temp_dir)) + optList.append((i, j, alpha, exp, cellsize, nodata, flux_threshold, + max_z, temp_dir, infra_bool)) # Calculation logging.info('Multiprocessing starts, used cores: {}'.format(cpu_count() - 1)) print("{} Processes started and {} calculations to perform.".format(mp.cpu_count() - 1, len(optList))) pool = mp.Pool(mp.cpu_count() - 1) - - if infra_bool: - pool.map(fc.calculation, optList) - else: - pool.map(fc.calculation_effect, optList) - + pool.map(fc.calculation_effect, optList) pool.close() pool.join() @@ -627,4 +618,4 @@ def main(args, kwargs): main(args, kwargs) # example dam: python main.py 25 8 ./examples/dam/ ./examples/dam/dam_010m_standard_cr100_sw250_f2500.20.6_n0.asc ./examples/dam/release_dam.tif -# example dam: python3 main.py 25 8 ./examples/dam/ ./examples/dam/dam_010m_standard_cr100_sw250_f2500.20.6_n0.asc ./examples/dam/release_dam.tif infra=./examples/dam/infra.tif flux=0.0003 max_z=270 +# example dam: python main.py 25 8 ./examples/dam/ ./examples/dam/dam_010m_standard_cr100_sw250_f2500.20.6_n0.asc ./examples/dam/release_dam.tif infra=./examples/dam/infra.tif flux=0.0003 max_z=270 From d7e727d0a1c9d3a27637b1b4211913835dfec587 Mon Sep 17 00:00:00 2001 From: Neuhauser Michael Date: Mon, 2 Oct 2023 14:40:20 +0200 Subject: [PATCH 5/5] splitted gui from main.py --- Simulation.py | 19 +-- flow_core.py | 18 +-- gui.py | 399 ++++++++++++++++++++++++++++++++++++++++++++++++++ main.py | 392 +------------------------------------------------ 4 files changed, 416 insertions(+), 412 deletions(-) create mode 100644 gui.py diff --git a/Simulation.py b/Simulation.py index e3945e4..ab65ea2 100644 --- a/Simulation.py +++ b/Simulation.py @@ -43,20 +43,11 @@ def __init__(self, optList, infra_bool): def run(self): - # This part will is for Calculation of the top release cells and erasing the lower ones - #if __name__ != '__main__': # needed that it runs on windows, but it doesnt!!! if __name__ == main: would it be. - if self.infra_bool: - print("{} Processes started.".format(mp.cpu_count() - 1)) - pool = mp.Pool(mp.cpu_count() - 1) - pool.map(fc.calculation, self.optList) - pool.close() - pool.join() - else: - print("{} Processes started.".format(mp.cpu_count() - 1)) - pool = mp.Pool(mp.cpu_count() - 1) - pool.map(fc.calculation_effect, self.optList) - pool.close() - pool.join() + print("{} Processes started.".format(mp.cpu_count() - 1)) + pool = mp.Pool(mp.cpu_count() - 1) + pool.map(fc.calculation, self.optList) + pool.close() + pool.join() print("Processes finished") self.finished.emit() \ No newline at end of file diff --git a/flow_core.py b/flow_core.py index 2f120fc..2c7679f 100644 --- a/flow_core.py +++ b/flow_core.py @@ -97,12 +97,11 @@ def calculation(optTuple): infra Infrastrucutre array [0 = NoInfra, 1 or greater = Infrastructure] Output parameters: - z_delta Array like DEM with the max. Energy Line Height for every - pixel + z_delta Array like DEM with the max. z_delta for every pixel flux_array Array with max. concentration factor saved count_array Array with the number of hits for every pixel - z_delta_sum Array with the sum of Energy Line Height - back_calc Array with back calculation, still to do!!! + z_delta_sum Array with the sum of z_delta + back_calc Array with back calculation fp_travelangle ... sl_travelangle ... """ @@ -122,6 +121,7 @@ def calculation(optTuple): flux_threshold = float(optTuple[6]) max_z_delta = float(optTuple[7]) + # Init arrays to save results z_delta_array = np.zeros_like(dem, dtype=np.float32) z_delta_sum = np.zeros_like(dem, dtype=np.float32) flux_array = np.zeros_like(dem, dtype=np.float32) @@ -135,7 +135,7 @@ def calculation(optTuple): # Core start = datetime.now() - row_list, col_list = get_start_idx(dem, release) + row_list, col_list = get_start_idx(dem, release) # get idx of release cells startcell_idx = 0 while startcell_idx < len(row_list): @@ -163,14 +163,14 @@ def calculation(optTuple): for cell in cell_list: row, col, flux, z_delta = cell.calc_distribution() - if len(row) > 1: + if len(row) > 1: # if there is more then 1 element in list, sort it by z_delta, lowest -> highest z_delta, flux, row, col = zip(*sorted(zip(z_delta, flux, row, col), reverse=False)) # reverse = True == descending row = list(row) col = list(col) flux = list(flux) z_delta = list(z_delta) - for i in range(len(cell_list)): # Check if Cell already exists + for i in range(len(cell_list)): # Check if Cell already exists in cell_list k = 0 while k < len(row): if row[k] == cell_list[i].rowindex and col[k] == cell_list[i].colindex: @@ -186,7 +186,7 @@ def calculation(optTuple): else: k += 1 - for i in range(len(child_list)): # Check if Cell already exists + for i in range(len(child_list)): # Check if Cell already exists in child_list k = 0 while k < len(row): if row[k] == child_list[i].rowindex and col[k] == child_list[i].colindex: @@ -214,7 +214,7 @@ def calculation(optTuple): gen_list.append(cell_list) child_list = [] - for cell_list in gen_list: + for cell_list in gen_list: # Save results to arrays for cell in cell_list: z_delta_array[cell.rowindex, cell.colindex] = max(z_delta_array[cell.rowindex, cell.colindex], cell.z_delta) flux_array[cell.rowindex, cell.colindex] = max(flux_array[cell.rowindex, cell.colindex], diff --git a/gui.py b/gui.py new file mode 100644 index 0000000..3b23247 --- /dev/null +++ b/gui.py @@ -0,0 +1,399 @@ +# -*- coding: utf-8 -*- +""" +Created on Mon May 7 14:23:00 2018 + + Copyright (C) <2020> + Michael.Neuhauser@bfw.gv.at + + 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 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +""" +# import standard libraries +import os +import sys +import numpy as np +from datetime import datetime +from multiprocessing import cpu_count +import logging +from xml.etree import ElementTree as ET +import pickle + +# Flow-Py Libraries +import raster_io as io +import Simulation as Sim +import split_and_merge as SPAM + +# Libraries for GUI, PyQt5 +from PyQt5.QtCore import QCoreApplication +from PyQt5.QtWidgets import QFileDialog, QMessageBox, QMainWindow, QApplication + +from Flow_GUI import Ui_MainWindow + + +class Flow_Py_EXEC(): + + def __init__(self): + + app = QApplication(sys.argv) + MainWindow = QMainWindow() + self.ui = Ui_MainWindow() + self.ui.setupUi(MainWindow) + + self.directory = os.getcwd() + + self.ui.alpha_Edit.setText('25') + self.ui.exp_Edit.setText('8') + self.ui.flux_Edit.setText('0.0003') + self.ui.z_Edit.setText('8848') + + self.ui.wDir_Button.clicked.connect(self.open_wDir) + self.ui.DEM_Button.clicked.connect(self.open_dhm) + self.ui.Release_Button.clicked.connect(self.open_release) + self.ui.infra_Button.clicked.connect(self.open_infra) + #self.ui.forest_Button.clicked.connect(self.open_forest) + #self.ui.process_Box.currentIndexChanged.connect(self.processChanged) + self.ui.calc_Button.clicked.connect(self.calculation) + self.ui.actionSave.triggered.connect(self.save) + self.ui.actionLoad.triggered.connect(self.load) + self.ui.actionQuit.triggered.connect(self.quit) + + self.calc_class = None + self.prot_for_bool = False + self.infra_bool = False + self.threads_calc = 0 + self.progress_value = 0 + self.cpu_count = 1 + self.thread_list = [] + self.start_list = [] + self.end_list = [] + for i in range(self.cpu_count): + self.thread_list.append(0) + self.start_list.append(0) + self.end_list.append(0) + + # show the constructed window + MainWindow.show() + sys.exit(app.exec_()) + + def set_gui_bool(self, bool): + self.ui.calc_Button.setEnabled(bool) + self.ui.wDir_lineEdit.setEnabled(bool) + self.ui.DEM_lineEdit.setEnabled(bool) + self.ui.release_lineEdit.setEnabled(bool) + self.ui.infra_lineEdit.setEnabled(bool) + + def save(self): + """Save the input paths""" + name = QFileDialog.getSaveFileName(None, 'Save File', + ".xml")[0] + if len(name) != 0: + + root = ET.Element('root') + wdir = ET.SubElement(root, 'wDir') + dhm = ET.SubElement(root, 'DHM') + release = ET.SubElement(root, 'Release') + infra = ET.SubElement(root, 'Infrastructure') + forest = ET.SubElement(root, 'Forest') + + wdir.set('Directory', 'Working') + dhm.set('Directory', 'DHM') + release.set('Directory', 'Release') + infra.set('Directory', 'Infrastructure') + forest.set('Directory', 'Forest') + + wdir.text = self.ui.wDir_lineEdit.text() + dhm.text = self.ui.DEM_lineEdit.text() + release.text = self.ui.release_lineEdit.text() + infra.text = self.ui.infra_lineEdit.text() + #forest.text = self.ui.forest_lineEdit.text() + + tree = ET.ElementTree(root) + tree.write(name) + + def load(self): + xml_file = QFileDialog.getOpenFileNames(None, 'Open xml', + self.directory, + "xml (*.xml);;All Files (*.*)")[0] + + if len(xml_file) != 0: + tree = ET.parse(xml_file[0]) + root = tree.getroot() + + try: + self.ui.wDir_lineEdit.setText(root[0].text) + self.directory = root[0].text + except: + print("No Working Directory Path in File!") + + try: + self.ui.DEM_lineEdit.setText(root[1].text) + except: + print("No DEM Path in File!") + + try: + self.ui.release_lineEdit.setText(root[2].text) + except: + print("No Release Path in File!") + + try: + self.ui.infra_lineEdit.setText(root[3].text) + except: + print("No Infrastructure Path in File!") + + try: + self.ui.forest_lineEdit.setText(root[4].text) + except: + print("No Forest Path in File!") + + def quit(self): + QCoreApplication.quit() + + def open_wDir(self): + """Open the Working Directory, where results are stored""" + directory = QFileDialog.getExistingDirectory(None, 'Open Working Directory', + self.directory, + QFileDialog.ShowDirsOnly) + if len(directory) != 0: + self.directory = directory + self.ui.wDir_lineEdit.setText(self.directory) + + def open_dhm(self): + """Open digital elevation model""" + dem_file = QFileDialog.getOpenFileNames(None, 'Open DEM', + self.directory, + "ascii (*.asc);;tif (*.tif);;All Files (*.*)") + if len(dem_file[0]) != 0: + dem = dem_file[0] + self.ui.DEM_lineEdit.setText(dem[0]) + + def open_release(self): + """Open release layer""" + release_file = QFileDialog.getOpenFileNames(None, 'Open Release', + self.directory, + "ascii (*.asc);;tif (*.tif);;All Files (*.*)") + if len(release_file[0]) != 0: + release = release_file[0] + self.ui.release_lineEdit.setText(release[0]) + + def open_infra(self): + """Open infrastructure layer""" + infra_file = QFileDialog.getOpenFileNames(None, 'Open Infrastructure Layer', + self.directory, + "ascii (*.asc);;tif (*.tif);;All Files (*.*)") + if len(infra_file[0]) != 0: + infra = infra_file[0] + self.ui.infra_lineEdit.setText(infra[0]) + + def update_progressBar(self, float, thread, start, end): + self.thread_list[thread] = float + self.start_list[thread] = start + self.end_list[thread] = end + + self.progress_value = sum(self.thread_list) / len(self.thread_list) + self.progressBar.setValue(self.progress_value) + for i in range(len(self.thread_list)): + sys.stdout.write( + "Thread {}: Startcell {} of {} = {}%"'\n'.format(i + 1, self.start_list[i], self.end_list[i], + self.thread_list[i])) + sys.stdout.flush() + for i in range(len(self.thread_list)): + sys.stdout.write('\x1b[1A' + '\x1b[2K') # Go 1 line up and erase that line + + @staticmethod + def showdialog(path): + msg = QMessageBox() + msg.setIcon(QMessageBox.Critical) + msg.setText("No " + path + " set") + msg.setWindowTitle("Error") + msg.setStandardButtons(QMessageBox.Ok) + msg.exec_() + + def calculation(self): + self.start = datetime.now().replace(microsecond=0) + + # Check if input is ok + if self.ui.wDir_lineEdit.text() == '': + self.showdialog('Working Directory') + return + if self.ui.DEM_lineEdit.text() == '': + self.showdialog('DEM Layer') + return + if self.ui.release_lineEdit.text() == '': + self.showdialog('Release Layer') + return + # Disable all input line Edits and Buttons + self.set_gui_bool(False) + + # Create result directory + time_string = datetime.now().strftime("%Y%m%d_%H%M%S") + try: + os.makedirs(self.ui.wDir_lineEdit.text() + '/res_{}/'.format(time_string)) + self.res_dir = ('/res_{}/'.format(time_string)) + except FileExistsError: + self.res_dir = ('/res_{}/'.format(time_string)) + + directory = self.ui.wDir_lineEdit.text() + try: + os.makedirs(directory + self.res_dir + 'temp/') + temp_dir = (directory + self.res_dir + 'temp/') + except FileExistsError: + temp_dir = (directory + self.res_dir + 'temp/') + + self.temp_dir = temp_dir + # Setup logger + + for handler in logging.root.handlers[:]: + logging.root.removeHandler(handler) + + logging.basicConfig(level=logging.INFO, + format='%(asctime)s %(levelname)-8s %(message)s', + datefmt='%Y-%m-%d %H:%M:%S', + filename=(self.directory + self.res_dir + 'log_{}.txt').format(time_string), + filemode='w') + + # Start of Calculation + logging.info('Start Calculation') + # Read in raster files + try: + dem, header = io.read_raster(self.ui.DEM_lineEdit.text()) + logging.info('DEM File: {}'.format(self.ui.DEM_lineEdit.text())) + except FileNotFoundError: + print("Wrong filepath or filename") + self.set_gui_bool(True) + return + + try: + release, release_header = io.read_raster(self.ui.release_lineEdit.text()) + logging.info('Release File: {}'.format(self.ui.release_lineEdit.text())) + except FileNotFoundError: + print("Wrong filepath or filename") + self.set_gui_bool(True) + return + + # Check if Layers have same size!!! + if header['ncols'] == release_header['ncols'] and header['nrows'] == release_header['nrows']: + print("DEM and Release Layer ok!") + else: + print("Error: Release Layer doesn't match DEM!") + self.set_gui_bool(True) + return + + try: + infra, infra_header = io.read_raster(self.ui.infra_lineEdit.text()) + if header['ncols'] == infra_header['ncols'] and header['nrows'] == infra_header['nrows']: + print("Infra Layer ok!") + self.infra_bool = True + logging.info('Infrastructure File: {}'.format(self.ui.infra_lineEdit.text())) + else: + print("Error: Infra Layer doesn't match DEM!") + self.set_gui_bool(True) + return + except: + infra = np.zeros_like(dem) + + logging.info('Files read in') + + cellsize = header["cellsize"] + nodata = header["noDataValue"] + del dem, release, infra + + tileCOLS = int(15000 / cellsize) + tileROWS = int(15000 / cellsize) + U = int(5000 / cellsize) # 5km overlap + + logging.info("Start Tiling.") + + SPAM.tileRaster(self.ui.DEM_lineEdit.text(), "dem", temp_dir, tileCOLS, tileROWS, U) + SPAM.tileRaster(self.ui.release_lineEdit.text(), "init", temp_dir, tileCOLS, tileROWS, U, isInit=True) + if self.infra_bool: + SPAM.tileRaster(self.ui.infra_lineEdit.text(), "infra", temp_dir, tileCOLS, tileROWS, U) + + nTiles = pickle.load(open(temp_dir + "nTiles", "rb")) + + alpha = self.ui.alpha_Edit.text() + exp = self.ui.exp_Edit.text() + flux_threshold = self.ui.flux_Edit.text() + max_z = self.ui.z_Edit.text() + + logging.info('Alpha Angle: {}'.format(alpha)) + logging.info('Exponent: {}'.format(exp)) + logging.info('Flux Threshold: {}'.format(flux_threshold)) + logging.info('Max Z_delta: {}'.format(max_z)) + logging.info + + optList = [] + # das hier ist die batch-liste, die von mulitprocessing + # abgearbeitet werden muss - sieht so aus: + # [(0,0,alpha,exp,cellsize,-9999.), + # (0,1,alpha,exp,cellsize,-9999.), + # etc.] + + for i in range(nTiles[0]+1): + for j in range(nTiles[1]+1): + optList.append((i, j, alpha, exp, cellsize, nodata, + flux_threshold, max_z, temp_dir, self.infra_bool)) + + # Calculation with multithreading + self.calc_class = Sim.Simulation(optList, self.infra_bool) + self.calc_class.finished.connect(self.thread_finished) + logging.info('Multiprocessing starts, used cores: {}'.format(cpu_count() - 1)) + self.calc_class.start() + + def thread_finished(self): + logging.info('Calculation finished, getting results.') + # Merge calculated tiles + self.z_delta = SPAM.MergeRaster(self.temp_dir, "res_z_delta") + self.flux = SPAM.MergeRaster(self.temp_dir, "res_flux") + self.cell_counts = SPAM.MergeRaster(self.temp_dir, "res_count") + self.z_delta_sum = SPAM.MergeRaster(self.temp_dir, "res_z_delta_sum") + self.fp_ta = SPAM.MergeRaster(self.temp_dir, "res_fp") + self.sl_ta = SPAM.MergeRaster(self.temp_dir, "res_sl") + if self.infra_bool: + self.backcalc = SPAM.MergeRaster(self.temp_dir, "res_backcalc") + self.output() + + def output(self): + # time_string = datetime.now().strftime("%Y%m%d_%H%M%S") + logging.info('Writing Output Files') + io.output_raster(self.ui.DEM_lineEdit.text(), + self.directory + self.res_dir + "flux{}".format(self.ui.outputBox.currentText()), + self.flux) + io.output_raster(self.ui.DEM_lineEdit.text(), + self.directory + self.res_dir + "z_delta{}".format(self.ui.outputBox.currentText()), + self.z_delta) + io.output_raster(self.ui.DEM_lineEdit.text(), + self.directory + self.res_dir + "FP_travel_angle{}".format(self.ui.outputBox.currentText()), + self.fp_ta) + io.output_raster(self.ui.DEM_lineEdit.text(), + self.directory + self.res_dir + "SL_travel_angle{}".format(self.ui.outputBox.currentText()), + self.sl_ta) + if not self.infra_bool: + io.output_raster(self.ui.DEM_lineEdit.text(), + self.directory + self.res_dir + "cell_counts{}".format(self.ui.outputBox.currentText()), + self.cell_counts) + io.output_raster(self.ui.DEM_lineEdit.text(), + self.directory + self.res_dir + "z_delta_sum{}".format(self.ui.outputBox.currentText()), + self.z_delta_sum) + if self.infra_bool: + io.output_raster(self.ui.DEM_lineEdit.text(), + self.directory + self.res_dir + "backcalculation{}".format(self.ui.outputBox.currentText()), + self.backcalc) + + print("Calculation finished") + end = datetime.now().replace(microsecond=0) + logging.info('Calculation needed: ' + str(end - self.start) + ' seconds') + + self.set_gui_bool(True) + +if __name__ == '__main__': + Flow_Py_EXEC() \ No newline at end of file diff --git a/main.py b/main.py index 0d0979a..8236136 100755 --- a/main.py +++ b/main.py @@ -22,396 +22,18 @@ # import standard libraries import os import sys -import psutil import numpy as np from datetime import datetime from multiprocessing import cpu_count import multiprocessing as mp import logging -from xml.etree import ElementTree as ET import pickle # Flow-Py Libraries import raster_io as io -import Simulation as Sim import flow_core as fc import split_and_merge as SPAM - -# Libraries for GUI, PyQt5 -from PyQt5.QtCore import pyqtSlot, QCoreApplication -from PyQt5.QtWidgets import QFileDialog, QMessageBox, QMainWindow, QApplication - -from Flow_GUI import Ui_MainWindow - - -class Flow_Py_EXEC(): - - def __init__(self): - - app = QApplication(sys.argv) - MainWindow = QMainWindow() - self.ui = Ui_MainWindow() - self.ui.setupUi(MainWindow) - - # self.showMaximized() - #self.ui.setWindowTitle("Flow-Py") - #self.ui.setWindowIcon(QIcon('logo.jpg')) - - self.directory = os.getcwd() - - self.ui.alpha_Edit.setText('25') - self.ui.exp_Edit.setText('8') - self.ui.flux_Edit.setText('0.0003') - self.ui.z_Edit.setText('8848') - - self.ui.wDir_Button.clicked.connect(self.open_wDir) - self.ui.DEM_Button.clicked.connect(self.open_dhm) - self.ui.Release_Button.clicked.connect(self.open_release) - self.ui.infra_Button.clicked.connect(self.open_infra) - #self.ui.forest_Button.clicked.connect(self.open_forest) - #self.ui.process_Box.currentIndexChanged.connect(self.processChanged) - self.ui.calc_Button.clicked.connect(self.calculation) - self.ui.actionSave.triggered.connect(self.save) - self.ui.actionLoad.triggered.connect(self.load) - self.ui.actionQuit.triggered.connect(self.quit) - - self.calc_class = None - self.prot_for_bool = False - self.infra_bool = False - self.threads_calc = 0 - self.progress_value = 0 - self.cpu_count = 1 - self.thread_list = [] - self.start_list = [] - self.end_list = [] - for i in range(self.cpu_count): - self.thread_list.append(0) - self.start_list.append(0) - self.end_list.append(0) - - # show the constructed window - MainWindow.show() - sys.exit(app.exec_()) - - def set_gui_bool(self, bool): - self.ui.calc_Button.setEnabled(bool) - self.ui.wDir_lineEdit.setEnabled(bool) - self.ui.DEM_lineEdit.setEnabled(bool) - self.ui.release_lineEdit.setEnabled(bool) - self.ui.infra_lineEdit.setEnabled(bool) - - def save(self): - """Save the input paths""" - name = QFileDialog.getSaveFileName(None, 'Save File', - ".xml")[0] - if len(name) != 0: - - root = ET.Element('root') - wdir = ET.SubElement(root, 'wDir') - dhm = ET.SubElement(root, 'DHM') - release = ET.SubElement(root, 'Release') - infra = ET.SubElement(root, 'Infrastructure') - forest = ET.SubElement(root, 'Forest') - - wdir.set('Directory', 'Working') - dhm.set('Directory', 'DHM') - release.set('Directory', 'Release') - infra.set('Directory', 'Infrastructure') - forest.set('Directory', 'Forest') - - wdir.text = self.ui.wDir_lineEdit.text() - dhm.text = self.ui.DEM_lineEdit.text() - release.text = self.ui.release_lineEdit.text() - infra.text = self.ui.infra_lineEdit.text() - #forest.text = self.ui.forest_lineEdit.text() - - tree = ET.ElementTree(root) - tree.write(name) - - def load(self): - xml_file = QFileDialog.getOpenFileNames(None, 'Open xml', - self.directory, - "xml (*.xml);;All Files (*.*)")[0] - - if len(xml_file) != 0: - tree = ET.parse(xml_file[0]) - root = tree.getroot() - - try: - self.ui.wDir_lineEdit.setText(root[0].text) - self.directory = root[0].text - except: - print("No Working Directory Path in File!") - - try: - self.ui.DEM_lineEdit.setText(root[1].text) - except: - print("No DEM Path in File!") - - try: - self.ui.release_lineEdit.setText(root[2].text) - except: - print("No Release Path in File!") - - try: - self.ui.infra_lineEdit.setText(root[3].text) - except: - print("No Infrastructure Path in File!") - - try: - self.ui.forest_lineEdit.setText(root[4].text) - except: - print("No Forest Path in File!") - - def quit(self): - QCoreApplication.quit() - - def open_wDir(self): - """Open the Working Directory, where results are stored""" - directory = QFileDialog.getExistingDirectory(None, 'Open Working Directory', - self.directory, - QFileDialog.ShowDirsOnly) - if len(directory) != 0: - self.directory = directory - self.ui.wDir_lineEdit.setText(self.directory) - - def open_dhm(self): - """Open digital elevation model""" - dem_file = QFileDialog.getOpenFileNames(None, 'Open DEM', - self.directory, - "ascii (*.asc);;tif (*.tif);;All Files (*.*)") - if len(dem_file[0]) != 0: - dem = dem_file[0] - self.ui.DEM_lineEdit.setText(dem[0]) - - def open_release(self): - """Open release layer""" - release_file = QFileDialog.getOpenFileNames(None, 'Open Release', - self.directory, - "ascii (*.asc);;tif (*.tif);;All Files (*.*)") - if len(release_file[0]) != 0: - release = release_file[0] - self.ui.release_lineEdit.setText(release[0]) - - def open_infra(self): - """Open infrastructure layer""" - infra_file = QFileDialog.getOpenFileNames(None, 'Open Infrastructure Layer', - self.directory, - "ascii (*.asc);;tif (*.tif);;All Files (*.*)") - if len(infra_file[0]) != 0: - infra = infra_file[0] - self.ui.infra_lineEdit.setText(infra[0]) - - def update_progressBar(self, float, thread, start, end): - self.thread_list[thread] = float - self.start_list[thread] = start - self.end_list[thread] = end - - self.progress_value = sum(self.thread_list) / len(self.thread_list) - self.progressBar.setValue(self.progress_value) - for i in range(len(self.thread_list)): - sys.stdout.write( - "Thread {}: Startcell {} of {} = {}%"'\n'.format(i + 1, self.start_list[i], self.end_list[i], - self.thread_list[i])) - sys.stdout.flush() - for i in range(len(self.thread_list)): - sys.stdout.write('\x1b[1A' + '\x1b[2K') # Go 1 line up and erase that line - - @staticmethod - def showdialog(path): - msg = QMessageBox() - msg.setIcon(QMessageBox.Critical) - msg.setText("No " + path + " set") - msg.setWindowTitle("Error") - msg.setStandardButtons(QMessageBox.Ok) - msg.exec_() - - def calculation(self): - self.start = datetime.now().replace(microsecond=0) - - # Check if input is ok - if self.ui.wDir_lineEdit.text() == '': - self.showdialog('Working Directory') - return - if self.ui.DEM_lineEdit.text() == '': - self.showdialog('DEM Layer') - return - if self.ui.release_lineEdit.text() == '': - self.showdialog('Release Layer') - return - # Disable all input line Edits and Buttons - self.set_gui_bool(False) - - # Create result directory - time_string = datetime.now().strftime("%Y%m%d_%H%M%S") - try: - os.makedirs(self.ui.wDir_lineEdit.text() + '/res_{}/'.format(time_string)) - self.res_dir = ('/res_{}/'.format(time_string)) - except FileExistsError: - self.res_dir = ('/res_{}/'.format(time_string)) - - directory = self.ui.wDir_lineEdit.text() - try: - os.makedirs(directory + self.res_dir + 'temp/') - temp_dir = (directory + self.res_dir + 'temp/') - except FileExistsError: - temp_dir = (directory + self.res_dir + 'temp/') - - self.temp_dir = temp_dir - # Setup logger - - for handler in logging.root.handlers[:]: - logging.root.removeHandler(handler) - - logging.basicConfig(level=logging.INFO, - format='%(asctime)s %(levelname)-8s %(message)s', - datefmt='%Y-%m-%d %H:%M:%S', - filename=(self.directory + self.res_dir + 'log_{}.txt').format(time_string), - filemode='w') - - # Start of Calculation - logging.info('Start Calculation') - # Read in raster files - try: - dem, header = io.read_raster(self.ui.DEM_lineEdit.text()) - logging.info('DEM File: {}'.format(self.ui.DEM_lineEdit.text())) - except FileNotFoundError: - print("Wrong filepath or filename") - self.set_gui_bool(True) - return - - try: - release, release_header = io.read_raster(self.ui.release_lineEdit.text()) - logging.info('Release File: {}'.format(self.ui.release_lineEdit.text())) - except FileNotFoundError: - print("Wrong filepath or filename") - self.set_gui_bool(True) - return - - # Check if Layers have same size!!! - if header['ncols'] == release_header['ncols'] and header['nrows'] == release_header['nrows']: - print("DEM and Release Layer ok!") - else: - print("Error: Release Layer doesn't match DEM!") - self.set_gui_bool(True) - return - - try: - infra, infra_header = io.read_raster(self.ui.infra_lineEdit.text()) - if header['ncols'] == infra_header['ncols'] and header['nrows'] == infra_header['nrows']: - print("Infra Layer ok!") - self.infra_bool = True - logging.info('Infrastructure File: {}'.format(self.ui.infra_lineEdit.text())) - else: - print("Error: Infra Layer doesn't match DEM!") - self.set_gui_bool(True) - return - except: - infra = np.zeros_like(dem) - - logging.info('Files read in') - - cellsize = header["cellsize"] - nodata = header["noDataValue"] - del dem, release, infra - - tileCOLS = int(15000 / cellsize) - tileROWS = int(15000 / cellsize) - U = int(5000 / cellsize) # 5km overlap - - logging.info("Start Tiling.") - - SPAM.tileRaster(self.ui.DEM_lineEdit.text(), "dem", temp_dir, tileCOLS, tileROWS, U) - SPAM.tileRaster(self.ui.release_lineEdit.text(), "init", temp_dir, tileCOLS, tileROWS, U, isInit=True) - if self.infra_bool: - SPAM.tileRaster(self.ui.infra_lineEdit.text(), "infra", temp_dir, tileCOLS, tileROWS, U) - - nTiles = pickle.load(open(temp_dir + "nTiles", "rb")) - - alpha = self.ui.alpha_Edit.text() - exp = self.ui.exp_Edit.text() - flux_threshold = self.ui.flux_Edit.text() - max_z = self.ui.z_Edit.text() - - logging.info('Alpha Angle: {}'.format(alpha)) - logging.info('Exponent: {}'.format(exp)) - logging.info('Flux Threshold: {}'.format(flux_threshold)) - logging.info('Max Z_delta: {}'.format(max_z)) - logging.info - -# ============================================================================= -# self.z_delta = np.zeros_like(dem, dtype=np.float32) -# self.flux = np.zeros_like(dem, dtype=np.float32) -# self.cell_counts = np.zeros_like(dem, dtype=np.int32) -# self.z_delta_sum = np.zeros_like(dem, dtype=np.float32) -# self.backcalc = np.zeros_like(dem, dtype=np.int32) -# self.fp_ta = np.zeros_like(dem, dtype=np.float32) -# self.sl_ta = np.zeros_like(dem, dtype=np.float32) -# ============================================================================= - - optList = [] - # das hier ist die batch-liste, die von mulitprocessing - # abgearbeitet werden muss - sieht so aus: - # [(0,0,alpha,exp,cellsize,-9999.), - # (0,1,alpha,exp,cellsize,-9999.), - # etc.] - - for i in range(nTiles[0]+1): - for j in range(nTiles[1]+1): - optList.append((i, j, alpha, exp, cellsize, nodata, - flux_threshold, max_z, temp_dir, self.infra_bool)) - - # Calculation - self.calc_class = Sim.Simulation(optList, self.infra_bool) - self.calc_class.finished.connect(self.thread_finished) - logging.info('Multiprocessing starts, used cores: {}'.format(cpu_count() - 1)) - self.calc_class.start() - - def thread_finished(self): - logging.info('Calculation finished, getting results.') - # Merge calculated tiles - self.z_delta = SPAM.MergeRaster(self.temp_dir, "res_z_delta") - self.flux = SPAM.MergeRaster(self.temp_dir, "res_flux") - self.cell_counts = SPAM.MergeRaster(self.temp_dir, "res_count") - self.z_delta_sum = SPAM.MergeRaster(self.temp_dir, "res_z_delta_sum") - self.fp_ta = SPAM.MergeRaster(self.temp_dir, "res_fp") - self.sl_ta = SPAM.MergeRaster(self.temp_dir, "res_sl") - if self.infra_bool: - self.backcalc = SPAM.MergeRaster(self.temp_dir, "res_backcalc") - self.output() - - def output(self): - # time_string = datetime.now().strftime("%Y%m%d_%H%M%S") - logging.info('Writing Output Files') - io.output_raster(self.ui.DEM_lineEdit.text(), - self.directory + self.res_dir + "flux{}".format(self.ui.outputBox.currentText()), - self.flux) - io.output_raster(self.ui.DEM_lineEdit.text(), - self.directory + self.res_dir + "z_delta{}".format(self.ui.outputBox.currentText()), - self.z_delta) - io.output_raster(self.ui.DEM_lineEdit.text(), - self.directory + self.res_dir + "FP_travel_angle{}".format(self.ui.outputBox.currentText()), - self.fp_ta) - io.output_raster(self.ui.DEM_lineEdit.text(), - self.directory + self.res_dir + "SL_travel_angle{}".format(self.ui.outputBox.currentText()), - self.sl_ta) - if not self.infra_bool: - io.output_raster(self.ui.DEM_lineEdit.text(), - self.directory + self.res_dir + "cell_counts{}".format(self.ui.outputBox.currentText()), - self.cell_counts) - io.output_raster(self.ui.DEM_lineEdit.text(), - self.directory + self.res_dir + "z_delta_sum{}".format(self.ui.outputBox.currentText()), - self.z_delta_sum) - if self.infra_bool: - io.output_raster(self.ui.DEM_lineEdit.text(), - self.directory + self.res_dir + "backcalculation{}".format(self.ui.outputBox.currentText()), - self.backcalc) - - print("Calculation finished") - end = datetime.now().replace(microsecond=0) - logging.info('Calculation needed: ' + str(end - self.start) + ' seconds') - - self.set_gui_bool(True) +from gui import Flow_Py_EXEC def main(args, kwargs): @@ -547,7 +169,7 @@ def main(args, kwargs): logging.info('Multiprocessing starts, used cores: {}'.format(cpu_count() - 1)) print("{} Processes started and {} calculations to perform.".format(mp.cpu_count() - 1, len(optList))) pool = mp.Pool(mp.cpu_count() - 1) - pool.map(fc.calculation_effect, optList) + pool.map(fc.calculation, optList) pool.close() pool.join() @@ -597,15 +219,7 @@ def main(args, kwargs): if __name__ == '__main__': - #mp.set_start_method('spawn') # used in Windows - argv = sys.argv[1:] - #argv = ['--gui'] - #argv = ["25", "8", "./examples/dam/", "./examples/dam/dam_010m_standard_cr100_sw250_f2500.20.6_n0.asc", "./examples/dam/release_dam.tif"] - #argv = ["15", "8", "./examples/dam/", "./examples/dam/dam_010m_standard_cr100_sw250_f2500.20.6_n0.asc", "./examples/dam/release_dam.tif", "infra=./examples/dam/infra.tif", "flux=0.0003", "max_z=270"] - #argv = ["25", "8", "./examples/Arzler/", "./examples/Arzler/arzleralmdhm0101m_clipped.tif", "./examples/Arzler/release.tif"] - #argv = ["25", "8", "./examples/Oberammergau/", "./examples/Oberammergau/PAR3_OAG_DGM_utm32n.tif", "./examples/Oberammergau/release.tif", "max_z=270"] - #argv = ["25", "8", "./examples/Osttirol/", "./examples/Osttirol/DTM_5m.tif", "./examples/Osttirol/post_VAIA_release_areas_DGM_extend.tif", "max_z=270"] - + argv = sys.argv[1:] if len(argv) < 1: print("Too few input arguments!!!") sys.exit(1)