zavavan commited on
Commit
0f6df01
·
verified ·
1 Parent(s): 06d2d25

Update dashboard.py

Browse files
Files changed (1) hide show
  1. dashboard.py +136 -429
dashboard.py CHANGED
@@ -1,8 +1,5 @@
1
- import json
2
- import warnings
3
-
4
- from bokeh.models import DatetimeTicker, DatetimeTickFormatter
5
 
 
6
  warnings.filterwarnings("ignore")
7
  import io
8
  import os
@@ -34,25 +31,22 @@ from bokeh.resources import INLINE
34
  from holoviews.operation.timeseries import rolling, rolling_outlier_std
35
  hv.extension('bokeh')
36
 
37
-
38
-
39
-
40
  ## LOAD DATASETS
41
 
42
- data_folder = './data'
43
 
44
- country_name_df = pd.read_csv(os.path.join(data_folder, 'country_name_map.tsv'), header=0, sep='\t', lineterminator='\n', low_memory=False)
45
- country_name_map = dict(zip(country_name_df.Country_Code, country_name_df.Country_Name))
46
 
47
- total_publications_time_indexed = pd.read_csv(os.path.join(data_folder, 'total_publications_time_indexed.tsv'), header=0, sep='\t', lineterminator='\n', low_memory=False)
48
- country_publications_time_indexed = pd.read_csv(os.path.join(data_folder, 'country_publications_time_indexed.tsv'), header=0, sep='\t', lineterminator='\n', low_memory=False)
49
 
 
 
 
50
 
51
- ## AECO topic over time html file:
52
- AECO_topics_over_time_file_path = '/assets/optimized_merged_AECO_topics_over_time_2D_gpt_labels.html'
53
- AECO_topics_dendogram_file_path = '/assets/topic_hierarchy_optimal_params.htm'
54
- AECO_topic_map_path = '/assets/document_datamap_ver2.html'
55
 
 
 
 
56
 
57
  regions = ['eu', 'us', 'eu_us']
58
 
@@ -61,19 +55,19 @@ sorted_ent_type_freq_map_us=dict()
61
  sorted_ent_type_freq_map_eu_us=dict()
62
 
63
  def read_top_ent_types():
64
- reader = csv.reader(open(os.path.join(data_folder, 'sorted_ent_type_freq_map_eu.tsv'), 'r'))
65
  for i,row in enumerate(reader):
66
  if i < 20:
67
  k, v = row
68
  sorted_ent_type_freq_map_eu[k] = int(v)
69
  del sorted_ent_type_freq_map_eu['Entity']
70
- reader = csv.reader(open(os.path.join(data_folder, 'sorted_ent_type_freq_map_us.tsv'), 'r'))
71
  for i, row in enumerate(reader):
72
  if i < 20:
73
  k, v = row
74
  sorted_ent_type_freq_map_us[k] = int(v)
75
  del sorted_ent_type_freq_map_us['Entity']
76
- reader = csv.reader(open(os.path.join(data_folder, 'sorted_ent_type_freq_map_eu_us.tsv'), 'r'))
77
  for i, row in enumerate(reader):
78
  if i < 20:
79
  k, v = row
