import dearpygui.dearpygui as dpg import tifffile from utils import * from constants import SPACE, TREE_COLOR, ROAD_COLOR, BUILDING_COLOR from remote_run import start_remote_execution, start_model_build, get_server_output_structure from map_edit import dump_height_map, load_height_map, update_texture from styles import get_accent_color, apply_theme from generator import LCZ from config import load_config, dump_config from dynamic_ui import construct_config_ui, construct_model_output_structure_ui def map_window_on_close_clb(s, a, u): delete_item_and_clear_alias(f'map_buildings_texture') delete_item_and_clear_alias(f'map_trees_texture') delete_item_and_clear_alias(f'map_roads_texture') delete_item_children_and_clear_aliases(f'map_drawlist') user_data = { 'buildings_map': None, 'trees_map': None, 'roads_map': None, 'height_map_file_path': None, 'drawing': False, 'prev_coords': None, 'current_action': None, 'max_height': 0, 'output_dirs': None, } dpg.set_item_user_data('map_window', user_data) def set_file_path_clb(s, a, u): file_path = a['file_path_name'] dpg.set_value(u, file_path) def construct_config_ui_clb(s, a, u): if not get_config_file_path(): return delete_config_items_and_clear_aliases() update_config_values() construct_config_ui(get_config_file_path(), get_config()) ################################################################################ # # Config # ################################################################################ def update_config_values(): config = get_config() for path in config: if dpg.does_item_exist(f'{get_config_file_path()}.{path}'): config[path].value = dpg.get_value(f'{get_config_file_path()}.{path}') set_main_window_value('config', config) def config_save_as_clb(s, a, u): update_config_values() dump_config(get_config(), a['file_path_name']) dpg.show_item('message_popup') def config_open_clb(s, a, u): delete_config_items_and_clear_aliases() config_file_path = a['file_path_name'] config = load_config(config_file_path) set_main_window_value('config', config) set_main_window_value('config_file_path', config_file_path) construct_config_ui(a['file_path_name'], config) def config_save_clb(s, a, u): update_config_values() dump_config(get_config(), get_config_file_path()) dpg.show_item('message_popup') def open_config_open_dialog_clb(s, a, u): dpg.show_item('config_open') def show_config_search_window_clb(s, a, u): dpg.show_item('search_popup') def open_config_save_as_dialog_clb(s, a, u): dpg.show_item('config_open') ################################################################################ # # Config Search # ################################################################################ def search_clb(s, data, u): if not get_config_file_path(): return if not data: return for path in get_config(): if data.lower() in path.split('.')[-1]: dpg.set_y_scroll('main', dpg.get_item_pos('.'.join([get_config_file_path(), path.split('.')[0]]))[1]) for tag in path_iter(path, prefix=get_config_file_path()): if dpg.get_value(COLLAPSING_HEADERS_UI) == True: dpg.set_value(tag, True) else: dpg.set_value(dpg.get_item_parent(dpg.get_item_parent(tag)), dpg.get_item_parent(tag)) change_color_temporarily('.'.join([get_config_file_path(), path, 'text']), color=get_accent_color()) ################################################################################ # # Map edit # ################################################################################ def construct_map_layers(w, h): dpg.set_item_width('map_child_window', w) dpg.set_item_height('map_child_window', h) # dpg.add_texture_registry(tag='textures') dpg.add_dynamic_texture(w, h, np.zeros(w * h * 4), tag=f'map_buildings_texture', parent='textures') dpg.add_dynamic_texture(w, h, np.zeros(w * h * 4), tag=f'map_trees_texture', parent='textures') dpg.add_dynamic_texture(w, h, np.zeros(w * h * 4), tag=f'map_roads_texture', parent='textures') dpg.bind_item_theme('map_child_window', 'map_image_theme') dpg.add_drawlist(w, h, tag=f'map_drawlist', parent='map_child_window', pos=[0, 0]) dpg.draw_image(f'map_buildings_texture', color=BUILDING_COLOR, tag=f'map_buildings_image', pmin=(0, 0), pmax=(w, h), parent=f'map_drawlist') dpg.draw_image(f'map_trees_texture', color=TREE_COLOR, tag=f'map_trees_image', pmin=(0, 0), pmax=(w, h), parent=f'map_drawlist') dpg.draw_image(f'map_roads_texture', color=ROAD_COLOR, tag=f'map_roads_image', pmin=(0, 0), pmax=(w, h), parent=f'map_drawlist') def map_open_clb(s, a, u): height_map_file_path = a['file_path_name'] if height_map_file_path.endswith('txt'): height_map = load_height_map(height_map_file_path) max_height = np.max(height_map) height_map /= max_height else: height_map = tifffile.imread(height_map_file_path) max_height = 1 h, w = height_map.shape print(dpg.get_item_user_data('map_window')) set_map_window_value('buildings_map', height_map) set_map_window_value('roads_map', np.zeros((h, w))) set_map_window_value('trees_map', np.zeros((h, w))) set_map_window_value('height_map_file_path', height_map_file_path) set_map_window_value('max_height', max_height) construct_map_layers(w, h) update_texture() dpg.show_item('map_window') def generate_map_clb(s, a, u): height_map = LCZ(config_path=f'configs/{s}.json').to_height_map(dtype=np.float64) max_height = np.max(height_map) height_map /= max_height h, w = height_map.shape set_map_window_value('buildings_map', height_map) set_map_window_value('roads_map', np.zeros((h, w))) set_map_window_value('trees_map', np.zeros((h, w))) set_map_window_value('height_map_file_path', f'{dpg.generate_uuid()}.txt') set_map_window_value('max_height', max_height) construct_map_layers(w, h) update_texture() dpg.show_item('map_window') def save_map(file_path): if file_path.endswith('.tif') or file_path.endswith('.tiff'): with TiffWriter(file_path) as tif: tif.write(get_map_window_value('buildings_map')) tif.write(get_map_window_value('roads_map')) tif.write(get_map_window_value('trees_map')) else: dump_height_map(get_map_window_value('buildings_map'), file_path) def map_save_clb(s, a, u): file_path = get_height_map_file_path() save_map(file_path) dpg.show_item('message_popup') def map_save_as_clb(s, a, u): file_path = a['file_path_name'] save_map(file_path) dpg.show_item('message_popup') def open_map_save_as_dialog_clb(s, a, u): dpg.show_item('map_save_as') def open_map_open_dialog_clb(s, a, u): dpg.show_item('map_open') def set_action_clb(s, a, u): set_map_window_value('current_action', s) def set_action_none_clb(s, a, u): set_map_window_value('current_action', None) ################################################################################ # # Styles # ################################################################################ def apply_theme_clb(s, a, u): apply_theme(s) ################################################################################ # # Remote execution # ################################################################################ def start_remote_execution_clb(s, a, u): dpg.configure_item('login_modal', show=False) u = dpg.get_item_user_data('login_modal') if u == 'build_model': start_model_build(dpg.get_value('server_username'), dpg.get_value('server_password'), dpg.get_value('gitlab_username'), dpg.get_value('gitlab_password')) elif u == 'run_on_lab_server': start_remote_execution(dpg.get_value('server_username'), dpg.get_value('server_password')) elif u == 'download_output': s = get_server_output_structure(dpg.get_value('server_username'), dpg.get_value('server_password')) folders, filepaths = parse_dirs(s) delete_item_children_and_clear_aliases('output') construct_model_output_structure_ui(filepaths, folders) dpg.show_item('model_output_window') def build_model_on_lab_server_clb(s, a, u): pass def show_get_credentials_modal_clb(s, a, u): dpg.set_item_user_data('login_modal', u) if u == 'run_on_lab_server': if not get_config_file_path(): show_status_text('no config.txt specified. cannot run.') return update_config_values() dump_config(get_config(), 'tmp.txt') dpg.hide_item('gitlab_password') dpg.hide_item('gitlab_username') elif u == 'download_output': dpg.hide_item('gitlab_password') dpg.hide_item('gitlab_username') dpg.show_item('login_modal')