ChrisDelClea / streamlit-agraph

A Streamlit Graph Vis
MIT License
387 stars 52 forks source link

Graphviz Layout support #18

Closed fabiogra closed 3 years ago

fabiogra commented 3 years ago

15

ChrisDelClea commented 3 years ago

Awesome, thank you @fabiogra!

fabiogra commented 3 years ago

Thank you @ChrisChross for creating this streamlit component!

atakanokan commented 3 years ago

This is awesome @fabiogra! One question I have on this is if I was to not use the DOT formatted data, how would one incorporate just the X & Y coordinates into your example script iris_decision_tree.py? I am thinking of either doing T-SNE or manual coordinates for my work.

fabiogra commented 3 years ago

Hi @atakanokan! Interesting question, it could be nice to visualize data transformed by T-SNE (I'm thinking an use case for Image Similarity). So here's what you need to do it with streamlit-agraph: 1) Use x and y argument to pass each Node their coordinates 2) Set d3 = {'disableLinkForce': True} in Config

Here's an example using this data (https://scipy-lectures.org/packages/scikit-learn/auto_examples/plot_tsne.html) from Scikit-learn T-SNE algorithm:

import streamlit as st
from sklearn import datasets
from sklearn.manifold import TSNE
from streamlit_agraph import Config, Edge, Node, agraph

digits = datasets.load_digits()
X = digits.data[:500]
y = digits.target[:500]

tsne = TSNE(n_components=2, random_state=0)
X_2d = tsne.fit_transform(X)

target_ids = range(len(digits.target_names))

GRAPH_WIDTH = 1200
GRAPH_HEIGHT = 500

colors = 'red', 'green', 'blue', 'cyan', 'pink', 'yellow', 'gray', 'black', 'orange', 'purple'

nodes = []
j=0

for i, c, label in zip(target_ids, colors, digits.target_names):
    for elem in X_2d[y==i].tolist():
        nodes.append(Node(id=j, 
                            size=1, 
                            color=c,
                            renderLabel=False, 
                            x=GRAPH_WIDTH/4+float(elem[0]), 
                            y=GRAPH_HEIGHT/2+float(elem[1])
                            )
                     )
        j+=1

# You need to pass some Edge, so you can fake it and don't get some error:
edges = [Edge(source=0, 
              target=0,               
              type="CURVE_SMOOTH", 
              staticGraphWithDragAndDrop=False,
              staticGraph=False
              )]

config = Config(width=GRAPH_WIDTH, 
                height=GRAPH_HEIGHT, 
                directed=True,
                nodeHighlightBehavior=True, 
                highlightColor="#F7A7A6",
                collapsible=True,
                node={'labelProperty':'label'},
                link={'labelProperty': 'label', 'renderLabel': True},
                maxZoom=10,
                minZoom=0.1,
                staticGraphWithDragAndDrop=False,
                staticGraph=False,
                initialZoom=1,
                d3 = {'disableLinkForce': True}
                ) 

return_value = agraph(nodes=nodes, 
                      edges=edges, 
                      config=config)

Results: immagine

atakanokan commented 3 years ago

Great solution to manual positioning of the nodes using the x and y arguments. Where can I find a comprehensive list of kwargs that I can pass to Node or Edge classes?

fabiogra commented 3 years ago

This component is based on react-d3-graph, so you should look on https://danielcaldas.github.io/react-d3-graph/docs/index.html#config-node

atakanokan commented 3 years ago

Thanks @fabiogra!