hkayabilisim commited on
Commit
c818aff
·
1 Parent(s): 1ad6ce2

Completed landslide + building + metric average

Browse files
tomorrowcities/backend/engine.py CHANGED
@@ -290,7 +290,8 @@ def compute_power_infra(buildings, household, nodes,edges,intensity,fragility,ha
290
 
291
  def compute(gdf_landuse, gdf_buildings, df_household, df_individual,gdf_intensity, df_hazard, hazard_type, policies=[]):
292
 
293
- np.random.seed(seed=0)
 
294
 
295
  column_names = {'zoneID':'zoneid','bldID':'bldid','nHouse':'nhouse',
296
  'specialFac':'specialfac','expStr':'expstr','repValue':'repvalue',
@@ -344,6 +345,15 @@ def compute(gdf_landuse, gdf_buildings, df_household, df_individual,gdf_intensit
344
 
345
  gdf_building_intensity['rnd'] = np.random.random((len(gdf_building_intensity),1))
346
 
 
 
 
 
 
 
 
 
 
347
  # TODO: Check if the logic makes sense
348
  if hazard_type == HAZARD_FLOOD:
349
  away_from_flood = gdf_building_intensity['distance'] > threshold_flood_distance
 
290
 
291
  def compute(gdf_landuse, gdf_buildings, df_household, df_individual,gdf_intensity, df_hazard, hazard_type, policies=[]):
292
 
293
+ if hazard_type != "landslide":
294
+ np.random.seed(seed=0)
295
 
296
  column_names = {'zoneID':'zoneid','bldID':'bldid','nHouse':'nhouse',
297
  'specialFac':'specialfac','expStr':'expstr','repValue':'repvalue',
 
345
 
346
  gdf_building_intensity['rnd'] = np.random.random((len(gdf_building_intensity),1))
347
 
348
+ if hazard_type == "landslide":
349
+ gdf_building_collapse_prob = gdf_building_intensity.merge(df_hazard,
350
+ on=['expstr','susceptibility'], how='left')
351
+ gdf_building_collapse_prob['ds'] = DS_NO
352
+ collapsed_idx = (gdf_building_collapse_prob['rnd'] < gdf_building_collapse_prob['collapse_probability'])
353
+ gdf_building_collapse_prob.loc[collapsed_idx, 'ds'] = DS_COLLAPSED
354
+ bld_hazard = gdf_building_collapse_prob[['bldid','ds']]
355
+ return bld_hazard
356
+
357
  # TODO: Check if the logic makes sense
358
  if hazard_type == HAZARD_FLOOD:
359
  away_from_flood = gdf_building_intensity['distance'] > threshold_flood_distance
tomorrowcities/content/articles/contribution.md ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ author: huseyin.kaya
3
+ title: Contributing
4
+ description: A step-by-step guideline for contributors
5
+ image: https://github.com/TomorrowsCities/tomorrowcities/blob/main/tomorrowcities/content/images/data.png?raw=true
6
+ thumbnail: https://github.com/TomorrowsCities/tomorrowcities/blob/main/tomorrowcities/content/images/data.png?raw=true
7
+ alt: "Data Formats"
8
+ createdAt: 2023-10-10
9
+ duration: 6 min read
10
+ category:
11
+ - general
12
+ ---
13
+
14
+ [TOC]
15
+
16
+ ## Adding a new layer
17
+
18
+ On top of the **engine.py**, there is a reactive variable caller **layers**
19
+ to contain all information about the layers. You can add a new layer to that
20
+ variable. Here we provide an example.
21
+
22
+ ```python
23
+ layers = solara.reactive({
24
+ # ...
25
+ 'layers' : {
26
+ 'landslide susceptibility': {
27
+ 'render_order': 50,
28
+ 'map_info_tooltip': 'Number of zones in the susceptibility map',
29
+ 'data': solara.reactive(None),
30
+ 'map_layer': solara.reactive(None),
31
+ 'force_render': solara.reactive(False),
32
+ 'visible': solara.reactive(False),
33
+ 'pre_processing': identity_preprocess,
34
+ 'extra_cols': {},
35
+ 'attributes_required': [set(['id','susceptibility','geometry'])],
36
+ 'attributes': [set(['id','susceptibility','geometry'])]},
37
+ #...
38
+ ```
39
+
40
+ The above step is the minimum requirement of importing data and visualizing
41
+ on the map. If you need extra stuff for visualization, then edit **create_map_layer** function.
42
+
43
+ ## Adding a new Hazard
44
+ Add your hazard to application state:
45
+
46
+ ```python
47
+ app_state = solara.reactive({
48
+ #...
49
+ 'hazard_list': ["earthquake","flood","landslide"],
50
+ #...
51
+ ```
52
+
53
+ Update **is_ready_to_run** to add the required layers for your hazard.
54
+
55
+ Update **execute_engine** to include the relation with your hazard and infrastructure type.
56
+ For each instrastructure type, you'll see dedicated functions such as **execute_road**,
57
+ or **execute_power**, etc. Inside each one, make sure you load the necessary data
58
+ before calling the backend.
tomorrowcities/content/articles/landslide.md ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ author: huseyin.kaya
3
+ title: Land Slide
4
+ description: Land Slide damage assessment via Monte-Carlo Approach
5
+ image: https://raw.githubusercontent.com/TomorrowsCities/tomorrowcities/main/tomorrowcities/content/images/landslide.jpg?raw=true
6
+ thumbnail: https://raw.githubusercontent.com/TomorrowsCities/tomorrowcities/main/tomorrowcities/content/images/landslide.jpg?raw=true
7
+ alt: "Landslide analysis"
8
+ createdAt: 2023-10-10
9
+ duration: 6 min read
10
+ category:
11
+ - general
12
+ ---
13
+
14
+ [TOC]
15
+
16
+ ## Data Formats
17
+
18
+ ### Susceptibility Map
19
+ Since it contains geo-spatial information, the format of this file should be GeoJSON.
20
+
21
+ |id|susceptibility|geometry|
22
+ |--|--------------|--------|
23
+ |0 |low |MULTIPOLYGON (((82.66785 27.80147, 82.66906 27... |
24
+ |1 |medium |MULTIPOLYGON (((82.60206 27.85078, 82.60202 27... |
25
+ |2 |low |MULTIPOLYGON (((82.68074 27.79833, 82.68025 27... |
26
+ |3 |high |MULTIPOLYGON (((82.62131 27.86873, 82.62120 27... |
27
+
28
+ ### Fragility
29
+ Collapse probability depends on three factors:
30
+
31
+ * **expstr**: taxonomy of the structure
32
+ * **susceptibility**: which susceptibility zone the structure is in
33
+ * **trigger level**: amount of rainfall which is categorized into minor, moderate and severe.
34
+
35
+ Since it is a tabular data with no geo-spatial context, the data can be provided in
36
+ Microsoft Excel or JSON format.
37
+
38
+ |expstr|susceptibility|minor|moderate|severe|
39
+ |------|--------------|-----|--------|------|
40
+ |Adb+HC+10s+Edu| low |0.01 |0.02 |0.03|
41
+ |Adb+HC+1s+Res | low |0.03 |0.04 |0.05|
42
+ |Adb+HC+1s+ResCom| low |0.06 |0.08 |0.09|
43
+
44
+ ### Trigger Level
45
+ Trigger level selection becomes active when the user selects "landuse" hazard type.
46
+ There are three pre-defined levels: minor, moderate, and severe. The fragility data
47
+ should contain a column for each category.
48
+
49
+ ## Algorithm
50
+ The algorithm starts with geo-spatial merge of susceptibility map and the building layer.
51
+ For this purpose, **sjoin_nearest** function of GeoPandas is used. As a result of
52
+ merging process, the buildings have susceptibility attribute.
53
+
54
+ The merged tabular data is left joined with fragility data. In this merge, instead of using all minor, moderate
55
+ and severe columns, only the column matching to the trigger level is used. For instance, if the trigger level
56
+ is moderate, expstr, susceptibility, and moderate columns are used. As a result of this merge, the buildings
57
+ now have collapse probabilities.
58
+
59
+ The next step is Monte-Carlo simulation. For each building, a random number between zero and one is picked.
60
+ If it is less than the building's collapse probability, then the damage state of the building is set to DS_COLLAPSED (4)
61
+ otherwise to DS_NO (0).
62
+
63
+ Then by using household, landuse and individual layers, the seven impact metrics are calculated.
64
+
65
+ Above process is repeated N times and the impact metrics are averaged. In the metric widgets
66
+ these averaged impact metrics are displayed.
67
+
68
+ In the map, and the layer displayer, however, the damage states of the buildings and other infrastructures are displayed
69
+ according to the last Monte-Carlo random realization. However, the attributes metric1,...,metric7 denote the average
70
+ over N random trials.
71
+
72
+
73
+
tomorrowcities/content/articles/metrics.md CHANGED
@@ -66,3 +66,7 @@ An individual is assumed to be displaced when any of the following condition hol
66
  * the individual's workplace, school, or associated hospital is damaged
67
  * the individual can not reach to workplace, school, or associated hospital via transportation network
68
  * the individual's workplace, school, or associated hospital has no electricity
 
 
 
 
 
66
  * the individual's workplace, school, or associated hospital is damaged
67
  * the individual can not reach to workplace, school, or associated hospital via transportation network
68
  * the individual's workplace, school, or associated hospital has no electricity
69
+
70
+ ## Average Impact Metrics in Monte-Carlo Simulations
71
+ When the hazard scenario is run with different random realizations such as landslide calculations,
72
+ then the impact metrics are calculated by taking average of all simulations.
tomorrowcities/pages/engine.py CHANGED
@@ -21,7 +21,7 @@ import logging, sys
21
  #logging.basicConfig(stream=sys.stderr, level=logging.INFO)
22
  import pickle
23
  import datetime
24
- from .settings import storage
25
  from ..backend.engine import compute, compute_power_infra, compute_road_infra, calculate_metrics
26
  from ..backend.utils import building_preprocess, identity_preprocess
27
  from .utilities import S3FileBrowser, extension_list, extension_list_w_dots
@@ -30,11 +30,36 @@ from .docs import data_import_help
30
  layers = solara.reactive({
31
  'infra': solara.reactive(["building"]),
32
  'hazard': solara.reactive("flood"),
 
33
  'datetime_analysis': datetime.datetime.utcnow(),
34
  'road_water_height_threshold': solara.reactive(0.3),
 
 
35
  'dialog_message_to_be_shown': solara.reactive(None),
36
  'version': '0.2.3',
37
  'layers' : {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
  'building': {
39
  'render_order': 50,
40
  'map_info_tooltip': 'Number of buildings',
@@ -318,6 +343,17 @@ def load_app_state():
318
  loaded_state = pickle.load(fileObj)
319
  load_from_state(loaded_state)
320
 
 
 
 
 
 
 
 
 
 
 
 
321
 
322
  def building_colors(feature):
323
  ds_to_color = {0: 'lavender', 1:'violet',2:'fuchsia',3:'indigo',4:'darkslateblue',5:'black'}
@@ -328,7 +364,7 @@ def building_colors(feature):
328
  occupancy = feature['properties']['occupancy']
329
  normal_color = 'green' if occupancy == 'Hea' else 'blue'
330
  #return {'fillColor': 'black', 'color': 'red' if hospital_access == False else normal_color}
331
- return {'fillColor': 'black', 'color': 'green' if has_power else 'red'}
332
 
333
  def building_click_handler(event=None, feature=None, id=None, properties=None):
334
  layers.value['map_info_detail'].set(properties)
@@ -502,9 +538,18 @@ def create_map_layer(df, name):
502
  map_layer= ipyleaflet.MarkerCluster(markers=markers,
503
  disable_clustering_at_zoom=5)
504
 
505
-
 
 
 
 
 
506
  else:
507
- map_layer = ipyleaflet.GeoData(geo_dataframe = df)
 
 
 
 
508
  layers.value['layers'][name]['map_layer'].set(map_layer)
509
  layers.value['layers'][name]['force_render'].set(False)
510
  return map_layer
@@ -950,7 +995,7 @@ def MapViewer():
950
  @solara.component
951
  def ExecutePanel():
952
 
953
-
954
  execute_counter, set_execute_counter = solara.use_state(0)
955
  execute_btn_disabled, set_execute_btn_disabled = solara.use_state(False)
956
  execute_error = solara.reactive("")
@@ -977,6 +1022,13 @@ def ExecutePanel():
977
  missing += list(set(["road edges","road nodes","intensity"]) - existing_layers)
978
  if "building" in infra:
979
  missing += list(set(["landuse","building","household","individual","intensity","vulnerability"]) - existing_layers)
 
 
 
 
 
 
 
980
 
981
  if infra == []:
982
  missing += ['You should select at least one of power, road or building']
@@ -1071,14 +1123,28 @@ def ExecutePanel():
1071
  buildings_freqincome = buildings[['bldid']].merge(freqincome,on='bldid',how='left')
1072
  buildings['freqincome'] = buildings_freqincome['freqincome']
1073
  print('policies',policies)
1074
- df_bld_hazard = compute(
1075
- landuse,
1076
- buildings,
1077
- household,
1078
- individual,
1079
- intensity,
1080
- fragility if layers.value['hazard'].value == "earthquake" else vulnerability,
1081
- layers.value['hazard'].value,policies=policies)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1082
  buildings['ds'] = list(df_bld_hazard['ds'])
1083
 
1084
  return buildings
@@ -1111,25 +1177,40 @@ def ExecutePanel():
1111
  is_ready, missing = is_ready_to_run(layers.value['infra'].value, layers.value['hazard'].value)
1112
  if not is_ready:
1113
  raise Exception(f'Missing {missing}')
1114
-
1115
- if 'power' in layers.value['infra'].value:
1116
- nodes, buildings, household = execute_power()
1117
- layers.value['layers']['power nodes']['data'].set(nodes)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1118
  layers.value['layers']['building']['data'].set(buildings)
1119
- layers.value['layers']['household']['data'].set(household)
1120
- if 'road' in layers.value['infra'].value:
1121
- edges, buildings, household, individual = execute_road()
1122
- layers.value['layers']['road edges']['data'].set(edges)
1123
- layers.value['layers']['building']['data'].set(buildings)
1124
- layers.value['layers']['household']['data'].set(household)
1125
- layers.value['layers']['individual']['data'].set(individual)
1126
- if 'building' in layers.value['infra'].value:
1127
- buildings = execute_building()
1128
- layers.value['layers']['building']['data'].set(buildings)
1129
-
1130
- buildings = execute_metric()
1131
- layers.value['layers']['building']['data'].set(buildings)
1132
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1133
  # trigger render event
1134
  layers.value['render_count'].set(layers.value['render_count'].value + 1)
1135
  if 'power' in layers.value['infra'].value:
@@ -1154,7 +1235,13 @@ def ExecutePanel():
1154
  solara.ToggleButtonsMultiple(value=layers.value['infra'].value, on_value=layers.value['infra'].set, values=["building","power","road"])
1155
  solara.Markdown("#### Hazard")
1156
  with solara.Row(justify="left"):
1157
- solara.ToggleButtonsSingle(value=layers.value['hazard'].value, on_value=layers.value['hazard'].set, values=["earthquake","flood"])
 
 
 
 
 
 
1158
  with solara.Tooltip("Building-level metrics will be increased by 25% and 50% for medium and low"):
1159
  solara.Markdown("#### Implementation Capacity Score")
1160
  with solara.Row(justify="left"):
@@ -1180,8 +1267,10 @@ def ExecutePanel():
1180
 
1181
  if result.state in [solara.ResultState.RUNNING, solara.ResultState.WAITING]:
1182
  set_execute_btn_disabled(True)
 
1183
  solara.ProgressLinear(value=True)
1184
  else:
 
1185
  set_execute_btn_disabled(False)
1186
  solara.ProgressLinear(value=False)
1187
 
 
21
  #logging.basicConfig(stream=sys.stderr, level=logging.INFO)
22
  import pickle
23
  import datetime
24
+ from .settings import storage, landslide_max_trials
25
  from ..backend.engine import compute, compute_power_infra, compute_road_infra, calculate_metrics
26
  from ..backend.utils import building_preprocess, identity_preprocess
27
  from .utilities import S3FileBrowser, extension_list, extension_list_w_dots
 
30
  layers = solara.reactive({
31
  'infra': solara.reactive(["building"]),
32
  'hazard': solara.reactive("flood"),
33
+ 'hazard_list': ["earthquake","flood","landslide"],
34
  'datetime_analysis': datetime.datetime.utcnow(),
35
  'road_water_height_threshold': solara.reactive(0.3),
36
+ 'landslide_trigger_level': solara.reactive('moderate'),
37
+ 'landslide_trigger_level_list': ['minor','moderate','severe'],
38
  'dialog_message_to_be_shown': solara.reactive(None),
39
  'version': '0.2.3',
40
  'layers' : {
41
+ 'landslide fragility': {
42
+ 'render_order': 0,
43
+ 'map_info_tooltip': 'Number of landslide fragility records',
44
+ 'data': solara.reactive(None),
45
+ 'map_layer': solara.reactive(None),
46
+ 'force_render': solara.reactive(False),
47
+ 'visible': solara.reactive(False),
48
+ 'pre_processing': identity_preprocess,
49
+ 'extra_cols': {},
50
+ 'attributes_required': [set(['expstr','susceptibility','minor','moderate','severe'])],
51
+ 'attributes': [set(['expstr','susceptibility','minor','moderate','severe'])]},
52
+ 'landslide susceptibility': {
53
+ 'render_order': 21,
54
+ 'map_info_tooltip': 'Number of zones in the landslide susceptibility map',
55
+ 'data': solara.reactive(None),
56
+ 'map_layer': solara.reactive(None),
57
+ 'force_render': solara.reactive(False),
58
+ 'visible': solara.reactive(False),
59
+ 'pre_processing': identity_preprocess,
60
+ 'extra_cols': {},
61
+ 'attributes_required': [set(['id','susceptibility','geometry'])],
62
+ 'attributes': [set(['id','susceptibility','geometry'])]},
63
  'building': {
64
  'render_order': 50,
65
  'map_info_tooltip': 'Number of buildings',
 
343
  loaded_state = pickle.load(fileObj)
344
  load_from_state(loaded_state)
345
 
346
+ def generic_layer_colors(feature):
347
+ return None
348
+
349
+ def susceptibility_colors(feature):
350
+ susceptibility = feature['properties']['susceptibility']
351
+ s_to_color = {'low': 'green', 'medium':'orange','high': 'red'}
352
+ return {'fillColor': s_to_color[susceptibility], 'color': s_to_color[susceptibility]}
353
+
354
+ def generic_layer_click_handler(event=None, feature=None, id=None, properties=None):
355
+ layers.value['map_info_detail'].set(properties)
356
+ layers.value['map_info_button'].set("detail")
357
 
358
  def building_colors(feature):
359
  ds_to_color = {0: 'lavender', 1:'violet',2:'fuchsia',3:'indigo',4:'darkslateblue',5:'black'}
 
364
  occupancy = feature['properties']['occupancy']
365
  normal_color = 'green' if occupancy == 'Hea' else 'blue'
366
  #return {'fillColor': 'black', 'color': 'red' if hospital_access == False else normal_color}
367
+ return {'fillColor': 'black', 'color': 'green' if ds == 0 else 'red'}
368
 
369
  def building_click_handler(event=None, feature=None, id=None, properties=None):
370
  layers.value['map_info_detail'].set(properties)
 
538
  map_layer= ipyleaflet.MarkerCluster(markers=markers,
539
  disable_clustering_at_zoom=5)
540
 
541
+ elif name == 'landslide susceptibility':
542
+ map_layer = ipyleaflet.GeoJSON(data = json.loads(df.to_json()),
543
+ style={'opacity': 1, 'dashArray': '9', 'fillOpacity': 0.5, 'weight': 1},
544
+ hover_style={'color': 'white', 'dashArray': '0', 'fillOpacity': 0.5},
545
+ style_callback=susceptibility_colors)
546
+ map_layer.on_click(generic_layer_click_handler)
547
  else:
548
+ map_layer = ipyleaflet.GeoJSON(data = json.loads(df.to_json()),
549
+ style={'opacity': 1, 'dashArray': '9', 'fillOpacity': 0.5, 'weight': 1},
550
+ hover_style={'color': 'white', 'dashArray': '0', 'fillOpacity': 0.5},
551
+ style_callback=generic_layer_colors)
552
+ map_layer.on_click(generic_layer_click_handler)
553
  layers.value['layers'][name]['map_layer'].set(map_layer)
554
  layers.value['layers'][name]['force_render'].set(False)
555
  return map_layer
 
995
  @solara.component
996
  def ExecutePanel():
997
 
998
+ progress_message, set_progress_message = solara.use_state("")
999
  execute_counter, set_execute_counter = solara.use_state(0)
1000
  execute_btn_disabled, set_execute_btn_disabled = solara.use_state(False)
1001
  execute_error = solara.reactive("")
 
1022
  missing += list(set(["road edges","road nodes","intensity"]) - existing_layers)
1023
  if "building" in infra:
1024
  missing += list(set(["landuse","building","household","individual","intensity","vulnerability"]) - existing_layers)
1025
+ elif hazard == "landslide":
1026
+ if "power" in infra:
1027
+ missing += list(set(["power edges","power nodes","landslide fragility","landslide susceptibility"]) - existing_layers)
1028
+ if "road" in infra:
1029
+ missing += list(set(["road edges","road nodes","landslide fragility","landslide susceptibility"]) - existing_layers)
1030
+ if "building" in infra:
1031
+ missing += list(set(["landuse","building","household","individual","landslide fragility","landslide susceptibility"]) - existing_layers)
1032
 
1033
  if infra == []:
1034
  missing += ['You should select at least one of power, road or building']
 
1123
  buildings_freqincome = buildings[['bldid']].merge(freqincome,on='bldid',how='left')
1124
  buildings['freqincome'] = buildings_freqincome['freqincome']
1125
  print('policies',policies)
1126
+ if layers.value['hazard'].value == 'landslide':
1127
+ fragility = layers.value['layers']['landslide fragility']['data'].value
1128
+ intensity = layers.value['layers']['landslide susceptibility']['data'].value
1129
+ trigger_level= layers.value['landslide_trigger_level'].value
1130
+ df_bld_hazard = compute(
1131
+ landuse,
1132
+ buildings,
1133
+ household,
1134
+ individual,
1135
+ intensity,
1136
+ fragility[['expstr','susceptibility',trigger_level]].rename(columns={trigger_level:'collapse_probability'}),
1137
+ layers.value['hazard'].value,
1138
+ policies=policies)
1139
+ else:
1140
+ df_bld_hazard = compute(
1141
+ landuse,
1142
+ buildings,
1143
+ household,
1144
+ individual,
1145
+ intensity,
1146
+ fragility if layers.value['hazard'].value == "earthquake" else vulnerability,
1147
+ layers.value['hazard'].value, policies=policies)
1148
  buildings['ds'] = list(df_bld_hazard['ds'])
1149
 
1150
  return buildings
 
1177
  is_ready, missing = is_ready_to_run(layers.value['infra'].value, layers.value['hazard'].value)
1178
  if not is_ready:
1179
  raise Exception(f'Missing {missing}')
1180
+ max_trials = landslide_max_trials.value if layers.value['hazard'].value == "landslide" else 1
1181
+ for trial in range(1,max_trials+1):
1182
+ set_progress_message(f'Monte-Carlo trial {trial}/{max_trials}...')
1183
+ if 'power' in layers.value['infra'].value:
1184
+ nodes, buildings, household = execute_power()
1185
+ layers.value['layers']['power nodes']['data'].set(nodes)
1186
+ layers.value['layers']['building']['data'].set(buildings)
1187
+ layers.value['layers']['household']['data'].set(household)
1188
+ if 'road' in layers.value['infra'].value:
1189
+ edges, buildings, household, individual = execute_road()
1190
+ layers.value['layers']['road edges']['data'].set(edges)
1191
+ layers.value['layers']['building']['data'].set(buildings)
1192
+ layers.value['layers']['household']['data'].set(household)
1193
+ layers.value['layers']['individual']['data'].set(individual)
1194
+ if 'building' in layers.value['infra'].value:
1195
+ buildings = execute_building()
1196
+ layers.value['layers']['building']['data'].set(buildings)
1197
+
1198
+ buildings = execute_metric()
1199
  layers.value['layers']['building']['data'].set(buildings)
 
 
 
 
 
 
 
 
 
 
 
 
 
1200
 
1201
+ # Taking average without storing intermediate values
1202
+ # averaga_n = [(n-1)*average_(n-1) + value_n]/2
1203
+ if trial == 1:
1204
+ avg_metrics = buildings[layers.value['metrics'].keys()]
1205
+ else:
1206
+ avg_metrics = ((trial-1) * avg_metrics + buildings[layers.value['metrics'].keys()])/trial
1207
+ for metric in layers.value['metrics'].keys():
1208
+ print('average', metric, avg_metrics[metric].sum())
1209
+
1210
+ for metric in layers.value['metrics'].keys():
1211
+ buildings[metric] = list(avg_metrics[metric])
1212
+ layers.value['metrics'][metric]['value'] = avg_metrics[metric].sum()
1213
+ set_progress_message('')
1214
  # trigger render event
1215
  layers.value['render_count'].set(layers.value['render_count'].value + 1)
1216
  if 'power' in layers.value['infra'].value:
 
1235
  solara.ToggleButtonsMultiple(value=layers.value['infra'].value, on_value=layers.value['infra'].set, values=["building","power","road"])
1236
  solara.Markdown("#### Hazard")
1237
  with solara.Row(justify="left"):
1238
+ solara.ToggleButtonsSingle(value=layers.value['hazard'].value, on_value=layers.value['hazard'].set, values=layers.value['hazard_list'])
1239
+ if layers.value['hazard'].value == 'landslide':
1240
+ solara.Markdown("#### Landslide trigger level")
1241
+ with solara.Row(justify="left"):
1242
+ solara.ToggleButtonsSingle(value=layers.value['landslide_trigger_level'].value,
1243
+ on_value=layers.value['landslide_trigger_level'].set,
1244
+ values=layers.value['landslide_trigger_level_list'])
1245
  with solara.Tooltip("Building-level metrics will be increased by 25% and 50% for medium and low"):
1246
  solara.Markdown("#### Implementation Capacity Score")
1247
  with solara.Row(justify="left"):
 
1267
 
1268
  if result.state in [solara.ResultState.RUNNING, solara.ResultState.WAITING]:
1269
  set_execute_btn_disabled(True)
1270
+ solara.Text(progress_message)
1271
  solara.ProgressLinear(value=True)
1272
  else:
1273
+ solara.Text("Spacer", style={"visibility": "hidden"})
1274
  set_execute_btn_disabled(False)
1275
  solara.ProgressLinear(value=False)
1276
 
tomorrowcities/pages/settings.py CHANGED
@@ -3,7 +3,6 @@ from typing import Optional, cast
3
  import pickle
4
  import boto3
5
  import os
6
-
7
  from . import user
8
 
9
  class S3Storage:
@@ -86,6 +85,7 @@ def revive_storage():
86
  os.environ['bucket_name'])
87
 
88
  storage = solara.reactive(revive_storage())
 
89
 
90
  def storage_control(aws_access_key_id: str, aws_secret_access_key: str, region_name: str, bucket_name: str):
91
  storage.value = S3Storage(aws_access_key_id, aws_secret_access_key, region_name, bucket_name)
@@ -164,4 +164,7 @@ def Page(name: Optional[str] = None, page: int = 0, page_size=100):
164
  # StorageViewer()
165
 
166
  if err_message != '':
167
- solara.Error(err_message)
 
 
 
 
3
  import pickle
4
  import boto3
5
  import os
 
6
  from . import user
7
 
8
  class S3Storage:
 
85
  os.environ['bucket_name'])
86
 
87
  storage = solara.reactive(revive_storage())
88
+ landslide_max_trials = solara.reactive(5)
89
 
90
  def storage_control(aws_access_key_id: str, aws_secret_access_key: str, region_name: str, bucket_name: str):
91
  storage.value = S3Storage(aws_access_key_id, aws_secret_access_key, region_name, bucket_name)
 
164
  # StorageViewer()
165
 
166
  if err_message != '':
167
+ solara.Error(err_message)
168
+
169
+ with solara.Card(title='Landslide Parameters',subtitle='Choose the parameters for the landslide simulation'):
170
+ solara.SliderInt(label='Number of Monte-Carlo Trials', value=landslide_max_trials, min=1,max=100)