@@ -86,9 +80,12 @@ top_type_filtered_eu = ['DBpedia:Country', 'DBpedia:Organisation', 'DBpedia:Comp
86
  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']
87
  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']
88
 
 
 
 
89
 
90
  def read_top_ent_maps():
91
- reader = csv.reader(open(os.path.join(data_folder, 'sorted_ent_freq_map_eu.tsv'), 'r'), delimiter='\t')
92
  for row in reader:
93
  k,v = row
94
  lista = ast.literal_eval(v)
@@ -98,7 +95,7 @@ def read_top_ent_maps():
98
  dizionario = sorted(dizionario.items(), key=lambda x: x[1], reverse=True)
99
  ent_freq_maps_eu[k]=dizionario
100
 
101
- reader = csv.reader(open(os.path.join(data_folder, 'sorted_ent_freq_map_us.tsv'), 'r'), delimiter='\t')
102
  for row in reader:
103
  k, v = row
104
  lista = ast.literal_eval(v)
@@ -108,7 +105,7 @@ def read_top_ent_maps():
108
  dizionario = sorted(dizionario.items(), key=lambda x: x[1], reverse=True)
109
  ent_freq_maps_us[k] = dizionario
110
 
111
- reader = csv.reader(open(os.path.join(data_folder, 'sorted_ent_freq_map_eu_us.tsv'), 'r'), delimiter='\t')
112
  for row in reader:
113
  k, v = row
114
  lista = ast.literal_eval(v)
@@ -127,15 +124,15 @@ read_top_ent_maps()
127
 
128
  def read_type_filtered_triples():
129
  for t in top_type_filtered_eu:
130
- df = pd.read_csv(data_folder+'/filtered_rows/eu/'+t.replace(':','_')+'.tsv', sep=" ", header=0)
131
  df.drop(columns=['Unnamed: 0'], inplace=True)
132
  top_type_filtered_triples_eu[t]=df
133
  for t in top_type_filtered_us:
134
- df = pd.read_csv(data_folder+'/filtered_rows/us/'+t.replace(':','_')+'.tsv', sep=" ")
135
  df.drop(columns=['Unnamed: 0'], inplace=True)
136
  top_type_filtered_triples_us[t]=df
137
  for t in top_type_filtered_eu_us:
138
- df = pd.read_csv(data_folder+'/filtered_rows/eu_us/'+t.replace(':','_')+'.tsv', sep=" ")
139
  df.drop(columns=['Unnamed: 0'], inplace=True)
140
  top_type_filtered_triples_eu_us[t]=df
141
 
@@ -147,238 +144,83 @@ top_type_filtered_triples_eu_us = dict()
147
 
148
  read_type_filtered_triples()
149
 
150
- grouping_filtered = pd.read_csv(os.path.join(data_folder, 'dna_relations.tsv'), sep=" ")
151
-
152
-
153
- def load_topic2toptasks():
154
- with open(os.path.join(data_folder+'/time_series','topic2toptasks.json'), "r", encoding="utf-8") as file:
155
- mapping = json.load(file)
156
-
157
- return mapping
158
-
159
-
160
-
161
- def loadTaskMethodTimeSeries(topic,task):
162
-
163
- task_method_ts = pd.read_csv(os.path.join(data_folder+'/time_series', f"""{topic}_{task}_time_series.csv"""),
164
- header=0, sep=',', lineterminator='\n', low_memory=False)
165
-
166
- task_method_ts.set_index(task_method_ts.columns[0], inplace=True)
167
- return task_method_ts
168
-
169
-
170
- def loadTaskTimeSeries(topic):
171
- #cluster_{cluster_id}_TASK_time_series.csv
172
- task_ts = pd.read_csv(os.path.join(data_folder+'/time_series', f"""cluster_{topic}_TASK_time_series.csv"""),
173
- header=0, sep=',', lineterminator='\n', low_memory=False)
174
-
175
- task_ts.set_index(task_ts.columns[0], inplace=True)
176
- return task_ts
177
-
178
- def loadMethodTimeSeries(topic):
179
-
180
- method_ts = pd.read_csv(os.path.join(data_folder+'/time_series', f"""cluster_{topic}_METHOD_time_series.csv"""),
181
- header=0, sep=',', lineterminator='\n', low_memory=False)
182
-
183
- method_ts.set_index(method_ts.columns[0], inplace=True)
184
- return method_ts
185
-
186
-
187
- ################################# CREATE CHARTS ############################
188
  ################################# CREATE CHARTS ############################
189
-
190
- # Hook function to customize x-axis for Bokeh
191
- def customize_x_axis_bokeh(plot, element):
192
- bokeh_plot = plot.state
193
- bokeh_plot.xaxis.formatter = DatetimeTickFormatter(months='%m%Y')
194
- bokeh_plot.xaxis.ticker.desired_num_ticks = 12
195
- def create_publication_curve_chart():
196
- country_name_df = pd.read_csv(os.path.join(data_folder, 'country_name_map.tsv'), header=0, sep='\t', lineterminator='\n', low_memory=False)
197
- country_name_map = dict(zip(country_name_df.Country_Code, country_name_df.Country_Name))
198
- #country_name_map
199
- total_publications_time_indexed = pd.read_csv(os.path.join(data_folder, 'total_publications_time_indexed.tsv'), header=0, sep='\t', lineterminator='\n', low_memory=False)
200
- total_publications_time_indexed['month_bin'] = pd.to_datetime(total_publications_time_indexed['month_bin'])
201
-
202
- country_publications_time_indexed = pd.read_csv(os.path.join(data_folder, 'country_publications_time_indexed.tsv'), header=0, sep='\t', lineterminator='\n', low_memory=False)
203
- total_publications_time_indexed.id = np.log1p(total_publications_time_indexed.id)
204
- country_publications_time_indexed = country_publications_time_indexed.applymap(lambda x: np.log1p(x) if np.issubdtype(type(x), np.number) else x)
205
- curve_total = hv.Curve((total_publications_time_indexed.month_bin, total_publications_time_indexed.id), 'Time', 'Publication Counts (log)',label='Total')
206
  #Overlay the line plots
207
- overlay = curve_total
208
- curve_countries = []
209
- for country in country_name_map.keys():
210
- overlay = overlay * hv.Curve((total_publications_time_indexed.month_bin, country_publications_time_indexed[country]), label=country_name_map[country])
211
- overlay.opts(show_legend=True,legend_position='right', width=1400, height=900, hooks=[customize_x_axis_bokeh])
212
  return overlay
213
 
214
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
215
 
216
- macro_topics_mapping = {"Energy Efficiency and Thermal Comfort in Building Environments":0,
217
- "Indoor Air Quality and Sustainable Air Conditioning Systems":1,
218
- "Urban Development Strategies and Sustainable City Planning":2,
219
- "Enhancing Child-Friendly Urban Spaces Through Design":3,
220
- "Smart city development and urban data management":4,
221
- "Urban Resilience and Green Infrastructure in Climate Change Planning":5,
222
- "Architectural Integration of Solar Photovoltaic Systems in Buildings":6,
223
- "Preservation and Evolution of Traditional Architecture in Modern Contexts":7,
224
- "Sustainable Building Construction and Design with Environmental Assessment":8,
225
- "Landscape Planning and Design Theory":9,
226
- "Urban Sound Environment Research in Architectural Design":10,
227
- "Sustainable Construction Materials and Technologies":11,
228
- "Utilizing BIM in Construction and Building Information Modeling Industry":12,
229
- "Urban Agriculture and Sustainable Food Systems":13,
230
- "Sustainable Bridge Design and Construction":14,
231
- "Investigation of Cavity Dynamics and Heat Transfer in Various Flow Scenarios":15}
232
-
233
- macro_topics_active_subset = ["Energy Efficiency and Thermal Comfort in Building Environments","Architectural Integration of Solar Photovoltaic Systems in Buildings","Utilizing BIM in Construction and Building Information Modeling Industry"]
234
-
235
- def load_institute_network(topic, **kwargs):
236
- if topic=='Energy Efficiency and Thermal Comfort in Building Environments':
237
- html = """<iframe src="https://tinyurl.com/2d4gl4tl" width="1000" height="800"></iframe>"""
238
- html_pane = pn.pane.HTML(html)
239
- return html_pane
240
- elif topic=='Indoor Air Quality and Sustainable Air Conditioning Systems':
241
- html = """<iframe src="https://app.vosviewer.com/?json=https%3A%2F%2Fdrive.google.com%2Fuc%3Fid%3D1rqPx3X_9Hnv9mTq2bMCbWWh5VIOw9CRh" width="1000" height="800"></iframe>"""
242
- html_pane = pn.pane.HTML(html)
243
- return html_pane
244
- elif topic=='Urban Development Strategies and Sustainable City Planning':
245
- html = """<iframe src="" width="1000" height="800"></iframe>"""
246
- html_pane = pn.pane.HTML(html)
247
- return html_pane
248
- elif topic=='Enhancing Child-Friendly Urban Spaces Through Design':
249
- html = """<iframe src="" width="1000" height="800"></iframe>"""
250
- html_pane = pn.pane.HTML(html)
251
- return html_pane
252
- elif topic=='Smart city development and urban data management':
253
- html = """<iframe src="" width="1000" height="800"></iframe>"""
254
- html_pane = pn.pane.HTML(html)
255
- return html_pane
256
- elif topic=='Urban Resilience and Green Infrastructure in Climate Change Planning':
257
- html = """<iframe src="" width="1000" height="800"></iframe>"""
258
- html_pane = pn.pane.HTML(html)
259
- return html_pane
260
- elif topic=='Architectural Integration of Solar Photovoltaic Systems in Buildings':
261
- html = """<iframe src="https://tinyurl.com/2a2ha2r8" width="1000" height="800"></iframe>"""
262
- html_pane = pn.pane.HTML(html)
263
- return html_pane
264
- elif topic=='Preservation and Evolution of Traditional Architecture in Modern Contexts':
265
- html = """<iframe src="" width="1000" height="800"></iframe>"""
266
- html_pane = pn.pane.HTML(html)
267
- return html_pane
268
- elif topic=='Sustainable Building Construction and Design with Environmental Assessment':
269
- html = """<iframe src="" width="1000" height="800"></iframe>"""
270
- html_pane = pn.pane.HTML(html)
271
- return html_pane
272
- elif topic=='Landscape Planning and Design Theory':
273
- html = """<iframe src="" width="1000" height="800"></iframe>"""
274
- html_pane = pn.pane.HTML(html)
275
- return html_pane
276
- elif topic=='Urban Sound Environment Research in Architectural Design':
277
- html = """<iframe src="" width="1000" height="800"></iframe>"""
278
- html_pane = pn.pane.HTML(html)
279
- return html_pane
280
- elif topic=='Sustainable Construction Materials and Technologies':
281
- html = """<iframe src="" width="1000" height="800"></iframe>"""
282
- html_pane = pn.pane.HTML(html)
283
- return html_pane
284
- elif topic=='Utilizing BIM in Construction and Building Information Modeling Industry':
285
- html = """<iframe src="https://app.vosviewer.com/?json=https%3A%2F%2Fdrive.google.com%2Fuc%3Fid%3D1V-Cto19dxV_GR3MtNP6Yk642CnTQkjEK" width="1000" height="800"></iframe>"""
286
- html_pane = pn.pane.HTML(html)
287
- return html_pane
288
- elif topic=='Urban Agriculture and Sustainable Food Systems':
289
- html = """<iframe src="" width="1000" height="800"></iframe>"""
290
- html_pane = pn.pane.HTML(html)
291
- return html_pane
292
- elif topic=='Sustainable Bridge Design and Construction':
293
- html = """<iframe src="" width="1000" height="800"></iframe>"""
294
- html_pane = pn.pane.HTML(html)
295
- return html_pane
296
- elif topic=='Investigation of Cavity Dynamics and Heat Transfer in Various Flow Scenarios':
297
- html = """<iframe src="" width="1000" height="800"></iframe>"""
298
- html_pane = pn.pane.HTML(html)
299
- return html_pane
300
-
301
-
302
- def load_country_network(topic, **kwargs):
303
- if topic=='Energy Efficiency and Thermal Comfort in Building Environments':
304
- html = """<iframe src="https://tinyurl.com/2b7sqbdc" width="1000" height="800"></iframe>"""
305
- html_pane = pn.pane.HTML(html)
306
- return html_pane
307
- elif topic=='Indoor Air Quality and Sustainable Air Conditioning Systems':
308
- html = """<iframe src="" width="1000" height="800"></iframe>"""
309
- html_pane = pn.pane.HTML(html)
310
- return html_pane
311
- elif topic=='Urban Development Strategies and Sustainable City Planning':
312
- html = """<iframe src="" width="1000" height="800"></iframe>"""
313
- html_pane = pn.pane.HTML(html)
314
- return html_pane
315
- elif topic=='Enhancing Child-Friendly Urban Spaces Through Design':
316
- html = """<iframe src="" width="1000" height="800"></iframe>"""
317
- html_pane = pn.pane.HTML(html)
318
- return html_pane
319
- elif topic=='Smart city development and urban data management':
320
- html = """<iframe src="" width="1000" height="800"></iframe>"""
321
- html_pane = pn.pane.HTML(html)
322
- return html_pane
323
- elif topic=='Urban Resilience and Green Infrastructure in Climate Change Planning':
324
- html = """<iframe src="" width="1000" height="800"></iframe>"""
325
- html_pane = pn.pane.HTML(html)
326
- return html_pane
327
- elif topic=='Architectural Integration of Solar Photovoltaic Systems in Buildings':
328
- html = """<iframe src="https://tinyurl.com/29mkxzep" width="1000" height="800"></iframe>"""
329
- html_pane = pn.pane.HTML(html)
330
- return html_pane
331
- elif topic=='Preservation and Evolution of Traditional Architecture in Modern Contexts':
332
- html = """<iframe src="" width="1000" height="800"></iframe>"""
333
- html_pane = pn.pane.HTML(html)
334
- return html_pane
335
- elif topic=='Sustainable Building Construction and Design with Environmental Assessment':
336
- html = """<iframe src="" width="1000" height="800"></iframe>"""
337
- html_pane = pn.pane.HTML(html)
338
- return html_pane
339
- elif topic=='Landscape Planning and Design Theory':
340
- html = """<iframe src="" width="1000" height="800"></iframe>"""
341
- html_pane = pn.pane.HTML(html)
342
- return html_pane
343
- elif topic=='Urban Sound Environment Research in Architectural Design':
344
- html = """<iframe src="" width="1000" height="800"></iframe>"""
345
- html_pane = pn.pane.HTML(html)
346
- return html_pane
347
- elif topic=='Sustainable Construction Materials and Technologies':
348
- html = """<iframe src="" width="1000" height="800"></iframe>"""
349
- html_pane = pn.pane.HTML(html)
350
- return html_pane
351
- elif topic=='Utilizing BIM in Construction and Building Information Modeling Industry':
352
- html = """<iframe src="https://tinyurl.com/2ynebkcr" width="1000" height="800"></iframe>"""
353
- html_pane = pn.pane.HTML(html)
354
- return html_pane
355
- elif topic=='Urban Agriculture and Sustainable Food Systems':
356
- html = """<iframe src="" width="1000" height="800"></iframe>"""
357
- html_pane = pn.pane.HTML(html)
358
- return html_pane
359
- elif topic=='Sustainable Bridge Design and Construction':
360
- html = """<iframe src="" width="1000" height="800"></iframe>"""
361
- html_pane = pn.pane.HTML(html)
362
- return html_pane
363
- elif topic=='Investigation of Cavity Dynamics and Heat Transfer in Various Flow Scenarios':
364
- html = """<iframe src="" width="1000" height="800"></iframe>"""
365
- html_pane = pn.pane.HTML(html)
366
- return html_pane
367
-
368
-
369
- def create_overlay_plot(subject_df):
370
- overlay = hv.Overlay()
371
- for obj_column in subject_df.columns:
372
- overlay *= hv.Curve((subject_df.index, subject_df[obj_column]), 'Time', 'Frequency', label=obj_column)
373
-
374
- overlay.opts(
375
- show_legend=True,
376
- legend_position='right',
377
- width=1400,
378
- height=900
379
- )
380
  return overlay
381
 
 
382
  ############################# WIDGETS & CALLBACK ###########################################
383
 
384
  def filter_data0(df, min_value):
@@ -437,20 +279,15 @@ def generate_radio_buttons(value):
437
 
438
 
439
  # https://tabler-icons.io/
440
- button0 = pn.widgets.Button(name="Introduction", button_type="warning", icon="file-info", styles={"width": "100%"})
441
- button1 = pn.widgets.Button(name="Publication Trends", button_type="warning", icon="chart-histogram", styles={"width": "100%"})
442
- button2 = pn.widgets.Button(name="Topic Map", button_type="warning", icon="chart-dots-3", styles={"width": "100%"})
443
- button3 = pn.widgets.Button(name="AECO Macro Topic Hierarchy", button_type="warning", icon="chart-dots-3", styles={"width": "100%"})
444
- button4 = pn.widgets.Button(name="AECO Macro Topics Trends", button_type="warning", icon="chart-histogram", styles={"width": "100%"})
445
- button5 = pn.widgets.Button(name="Research Collaboration Networks: Institutes", button_type="warning", icon="chart-dots-3", styles={"width": "100%"})
446
- button6 = pn.widgets.Button(name="Research Collaboration Networks: Countries", button_type="warning", icon="chart-dots-3", styles={"width": "100%"})
447
- button7 = pn.widgets.Button(name="Research Tasks and Methods Trends", button_type="warning", icon="chart-dots-3", styles={"width": "100%"})
448
 
449
 
450
  region1 = pn.widgets.RadioButtonGroup(name='### Select News Region', options=regions)
451
 
452
- macro_topics_button = pn.widgets.Select(name='Select Macro Topic', value='Energy Efficiency and Thermal Comfort in Building Environments', options=macro_topics_active_subset)
453
-
454
 
455
  # Initial RadioButtonGroup
456
  radio_buttons_regions = pn.widgets.RadioButtonGroup(options=regions,value='eu',name='Select region')
@@ -467,6 +304,7 @@ def update_radio_group(event):
467
 
468
 
469
  # bind the function to the widget(s)
 
470
  # Bind the selected value of the first RadioButtonGroup to update the second RadioButtonGroup
471
  radio_buttons_regions.param.watch(update_radio_group, 'value')
472
 
@@ -487,227 +325,96 @@ region_radio_button.param.watch(update_holomap, 'value')
487
  def show_page(page_key):
488
  main_area.clear()
489
  main_area.append(mapping[page_key])
490
-
491
- button0.on_click(lambda event: show_page("Page0"))
492
  button1.on_click(lambda event: show_page("Page1"))
493
  button2.on_click(lambda event: show_page("Page2"))
494
  button3.on_click(lambda event: show_page("Page3"))
495
  button4.on_click(lambda event: show_page("Page4"))
496
  button5.on_click(lambda event: show_page("Page5"))
497
- button6.on_click(lambda event: show_page("Page6"))
498
- button7.on_click(lambda event: show_page("Page7"))
499
 
500
 
501
  ### CREATE PAGE LAYOUTS
502
- def CreatePage0():
 
503
  return pn.Column(pn.pane.Markdown("""
504
 
 
 
505
 
506
- ## Introduction
 
507
 
508
- This is a dashboard for a Data Analytics project regarding research publications in the AECO domain. The source data consists of around 267k English-language research papers gathered from the openalex.org graph database, covering a timeframe from 2011 through early 2024.
509
 
510
  ---------------------------
511
 
512
- ## Publication Trends
513
-
514
- In the "Publication Trends" panel we show monthly time series of the total number of publications and the number of publications per country (both in log scale), for the top 20 countries by number of publications in the dataset.
515
-
516
 
517
- ## Topic Map
518
- In the "Topic Map" panel we show a UMAP reduced 2-dimensional visualization of the optimized 52 topic clusters of AECO research papers, embedded using Sentence Transformer model, with the descriptive labels overlayed on the clusters being generated by LLama 2 Large Language Model. Each point in the space represent a paper from the dataset.
519
- Hovering over it has the paper title popping up, while clicking on it redirects to the corresponding OpenAlex paper entry page.
520
-
521
-
522
- ## AECO Macro Topic Hierarchy
523
- The "AECO Macro Topic Hierarchy" panel allows to explore the dendrogram representation of the optimized clustering, with the leaves of the tree representing the 51 clusters, the intermediate nodes representing merged clusters and the height of the merging (distance from the leaves) indicating topic
524
- similarity as based on the cosine distance matrix between topic embeddings.
525
-
526
-
527
- ## AECO Macro Topic Trends
528
- The "AECO Macro Topic Trends" panel shows the evolution over time of the 16 AECO macro topics by plotting the semi-annual time series of the absolute numbers of publications per topic.
529
 
530
- ## Research Collaboration Networks: Institutes
531
- The "Research Collaboration Networks: Institutes" panel contains VOSViewer-generated network representations of the research institutions co-authorship connections, for each of the 16 macro clusters. By selecting a macro-cluster from by the drop-down menu, a graph is loaded whose nodes represent research institutions, edges represent co-authorships relations (with edge thickness being proportional to the frequency of the relations) and the color code clustering highlights the partition of the graph in highly interconnected node groups.
532
- Open the VOSViewer left panel to customize the visualization and/or search for a target institution in the graph.
533
-
534
-
535
- ## Research Collaboration Networks: Countries
536
- The "Research Collaboration Networks: Countries" panel contains VOSViewer-generated network representations of the authors/institutions' country co-authorship connections, for each of the 16 macro clusters. By selecting a macro-cluster from by the drop-down menu, a graph is loaded whose nodes represent authors/institutions' countries, edges represent co-authorships relations (with edge thickness being proportional to the frequency of the relations) and the color code clustering highlights the partition of the graph in highly interconnected node groups.
537
- Open the VOSViewer left panel to customize the visualization and/or search for a target country in the graph.
538
-
539
-
540
- """, width=1000), align="center")
541
-
542
- def CreatePage1():
543
- return pn.Column(
544
- pn.pane.Markdown("## Publication Trends "),
545
- create_publication_curve_chart(),
546
- align="center",
547
- )
548
 
 
 
549
 
 
 
 
 
550
 
551
  def CreatePage2():
552
- # Load the HTML content from the local file
553
- #with open(AECO_topics_over_time_file_path, 'r', encoding='utf-8') as file:
554
- # html_content = file.read()
555
- # Use an iframe to load the local HTML file
556
- iframe_html = f'<iframe src="{AECO_topic_map_path}" width="1400px" height="1200px"></iframe>'
557
- # Create an HTML pane to render the content
558
- html_pane = pn.pane.HTML(iframe_html , sizing_mode='stretch_both')
559
- return pn.Column(pn.pane.Markdown(" ## AECO Topic Map "), html_pane, align="center")
560
-
561
-
562
- def CreatePage3():
563
- # Load the HTML content from the local file
564
- #with open(AECO_topics_over_time_file_path, 'r', encoding='utf-8') as file:
565
- # html_content = file.read()
566
- # Use an iframe to load the local HTML file
567
- iframe_html = f'<iframe src="{AECO_topics_dendogram_file_path}" width="1400px" height="1200px"></iframe>'
568
- # Create an HTML pane to render the content
569
- html_pane = pn.pane.HTML(iframe_html , sizing_mode='stretch_both')
570
- return pn.Column(pn.pane.Markdown(" ## AECO Macro Topics Dendogram "), html_pane, align="center")
571
-
572
-
573
- def CreatePage4():
574
- # Load the HTML content from the local file
575
- #with open(AECO_topics_over_time_file_path, 'r', encoding='utf-8') as file:
576
- # html_content = file.read()
577
- # Use an iframe to load the local HTML file
578
- iframe_html = f'<iframe src="{AECO_topics_over_time_file_path}" width="1400px" height="1200px"></iframe>'
579
- # Create an HTML pane to render the content
580
- html_pane = pn.pane.HTML(iframe_html , sizing_mode='stretch_both')
581
- return pn.Column(pn.pane.Markdown(" ## AECO Macro Topics "), html_pane, align="center")
582
-
583
- def CreatePage5():
584
  return pn.Column(
585
- macro_topics_button,
586
- pn.bind(load_institute_network, macro_topics_button),
587
  align="center",
588
  )
589
 
590
-
591
- def CreatePage6():
592
  return pn.Column(
593
- macro_topics_button,
594
- pn.bind(load_country_network, macro_topics_button),
595
  align="center",
596
  )
597
 
598
- def CreatePage7():
599
  return pn.Column(
600
- macro_topics_button,
601
- pn.bind(load_Task_Method_trends, macro_topics_button),
602
- align="center",
603
- )
604
-
605
- def load_Task_Method_trends(topic, **kwargs):
606
-
607
- task_data = dict()
608
-
609
- # Check if macro_topics_mapping exists
610
- if topic not in macro_topics_mapping:
611
- raise ValueError(f"Topic '{topic}' not found in macro_topics_mapping")
612
- macro_topic_str = str(macro_topics_mapping[topic])
613
-
614
-
615
- #load the tasks and methods timeseries dataframe for the selected topic
616
- task_ts_df = loadTaskTimeSeries(macro_topic_str)
617
- method_ts_df = loadMethodTimeSeries(macro_topic_str)
618
 
619
- task_overlay = create_overlay_plot(task_ts_df)
620
- method_overlay = create_overlay_plot(method_ts_df)
621
-
622
- # Recolor and relabel elements in overlays
623
-
624
- task_overlay_colored = hv.Overlay([
625
- curve.opts(color='red', legend_label=curve.label if curve.label else f"Series {i + 1}")
626
- for i, curve in enumerate(task_overlay)
627
- ])
628
- method_overlay_colored = hv.Overlay([
629
- curve.opts(color='blue', legend_label=curve.label if curve.label else f"Series {i + 1}")
630
- for i, curve in enumerate(method_overlay)
631
- ])
632
-
633
- # Merge overlays into one plot
634
- merged_overlay = task_overlay_colored * method_overlay_colored
635
- merged_overlay.opts(
636
- show_legend=True,
637
- legend_position='right',
638
- width=1400,
639
- height=900
640
- )
641
  return pn.Column(
642
- merged_overlay
643
- )
644
-
645
-
646
-
647
- def load_Task_Method_triple_trends(topic, **kwargs):
648
-
649
- task_data = dict()
650
 
651
- # Check if macro_topics_mapping exists
652
- if topic not in macro_topics_mapping:
653
- raise ValueError(f"Topic '{topic}' not found in macro_topics_mapping")
654
- macro_topic_str = str(macro_topics_mapping[topic])
655
-
656
- topic2toptasks = load_topic2toptasks()
657
-
658
-
659
- #load the task_timeseries dataframe for each of the task mapped from the selected topic in the dict topic2toptasks
660
- for task in topic2toptasks.get(macro_topic_str, []):
661
- task_data[task] = loadTaskMethodTimeSeries(macro_topic_str, task)
662
-
663
- # Create Panel UI with dropdown selection
664
- task_dropdown = pn.widgets.Select(
665
- name="Select TASK",
666
- options=[key for key in task_data.keys()] if task_data else ["No available tasks"]
667
- )
668
-
669
- #@pn.depends(task_dropdown.param.value)
670
- def load_task_overlays(task):
671
- if task not in task_data:
672
- return hv.Text(0.5, 0.5, "No data available", halign="center")
673
- else:
674
- task_method_df = task_data.get(task)
675
- return create_overlay_plot(task_method_df)
676
-
677
- return pn.Column(
678
- task_dropdown,
679
- pn.bind(load_task_overlays, task_dropdown)
680
- )
681
-
682
  mapping = {
683
- "Page0": CreatePage0(),
684
  "Page1": CreatePage1(),
685
  "Page2": CreatePage2(),
686
  "Page3": CreatePage3(),
687
  "Page4": CreatePage4(),
688
  "Page5": CreatePage5(),
689
- "Page6": CreatePage6(),
690
- "Page7": CreatePage7()
691
  }
692
 
693
  #################### SIDEBAR LAYOUT ##########################
694
- sidebar = pn.Column(pn.pane.Markdown("## Panels"),button0,button1,button2,button3,button4,button5,button6,button7,
695
- #button5,
696
- #button6,
697
- styles={"width": "100%", "padding": "15px"})
698
 
699
  #################### MAIN AREA LAYOUT ##########################
700
- main_area = pn.Column(mapping["Page0"], styles={"width":"100%"})
701
 
702
  ###################### APP LAYOUT ##############################
703
  template = pn.template.BootstrapTemplate(
704
- title=" AECO Tech Dashboard",
705
  sidebar=[sidebar],
706
  main=[main_area],
707
  header_background="black",
708
- #site="Charting the Landscape of AECO Research",
709
  theme=pn.template.DarkTheme,
710
- sidebar_width=330, ## Default is 330
711
  busy_indicator=pn.indicators.BooleanStatus(value=True),
712
  )
713
 
 
 
 
 
 
1
 
2
+ import warnings
3
  warnings.filterwarnings("ignore")
4
  import io
5
  import os
 
31
  from holoviews.operation.timeseries import rolling, rolling_outlier_std
32
  hv.extension('bokeh')
33
 
 
 
 
34
  ## LOAD DATASETS
35
 
36
+ dna_folder = './data'
37
 
 
 
38
 
39
+ #### full data unfiltered:
 
40
 
41
+ 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)
42
+ 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)
43
+ 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)
44
 
