hkayabilisim commited on
Commit
2600a6c
·
1 Parent(s): fa3ce67

feature: GEM fragility XML import

Browse files

With this update, Ffur (slight, medium, extensive, collapsed) cumulative distribution functions
in discrete form can be uploaded to engine.

tomorrowcities/backend/utils.py CHANGED
@@ -1,5 +1,7 @@
1
  import pandas as pd
2
  import geopandas as gpd
 
 
3
 
4
  def inject_columns(df, extra_cols):
5
  if isinstance(df, gpd.GeoDataFrame) or isinstance(df, pd.DataFrame):
@@ -30,4 +32,74 @@ class ParameterFile:
30
  self.df3 = pd.read_excel(content,sheet_name=5, header=None)
31
 
32
  def get_sheets(self):
33
- return (self.df_nc, self.ipdf, self.df1, self.df2, self.df3)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import pandas as pd
2
  import geopandas as gpd
3
+ import xml
4
+ import numpy as np
5
 
6
  def inject_columns(df, extra_cols):
7
  if isinstance(df, gpd.GeoDataFrame) or isinstance(df, pd.DataFrame):
 
32
  self.df3 = pd.read_excel(content,sheet_name=5, header=None)
33
 
34
  def get_sheets(self):
35
+ return (self.df_nc, self.ipdf, self.df1, self.df2, self.df3)
36
+
37
+
38
+ def getText(node):
39
+ nodelist = node.childNodes
40
+ rc = []
41
+ for node in nodelist:
42
+ if node.nodeType == node.TEXT_NODE:
43
+ rc.append(node.data)
44
+ return ''.join(rc)
45
+
46
+
47
+ def read_gem_xml_vulnerability(dom):
48
+ d = dict()
49
+ node = dom.getElementsByTagName('vulnerabilityModel')[0]
50
+ for i in range(node.attributes.length):
51
+ d[node.attributes.item(i).name] = node.attributes.item(i).value
52
+
53
+ d['description'] = getText(dom.getElementsByTagName('description')[0])
54
+ d['vulnerabilityFunctions'] = []
55
+ for node in dom.getElementsByTagName('vulnerabilityFunction'):
56
+ v = dict()
57
+ for i in range(node.attributes.length):
58
+ v[node.attributes.item(i).name] = node.attributes.item(i).value
59
+ imls = node.getElementsByTagName('imls')[0]
60
+ v['imt'] = imls.getAttribute('imt')
61
+ v['imls'] = np.fromstring(getText(imls),dtype=float, sep=' ')
62
+ v['meanLRs'] = np.fromstring(getText(node.getElementsByTagName('meanLRs')[0]),dtype=float, sep=' ')
63
+ v['covLRs'] = np.fromstring(getText(node.getElementsByTagName('covLRs')[0]),dtype=float, sep=' ')
64
+ d['vulnerabilityFunctions'].append(v)
65
+ return d
66
+
67
+
68
+ def read_gem_xml_fragility(dom):
69
+ d = dict()
70
+ node = dom.getElementsByTagName('fragilityModel')[0]
71
+ for i in range(node.attributes.length):
72
+ d[node.attributes.item(i).name] = node.attributes.item(i).value
73
+
74
+ d['description'] = getText(dom.getElementsByTagName('description')[0])
75
+ d['fragilityFunctions'] = []
76
+ for node in dom.getElementsByTagName('fragilityFunction'):
77
+ v = dict()
78
+ for i in range(node.attributes.length):
79
+ v[node.attributes.item(i).name] = node.attributes.item(i).value
80
+ imls = node.getElementsByTagName('imls')[0]
81
+ v['imt'] = imls.getAttribute('imt')
82
+ v['noDamageLimit'] = imls.getAttribute('noDamageLimit')
83
+ v['imls'] = np.fromstring(getText(imls),dtype=float, sep=' ')
84
+
85
+
86
+ for poesnode in node.getElementsByTagName('poes'):
87
+ poedict = dict()
88
+ for i in range(poesnode.attributes.length):
89
+ poedict[poesnode.attributes.item(i).name] = poesnode.attributes.item(i).value
90
+ poedict['data'] = np.fromstring(getText(poesnode),dtype=float, sep=' ')
91
+ v[poedict['ls']] = poedict['data']
92
+ d['fragilityFunctions'].append(v)
93
+ return d
94
+
95
+
96
+ def read_gem_xml(data: [bytes]):
97
+ content_as_string = data.decode('utf-8')
98
+ content_as_string = content_as_string.replace('\n','')
99
+ dom = xml.dom.minidom.parseString(content_as_string)
100
+ d = dict()
101
+ if len(dom.getElementsByTagName('vulnerabilityModel')) > 0:
102
+ d = read_gem_xml_vulnerability(dom)
103
+ elif len(dom.getElementsByTagName('fragilityModel')) > 0:
104
+ d = read_gem_xml_fragility(dom)
105
+ return d
tomorrowcities/pages/engine.py CHANGED
@@ -25,7 +25,7 @@ from .settings import storage, landslide_max_trials, revive_storage
25
  from .settings import threshold_flood, threshold_flood_distance, threshold_road_water_height, threshold_culvert_water_height, preserve_edge_directions,\
