syd 0.1.3__py3-none-any.whl → 0.1.5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- syd/__init__.py +15 -1
- syd/interactive_viewer.py +1139 -81
- syd/notebook_deploy/__init__.py +1 -0
- syd/notebook_deploy/deployer.py +237 -0
- syd/notebook_deploy/widgets.py +471 -0
- syd/parameters.py +1135 -154
- {syd-0.1.3.dist-info → syd-0.1.5.dist-info}/METADATA +10 -2
- syd-0.1.5.dist-info/RECORD +10 -0
- syd/notebook_deploy.py +0 -277
- syd-0.1.3.dist-info/RECORD +0 -8
- {syd-0.1.3.dist-info → syd-0.1.5.dist-info}/WHEEL +0 -0
- {syd-0.1.3.dist-info → syd-0.1.5.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: syd
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.5
|
|
4
4
|
Summary: A Python package for making GUIs for data science easy.
|
|
5
5
|
Project-URL: Homepage, https://github.com/landoskape/syd
|
|
6
6
|
Author-email: Andrew Landau <andrew+tyler+landau+getridofthisanddtheplusses@gmail.com>
|
|
@@ -18,13 +18,21 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
18
18
|
Classifier: Programming Language :: Python :: 3.12
|
|
19
19
|
Classifier: Programming Language :: Python :: 3.13
|
|
20
20
|
Requires-Python: >=3.9
|
|
21
|
+
Requires-Dist: ipywidgets
|
|
22
|
+
Requires-Dist: matplotlib
|
|
21
23
|
Provides-Extra: test
|
|
22
24
|
Requires-Dist: pytest-cov>=4.0.0; extra == 'test'
|
|
23
25
|
Requires-Dist: pytest>=7.0.0; extra == 'test'
|
|
24
26
|
Description-Content-Type: text/markdown
|
|
25
27
|
|
|
26
28
|
# syd
|
|
27
|
-
|
|
29
|
+
|
|
30
|
+
[](https://badge.fury.io/py/syd)
|
|
31
|
+
[](https://github.com/landoskape/syd/actions/workflows/tests.yml)
|
|
32
|
+
[](https://shareyourdata.readthedocs.io/en/latest/?badge=latest)
|
|
33
|
+
[](https://codecov.io/gh/landoskape/syd)
|
|
34
|
+
|
|
35
|
+
A package to help you share your data!
|
|
28
36
|
|
|
29
37
|
Have you ever wanted to look through all your data really quickly interactively? Of course you have. Mo data mo problems, but only if you don't know what to do with it. And that starts with looking at your data. And that's why syd stands for show your data!
|
|
30
38
|
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
syd/__init__.py,sha256=XbdbJARNH99CINN6KzlegiXb4i3su1Gg542Jyq9Ve28,298
|
|
2
|
+
syd/interactive_viewer.py,sha256=QrDAL5n9rk8j1nlKEpyCdiFLqVrTndnL-Fa1Csido-U,46560
|
|
3
|
+
syd/parameters.py,sha256=AO8hyT4KYNvNWh9KyrAARSF5zUSfoj7wZEPgNO5U7oA,39649
|
|
4
|
+
syd/notebook_deploy/__init__.py,sha256=eRum4_pXLTtaoUWvVnVCxJFrLM8Nn8EQ0yLwE9puh-w,41
|
|
5
|
+
syd/notebook_deploy/deployer.py,sha256=66kXYtxej32I5TTaFk0KxKeAc9z0RepIZNoYzCkz7Gg,8051
|
|
6
|
+
syd/notebook_deploy/widgets.py,sha256=_KrPfJR6qW3bvb0BOKYE8t7-uVbD4NPv9gStI59aAF0,17442
|
|
7
|
+
syd-0.1.5.dist-info/METADATA,sha256=XOWtqAVesbPPFCzGnZT3X4qQNOKIVgIXCw5FPv9kTnE,3006
|
|
8
|
+
syd-0.1.5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
9
|
+
syd-0.1.5.dist-info/licenses/LICENSE,sha256=YF6QR6Vjxcg5b_sYIyqkME7FZYau5TfEUGTG-0JeRK0,35129
|
|
10
|
+
syd-0.1.5.dist-info/RECORD,,
|
syd/notebook_deploy.py
DELETED
|
@@ -1,277 +0,0 @@
|
|
|
1
|
-
from typing import Dict, Any, Tuple
|
|
2
|
-
import matplotlib.pyplot as plt
|
|
3
|
-
import ipywidgets as widgets
|
|
4
|
-
from IPython.display import display
|
|
5
|
-
from .parameters import (
|
|
6
|
-
Parameter,
|
|
7
|
-
TextParameter,
|
|
8
|
-
SingleSelectionParameter,
|
|
9
|
-
MultipleSelectionParameter,
|
|
10
|
-
BooleanParameter,
|
|
11
|
-
IntegerParameter,
|
|
12
|
-
FloatParameter,
|
|
13
|
-
IntegerPairParameter,
|
|
14
|
-
FloatPairParameter,
|
|
15
|
-
)
|
|
16
|
-
from .interactive_viewer import InteractiveViewer
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
class NotebookDeployment:
|
|
20
|
-
"""
|
|
21
|
-
Deployment system for InteractiveViewer in Jupyter notebooks using ipywidgets.
|
|
22
|
-
Includes enhanced layout control and figure size management.
|
|
23
|
-
"""
|
|
24
|
-
|
|
25
|
-
def __init__(self, viewer: InteractiveViewer, figsize: Tuple[float, float] = (8, 6), controls_width: float = 30, continuous=False):
|
|
26
|
-
"""Initialize with an InteractiveViewer instance."""
|
|
27
|
-
self.viewer = viewer
|
|
28
|
-
self.widgets: Dict[str, widgets.Widget] = {}
|
|
29
|
-
self._widget_callbacks = {}
|
|
30
|
-
self._current_figure = None
|
|
31
|
-
|
|
32
|
-
# Default figure size
|
|
33
|
-
self.fig_width = figsize[0]
|
|
34
|
-
self.fig_height = figsize[1]
|
|
35
|
-
self.controls_width = controls_width
|
|
36
|
-
self.continuous = continuous
|
|
37
|
-
|
|
38
|
-
def _create_text_widget(self, param: TextParameter) -> widgets.Text:
|
|
39
|
-
"""Create a text input widget."""
|
|
40
|
-
w = widgets.Text(value=param.default, description=param.name, layout=widgets.Layout(width="95%"), style={"description_width": "initial"})
|
|
41
|
-
return w
|
|
42
|
-
|
|
43
|
-
def _create_selection_widget(self, param: SingleSelectionParameter) -> widgets.Dropdown:
|
|
44
|
-
"""Create a dropdown selection widget."""
|
|
45
|
-
w = widgets.Dropdown(
|
|
46
|
-
options=param.options,
|
|
47
|
-
value=param.default if param.default else param.options[0],
|
|
48
|
-
description=param.name,
|
|
49
|
-
layout=widgets.Layout(width="95%"),
|
|
50
|
-
style={"description_width": "initial"},
|
|
51
|
-
)
|
|
52
|
-
return w
|
|
53
|
-
|
|
54
|
-
def _create_multiple_selection_widget(self, param: MultipleSelectionParameter) -> widgets.SelectMultiple:
|
|
55
|
-
"""Create a multiple selection widget."""
|
|
56
|
-
w = widgets.SelectMultiple(
|
|
57
|
-
options=param.options,
|
|
58
|
-
value=param.default if param.default else [],
|
|
59
|
-
description=param.name,
|
|
60
|
-
layout=widgets.Layout(width="95%"),
|
|
61
|
-
style={"description_width": "initial"},
|
|
62
|
-
)
|
|
63
|
-
return w
|
|
64
|
-
|
|
65
|
-
def _create_boolean_widget(self, param: BooleanParameter) -> widgets.Checkbox:
|
|
66
|
-
"""Create a checkbox widget."""
|
|
67
|
-
w = widgets.Checkbox(value=param.default, description=param.name, layout=widgets.Layout(width="95%"), style={"description_width": "initial"})
|
|
68
|
-
return w
|
|
69
|
-
|
|
70
|
-
def _create_integer_widget(self, param: IntegerParameter) -> widgets.IntSlider:
|
|
71
|
-
"""Create an integer slider widget."""
|
|
72
|
-
w = widgets.IntSlider(
|
|
73
|
-
value=param.default if param.default is not None else param.min_value,
|
|
74
|
-
min=param.min_value,
|
|
75
|
-
max=param.max_value,
|
|
76
|
-
description=param.name,
|
|
77
|
-
continuous_update=self.continuous,
|
|
78
|
-
layout=widgets.Layout(width="95%"),
|
|
79
|
-
style={"description_width": "initial"},
|
|
80
|
-
)
|
|
81
|
-
return w
|
|
82
|
-
|
|
83
|
-
def _create_float_widget(self, param: FloatParameter) -> widgets.FloatSlider:
|
|
84
|
-
"""Create a float slider widget."""
|
|
85
|
-
w = widgets.FloatSlider(
|
|
86
|
-
value=param.default if param.default is not None else param.min_value,
|
|
87
|
-
min=param.min_value,
|
|
88
|
-
max=param.max_value,
|
|
89
|
-
step=param.step,
|
|
90
|
-
description=param.name,
|
|
91
|
-
continuous_update=self.continuous,
|
|
92
|
-
layout=widgets.Layout(width="95%"),
|
|
93
|
-
style={"description_width": "initial"},
|
|
94
|
-
)
|
|
95
|
-
return w
|
|
96
|
-
|
|
97
|
-
def _create_integer_pair_widget(self, param: IntegerPairParameter) -> widgets.HBox:
|
|
98
|
-
"""Create a pair of integer input widgets."""
|
|
99
|
-
low = widgets.IntText(
|
|
100
|
-
value=param.default_low if param.default_low is not None else param.min_value,
|
|
101
|
-
description=f"{param.name} (low)",
|
|
102
|
-
layout=widgets.Layout(width="47%"),
|
|
103
|
-
style={"description_width": "initial"},
|
|
104
|
-
)
|
|
105
|
-
high = widgets.IntText(
|
|
106
|
-
value=param.default_high if param.default_high is not None else param.max_value,
|
|
107
|
-
description=f"{param.name} (high)",
|
|
108
|
-
layout=widgets.Layout(width="47%"),
|
|
109
|
-
style={"description_width": "initial"},
|
|
110
|
-
)
|
|
111
|
-
return widgets.HBox([low, high], layout=widgets.Layout(width="95%"))
|
|
112
|
-
|
|
113
|
-
def _create_float_pair_widget(self, param: FloatPairParameter) -> widgets.HBox:
|
|
114
|
-
"""Create a pair of float input widgets."""
|
|
115
|
-
low = widgets.FloatText(
|
|
116
|
-
value=param.default_low if param.default_low is not None else param.min_value,
|
|
117
|
-
description=f"{param.name} (low)",
|
|
118
|
-
layout=widgets.Layout(width="47%"),
|
|
119
|
-
style={"description_width": "initial"},
|
|
120
|
-
)
|
|
121
|
-
high = widgets.FloatText(
|
|
122
|
-
value=param.default_high if param.default_high is not None else param.max_value,
|
|
123
|
-
description=f"{param.name} (high)",
|
|
124
|
-
layout=widgets.Layout(width="47%"),
|
|
125
|
-
style={"description_width": "initial"},
|
|
126
|
-
)
|
|
127
|
-
return widgets.HBox([low, high], layout=widgets.Layout(width="95%"))
|
|
128
|
-
|
|
129
|
-
def _create_widget_for_parameter(self, param: Parameter) -> widgets.Widget:
|
|
130
|
-
"""Create the appropriate widget based on parameter type."""
|
|
131
|
-
widget_creators = {
|
|
132
|
-
TextParameter: self._create_text_widget,
|
|
133
|
-
SingleSelectionParameter: self._create_selection_widget,
|
|
134
|
-
MultipleSelectionParameter: self._create_multiple_selection_widget,
|
|
135
|
-
BooleanParameter: self._create_boolean_widget,
|
|
136
|
-
IntegerParameter: self._create_integer_widget,
|
|
137
|
-
FloatParameter: self._create_float_widget,
|
|
138
|
-
IntegerPairParameter: self._create_integer_pair_widget,
|
|
139
|
-
FloatPairParameter: self._create_float_pair_widget,
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
creator = widget_creators.get(type(param))
|
|
143
|
-
if not creator:
|
|
144
|
-
raise ValueError(f"Unsupported parameter type: {type(param)}")
|
|
145
|
-
|
|
146
|
-
return creator(param)
|
|
147
|
-
|
|
148
|
-
def _create_size_controls(self) -> widgets.VBox:
|
|
149
|
-
"""Create controls for adjusting the figure size."""
|
|
150
|
-
self.width_slider = widgets.FloatSlider(
|
|
151
|
-
value=self.fig_width,
|
|
152
|
-
min=4,
|
|
153
|
-
max=20,
|
|
154
|
-
step=0.5,
|
|
155
|
-
description="Figure Width",
|
|
156
|
-
continuous_update=True,
|
|
157
|
-
layout=widgets.Layout(width="95%"),
|
|
158
|
-
style={"description_width": "initial"},
|
|
159
|
-
)
|
|
160
|
-
|
|
161
|
-
self.height_slider = widgets.FloatSlider(
|
|
162
|
-
value=self.fig_height,
|
|
163
|
-
min=3,
|
|
164
|
-
max=15,
|
|
165
|
-
step=0.5,
|
|
166
|
-
description="Figure Height",
|
|
167
|
-
continuous_update=True,
|
|
168
|
-
layout=widgets.Layout(width="95%"),
|
|
169
|
-
style={"description_width": "initial"},
|
|
170
|
-
)
|
|
171
|
-
|
|
172
|
-
self.container_width = widgets.IntSlider(
|
|
173
|
-
value=30,
|
|
174
|
-
min=20,
|
|
175
|
-
max=80,
|
|
176
|
-
description="Controls Width %",
|
|
177
|
-
continuous_update=True,
|
|
178
|
-
layout=widgets.Layout(width="95%"),
|
|
179
|
-
style={"description_width": "initial"},
|
|
180
|
-
)
|
|
181
|
-
|
|
182
|
-
# Add callbacks for size changes
|
|
183
|
-
self.width_slider.observe(self._handle_size_change, names="value")
|
|
184
|
-
self.height_slider.observe(self._handle_size_change, names="value")
|
|
185
|
-
self.container_width.observe(self._handle_container_width_change, names="value")
|
|
186
|
-
|
|
187
|
-
return widgets.VBox(
|
|
188
|
-
[widgets.HTML("<b>Layout Controls</b>"), self.width_slider, self.height_slider, self.container_width],
|
|
189
|
-
layout=widgets.Layout(margin="10px 0px"),
|
|
190
|
-
)
|
|
191
|
-
|
|
192
|
-
def _handle_size_change(self, change: Dict[str, Any]) -> None:
|
|
193
|
-
"""Handle changes to figure size."""
|
|
194
|
-
self.fig_width = self.width_slider.value
|
|
195
|
-
self.fig_height = self.height_slider.value
|
|
196
|
-
self._update_plot()
|
|
197
|
-
|
|
198
|
-
def _handle_container_width_change(self, change: Dict[str, Any]) -> None:
|
|
199
|
-
"""Handle changes to container widths."""
|
|
200
|
-
controls_width = f"{self.container_width.value}%"
|
|
201
|
-
plot_width = f"{100 - self.container_width.value}%"
|
|
202
|
-
|
|
203
|
-
self.widgets_container.layout.width = controls_width
|
|
204
|
-
self.plot_container.layout.width = plot_width
|
|
205
|
-
|
|
206
|
-
def _handle_widget_change(self, name: str, change: Dict[str, Any]) -> None:
|
|
207
|
-
"""Handle widget value changes and update the viewer parameter."""
|
|
208
|
-
if isinstance(self.widgets[name], widgets.HBox):
|
|
209
|
-
# Handle pair widgets
|
|
210
|
-
low_value = self.widgets[name].children[0].value
|
|
211
|
-
high_value = self.widgets[name].children[1].value
|
|
212
|
-
value = (low_value, high_value)
|
|
213
|
-
else:
|
|
214
|
-
value = change["new"]
|
|
215
|
-
|
|
216
|
-
self.viewer.set_parameter_value(name, value)
|
|
217
|
-
self._update_plot()
|
|
218
|
-
|
|
219
|
-
def _update_plot(self) -> None:
|
|
220
|
-
"""Update the plot with current parameters and size."""
|
|
221
|
-
self._current_fig.clear()
|
|
222
|
-
self._current_fig.set_size_inches(self.fig_width, self.fig_height)
|
|
223
|
-
self._current_fig = self.viewer.plot(fig=self._current_fig, state=self.viewer.get_state())
|
|
224
|
-
|
|
225
|
-
# Apply tight layout to remove dead space
|
|
226
|
-
self._current_fig.tight_layout()
|
|
227
|
-
|
|
228
|
-
self.plot_output.clear_output(wait=True)
|
|
229
|
-
with self.plot_output:
|
|
230
|
-
display(self._current_fig)
|
|
231
|
-
|
|
232
|
-
def create_widgets(self) -> None:
|
|
233
|
-
"""Create widgets for all parameters in the viewer."""
|
|
234
|
-
for name, param in self.viewer.parameters.items():
|
|
235
|
-
widget = self._create_widget_for_parameter(param)
|
|
236
|
-
self.widgets[name] = widget
|
|
237
|
-
|
|
238
|
-
# Set up callback
|
|
239
|
-
if isinstance(widget, widgets.HBox):
|
|
240
|
-
# For pair widgets, observe both components
|
|
241
|
-
widget.children[0].observe(lambda change, n=name: self._handle_widget_change(n, change), names="value")
|
|
242
|
-
widget.children[1].observe(lambda change, n=name: self._handle_widget_change(n, change), names="value")
|
|
243
|
-
else:
|
|
244
|
-
widget.observe(lambda change, n=name: self._handle_widget_change(n, change), names="value")
|
|
245
|
-
|
|
246
|
-
def display_widgets(self) -> None:
|
|
247
|
-
"""Display all widgets and plot in an organized layout."""
|
|
248
|
-
# Create size controls
|
|
249
|
-
size_controls = self._create_size_controls()
|
|
250
|
-
|
|
251
|
-
# Create widgets container with parameters and size controls
|
|
252
|
-
all_widgets = list(self.widgets.values()) + [size_controls]
|
|
253
|
-
self.widgets_container = widgets.VBox(all_widgets, layout=widgets.Layout(width="30%", padding="10px", overflow_y="auto"))
|
|
254
|
-
|
|
255
|
-
# Create output widget for plot
|
|
256
|
-
self.plot_output = widgets.Output()
|
|
257
|
-
self.plot_container = widgets.VBox([self.plot_output], layout=widgets.Layout(width="70%", padding="10px"))
|
|
258
|
-
|
|
259
|
-
# Combine widgets and plot in layout
|
|
260
|
-
# Make the container height dynamic
|
|
261
|
-
layout = widgets.HBox(
|
|
262
|
-
[self.widgets_container, self.plot_container], layout=widgets.Layout(width="100%", height="auto") # Dynamic height based on content
|
|
263
|
-
)
|
|
264
|
-
display(layout)
|
|
265
|
-
|
|
266
|
-
# Create initial plot
|
|
267
|
-
self._current_fig = plt.figure(figsize=(self.fig_width, self.fig_height))
|
|
268
|
-
plt.close(self._current_fig) # close the figure to prevent it from being displayed
|
|
269
|
-
self._current_fig = self.viewer.plot(fig=self._current_fig, state=self.viewer.get_state())
|
|
270
|
-
with self.plot_output:
|
|
271
|
-
display(self._current_fig)
|
|
272
|
-
|
|
273
|
-
def deploy(self) -> None:
|
|
274
|
-
"""Create and display all widgets with proper deployment state management."""
|
|
275
|
-
with self.viewer.deploy_app():
|
|
276
|
-
self.create_widgets()
|
|
277
|
-
self.display_widgets()
|
syd-0.1.3.dist-info/RECORD
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
syd/__init__.py,sha256=XEqb2aiIn8fzGE68Mph4ck1FtQqsR_am0wRWvrYPffQ,22
|
|
2
|
-
syd/interactive_viewer.py,sha256=33aFY6Q4vg6fP5QVs2RYqfnqmFJzML-Lcnhbb1XwN2g,9353
|
|
3
|
-
syd/notebook_deploy.py,sha256=GAvrWEnvy__N2_0qQTmfoX6UZZKikKCjWn0tGpTUXK8,11696
|
|
4
|
-
syd/parameters.py,sha256=oQSAGM2D2Db4YLzj_nQb6_vPp18ltld7qvFC138lRJw,9885
|
|
5
|
-
syd-0.1.3.dist-info/METADATA,sha256=r6JMz__aTLlirGUqUkki6emZwx9Ywq1HFKhlH2p2mdk,2449
|
|
6
|
-
syd-0.1.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
7
|
-
syd-0.1.3.dist-info/licenses/LICENSE,sha256=YF6QR6Vjxcg5b_sYIyqkME7FZYau5TfEUGTG-0JeRK0,35129
|
|
8
|
-
syd-0.1.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|