Source code for mdt.model_building.trees
__author__ = 'Robbert Harms'
__date__ = "2015-03-26"
__license__ = "LGPL v3"
__maintainer__ = "Robbert Harms"
__email__ = "robbert@xkls.nl"
[docs]class Tree:
def __init__(self, data=None, tag=None, children=None, parent=None):
"""Create a new Tree.
In this tree, every node is a tree object as well. The tree is implemented as a linked list.
Each node has a reference to its children and to its parent node.
Args:
data : The data object
tag (str): The tag used for displaying this node
children (list of Tree): The list of children to this node
parent (Tree): The parent tree node.
Attributes:
data : The data object
tag (str): The tag used for displaying this node
children (list of Tree): The list of children to this node
parent (Tree): The parent tree node.
"""
self.data = data
self.tag = tag or ""
self.children = children or []
self.parent = parent
@property
def leaves(self):
"""Get all the leaves under this tree.
Returns:
list: A list of all leaves under this tree.
"""
leaves = []
if not self.children:
leaves.append(self)
else:
for child in self.children:
leaves.extend(child.leaves)
return leaves
@property
def internal_nodes(self):
"""Get all the non-leaves under this tree (the internal nodes).
Returns:
list: A list of all non-leaves under this tree.
"""
internal_nodes = []
if self.children:
internal_nodes.append(self)
for child in self.children:
internal_nodes.extend(child.internal_nodes)
return internal_nodes
def __str__(self, level=0):
ret = "\t"*level + self.tag + "\n"
for child in self.children:
ret += child.__str__(level+1)
return ret
[docs]class CompartmentModelTree(Tree):
def __init__(self, model_lists):
"""Builds a multi modal multi compartment model from the given model tree.
Valid model trees abides this grammar:
tree ::= model | '(' tree ')' | '(' tree ',' operator ')'
model ::= CompartmentModel ['(' nickname ')']
operator ::= '*' | '/' | '+' | '-'
This means that one can build complex models consisting of compartment models combined using basic
math operators.
Args:
model_lists (list of mdt.models.compartments.CompartmentModel): The model tree list
"""
super().__init__()
self._init_tree(model_lists)
[docs] def get_compartment_models(self):
"""Get the compartment models that are part of this tree.
This basically just returns the leaves of the tree.
Returns:
list of mdt.models.compartments.CompartmentModel: the compartments in this tree
"""
return [n.data for n in self.leaves]
def _init_tree(self, listing):
if isinstance(listing, (list, tuple)):
if len(listing) == 1:
self.data = listing[0]
self.tag = listing[0].name
else:
operator = None
for node in listing:
if isinstance(node, str):
if operator is not None:
raise ValueError('Double operator in model listing.')
operator = node
else:
nn = CompartmentModelTree(node)
nn.parent = self
self.children.append(nn)
if operator is None:
raise ValueError('No operator in model listing.')
self.data = operator
self.tag = operator
else:
self.data = listing
self.tag = listing.name
def __str__(self, level=0):
if isinstance(self.data, str):
operator = ' ' + self.data + ' '
return '(' + "\n" + "\t" * (level + 1) + \
operator.join([child.__str__(level + 1) for child in self.children]) + \
"\n" + "\t" * level + ')'
else:
return self.data.name + '(' + ', '.join([p.name for p in self.data.get_parameters()]) + ')'