diff --git a/config.py b/config.py
index a68c6779240763255e1f670be2cb0417ee72be90..1e9cde2a5ae79788fed5784d04cd3bbe589c9828 100644
--- a/config.py
+++ b/config.py
@@ -235,7 +235,11 @@ def write_namespace(file, ns, ns_name, indent):
         if isinstance(ns[key], dict):
             write_namespace(file, ns[key], key, indent + 4)
         else:
-            file.write(" " * (indent + 4) + f"{key} = {get_str_from_value(ns[key].value, ns[key].value_type)};\n")
+            if ns[key].comment:
+                line = " " * (indent + 4) + f"{key} = {get_str_from_value(ns[key].value, ns[key].value_type)}; # {ns[key].comment}\n"
+            else:
+                line = " " * (indent + 4) + f"{key} = {get_str_from_value(ns[key].value, ns[key].value_type)};\n"
+            file.write(line)
     file.write(" " * indent + "}\n")
     file.write("\n")
 
@@ -248,7 +252,11 @@ def dump_config(config, file_path):
             if isinstance(config_nested[key], dict):
                 write_namespace(file, config_nested[key], key, indent)
             else:
-                file.write(f"{key} = {get_str_from_value(config_nested[key].value, config_nested[key].value_type)};\n")
+                if config_nested[key].comment:
+                    line = f"{key} = {get_str_from_value(config_nested[key].value, config_nested[key].value_type)}; # {config_nested[key].comment}\n"
+                else:
+                    line = f"{key} = {get_str_from_value(config_nested[key].value, config_nested[key].value_type)};\n"
+                file.write(line)
 
 
 if __name__ == '__main__':
diff --git a/config_callbacks.py b/config_callbacks.py
index 967e4b991c7aff6bbc33f4bc889e9ea9e8ba0cb3..71a80f65d28f42fa0c0cf8311a4d7f5df5387388 100644
--- a/config_callbacks.py
+++ b/config_callbacks.py
@@ -6,6 +6,15 @@ from style_constants import SPACE, COLLAPSING_HEADERS_UI
 from style import get_accent_color, apply_theme
 from config import load_config, dump_config, ConfigParserError
 from dynamic_ui import construct_config_ui, construct_model_output_structure_ui
+from map_edit_callbacks import open_map
+
+def show_map_window_clb(s, a, u):
+    if get_config_file_path():
+        config = get_config()
+        if 'topography.filename' in config:
+            filename = config['topography.filename'].value
+            open_map(filename)
+    dpg.show_item('map_window')
 
 def set_file_path_clb(s, a, u):
     file_path = a['file_path_name']
diff --git a/config_ui.py b/config_ui.py
index 69c389611cc1b14aeda5a480c6f452d878e81d98..87e0b67297a7886e314295ac029c04526dfe8216 100644
--- a/config_ui.py
+++ b/config_ui.py
@@ -14,7 +14,7 @@ def construct_main_window_ui():
                 dpg.add_menu_item(label='save\t\t', shortcut='ctrl+s', callback=config_save_clb, tag='save_config')
                 dpg.add_menu_item(label='save as\t\t', shortcut='ctrl+shift+s', callback=open_config_save_as_dialog_clb, tag='open_config_save_as_dialog')
 
-            dpg.add_menu_item(label='map', callback=lambda: dpg.show_item('map_window'))
+            dpg.add_menu_item(label='map', callback=show_map_window_clb)
             dpg.add_menu_item(label='run', callback=lambda: dpg.show_item('run_window'))
 
             with dpg.menu(label='view'):
