hkayabilisim commited on
Commit
00ba576
·
1 Parent(s): fe20df4

Completed (eq,fl,ls) x (bld,pwr,road) combinations

Browse files
tomorrowcities/backend/engine.py CHANGED
@@ -45,17 +45,40 @@ def compute_road_infra(buildings, household, individual,
45
  gdf_buildings = gpd.sjoin_nearest(gdf_buildings,gdf_nodes,
46
  how='left', rsuffix='road_node',distance_col='road_node_distance')
47
 
48
- if hazard in ['flood', 'debris']:
49
- roads_with_width = gdf_edges['geometry'].buffer(threshold_flood_distance)
50
- for i, road in enumerate(roads_with_width):
51
- within_ims = gdf_intensity.clip(road)
52
- if len(within_ims) > 0:
53
- max_im = within_ims['im'].max()
54
- else:
55
- max_im = 0
56
- gdf_edges.loc[i,'im'] = max_im
57
- gdf_edges.loc[gdf_edges['im'] > road_water_height_threshold, 'ds'] = 1
58
- gdf_edges.loc[gdf_edges['im'] > road_water_height_threshold, 'is_damaged'] = True
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
  elif hazard == 'earthquake':
60
  fragility = fragility.rename(columns={"med_slight": "med_ds1",
61
  "med_moderate": "med_ds2",
@@ -124,11 +147,18 @@ def compute_road_infra(buildings, household, individual,
124
  # For each individual, find the closest road node (closest) of the
125
  # household and the facility
126
 
 
 
 
 
 
 
127
  individual_w_nodes = individual.merge(household_w_node_id[['hhid','node_id']],on='hhid',how='left')\
128
  .rename(columns={'node_id':'household_node_id'})\
129
  .merge(gdf_buildings[['bldid','node_id']],how='left',left_on='indivfacid',right_on='bldid')\
130
  .rename(columns={'node_id':'facility_node_id'})
131
-
 
132
  # Calculate distances between all nodes in the damaged network
133
  shortest_distance = nx.shortest_path_length(G_dmg)
134
 
@@ -140,11 +170,13 @@ def compute_road_infra(buildings, household, individual,
140
  connection_dict[source][target] = True
141
 
142
  # Based on connectivity, fill-in facillity_access attribute in the individual layer
 
143
  individual_w_nodes['facility_access'] = individual_w_nodes.apply(lambda x: x['facility_node_id'] in connection_dict[x['household_node_id']].keys(),axis=1)
144
 
145
  return gdf_edges['ds'], gdf_edges['is_damaged'], gdf_buildings['node_id'], gdf_buildings['hospital_access'], household_w_node_id['node_id'], household_w_node_id['hospital_access'], individual_w_nodes['facility_access']
146
 
147
- def compute_power_infra(buildings, household, nodes,edges,intensity,fragility,hazard):
 
148
  print('Computing power infrastructure')
149
  print(nodes.head())
150
  print(edges.head())
@@ -192,7 +224,8 @@ def compute_power_infra(buildings, household, nodes,edges,intensity,fragility,ha
192
  "beta_moderate": "beta_ds2",
193
  "beta_extensive": "beta_ds3",
194
  "beta_complete": "beta_ds4"})
195
- gdf_nodes = gdf_nodes.merge(fragility, how='left',left_on='eq_vuln',right_on='vuln_string')
 
196
  nulls = gdf_nodes['med_ds1'].isna()
197
  gdf_nodes.loc[nulls, ['med_ds1','med_ds2','med_ds3','med_ds4']] = [99999,99999,99999,99999]
198
  gdf_nodes.loc[nulls, ['beta_ds1','beta_ds2','beta_ds3','beta_ds4']] = [1,1,1,1]
@@ -209,6 +242,39 @@ def compute_power_infra(buildings, household, nodes,edges,intensity,fragility,ha
209
  gdf_nodes[f'ds_{i}'] = np.abs(gdf_nodes[f'prob_ds{i-1}'] - gdf_nodes[f'prob_ds{i}'])
210
  df_ds = gdf_nodes[['ds_1','ds_2','ds_3','ds_4','ds_5']]
211
  gdf_nodes['ds'] = df_ds.idxmax(axis='columns').str.extract(r'ds_([0-9]+)').astype('int') - 1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
212
 
213
  # All Nodes
214
  all_nodes = set(gdf_nodes['node_id'])
@@ -346,8 +412,28 @@ def compute(gdf_landuse, gdf_buildings, df_household, df_individual,gdf_intensit
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
 
45
  gdf_buildings = gpd.sjoin_nearest(gdf_buildings,gdf_nodes,
46
  how='left', rsuffix='road_node',distance_col='road_node_distance')
47
 
48
+ if hazard in ['flood', 'debris','landslide']:
49
+ gdf_edges = gpd.sjoin_nearest(gdf_edges, gdf_intensity, how='left',
50
+ rsuffix='intensity',distance_col='distance')
51
+ # TODO: sjoin_nearest or the approach below: compare
52
+ #roads_with_width = gdf_edges['geometry'].buffer(threshold_flood_distance)
53
+ #for i, road in enumerate(roads_with_width):
54
+ # print(i)
55
+ # within_ims = gdf_intensity.clip(road)
56
+ # if len(within_ims) > 0:
57
+ # max_im = within_ims['im'].max()
58
+ # else:
59
+ # max_im = 0
60
+ # gdf_edges.loc[i,'im'] = max_im
61
+ if hazard == 'landslide':
62
+ print('before')
63
+ print(gdf_edges.loc[0])
64
+ gdf_edges['susceptibility'] = 'low'
65
+ gdf_edges.loc[gdf_edges['im'] == 2.0, 'susceptibility'] = 'medium'
66
+ gdf_edges.loc[gdf_edges['im'] == 3.0, 'susceptibility'] = 'high'
67
+
68
+ fragility['landslide_expstr'] = fragility['expstr'].astype(str) + "+"+ fragility["susceptibility"].astype(str)
69
+ gdf_edges['landslide_expstr'] = 'roads'
70
+ gdf_edges['landslide_expstr'] = gdf_edges['landslide_expstr'] + "+" + gdf_edges['susceptibility'].astype(str)
71
+ gdf_edges = gdf_edges.merge(fragility, on='landslide_expstr', how='left')
72
+ gdf_edges['ds'] = DS_NO
73
+ gdf_edges['rnd'] = np.random.random((len(gdf_edges),1))
74
+ collapsed_idx = (gdf_edges['rnd'] < gdf_edges['collapse_probability'])
75
+ gdf_edges.loc[collapsed_idx, 'ds'] = DS_COMPLETE
76
+ gdf_edges.loc[collapsed_idx, 'is_damaged'] = True
77
+ print('after')
78
+ print(gdf_edges.loc[0])
79
+ else:
80
+ gdf_edges.loc[gdf_edges['im'] > road_water_height_threshold, 'ds'] = 1
81
+ gdf_edges.loc[gdf_edges['im'] > road_water_height_threshold, 'is_damaged'] = True
82
  elif hazard == 'earthquake':
83
  fragility = fragility.rename(columns={"med_slight": "med_ds1",
84
  "med_moderate": "med_ds2",
 
147
  # For each individual, find the closest road node (closest) of the
148
  # household and the facility
149
 
150
+ print('individua')
151
+ print(individual)
152
+ print('household_w_node_id')
153
+ print(household_w_node_id)
154
+ print('gdf_buildings')
155
+ print(gdf_buildings)
156
  individual_w_nodes = individual.merge(household_w_node_id[['hhid','node_id']],on='hhid',how='left')\
157
  .rename(columns={'node_id':'household_node_id'})\
158
  .merge(gdf_buildings[['bldid','node_id']],how='left',left_on='indivfacid',right_on='bldid')\
159
  .rename(columns={'node_id':'facility_node_id'})
160
+ print('individual_w_nodes')
161
+ print(individual_w_nodes)
162
  # Calculate distances between all nodes in the damaged network
163
  shortest_distance = nx.shortest_path_length(G_dmg)
164
 
 
170
  connection_dict[source][target] = True
171
 
172
  # Based on connectivity, fill-in facillity_access attribute in the individual layer
173
+ print(individual_w_nodes)
174
  individual_w_nodes['facility_access'] = individual_w_nodes.apply(lambda x: x['facility_node_id'] in connection_dict[x['household_node_id']].keys(),axis=1)
175
 
176
  return gdf_edges['ds'], gdf_edges['is_damaged'], gdf_buildings['node_id'], gdf_buildings['hospital_access'], household_w_node_id['node_id'], household_w_node_id['hospital_access'], individual_w_nodes['facility_access']
177
 
178
+ def compute_power_infra(buildings, household, nodes,edges,intensity,fragility,hazard,
179
+ threshold_flood, threshold_flood_distance):
180
  print('Computing power infrastructure')
181
  print(nodes.head())
182
  print(edges.head())
 
224
  "beta_moderate": "beta_ds2",
225
  "beta_extensive": "beta_ds3",
226
  "beta_complete": "beta_ds4"})
227
+ #gdf_nodes = gdf_nodes.merge(fragility, how='left',left_on='eq_vuln',right_on='vuln_string')
228
+ gdf_nodes = gdf_nodes.merge(fragility, how='left',left_on='eq_frgl',right_on='vuln_string')
229
  nulls = gdf_nodes['med_ds1'].isna()
230
  gdf_nodes.loc[nulls, ['med_ds1','med_ds2','med_ds3','med_ds4']] = [99999,99999,99999,99999]
231
  gdf_nodes.loc[nulls, ['beta_ds1','beta_ds2','beta_ds3','beta_ds4']] = [1,1,1,1]
 
242
  gdf_nodes[f'ds_{i}'] = np.abs(gdf_nodes[f'prob_ds{i-1}'] - gdf_nodes[f'prob_ds{i}'])
243
  df_ds = gdf_nodes[['ds_1','ds_2','ds_3','ds_4','ds_5']]
244
  gdf_nodes['ds'] = df_ds.idxmax(axis='columns').str.extract(r'ds_([0-9]+)').astype('int') - 1
245
+ elif hazard == 'landslide':
246
+ print(gdf_nodes.loc[0])
247
+ gdf_nodes['rnd'] = np.random.random((len(gdf_nodes),1))
248
+ if 'ls_susceptibility' in gdf_nodes.columns:
249
+ gdf_nodes['susceptibility'] = gdf_nodes['ls_susceptibility']
250
+ else:
251
+ gdf_nodes['susceptibility'] = 'low'
252
+ gdf_nodes.loc[gdf_nodes['im'] == 2.0, 'susceptibility'] = 'medium'
253
+ gdf_nodes.loc[gdf_nodes['im'] == 3.0, 'susceptibility'] = 'high'
254
+ fragility['landslide_expstr'] = fragility['expstr'].astype(str) + "+"+ fragility["susceptibility"].astype(str)
255
+ gdf_nodes['landslide_expstr'] = gdf_nodes['ls_frgl'].astype(str) + "+" \
256
+ + gdf_nodes['susceptibility'].astype(str)
257
+ gdf_nodes = gdf_nodes.merge(fragility, on='landslide_expstr', how='left')
258
+ gdf_nodes['ds'] = DS_NO
259
+ collapsed_idx = (gdf_nodes['rnd'] < gdf_nodes['collapse_probability'])
260
+ gdf_nodes.loc[collapsed_idx, 'ds'] = DS_COMPLETE
261
+ print(gdf_nodes.loc[0])
262
+ elif hazard == 'flood':
263
+ away_from_flood = gdf_nodes['distance'] > threshold_flood_distance
264
+ print('threshold_flood_distance',threshold_flood_distance)
265
+ print('number of distant buildings', len(gdf_nodes.loc[away_from_flood, 'im']))
266
+ gdf_nodes.loc[away_from_flood, 'im'] = 0
267
+
268
+
269
+ gdf_nodes = gdf_nodes.merge(fragility, left_on='fl_vuln', right_on='expstr', how='left')
270
+ x = np.array([0,0.5,1,1.5,2,3,4,5,6])
271
+ y = gdf_nodes[['hw0','hw0_5','hw1','hw1_5','hw2','hw3','hw4','hw5','hw6']].to_numpy()
272
+ xnew = gdf_nodes['im'].to_numpy()
273
+ flood_mapping = interp1d(x,y,axis=1,kind='linear',bounds_error=False, fill_value=(0,1))
274
+ # TODO: find another way for vectorized interpolate
275
+ gdf_nodes['fl_prob'] = np.diag(flood_mapping(xnew))
276
+ gdf_nodes['ds'] = 0
277
+ gdf_nodes.loc[gdf_nodes['fl_prob'] > threshold_flood,'ds'] = 1
278
 
279
  # All Nodes
280
  all_nodes = set(gdf_nodes['node_id'])
 
412
  gdf_building_intensity['rnd'] = np.random.random((len(gdf_building_intensity),1))
413
 
414
  if hazard_type == "landslide":
415
+ print('----------up side down prev', gdf_building_intensity.shape)
416
+ print(pd.unique(gdf_building_intensity['im']))
417
+ gdf_building_intensity['susceptibility'] = 'low'
418
+ gdf_building_intensity.loc[gdf_building_intensity['im'] == 2.0, 'susceptibility'] = 'medium'
419
+ gdf_building_intensity.loc[gdf_building_intensity['im'] == 3.0, 'susceptibility'] = 'high'
420
+ print(gdf_building_intensity.loc[0])
421
+ print(gdf_building_intensity.columns)
422
+ print(df_hazard.loc[0])
423
+ df_hazard['landslide_expstr'] = df_hazard['expstr'].astype(str) +"+"+ df_hazard["susceptibility"].astype(str)
424
+
425
+ gdf_building_intensity['landslide_expstr'] = gdf_building_intensity['material'].astype(str) + "+" \
426
+ + gdf_building_intensity['code_level'].astype(str) + "+" \
427
+ + gdf_building_intensity["susceptibility"].astype(str)
428
+ print('x1', gdf_building_intensity.columns)
429
+ print('x2', df_hazard.columns)
430
+
431
+ print(len(gdf_building_intensity))
432
  gdf_building_collapse_prob = gdf_building_intensity.merge(df_hazard,
433
+ on='landslide_expstr', how='left')
434
+ print('----------up side down ', gdf_building_collapse_prob.shape)
435
+ print(gdf_building_collapse_prob.loc[0])
436
+ print(len(gdf_building_collapse_prob))
437
  gdf_building_collapse_prob['ds'] = DS_NO
438
  collapsed_idx = (gdf_building_collapse_prob['rnd'] < gdf_building_collapse_prob['collapse_probability'])
439
  gdf_building_collapse_prob.loc[collapsed_idx, 'ds'] = DS_COLLAPSED
tomorrowcities/components/article.py CHANGED
@@ -6,9 +6,9 @@ from ..data import articles
6
  @solara.component
7
  def ArticleCard(name):
8
  article = articles[name]
9
- with rv.Card(max_width="400px") as main:
10
  with solara.Link(f"/docs/{name}"):
11
- rv.Img(height="250", src=article.image_url)
12
  rv.CardTitle(children=[article.title])
13
  with rv.CardText():
14
  solara.Markdown(article.description)
@@ -21,7 +21,7 @@ def ArticleCard(name):
21
  def Overview():
22
  with solara.ColumnsResponsive(12) as main:
23
  with solara.Card():
24
- with solara.ColumnsResponsive(12, small=6, large=4):
25
  for name in articles:
26
  ArticleCard(name)
27
  return main
 
6
  @solara.component
7
  def ArticleCard(name):
8
  article = articles[name]
9
+ with rv.Card(max_width="300px") as main:
10
  with solara.Link(f"/docs/{name}"):
11
+ rv.Img(height="150", src=article.image_url)
12
  rv.CardTitle(children=[article.title])
13
  with rv.CardText():
14
  solara.Markdown(article.description)
 
21
  def Overview():
22
  with solara.ColumnsResponsive(12) as main:
23
  with solara.Card():
24
+ with solara.ColumnsResponsive(12, small=6, large=2):
25
  for name in articles:
26
  ArticleCard(name)
27
  return main
tomorrowcities/content/articles/data.md CHANGED
@@ -43,7 +43,8 @@ in the GeoTIFF are labelled such as "PGA", "SA 0.3", "SA 1", etc.
43
 
44
 
45
  ## Layers
46
- The layers supported by tomorrowcities are listed below. In this section, we will cover all of them and provide information so that the users are able to generate data compatible to web application.
 
47
 
48
  * land use
49
  * building
@@ -55,6 +56,17 @@ The layers supported by tomorrowcities are listed below. In this section, we wi
55
  * power nodes
56
  * power edges
57
 
 
 
 
 
 
 
 
 
 
 
 
58
  ### Buildings
59
  Buildings are the core component of visioning scenarios. The features of the building with some example data are shown below:
60
 
@@ -86,6 +98,26 @@ where
86
  * **nind (integer)** is the number of individuals living in the household
87
  * **commfacid (integer)** is the building identifier of the community facility. In Tomorrow's Cities, it is used to define the hospital associated with the household.
88
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
  ### Intensity Measures
90
  Whether it is flood, debris or earthquake, every hazard map should contain at least two properties: a point geometry and intensity measure denotes by 'im'. The data can be provided via GeoTIFF or GeoJSON format. TIFF files should contain CRS
91
  information so that the engine could map the coordinates to a common CRS to conduct calculations.
 
43
 
44
 
45
  ## Layers
46
+ The layers supported by tomorrowcities are listed below. In this section, we will cover all of them and provide information so that the users are able to generate data compatible to web application. Unless otherwise
47
+ mentioned, all geo-spatial layers have WGS 84 coordinate reference system with EPSG:4326.
48
 
49
  * land use
50
  * building
 
56
  * power nodes
57
  * power edges
58
 
59
+ ### Landuse
60
+ Landuse plan is presented as a GeoJSON format whose attributes are given below:
61
+
62
+
63
+ |population|status|zone|densitycap|luf|landuse_lu|area|zoneid|floorarear|setback|avgincome|
64
+ |----------|------|----|----------|---|----------|----|------|----------|-------|---------|
65
+ 0|None |Agricultural Zone |0.0 |Agricultural Zone |Agricultural Zone |4099.24144134 |4 |0.0 |0.0 |None|
66
+ 0| None |Forest Zone |0.0 |Forest Zone |Forest Zone |30843.9849839 |5 |0.0 |0.0 |None|
67
+ 7081 |None |Residential Very Low Density |5.0 |Residential-Very Low Density | Agriculture Cum Resedential |1416.16357154 |226 |0.0 |0.0 |lowIncome|
68
+
69
+
70
  ### Buildings
71
  Buildings are the core component of visioning scenarios. The features of the building with some example data are shown below:
72
 
 
98
  * **nind (integer)** is the number of individuals living in the household
99
  * **commfacid (integer)** is the building identifier of the community facility. In Tomorrow's Cities, it is used to define the hospital associated with the household.
100
 
101
+ ### Individuals
102
+ Individual layer is a tabular data which can be stored in Excel or JSON format.
103
+ The attributes are:
104
+
105
+ |hhid|individ|gender|age|head|eduattstat|indivfacid|
106
+ |----|-------|------|---|----|----------|----------|
107
+ |24448| 1| 2| 8| 1| 3| -1|
108
+ |1 |5552 |2 |2 |8 |1 |4 |-1 |
109
+ |2 |31586 |3 |2 |9 |1 |5 |-1 |
110
+
111
+ where
112
+
113
+ * **hhid** refers to household identifier where the individual lives in.
114
+ * **individ** is the unique individual identifier
115
+ * **gender** is a categorical variable for gender: 1: male, 2:female
116
+ * **age** is the age category
117
+ * **head** is a binary feature indicating that the individual is the head of the household
118
+ * **eduattstat** is the education level
119
+ * **indivfacid** is the facility (school or workspace) that the individual is associated with
120
+
121
  ### Intensity Measures
122
  Whether it is flood, debris or earthquake, every hazard map should contain at least two properties: a point geometry and intensity measure denotes by 'im'. The data can be provided via GeoTIFF or GeoJSON format. TIFF files should contain CRS
123
  information so that the engine could map the coordinates to a common CRS to conduct calculations.
tomorrowcities/pages/engine.py CHANGED
@@ -48,18 +48,7 @@ layers = solara.reactive({
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',
@@ -159,7 +148,7 @@ layers = solara.reactive({
159
  'visible': solara.reactive(False),
160
  'pre_processing': identity_preprocess,
161
  'extra_cols': {'ds': 0, 'is_damaged': False, 'is_operational': True},
162
- 'attributes_required': [set(['geometry', 'node_id', 'pwr_plant', 'n_bldgs', 'eq_vuln'])],
163
  'attributes': [set(['geometry', 'fltytype', 'strctype', 'utilfcltyc', 'indpnode', 'guid',
164
  'node_id', 'x_coord', 'y_coord', 'pwr_plant', 'serv_area', 'n_bldgs',
165
  'income', 'eq_vuln'])]},
@@ -346,11 +335,6 @@ def load_app_state():
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")
@@ -486,9 +470,12 @@ def create_map_layer(df, name):
486
  if name == "intensity":
487
  # Take the largest 500_000 values to display
488
  im_col = 'pga' if 'pga' in df.columns else 'im'
489
- df_limited = df.sort_values(by=im_col,ascending=False).head(500_000)
 
 
 
490
  locs = np.array([df_limited.geometry.y.to_list(), df_limited.geometry.x.to_list(), df_limited[im_col].to_list()]).transpose().tolist()
491
- map_layer = ipyleaflet.Heatmap(locations=locs, radius = 5)
492
  elif name == "landuse":
493
  map_layer = ipyleaflet.GeoJSON(data = json.loads(df.to_json()),
494
  style={'opacity': 1, 'dashArray': '9', 'fillOpacity': 0.5, 'weight': 1},
@@ -537,13 +524,7 @@ def create_map_layer(df, name):
537
  markers.append(marker)
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},
@@ -1017,23 +998,35 @@ def ExecutePanel():
1017
  missing += list(set(["landuse","building","household","individual","intensity","fragility"]) - existing_layers)
1018
  elif hazard == "flood":
1019
  if "power" in infra:
1020
- missing += list(set(["power edges","power nodes","intensity","power vulnerability"]) - existing_layers)
1021
  if "road" in infra:
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']
1035
  return missing == [], missing
1036
 
 
 
 
 
 
 
 
 
 
 
 
 
1037
 
1038
 
1039
  def execute_engine():
@@ -1047,6 +1040,10 @@ def ExecutePanel():
1047
  edges = layers.value['layers']['road edges']['data'].value
1048
  intensity = layers.value['layers']['intensity']['data'].value
1049
  fragility = layers.value['layers']['road fragility']['data'].value
 
 
 
 
1050
  hazard = layers.value['hazard'].value
1051
 
1052
  edges['ds'] = 0
@@ -1080,9 +1077,16 @@ def ExecutePanel():
1080
  nodes = layers.value['layers']['power nodes']['data'].value
1081
  edges = layers.value['layers']['power edges']['data'].value
1082
  intensity = layers.value['layers']['intensity']['data'].value
1083
- power_fragility = layers.value['layers']['power fragility']['data'].value
1084
  hazard = layers.value['hazard'].value
1085
 
 
 
 
 
 
 
 
1086
 
1087
  ds, is_damaged, is_operational, has_power, household_has_power, hospital_has_power = \
1088
  compute_power_infra(buildings,
@@ -1090,8 +1094,8 @@ def ExecutePanel():
1090
  nodes,
1091
  edges,
1092
  intensity,
1093
- power_fragility,
1094
- hazard)
1095
 
1096
  #power_node_df = dfs['Power Nodes'].copy()
1097
  nodes['ds'] = list(ds)
@@ -1124,7 +1128,6 @@ def ExecutePanel():
1124
  #print('policies',policies)
1125
  if layers.value['hazard'].value == 'landslide':
1126
  fragility = layers.value['layers']['landslide fragility']['data'].value
1127
- intensity = layers.value['layers']['landslide susceptibility']['data'].value
1128
  trigger_level= layers.value['landslide_trigger_level'].value
1129
  df_bld_hazard = compute(
1130
  landuse,
@@ -1180,9 +1183,15 @@ def ExecutePanel():
1180
  is_ready, missing = is_ready_to_run(layers.value['infra'].value, layers.value['hazard'].value)
1181
  if not is_ready:
1182
  raise Exception(f'Missing {missing}')
 
 
 
1183
  max_trials = landslide_max_trials.value if layers.value['hazard'].value == "landslide" else 1
1184
  for trial in range(1,max_trials+1):
1185
- set_progress_message('Running...')
 
 
 
1186
  if 'power' in layers.value['infra'].value:
1187
  nodes, buildings, household = execute_power()
1188
  layers.value['layers']['power nodes']['data'].set(nodes)
 
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','description'])]},
 
 
 
 
 
 
 
 
 
 
 
52
  'building': {
53
  'render_order': 50,
54
  'map_info_tooltip': 'Number of buildings',
 
148
  'visible': solara.reactive(False),
149
  'pre_processing': identity_preprocess,
150
  'extra_cols': {'ds': 0, 'is_damaged': False, 'is_operational': True},
151
+ 'attributes_required': [set(['geometry', 'node_id', 'pwr_plant', 'n_bldgs'])],
152
  'attributes': [set(['geometry', 'fltytype', 'strctype', 'utilfcltyc', 'indpnode', 'guid',
153
  'node_id', 'x_coord', 'y_coord', 'pwr_plant', 'serv_area', 'n_bldgs',
154
  'income', 'eq_vuln'])]},
 
335
  def generic_layer_colors(feature):
336
  return None
337
 
 
 
 
 
 
338
  def generic_layer_click_handler(event=None, feature=None, id=None, properties=None):
339
  layers.value['map_info_detail'].set(properties)
340
  layers.value['map_info_button'].set("detail")
 
470
  if name == "intensity":
471
  # Take the largest 500_000 values to display
472
  im_col = 'pga' if 'pga' in df.columns else 'im'
473
+ df_non_zero = df[df[im_col] > 0]
474
+ df_limited = df_non_zero.sample(min(len(df_non_zero),500_000))
475
+ df_limited[im_col] = df_limited[im_col] / df_limited[im_col].max()
476
+ #df_limited = df.sort_values(by=im_col,ascending=False).head(500_000)
477
  locs = np.array([df_limited.geometry.y.to_list(), df_limited.geometry.x.to_list(), df_limited[im_col].to_list()]).transpose().tolist()
478
+ map_layer = ipyleaflet.Heatmap(locations=locs, radius = 5, blur = 1)
479
  elif name == "landuse":
480
  map_layer = ipyleaflet.GeoJSON(data = json.loads(df.to_json()),
481
  style={'opacity': 1, 'dashArray': '9', 'fillOpacity': 0.5, 'weight': 1},
 
524
  markers.append(marker)
525
  map_layer= ipyleaflet.MarkerCluster(markers=markers,
526
  disable_clustering_at_zoom=5)
527
+
 
 
 
 
 
 
528
  else:
529
  map_layer = ipyleaflet.GeoJSON(data = json.loads(df.to_json()),
530
  style={'opacity': 1, 'dashArray': '9', 'fillOpacity': 0.5, 'weight': 1},
 
998
  missing += list(set(["landuse","building","household","individual","intensity","fragility"]) - existing_layers)
999
  elif hazard == "flood":
1000
  if "power" in infra:
1001
+ missing += list(set(["landuse","building","household","individual","power edges","power nodes","intensity","vulnerability"]) - existing_layers)
1002
  if "road" in infra:
1003
+ missing += list(set(["landuse","building","household","individual","road edges","road nodes","intensity"]) - existing_layers)
1004
  if "building" in infra:
1005
  missing += list(set(["landuse","building","household","individual","intensity","vulnerability"]) - existing_layers)
1006
  elif hazard == "landslide":
1007
  if "power" in infra:
1008
+ missing += list(set(["landuse","building","household","individual","power edges","power nodes","landslide fragility"]) - existing_layers)
1009
  if "road" in infra:
1010
+ missing += list(set(["landuse","building","household","individual","road edges","road nodes","landslide fragility"]) - existing_layers)
1011
  if "building" in infra:
1012
+ missing += list(set(["landuse","building","household","individual","landslide fragility"]) - existing_layers)
1013
 
1014
  if infra == []:
1015
  missing += ['You should select at least one of power, road or building']
1016
  return missing == [], missing
1017
 
1018
+ def pre_compute_checks():
1019
+ hazard = layers.value['hazard'].value
1020
+ infra = layers.value['infra'].value
1021
+ building = layers.value['layers']['building']['data'].value
1022
+ household = layers.value['layers']['household']['data'].value
1023
+
1024
+ missing_buildings = set(household['bldid']) - set(building['bldid'])
1025
+ print('missing buildings', missing_buildings)
1026
+ if len(missing_buildings) > 0:
1027
+ return False, f"There are {len(missing_buildings)} household without buildings. Please add buildings for these households."
1028
+
1029
+ return True, ''
1030
 
1031
 
1032
  def execute_engine():
 
1040
  edges = layers.value['layers']['road edges']['data'].value
1041
  intensity = layers.value['layers']['intensity']['data'].value
1042
  fragility = layers.value['layers']['road fragility']['data'].value
1043
+ if layers.value['hazard'].value == 'landslide':
1044
+ fragility = layers.value['layers']['landslide fragility']['data'].value
1045
+ trigger_level= layers.value['landslide_trigger_level'].value
1046
+ fragility = fragility[['expstr','susceptibility',trigger_level]].rename(columns={trigger_level:'collapse_probability'})
1047
  hazard = layers.value['hazard'].value
1048
 
1049
  edges['ds'] = 0
 
1077
  nodes = layers.value['layers']['power nodes']['data'].value
1078
  edges = layers.value['layers']['power edges']['data'].value
1079
  intensity = layers.value['layers']['intensity']['data'].value
1080
+ fragility = layers.value['layers']['power fragility']['data'].value
1081
  hazard = layers.value['hazard'].value
1082
 
1083
+ if layers.value['hazard'].value == 'landslide':
1084
+ fragility = layers.value['layers']['landslide fragility']['data'].value
1085
+ trigger_level= layers.value['landslide_trigger_level'].value
1086
+ fragility = fragility[['expstr','susceptibility',trigger_level]].rename(columns={trigger_level:'collapse_probability'})
1087
+
1088
+ if layers.value['hazard'].value == 'flood':
1089
+ fragility = layers.value['layers']['vulnerability']['data'].value
1090
 
1091
  ds, is_damaged, is_operational, has_power, household_has_power, hospital_has_power = \
1092
  compute_power_infra(buildings,
 
1094
  nodes,
1095
  edges,
1096
  intensity,
1097
+ fragility,
1098
+ hazard, threshold_flood.value, threshold_flood_distance.value)
1099
 
1100
  #power_node_df = dfs['Power Nodes'].copy()
1101
  nodes['ds'] = list(ds)
 
1128
  #print('policies',policies)
1129
  if layers.value['hazard'].value == 'landslide':
1130
  fragility = layers.value['layers']['landslide fragility']['data'].value
 
1131
  trigger_level= layers.value['landslide_trigger_level'].value
1132
  df_bld_hazard = compute(
1133
  landuse,
 
1183
  is_ready, missing = is_ready_to_run(layers.value['infra'].value, layers.value['hazard'].value)
1184
  if not is_ready:
1185
  raise Exception(f'Missing {missing}')
1186
+ #is_ready, message = pre_compute_checks()
1187
+ #if not is_ready:
1188
+ # raise Exception(message)
1189
  max_trials = landslide_max_trials.value if layers.value['hazard'].value == "landslide" else 1
1190
  for trial in range(1,max_trials+1):
1191
+ if trial == 1:
1192
+ set_progress_message('Running...')
1193
+ else:
1194
+ set_progress_message(f'Monte-Carlo trial {trial}/{max_trials}...')
1195
  if 'power' in layers.value['infra'].value:
1196
  nodes, buildings, household = execute_power()
1197
  layers.value['layers']['power nodes']['data'].set(nodes)