Huseyin Kaya commited on
Commit
cabd409
·
unverified ·
2 Parent(s): 1a6f13a 7853da4

Merge pull request #93 from TomorrowsCities/feature_persistence_to_browser_refresh

Browse files
Files changed (1) hide show
  1. tomorrowcities/pages/engine.py +72 -21
tomorrowcities/pages/engine.py CHANGED
@@ -39,7 +39,7 @@ tally_counter = solara.reactive(0)
39
  tally_filter = solara.reactive(None)
40
  building_filter = solara.reactive(None)
41
  landuse_filter = solara.reactive(None)
42
-
43
  def create_new_app_state():
44
  return solara.reactive({
45
  'infra': solara.reactive(["building"]),
@@ -235,7 +235,7 @@ def create_new_app_state():
235
  'attributes': [set(['vuln_string', 'med_slight', 'med_moderate', 'med_extensive', 'med_complete',
236
  'dispersion'])]}
237
  },
238
- 'center': solara.reactive((41.01,28.98)),
239
  'selected_layer' : solara.reactive(None),
240
  'render_count': solara.reactive(0),
241
  'bounds': solara.reactive(None),
@@ -341,7 +341,55 @@ def load_from_state(source_dict):
341
  assign_nested_value(layers.value, keys, solara.reactive(src_value))
342
  else:
343
  assign_nested_value(layers.value, keys, src_value)
344
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
345
  def create_metadata(data):
346
  m = dict()
347
  m['hazard'] = data['hazard']
@@ -896,13 +944,13 @@ def FilterPanel():
896
  # filters[layer_name], _ = solara.use_cross_filter(id(df), "dataframe")
897
 
898
  building = layers.value['layers']['building']['df'].value
 
899
  if building is not None:
900
  with solara.Row(): #spacer
901
  solara.Markdown('''<h5 style=""></h5>''')
902
  btn = solara.Button("BUILDING FILTERS")
903
  with solara.Column(align="stretch"):
904
  with solara.lab.Menu(activator=btn, close_on_content_click=False, style={"width":"35vh", "align":"stretch"}): #"height":"60vh"
905
- building_filter.value, _ = solara.use_cross_filter(id(building), "building_filter")
906
  solara.CrossFilterReport(building)
907
  solara.CrossFilterSelect(building, "ds", multiple=True)
908
  solara.CrossFilterSelect(building, "specialfac", multiple=True)
@@ -913,29 +961,30 @@ def FilterPanel():
913
  solara.CrossFilterSelect(building, "code_level", multiple=True)
914
  solara.CrossFilterSelect(building, "material", multiple=True)
915
  solara.CrossFilterSelect(building, "zoneid", multiple=True)
916
-
917
  landuse = layers.value['layers']['landuse']['df'].value
 
918
  if landuse is not None:
919
  with solara.Row(): #spacer
920
  solara.Markdown('''<h5 style=""></h5>''')
921
  btn = solara.Button("LANDUSE FILTERS")
922
  with solara.Column(align="stretch"):
923
  with solara.lab.Menu(activator=btn, close_on_content_click=False, style={"width":"35vh", "align":"stretch"}): #"height":"60vh"
924
- landuse_filter.value, _ = solara.use_cross_filter(id(landuse), "landuse_filter")
925
  solara.CrossFilterReport(landuse)
926
  solara.CrossFilterSelect(landuse, "luf", multiple=True)
927
  solara.CrossFilterSelect(landuse, "avgincome", multiple=True)
928
 
 
929
  tc = tally_counter.value
930
  print('tally_counter', tc)
931
  tally_minimal = read_from_session_storage('tally_minimal')
 
932
  if tally_minimal is not None:
933
  with solara.Row(): #spacer
934
  solara.Markdown('''<h5 style=""></h5>''')
935
  btn = solara.Button("METRIC FILTERS")
936
  with solara.Column(align="stretch"):
937
  with solara.lab.Menu(activator=btn, close_on_content_click=False, style={"width":"35vh", "align":"stretch"}): #"height":"60vh"
938
- tally_filter.value, _ = solara.use_cross_filter(id(tally_minimal), "tally_filter")
939
  solara.CrossFilterReport(tally_minimal)
940
  for col in layers.value['tally_filter_cols']:
941
  solara.CrossFilterSelect(tally_minimal, col, multiple=True)
@@ -989,14 +1038,15 @@ def generate_metrics_local():
989
  metrics = {name: {'value':0, 'max_value':0, 'desc': metric['desc']} for name, metric in layers.value['metrics'].items()}