diff --git a/constants.py b/constants.py
deleted file mode 100644
index 28d924d673225bb3c0da17f43c524dfc691ac59d..0000000000000000000000000000000000000000
--- a/constants.py
+++ /dev/null
@@ -1,86 +0,0 @@
-import os
-
-from config import CfgVar
-
-ROAD_COLOR = (221, 161, 94, 255)
-TREE_COLOR = (96, 108, 56, 255)
-BUILDING_COLOR = (188, 108, 37, 255)
-EMISSION_POINT_COLOR = (255, 0, 0, 255)
-
-TABS_UI = 'tabs_ui'
-COLLAPSING_HEADERS_UI = 'collapsing_headers_ui'
-WIDGET_WIDTH = 300
-XOFFSET = 300
-LCZS = ['compact_high_rise', 'compact_low_rise', 'compact_mid_rise', 'heavy_industry', 'large_low_rise', 'lightweight_low_rise', 'open_high_rise', 'open_low_rise', 'open_mid_rise', 'sparsley_build']
-
-MAX_MAP_WIDTH = 2000
-MAX_MAP_HEIGHT = 2000
-
-EMISSION_POINT_CONFIG_VARIABLES = {
-    'value': CfgVar(key='value', value=28481176.531511, value_type='DOUBLE', comment=''),
-	'begin': CfgVar(key='begin', value=25200.0, value_type='DOUBLE', comment='[s]'),
-	'xpos': CfgVar(key='xpos', value=200.0, value_type='DOUBLE', comment='[m]'),
-	'ypos': CfgVar(key='ypos', value=200.0, value_type='DOUBLE', comment='[m]'),
-	'zpos': CfgVar(key='zpos', value=60.0, value_type='DOUBLE', comment='[m]'),
-	'sx': CfgVar(key='sx', value=20.0, value_type='DOUBLE', comment='[m]'),
-	'sy': CfgVar(key='sy', value=20.0, value_type='DOUBLE', comment='[m]'),
-	'sz': CfgVar(key='sz', value=10.0, value_type='DOUBLE', comment='[m]')
-}
-
-UIS = [TABS_UI, COLLAPSING_HEADERS_UI]
-
-FONT_PATH = os.path.join('fonts', 'Montserrat-Medium.ttf')
-ICON_PATH = os.path.join('icons', 'icon.ico')
-FONT_SIZE = 24
-ACCENT_COLOR = (0, 119, 200, 100)
-ROUNDING = 10
-SPACE = 10
-INDENT = 40
-BORDER = 3
-
-TEXT = (0, 1)
-ACCENT = (5, 18, 19, 20, 15, 16, 35, 37, 34, 23, 22, 25, 26, 27, 28, 29, 10, 11, 12, 30, 31, 32, 49, 50)
-PRIMARY = (2, 3, 39)
-SECONDARY = (36, 33, 21, 24, 4, 7, 8, 9, 13, 14)
-APPLY_ALPHA = (22, 25, 31, 34, 16)
-COLOR_TYPE_TO_DPG_ITEM = {
-    'TEXT': (0, 1),
-	'PRIMARY': (2, 3, 39),
-	'SECONDARY': (36, 33, 21, 24, 4, 7, 8, 9, 13, 14),
-	'ACCENT': (5, 18, 19, 20, 15, 16, 35, 37, 34, 23, 22, 25, 26, 27, 28, 29, 10, 11, 12, 30, 31, 32, 49, 50)}
-COLOR_TO_COLOR_TYPE = {0: 'TEXT', 1: 'TEXT', 2: 'PRIMARY', 3: 'PRIMARY', 39: 'PRIMARY', 36: 'SECONDARY', 21: 'SECONDARY', 24: 'SECONDARY', 4: 'SECONDARY', 7: 'SECONDARY', 8: 'SECONDARY', 9: 'SECONDARY', 13: 'SECONDARY', 33: 'SECONDARY', 14: 'SECONDARY', 35: 'ACCENT', 20: 'ACCENT', 37: 'ACCENT', 22: 'ACCENT', 23: 'ACCENT', 5: 'ACCENT', 25: 'ACCENT', 26: 'ACCENT', 27: 'ACCENT', 28: 'ACCENT', 29: 'ACCENT', 10: 'ACCENT', 30: 'ACCENT', 11: 'ACCENT', 31: 'ACCENT', 12: 'ACCENT', 32: 'ACCENT', 49: 'ACCENT', 34: 'ACCENT', 15: 'ACCENT', 50: 'ACCENT', 16: 'ACCENT', 18: 'ACCENT', 19: 'ACCENT', 1: 'TEXT'}
-
-BLUE = {
-    'enabled': {
-        'TEXT': (255, 255, 255, 255),
-        'PRIMARY': (37, 37, 38, 255),
-        'SECONDARY': (51, 51, 55, 255),
-        'ACCENT': (0, 119, 200, 153)
-    },
-    'disabled': {
-        'TEXT': (255, 255, 255, 150),
-        'PRIMARY': (37, 37, 38, 255),
-        'SECONDARY': (51, 51, 55, 255),
-        'ACCENT': (0, 119, 200, 153)
-    },
-}
-
-ORANGE = {
-    'enabled': {
-        'TEXT': (255, 255, 255, 255),
-        'PRIMARY': (37, 37, 38, 255),
-        'SECONDARY': (51, 51, 55, 255),
-        'ACCENT': (251, 133, 0, 153)
-    },
-    'disabled': {
-        'TEXT': (255, 255, 255, 150),
-        'PRIMARY': (37, 37, 38, 255),
-        'SECONDARY': (51, 51, 55, 255),
-        'ACCENT': (251, 133, 0, 153)
-    },
-}
-
-THEMES = {
-    'blue': BLUE,
-    'orange': ORANGE
-}
\ No newline at end of file
diff --git a/dynamic_ui.py b/dynamic_ui.py
index 7a8d52922b8c599acaaf534440b7828dba36f841..dc2b64cff4658e9ec959278bad43340a5f61c093 100644
--- a/dynamic_ui.py
+++ b/dynamic_ui.py
@@ -55,7 +55,7 @@ def construct_config_ui(config_file_path, config):
     else:
         construct_config_ui_collapsing_headers(config_file_path, config)
 
