zavavan commited on
Commit
5b6a877
·
verified ·
1 Parent(s): 90fb8af

Update dashboard.py

Browse files
Files changed (1) hide show
  1. dashboard.py +422 -404
dashboard.py CHANGED
@@ -1,4 +1,5 @@
1
 
 
2
  import warnings
3
  warnings.filterwarnings("ignore")
4
  import io
@@ -31,416 +32,433 @@ from bokeh.resources import INLINE
31
  from holoviews.operation.timeseries import rolling, rolling_outlier_std
32
  hv.extension('bokeh')
33
 
34
- ## LOAD DATASETS
35
 
36
- #static_folder = '/static'
37
- dna_folder = './data'
38
 
 
 
 
 
39
 
40
- macro_topics = ["Energy-Efficient Building Design for Thermal Comfort and Sustainability","Indoor Air Quality and Energy Efficiency in Low-Energy Houses","Urban Planning and Development in China\'s Cities", "Design Thinking and Sustainable Product Development", "Smart Cities and Urban Computing", "Urban Resilience and Water Management","Renewable Energy Systems: Solar PV & Building Applications","Exploring the Intersection of Traditional Heritage and Modern Steel Architecture in Historical Buildings","Green Building Assessment and Design","Landscape Design, Planning, and Research: Integrating Cultural, Ecological, and Rural Perspectives", "Noise and Acoustic Design in Urban Development","Sustainable Building Materials: Wood & 3D Printing Innovations","BIM in AEC: Trends, Challenges, and Opportunities","Urban Food Systems: Community Development and Social Sustainability in Cities","Innovative Bridge Design and Construction: Trends and Case Studies", "Cavity Flow and Heat Transfer"]
41
 
42
-
43
-
44
- ## AECO topic over time html file:
45
- AECO_topics_over_time_file_path = '/static/optimized_merged_AECO_topics_over_time_2D.html'
46
-
47
- #### full data unfiltered:
48
-
49
- dna_articles_unfiltered_eu_time_indexed_resampled = pd.read_csv(os.path.join(dna_folder, 'dna_articles_unfiltered_eu_time_indexed_resampled.tsv'),sep='\t',header=0)
50
- dna_articles_unfiltered_us_time_indexed_resampled = pd.read_csv(os.path.join(dna_folder, 'dna_articles_unfiltered_us_time_indexed_resampled.tsv'),sep='\t',header=0)
51
- dna_articles_unfiltered_eu_us_time_indexed_resampled = pd.read_csv(os.path.join(dna_folder, 'dna_articles_unfiltered_eu_us_time_indexed_resampled.tsv'),sep='\t',header=0)
52
-
53
- #### classifier filtered articles:
54
-
55
- dh_ration_df_eu = pd.read_csv(os.path.join(dna_folder, 'dh_ration_df_eu.tsv'),sep='\t',header=0)
56
- dh_ration_df_us = pd.read_csv(os.path.join(dna_folder, 'dh_ration_df_us.tsv'),sep='\t',header=0)
57
- dh_ration_df_eu_us = pd.read_csv(os.path.join(dna_folder, 'dh_ration_df_eu_us.tsv'),sep='\t',header=0)
58
-
59
- regions = ['eu', 'us', 'eu_us']
60
-
61
- sorted_ent_type_freq_map_eu=dict()
62
- sorted_ent_type_freq_map_us=dict()
63
- sorted_ent_type_freq_map_eu_us=dict()
64
-
65
- def read_top_ent_types():
66
- reader = csv.reader(open(os.path.join(dna_folder, 'sorted_ent_type_freq_map_eu.tsv'), 'r'))
67
- for i,row in enumerate(reader):
68
- if i < 20:
69
- k, v = row
70
- sorted_ent_type_freq_map_eu[k] = int(v)
71
- del sorted_ent_type_freq_map_eu['Entity']
72
- reader = csv.reader(open(os.path.join(dna_folder, 'sorted_ent_type_freq_map_us.tsv'), 'r'))
73
- for i, row in enumerate(reader):
74
- if i < 20:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75
  k, v = row
76
- sorted_ent_type_freq_map_us[k] = int(v)
77
- del sorted_ent_type_freq_map_us['Entity']
78
- reader = csv.reader(open(os.path.join(dna_folder, 'sorted_ent_type_freq_map_eu_us.tsv'), 'r'))
79
- for i, row in enumerate(reader):
80
- if i < 20:
 
 
 
 
81
  k, v = row
