nova-trame 0.13.1__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,85 @@
1
+ """View implementation for Interactive2DPlot."""
2
+
3
+ from typing import Any, Optional
4
+
5
+ from altair import Chart
6
+ from trame.widgets import client, vega
7
+
8
+
9
+ class Interactive2DPlot(vega.Figure):
10
+ """Creates an interactive 2D plot in Trame using Vega.
11
+
12
+ Trame provides two primary mechanisms for composing 2D plots: `Plotly <https://github.com/Kitware/trame-plotly>`_
13
+ and `Vega-Lite/Altair <https://github.com/Kitware/trame-vega>`_. If you only need static plots or basic browser
14
+ event handling, then please use these libraries directly.
15
+
16
+ If you need to capture complex front-end interactions, then you can
17
+ use our provided Interactive2DPlot widget that is based on Vega-Lite. This uses the same API as Trame's vega.Figure,
18
+ except that it will automatically sync Vega's signal states as the user interacts with the plot.
19
+
20
+ The following allows the user to select a region of the plot and tracks the selected region in Python:
21
+
22
+ .. literalinclude:: ../tests/test_interactive_2d_plot.py
23
+ :start-after: setup 2d plot
24
+ :end-before: setup 2d plot complete
25
+ :dedent:
26
+ """
27
+
28
+ def __init__(self, figure: Optional[Chart] = None, **kwargs: Any) -> None:
29
+ """Constructor for Interactive2DPlot.
30
+
31
+ Parameters
32
+ ----------
33
+ figure : `altair.Chart <https://altair-viz.github.io/user_guide/generated/toplevel/altair.Chart.html#altair.Chart>`_
34
+ Altair chart object
35
+ kwargs
36
+ Arguments to be passed to `AbstractElement <https://trame.readthedocs.io/en/latest/core.widget.html#trame_client.widgets.core.AbstractElement>`_
37
+
38
+ Returns
39
+ -------
40
+ None
41
+ """
42
+ self._initialized = False
43
+
44
+ super().__init__(figure=figure, **kwargs)
45
+ self.ref = f"nova__vega_{self._id}"
46
+ self.server.state[self.ref] = {}
47
+ self._start_update_handlers = client.JSEval(
48
+ exec=(
49
+ "async () => {"
50
+ f" let ref = window.trame.refs['{self.ref}'];"
51
+ " await ref.mountVis();" # wait for the new visualization to be rendered in the front-end
52
+ " if (ref.viz === undefined) { return; }" # If the component is not mounted, do nothing
53
+ " for (const [key, value] of Object.entries(ref.viz.view._signals)) {"
54
+ " if (key === 'unit') { continue; }" # this causes a JSError for some reason if not skipped
55
+ " ref.viz.view.addSignalListener(key, (name, value) => {"
56
+ f" window.trame.state.state['{self.ref}'][name] = value;" # sync front-end state
57
+ f" flushState('{self.ref}');" # sync back-end state
58
+ " })"
59
+ " }"
60
+ "}"
61
+ )
62
+ ).exec
63
+
64
+ client.ClientTriggers(mounted=self.update)
65
+
66
+ def get_signal_state(self, name: str) -> Any:
67
+ """Retrieves a Vega signal's state by name.
68
+
69
+ Parameters
70
+ ----------
71
+ name : str
72
+ The name of the signal to retrieve.
73
+
74
+ Returns
75
+ -------
76
+ typing.Any
77
+ The current value of the Vega signal.
78
+ """
79
+ return self.server.state[self.ref].get(name, None)
80
+
81
+ def update(self, figure: Optional[Chart] = None, **kwargs: Any) -> None:
82
+ super().update(figure=figure, **kwargs)
83
+
84
+ if hasattr(self, "_start_update_handlers"):
85
+ self._start_update_handlers()
@@ -0,0 +1,5 @@
1
+ from .grid import GridLayout
2
+ from .hbox import HBoxLayout
3
+ from .vbox import VBoxLayout
4
+
5
+ __all__ = ["GridLayout", "HBoxLayout", "VBoxLayout"]
@@ -0,0 +1,148 @@
1
+ """Trame implementation of the GridLayout class."""
2
+
3
+ from typing import Any, Optional, Union
4
+
5
+ from trame.widgets import html
6
+ from trame_client.widgets.core import AbstractElement
7
+
8
+
9
+ class GridLayout(html.Div):
10
+ """Creates a grid with a specified number of columns."""
11
+
12
+ def __init__(
13
+ self,
14
+ columns: int = 1,
15
+ height: Optional[Union[int, str]] = None,
16
+ width: Optional[Union[int, str]] = None,
17
+ halign: Optional[str] = None,
18
+ valign: Optional[str] = None,
19
+ **kwargs: Any,
20
+ ) -> None:
21
+ """Constructor for GridLayout.
22
+
23
+ Parameters
24
+ ----------
25
+ columns : int
26
+ The number of columns in the grid.
27
+ height : optional[int | str]
28
+ The height of this grid. If an integer is provided, it is interpreted as pixels. If a string is provided,
29
+ the string is treated as a CSS value.
30
+ width : optional[int | str]
31
+ The width of this grid. If an integer is provided, it is interpreted as pixels. If a string is provided,
32
+ the string is treated as a CSS value.
33
+ halign : optional[str]
34
+ The horizontal alignment of items in the grid. See `MDN
35
+ <https://developer.mozilla.org/en-US/docs/Web/CSS/justify-items>`__ for available options.
36
+ valign : optional[str]
37
+ The vertical alignment of items in the grid. See `MDN
38
+ <https://developer.mozilla.org/en-US/docs/Web/CSS/align-items>`__ for available options.
39
+ kwargs : Any
40
+ Additional keyword arguments to pass to html.Div.
41
+
42
+ Returns
43
+ -------
44
+ None
45
+
46
+ Examples
47
+ --------
48
+ Basic usage:
49
+
50
+ .. literalinclude:: ../tests/gallery/app.py
51
+ :start-after: setup grid
52
+ :end-before: setup grid complete
53
+ :dedent:
54
+
55
+ Building a custom left-middle-right layout:
56
+
57
+ .. literalinclude:: ../tests/test_layouts.py
58
+ :start-after: setup complex layout example
59
+ :end-before: setup complex layout example complete
60
+ :dedent:
61
+ """
62
+ classes = kwargs.pop("classes", [])
63
+ if isinstance(classes, list):
64
+ classes = " ".join(classes)
65
+ classes += " d-grid"
66
+
67
+ style = self.get_root_styles(columns, height, width, halign, valign) | kwargs.pop("style", {})
68
+
69
+ super().__init__(classes=classes, style=style, **kwargs)
70
+
71
+ def get_root_styles(
72
+ self,
73
+ columns: int,
74
+ height: Optional[Union[int, str]],
75
+ width: Optional[Union[int, str]],
76
+ halign: Optional[str],
77
+ valign: Optional[str],
78
+ ) -> dict[str, str]:
79
+ height = f"{height}px" if isinstance(height, int) else height
80
+ width = f"{width}px" if isinstance(width, int) else width
81
+
82
+ styles = {
83
+ "grid-template-columns": f"repeat({columns}, 1fr)",
84
+ }
85
+
86
+ if height:
87
+ styles["height"] = height
88
+ if width:
89
+ styles["width"] = width
90
+ if halign:
91
+ styles["justify-items"] = halign
92
+ if valign:
93
+ styles["align-items"] = valign
94
+
95
+ return styles
96
+
97
+ def get_row_style(self, row_span: int) -> str:
98
+ return f"grid-row-end: span {row_span};"
99
+
100
+ def get_column_style(self, column_span: int) -> str:
101
+ return f"grid-column-end: span {column_span};"
102
+
103
+ def add_child(self, child: Union[AbstractElement, str]) -> AbstractElement:
104
+ """Add a child to the grid.
105
+
106
+ Do not call this directly. Instead, use Trame's `with` syntax, which will call this method internally. This
107
+ method is documented here as a reference for the span parameters.
108
+
109
+ Parameters
110
+ ----------
111
+ child : `AbstractElement \
112
+ <https://trame.readthedocs.io/en/latest/core.widget.html#trame_client.widgets.core.AbstractElement>`_ | str
113
+ The child to add to the grid.
114
+ row_span : int
115
+ The number of rows this child should span.
116
+ column_span : int
117
+ The number of columns this child should span.
118
+
119
+ Returns
120
+ -------
121
+ None
122
+
123
+ Example
124
+ -------
125
+ .. literalinclude:: ../tests/gallery/app.py
126
+ :start-after: grid row and column span example
127
+ :end-before: grid row and column span example end
128
+ :dedent:
129
+ """
130
+ if isinstance(child, str):
131
+ child = html.Div(child)
132
+
133
+ row_span = 1
134
+ column_span = 1
135
+ if "row_span" in child._py_attr:
136
+ row_span = child._py_attr["row_span"]
137
+ if "column_span" in child._py_attr:
138
+ column_span = child._py_attr["column_span"]
139
+
140
+ if "style" not in child._py_attr or child.style is None:
141
+ child.style = ""
142
+ child.style += f"; {self.get_row_style(row_span)} {self.get_column_style(column_span)}"
143
+
144
+ if "classes" not in child._py_attr or child.classes is None:
145
+ child.classes = ""
146
+ child.classes += " d-grid-item"
147
+
148
+ super().add_child(child)
@@ -0,0 +1,79 @@
1
+ """Trame implementation of the HBoxLayout class."""
2
+
3
+ from typing import Any, Optional, Union
4
+
5
+ from trame.widgets import html
6
+
7
+
8
+ class HBoxLayout(html.Div):
9
+ """Creates an element that horizontally stacks its children."""
10
+
11
+ def __init__(
12
+ self,
13
+ height: Optional[Union[int, str]] = None,
14
+ width: Optional[Union[int, str]] = None,
15
+ halign: Optional[str] = None,
16
+ valign: Optional[str] = None,
17
+ **kwargs: Any,
18
+ ) -> None:
19
+ """Constructor for HBoxLayout.
20
+
21
+ Parameters
22
+ ----------
23
+ height : optional[int | str]
24
+ The height of this box. If an integer is provided, it is interpreted as pixels. If a string is provided,
25
+ the string is treated as a CSS value.
26
+ width : optional[int | str]
27
+ The width of this box. If an integer is provided, it is interpreted as pixels. If a string is provided,
28
+ the string is treated as a CSS value.
29
+ halign : optional[str]
30
+ The horizontal alignment of items in the grid. See `MDN
31
+ <https://developer.mozilla.org/en-US/docs/Web/CSS/justify-items>`__ for available options.
32
+ valign : optional[str]
33
+ The vertical alignment of items in the grid. See `MDN
34
+ <https://developer.mozilla.org/en-US/docs/Web/CSS/align-items>`__ for available options.
35
+ kwargs : Any
36
+ Additional keyword arguments to pass to html.Div.
37
+
38
+ Returns
39
+ -------
40
+ None
41
+
42
+ Example
43
+ -------
44
+ .. literalinclude:: ../tests/gallery/app.py
45
+ :start-after: setup hbox
46
+ :end-before: setup hbox complete
47
+ :dedent:
48
+ """
49
+ classes = kwargs.pop("classes", [])
50
+ if isinstance(classes, list):
51
+ classes = " ".join(classes)
52
+ classes += " d-flex flex-row"
53
+
54
+ style = self.get_root_styles(height, width, halign, valign) | kwargs.pop("style", {})
55
+
56
+ super().__init__(classes=classes, style=style, **kwargs)
57
+
58
+ def get_root_styles(
59
+ self,
60
+ height: Optional[Union[int, str]],
61
+ width: Optional[Union[int, str]],
62
+ halign: Optional[str],
63
+ valign: Optional[str],
64
+ ) -> dict:
65
+ height = f"{height}px" if isinstance(height, int) else height
66
+ width = f"{width}px" if isinstance(width, int) else width
67
+
68
+ styles = {}
69
+
70
+ if height:
71
+ styles["height"] = height
72
+ if width:
73
+ styles["width"] = width
74
+ if halign:
75
+ styles["justify-content"] = halign
76
+ if valign:
77
+ styles["align-items"] = valign
78
+
79
+ return styles
@@ -0,0 +1,79 @@
1
+ """Trame implementation of the VBoxLayout class."""
2
+
3
+ from typing import Any, Optional, Union
4
+
5
+ from trame.widgets import html
6
+
7
+
8
+ class VBoxLayout(html.Div):
9
+ """Creates an element that vertically stacks its children."""
10
+
11
+ def __init__(
12
+ self,
13
+ height: Optional[Union[int, str]] = None,
14
+ width: Optional[Union[int, str]] = None,
15
+ halign: Optional[str] = None,
16
+ valign: Optional[str] = None,
17
+ **kwargs: Any,
18
+ ) -> None:
19
+ """Constructor for VBoxLayout.
20
+
21
+ Parameters
22
+ ----------
23
+ height : optional[int | str]
24
+ The height of this box. If an integer is provided, it is interpreted as pixels. If a string is provided,
25
+ the string is treated as a CSS value.
26
+ width : optional[int | str]
27
+ The width of this box. If an integer is provided, it is interpreted as pixels. If a string is provided,
28
+ the string is treated as a CSS value.
29
+ halign : optional[str]
30
+ The horizontal alignment of items in the grid. See `MDN
31
+ <https://developer.mozilla.org/en-US/docs/Web/CSS/align-items>`__ for available options.
32
+ valign : optional[str]
33
+ The vertical alignment of items in the grid. See `MDN
34
+ <https://developer.mozilla.org/en-US/docs/Web/CSS/justify-items>`__ for available options.
35
+ kwargs : Any
36
+ Additional keyword arguments to pass to html.Div.
37
+
38
+ Returns
39
+ -------
40
+ None
41
+
42
+ Example
43
+ -------
44
+ .. literalinclude:: ../tests/gallery/app.py
45
+ :start-after: setup vbox
46
+ :end-before: setup vbox complete
47
+ :dedent:
48
+ """
49
+ classes = kwargs.pop("classes", [])
50
+ if isinstance(classes, list):
51
+ classes = " ".join(classes)
52
+ classes += " d-flex flex-column"
53
+
54
+ style = self.get_root_styles(height, width, halign, valign) | kwargs.pop("style", {})
55
+
56
+ super().__init__(classes=classes, style=style, **kwargs)
57
+
58
+ def get_root_styles(
59
+ self,
60
+ height: Optional[Union[int, str]],
61
+ width: Optional[Union[int, str]],
62
+ halign: Optional[str],
63
+ valign: Optional[str],
64
+ ) -> dict:
65
+ height = f"{height}px" if isinstance(height, int) else height
66
+ width = f"{width}px" if isinstance(width, int) else width
67
+
68
+ styles = {}
69
+
70
+ if height:
71
+ styles["height"] = height
72
+ if width:
73
+ styles["width"] = width
74
+ if halign:
75
+ styles["align-items"] = halign
76
+ if valign:
77
+ styles["justify-content"] = valign
78
+
79
+ return styles
@@ -0,0 +1,3 @@
1
+ from .theme import ThemedApp
2
+
3
+ __all__ = ["ThemedApp"]
@@ -0,0 +1,30 @@
1
+ html {
2
+ overflow-y: auto;
3
+ }
4
+
5
+ .d-grid {
6
+ display: grid;
7
+ gap: 0.25em;
8
+ grid-auto-rows: auto;
9
+ }
10
+
11
+ @media only screen and (max-width: 959px) {
12
+ .d-grid {
13
+ grid-template-columns: repeat(1, 1fr) !important;
14
+ }
15
+
16
+ .d-grid-item {
17
+ grid-column: 1 / 1 !important;
18
+ }
19
+ }
20
+
21
+ /* Global font sizes can't be set through the Vuetify configuration. */
22
+ .v-theme--CompactTheme {
23
+ font-size: 0.85rem;
24
+
25
+ .v-card-title,
26
+ .v-list-item-title,
27
+ .v-toolbar-title {
28
+ font-size: 1rem;
29
+ }
30
+ }
Binary file
@@ -0,0 +1,180 @@
1
+ {
2
+ "defaults": {
3
+ "global": {
4
+ "hideDetails": "auto",
5
+ "hideSpinButtons": true,
6
+ "persistentPlaceholder": true
7
+ },
8
+ "VAlert": {
9
+ "color": "secondary"
10
+ },
11
+ "VAppBar": {
12
+ "color": "primary",
13
+ "VBtn": {
14
+ "color": false
15
+ }
16
+ },
17
+ "VBadge": {
18
+ "color": "secondary"
19
+ },
20
+ "VBtn": {
21
+ "color": "primary"
22
+ },
23
+ "VBtnToggle": {
24
+ "color": "primary",
25
+ "VBtn": {
26
+ "class": "border-primary border-sm"
27
+ }
28
+ },
29
+ "VCard": {
30
+ "VCardSubtitle": {
31
+ "style": {
32
+ "white-space": "normal"
33
+ }
34
+ },
35
+ "VCardTitle": {
36
+ "style": {
37
+ "line-height": 1.2,
38
+ "white-space": "normal"
39
+ }
40
+ }
41
+ },
42
+ "VCardSubtitle": {
43
+ "opacity": 0.8
44
+ },
45
+ "VCheckbox": {
46
+ "color": "primary"
47
+ },
48
+ "VChip": {
49
+ "color": "primary"
50
+ },
51
+ "VDivider": {
52
+ "color": "primary"
53
+ },
54
+ "VExpansionPanels": {
55
+ "color": "primary"
56
+ },
57
+ "VFileInput": {
58
+ "color": "primary",
59
+ "prependIcon": false
60
+ },
61
+ "VLabel": {
62
+ "style": {
63
+ "opacity": 1.0
64
+ }
65
+ },
66
+ "VList": {
67
+ "VListItemAction": {
68
+ "VBtn": {
69
+ "class": "ml-2"
70
+ },
71
+ "VProgressCircular": {
72
+ "class": "ml-2"
73
+ }
74
+ }
75
+ },
76
+ "VListItem": {
77
+ "VBtn": {
78
+ "color": "secondary"
79
+ }
80
+ },
81
+ "VListItemSubtitle": {
82
+ "opacity": 0.8
83
+ },
84
+ "VProgressCircular": {
85
+ "color": "secondary"
86
+ },
87
+ "VProgressLinear": {
88
+ "color": "secondary"
89
+ },
90
+ "VRadioGroup": {
91
+ "color": "primary"
92
+ },
93
+ "VSelect": {
94
+ "color": "primary"
95
+ },
96
+ "VSlider": {
97
+ "color": "primary"
98
+ },
99
+ "VSnackbar": {
100
+ "color": "primary",
101
+ "VBtn": {
102
+ "color": false
103
+ }
104
+ },
105
+ "VSwitch": {
106
+ "color": "primary"
107
+ },
108
+ "VTextarea": {
109
+ "color": "primary"
110
+ },
111
+ "VTextField": {
112
+ "color": "primary"
113
+ },
114
+ "VWindowItem": {
115
+ "reverseTransition": "fade-transition",
116
+ "transition": "fade-transition"
117
+ }
118
+ },
119
+ "theme": {
120
+ "defaultTheme": "ModernTheme",
121
+ "themes": {
122
+ "ModernTheme": {
123
+ "colors": {
124
+ "background": "#f0f0f0",
125
+ "primary": "#007833",
126
+ "secondary": "#f48e5c"
127
+ },
128
+ "defaults": {
129
+ "VCard": {
130
+ "class": "pa-4",
131
+ "VCard": {
132
+ "class": "border-primary border-sm pa-4",
133
+ "style": {
134
+ "background-color": "rgba(var(--v-theme-primary), 0.1)"
135
+ }
136
+ },
137
+ "VListItem": {
138
+ "class": "border-primary border-sm",
139
+ "style": {
140
+ "background-color": "rgba(var(--v-theme-primary), 0.1)"
141
+ }
142
+ }
143
+ }
144
+ },
145
+ "title": "Modern",
146
+ "value": "ModernTheme"
147
+ },
148
+ "CompactTheme": {
149
+ "colors": {
150
+ "background": "#f0f0f0",
151
+ "primary": "#007833",
152
+ "secondary": "#f48e5c"
153
+ },
154
+ "defaults": {
155
+ "global": {
156
+ "density": "compact"
157
+ },
158
+ "VBadge": {
159
+ "dot": true
160
+ },
161
+ "VBtn": {
162
+ "density": "default"
163
+ },
164
+ "VTextField": {
165
+ "VBtn": {
166
+ "size": "small"
167
+ }
168
+ }
169
+ },
170
+ "title": "Compact",
171
+ "value": "CompactTheme"
172
+ }
173
+ },
174
+ "variations": {
175
+ "colors": ["primary", "secondary", "accent"],
176
+ "darken": 5,
177
+ "lighten": 5
178
+ }
179
+ }
180
+ }