26
  population_displacement_consensus
27
  from ..backend.engine import compute, compute_power_infra, compute_road_infra, calculate_metrics, generate_exposure
28
- from ..backend.utils import building_preprocess, identity_preprocess, ParameterFile
29
  from .utilities import S3FileBrowser, extension_list, extension_list_w_dots
30
  from ..components.file_drop import FileDropMultiple
31
  from .docs import data_import_help
@@ -146,6 +146,17 @@ def create_new_app_state():
146
  'attributes_required': [set(['id', 'assetCategory', 'lossCategory', 'description', 'vulnerabilityFunctions'])],
147
  'attributes': [set(['id', 'assetCategory', 'lossCategory', 'description', 'vulnerabilityFunctions'])],
148
  },
 
 
 
 
 
 
 
 
 
 
 
149
  'power nodes': {
150
  'render_order': 90,
151
  'data': solara.reactive(None),
@@ -589,39 +600,6 @@ def read_tiff(file_bytes):
589
  return gdf[(gdf.drop(columns='geometry')>0).any(axis=1)]
590
  #return gdf.sort_values(by='im',ascending=False).head(10000)
591
 
592
- def read_gem_xml(data: [bytes]):
593
- content_as_string = data.decode('utf-8')
594
- content_as_string = content_as_string.replace('\n','')
595
- dom = xml.dom.minidom.parseString(content_as_string)
596
-
597
- def getText(node):
598
- nodelist = node.childNodes
599
- rc = []
600
- for node in nodelist:
601
- if node.nodeType == node.TEXT_NODE:
602
- rc.append(node.data)
603
- return ''.join(rc)
604
-
605
- d = dict()
606
- node = dom.getElementsByTagName('vulnerabilityModel')[0]
607
- for i in range(node.attributes.length):
608
- d[node.attributes.item(i).name] = node.attributes.item(i).value
609
-
610
- d['description'] = getText(dom.getElementsByTagName('description')[0])
611
-
612
- d['vulnerabilityFunctions'] = []
613
- for node in dom.getElementsByTagName('vulnerabilityFunction'):
614
- v = dict()
615
- for i in range(node.attributes.length):
616
- v[node.attributes.item(i).name] = node.attributes.item(i).value
617
- imls = node.getElementsByTagName('imls')[0]
618
- v['imt'] = imls.getAttribute('imt')
619
- v['imls'] = np.fromstring(getText(imls),dtype=float, sep=' ')
620
- v['meanLRs'] = np.fromstring(getText(node.getElementsByTagName('meanLRs')[0]),dtype=float, sep=' ')
621
- v['covLRs'] = np.fromstring(getText(node.getElementsByTagName('covLRs')[0]),dtype=float, sep=' ')
622
- d['vulnerabilityFunctions'].append(v)
623
-
624
- return d
625
 
626
  @solara.component
627
  def ParameterFileWidget(parameter_file: ParameterFile):
@@ -705,6 +683,103 @@ def VulnerabilityFunctionDisplayer(vuln_func):
705
  }
706
  solara.FigureEcharts(option=options)
707
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
708
  @solara.component
709
  def VulnerabiliyDisplayer(vuln_xml: dict):
710
  vuln_xml, set_vuln_xml = solara.use_state_or_update(vuln_xml)
@@ -733,6 +808,36 @@ def VulnerabiliyDisplayer(vuln_xml: dict):
733
  with solara.Column():
734
  VulnerabilityFunctionDisplayer(vuln_xml['vulnerabilityFunctions'][func_labels.index(func_label)])
735
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
736
  @solara.component
737
  def MetricWidget(name, description, value, max_value, render_count):
738
  value, set_value = solara.use_state_or_update(value)
@@ -925,6 +1030,8 @@ def LayerDisplayer():
925
  ParameterFileWidget(parameter_file=data)
926
  if selected == 'gem_vulnerability':
927
  VulnerabiliyDisplayer(data)
 
 
928
 
929
  @solara.component
930
  def MetricPanel():
@@ -987,7 +1094,7 @@ def MapViewer():
987
  map_layers = []
988
  for l in layers.value['layers'].keys():