82
- sorted_ent_type_freq_map_eu_us[k] = int(v)
83
- del sorted_ent_type_freq_map_eu_us['Entity']
84
-
85
- read_top_ent_types()
86
-
87
- top_type_filtered_eu = ['DBpedia:Country', 'DBpedia:Organisation', 'DBpedia:Company', 'DBpedia:Person', 'DBpedia:Disease', 'DBpedia:ChemicalSubstance', 'DBpedia:Drug', 'DBpedia:GovernmentAgency', 'DBpedia:City', 'DBpedia:MonoclonalAntibody']
88
- top_type_filtered_us = ['DBpedia:Organisation', 'DBpedia:Company', 'DBpedia:Disease', 'DBpedia:ChemicalSubstance', 'DBpedia:Person', 'DBpedia:Drug', 'DBpedia:Country', 'DBpedia:Region', 'DBpedia:MonoclonalAntibody', 'DBpedia:City', 'DBpedia:Biomolecule']
89
- top_type_filtered_eu_us = ['DBpedia:Organisation', 'DBpedia:Company', 'DBpedia:ChemicalSubstance', 'DBpedia:Drug', 'DBpedia:Country', 'DBpedia:Person', 'DBpedia:Disease', 'DBpedia:MonoclonalAntibody', 'DBpedia:GovernmentAgency', 'DBpedia:Biomolecule', 'DBpedia:Gene']
90
-
91
- dna_healthtech_articles_eu_time_indexed_resampled=pd.read_csv(os.path.join(dna_folder, 'dna_healthtech_articles_eu_time_indexed_resampled.tsv'),sep='\t',header=0)
92
- dna_healthtech_articles_us_time_indexed_resampled=pd.read_csv(os.path.join(dna_folder, 'dna_healthtech_articles_us_time_indexed_resampled.tsv'),sep='\t',header=0)
93
- dna_healthtech_articles_eu_us_time_indexed_resampled=pd.read_csv(os.path.join(dna_folder, 'dna_healthtech_articles_eu_us_time_indexed_resampled.tsv'),sep='\t',header=0)
94
-
95
- def read_top_ent_maps():
96
- reader = csv.reader(open(os.path.join(dna_folder, 'sorted_ent_freq_map_eu.tsv'), 'r'), delimiter='\t')
97
- for row in reader:
98
- k,v = row
99
- lista = ast.literal_eval(v)
100
- dizionario = dict()
101
- for pair in lista:
102
- dizionario[pair[0]]=pair[1]
103
- dizionario = sorted(dizionario.items(), key=lambda x: x[1], reverse=True)
104
- ent_freq_maps_eu[k]=dizionario
105
-
106
- reader = csv.reader(open(os.path.join(dna_folder, 'sorted_ent_freq_map_us.tsv'), 'r'), delimiter='\t')
107
- for row in reader:
108
- k, v = row
109
- lista = ast.literal_eval(v)
110
- dizionario = dict()
111
- for pair in lista:
112
- dizionario[pair[0]] = pair[1]
113
- dizionario = sorted(dizionario.items(), key=lambda x: x[1], reverse=True)
114
- ent_freq_maps_us[k] = dizionario
115
-
116
- reader = csv.reader(open(os.path.join(dna_folder, 'sorted_ent_freq_map_eu_us.tsv'), 'r'), delimiter='\t')
117
- for row in reader:
118
- k, v = row
119
- lista = ast.literal_eval(v)
120
- dizionario = dict()
121
- for pair in lista:
122
- dizionario[pair[0]] = pair[1]
123
- dizionario = sorted(dizionario.items(), key=lambda x: x[1], reverse=True)
124
- ent_freq_maps_eu_us[k] = dizionario
125
-
126
- ent_freq_maps_eu = dict()
127
- ent_freq_maps_us = dict()
128
- ent_freq_maps_eu_us = dict()
129
-
130
- read_top_ent_maps()
131
-
132
-
133
- def read_type_filtered_triples():
134
- for t in top_type_filtered_eu:
135
- df = pd.read_csv(dna_folder+'/filtered_rows/eu/'+t.replace(':','_')+'.tsv', sep=" ", header=0)
136
- df.drop(columns=['Unnamed: 0'], inplace=True)
137
- top_type_filtered_triples_eu[t]=df
138
- for t in top_type_filtered_us:
139
- df = pd.read_csv(dna_folder+'/filtered_rows/us/'+t.replace(':','_')+'.tsv', sep=" ")
140
- df.drop(columns=['Unnamed: 0'], inplace=True)
141
- top_type_filtered_triples_us[t]=df
142
- for t in top_type_filtered_eu_us:
143
- df = pd.read_csv(dna_folder+'/filtered_rows/eu_us/'+t.replace(':','_')+'.tsv', sep=" ")
144
- df.drop(columns=['Unnamed: 0'], inplace=True)
145
- top_type_filtered_triples_eu_us[t]=df
146
-
147
-
148
-
149
- top_type_filtered_triples_eu = dict()
150
- top_type_filtered_triples_us = dict()
151
- top_type_filtered_triples_eu_us = dict()
152
-
153
- read_type_filtered_triples()
154
-
155
- grouping_filtered = pd.read_csv(os.path.join(dna_folder, 'dna_relations.tsv'), sep=" ")
156
- ################################# CREATE CHARTS ############################
157
- def create_curve_chart():
158
- # Create the 3 line plots
159
- curve_eu = hv.Curve((dh_ration_df_eu.index, dh_ration_df_eu.ids/dna_articles_unfiltered_eu_time_indexed_resampled.ids), 'Time', 'Digital Health News Ratio',label='EU')
160
- curve_us = hv.Curve((dh_ration_df_us.index, dh_ration_df_us.ids/dna_articles_unfiltered_us_time_indexed_resampled.ids),'Time', 'Digital Health News Ratio', label='US')
161
- curve_eu_us = hv.Curve((dh_ration_df_eu_us.index, dh_ration_df_eu_us.ids/dna_articles_unfiltered_eu_us_time_indexed_resampled.ids),'Time', 'Digital Health News Ratio', label='EU-US')
162
- #Overlay the line plots
163
- overlay = curve_eu * curve_us * curve_eu_us
164
- overlay.opts(show_legend = True, legend_position='top_left', width=1200, height=600)
165
- return overlay
166
-
167
-
168
- def create_bar_charts(region, **kwargs):
169
- if region=='eu':
170
- sliced = sorted_ent_type_freq_map_eu
171
- return hv.Bars(sliced, hv.Dimension('Entity Types'), 'Frequency').opts( framewise=True, xrotation=45,width=1200, height=600)
172
- elif region=='us':
173
- sliced = sorted_ent_type_freq_map_us
174
- return hv.Bars(sliced, hv.Dimension('Entity Types'), 'Frequency').opts(framewise=True, xrotation=45,width=1200, height=600)
175
- elif region=='eu_us':
176
- sliced = sorted_ent_type_freq_map_eu_us
177
- return hv.Bars(sliced, hv.Dimension('Entity Types'), 'Frequency').opts(framewise=True, xrotation=45,width=1200, height=600)
178
-
179
-
180
-
181
- # Define a function to generate Curve based on selected values
182
- def generate_entity_curves(region_value, type_value, **kwargs):
183
- if region_value=='eu':
184
- top20Ents = ent_freq_maps_eu[type_value]
185
- curveList = []
186
- for ent in top20Ents:
187
- entityTriples = top_type_filtered_triples_eu[type_value][(top_type_filtered_triples_eu[type_value]['subjEntityLinks']==ent[0]) | (top_type_filtered_triples_eu[type_value]['objEntityLinks']==ent[0])]
188
- entityTriples_time_indexed = entityTriples.set_index(pd.DatetimeIndex(entityTriples['timestamp']), inplace=False)
189
- del entityTriples_time_indexed['timestamp']
190
- entityTriples_time_indexed_resampled = entityTriples_time_indexed.resample("Y").count()
191
- #print(entityTriples_time_indexed_resampled)
192
- entityTriples_time_indexed_resampled = entityTriples_time_indexed_resampled.reindex(dna_healthtech_articles_eu_time_indexed_resampled.index, fill_value=0)
193
- curve = hv.Curve((entityTriples_time_indexed_resampled.index, (entityTriples_time_indexed_resampled['doc_id']/dna_healthtech_articles_eu_time_indexed_resampled['ids'])), 'Time', 'Key Entity Occurrence', label=ent[0])
194
- curve.opts(autorange='y')
195
- #curve.opts(logy=True)
196
- curveList.append(curve)
197
- overlay = hv.Overlay(curveList)
198
- overlay.opts(legend_muted=False, legend_cols=4, show_legend = True, legend_position='top_left', fontsize={'legend':13},width=1200, height=800)
199
- return overlay
200
-
201
- elif region_value=='us':
202
- top20Ents = ent_freq_maps_us[type_value]
203
- curveList = []
204
- for ent in top20Ents:
205
- entityTriples = top_type_filtered_triples_us[type_value][(top_type_filtered_triples_us[type_value]['subjEntityLinks']==ent[0]) | (top_type_filtered_triples_us[type_value]['objEntityLinks']==ent[0])]
206
- entityTriples_time_indexed = entityTriples.set_index(pd.DatetimeIndex(entityTriples['timestamp']), inplace=False)
207
- del entityTriples_time_indexed['timestamp']
208
- entityTriples_time_indexed_resampled = entityTriples_time_indexed_resampled.reindex(dna_healthtech_articles_us_time_indexed_resampled.index, fill_value=0)
209
- curve = hv.Curve((entityTriples_time_indexed_resampled.index, (entityTriples_time_indexed_resampled['doc_id']/dna_healthtech_articles_us_time_indexed_resampled['ids'])), 'Time', 'Key Entity Occurrence', label=ent[0])
210
- curve.opts(autorange='y')
211
- curveList.append(curve)
212
- overlay = hv.Overlay(curveList)
213
- overlay.opts(legend_muted=False, legend_cols=4, show_legend = True, legend_position='top_left', fontsize={'legend':13},width=1200, height=800)
214
- return overlay
215
-
216
- elif region_value=='eu_us':
217
- top20Ents = ent_freq_maps_eu_us[type_value]
218
- curveList = []
219
- for ent in top20Ents:
220
- entityTriples = top_type_filtered_triples_eu_us[type_value][(top_type_filtered_triples_eu_us[type_value]['subjEntityLinks']==ent[0]) | (top_type_filtered_triples_eu_us[type_value]['objEntityLinks']==ent[0])]
221
- entityTriples_time_indexed = entityTriples.set_index(pd.DatetimeIndex(entityTriples['timestamp']), inplace=False)
222
- del entityTriples_time_indexed['timestamp']
223
- entityTriples_time_indexed_resampled = entityTriples_time_indexed_resampled.reindex(dna_healthtech_articles_eu_us_time_indexed_resampled.index, fill_value=0)
224
- curve = hv.Curve((entityTriples_time_indexed_resampled.index, (entityTriples_time_indexed_resampled['doc_id']/dna_healthtech_articles_eu_us_time_indexed_resampled['ids'])), 'Time', 'Key Entity Occurrence', label=ent[0])
225
- curve.opts(autorange='y')
226
- curveList.append(curve)
227
- overlay = hv.Overlay(curveList)
228
- overlay.opts(legend_muted=False, legend_cols=4, show_legend = True, legend_position='top_left', fontsize={'legend':13},width=1200, height=800)
229
- return overlay
230
-
231
-
232
- ############################# WIDGETS & CALLBACK ###########################################
233
-
234
- def filter_data0(df, min_value):
235
- filtered_df = df[df['value'] >= min_value]
236
- return filtered_df
237
-
238
-
239
- def plot_chord0_new(df,min_value):
240
- filtered_df = filter_data0(df, min_value)
241
- # Create a Holoviews Dataset for nodes
242
- nodes = hv.Dataset(filtered_df, 'index')
243
- nodes.data.head()
244
- chord = hv.Chord(filtered_df, ['source', 'target'], ['value'])
245
- return chord.opts(opts.Chord(cmap='Category20', edge_cmap='Category20', label_text_color="white", node_color = hv.dim('index').str(), edge_color = hv.dim('source').str(), labels = 'index', tools=['hover'], width=800, height=800))
246
-
247
-
248
- def retrieveRegionTypes(region):
249
- if region == 'eu':
250
- return top_type_filtered_eu
251
- elif region == 'us':
252
- return top_type_filtered_us
253
- elif region == 'eu_us':
254
- return top_type_filtered_eu_us
255
-
256
-
257
- def filter_region(region):
258
- if region == 'eu':
259
- region_grouping = grouping_filtered[grouping_filtered['region'] == 'eu']
260
- elif region == 'us':
261
- region_grouping = grouping_filtered[grouping_filtered['region'] == 'us']
262
- elif region == 'eu_us':
263
- region_grouping = grouping_filtered[grouping_filtered['region'] == 'eu_us']
264
-
265
- #print(len(region_grouping))
266
- # Define range for minimum value slider
267
- min_value_range = region_grouping['value'].unique()
268
- min_value_range.sort()
269
-
270
- # Define HoloMap with minimum value and attribute as key dimensions
271
- holomap = hv.HoloMap({min_value: plot_chord0_new(region_grouping, min_value)
272
- for min_value in min_value_range},
273
- kdims=['Show triples with support greater than']
274
- )
275
- return holomap
276
-
277
-
278
- # Define a function to generate Entity List RadioButtonGroup based on Region selection
279
- def generate_radio_buttons(value):
280
- if value == 'eu':
281
- return pn.widgets.RadioButtonGroup(options=retrieveRegionTypes(value), value='DBpedia:Company', name='eu', orientation='vertical')
282
- elif value == 'us':
283
- return pn.widgets.RadioButtonGroup(options=retrieveRegionTypes(value), value='DBpedia:Disease', name='us', orientation='vertical')
284
- elif value == 'eu_us':
285
- return pn.widgets.RadioButtonGroup(options=retrieveRegionTypes(value), value='DBpedia:Person', name='eu_us', orientation='vertical')
286
-
287
-
288
-
289
- # https://tabler-icons.io/
290
- button1 = pn.widgets.Button(name="Introduction", button_type="warning", icon="file-info", styles={"width": "100%"})
291
- button2 = pn.widgets.Button(name="AECO Macro Topics", button_type="warning", icon="chart-histogram", styles={"width": "100%"})
292
- #button3 = pn.widgets.Button(name="Top Entity Types", button_type="warning", icon="chart-bar", styles={"width": "100%"})
293
- #button4 = pn.widgets.Button(name="Top Key Entities", button_type="warning", icon="chart-dots-filled", styles={"width": "100%"})
294
- #button5 = pn.widgets.Button(name="Entity Chord Diagrams", button_type="warning", icon="chart-dots-filled", styles={"width": "100%"})
295
- #button3 = pn.widgets.Button(name="Research Collaboration Networks: Institutes", button_type="warning", icon="chart-dots-3", styles={"width": "100%"})
296
- #button4 = pn.widgets.Button(name="Research Collaboration Networks: Authors", button_type="warning", icon="chart-dots-3", styles={"width": "100%"})
297
-
298
-
299
- region1 = pn.widgets.RadioButtonGroup(name='### Select News Region', options=regions)
300
-
301
- macro_topics_button = pn.widgets.RadioButtonGroup(name='### Select Macro Topic', value='Energy-Efficient Building Design for Thermal Comfort and Sustainability', options=macro_topics)
302
-
303
-
304
- # Initial RadioButtonGroup
305
- radio_buttons_regions = pn.widgets.RadioButtonGroup(options=regions,value='eu',name='Select region')
306
- # Generate initial dynamic RadioButtonGroup
307
- radio_buttons_types = generate_radio_buttons(radio_buttons_regions.value)
308
-
309
-
310
-
311
- # Define a callback function to update the panel dynamically
312
- def update_radio_group(event):
313
- #print(event.new)
314
- #print(retrieveRegionTypes(event.new))
315
- radio_buttons_types.options = retrieveRegionTypes(event.new)
316
-
317
-
318
- # bind the function to the widget(s)
319
- dmap2 = hv.DynamicMap(pn.bind(generate_entity_curves, radio_buttons_regions,radio_buttons_types))
320
- # Bind the selected value of the first RadioButtonGroup to update the second RadioButtonGroup
321
- radio_buttons_regions.param.watch(update_radio_group, 'value')
322
-
323
- # Define the callback function to update the HoloMap
324
- def update_holomap(event):
325
- initial_holomap.object = filter_region(event.new)
326
-
327
- region_radio_button = pn.widgets.RadioButtonGroup(options=regions, value='eu', name='Select Region')
328
-
329
- # Create the initial HoloMap
330
- initial_holomap = filter_region(region_radio_button.value)
331
-
332
- # Bind the callback function to the value change event of the RadioButton widget
333
- region_radio_button.param.watch(update_holomap, 'value')
334
-
335
-
336
-
337
- def show_page(page_key):
338
- main_area.clear()
339
- main_area.append(mapping[page_key])
340
-
341
- button1.on_click(lambda event: show_page("Page1"))
342
- button2.on_click(lambda event: show_page("Page2"))
343
- #button3.on_click(lambda event: show_page("Page3"))
344
- #button4.on_click(lambda event: show_page("Page4"))
345
- #button5.on_click(lambda event: show_page("Page5"))
346
- #button6.on_click(lambda event: show_page("Page6"))
347
-
348
-
349
- ### CREATE PAGE LAYOUTS
350
-
351
- def CreatePage1():
352
- return pn.Column(pn.pane.Markdown("""
353
-
354
- This is a dashboard for a Research Analysis project regarding research and technology in the AECO domain. The source data consists of around
355
- 276k English-language research papers gathered from the openalex.org graph database, covering a timeframe from 2011 through 2024.
356
-
357
- ---------------------------
358
-
359
- ## 1. AECO Macro Topics
360
- In the AECO Macro Topics panel we present the 6-month-sampled time series depicting the number of published research papers
361
- for the 16 macro-topics automatically detected by an optimized BerTopic model and ppst-processed for manual topic merging.
362
-
363
-
364
- ### 2. Research Collaboration Networks: Institutes
365
-
366
- ### 3. Research Collaboration Networks: Authors
367
- """, width=800), align="center")
368
-
369
- def CreatePage2():
370
- # Load the HTML content from the local file
371
- #with open(AECO_topics_over_time_file_path, 'r', encoding='utf-8') as file:
372
- # html_content = file.read()
373
- # Use an iframe to load the local HTML file
374
- iframe_html = f'<iframe src="{AECO_topics_over_time_file_path}" width="100%" height="600px"></iframe>'
375
- # Create an HTML pane to render the content
376
- html_pane = pn.pane.HTML(iframe_html , sizing_mode='stretch_width')
377
- return pn.Column(pn.pane.Markdown(" ## AECO Macro Topics "), html_pane, align="center")
378
-
379
- def CreatePage3():
380
- return pn.Column(
381
- macro_topics_button,
382
- pn.bind(create_bar_charts, region1),
383
- align="center",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
384
  )