45
+ #### classifier filtered articles:
 
 
 
46
 
47
+ dh_ration_df_eu = pd.read_csv(os.path.join(dna_folder, 'dh_ration_df_eu.tsv'),sep='\t',header=0)
48
+ dh_ration_df_us = pd.read_csv(os.path.join(dna_folder, 'dh_ration_df_us.tsv'),sep='\t',header=0)
49
+ dh_ration_df_eu_us = pd.read_csv(os.path.join(dna_folder, 'dh_ration_df_eu_us.tsv'),sep='\t',header=0)
50
 
51
  regions = ['eu', 'us', 'eu_us']
52
 
 
55
  sorted_ent_type_freq_map_eu_us=dict()
56
 
57
  def read_top_ent_types():
58
+ reader = csv.reader(open(os.path.join(dna_folder, 'sorted_ent_type_freq_map_eu.tsv'), 'r'))
59
  for i,row in enumerate(reader):
60
  if i < 20:
61
  k, v = row
62
  sorted_ent_type_freq_map_eu[k] = int(v)
63
  del sorted_ent_type_freq_map_eu['Entity']
64
+ reader = csv.reader(open(os.path.join(dna_folder, 'sorted_ent_type_freq_map_us.tsv'), 'r'))
65
  for i, row in enumerate(reader):