-def add_item_to_config_ui(full_path):
+def add_item_to_config_ui(full_path, before=None):
     config_file_path = get_config_file_path()
     config = get_config()
     if get_current_ui_type() == TABS_UI:
@@ -83,7 +83,10 @@ def add_item_to_config_ui(full_path):
             path = config_file_path + '.' + '.'.join(namespaces[:level+1])
 
             if not dpg.does_item_exist(path):
-                dpg.add_collapsing_header(label=namespaces[level], parent=parent, tag=path, indent=INDENT)
+                if before:
+                    dpg.add_collapsing_header(label=namespaces[level], parent=parent, tag=path, indent=INDENT, before=before)
+                else:
+                    dpg.add_collapsing_header(label=namespaces[level], parent=parent, tag=path, indent=INDENT)
 
             parent = path
 
diff --git a/map_edit_callbacks.py b/map_edit_callbacks.py
index 48dbe38e5b2142acbbc3319ec966d9e202a77a96..dfde03cc58dba09f01d087c2da9ed3360c449c0c 100644
--- a/map_edit_callbacks.py
+++ b/map_edit_callbacks.py
@@ -9,6 +9,43 @@ from map_edit import dump_height_map, load_height_map, update_texture
 from generator import LCZ
 from paths import BASE_PATH
 from utils import show_message, set_main_window_value, get_config, get_config_file_path, delete_item_and_clear_alias, delete_item_children_and_clear_aliases, set_map_window_value, get_map_window_value, get_height_map_file_path
+from dynamic_ui import add_item_to_config_ui
+from config import CfgVar
+
+def add_map_to_config_clb(s, a, u):
+    if not get_config_file_path():
+        return
+
+    config = get_config()
+
+    keys = []
+
+    prev_key = ''
+
+    before = None
+
+    for key in config:
+        if 'topography' in key:
+            keys.append(key)
+        elif 'topography' in prev_key:
+            before = key.split('.')[0]
+            break
+        prev_key = key
+
+    for key in keys:
+        del config[key]
+
+    set_main_window_value('config', config)
+
+    delete_item_children_and_clear_aliases(f'{get_config_file_path()}.topography')
+
+    config['topography.mode'] = CfgVar(key='mode', value='ascii-mask')
+    config['topography.filename'] = CfgVar(key='filename', value=get_height_map_file_path())
+
+    add_item_to_config_ui('topography.mode', before=f'{get_config_file_path()}.{before}')
+    add_item_to_config_ui('topography.filename', before=dpg.last_item())
+
+    dump_height_map(get_map_window_value('buildings_map'), get_height_map_file_path())
 
 def delete_emission_point_clb(s, a, u):
     n = dpg.get_item_user_data('emission_settings_window')
@@ -66,7 +103,7 @@ def clear_map():
     dpg.set_item_user_data('map_window', settings)
 
 def map_window_on_close_clb(s, a, u):
-    clear_map()
+    pass
 
 def construct_map_layers(w, h):
     dpg.set_item_width('map_child_window', w)
@@ -121,13 +158,15 @@ def map_open_layer_clb(s, a, u):
     
     dpg.draw_image(f'map_{layer}_texture', color=LAYER_TO_COLOR[layer], tag=f'map_{layer}_image', pmin=(0, 0), pmax=(w, h), parent=f'map_drawlist')
 
+    layer_old = dpg.get_value('layer')
+
     dpg.set_value('layer', layer)
 
     update_texture()
 