990
 
991
  tally_geo = read_from_session_storage('tally_geo')
 
 
992
  if tally_geo is not None and layers.value['bounds'].value is not None:
993
  ((ymin,xmin),(ymax,xmax)) = layers.value['bounds'].value
994
  tally_filtered = tally_geo.cx[xmin:xmax,ymin:ymax]
995
  if tally_filter.value is not None:
996
  tally_filtered = tally_filtered[tally_filter.value]
997
- hazard_type = layers.value['hazard'].value
998
  print('Triggering generate_metrics')
999
- metrics = generate_metrics(tally_filtered, tally_geo, hazard_type, population_displacement_consensus.value)
1000
  print('metrics', metrics)
1001
  metric_update_pending.set(False)
1002
  return metrics
@@ -1105,6 +1155,10 @@ def ExecutePanel():
1105
  set_execute_counter(execute_counter + 1)
1106
  execute_error.set("")
1107
 
 
 
 
 
1108
  def is_ready_to_run(infra, hazard):
1109
  existing_layers = set([name for name, l in layers.value['layers'].items() if l['data'].value is not None])
1110
  missing = []
@@ -1356,20 +1410,10 @@ def ExecutePanel():
1356
  return buildings
1357
 
1358
  def execute_metric():
1359
- hazard_type = layers.value['hazard'].value
1360
  landuse = layers.value['layers']['landuse']['data'].value
1361
  buildings = layers.value['layers']['building']['data'].value
1362
  household = layers.value['layers']['household']['data'].value
1363
  individual = layers.value['layers']['individual']['data'].value
1364
- policies = [p['id'] for _, p in layers.value['policies'].items() if f"{p['label']}/{p['description']}" in layers.value['selected_policies'].value]
1365
-
1366
- # implementation_capacity_score = layers.value['implementation_capacity_score'].value
1367
- # if implementation_capacity_score == 'medium':
1368
- # capacity = 1.25
1369
- # elif implementation_capacity_score == 'low':
1370
- # capacity = 1.50
1371
- # else:
1372
- # capacity = 1
1373
 
1374
  tally, tally_geo = create_tally(landuse, buildings, household, individual)
1375
  return tally, tally_geo
@@ -1415,6 +1459,7 @@ def ExecutePanel():
1415
  store_in_session_storage('tally', tally)
1416
  store_in_session_storage('tally_geo', tally_geo)
1417
  store_in_session_storage('tally_minimal', tally[layers.value['tally_filter_cols']])
 
1418
  layers.value['tally_is_available'].value = True
1419
  tally_counter.value += 1
1420
  set_progress_message('')
@@ -1450,8 +1495,13 @@ def ExecutePanel():
1450
  # )
1451
 
1452
  solara.ProgressLinear(value=False)
1453
- solara.Button("Calculate", on_click=on_click, outlined=True,
 
 
1454
  disabled=execute_btn_disabled)
 
 
 
1455
  if storage.value is not None:
1456
  if layers.value['tally_is_available'].value and user.value is not None:
1457
  solara.Button("Save Session",on_click=save_app_state, disabled=False)
@@ -1487,7 +1537,7 @@ def ExecutePanel():
1487
  solara.Text("Spacer", style={"visibility": "hidden"})
1488
  set_execute_btn_disabled(False)
1489
  solara.ProgressLinear(value=False)
1490
-
1491
  @solara.component
1492
  def PolicyPanel():
1493
  all_policies = [f"{p['label']}/{p['description']}" for _, p in layers.value['policies'].items()]
@@ -1737,6 +1787,7 @@ def ImportDataZone():
1737
  @solara.component
1738
  def WebApp():
1739
  solara.Title(" ")
 
1740
  with solara.Sidebar():
1741
  with solara.lab.Tabs():
1742
  with solara.lab.Tab("DATA IMPORT"):
 
39
  tally_filter = solara.reactive(None)
40
  building_filter = solara.reactive(None)
41
  landuse_filter = solara.reactive(None)
42
+ center_default = (41.01,28.98)
43
  def create_new_app_state():
44
  return solara.reactive({
45
  'infra': solara.reactive(["building"]),
 
235
  'attributes': [set(['vuln_string', 'med_slight', 'med_moderate', 'med_extensive', 'med_complete',
236
  'dispersion'])]}
237
  },
238
+ 'center': solara.reactive(center_default),
239
  'selected_layer' : solara.reactive(None),
240
  'render_count': solara.reactive(0),
241
  'bounds': solara.reactive(None),
 