66
  if i < 20:
67
  k, v = row
68
  sorted_ent_type_freq_map_us[k] = int(v)
69
  del sorted_ent_type_freq_map_us['Entity']
70
+ reader = csv.reader(open(os.path.join(dna_folder, 'sorted_ent_type_freq_map_eu_us.tsv'), 'r'))
71
  for i, row in enumerate(reader):
72
  if i < 20:
73
  k, v = row
 
80
  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']
81
  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']
82
 
83
+ 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)
84
+ 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)
85
+ 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)
86
 
87
  def read_top_ent_maps():
88
+ reader = csv.reader(open(os.path.join(dna_folder, 'sorted_ent_freq_map_eu.tsv'), 'r'), delimiter='\t')
89
  for row in reader:
90
  k,v = row
91
  lista = ast.literal_eval(v)
 
95
  dizionario = sorted(dizionario.items(), key=lambda x: x[1], reverse=True)
96
  ent_freq_maps_eu[k]=dizionario
97
 
98
+ reader = csv.reader(open(os.path.join(dna_folder, 'sorted_ent_freq_map_us.tsv'), 'r'), delimiter='\t')
99
  for row in reader:
100
  k, v = row
101
  lista = ast.literal_eval(v)
 
105
  dizionario = sorted(dizionario.items(), key=lambda x: x[1], reverse=True)