989
  df = layers.value['layers'][l]['data'].value
990
- if df is not None and 'geometry' in df.columns:
991
  df_filtered = df
992
  if l in filters.keys():
993
  if filters[l] is not None:
@@ -1377,6 +1484,9 @@ def MapInfo():
1377
  solara.Text(f"{len(data)}")
1378
  elif isinstance(data, dict) and layer_name == 'gem_vulnerability':
1379
  solara.Text(f"{len(data['vulnerabilityFunctions'])}")
 
 
 
1380
  else:
1381
  with solara.GridFixed(columns=2,row_gap="1px"):
1382
  for key, value in layers.value['map_info_detail'].value.items():
 
25
  from .settings import threshold_flood, threshold_flood_distance, threshold_road_water_height, threshold_culvert_water_height, preserve_edge_directions,\
26
  population_displacement_consensus
27
  from ..backend.engine import compute, compute_power_infra, compute_road_infra, calculate_metrics, generate_exposure
28
+ from ..backend.utils import building_preprocess, identity_preprocess, ParameterFile, read_gem_xml, read_gem_xml_fragility, read_gem_xml_vulnerability, getText
29
  from .utilities import S3FileBrowser, extension_list, extension_list_w_dots
30
  from ..components.file_drop import FileDropMultiple
31
  from .docs import data_import_help
 
146
  'attributes_required': [set(['id', 'assetCategory', 'lossCategory', 'description', 'vulnerabilityFunctions'])],
147
  'attributes': [set(['id', 'assetCategory', 'lossCategory', 'description', 'vulnerabilityFunctions'])],
148
  },
149
+ 'gem_fragility': {
150
+ 'render_order': 0,
151
+ 'data': solara.reactive(None),
152
+ 'df': solara.reactive(None),
153
+ 'map_info_tooltip': 'Number of functions in gem fragility',
154
+ 'pre_processing': identity_preprocess,
155
+ 'extra_cols': {},
156
+ 'filter_cols': ['id'],
157
+ 'attributes_required': [set(['id', 'assetCategory', 'lossCategory', 'description', 'fragilityFunctions'])],
158
+ 'attributes': [set(['id', 'assetCategory', 'lossCategory', 'description', 'fragilityFunctions'])],
159
+ },
160
  'power nodes': {
161
  'render_order': 90,
162
  'data': solara.reactive(None),
 
600
  return gdf[(gdf.drop(columns='geometry')>0).any(axis=1)]
601
  #return gdf.sort_values(by='im',ascending=False).head(10000)
602
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
603
 
604
  @solara.component
605
  def ParameterFileWidget(parameter_file: ParameterFile):
 
683
  }
684
  solara.FigureEcharts(option=options)
685
 
686
+
687
+ @solara.component
688
+ def FragilityFunctionDisplayer(vuln_func):
689
+ vuln_func, _ = solara.use_state_or_update(vuln_func)
690
+
691
+ x = vuln_func['imls']
692
+ y1 = vuln_func['slight']
693
+ y2 = vuln_func['moderate']
694
+ y3 = vuln_func['extensive']
695
+ y4 = vuln_func['complete']
696
+
697
+ xlabel = vuln_func['imt']
698
+
699
+ options = {
700
+ 'title': {
701
+ 'text': vuln_func['id'],
702
+ 'left': 'center'},
703
+ 'tooltip': {
704
+ 'trigger': 'axis',
705
+ 'axisPointer': {
706
+ 'type': 'cross'
707
+ }
708
+ },
709
+ #'legend': {'data': ['Covariance','Mean']},
710
+ 'xAxis': {
711
+ 'axisTick': {
712
+ 'alignWithLabel': True
713
+ },
714
+ 'data': list(x),
715
+ 'name': xlabel,
716
+ 'nameLocation': 'middle',
717
+ 'nameTextStyle': {'verticalAlign': 'top','padding': [10, 0, 0, 0]}
718
+ },
719
+ 'yAxis': [
720
+ {
721
+ 'type': 'value',
722
+ 'position': 'left',
723
+ 'alignTicks': True,
724
+ 'axisLine': {
725
+ 'show': True,
726
+ 'lineStyle': {'color': 'green'}}
727
+ },
728
+ {
729
+ 'type': 'value',
730
+ 'position': 'left',
731
+ 'alignTicks': True,
732
+ 'axisLine': {
733
+ 'show': True,
734
+ 'lineStyle': {'color': 'blue'}}
735
+ },
736
+ {
737
+ 'type': 'value',
738
+ 'position': 'left',
739
+ 'alignTicks': True,
740
+ 'axisLine': {
741
+ 'show': True,
742
+ 'lineStyle': {'color': 'yellow'}}
743
+ },
744
+ {
745
+ 'type': 'value',
746
+ 'position': 'left',
747
+ 'alignTicks': True,
748
+ 'axisLine': {
749
+ 'show': True,
750
+ 'lineStyle': {'color': 'purple'}}
751
+ },
752
+ ],
753
+ 'series': [
754
+ {
755
+ 'name': 'slight',
756
+ 'data': list(y1),
757
+ 'type': 'line',
758
+ 'yAxisIndex': 0
759
+ },
760
+ {
761
+ 'name': 'moderate',
762
+ 'data': list(y2),
763
+ 'type': 'line',
764
+ 'yAxisIndex': 1
765
+ },
766
+ {
767
+ 'name': 'extensive',
768
+ 'data': list(y3),
769
+ 'type': 'line',
770
+ 'yAxisIndex': 2
771
+ },
772
+ {
773
+ 'name': 'complete',
774
+ 'data': list(y4),
775
+ 'type': 'line',
776
+ 'yAxisIndex': 3
777
+ },
778
+ ],
779
+ }
780
+ solara.FigureEcharts(option=options)
781
+
782
+
783
  @solara.component
