Skip to content

Base Node

BaseNode

Bases: ABC

Abstract base class for all node types in a tree.

Attributes:

Name Type Description
id int

Unique identifier assigned to the node, or None if unset.

indices ndarray

Row indices of the samples associated with this node.

y_res ndarray

Residuals of the target variable at this node.

rss float

Residual sum of squares at this node.

Source code in imote/nodes/base_node.py
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
class BaseNode(ABC):
    """Abstract base class for all node types in a tree.

    Attributes:
        id: Unique identifier assigned to the node, or None if unset.
        indices: Row indices of the samples associated with this node.
        y_res: Residuals of the target variable at this node.
        rss: Residual sum of squares at this node.
    """
    id: int
    indices: np.ndarray
    y_res: np.ndarray
    rss: float

    def __init__(self, indices: np.ndarray, y_res: np.ndarray, rss: float):
        """
        Args:
            indices: Row indices of the samples belonging to this node.
            y_res: Residuals of the target variable at this node.
            rss: Residual sum of squares at this node.
        """
        self.indices = indices
        self.y_res = y_res
        self.rss = rss

    def set_id(self, id: int):
        """Sets the unique identifier of the node.

        Args:
            id: Identifier to assign.
        """
        self.id = id

    @abstractmethod
    def get_children(self) -> List["BaseNode"]:
        """Returns the list of child nodes of this node.

        Returns:
            List of child BaseNode instances (empty for leaf-like nodes).
        """
        pass

    def get_all_children(self) -> List["BaseNode"]:
        """Returns all descendant nodes of this node, recursively.

        Returns:
            Flat list of all descendant BaseNode instances, in
            depth-first order.
        """
        children = self.get_children()
        descendants = list(children)
        for child in children:
            descendants.extend(child.get_all_children())
        return descendants

    @abstractmethod
    def get_label(self) -> str:
        """Returns the full display label for this node.

        Returns:
            String of label, shown in a tree visualization.
        """
        pass

    @abstractmethod
    def get_minimal_label(self) -> str:
        """Returns a short display label for this node.

        Returns:
            String of minimal label, used when space is limited.
        """
        pass

    def to_dict(self) -> dict:
        """Serializes the node's base attributes to a dictionary.

        Subclasses should call this and extend the result with their
        own attributes.

        Returns:
            Dictionary with the node's id, rss, indices, and y_res.
        """
        node_dict = {"id": self.id, "rss": self.rss}
        if isinstance(self.indices, list):
            node_dict["indices"] = self.indices
        else:
            node_dict["indices"] = self.indices.tolist()
        if isinstance(self.y_res, list):
            node_dict["y_res"] = self.y_res
        else:
            node_dict["y_res"] = self.y_res.tolist()
        return node_dict

    @classmethod
    def from_dict(cls, node_dict: dict) -> "BaseNode":
        """Reconstructs the node's base attributes from a dictionary.

        Subclasses should call this and populate their own attributes
        on the returned object.

        Args:
            node_dict: Dictionary of node previously produced by to_dict().

        Returns:
            A new instance of cls with base attributes restored.
        """
        obj = cls.__new__(cls)
        obj.id = node_dict["id"]
        obj.indices = np.array(node_dict["indices"])
        obj.y_res = np.array(node_dict["y_res"])
        obj.rss = node_dict["rss"]
        return obj

    class_registry = {}
    """Maps subclass names to subclass objects, for use in from_dict()."""

    @classmethod
    def register(cls, subclass: Type[T]) -> Type[T]:
        """Class decorator that registers a node subclass by name.

        Registration is required so that from_dict() can look up the
        correct class when deserializing a node whose type is only
        known by name (e.g. a child stored as "left_child_class").

        Args:
            subclass: The BaseNode subclass to register.

        Returns:
            The subclass, unchanged (so it can be used as a decorator).
        """
        cls.class_registry[subclass.__name__] = subclass
        return subclass

class_registry = {} class-attribute instance-attribute

Maps subclass names to subclass objects, for use in from_dict().

__init__(indices: np.ndarray, y_res: np.ndarray, rss: float)

Parameters:

Name Type Description Default
indices ndarray

Row indices of the samples belonging to this node.

required
y_res ndarray

Residuals of the target variable at this node.

required
rss float

Residual sum of squares at this node.

required
Source code in imote/nodes/base_node.py
22
23
24
25
26
27
28
29
30
31
def __init__(self, indices: np.ndarray, y_res: np.ndarray, rss: float):
    """
    Args:
        indices: Row indices of the samples belonging to this node.
        y_res: Residuals of the target variable at this node.
        rss: Residual sum of squares at this node.
    """
    self.indices = indices
    self.y_res = y_res
    self.rss = rss

set_id(id: int)

Sets the unique identifier of the node.

Parameters:

Name Type Description Default
id int

Identifier to assign.