106
  ent_freq_maps_us[k] = dizionario
107
 
108
+ reader = csv.reader(open(os.path.join(dna_folder, 'sorted_ent_freq_map_eu_us.tsv'), 'r'), delimiter='\t')
109
  for row in reader:
110
  k, v = row
111
  lista = ast.literal_eval(v)
 
124
 
125
  def read_type_filtered_triples():
126
  for t in top_type_filtered_eu:
127
+ df = pd.read_csv(dna_folder+'/filtered_rows/eu/'+t.replace(':','_')+'.tsv', sep=" ", header=0)
128
  df.drop(columns=['Unnamed: 0'], inplace=True)
129
  top_type_filtered_triples_eu[t]=df
130
  for t in top_type_filtered_us:
131
+ df = pd.read_csv(dna_folder+'/filtered_rows/us/'+t.replace(':','_')+'.tsv', sep=" ")
132
  df.drop(columns=['Unnamed: 0'], inplace=True)
133
  top_type_filtered_triples_us[t]=df
134
  for t in top_type_filtered_eu_us:
135
+ df = pd.read_csv(dna_folder+'/filtered_rows/eu_us/'+t.replace(':','_')+'.tsv', sep=" ")
136
  df.drop(columns=['Unnamed: 0'], inplace=True)
137
  top_type_filtered_triples_eu_us[t]=df
