Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor python netstream example, adapt to python3 #12

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
Open
12 changes: 12 additions & 0 deletions python/Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Python example of the NetStreamGraph usage

For running NetStreamGraph on python you need to do the following:
1. Run a server receiver for graph visualization.

[Java server example](https://github.com/max-kalganov/graph_stream_server)
2. Use NetStreamProxyGraph to fill a graph.

class import - `from gs_netstream import NetStreamProxyGraph`
See NetStreamProxyGraph implementation to look up graph methods.

Run `example_sender.py` for an experiment.
40 changes: 28 additions & 12 deletions python/example_sender.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,35 @@
import logging
from gs_netstream.sender import NetStreamProxyGraph, NetStreamSender
from time import sleep
from gs_netstream import NetStreamProxyGraph
from random import randint

logging.basicConfig(level=logging.DEBUG)

sender = NetStreamSender(2012)
proxy = NetStreamProxyGraph(sender)

style = "node{fill-mode:plain;fill-color:gray;size:1px;}"
proxy.add_attribute("stylesheet", style)
def ex1(graph: NetStreamProxyGraph) -> None:
style = "node{fill-mode:plain;fill-color:gray;size:1px;}"
graph.add_attribute("stylesheet", style)

proxy.add_attribute("ui.antialias", True)
proxy.add_attribute("layout.stabilization-limit", 0)
graph.add_attribute("ui.antialias", True)
graph.add_attribute("layout.stabilization-limit", 0)

for i in range(0,500):
proxy.add_node(str(i))
if i > 0:
proxy.add_edge(str(i) + "_" + str(i-1), str(i), str(i-1), False)
proxy.add_edge(str(i) + "__" + str(i/2), str(i), str(i/2), False)
for i in range(500):
sleep(0.2)
graph.add_node(str(i))
if i > 0:
graph.add_edge(str(i) + "_" + str(i-1), str(i), str(i-1), False)
graph.add_edge(str(i) + "__" + str(i/2), str(i), str(i/2), False)


def ex2(graph: NetStreamProxyGraph) -> None:
graph.add_node("0")
for i in range(1, 200):
sleep(0.2)
graph.add_node(str(i))
i2 = str(randint(0, i-1))
graph.add_edge(f"{str(i)}_{i2}", str(i), i2)


if __name__ == '__main__':
graph = NetStreamProxyGraph(port=8008)
ex2(graph)
1 change: 1 addition & 0 deletions python/gs_netstream/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .graph_sender import NetStreamProxyGraph
53 changes: 34 additions & 19 deletions python/gs_netstream/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,53 +6,68 @@
Created by Yoann Pigné on 2011-08-21.
Copyright (c) 2011 University of Luxembourg. All rights reserved.
"""
from abc import ABC, abstractmethod

import sys
import os

class AttributeSink(object):
class AttributeSink(ABC):
@abstractmethod
def graph_attribute_added(self, source_id, time_id, attribute, value):
raise NotImplementedError
pass

@abstractmethod
def graph_attribute_changed(self, source_id, time_id, attribute, old_value, new_value):
raise NotImplementedError
pass

@abstractmethod
def graph_attribute_removed(self, source_id, time_id, attribute):
raise NotImplementedError
pass

@abstractmethod
def node_attribute_added(self, source_id, time_id, node_id, attribute, value):
raise NotImplementedError
pass

@abstractmethod
def node_attribute_changed(self, source_id, time_id, node_id, attribute, old_value, new_value):
raise NotImplementedError
pass

@abstractmethod
def node_attribute_removed(self, source_id, time_id, node_id, attribute):
raise NotImplementedError
pass

@abstractmethod
def edge_attribute_added(self, source_id, time_id, edge_id, attribute, value):
raise NotImplementedError
pass

@abstractmethod
def edge_attribute_changed(self, source_id, time_id, edge_id, attribute, old_value, new_value):
raise NotImplementedError
pass

@abstractmethod
def edge_attribute_removed(self, source_id, time_id, edge_id, attribute):
raise NotImplementedError
pass

class ElementSink(object):

class ElementSink(ABC):
@abstractmethod
def node_added(self, source_id, time_id, node_id):
raise NotImplementedError
pass

@abstractmethod
def node_removed(self, source_id, time_id, node_id):
raise NotImplementedError
pass

@abstractmethod
def edge_added(self, source_id, time_id, edge_id, from_node, to_node, directed):
raise NotImplementedError
pass

@abstractmethod
def edge_removed(self, source_id, time_id, edge_id):
raise NotImplementedError
pass

@abstractmethod
def step_begun(self, source_id, time_id, timestamp):
raise NotImplementedError
pass

@abstractmethod
def graph_cleared(self, source_id, time_id):
raise NotImplementedError
pass
86 changes: 86 additions & 0 deletions python/gs_netstream/graph_sender.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
"""Proxy Netstream graph class"""
from random import random
from typing import Optional

from gs_netstream.sender import NetStreamSender


class NetStreamProxyGraph:
"""
This is a utility class that handles 'source id' and 'time id' synchronization tokens.
It proposes utile classes that allow to directly send events through the network pipe.
"""

def __init__(self, sender: Optional[NetStreamSender] = None, source_id: Optional[str] = None, port: int = 8008):
"""Constructor can be with one NetStreamSender object and a source id OR with with 4 args.

Notes:
4 args: Source ID, Stream ID, Host, and port number
"""
self.sender = sender if sender is not None else NetStreamSender(port)
self.source_id = source_id if source_id else "nss%d" % (1000 * random())
self.time_id = 0

def run_sender_method(self, sender_method, *args, **kwargs):
sender_method(self.source_id, self.time_id, *args, **kwargs)
self.time_id += 1

def add_node(self, node: str):
"""Add a node to the graph."""
self.run_sender_method(self.sender.node_added, node)

def remove_node(self, node: str):
"""Remove a node from the graph."""
self.run_sender_method(self.sender.node_removed, node)

def add_edge(self, edge: str, from_node: str, to_node: str, directed: bool = False):
"""Add an edge to the graph."""
self.run_sender_method(self.sender.edge_added, edge, from_node, to_node, directed)

def remove_edge(self, edge: str):
"""Remove an edge from the graph."""
self.run_sender_method(self.sender.edge_removed, edge)

def add_attribute(self, attribute: str, value):
"""Add an attribute to the graph."""
self.run_sender_method(self.sender.graph_attribute_added, attribute, value)

def remove_attribute(self, attribute: str):
"""Remove an attribute from the graph."""
self.run_sender_method(self.sender.graph_attribute_removed, attribute)

def change_attribute(self, attribute: str, old_value, new_value):
"""Change an attribute of the graph."""
self.run_sender_method(self.sender.graph_attribute_changed, attribute, old_value, new_value)

def add_node_attribute(self, node: str, attribute: str, value):
"""Add an attribute to a node."""
self.run_sender_method(self.sender.node_attribute_added, node, attribute, value)

def remove_node_attibute(self, node: str, attribute: str):
"""Remove an attribute from a node."""
self.run_sender_method(self.sender.node_attribute_removed, node, attribute)

def change_node_attribute(self, node: str, attribute: str, old_value, new_value):
"""Change an attribute of a node."""
self.run_sender_method(self.sender.node_attribute_changed, node, attribute, old_value, new_value)

def add_edge_attribute(self, edge: str, attribute: str, value):
"""Add an attribute to an edge."""
self.run_sender_method(self.sender.edge_attribute_added, edge, attribute, value)

def remove_edge_attribute(self, edge: str, attribute: str):
"""Remove an attribute from an edge."""
self.run_sender_method(self.sender.edge_attribute_removed, edge, attribute)

def change_edge_attribute(self, edge: str, attribute: str, old_value, new_value):
"""Change an attribute of an edge."""
self.run_sender_method(self.sender.edge_attribute_changed, edge, attribute, old_value, new_value)

def clear_graph(self):
"""Clear the graph."""
self.run_sender_method(self.sender.graph_cleared)

def step_begins(self, time: int):
"""Begin a step."""
self.run_sender_method(self.sender.step_begun, time)
Loading