from copy import copy
from functools import reduce
from pydistsim.utils.memory import MemoryStructure
[docs]
class Positions(MemoryStructure):
"""Class to represent subclusters positions data in node memory.
Position instances initializer has only one attribute ``subclusters`` a
list of dictionaries in form {node: position_array,}. Node can be part of
multiple subclusters.
"""
def __init__(self, subclusters=None):
self.subclusters = []
if subclusters is not None:
# list of dictionaries of positioned subclusters
assert isinstance(subclusters, list)
# create subclusters by copying from given list and its dicts
ini_subclusters = list(subclusters)
self.subclusters = []
for subcluster in ini_subclusters:
new_subcluster = {}
for n, p in list(subcluster.items()):
new_subcluster.update({n: copy(p)})
self.subclusters.append(new_subcluster)
self.old_style_positions = {}
self.old_style_subclusters = []
[docs]
@classmethod
def create(cls, obj):
"""Create Positions instance from obj which can be dict or list.
If it's dict this method wraps it in list. Returns Position object
dereferenced from the initial list or dict.
For example ``obj`` can be ``net.pos`` dict.
"""
if not isinstance(obj, cls):
if not isinstance(obj, list):
assert isinstance(obj, dict)
obj = [obj]
obj = cls(obj)
return obj
@property
def subclusters_nodes(self):
"""Returns list of subclusters without positions."""
cl = []
for c in self.subclusters:
cl.append(list(c.keys()))
return cl
[docs]
def set_pos_copy(self, positions):
"""Empty all subclusters and copy in data from ``positions``."""
assert isinstance(positions, Positions)
self.subclusters = []
for subcluster in positions.subclusters:
new_subcluster = {}
for n, p in list(subcluster.items()):
new_subcluster.update({n: copy(p)})
self.subclusters.append(new_subcluster)
def __len__(self):
return len(self.subclusters)
[docs]
def get_nodes(self):
"""Returns nodes in all subclusters."""
nodes = []
for subcluster in self.subclusters:
nodes += [node for node in subcluster if node not in nodes]
return nodes
[docs]
def get_largest_subcluster(self):
"""Returns new Positions instance with only one largest subcluster.
If multiple subclusters have maximum number of nodes, first one is
returned."""
return Positions([reduce(lambda x, y: len(x) > len(y) and x or y, self.subclusters)])
[docs]
def get_dic(self):
dic = {}
for i, sc in enumerate(self.subclusters):
dic["subclusters[%d] (%d nodes)" % (i, len(sc))] = sc
return dic
def __str__(self):
return str(self.subclusters)
def __getitem__(self, key):
if isinstance(key, int):
return self.subclusters[key]
return self.__getattribute__(key)