import warnings warnings.filterwarnings("ignore") import io import os import time import warnings warnings.simplefilter(action='ignore', category=FutureWarning) warnings.simplefilter(action='ignore', category=RuntimeWarning) import pandas as pd import csv import ast from tqdm import tqdm from operator import itemgetter import numpy as np import re import datetime import html from joblib import Parallel, delayed import matplotlib.pyplot as plt import matplotlib.dates as mdates #plt.style.use('seaborn-paper') import holoviews as hv from holoviews import opts, dim from bokeh.sampledata.les_mis import data from bokeh.io import show from bokeh.sampledata.les_mis import data import panel as pn #pn.extension(design='material') import bokeh from bokeh.resources import INLINE from holoviews.operation.timeseries import rolling, rolling_outlier_std hv.extension('bokeh') ## LOAD DATASETS data = './data' def read_freq_map(filename): df = pd.read_csv(os.path.join(data,filename), sep=' ') #df = df.head(10) if 'Unnamed: 0' in df.columns: df = df.drop('Unnamed: 0', axis=1) column_0 = df.columns[0] column_1 = df.columns[1] freqmap = dict(zip(df[column_0], df[column_1])) return freqmap def read_ont_freq_dataframe(filename): df = pd.read_csv(os.path.join(data,filename), sep=' ') #print(df) if 'Unnamed: 0' in df.columns: df = df.drop('Unnamed: 0', axis=1) column_0 = df.columns[0] column_1 = df.columns[1] freqmap = dict(zip(df[column_0], df[column_1])) return freqmap entityTypesFreqMap = read_freq_map('entityTypes.tsv') relationTypesFreqMap = read_freq_map('relationTypes.tsv') topDrugEntities = read_freq_map('topDrugs.tsv') #print(topDrugEntities) topConditionEntities = read_freq_map('topConditions.tsv') topDrugOnts_df = pd.read_csv(os.path.join(data,'topDrugOntologies.tsv'), sep='\t') topConditionOnts_df = pd.read_csv(os.path.join(data,'topConditionOntologies.tsv'), sep='\t') grouping_filtered = pd.read_csv(os.path.join(data, 'drugReviewsCausal_relations.tsv'), sep=" ") ################################# CREATE CHARTS ############################ def create_type_bar_charts(entRelsButton, **kwargs): if entRelsButton=='Entity': dictionary = entityTypesFreqMap return hv.Bars(dictionary, hv.Dimension('Entity Types'), 'Frequency').opts( framewise=True, xrotation=45,width=1200, height=600) elif entRelsButton=='Relation': dictionary = relationTypesFreqMap return hv.Bars(dictionary, hv.Dimension('Relation Types'), 'Frequency').opts(framewise=True, xrotation=45,width=1200, height=600) def create_ent_bar_charts(ents, **kwargs): # Create button widgets for each label drug_buttons = [] condition_buttons = [] for i, drg in enumerate(list(topDrugEntities.keys())): button = pn.widgets.Button(name=drg, width=150) ## Open the associated URL in a new tab when button is clicked button.js_on_click(code=f'window.open("https://api-vast.jrc.service.ec.europa.eu/describe/?url=http://causaldrugskg.org/causaldrugskg/resource/{drg}", "_blank");') drug_buttons.append(button) for i, cnd in enumerate(list(topConditionEntities.keys())): button = pn.widgets.Button(name=cnd, width=150) ## Open the associated URL in a new tab when button is clicked button.js_on_click( code=f'window.open("https://api-vast.jrc.service.ec.europa.eu/describe/?url=http://causaldrugskg.org/causaldrugskg/resource/{cnd}", "_blank");') condition_buttons.append(button) # Stack the buttons vertically (or wrap in a GridBox for nicer layout) drug_button_column = pn.Column(*drug_buttons, sizing_mode='stretch_width') condition_button_column = pn.Column(*condition_buttons, sizing_mode='stretch_width') if ents=='Drug': dictionary = topDrugEntities bars = hv.Bars(dictionary, hv.Dimension('Drug Entities'), 'Frequency').opts(framewise=True, xrotation=45,width=1200, height=600, fontsize={'xticks': 18, 'xlabel':18, 'ylabel':16}) # Combine everything into a Panel layout layout = pn.Row(bars, drug_button_column) return layout elif ents=='Condition': dictionary = topConditionEntities bars = hv.Bars(dictionary, hv.Dimension('Condition Entities'), 'Frequency').opts(framewise=True, xrotation=45,width=1200, height=600, fontsize={'xticks': 18, 'xlabel':18, 'ylabel':16}) layout = pn.Row(bars, condition_button_column) return layout def create_ontology_bar_charts(ents, **kwargs): if ents=='Drug': df = pd.DataFrame({ 'Drug_Ontologies': [ont.split('/')[-1] for ont in topDrugOnts_df['ontology']], 'Frequency': list(topDrugOnts_df['count']), 'url': list(topDrugOnts_df['ontology_url']) # using full keys as hyperlinks }) drug_ontolgy_buttons = [] for i,row in df.iterrows(): button = pn.widgets.Button(name=row['Drug_Ontologies'], width=150) ## Open the associated URL in a new tab when button is clicked url = row["url"] button.js_on_click( code=f'window.open("{url}", "_blank");') drug_ontolgy_buttons.append(button) drug_ontology_column = pn.Column(*drug_ontolgy_buttons, sizing_mode='stretch_width') # Create bar chart with label as x-axis bars = hv.Bars(df, kdims=['Drug_Ontologies'], vdims=['Frequency']) bars.opts( framewise=True, tools=['hover'], width=1200, height=600, show_legend=True, xrotation=45, xlabel='Drug_Ontologies', ylabel='Frequency', hover_tooltips=[ ("Drug_Ontologies", "@Drug_Ontologies"), ("Frequency", "@Frequency") ] ) #links_panel = pn.Column(*[pn.pane.Markdown(f"[{row.Drug_Ontologies}]({row.url})", width=400) for _, row in df.iterrows()],name='Links') layout = pn.Row(bars, drug_ontology_column) return layout elif ents=='Condition': df = pd.DataFrame({ 'Condition_Ontologies': [ont.split('/')[-1] for ont in topConditionOnts_df['ontology']], 'Frequency': list(topConditionOnts_df['count']), 'url': list(topConditionOnts_df['ontology_url']) # using full keys as hyperlinks }) condition_ontolgy_buttons = [] for i, row in df.iterrows(): button = pn.widgets.Button(name=row['Condition_Ontologies'], width=150) ## Open the associated URL in a new tab when button is clicked url = row["url"] button.js_on_click( code=f'window.open("{url}", "_blank");') condition_ontolgy_buttons.append(button) condition_ontology_column = pn.Column(*condition_ontolgy_buttons, sizing_mode='stretch_width') # Create bar chart with label as x-axis bars = hv.Bars(df, kdims=['Condition_Ontologies'], vdims=['Frequency']) bars.opts( framewise=True, tools=['hover'], width=1200, height=600, show_legend=True, xrotation=45, xlabel='Condition_Ontologies', ylabel='Frequency', hover_tooltips=[ ("Condition Ontologies", "@Condition Ontologies"), ("Frequency", "@Frequency") ]) #links_panel = pn.Column(*[pn.pane.Markdown(f"[{row.Condition_Ontologies}]({row.url})", width=400) for _, row in df.iterrows()],name='Links') layout = pn.Row(bars, condition_ontology_column) return layout ############################# WIDGETS & CALLBACK ########################################### def filter_data0(df, min_value): filtered_df = df[df['value'] >= min_value] return filtered_df def plot_chord_new(df,min_value): filtered_df = filter_data0(df, min_value) # Create a Holoviews Dataset for nodes nodes = hv.Dataset(filtered_df, 'index') nodes.data.head() chord = hv.Chord(filtered_df, ['source', 'target'], ['value']) # calculate positions for labels (simple approximation for circular layout) num_nodes = len(nodes.data) angles = np.linspace(0, 2 * np.pi, num_nodes, endpoint=False) radius = 1.05 # slightly outside the chord circle label_data = [] for i, row in nodes.data.iterrows(): angle = angles[i] x = radius * np.cos(angle) y = radius * np.sin(angle) label_data.append((x, y, row['index'])) labels = hv.Labels(label_data, ['x', 'y'], 'text') layout = chord.opts( opts.Chord( labels=None, # remove default labels node_color=hv.dim('index').str(), edge_color=hv.dim('source').str(), cmap='Category20', edge_cmap='Category20', label_text_color='black', width=800, height=800, tools=['hover'] ) ) * labels.opts( text_font_size='9pt', text_align='center', text_baseline='middle' ) return layout def plot_chord(df,min_value): filtered_df = filter_data0(df, min_value) # Create a Holoviews Dataset for nodes nodes = hv.Dataset(filtered_df, 'index') nodes.data.head() chord = hv.Chord(filtered_df, ['source', 'target'], ['value']) 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', label_text_font_size="12pt", width=800, height=800)) def chordify_triples(rel_grouping, min_val): # Define range for minimum value slider min_value_range = rel_grouping['value'].unique() min_value_range.sort() min_value_range = min_value_range[min_value_range > min_val] # Define HoloMap with minimum value and attribute as key dimensions holomap = hv.HoloMap({min_value: plot_chord(rel_grouping, min_value) for min_value in min_value_range}, kdims=['Show triples with support greater than'] ) return holomap # https://tabler-icons.io/ button1 = pn.widgets.Button(name="Introduction", button_type="warning", icon="file-info", styles={"width": "100%"}) button2 = pn.widgets.Button(name="Top Key Entities", button_type="warning", icon="chart-bar", styles={"width": "100%"}) button3 = pn.widgets.Button(name="Entity/Relation Types:", button_type="warning", icon="chart-histogram", styles={"width": "100%"}) button4 = pn.widgets.Button(name="Ontology Coverage", button_type="warning", icon="chart-dots-filled", styles={"width": "100%"}) #button5 = pn.widgets.Button(name="Causal Relation Chord Diagrams", button_type="warning", icon="chart-dots-filled", styles={"width": "100%"}) markdown_button_style = """