required
Source code in imote/nodes/base_node.py
33
34
35
36
37
38
39
def set_id(self, id: int):
    """Sets the unique identifier of the node.

    Args:
        id: Identifier to assign.
    """
    self.id = id

get_children() -> List[BaseNode] abstractmethod

Returns the list of child nodes of this node.

Returns:

Type Description
List[BaseNode]

List of child BaseNode instances (empty for leaf-like nodes).

Source code in imote/nodes/base_node.py
41
42
43
44
45
46
47
48
@abstractmethod
def get_children(self) -> List["BaseNode"]:
    """Returns the list of child nodes of this node.

    Returns:
        List of child BaseNode instances (empty for leaf-like nodes).
    """
    pass

get_all_children() -> List[BaseNode]

Returns all descendant nodes of this node, recursively.

Returns:

Type Description
List[BaseNode]

Flat list of all descendant BaseNode instances, in

List[BaseNode]

depth-first order.

Source code in imote/nodes/base_node.py
50
51
52
53
54
55
56
57
58
59
60
61
def get_all_children(self) -> List["BaseNode"]:
    """Returns all descendant nodes of this node, recursively.

    Returns:
        Flat list of all descendant BaseNode instances, in
        depth-first order.
    """
    children = self.get_children()
    descendants = list(children)
    for child in children:
        descendants.extend(child.get_all_children())
    return descendants

get_label() -> str abstractmethod

Returns the full display label for this node.

Returns:

Type Description
str

String of label, shown in a tree visualization.

Source code in imote/nodes/base_node.py
63
64
65
66
67
68
69
70
@abstractmethod
def get_label(self) -> str:
    """Returns the full display label for this node.

    Returns:
        String of label, shown in a tree visualization.
    """
    pass

get_minimal_label() -> str abstractmethod

Returns a short display label for this node.

Returns:

Type Description
str

String of minimal label, used when space is limited.

Source code in imote/nodes/base_node.py
72
73
74
75
76
77
78
79
@abstractmethod
def get_minimal_label(self) -> str:
    """Returns a short display label for this node.

    Returns:
        String of minimal label, used when space is limited.
    """
    pass

to_dict() -> dict

Serializes the node's base attributes to a dictionary.

Subclasses should call this and extend the result with their own attributes.

Returns:

Type Description
dict

Dictionary with the node's id, rss, indices, and y_res.

Source code in imote/nodes/base_node.py
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
def to_dict(self) -> dict:
    """Serializes the node's base attributes to a dictionary.

    Subclasses should call this and extend the result with their
    own attributes.

    Returns:
        Dictionary with the node's id, rss, indices, and y_res.
    """
    node_dict = {"id": self.id, "rss": self.rss}
    if isinstance(self.indices, list):
        node_dict["indices"] = self.indices
    else:
        node_dict["indices"] = self.indices.tolist()
    if isinstance(self.y_res, list):
        node_dict["y_res"] = self.y_res
    else:
        node_dict["y_res"] = self.y_res.tolist()
    return node_dict

from_dict(node_dict: dict) -> BaseNode classmethod

Reconstructs the node's base attributes from a dictionary.

Subclasses should call this and populate their own attributes on the returned object.

Parameters:

Name Type Description Default
node_dict dict

Dictionary of node previously produced by to_dict().

required

Returns:

Type Description
BaseNode

A new instance of cls with base attributes restored.

Source code in imote/nodes/base_node.py
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
@classmethod
def from_dict(cls, node_dict: dict) -> "BaseNode":
    """Reconstructs the node's base attributes from a dictionary.

    Subclasses should call this and populate their own attributes
    on the returned object.

    Args:
        node_dict: Dictionary of node previously produced by to_dict().

    Returns:
        A new instance of cls with base attributes restored.
    """
    obj = cls.__new__(cls)
    obj.id = node_dict["id"]
    obj.indices = np.array(node_dict["indices"])
    obj.y_res = np.array(node_dict["y_res"])
    obj.rss = node_dict["rss"]
    return obj

register(subclass: Type[T]) -> Type[T] classmethod

Class decorator that registers a node subclass by name.

Registration is required so that from_dict() can look up the correct class when deserializing a node whose type is only known by name (e.g. a child stored as "left_child_class").

Parameters:

Name Type Description Default
subclass Type[T]

The BaseNode subclass to register.

required

Returns:

Type Description
Type[T]

The subclass, unchanged (so it can be used as a decorator).

Source code in imote/nodes/base_node.py
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
@classmethod
def register(cls, subclass: Type[T]) -> Type[T]:
    """Class decorator that registers a node subclass by name.

    Registration is required so that from_dict() can look up the
    correct class when deserializing a node whose type is only
    known by name (e.g. a child stored as "left_child_class").

    Args:
        subclass: The BaseNode subclass to register.

    Returns:
        The subclass, unchanged (so it can be used as a decorator).
    """
    cls.class_registry[subclass.__name__] = subclass
    return subclass