syd 0.1.4__py3-none-any.whl → 0.1.6__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.
@@ -0,0 +1,106 @@
1
+ Metadata-Version: 2.4
2
+ Name: syd
3
+ Version: 0.1.6
4
+ Summary: A Python package for making GUIs for data science easy.
5
+ Project-URL: Homepage, https://github.com/landoskape/syd
6
+ Author-email: Andrew Landau <andrew+tyler+landau+getridofthisanddtheplusses@gmail.com>
7
+ License-Expression: GPL-3.0-or-later
8
+ License-File: LICENSE
9
+ Keywords: data-science,gui,interactive,jupyter,machine-learning,notebook,python
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Intended Audience :: Science/Research
13
+ Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Requires-Python: >=3.9
21
+ Requires-Dist: ipywidgets
22
+ Requires-Dist: matplotlib
23
+ Provides-Extra: test
24
+ Requires-Dist: pytest-cov>=4.0.0; extra == 'test'
25
+ Requires-Dist: pytest>=7.0.0; extra == 'test'
26
+ Description-Content-Type: text/markdown
27
+
28
+ # syd
29
+
30
+ [![PyPI version](https://badge.fury.io/py/syd.svg)](https://badge.fury.io/py/syd)
31
+ [![Tests](https://github.com/landoskape/syd/actions/workflows/tests.yml/badge.svg)](https://github.com/landoskape/syd/actions/workflows/tests.yml)
32
+ [![Documentation Status](https://readthedocs.org/projects/shareyourdata/badge/?version=stable)](https://shareyourdata.readthedocs.io/en/stable/?badge=stable)
33
+ [![codecov](https://codecov.io/gh/landoskape/syd/branch/main/graph/badge.svg)](https://codecov.io/gh/landoskape/syd)
34
+ [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
35
+
36
+
37
+ A package to help you share your data!
38
+
39
+ 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!
40
+
41
+ Syd is a system for creating a data viewing GUI that you can view on a web-browser. And guess what? Since it opens on a web browser, you can even open it on any other computer on your local network! For example, your PI. Gone are the days of single random examples that they make infinitely stubborn conclusions about. Now, you can look at all the examples, quickly and easily, on their computer. And that's why syd stands for share your data!
42
+
43
+ Okay, so what is it? Syd is an automated system to convert some basic python plotting code into an interactive GUI. This is great, because it means you only have to think about what you want to plot and what you want to be interactive, syd does the work to make an interface. There's some small overhead for learning how to prepare your data to work with syd, but we provide some templates to make it easy. You know what that means? That means you get to focus on _thinking_ about your data, rather than spending time writing code to look at it. And that's why syd stands for Science, Yes! Datum!
44
+
45
+ ## Installation
46
+
47
+ ```bash
48
+ pip install syd
49
+ ```
50
+
51
+ ## Quick Start
52
+ Right now the only way to use it is in a jupyter notebook. More deployments coming soon!
53
+ This is an example of a sine wave viewer which is about as simple as it gets.
54
+ ```python
55
+ # In a notebook!
56
+ import matplotlib.pyplot as plt
57
+ import numpy as np
58
+ from syd import make_viewer
59
+ def plot(viewer, state):
60
+ fig, ax = plt.subplots()
61
+ x = np.linspace(0, 10, 1000)
62
+ y = state['amplitude'] * np.sin(state['frequency'] * x)
63
+ ax.plot(x, y)
64
+ return fig
65
+
66
+ viewer = make_viewer()
67
+ viewer.set_plot(plot)
68
+ viewer.add_float('amplitude', value=1.0, min_value=0, max_value=2)
69
+ viewer.add_float('frequency', value=1.0, min_value=0.1, max_value=5)
70
+ viewer.deploy(continuous=True)
71
+ ```
72
+
73
+ We have several examples of more complex viewers in the [examples](examples) folder. A good one
74
+ to start with is the [first example](examples/first_example.ipynb) because this has detailed
75
+ explanations of how to use the core elements of SYD. To see what the exact same viewer looks like
76
+ when written as a class, see the [subclass example](examples/subclass_example.ipynb). This format
77
+ is pretty useful when you want complex functionality - for example if you want to add extra
78
+ supporting methods for processing data and updating parameters that require more complex logic.
79
+
80
+ ## Documentation
81
+
82
+ Full documentation is available at [shareyourdata.readthedocs.io](https://shareyourdata.readthedocs.io/).
83
+
84
+ Key features:
85
+ - Create interactive matplotlib visualizations with minimal code
86
+ - Support for various parameter types (sliders, dropdowns, checkboxes, etc.)
87
+ - Real-time updates as parameters change
88
+ - Works in Jupyter notebooks and can be shared over local network
89
+
90
+ ## License
91
+
92
+ This project is licensed under the GNU General Public License v3.0 - see the [LICENSE](LICENSE) file for details.
93
+
94
+ ## Contributing
95
+
96
+ Contributions are welcome! Here's how you can help:
97
+
98
+ 1. Fork the repository
99
+ 2. Create a new branch (`git checkout -b feature/amazing-feature`)
100
+ 3. Make your changes
101
+ 4. Run the tests (`pytest`)
102
+ 5. Commit your changes (`git commit -m 'Add amazing feature'`)
103
+ 6. Push to the branch (`git push origin feature/amazing-feature`)
104
+ 7. Open a Pull Request online
105
+
106
+ Please make sure to update tests as appropriate and adhere to the existing coding style.
@@ -0,0 +1,18 @@
1
+ syd/__init__.py,sha256=elTyYXUlIX5Vv8AFjhM5C_XeZtU83YeGq_W980duI6k,284
2
+ syd/interactive_viewer.py,sha256=2vEyRwq4dxzGbJOz3UymNw_RJXRHrzv7UbJ2CV6q1bI,53950
3
+ syd/parameters.py,sha256=DbjevWsbIoVqlS3bYkqRd6SXJ054iexoNFj4VBss2eA,47703
4
+ syd/flask_deployment/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
+ syd/flask_deployment/components.py,sha256=I5xTFX5ho6EZ8ZjxknlluzSsxP5atUBAi_k7b8p_9Os,17391
6
+ syd/flask_deployment/deployer.py,sha256=EOo-oT3duBwWxVpQdpe-pXmAGGzfnqk4EY-vNcN-vAI,11288
7
+ syd/flask_deployment/static/css/styles.css,sha256=0zBjzquFMcxTNYNmVP1KdS3_7c1WiMYEqYHvubUyRhU,514
8
+ syd/flask_deployment/static/js/components.js,sha256=o_Ty-fvFsXTSl0eavJDDqhhxi-N3nuB-IPXkmin4vvI,1563
9
+ syd/flask_deployment/static/js/viewer.js,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
+ syd/flask_deployment/templates/base.html,sha256=6WZ9-Pc6pAysQbBSg_rihfRXPHMwyFxVR8YYD5bL524,783
11
+ syd/flask_deployment/templates/viewer.html,sha256=AoCdWQ5TIUEnpi6fjWdWUO9XJSLGFH0fHggGZd87yeg,2813
12
+ syd/notebook_deployment/__init__.py,sha256=eRum4_pXLTtaoUWvVnVCxJFrLM8Nn8EQ0yLwE9puh-w,41
13
+ syd/notebook_deployment/deployer.py,sha256=7iQ5kzs2VIkItmHbPpxtWdSRkGth5OABqyATc5WtbgI,8739
14
+ syd/notebook_deployment/widgets.py,sha256=bBBBJtgzfYcoXdhkuF4Du7HNXwwPjj_shGDhy3VoWs8,17446
15
+ syd-0.1.6.dist-info/METADATA,sha256=N7-fVmqKWzwJhhgl6t-Gft9BAlnhUpcTG9eni1Zs9Dk,5412
16
+ syd-0.1.6.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
17
+ syd-0.1.6.dist-info/licenses/LICENSE,sha256=YF6QR6Vjxcg5b_sYIyqkME7FZYau5TfEUGTG-0JeRK0,35129
18
+ syd-0.1.6.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[0],
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[1],
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[0],
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[1],
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()
@@ -1,33 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: syd
3
- Version: 0.1.4
4
- Summary: A Python package for making GUIs for data science easy.
5
- Project-URL: Homepage, https://github.com/landoskape/syd
6
- Author-email: Andrew Landau <andrew+tyler+landau+getridofthisanddtheplusses@gmail.com>
7
- License-Expression: GPL-3.0-or-later
8
- License-File: LICENSE
9
- Keywords: data-science,gui,interactive,jupyter,machine-learning,notebook,python
10
- Classifier: Development Status :: 4 - Beta
11
- Classifier: Intended Audience :: Developers
12
- Classifier: Intended Audience :: Science/Research
13
- Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
14
- Classifier: Operating System :: OS Independent
15
- Classifier: Programming Language :: Python :: 3.9
16
- Classifier: Programming Language :: Python :: 3.10
17
- Classifier: Programming Language :: Python :: 3.11
18
- Classifier: Programming Language :: Python :: 3.12
19
- Classifier: Programming Language :: Python :: 3.13
20
- Requires-Python: >=3.9
21
- Provides-Extra: test
22
- Requires-Dist: pytest-cov>=4.0.0; extra == 'test'
23
- Requires-Dist: pytest>=7.0.0; extra == 'test'
24
- Description-Content-Type: text/markdown
25
-
26
- # syd
27
- A package to help you share your data!
28
-
29
- 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
-
31
- Syd is a system for creating a data viewing GUI that you can view on a web-browser. And guess what? Since it opens on a web browser, you can even open it on any other computer on your local network! For example, your PI. Gone are the days of single random examples that they make infinitely stubborn conclusions about. Now, you can look at all the examples, quickly and easily, on their computer. And that's why syd stands for share your data!
32
-
33
- Okay, so what is it? Syd is an automated system to convert some basic python plotting code into an interactive GUI. This is great, because it means you only have to think about what you want to plot and what you want to be interactive, syd does the work to make an interface. There's some small overhead for learning how to prepare your data to work with syd, but we provide some templates to make it easy. You know what that means? That means you get to focus on _thinking_ about your data, rather than spending time writing code to look at it. And that's why syd stands for Science, Yes! Datum!
@@ -1,8 +0,0 @@
1
- syd/__init__.py,sha256=Wzf5T3NBDfhQoTnhnRNHSlAsE0XMqbclXG-M81Vas70,22
2
- syd/interactive_viewer.py,sha256=33aFY6Q4vg6fP5QVs2RYqfnqmFJzML-Lcnhbb1XwN2g,9353
3
- syd/notebook_deploy.py,sha256=k7yq7Noq30IlCbMXZ1rrX8oW5a3nxLNJHDFGvoJMYxg,11472
4
- syd/parameters.py,sha256=oQSAGM2D2Db4YLzj_nQb6_vPp18ltld7qvFC138lRJw,9885
5
- syd-0.1.4.dist-info/METADATA,sha256=re0-a0zHTlvEMyJIAHf7AM-OVEQkohwes7K2-xWfy_0,2449
6
- syd-0.1.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
7
- syd-0.1.4.dist-info/licenses/LICENSE,sha256=YF6QR6Vjxcg5b_sYIyqkME7FZYau5TfEUGTG-0JeRK0,35129
8
- syd-0.1.4.dist-info/RECORD,,
File without changes