385
-
386
- def CreatePage4():
387
- return pn.Column(
388
- pn.pane.Markdown("## Top Key Entities "),
389
- pn.Row(pn.Column(radio_buttons_regions, radio_buttons_types), dmap2),
390
- align="center", )
391
-
392
- def CreatePage5():
393
- return pn.Column(
394
- pn.pane.Markdown("## Entity Chord Diagrams "),
395
- pn.Row(region_radio_button, pn.bind(filter_region, region_radio_button)),
396
- align="center", )
397
-
398
-
399
- def CreatePage6():
400
- html = """<iframe src="https://app.vosviewer.com/?json=https%3A%2F%2Fdrive.google.com%2Fuc%3Fid%3D16q1oLQyEeMosAgeD9UkC9hSrpzAYX_-n" width="800" height="800"></iframe>"""
401
-
402
- html_pane = pn.pane.HTML(html)
403
- #url = 'https://app.vosviewer.com/?json=https%3A%2F%2Fdrive.google.com%2Fuc%3Fid%3D16q1oLQyEeMosAgeD9UkC9hSrpzAYX_-n'
404
- return html_pane
405
- #panel.show()
406
- #return pn.Column(
407
- # pn.pane.Markdown("## VOSViewer Network "),
408
- # pn.Row(panel)
409
- # )
410
-
411
 