341
  assign_nested_value(layers.value, keys, solara.reactive(src_value))
342
  else:
343
  assign_nested_value(layers.value, keys, src_value)
344
+
345
+ def store_info_to_session():
346
+ store_in_session_storage('population_displacement_consensus', population_displacement_consensus.value)
347
+ for layer_name in layers.value['layers'].keys():
348
+ store_in_session_storage(layer_name, {
349
+ 'data':layers.value['layers'][layer_name]['data'].value,
350
+ 'df': layers.value['layers'][layer_name]['df'].value,
351
+ })
352
+ for attr in ['hazard', 'tally_is_available', 'selected_policies','center',
353
+ 'bounds','selected_layer','render_count','implementation_capacity_score',
354
+ 'data_import_method','map_info_button','map_info_detail']:
355
+ store_in_session_storage(attr, layers.value[attr].value)
356
+
357
+ def reload_info_from_session():
358
+ session_data = read_from_session_storage('population_displacement_consensus')
359
+ if session_data is not None:
360
+ population_displacement_consensus.set(session_data)
361
+ for layer_name in layers.value['layers'].keys():
362
+ session_data = read_from_session_storage(layer_name)
363
+ if session_data is not None:
364
+ if layers.value['layers'][layer_name]['data'].value is None:
365
+ layers.value['layers'][layer_name]['data'].set(session_data['data'])
366
+ if layers.value['layers'][layer_name]['df'].value is None:
367
+ layers.value['layers'][layer_name]['df'].set(session_data['df'])
368
+
369
+ for attr in ['hazard', 'tally_is_available', 'selected_policies','center',
370
+ 'bounds','selected_layer','render_count','implementation_capacity_score',
371
+ 'data_import_method','map_info_button','map_info_detail']:
372
+ session_data = read_from_session_storage(attr)
373
+ if session_data is not None:
374
+ layers.value[attr].set(session_data)
375
+
376
+ def reset_session():
377
+ store_in_session_storage('population_displacement_consensus', None)
378
+ for layer_name in layers.value['layers'].keys():
379
+ store_in_session_storage(layer_name, None)
380
+ for attr in ['hazard', 'tally_is_available', 'selected_policies','center',
381
+ 'bounds','selected_layer','render_count','implementation_capacity_score',
382
+ 'data_import_method','map_info_button','map_info_detail']:
383
+ store_in_session_storage(attr, None)
384
+ store_in_session_storage('tally', None)
385
+ store_in_session_storage('tally_geo', None)
386
+ store_in_session_storage('tally_minimal', None)
387
+ layers.set(create_new_app_state().value)
388
+ tally_filter.set(None)
389
+ building_filter.set(None)
390
+ landuse_filter.set(None)
391
+ tally_counter.set(0)
392
+
393
  def create_metadata(data):
394
  m = dict()
395
  m['hazard'] = data['hazard']
 
944
  # filters[layer_name], _ = solara.use_cross_filter(id(df), "dataframe")
945
 
946
  building = layers.value['layers']['building']['df'].value
947
+ building_filter.value, _ = solara.use_cross_filter(id(building), "building_filter")
948
  if building is not None:
949
  with solara.Row(): #spacer
950
  solara.Markdown('''<h5 style=""></h5>''')
951
  btn = solara.Button("BUILDING FILTERS")
952
  with solara.Column(align="stretch"):
953
  with solara.lab.Menu(activator=btn, close_on_content_click=False, style={"width":"35vh", "align":"stretch"}): #"height":"60vh"
 
954
  solara.CrossFilterReport(building)
955
  solara.CrossFilterSelect(building, "ds", multiple=True)
956
  solara.CrossFilterSelect(building, "specialfac", multiple=True)
 
961
  solara.CrossFilterSelect(building, "code_level", multiple=True)
962
  solara.CrossFilterSelect(building, "material", multiple=True)
963
  solara.CrossFilterSelect(building, "zoneid", multiple=True)
964
+
965
  landuse = layers.value['layers']['landuse']['df'].value
966
+ landuse_filter.value, _ = solara.use_cross_filter(id(landuse), "landuse_filter")
967
  if landuse is not None:
968
  with solara.Row(): #spacer
969
  solara.Markdown('''<h5 style=""></h5>''')
970
  btn = solara.Button("LANDUSE FILTERS")
971
  with solara.Column(align="stretch"):
972
  with solara.lab.Menu(activator=btn, close_on_content_click=False, style={"width":"35vh", "align":"stretch"}): #"height":"60vh"
 
973
  solara.CrossFilterReport(landuse)