138
 
 
144
 
145
  read_type_filtered_triples()
146
 
147
+ grouping_filtered = pd.read_csv(os.path.join(dna_folder, 'dna_relations.tsv'), sep=" ")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
148
  ################################# CREATE CHARTS ############################
149
+ def create_curve_chart():
150
+ # Create the 3 line plots
151
+ 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')
152
+ 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')
153
+ 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')
 
 
 
 
 
 
 
 
 
 
 
 
154
  #Overlay the line plots
155
+ overlay = curve_eu * curve_us * curve_eu_us
156
+ overlay.opts(show_legend = True, legend_position='top_left', width=1200, height=600)
 
 
 
157
  return overlay
158
 
159
 
160
+ def create_bar_charts(region, **kwargs):
161
+ if region=='eu':
162
+ sliced = sorted_ent_type_freq_map_eu
163
+ return hv.Bars(sliced, hv.Dimension('Entity Types'), 'Frequency').opts( framewise=True, xrotation=45,width=1200, height=600)
164
+ elif region=='us':
165
+ sliced = sorted_ent_type_freq_map_us
166
+ return hv.Bars(sliced, hv.Dimension('Entity Types'), 'Frequency').opts(framewise=True, xrotation=45,width=1200, height=600)
167
+ elif region=='eu_us':
168
+ sliced = sorted_ent_type_freq_map_eu_us
169
+ return hv.Bars(sliced, hv.Dimension('Entity Types'), 'Frequency').opts(framewise=True, xrotation=45,width=1200, height=600)
170
+
171
+
172
+
173
+ # Define a function to generate Curve based on selected values
174
+ def generate_entity_curves(region_value, type_value, **kwargs):
175
+ if region_value=='eu':
176
+ top20Ents = ent_freq_maps_eu[type_value]
177
+ curveList = []
178
+ for ent in top20Ents:
179
+ 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])]
180
+ entityTriples_time_indexed = entityTriples.set_index(pd.DatetimeIndex(entityTriples['timestamp']), inplace=False)
181
+ del entityTriples_time_indexed['timestamp']
182
+ entityTriples_time_indexed_resampled = entityTriples_time_indexed.resample("Y").count()
183
+ #print(entityTriples_time_indexed_resampled)
184
+ entityTriples_time_indexed_resampled = entityTriples_time_indexed_resampled.reindex(dna_healthtech_articles_eu_time_indexed_resampled.index, fill_value=0)
185
+ 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])
186
+ curve.opts(autorange='y')
187
+ #curve.opts(logy=True)
188
+ curveList.append(curve)
189
+ overlay = hv.Overlay(curveList)
190
+ overlay.opts(legend_muted=False, legend_cols=4, show_legend = True, legend_position='top_left', fontsize={'legend':13},width=1200, height=800)
191
+ return overlay
192
+
193
+ elif region_value=='us':
194
+ top20Ents = ent_freq_maps_us[type_value]
195
+ curveList = []
196
+ for ent in top20Ents:
197
+ 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])]
198
+ entityTriples_time_indexed = entityTriples.set_index(pd.DatetimeIndex(entityTriples['timestamp']), inplace=False)
199
+ del entityTriples_time_indexed['timestamp']
200
+ entityTriples_time_indexed_resampled = entityTriples_time_indexed_resampled.reindex(dna_healthtech_articles_us_time_indexed_resampled.index, fill_value=0)
201
+ 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])
202
+ curve.opts(autorange='y')
203
+ curveList.append(curve)
204
+ overlay = hv.Overlay(curveList)
205
+ overlay.opts(legend_muted=False, legend_cols=4, show_legend = True, legend_position='top_left', fontsize={'legend':13},width=1200, height=800)
206
+ return overlay
207
 