412
- mapping = {
413
- "Page1": CreatePage1(),
414
- "Page2": CreatePage2(),
415
- #"Page3": CreatePage3(),
416
- #"Page4": CreatePage4(),
417
- #"Page5": CreatePage5(),
418
- "Page6": CreatePage6()
419
- }
420
-
421
- #################### SIDEBAR LAYOUT ##########################
422
- sidebar = pn.Column(pn.pane.Markdown("## Pages"), button1,button2,#button3,
423
- #button4,
424
- #button5,
425
- #button6,
426
- styles={"width": "100%", "padding": "15px"})
427
-
428
- #################### MAIN AREA LAYOUT ##########################
429
- main_area = pn.Column(mapping["Page1"], styles={"width":"100%"})
430
-
431
- ###################### APP LAYOUT ##############################
432
- template = pn.template.BootstrapTemplate(
433
- title=" AECO Tech Dashboard",
434
- sidebar=[sidebar],
435
- main=[main_area],
436
- header_background="black",
437
- #site="Charting the Landscape of AECO Research",
438
- theme=pn.template.DarkTheme,
439
- sidebar_width=250, ## Default is 330
440
- busy_indicator=pn.indicators.BooleanStatus(value=True),
441
- )
442
-
443
- ### DEPLOY APP
444
 
445
- # Serve the Panel app
446
- template.servable()
 
1
 
2
+ from flask import Flask, send_from_directory
3
  import warnings
4
  warnings.filterwarnings("ignore")
5
  import io
 
32
  from holoviews.operation.timeseries import rolling, rolling_outlier_std
33
  hv.extension('bokeh')
34
 
 
35
 
36
+ # Create a Flask app
37
+ app = Flask(__name__)
38
 
39
+ # Serve the HTML file from the 'static' directory
40
+ @app.route('/static/<path:path>')
41
+ def serve_static(path):
42
+ return send_from_directory('static', path)
43
 
 
44
 