-def map_open_clb(s, a, u):
-    height_map_file_path = a['file_path_name']
+    dpg.set_value('layer', layer_old)
 
+def open_map(height_map_file_path):
     if height_map_file_path.endswith('txt'):
         try:
             height_map = load_height_map(height_map_file_path)
@@ -156,10 +195,14 @@ def map_open_clb(s, a, u):
     construct_map_layers(w, h)
 
     dpg.set_value('layer', 'buildings')
+    dpg.set_item_label('map_window', f'editing map {height_map_file_path}')
     
     update_texture()
 
-    dpg.show_item('map_window')
+def map_open_clb(s, a, u):
+    height_map_file_path = a['file_path_name']
+
+    open_map(height_map_file_path)
 
 def generate_map_clb(s, a, u):
     height_map = LCZ(config_path=os.path.join(BASE_PATH, 'configs', f'{s}.json')).to_height_map(dtype=np.float64)
@@ -177,14 +220,14 @@ def generate_map_clb(s, a, u):
     set_map_window_value('height_map_file_path', 'map.txt')
     set_map_window_value('max_height', max_height)
 
+    dpg.set_item_label('map_window', f'editing map map.txt')
+
     construct_map_layers(w, h)
 
     dpg.set_value('layer', 'buildings')
 
     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:
diff --git a/map_edit_ui.py b/map_edit_ui.py
index ff877d3bf233799749b746ac30b270cc1cb7307c..9163a342f60756f19b4886eca88fd51563a02a62 100644
--- a/map_edit_ui.py
+++ b/map_edit_ui.py
@@ -69,7 +69,7 @@ def construct_map_edit_window():
                         dpg.add_menu_item(label=lcz_type, check=False, callback=combo_menu(generate_map_clb), tag=lcz_type)
                 dpg.add_menu_item(label='save', callback=map_save_clb, tag='map_save')
                 dpg.add_menu_item(label='save as', callback=open_map_save_as_dialog_clb, tag='open_map_save_as_dialog')
-                dpg.add_menu_item(label='add map to config', tag='add_map_to_config')
+            dpg.add_menu_item(label='add map to config', tag='add_map_to_config', callback=add_map_to_config_clb)
 
         with dpg.group(horizontal=True):
             with dpg.group(width=200, tag='tools'):
diff --git a/remote_run.py b/remote_run.py
index 76a91d022e822996bfa11d12133dfb1263220430..29fe8d1f936f215f4041a1ce5e4b633da162c526 100644
--- a/remote_run.py
+++ b/remote_run.py
@@ -81,7 +81,7 @@ class BuildingSession:
         return ''
 
 class RunningSession:
-    def __init__(self, connection, config_file_path, run_commands, executable_file_path, uuid=None):
+    def __init__(self, connection, config_file_path, run_commands, executable_file_path, uuid=None, upload_paths=dict()):
         self.conn = connection
         if uuid is not None:
             self.uuid = uuid
@@ -93,6 +93,10 @@ class RunningSession:
 
         self.conn.exec_command(f'mkdir {self.uuid}; cp {self.executable_file_path} {self.uuid}/nsenx')
         self.conn.upload(self.config_file_path, f'{self.uuid}/config.txt')
+
+        for path in upload_paths:
+            self.conn.upload(path, f'{self.uuid}/{upload_paths[path]}')
+
         commands = [f'cd {self.uuid}'] + self.run_commands
 
         self.stdout = self.conn.exec_command('; '.join(commands))
diff --git a/remote_run_callbacks.py b/remote_run_callbacks.py
index 7356adeae0fc637da2b9cd4c11197a3f9fbd7ad0..3a4f1c331902c7b659b0b4d3d16093afa371c129 100644
--- a/remote_run_callbacks.py
+++ b/remote_run_callbacks.py
@@ -13,7 +13,7 @@ from remote_run import Connection, BuildingSession, RunningSession
 from remote_run_constants import *
 from style_constants import FONT_SIZE
 from dynamic_ui import construct_model_output_structure_ui
-from config import dump_config
+from config import dump_config, load_config
 from style import get_accent_color
 
 def update_run_model_window():
@@ -78,6 +78,23 @@ def make_execute_command():
 
     return command
 