974
  solara.CrossFilterSelect(landuse, "luf", multiple=True)
975
  solara.CrossFilterSelect(landuse, "avgincome", multiple=True)
976
 
977
+
978
  tc = tally_counter.value
979
  print('tally_counter', tc)
980
  tally_minimal = read_from_session_storage('tally_minimal')
981
+ tally_filter.value, _ = solara.use_cross_filter(id(tally_minimal), "tally_filter")
982
  if tally_minimal is not None:
983
  with solara.Row(): #spacer
984
  solara.Markdown('''<h5 style=""></h5>''')
985
  btn = solara.Button("METRIC FILTERS")
986
  with solara.Column(align="stretch"):
987
  with solara.lab.Menu(activator=btn, close_on_content_click=False, style={"width":"35vh", "align":"stretch"}): #"height":"60vh"
 
988
  solara.CrossFilterReport(tally_minimal)
989
  for col in layers.value['tally_filter_cols']:
990
  solara.CrossFilterSelect(tally_minimal, col, multiple=True)
 
1038
  metrics = {name: {'value':0, 'max_value':0, 'desc': metric['desc']} for name, metric in layers.value['metrics'].items()}
1039
 
1040
  tally_geo = read_from_session_storage('tally_geo')
1041
+ hazard = read_from_session_storage('hazard')
1042
+ population_displacement_consensus = read_from_session_storage('population_displacement_consensus')
1043
  if tally_geo is not None and layers.value['bounds'].value is not None:
1044
  ((ymin,xmin),(ymax,xmax)) = layers.value['bounds'].value
1045
  tally_filtered = tally_geo.cx[xmin:xmax,ymin:ymax]
1046
  if tally_filter.value is not None:
1047
  tally_filtered = tally_filtered[tally_filter.value]
 
1048
  print('Triggering generate_metrics')
1049
+ metrics = generate_metrics(tally_filtered, tally_geo, hazard, population_displacement_consensus)
1050
  print('metrics', metrics)
1051
  metric_update_pending.set(False)
1052
  return metrics
 
1155
  set_execute_counter(execute_counter + 1)
1156
  execute_error.set("")
1157
 
1158
+ def on_reset():
1159
+ reset_session()
1160
+
1161
+
1162
  def is_ready_to_run(infra, hazard):
1163
  existing_layers = set([name for name, l in layers.value['layers'].items() if l['data'].value is not None])
1164
  missing = []
 
1410
  return buildings
1411
 
1412
  def execute_metric():
 
1413
  landuse = layers.value['layers']['landuse']['data'].value
1414
  buildings = layers.value['layers']['building']['data'].value
1415
  household = layers.value['layers']['household']['data'].value
1416
  individual = layers.value['layers']['individual']['data'].value
 
 
 
 
 
 
 
 
 
1417
 
1418
  tally, tally_geo = create_tally(landuse, buildings, household, individual)
1419
  return tally, tally_geo
 
1459
  store_in_session_storage('tally', tally)
1460
  store_in_session_storage('tally_geo', tally_geo)
1461
  store_in_session_storage('tally_minimal', tally[layers.value['tally_filter_cols']])
1462
+ store_info_to_session()
1463
  layers.value['tally_is_available'].value = True
1464
  tally_counter.value += 1
1465
  set_progress_message('')
 
1495
  # )
1496
 
1497
  solara.ProgressLinear(value=False)
1498
+ with solara.Columns([70,30]):
1499
+ with solara.Column():
1500
+ solara.Button("Calculate", on_click=on_click, outlined=True,
1501
  disabled=execute_btn_disabled)
1502
+ with solara.Column():
1503
+ solara.Button("Reset", on_click=on_reset, outlined=True,
1504
+ disabled=False)
1505
  if storage.value is not None:
1506
  if layers.value['tally_is_available'].value and user.value is not None:
1507
  solara.Button("Save Session",on_click=save_app_state, disabled=False)
 
1537
  solara.Text("Spacer", style={"visibility": "hidden"})
1538
  set_execute_btn_disabled(False)
1539
  solara.ProgressLinear(value=False)
1540
+
1541
  @solara.component
1542
  def PolicyPanel():
1543
  all_policies = [f"{p['label']}/{p['description']}" for _, p in layers.value['policies'].items()]
 
1787
  @solara.component
1788
  def WebApp():
1789
  solara.Title(" ")
1790
+ reload_info_from_session()
1791
  with solara.Sidebar():
1792
  with solara.lab.Tabs():
1793
  with solara.lab.Tab("DATA IMPORT"):