45
+ # Panel-based dashboard
46
+ @app.route('/')
47
+ def dashboard():
48
+
49
+ ## LOAD DATASETS
50
+
51
+ #static_folder = '/static'
52
+ dna_folder = './data'
53
+
54
+
55
+ macro_topics = ["Energy-Efficient Building Design for Thermal Comfort and Sustainability","Indoor Air Quality and Energy Efficiency in Low-Energy Houses","Urban Planning and Development in China\'s Cities", "Design Thinking and Sustainable Product Development", "Smart Cities and Urban Computing", "Urban Resilience and Water Management","Renewable Energy Systems: Solar PV & Building Applications","Exploring the Intersection of Traditional Heritage and Modern Steel Architecture in Historical Buildings","Green Building Assessment and Design","Landscape Design, Planning, and Research: Integrating Cultural, Ecological, and Rural Perspectives", "Noise and Acoustic Design in Urban Development","Sustainable Building Materials: Wood & 3D Printing Innovations","BIM in AEC: Trends, Challenges, and Opportunities","Urban Food Systems: Community Development and Social Sustainability in Cities","Innovative Bridge Design and Construction: Trends and Case Studies", "Cavity Flow and Heat Transfer"]
56
+
57
+
58
+
59
+ ## AECO topic over time html file:
60
+ AECO_topics_over_time_file_path = '/static/optimized_merged_AECO_topics_over_time_2D.html'
61
+
62
+ #### full data unfiltered:
63
+
64
+ dna_articles_unfiltered_eu_time_indexed_resampled = pd.read_csv(os.path.join(dna_folder, 'dna_articles_unfiltered_eu_time_indexed_resampled.tsv'),sep='\t',header=0)
65
+ dna_articles_unfiltered_us_time_indexed_resampled = pd.read_csv(os.path.join(dna_folder, 'dna_articles_unfiltered_us_time_indexed_resampled.tsv'),sep='\t',header=0)
66
+ dna_articles_unfiltered_eu_us_time_indexed_resampled = pd.read_csv(os.path.join(dna_folder, 'dna_articles_unfiltered_eu_us_time_indexed_resampled.tsv'),sep='\t',header=0)
67
+
68
+ #### classifier filtered articles:
69
+
70
+ dh_ration_df_eu = pd.read_csv(os.path.join(dna_folder, 'dh_ration_df_eu.tsv'),sep='\t',header=0)
71
+ dh_ration_df_us = pd.read_csv(os.path.join(dna_folder, 'dh_ration_df_us.tsv'),sep='\t',header=0)
72
+ dh_ration_df_eu_us = pd.read_csv(os.path.join(dna_folder, 'dh_ration_df_eu_us.tsv'),sep='\t',header=0)
73
+
74
+ regions = ['eu', 'us', 'eu_us']
75
+
76
+ sorted_ent_type_freq_map_eu=dict()
77
+ sorted_ent_type_freq_map_us=dict()
78
+ sorted_ent_type_freq_map_eu_us=dict()
79
+
80
+ def read_top_ent_types():
81
+ reader = csv.reader(open(os.path.join(dna_folder, 'sorted_ent_type_freq_map_eu.tsv'), 'r'))
82
+ for i,row in enumerate(reader):
83
+ if i < 20:
84
+ k, v = row
85
+ sorted_ent_type_freq_map_eu[k] = int(v)
86
+ del sorted_ent_type_freq_map_eu['Entity']
87
+ reader = csv.reader(open(os.path.join(dna_folder, 'sorted_ent_type_freq_map_us.tsv'), 'r'))
88
+ for i, row in enumerate(reader):
89
+ if i < 20:
90
+ k, v = row
91
+ sorted_ent_type_freq_map_us[k] = int(v)
92
+ del sorted_ent_type_freq_map_us['Entity']
93
+ reader = csv.reader(open(os.path.join(dna_folder, 'sorted_ent_type_freq_map_eu_us.tsv'), 'r'))
94
+ for i, row in enumerate(reader):
95
+ if i < 20:
96
+ k, v = row
97
+ sorted_ent_type_freq_map_eu_us[k] = int(v)
98
+ del sorted_ent_type_freq_map_eu_us['Entity']
99
+
100
+ read_top_ent_types()
101
+
102
+ top_type_filtered_eu = ['DBpedia:Country', 'DBpedia:Organisation', 'DBpedia:Company', 'DBpedia:Person', 'DBpedia:Disease', 'DBpedia:ChemicalSubstance', 'DBpedia:Drug', 'DBpedia:GovernmentAgency', 'DBpedia:City', 'DBpedia:MonoclonalAntibody']
103
+ top_type_filtered_us = ['DBpedia:Organisation', 'DBpedia:Company', 'DBpedia:Disease', 'DBpedia:ChemicalSubstance', 'DBpedia:Person', 'DBpedia:Drug', 'DBpedia:Country', 'DBpedia:Region', 'DBpedia:MonoclonalAntibody', 'DBpedia:City', 'DBpedia:Biomolecule']
104
+ top_type_filtered_eu_us = ['DBpedia:Organisation', 'DBpedia:Company', 'DBpedia:ChemicalSubstance', 'DBpedia:Drug', 'DBpedia:Country', 'DBpedia:Person', 'DBpedia:Disease', 'DBpedia:MonoclonalAntibody', 'DBpedia:GovernmentAgency', 'DBpedia:Biomolecule', 'DBpedia:Gene']
105
+
106
+ dna_healthtech_articles_eu_time_indexed_resampled=pd.read_csv(os.path.join(dna_folder, 'dna_healthtech_articles_eu_time_indexed_resampled.tsv'),sep='\t',header=0)
107
+ dna_healthtech_articles_us_time_indexed_resampled=pd.read_csv(os.path.join(dna_folder, 'dna_healthtech_articles_us_time_indexed_resampled.tsv'),sep='\t',header=0)
108
+ dna_healthtech_articles_eu_us_time_indexed_resampled=pd.read_csv(os.path.join(dna_folder, 'dna_healthtech_articles_eu_us_time_indexed_resampled.tsv'),sep='\t',header=0)
109
+
110
+ def read_top_ent_maps():
111
+ reader = csv.reader(open(os.path.join(dna_folder, 'sorted_ent_freq_map_eu.tsv'), 'r'), delimiter='\t')
112
+ for row in reader:
113
+ k,v = row
114
+ lista = ast.literal_eval(v)
115
+ dizionario = dict()
116
+ for pair in lista:
117
+ dizionario[pair[0]]=pair[1]
118
+ dizionario = sorted(dizionario.items(), key=lambda x: x[1], reverse=True)
119
+ ent_freq_maps_eu[k]=dizionario
120
+
121
+ reader = csv.reader(open(os.path.join(dna_folder, 'sorted_ent_freq_map_us.tsv'), 'r'), delimiter='\t')
122
+ for row in reader:
123
  k, v = row
