Skip to content

Instantly share code, notes, and snippets.

@cosh
Last active February 28, 2024 17:07
Show Gist options
  • Save cosh/274b16720497b37c48a98f92893d9ad9 to your computer and use it in GitHub Desktop.
Save cosh/274b16720497b37c48a98f92893d9ad9 to your computer and use it in GitHub Desktop.
A stored function that uses the evaluate python operator to execute a Python script that uses the plotly, networkx and pandas libraries to create a plotly viz object from the input tables. The function also adds some styling and annotations to the graph object, such as colors, sizes, hover texts, etc. It uses the replace_string function to inser…
.create-or-alter function with (skipvalidation = "true") VisualizeGraphPlotly(
E:(sourceId:long,targetId:long), N:(nodeId:long),
pLayout:string="spring_layout", pColorscale:string="Picnic", pTitle:string="Happy kraphing!") {
let pythonCodeBlueprint = ```
import numpy as np
import pandas as pd
import plotly.graph_objects as go
import networkx as nx
G = nx.Graph()
for index, row in df.iterrows():
if row["tableName"] == "N":
G.add_node(row["nodeId"], size = 1, properties = row.where(pd.notnull(row), None).to_dict())
elif row["tableName"] == "E":
G.add_edge(row["sourceId"], row["targetId"], weight = 1, properties = row.where(pd.notnull(row), None).to_dict())
pos_ = nx.layout.##layout##(G)
edge_x = [];
edge_y = [];
mnode_x, mnode_y, mnode_txt = [], [], []
for edge in G.edges():
x0, y0 = pos_[edge[0]]
x1, y1 = pos_[edge[1]]
edge_x.append(x0)
edge_x.append(x1)
edge_x.append(None)
edge_y.append(y0)
edge_y.append(y1)
edge_y.append(None)
text = 'source: '+ str(edge[0]) + " destination: " + str(edge[1]) + '<br>' + 'Properties: ' + '<br>'.join(str(key) + ': ' + str(value) for key, value in G.edges[edge]['properties'].items() if value is not None and value != '')
mnode_x.extend([(x0 + x1)/2]) # assuming values positive/get midpoint
mnode_y.extend([(y0 + y1)/2]) # assumes positive vals/get midpoint
mnode_txt.append(text) # hovertext
edge_trace = go.Scatter(
x=edge_x, y=edge_y,
line=dict(width=0.5, color='#888'),
hoverinfo='none',
mode='lines')
mnode_trace = go.Scatter(
x = mnode_x, y = mnode_y,
mode = "markers",
hoverinfo='text',
opacity=0.5,
marker=dict(
color='LightSkyBlue',
size=2,
line_width=1))
mnode_trace.text = mnode_txt
node_x = []
node_y = []
for node in G.nodes():
x, y = pos_[node]
node_x.append(x)
node_y.append(y)
node_adjacencies = []
node_text = []
node_sizes = []
for node, adjacencies in enumerate(G.adjacency()):
node_sizes.append(10 + len(adjacencies[1])/G.number_of_nodes())
node_adjacencies.append(len(adjacencies[1]))
text = '# of connections: '+ str(len(adjacencies[1])) + '<br>' + 'Properties: ' + '<br>'.join(str(key) + ': ' + str(value) for key, value in G.nodes[adjacencies[0]]['properties'].items() if value is not None and value != '')
node_text.append(text)
node_trace = go.Scatter(
x=node_x, y=node_y,
mode='markers',
hoverinfo='text',
marker=dict(
showscale=True,
colorscale='##colorscale##',
reversescale=False,
color=[],
size=[],
colorbar=dict(
thickness=15,
title='Node Connections',
xanchor='left',
titleside='right'
),
line=dict(width=2, color='#888')))
node_trace.marker.color = node_adjacencies
node_trace.text = node_text
node_trace.marker.size = node_sizes
fig = go.Figure(data=[edge_trace, node_trace, mnode_trace],
layout=go.Layout(
title='<br>##title##',
titlefont_size=16,
showlegend=False,
hovermode='closest',
margin=dict(b=20,l=5,r=5,t=40),
annotations=[ dict(
text="Created using plotly, networkx and the python plugin of Kusto",
showarrow=False,
xref="paper", yref="paper",
x=0.005, y=-0.002 ) ],
xaxis=dict(showgrid=False, zeroline=False, showticklabels=False),
yaxis=dict(showgrid=False, zeroline=False, showticklabels=False))
)
plotly_obj = fig.to_json()
result = pd.DataFrame(data = [plotly_obj], columns = ['plotly'])
```;
let pythonCode = replace_string(replace_string(replace_string(pythonCodeBlueprint, "##layout##", pLayout), "##colorscale##", pColorscale), '##title##', pTitle);
union withsource=tableName E, N
| evaluate python(
//
typeof(plotly:string),
pythonCode)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment