Skip to content

whitecanvas.types

Alignment

Source code in whitecanvas\types\_enums.py
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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
class Alignment(_StrEnum):
    TOP = "top"
    BOTTOM = "bottom"
    LEFT = "left"
    RIGHT = "right"
    CENTER = "center"
    TOP_LEFT = "top_left"
    TOP_RIGHT = "top_right"
    BOTTOM_LEFT = "bottom_left"
    BOTTOM_RIGHT = "bottom_right"

    @classmethod
    def merge(cls, vertical, horizontal: Alignment) -> Alignment:
        if vertical not in (Alignment.TOP, Alignment.BOTTOM, Alignment.CENTER):
            raise ValueError(f"{vertical} is not a vertical alignment")
        if horizontal not in (Alignment.LEFT, Alignment.RIGHT, Alignment.CENTER):
            raise ValueError(f"{horizontal} is not a horizontal alignment")
        if vertical is Alignment.TOP:
            if horizontal is Alignment.LEFT:
                return Alignment.TOP_LEFT
            elif horizontal is Alignment.RIGHT:
                return Alignment.TOP_RIGHT
            elif horizontal is Alignment.CENTER:
                return Alignment.TOP
            else:
                raise RuntimeError  # unreachable
        elif vertical is Alignment.BOTTOM:
            if horizontal is Alignment.LEFT:
                return Alignment.BOTTOM_LEFT
            elif horizontal is Alignment.RIGHT:
                return Alignment.BOTTOM_RIGHT
            elif horizontal is Alignment.CENTER:
                return Alignment.BOTTOM
            else:
                raise RuntimeError  # unreachable
        elif vertical is Alignment.CENTER:
            return horizontal
        else:
            raise RuntimeError  # unreachable

    def split(self) -> tuple[Alignment, Alignment]:
        """Split the alignment into vertical and horizontal components."""
        name = self.name
        if "TOP" in name:
            vertical = Alignment.TOP
        elif "BOTTOM" in name:
            vertical = Alignment.BOTTOM
        else:
            vertical = Alignment.CENTER
        if "LEFT" in name:
            horizontal = Alignment.LEFT
        elif "RIGHT" in name:
            horizontal = Alignment.RIGHT
        else:
            horizontal = Alignment.CENTER
        return vertical, horizontal
split()

Split the alignment into vertical and horizontal components.

Source code in whitecanvas\types\_enums.py
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
def split(self) -> tuple[Alignment, Alignment]:
    """Split the alignment into vertical and horizontal components."""
    name = self.name
    if "TOP" in name:
        vertical = Alignment.TOP
    elif "BOTTOM" in name:
        vertical = Alignment.BOTTOM
    else:
        vertical = Alignment.CENTER
    if "LEFT" in name:
        horizontal = Alignment.LEFT
    elif "RIGHT" in name:
        horizontal = Alignment.RIGHT
    else:
        horizontal = Alignment.CENTER
    return vertical, horizontal

Location

Source code in whitecanvas\types\_enums.py
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
class Location(_StrEnum):
    TOP_CENTER = "top_center"
    BOTTOM_CENTER = "bottom_center"
    CENTER_LEFT = "center_left"
    CENTER_RIGHT = "center_right"
    CENTER = "center"
    TOP_LEFT = "top_left"
    TOP_RIGHT = "top_right"
    BOTTOM_LEFT = "bottom_left"
    BOTTOM_RIGHT = "bottom_right"
    LEFT_SIDE_TOP = "left_side_top"
    LEFT_SIDE_CENTER = "left_side_center"
    LEFT_SIDE_BOTTOM = "left_side_bottom"
    RIGHT_SIDE_TOP = "right_side_top"
    RIGHT_SIDE_CENTER = "right_side_center"
    RIGHT_SIDE_BOTTOM = "right_side_bottom"
    TOP_SIDE_LEFT = "top_side_left"
    TOP_SIDE_CENTER = "top_side_center"
    TOP_SIDE_RIGHT = "top_side_right"
    BOTTOM_SIDE_LEFT = "bottom_side_left"
    BOTTOM_SIDE_CENTER = "bottom_side_center"
    BOTTOM_SIDE_RIGHT = "bottom_side_right"

    @property
    def is_side(self) -> bool:
        """True if the location is in any of the side locations."""
        return "SIDE" in self.name

    @classmethod
    def parse(cls, value: str) -> Location:
        if value in ("top", "bottom", "left", "right"):
            return cls(value + "_center")
        if "-" in value:
            return cls(value.replace("-", "_"))
        return cls(value)
is_side: bool property

True if the location is in any of the side locations.

MeshData

Source code in whitecanvas\types\_tuples.py
139
140
141
142
143
144
145
146
147
148
149
150
class MeshData(NamedTuple):
    vertices: NDArray[np.floating]
    faces: NDArray[np.intp]

    @classmethod
    def from_dict(cls, data: dict[str, NDArray[np.floating]]) -> MeshData:
        """Create MeshData from a dictionary."""
        return cls(data["vertices"], data["faces"])

    def to_dict(self) -> dict[str, NDArray[np.floating]]:
        """Data as a dictionary."""
        return {"vertices": self.vertices, "faces": self.faces}
from_dict(data) classmethod

Create MeshData from a dictionary.

Source code in whitecanvas\types\_tuples.py
143
144
145
146
@classmethod
def from_dict(cls, data: dict[str, NDArray[np.floating]]) -> MeshData:
    """Create MeshData from a dictionary."""
    return cls(data["vertices"], data["faces"])
to_dict()

Data as a dictionary.

Source code in whitecanvas\types\_tuples.py
148
149
150
def to_dict(self) -> dict[str, NDArray[np.floating]]:
    """Data as a dictionary."""
    return {"vertices": self.vertices, "faces": self.faces}

Modifier

Enum that represents the keyboard modifiers.

Source code in whitecanvas\types\_enums.py
78
79
80
81
82
83
84
class Modifier(_StrEnum):
    """Enum that represents the keyboard modifiers."""

    SHIFT = "shift"
    CTRL = "ctrl"
    ALT = "alt"
    META = "meta"

MouseButton

Enum that represents the mouse buttons.

Source code in whitecanvas\types\_enums.py
87
88
89
90
91
92
93
94
95
class MouseButton(_StrEnum):
    """Enum that represents the mouse buttons."""

    NONE = "none"
    LEFT = "left"
    MIDDLE = "middle"
    RIGHT = "right"
    BACK = "back"
    FORWARD = "forward"

MouseEventType

Enum that represents the mouse event type.

Source code in whitecanvas\types\_enums.py
 98
 99
100
101
102
103
104
class MouseEventType(_StrEnum):
    """Enum that represents the mouse event type."""

    MOVE = "move"
    PRESS = "press"
    RELEASE = "release"
    DOUBLE_CLICK = "double_click"

Orientation

Source code in whitecanvas\types\_enums.py
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
class Orientation(_StrEnum):
    VERTICAL = "vertical"
    HORIZONTAL = "horizontal"

    @classmethod
    def parse(cls, value):
        if isinstance(value, str):
            if value == "v":
                return cls.VERTICAL
            elif value == "h":
                return cls.HORIZONTAL
        return cls(value)

    def transpose(self) -> Orientation:
        """Transpose the orientation."""
        if self is self.VERTICAL:
            return self.HORIZONTAL
        else:
            return self.VERTICAL

    @property
    def is_vertical(self):
        return self is Orientation.VERTICAL

    @property
    def is_horizontal(self):
        return self is Orientation.HORIZONTAL
transpose()

Transpose the orientation.

Source code in whitecanvas\types\_enums.py
224
225
226
227
228
229
def transpose(self) -> Orientation:
    """Transpose the orientation."""
    if self is self.VERTICAL:
        return self.HORIZONTAL
    else:
        return self.VERTICAL

Origin

Enum that define the center of image.

1-----+ 0: corner | | 1: edge | 0 | 2: center (center of image) | | +-----+

Source code in whitecanvas\types\_enums.py
243
244
245
246
247
248
249
250
251
252
253
254
255
256
class Origin(_StrEnum):
    """
    Enum that define the center of image.

    1-----+  0: corner
    |     |  1: edge
    |  0  |  2: center (center of image)
    |     |
    +-----+
    """

    CORNER = "corner"
    EDGE = "edge"
    CENTER = "center"

Rect

Rectangular range in left, right, bottom, top order.

Source code in whitecanvas\types\_tuples.py
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
class Rect(NamedTuple):
    """Rectangular range in left, right, bottom, top order."""

    left: float
    right: float
    bottom: float
    top: float

    def __repr__(self) -> str:
        return (
            f"Rect(left={self.left:.6g}, right={self.right:.6g}, "
            f"bottom={self.bottom:.6g}, top={self.top:.6g})"
        )

    @classmethod
    def with_check(cls, left: float, right: float, bottom: float, top: float):
        if left > right:
            raise ValueError("left must be less than or equal to right")
        if bottom > top:
            raise ValueError("bottom must be less than or equal to top")
        return cls(float(left), float(right), float(bottom), float(top))

    @classmethod
    def with_sort(cls, left: float, right: float, bottom: float, top: float):
        left, right = sorted([left, right])
        bottom, top = sorted([bottom, top])
        return cls(float(left), float(right), float(bottom), float(top))

    @property
    def width(self) -> float:
        """Width of the range."""
        return self.right - self.left

    @property
    def height(self) -> float:
        """Height of the range."""
        return self.top - self.bottom

    @property
    def size(self) -> tuple[float, float]:
        """Size (width, height) of the range."""
        return self.width, self.height

    @property
    def center(self) -> tuple[float, float]:
        """Center of the range."""
        return (self.left + self.right) / 2, (self.top + self.bottom) / 2

    @classmethod
    def from_dict(cls, data: dict[str, float]) -> Rect:
        """Create Rect from a dictionary."""
        return cls(data["left"], data["right"], data["bottom"], data["top"])

    def to_dict(self) -> dict[str, float]:
        """Data as a dictionary."""
        return {
            "left": self.left,
            "right": self.right,
            "bottom": self.bottom,
            "top": self.top,
        }
center: tuple[float, float] property

Center of the range.

height: float property

Height of the range.

size: tuple[float, float] property

Size (width, height) of the range.

width: float property

Width of the range.

from_dict(data) classmethod

Create Rect from a dictionary.

Source code in whitecanvas\types\_tuples.py
201
202
203
204
@classmethod
def from_dict(cls, data: dict[str, float]) -> Rect:
    """Create Rect from a dictionary."""
    return cls(data["left"], data["right"], data["bottom"], data["top"])
to_dict()

Data as a dictionary.

Source code in whitecanvas\types\_tuples.py
206
207
208
209
210
211
212
213
def to_dict(self) -> dict[str, float]:
    """Data as a dictionary."""
    return {
        "left": self.left,
        "right": self.right,
        "bottom": self.bottom,
        "top": self.top,
    }

XYData

Tuple of x and y array.

Used for data of Line, Markers etc.

Source code in whitecanvas\types\_tuples.py
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class XYData(NamedTuple):
    """
    Tuple of x and y array.

    Used for data of Line, Markers etc.
    """

    x: NDArray[np.floating]
    y: NDArray[np.floating]

    def stack(self) -> NDArray[np.floating]:
        """Data as a stacked (N, 2) array."""
        return np.stack([self.x, self.y], axis=1)

    @classmethod
    def from_dict(cls, data: dict[str, NDArray[np.floating]]) -> XYData:
        """Create XYData from a dictionary."""
        return cls(data["x"], data["y"])

    def to_dict(self) -> dict[str, NDArray[np.floating]]:
        """Data as a dictionary."""
        return {"x": self.x, "y": self.y}
from_dict(data) classmethod

Create XYData from a dictionary.

Source code in whitecanvas\types\_tuples.py
23
24
25
26
@classmethod
def from_dict(cls, data: dict[str, NDArray[np.floating]]) -> XYData:
    """Create XYData from a dictionary."""
    return cls(data["x"], data["y"])
stack()

Data as a stacked (N, 2) array.

Source code in whitecanvas\types\_tuples.py
19
20
21
def stack(self) -> NDArray[np.floating]:
    """Data as a stacked (N, 2) array."""
    return np.stack([self.x, self.y], axis=1)
to_dict()

Data as a dictionary.

Source code in whitecanvas\types\_tuples.py
28
29
30
def to_dict(self) -> dict[str, NDArray[np.floating]]:
    """Data as a dictionary."""
    return {"x": self.x, "y": self.y}

XYTextData

Source code in whitecanvas\types\_tuples.py
62
63
64
65
66
67
68
69
70
71
72
73
74
class XYTextData(NamedTuple):
    x: NDArray[np.floating]
    y: NDArray[np.floating]
    text: NDArray[np.object_]

    @classmethod
    def from_dict(cls, data: dict[str, NDArray[np.floating]]) -> XYTextData:
        """Create XYTextData from a dictionary."""
        return cls(data["x"], data["y"], data["text"])

    def to_dict(self) -> dict[str, NDArray[np.floating]]:
        """Data as a dictionary."""
        return {"x": self.x, "y": self.y, "text": self.text}
from_dict(data) classmethod

Create XYTextData from a dictionary.

Source code in whitecanvas\types\_tuples.py
67
68
69
70
@classmethod
def from_dict(cls, data: dict[str, NDArray[np.floating]]) -> XYTextData:
    """Create XYTextData from a dictionary."""
    return cls(data["x"], data["y"], data["text"])
to_dict()

Data as a dictionary.

Source code in whitecanvas\types\_tuples.py
72
73
74
def to_dict(self) -> dict[str, NDArray[np.floating]]:
    """Data as a dictionary."""
    return {"x": self.x, "y": self.y, "text": self.text}

XYVectorData

Source code in whitecanvas\types\_tuples.py
102
103
104
105
106
107
108
109
110
111
112
113
114
115
class XYVectorData(NamedTuple):
    x: NDArray[np.floating]
    y: NDArray[np.floating]
    vx: NDArray[np.floating]
    vy: NDArray[np.floating]

    @classmethod
    def from_dict(cls, data: dict[str, NDArray[np.floating]]) -> XYVectorData:
        """Create XYVectorData from a dictionary."""
        return cls(data["x"], data["y"], data["vx"], data["vy"])

    def to_dict(self) -> dict[str, NDArray[np.floating]]:
        """Data as a dictionary."""
        return {"x": self.x, "y": self.y, "vx": self.vx, "vy": self.vy}
from_dict(data) classmethod

Create XYVectorData from a dictionary.

Source code in whitecanvas\types\_tuples.py
108
109
110
111
@classmethod
def from_dict(cls, data: dict[str, NDArray[np.floating]]) -> XYVectorData:
    """Create XYVectorData from a dictionary."""
    return cls(data["x"], data["y"], data["vx"], data["vy"])
to_dict()

Data as a dictionary.

Source code in whitecanvas\types\_tuples.py
113
114
115
def to_dict(self) -> dict[str, NDArray[np.floating]]:
    """Data as a dictionary."""
    return {"x": self.x, "y": self.y, "vx": self.vx, "vy": self.vy}

XYYData

Tuple of x, y0, and y1 array.

Used for data of Bars, Errorbars etc.

Source code in whitecanvas\types\_tuples.py
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
class XYYData(NamedTuple):
    """
    Tuple of x, y0, and y1 array.

    Used for data of Bars, Errorbars etc.
    """

    x: NDArray[np.floating]
    y0: NDArray[np.floating]
    y1: NDArray[np.floating]

    @property
    def ycenter(self) -> NDArray[np.floating]:
        return (self.y0 + self.y1) / 2

    @property
    def ydiff(self) -> NDArray[np.floating]:
        return self.y1 - self.y0

    @classmethod
    def from_dict(cls, data: dict[str, NDArray[np.floating]]) -> XYYData:
        """Create XYYData from a dictionary."""
        return cls(data["x"], data["y0"], data["y1"])

    def to_dict(self) -> dict[str, NDArray[np.floating]]:
        """Data as a dictionary."""
        return {"x": self.x, "y0": self.y0, "y1": self.y1}