+def make_run_commands(running_session_id, executable_file_path, machine, model):
+    run_commands = []
+
+    folders = ['chem-forcing', 'chem-init', 'drag-configs', 'drag-forcing', 'meteo-forcing', 'meteo-init']
+    prefix = executable_file_path.split('/')[0] + '/nse-gabls1-urban-les'
+
+    for folder in folders:
+        path = f'{prefix}/{folder}'
+        run_commands.append(f'cp -r ../{path} {folder}')
+
+    if machine == LOMONOSOV:
+        run_commands += RUN_COMMANDS[(machine, model)] # + make_run_sh_for_slurm() + ['sbatch ./run.sh']
+    else:
+        run_commands += RUN_COMMANDS[(machine, model)] + [make_execute_command()]
+
+    return run_commands
+
 def update_progress(running_session_id, output):
     if not re.findall(r'([0-9]+)%', output):
         progress = dpg.get_value(f'{running_session_id}_progress_bar')
@@ -169,12 +186,25 @@ def run_model():
 
     dpg.set_value(f'{running_session_id}_status', 'running')
 
-    if machine == LOMONOSOV:
-        run_commands = RUN_COMMANDS[(machine, model)] # + make_run_sh_for_slurm() + ['sbatch ./run.sh']
+    run_commands = make_run_commands(running_session_id, executable_file_path, machine, model)
+
+    upload_paths = dict()
+
+    if get_config_file_path():
+        config = get_config()
+
+        if 'topography.filename' in config:
+            upload_paths = {config['topography.filename'].value: config['topography.filename'].value}
     else:
-        run_commands = RUN_COMMANDS[(machine, model)] + [make_execute_command()]
+        try:
+            config = load_config(config_file_path)
+            if 'topography.filename' in config:
+                upload_paths = {config['topography.filename'].value: config['topography.filename'].value}
+        except Exception as e:
+            show_message('bad file format')
+            return
 
-    running_session = RunningSession(conn, config_file_path, run_commands, executable_file_path, running_session_id)
+    running_session = RunningSession(conn, config_file_path, run_commands, executable_file_path, running_session_id, upload_paths=upload_paths)
 
     if machine == LOMONOSOV:
         output = running_session.output()
@@ -223,10 +253,12 @@ def download_output():
     dpg.hide_item('model_output_window')
     dirs, filepaths, running_session_id = dpg.get_item_user_data('model_output_window')
 
-    download = []
+    download = set()
+    download_folders = set()
     for filepath in filepaths:
         if dpg.get_value(filepath):
-            download.append(filepath)
+            download.add(filepath)
+            download_folders.add('/'.join(filepath.split('/')[:-1]))
 
     machine = LABEL_TO_MACHINE[dpg.get_value(f'{running_session_id}_machine')]
 
@@ -235,8 +267,8 @@ def download_output():
     dpg.set_value(f'{running_session_id}_status', 'downloading')
 
     prefix = os.path.join(download_to_folder)
-        
-    construct_folder_structure(dirs, prefix=prefix)
+    
+    construct_folder_structure(download_folders, prefix=prefix)
 
     conn = get_run_window_value('connections')[machine]
     
diff --git a/remote_run_ui.py b/remote_run_ui.py
index fac0c38cb36c2726a5d2d3184e93e0ec2b7340a8..0db618505cf6790fb6f159ad372341a912405751 100644
--- a/remote_run_ui.py
+++ b/remote_run_ui.py
@@ -7,10 +7,24 @@ from remote_run_callbacks import *
 from remote_run import *
 
 def construct_remote_run_window():
-    user_data = {
-        'connections': dict(),
-        'builds': dict()
-    }
+    if 'USE_BUILDS' in os.environ:
+        conn = {
+            LAB: Connection(LAB_HOST, os.getenv('SERVER_LOGIN', ''), os.getenv('SERVER_PASS', '')),
+            # LOMONOSOV: Connection(LOMONOSOV_HOST, os.getenv('LOMONOSOV_LOGIN'), id_rsa_path=os.getenv('ID_RSA_PATH', ''))
+        }
+        builds = {
+            (LAB, URBAN_LES): 'prebuild/code/nsenx',
+            # (LOMONOSOV, URBAN_LES): '6e094bc0-a5f6-4474-8c71-a2e3a90d8e85/build/nse-gabls1-urban-les'
+        }
+        user_data = {
+            'connections': conn,
+            'builds': builds
+        }
+    else:
+        user_data = {
+            'connections': dict(),
+            'builds': dict()
+        }
 
     with dpg.window(
                 label='remote run',