Bases: TM1Object
Abstraction of TM1 Hierarchy
Requires reference to a Dimension
Elements modeled as a Dictionary where key is the element name and value an instance of TM1py.Element
{
'US': instance of TM1py.Element,
'CN': instance of TM1py.Element,
'AU': instance of TM1py.Element
}
ElementAttributes of type TM1py.Objects.ElementAttribute
Edges are represented as a TM1py.Utils.CaseAndSpaceInsensitiveTupleDict:
{
(parent1, component1) : 10,
(parent1, component2) : 30
}
Subsets is list of type TM1py.Subset
Source code in TM1py/Objects/Hierarchy.py
| def __init__(
self,
name: str,
dimension_name: str,
elements: Optional[Iterable["Element"]] = None,
element_attributes: Optional[Iterable["ElementAttribute"]] = None,
edges: Optional["Dict"] = None,
subsets: Optional[Iterable[str]] = None,
structure: Optional[int] = None,
default_member: Optional[str] = None,
):
self._name = name
self._dimension_name = None
self.dimension_name = dimension_name
self._elements: Dict[str, Element] = CaseAndSpaceInsensitiveDict()
if elements:
for elem in elements:
self._elements[elem.name] = elem
self._element_attributes = list(element_attributes) if element_attributes else []
self._edges = CaseAndSpaceInsensitiveTuplesDict(edges) if edges else CaseAndSpaceInsensitiveTuplesDict()
self._subsets = list(subsets) if subsets else []
# balanced is true, false or None (in versions < TM1 11)
self._balanced = False if not structure else structure == 0
self._default_member = default_member
|
dimension_name
property
writable
element_attributes
property
__contains__(item)
Source code in TM1py/Objects/Hierarchy.py
| def __contains__(self, item):
return self.contains_element(item)
|
__getitem__(item)
Source code in TM1py/Objects/Hierarchy.py
| def __getitem__(self, item):
return self.get_element(item)
|
__iter__()
Source code in TM1py/Objects/Hierarchy.py
| def __iter__(self):
return iter(self._elements.values())
|
__len__()
Source code in TM1py/Objects/Hierarchy.py
| def __len__(self):
return len(self._elements)
|
add_component(parent_name, component_name, weight)
Source code in TM1py/Objects/Hierarchy.py
| def add_component(self, parent_name: str, component_name: str, weight: int):
if parent_name not in self._elements:
raise ValueError(f"Parent '{parent_name}' does not exist in hierarchy")
if self._elements[parent_name].element_type != Element.Types.CONSOLIDATED:
raise ValueError(f"Parent '{parent_name}' is not of type 'Consolidated'")
if component_name not in self.elements:
self.add_element(component_name, "Numeric")
elif self._elements[component_name].element_type == Element.Types.STRING:
raise ValueError(f"Component '{component_name}' must not be of type 'String'")
self.add_edge(parent_name, component_name, weight)
|
add_edge(parent, component, weight)
Source code in TM1py/Objects/Hierarchy.py
| def add_edge(self, parent: str, component: str, weight: float):
self._edges[(parent, component)] = weight
|
add_element(element_name, element_type)
Source code in TM1py/Objects/Hierarchy.py
| def add_element(self, element_name: str, element_type: Union[str, Element.Types]):
if element_name in self._elements:
raise ValueError("Element name must be unique")
self._elements[element_name] = Element(name=element_name, element_type=element_type)
|
add_element_attribute(name, attribute_type)
Source code in TM1py/Objects/Hierarchy.py
| def add_element_attribute(self, name: str, attribute_type: str):
attribute = ElementAttribute(name, attribute_type)
if attribute not in self.element_attributes:
self.element_attributes.append(attribute)
|
contains_element(element_name)
Source code in TM1py/Objects/Hierarchy.py
| def contains_element(self, element_name: str) -> bool:
return element_name in self._elements
|
from_dict(hierarchy_as_dict, dimension_name=None)
classmethod
Source code in TM1py/Objects/Hierarchy.py
| @classmethod
def from_dict(cls, hierarchy_as_dict: Dict, dimension_name: str = None) -> "Hierarchy":
# Build the Dictionary for the edges
edges = CaseAndSpaceInsensitiveTuplesDict(
{(edge["ParentName"], edge["ComponentName"]): edge["Weight"] for edge in hierarchy_as_dict["Edges"]}
)
if not dimension_name:
dimension_name = hierarchy_as_dict["UniqueName"][1 : hierarchy_as_dict["UniqueName"].find("].[")]
return cls(
name=hierarchy_as_dict["Name"],
dimension_name=dimension_name,
elements=[Element.from_dict(elem) for elem in hierarchy_as_dict["Elements"]],
element_attributes=[
ElementAttribute(ea["Name"], ea["Type"]) for ea in hierarchy_as_dict.get("ElementAttributes", [])
],
edges=edges,
subsets=[subset["Name"] for subset in hierarchy_as_dict.get("Subsets", [])],
structure=hierarchy_as_dict["Structure"] if "Structure" in hierarchy_as_dict else None,
default_member=(
hierarchy_as_dict["DefaultMember"]["Name"] if hierarchy_as_dict.get("DefaultMember", None) else None
),
)
|
get_ancestor_edges(element_name, recursive=False)
Source code in TM1py/Objects/Hierarchy.py
| def get_ancestor_edges(self, element_name: str, recursive: bool = False) -> Dict:
ancestor_edges = dict()
for (parent, component), weight in self._edges.items():
if not case_and_space_insensitive_equals(component, element_name):
continue
ancestor_edges[parent, component] = weight
ancestor: Element = self.elements[component]
if recursive:
ancestor_edges.update(self.get_ancestor_edges(ancestor.name, True))
return ancestor_edges
|
get_ancestors(element_name, recursive=False)
Source code in TM1py/Objects/Hierarchy.py
| def get_ancestors(self, element_name: str, recursive: bool = False) -> Set[Element]:
ancestors = set()
for parent, component in self._edges:
if not case_and_space_insensitive_equals(component, element_name):
continue
ancestor: Element = self.elements[parent]
ancestors.add(ancestor)
if recursive:
ancestors = ancestors.union(self.get_ancestors(ancestor.name, True))
return ancestors
|
get_descendant_edges(element_name, recursive=False)
Source code in TM1py/Objects/Hierarchy.py
| def get_descendant_edges(self, element_name: str, recursive: bool = False) -> Dict:
descendant_edges = dict()
for (parent, component), weight in self._edges.items():
if not case_and_space_insensitive_equals(parent, element_name):
continue
descendant_edges[parent, component] = weight
descendant: Element = self.elements[component]
if recursive and descendant.element_type == Element.Types.CONSOLIDATED:
descendant_edges.update(self.get_descendant_edges(descendant.name, True))
return descendant_edges
|
get_descendants(element_name, recursive=False, leaves_only=False)
Source code in TM1py/Objects/Hierarchy.py
| def get_descendants(self, element_name: str, recursive: bool = False, leaves_only=False) -> Set[Element]:
descendants = set()
for parent, component in self._edges:
if not case_and_space_insensitive_equals(parent, element_name):
continue
descendant: Element = self.elements[component]
if not leaves_only:
descendants.add(descendant)
else:
if descendant.element_type == Element.Types.NUMERIC:
descendants.add(descendant)
if recursive and descendant.element_type == Element.Types.CONSOLIDATED:
descendants = descendants.union(self.get_descendants(descendant.name, True, leaves_only=leaves_only))
return descendants
|
get_element(element_name)
Source code in TM1py/Objects/Hierarchy.py
| def get_element(self, element_name: str) -> Element:
if element_name in self._elements:
return self._elements[element_name]
else:
raise ValueError("Element: {} not found in Hierarchy: {}".format(element_name, self.name))
|
remove_all_edges()
Source code in TM1py/Objects/Hierarchy.py
| def remove_all_edges(self):
self._edges = CaseAndSpaceInsensitiveTuplesDict()
|
remove_all_elements()
Source code in TM1py/Objects/Hierarchy.py
| def remove_all_elements(self):
self._elements = CaseAndSpaceInsensitiveDict()
self.remove_all_edges()
|
remove_edge(parent, component)
Source code in TM1py/Objects/Hierarchy.py
| def remove_edge(self, parent: str, component: str):
if (parent, component) in self.edges:
del self.edges[(parent, component)]
|
remove_edges(edges)
Source code in TM1py/Objects/Hierarchy.py
| def remove_edges(self, edges: Iterable[Tuple[str, str]]):
for edge in edges:
self.remove_edge(*edge)
|
Source code in TM1py/Objects/Hierarchy.py
| def remove_edges_related_to_element(self, element_name: str):
element_name_adjusted = lower_and_drop_spaces(element_name)
edges_to_remove = set()
for edge in self._edges.adjusted_keys():
if element_name_adjusted in edge:
edges_to_remove.add(edge)
self.remove_edges(edges=edges_to_remove)
|
remove_element(element_name)
Source code in TM1py/Objects/Hierarchy.py
| def remove_element(self, element_name: str):
if element_name not in self._elements:
return
del self._elements[element_name]
self.remove_edges_related_to_element(element_name=element_name)
|
remove_element_attribute(name)
Source code in TM1py/Objects/Hierarchy.py
| def remove_element_attribute(self, name: str):
self._element_attributes = [
element_attribute
for element_attribute in self.element_attributes
if not case_and_space_insensitive_equals(element_attribute.name, name)
]
|
replace_element(old_element_name, new_element_name)
Substitute one element in the hierarchy structure,
so that all edges are moved from the old element to the new element.
Source code in TM1py/Objects/Hierarchy.py
| def replace_element(self, old_element_name: str, new_element_name: str):
"""
Substitute one element in the hierarchy structure,
so that all edges are moved from the old element to the new element.
"""
if old_element_name not in self.elements:
raise ValueError(f"Element '{old_element_name}' does not exist in hierarchy")
if new_element_name in self.elements:
raise ValueError(f"Element '{new_element_name}' already exists in hierarchy")
element = self.get_element(old_element_name)
ancestor_edges = self.get_ancestor_edges(old_element_name, recursive=False)
descendant_edges = self.get_descendant_edges(element_name=old_element_name, recursive=False)
self.remove_element(element_name=old_element_name)
self.add_element(element_name=new_element_name, element_type=element.element_type)
for (ancestor, _), weight in ancestor_edges.items():
self.add_edge(parent=ancestor, component=new_element_name, weight=weight)
for (_, descendant), weight in descendant_edges.items():
self.add_edge(parent=new_element_name, component=descendant, weight=weight)
|
update_edge(parent, component, weight)
Source code in TM1py/Objects/Hierarchy.py
| def update_edge(self, parent: str, component: str, weight: float):
self._edges[(parent, component)] = weight
|
update_element(element_name, element_type)
Source code in TM1py/Objects/Hierarchy.py
| def update_element(self, element_name: str, element_type: Union[str, Element.Types]):
self._elements[element_name].element_type = element_type
|