from_dict(data) classmethod

Create XYYData from a dictionary.

Source code in whitecanvas\types\_tuples.py
52
53
54
55
@classmethod
def from_dict(cls, data: dict[str, NDArray[np.floating]]) -> XYYData:
    """Create XYYData from a dictionary."""
    return cls(data["x"], data["y0"], data["y1"])
to_dict()

Data as a dictionary.

Source code in whitecanvas\types\_tuples.py
57
58
59
def to_dict(self) -> dict[str, NDArray[np.floating]]:
    """Data as a dictionary."""
    return {"x": self.x, "y0": self.y0, "y1": self.y1}

XYZData

Tuple of x, y, and z array.

Used for data of Surface etc.

Source code in whitecanvas\types\_tuples.py
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
class XYZData(NamedTuple):
    """
    Tuple of x, y, and z array.

    Used for data of Surface etc.
    """

    x: NDArray[np.floating]
    y: NDArray[np.floating]
    z: NDArray[np.floating]

    def stack(self) -> NDArray[np.floating]:
        """Data as a stacked (N, 3) array."""
        return np.stack([self.x, self.y, self.z], axis=1)

    @classmethod
    def from_dict(cls, data: dict[str, NDArray[np.floating]]) -> XYZData:
        """Create XYZData from a dictionary."""
        return cls(data["x"], data["y"], data["z"])

    def to_dict(self) -> dict[str, NDArray[np.floating]]:
        """Data as a dictionary."""
        return {"x": self.x, "y": self.y, "z": self.z}
from_dict(data) classmethod

Create XYZData from a dictionary.

Source code in whitecanvas\types\_tuples.py
92
93
94
95
@classmethod
def from_dict(cls, data: dict[str, NDArray[np.floating]]) -> XYZData:
    """Create XYZData from a dictionary."""
    return cls(data["x"], data["y"], data["z"])
stack()

Data as a stacked (N, 3) array.

Source code in whitecanvas\types\_tuples.py
88
89
90
def stack(self) -> NDArray[np.floating]:
    """Data as a stacked (N, 3) array."""
    return np.stack([self.x, self.y, self.z], axis=1)
to_dict()

Data as a dictionary.

Source code in whitecanvas\types\_tuples.py
97
98
99
def to_dict(self) -> dict[str, NDArray[np.floating]]:
    """Data as a dictionary."""
    return {"x": self.x, "y": self.y, "z": self.z}

XYZVectorData

Source code in whitecanvas\types\_tuples.py
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
class XYZVectorData(NamedTuple):
    x: NDArray[np.floating]
    y: NDArray[np.floating]
    z: NDArray[np.floating]
    vx: NDArray[np.floating]
    vy: NDArray[np.floating]
    vz: NDArray[np.floating]

    @classmethod
    def from_dict(cls, data: dict[str, NDArray[np.floating]]) -> XYZVectorData:
        """Create XYZVectorData from a dictionary."""
        return cls(data["x"], data["y"], data["z"], data["vx"], data["vy"], data["vz"])

    def to_dict(self) -> dict[str, NDArray[np.floating]]:
        """Data as a dictionary."""
        return {
            "x": self.x, "y": self.y, "z": self.z,
            "vx": self.vx, "vy": self.vy, "vz": self.vz
        }  # fmt: skip
from_dict(data) classmethod

Create XYZVectorData from a dictionary.

Source code in whitecanvas\types\_tuples.py
126
127
128
129
@classmethod
def from_dict(cls, data: dict[str, NDArray[np.floating]]) -> XYZVectorData:
    """Create XYZVectorData from a dictionary."""
    return cls(data["x"], data["y"], data["z"], data["vx"], data["vy"], data["vz"])
to_dict()

Data as a dictionary.

Source code in whitecanvas\types\_tuples.py
131
132
133
134
135
136
def to_dict(self) -> dict[str, NDArray[np.floating]]:
    """Data as a dictionary."""
    return {
        "x": self.x, "y": self.y, "z": self.z,
        "vx": self.vx, "vy": self.vy, "vz": self.vz
    }  # fmt: skip