208
+ elif region_value=='eu_us':
209
+ top20Ents = ent_freq_maps_eu_us[type_value]
210
+ curveList = []
211
+ for ent in top20Ents:
212
+ 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])]
213
+ entityTriples_time_indexed = entityTriples.set_index(pd.DatetimeIndex(entityTriples['timestamp']), inplace=False)
214
+ del entityTriples_time_indexed['timestamp']
215
+ entityTriples_time_indexed_resampled = entityTriples_time_indexed_resampled.reindex(dna_healthtech_articles_eu_us_time_indexed_resampled.index, fill_value=0)
216
+ 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])
217
+ curve.opts(autorange='y')
218
+ curveList.append(curve)
219
+ overlay = hv.Overlay(curveList)
220
+ overlay.opts(legend_muted=False, legend_cols=4, show_legend = True, legend_position='top_left', fontsize={'legend':13},width=1200, height=800)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
221
  return overlay
222
 
223
+
224
  ############################# WIDGETS & CALLBACK ###########################################
225
 
226
  def filter_data0(df, min_value):
 
279
 
280
 
281
  # https://tabler-icons.io/
282
+ button1 = pn.widgets.Button(name="Introduction", button_type="warning", icon="file-info", styles={"width": "100%"})
283
+ button2 = pn.widgets.Button(name="Health Tech News Ratio", button_type="warning", icon="chart-histogram", styles={"width": "100%"})
284
+ button3 = pn.widgets.Button(name="Top Entity Types", button_type="warning", icon="chart-bar", styles={"width": "100%"})
285
+ button4 = pn.widgets.Button(name="Top Key Entities", button_type="warning", icon="chart-dots-filled", styles={"width": "100%"})
286
+ button5 = pn.widgets.Button(name="Entity Chord Diagrams", button_type="warning", icon="chart-dots-filled", styles={"width": "100%"})
 
 
 