784
  def VulnerabiliyDisplayer(vuln_xml: dict):
785
  vuln_xml, set_vuln_xml = solara.use_state_or_update(vuln_xml)
 
808
  with solara.Column():
809
  VulnerabilityFunctionDisplayer(vuln_xml['vulnerabilityFunctions'][func_labels.index(func_label)])
810
 
811
+
812
+ @solara.component
813
+ def FragilityDisplayer(vuln_xml: dict):
814
+ vuln_xml, set_vuln_xml = solara.use_state_or_update(vuln_xml)
815
+
816
+ func_labels = [f'{v["imt"]}---{v["id"]}' for v in vuln_xml['fragilityFunctions']]
817
+ func_label, set_func_label = solara.use_state_or_update(func_labels[0])
818
+
819
+ with solara.GridFixed(columns=2):
820
+ with solara.Column(gap="1px"):
821
+ solara.Text('Description:',style={'fontWeight': 'bold'})
822
+ with solara.Row(justify="left"):
823
+ solara.Text(f'{vuln_xml["description"]}')
824
+ with solara.GridFixed(columns=2,row_gap="1px"):
825
+ solara.Text('Asset Category:',style={'fontWeight': 'bold'})
826
+ with solara.Row(justify="right"):
827
+ solara.Text(f'{vuln_xml["assetCategory"]}')
828
+ solara.Text('Loss Category:',style={'fontWeight': 'bold'})
829
+ with solara.Row(justify="right"):
830
+ solara.Text(f'{vuln_xml["lossCategory"]}')
831
+ solara.Text('# of vulnerability functions:',style={'fontWeight': 'bold'})
832
+ with solara.Row(justify="right"):
833
+ solara.Text(f'{len(vuln_xml["fragilityFunctions"])}')
834
+ solara.Text('Select vulnerability function:',style={'fontWeight': 'bold'})
835
+ solara.Select(label='',value=func_label, values=func_labels,
836
+ on_value=set_func_label)
837
+ with solara.Column():
838
+ FragilityFunctionDisplayer(vuln_xml['fragilityFunctions'][func_labels.index(func_label)])
839
+
840
+
841
  @solara.component
842
  def MetricWidget(name, description, value, max_value, render_count):
843
  value, set_value = solara.use_state_or_update(value)
 
1030
  ParameterFileWidget(parameter_file=data)
1031
  if selected == 'gem_vulnerability':
1032
  VulnerabiliyDisplayer(data)
1033
+ elif selected == 'gem_fragility':
1034
+ FragilityDisplayer(data)
1035
 
1036
  @solara.component
1037
  def MetricPanel():
 
1094
  map_layers = []
1095
  for l in layers.value['layers'].keys():
1096
  df = layers.value['layers'][l]['data'].value
1097
+ if df is not None and isinstance(df, gpd.GeoDataFrame):
1098
  df_filtered = df
1099
  if l in filters.keys():
1100
  if filters[l] is not None:
 
1484
  solara.Text(f"{len(data)}")
1485
  elif isinstance(data, dict) and layer_name == 'gem_vulnerability':
1486
  solara.Text(f"{len(data['vulnerabilityFunctions'])}")
1487
+ elif isinstance(data, dict) and layer_name == 'gem_fragility':
1488
+ solara.Text(f"{len(data['fragilityFunctions'])}")
1489
+
1490
  else:
1491
  with solara.GridFixed(columns=2,row_gap="1px"):
1492
  for key, value in layers.value['map_info_detail'].value.items():