Skip to content

Commit

Permalink
Merge pull request #53 from plotly/dev
Browse files Browse the repository at this point in the history
utils.Tree: Backward Compatibility, add properties props and edge props, remove add_child
  • Loading branch information
mkcor committed May 3, 2019
2 parents 6c187d0 + 2704503 commit 5f19ee7
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 26 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Expand Up @@ -6,6 +6,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Changed
* `utils.Tree`: v0.1.1 broke compatibility with Python 2. Therefore, modified code to be compatible
with Python 2. Added `props` and `edge_props` properties to accept arguments passed directly to
the node's and edge's dictionaries, respectively (e.g., 'classes', 'positions', etc.).
* Removed `Tree`'s method `add_child`, because it is redundant with `add_children` called with an
argument of length 1.

## [0.1.1] - 2019-04-05

### Fixed
Expand Down
1 change: 1 addition & 0 deletions README.md
@@ -1,4 +1,5 @@
# Dash Cytoscape [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/plotly/dash-cytoscape/blob/master/LICENSE) [![PyPi Version](https://img.shields.io/pypi/v/dash-cytoscape.svg)](https://pypi.org/project/dash-cytoscape/)
[![CircleCI](https://circleci.com/gh/plotly/dash-cytoscape.svg?style=svg)](https://circleci.com/gh/plotly/dash-cytoscape)

A Dash component library for creating interactive and customizable networks in Python, wrapped around [Cytoscape.js](http://js.cytoscape.org/).

Expand Down
77 changes: 51 additions & 26 deletions dash_cytoscape/utils/Tree.py
Expand Up @@ -2,26 +2,41 @@


class Tree(object):
def __init__(self, node_id, children=None, data=None, edge_data=None):
def __init__(self,
node_id,
children=None,
data=None,
props=None,
edge_data=None,
edge_props=None):
"""
A class to facilitate tree manipulation in Cytoscape.
:param node_id: The ID of this tree, passed to the node data dict
:param children: The children of this tree, also Tree objects
:param data: Dictionary passed to this tree's node data dict
:param props: Dictionary passed to this tree's node dict, containing the node's props
:param edge_data: Dictionary passed to the data dict of the edge connecting this tree to its
parent
:param edge_props: Dictionary passed to the dict of the edge connecting this tree to its
parent
"""
if not children:
if children is None:
children = []
if not data:
if data is None:
data = {}
if not edge_data:
if props is None:
props = {}
if edge_data is None:
edge_data = {}
if edge_props is None:
edge_props = {}

self.node_id = node_id
self.children = children
self.data = data
self.props = props
self.edge_data = edge_data
self.edge_props = edge_props
self.index = {}

def _dfs(self, search_id):
Expand Down Expand Up @@ -58,17 +73,10 @@ def is_leaf(self):
"""
return not self.children

def add_child(self, child):
"""
Add a single child to the children of a Tree.
:param child: Tree object
"""
self.children.append(child)

def add_children(self, children):
"""
Add a list of children to the current children of a Tree.
:param children: List of Tree objects
Add one or more children to the current children of a Tree.
:param children: List of Tree objects (one object or more)
"""
self.children.extend(children)

Expand All @@ -77,16 +85,18 @@ def get_edges(self):
Get all the edges of the tree in Cytoscape JSON format.
:return: List of dictionaries, each specifying an edge
"""
edges = [
{
edges = []

for child in self.children:
di = {
'data': {
'source': self.node_id,
'target': child.node_id,
**self.edge_data
'target': child.node_id
}
}
for child in self.children
]
di['data'].update(child.edge_data)
di.update(child.edge_props)
edges.append(di)

for child in self.children:
edges.extend(child.get_edges())
Expand All @@ -98,14 +108,15 @@ def get_nodes(self):
Get all the nodes of the tree in Cytoscape JSON format.
:return: List of dictionaries, each specifying a node
"""
nodes = [
{
'data': {
'id': self.node_id,
**self.data
}
di = {
'data': {
'id': self.node_id
}
]
}

di['data'].update(self.data)
di.update(self.props)
nodes = [di]

for child in self.children:
nodes.extend(child.get_nodes())
Expand Down Expand Up @@ -155,3 +166,17 @@ def create_index(self):
stack.append(child)

return self.index


if __name__ == '__main__':
import pprint

t1 = Tree('a', data={'hello': 'goodbye'}, children=[
Tree('b', edge_data={'foo': 'bar'}, edge_props={'classes': 'directed'}),
Tree('c', props={'selected': True})
])

print("Nodes:")
pprint.pprint(t1.get_nodes())
print('\nEdges:')
pprint.pprint(t1.get_edges())

0 comments on commit 5f19ee7

Please sign in to comment.