287
 
288
 
289
  region1 = pn.widgets.RadioButtonGroup(name='### Select News Region', options=regions)
290
 
 
 
291
 
292
  # Initial RadioButtonGroup
293
  radio_buttons_regions = pn.widgets.RadioButtonGroup(options=regions,value='eu',name='Select region')
 
304
 
305
 
306
  # bind the function to the widget(s)
307
+ dmap2 = hv.DynamicMap(pn.bind(generate_entity_curves, radio_buttons_regions,radio_buttons_types))
308
  # Bind the selected value of the first RadioButtonGroup to update the second RadioButtonGroup
309
  radio_buttons_regions.param.watch(update_radio_group, 'value')
310
 
 
325
  def show_page(page_key):
326
  main_area.clear()
327
  main_area.append(mapping[page_key])
328
+
 
329
  button1.on_click(lambda event: show_page("Page1"))
330
  button2.on_click(lambda event: show_page("Page2"))
331
  button3.on_click(lambda event: show_page("Page3"))
332
  button4.on_click(lambda event: show_page("Page4"))
333
  button5.on_click(lambda event: show_page("Page5"))
 
 
334
 
335
 
336
  ### CREATE PAGE LAYOUTS
337
+
338
+ def CreatePage1():
339
  return pn.Column(pn.pane.Markdown("""
340
 
341
+ This is a dashboard for a News Analysis project regarding Digital Health technology. The source data consists of around 7.8 million English-language news articles gathered from the **Dow Jones Data, News, and Analytics (DNA)**
342
+ platform (https://www.dowjones.com/professional/developer-platform/) covering a timeframe from September 1987 through December 2023. The news items text content is copyrighted and cannot be shared within this project.
343
 
344
+ Some of the data analytics visualizations show here come from a Knowledge Graph automatically extracted from DNA news sources. A Virtuoso SPARQL endpoint to this graph (named 'DHNEWS KG') is set up at the
345
+ URL: https://api-vast.jrc.service.ec.europa.eu/sparql/
346
 
 
347
 
348
  ---------------------------
349
 
350
+ ## 1. Health Tech News Ratio
351
+ In the Health Tech News Ratio panel we present the month-sampled time series depicting the proportion of 97k news articles con-
352
+ cerning Digital Health, as identified by a text classifier, out of the total number of English language DNA news articles pertaining to Europe and the US
 
353
 
 
 
 
 
 
 
 
 
 
 
 
 
354
 
355
+ ### 2. Top Entity Types
356
+ The Top Entity Types bar plots in the dashboard show the predominant DBpedia-inherited entity types within the graph for triples tagged with Europe, US, and EU-US region codes via their article support.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
357
 
358
+ ## 3. Top Key Entities
359
+ The Top Key Entities plots track the occurrence of several key entities per year, where occurrence means the entity is either the Subject or Object of an extracted triple in the KG.
360
 
361
+ ## 4. Entity Chord Diagrams
362
+ Entity Chord Diagrams represent the most frequently connected entity pairs within the KG through chord illustrations, serving as both Subjects and Objects of predicative triples.
363
+ The size of the chords corresponds to the support of the depicted relations.
364
+ """, width=800), align="center")
365
 
366
  def CreatePage2():
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
367
  return pn.Column(
368
+ pn.pane.Markdown("## Health Tech News Ratio "),
369
+ create_curve_chart(),
370
  align="center",
371
  )
372
 
373
+ def CreatePage3():
 
374
  return pn.Column(
375
+ region1,
376
+ pn.bind(create_bar_charts, region1),
377
  align="center",
378
  )
379
 
380
+ def CreatePage4():
381
  return pn.Column(
382
+ pn.pane.Markdown("## Top Key Entities "),
383
+ pn.Row(pn.Column(radio_buttons_regions, radio_buttons_types), dmap2),
384
+ align="center", )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
385
 
386
+ def CreatePage5():
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
387
  return pn.Column(
388
+ pn.pane.Markdown("## Entity Chord Diagrams "),
389
+ pn.Row(region_radio_button, pn.bind(filter_region, region_radio_button)),
390
+ align="center", )
 
 
 
 
 
391
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
392
  mapping = {
 
393
  "Page1": CreatePage1(),
394
  "Page2": CreatePage2(),
395
  "Page3": CreatePage3(),
396
  "Page4": CreatePage4(),
397
  "Page5": CreatePage5(),
 
 
398
  }
399
 
400
  #################### SIDEBAR LAYOUT ##########################
401
+ sidebar = pn.Column(pn.pane.Markdown("## Pages"), button1,button2,button3,
402
+ button4,
403
+ button5,
404
+ styles={"width": "100%", "padding": "15px"})
405
 
406
  #################### MAIN AREA LAYOUT ##########################
407
+ main_area = pn.Column(mapping["Page1"], styles={"width":"100%"})
408
 
409
  ###################### APP LAYOUT ##############################
410
  template = pn.template.BootstrapTemplate(
411
+ title=" Digital Health in the News: Analytics Dashboard ",
412
  sidebar=[sidebar],
413
  main=[main_area],
414
  header_background="black",
415
+ #site="Charting the Landscape of Digital Health",
416
  theme=pn.template.DarkTheme,
417
+ sidebar_width=250, ## Default is 330
418
  busy_indicator=pn.indicators.BooleanStatus(value=True),
419
  )
420