124
+ lista = ast.literal_eval(v)
125
+ dizionario = dict()
126
+ for pair in lista:
127
+ dizionario[pair[0]] = pair[1]
128
+ dizionario = sorted(dizionario.items(), key=lambda x: x[1], reverse=True)
129
+ ent_freq_maps_us[k] = dizionario
130
+
131
+ reader = csv.reader(open(os.path.join(dna_folder, 'sorted_ent_freq_map_eu_us.tsv'), 'r'), delimiter='\t')
132
+ for row in reader:
133
  k, v = row
134
+ lista = ast.literal_eval(v)
135
+ dizionario = dict()
136
+ for pair in lista:
137
+ dizionario[pair[0]] = pair[1]
138
+ dizionario = sorted(dizionario.items(), key=lambda x: x[1], reverse=True)
139
+ ent_freq_maps_eu_us[k] = dizionario
140
+
141
+ ent_freq_maps_eu = dict()
142
+ ent_freq_maps_us = dict()
143
+ ent_freq_maps_eu_us = dict()
144
+
145
+ read_top_ent_maps()
146
+
147
+
148
+ def read_type_filtered_triples():
149
+ for t in top_type_filtered_eu:
150
+ df = pd.read_csv(dna_folder+'/filtered_rows/eu/'+t.replace(':','_')+'.tsv', sep=" ", header=0)
151
+ df.drop(columns=['Unnamed: 0'], inplace=True)
152
+ top_type_filtered_triples_eu[t]=df
153
+ for t in top_type_filtered_us:
154
+ df = pd.read_csv(dna_folder+'/filtered_rows/us/'+t.replace(':','_')+'.tsv', sep=" ")
155
+ df.drop(columns=['Unnamed: 0'], inplace=True)
156
+ top_type_filtered_triples_us[t]=df
157
+ for t in top_type_filtered_eu_us:
158
+ df = pd.read_csv(dna_folder+'/filtered_rows/eu_us/'+t.replace(':','_')+'.tsv', sep=" ")
159
+ df.drop(columns=['Unnamed: 0'], inplace=True)
160
+ top_type_filtered_triples_eu_us[t]=df
161
+
162
+
163
+
164
+ top_type_filtered_triples_eu = dict()
165
+ top_type_filtered_triples_us = dict()
166
+ top_type_filtered_triples_eu_us = dict()
167
+
168
+ read_type_filtered_triples()
169
+
170
+ grouping_filtered = pd.read_csv(os.path.join(dna_folder, 'dna_relations.tsv'), sep=" ")
171
+ ################################# CREATE CHARTS ############################
172
+ def create_curve_chart():
173
+ # Create the 3 line plots
174
+ curve_eu = hv.Curve((dh_ration_df_eu.index, dh_ration_df_eu.ids/dna_articles_unfiltered_eu_time_indexed_resampled.ids), 'Time', 'Digital Health News Ratio',label='EU')
175
+ curve_us = hv.Curve((dh_ration_df_us.index, dh_ration_df_us.ids/dna_articles_unfiltered_us_time_indexed_resampled.ids),'Time', 'Digital Health News Ratio', label='US')
176
+ curve_eu_us = hv.Curve((dh_ration_df_eu_us.index, dh_ration_df_eu_us.ids/dna_articles_unfiltered_eu_us_time_indexed_resampled.ids),'Time', 'Digital Health News Ratio', label='EU-US')
177
+ #Overlay the line plots
178
+ overlay = curve_eu * curve_us * curve_eu_us
179
+ overlay.opts(show_legend = True, legend_position='top_left', width=1200, height=600)
180
+ return overlay
181
+
182
+
183
+ def create_bar_charts(region, **kwargs):
184
+ if region=='eu':
185
+ sliced = sorted_ent_type_freq_map_eu
186
+ return hv.Bars(sliced, hv.Dimension('Entity Types'), 'Frequency').opts( framewise=True, xrotation=45,width=1200, height=600)
187
+ elif region=='us':
188
+ sliced = sorted_ent_type_freq_map_us
189
+ return hv.Bars(sliced, hv.Dimension('Entity Types'), 'Frequency').opts(framewise=True, xrotation=45,width=1200, height=600)
190
+ elif region=='eu_us':
191
+ sliced = sorted_ent_type_freq_map_eu_us
192
+ return hv.Bars(sliced, hv.Dimension('Entity Types'), 'Frequency').opts(framewise=True, xrotation=45,width=1200, height=600)
193
+
194
+
195
+
196
+ # Define a function to generate Curve based on selected values
197
+ def generate_entity_curves(region_value, type_value, **kwargs):
198
+ if region_value=='eu':
199
+ top20Ents = ent_freq_maps_eu[type_value]
200
+ curveList = []
201
+ for ent in top20Ents:
202
+ entityTriples = top_type_filtered_triples_eu[type_value][(top_type_filtered_triples_eu[type_value]['subjEntityLinks']==ent[0]) | (top_type_filtered_triples_eu[type_value]['objEntityLinks']==ent[0])]
203
+ entityTriples_time_indexed = entityTriples.set_index(pd.DatetimeIndex(entityTriples['timestamp']), inplace=False)
204
+ del entityTriples_time_indexed['timestamp']
205
+ entityTriples_time_indexed_resampled = entityTriples_time_indexed.resample("Y").count()
206
+ #print(entityTriples_time_indexed_resampled)
207
+ entityTriples_time_indexed_resampled = entityTriples_time_indexed_resampled.reindex(dna_healthtech_articles_eu_time_indexed_resampled.index, fill_value=0)
208
+ curve = hv.Curve((entityTriples_time_indexed_resampled.index, (entityTriples_time_indexed_resampled['doc_id']/dna_healthtech_articles_eu_time_indexed_resampled['ids'])), 'Time', 'Key Entity Occurrence', label=ent[0])
209
+ curve.opts(autorange='y')
210
+ #curve.opts(logy=True)
211
+ curveList.append(curve)
212
+ overlay = hv.Overlay(curveList)
213
+ overlay.opts(legend_muted=False, legend_cols=4, show_legend = True, legend_position='top_left', fontsize={'legend':13},width=1200, height=800)
214
+ return overlay
215
+
216
+ elif region_value=='us':
217
+ top20Ents = ent_freq_maps_us[type_value]
218
+ curveList = []
219
+ for ent in top20Ents:
220
+ entityTriples = top_type_filtered_triples_us[type_value][(top_type_filtered_triples_us[type_value]['subjEntityLinks']==ent[0]) | (top_type_filtered_triples_us[type_value]['objEntityLinks']==ent[0])]
221
+ entityTriples_time_indexed = entityTriples.set_index(pd.DatetimeIndex(entityTriples['timestamp']), inplace=False)
222
+ del entityTriples_time_indexed['timestamp']
223
+ entityTriples_time_indexed_resampled = entityTriples_time_indexed_resampled.reindex(dna_healthtech_articles_us_time_indexed_resampled.index, fill_value=0)
224
+ curve = hv.Curve((entityTriples_time_indexed_resampled.index, (entityTriples_time_indexed_resampled['doc_id']/dna_healthtech_articles_us_time_indexed_resampled['ids'])), 'Time', 'Key Entity Occurrence', label=ent[0])
225
+ curve.opts(autorange='y')
226
+ curveList.append(curve)
227
+ overlay = hv.Overlay(curveList)
228
+ overlay.opts(legend_muted=False, legend_cols=4, show_legend = True, legend_position='top_left', fontsize={'legend':13},width=1200, height=800)
229
+ return overlay
230
+
231
+ elif region_value=='eu_us':
232
+ top20Ents = ent_freq_maps_eu_us[type_value]
233
+ curveList = []
234
+ for ent in top20Ents:
235
+ entityTriples = top_type_filtered_triples_eu_us[type_value][(top_type_filtered_triples_eu_us[type_value]['subjEntityLinks']==ent[0]) | (top_type_filtered_triples_eu_us[type_value]['objEntityLinks']==ent[0])]
236
+ entityTriples_time_indexed = entityTriples.set_index(pd.DatetimeIndex(entityTriples['timestamp']), inplace=False)
237
+ del entityTriples_time_indexed['timestamp']
238
+ entityTriples_time_indexed_resampled = entityTriples_time_indexed_resampled.reindex(dna_healthtech_articles_eu_us_time_indexed_resampled.index, fill_value=0)
239
+ curve = hv.Curve((entityTriples_time_indexed_resampled.index, (entityTriples_time_indexed_resampled['doc_id']/dna_healthtech_articles_eu_us_time_indexed_resampled['ids'])), 'Time', 'Key Entity Occurrence', label=ent[0])
240
+ curve.opts(autorange='y')
241
+ curveList.append(curve)
242
+ overlay = hv.Overlay(curveList)
243
+ overlay.opts(legend_muted=False, legend_cols=4, show_legend = True, legend_position='top_left', fontsize={'legend':13},width=1200, height=800)
244
+ return overlay
245
+
246
+
247
+ ############################# WIDGETS & CALLBACK ###########################################
248
+
249
+ def filter_data0(df, min_value):
250
+ filtered_df = df[df['value'] >= min_value]
251
+ return filtered_df
252
+
253
+
254
+ def plot_chord0_new(df,min_value):
255
+ filtered_df = filter_data0(df, min_value)
256
+ # Create a Holoviews Dataset for nodes
257
+ nodes = hv.Dataset(filtered_df, 'index')
258
+ nodes.data.head()
259
+ chord = hv.Chord(filtered_df, ['source', 'target'], ['value'])
260
+ return chord.opts(opts.Chord(cmap='Category20', edge_cmap='Category20', label_text_color="white", node_color = hv.dim('index').str(), edge_color = hv.dim('source').str(), labels = 'index', tools=['hover'], width=800, height=800))
261
+
262
+
263
+ def retrieveRegionTypes(region):
264
+ if region == 'eu':
265
+ return top_type_filtered_eu
266
+ elif region == 'us':
267
+ return top_type_filtered_us
268
+ elif region == 'eu_us':
269
+ return top_type_filtered_eu_us
270
+
271
+
272
+ def filter_region(region):
273
+ if region == 'eu':
274
+ region_grouping = grouping_filtered[grouping_filtered['region'] == 'eu']
275
+ elif region == 'us':
276
+ region_grouping = grouping_filtered[grouping_filtered['region'] == 'us']
277
+ elif region == 'eu_us':
278
+ region_grouping = grouping_filtered[grouping_filtered['region'] == 'eu_us']
279
+
280
+ #print(len(region_grouping))
281
+ # Define range for minimum value slider
282
+ min_value_range = region_grouping['value'].unique()
283
+ min_value_range.sort()
284
+
285
+ # Define HoloMap with minimum value and attribute as key dimensions
286
+ holomap = hv.HoloMap({min_value: plot_chord0_new(region_grouping, min_value)
287
+ for min_value in min_value_range},
288
+ kdims=['Show triples with support greater than']
289
+ )
290
+ return holomap
291
+
292
+
293
+ # Define a function to generate Entity List RadioButtonGroup based on Region selection
294
+ def generate_radio_buttons(value):
295
+ if value == 'eu':
296
+ return pn.widgets.RadioButtonGroup(options=retrieveRegionTypes(value), value='DBpedia:Company', name='eu', orientation='vertical')
297
+ elif value == 'us':
298
+ return pn.widgets.RadioButtonGroup(options=retrieveRegionTypes(value), value='DBpedia:Disease', name='us', orientation='vertical')
299
+ elif value == 'eu_us':
300
+ return pn.widgets.RadioButtonGroup(options=retrieveRegionTypes(value), value='DBpedia:Person', name='eu_us', orientation='vertical')
301
+
302
+
303
+
304
+ # https://tabler-icons.io/
305
+ button1 = pn.widgets.Button(name="Introduction", button_type="warning", icon="file-info", styles={"width": "100%"})
306
+ button2 = pn.widgets.Button(name="AECO Macro Topics", button_type="warning", icon="chart-histogram", styles={"width": "100%"})
307
+ #button3 = pn.widgets.Button(name="Top Entity Types", button_type="warning", icon="chart-bar", styles={"width": "100%"})
308
+ #button4 = pn.widgets.Button(name="Top Key Entities", button_type="warning", icon="chart-dots-filled", styles={"width": "100%"})
309
+ #button5 = pn.widgets.Button(name="Entity Chord Diagrams", button_type="warning", icon="chart-dots-filled", styles={"width": "100%"})
310
+ #button3 = pn.widgets.Button(name="Research Collaboration Networks: Institutes", button_type="warning", icon="chart-dots-3", styles={"width": "100%"})
311
+ #button4 = pn.widgets.Button(name="Research Collaboration Networks: Authors", button_type="warning", icon="chart-dots-3", styles={"width": "100%"})
312
+
313
+
314
+ region1 = pn.widgets.RadioButtonGroup(name='### Select News Region', options=regions)
315
+
316
+ macro_topics_button = pn.widgets.RadioButtonGroup(name='### Select Macro Topic', value='Energy-Efficient Building Design for Thermal Comfort and Sustainability', options=macro_topics)
317
+
318
+
319
+ # Initial RadioButtonGroup
320
+ radio_buttons_regions = pn.widgets.RadioButtonGroup(options=regions,value='eu',name='Select region')
321
+ # Generate initial dynamic RadioButtonGroup
322
+ radio_buttons_types = generate_radio_buttons(radio_buttons_regions.value)
323
+
324
+
325
+
326
+ # Define a callback function to update the panel dynamically
327
+ def update_radio_group(event):
328
+ #print(event.new)
329
+ #print(retrieveRegionTypes(event.new))
330
+ radio_buttons_types.options = retrieveRegionTypes(event.new)
331
+
332
+
333
+ # bind the function to the widget(s)
334
+ dmap2 = hv.DynamicMap(pn.bind(generate_entity_curves, radio_buttons_regions,radio_buttons_types))
335
+ # Bind the selected value of the first RadioButtonGroup to update the second RadioButtonGroup
336
+ radio_buttons_regions.param.watch(update_radio_group, 'value')
337
+
338
+ # Define the callback function to update the HoloMap
339
+ def update_holomap(event):
340
+ initial_holomap.object = filter_region(event.new)
341
+
342
+ region_radio_button = pn.widgets.RadioButtonGroup(options=regions, value='eu', name='Select Region')
343
+
344
+ # Create the initial HoloMap
345
+ initial_holomap = filter_region(region_radio_button.value)
346
+
347
+ # Bind the callback function to the value change event of the RadioButton widget
348
+ region_radio_button.param.watch(update_holomap, 'value')
349
+
350
+
351
+
352
+ def show_page(page_key):
353
+ main_area.clear()
354
+ main_area.append(mapping[page_key])
355
+
356
+ button1.on_click(lambda event: show_page("Page1"))
357
+ button2.on_click(lambda event: show_page("Page2"))
358
+ #button3.on_click(lambda event: show_page("Page3"))
359
+ #button4.on_click(lambda event: show_page("Page4"))
360
+ #button5.on_click(lambda event: show_page("Page5"))
361
+ #button6.on_click(lambda event: show_page("Page6"))
362
+
363
+
364
+ ### CREATE PAGE LAYOUTS
365
+
366
+ def CreatePage1():
367
+ return pn.Column(pn.pane.Markdown("""
368
+
369
+ This is a dashboard for a Research Analysis project regarding research and technology in the AECO domain. The source data consists of around
370
+ 276k English-language research papers gathered from the openalex.org graph database, covering a timeframe from 2011 through 2024.
371
+
372
+ ---------------------------
373
+
374
+ ## 1. AECO Macro Topics
375
+ In the AECO Macro Topics panel we present the 6-month-sampled time series depicting the number of published research papers
376
+ for the 16 macro-topics automatically detected by an optimized BerTopic model and ppst-processed for manual topic merging.
377
+
378
+
379
+ ### 2. Research Collaboration Networks: Institutes
380
+
381
+ ### 3. Research Collaboration Networks: Authors
382
+ """, width=800), align="center")
383
+
384
+ def CreatePage2():
385
+ # Load the HTML content from the local file
386
+ #with open(AECO_topics_over_time_file_path, 'r', encoding='utf-8') as file:
387
+ # html_content = file.read()
388
+ # Use an iframe to load the local HTML file
389
+ iframe_html = f'<iframe src="{AECO_topics_over_time_file_path}" width="100%" height="600px"></iframe>'
390
+ # Create an HTML pane to render the content
391
+ html_pane = pn.pane.HTML(iframe_html , sizing_mode='stretch_width')
392
+ return pn.Column(pn.pane.Markdown(" ## AECO Macro Topics "), html_pane, align="center")
393
+
394
+ def CreatePage3():
395
+ return pn.Column(
396
+ macro_topics_button,
397
+ pn.bind(create_bar_charts, region1),
398
+ align="center",
399
+ )
400
+
401
+ def CreatePage4():
402
+ return pn.Column(
403
+ pn.pane.Markdown("## Top Key Entities "),
404
+ pn.Row(pn.Column(radio_buttons_regions, radio_buttons_types), dmap2),
405
+ align="center", )
406
+
407
+ def CreatePage5():
408
+ return pn.Column(
409
+ pn.pane.Markdown("## Entity Chord Diagrams "),
410
+ pn.Row(region_radio_button, pn.bind(filter_region, region_radio_button)),
411
+ align="center", )
412
+
413
+
414
+ def CreatePage6():
415
+ html = """<iframe src="https://app.vosviewer.com/?json=https%3A%2F%2Fdrive.google.com%2Fuc%3Fid%3D16q1oLQyEeMosAgeD9UkC9hSrpzAYX_-n" width="800" height="800"></iframe>"""
416
+
417
+ html_pane = pn.pane.HTML(html)
418
+ #url = 'https://app.vosviewer.com/?json=https%3A%2F%2Fdrive.google.com%2Fuc%3Fid%3D16q1oLQyEeMosAgeD9UkC9hSrpzAYX_-n'
419
+ return html_pane
420
+ #panel.show()
421
+ #return pn.Column(
422
+ # pn.pane.Markdown("## VOSViewer Network "),
423
+ # pn.Row(panel)
424
+ # )
425
+
426
+
427
+ mapping = {
428
+ "Page1": CreatePage1(),
429
+ "Page2": CreatePage2(),
430
+ #"Page3": CreatePage3(),
431
+ #"Page4": CreatePage4(),
432
+ #"Page5": CreatePage5(),
433
+ "Page6": CreatePage6()
434
+ }
435
+
436
+ #################### SIDEBAR LAYOUT ##########################
437
+ sidebar = pn.Column(pn.pane.Markdown("## Pages"), button1,button2,#button3,
438
+ #button4,
439
+ #button5,
440
+ #button6,
441
+ styles={"width": "100%", "padding": "15px"})
442
+
443
+ #################### MAIN AREA LAYOUT ##########################
444
+ main_area = pn.Column(mapping["Page1"], styles={"width":"100%"})
445
+
446
+ ###################### APP LAYOUT ##############################
447
+ template = pn.template.BootstrapTemplate(
448
+ title=" AECO Tech Dashboard",
449
+ sidebar=[sidebar],
450
+ main=[main_area],
451
+ header_background="black",
452
+ #site="Charting the Landscape of AECO Research",
453
+ theme=pn.template.DarkTheme,
454
+ sidebar_width=250, ## Default is 330
455
+ busy_indicator=pn.indicators.BooleanStatus(value=True),
456
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
457
 
458
+ ### DEPLOY APP
459
+
460
+ # Serve the Panel app
461
+ template.servable()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
462
 
463
+ if __name__ == "__main__":
464
+ app.run(host="0.0.0.0", port=7860)