Viewer¶
- syd.viewer.make_viewer(plot_func: Callable | None = None) Viewer[source]¶
Create an empty viewer object.
- Parameters:
plot_func (Callable, optional) – A function that takes a state dictionary and returns a matplotlib figure.
- Returns:
viewer – A new viewer object
- Return type:
Examples
>>> from syd import make_viewer >>> def plot(state): >>> ... generate figure, plot stuff ... >>> return fig >>> viewer = make_viewer(plot) >>> viewer.add_float('x', value=1.0, min=0, max=10) >>> viewer.on_change('x', viewer.update_based_on_x) >>> viewer.show()
Viewer¶
- class syd.viewer.Viewer(*args, **kwargs)[source]¶
Base class for creating interactive matplotlib figures with GUI controls.
This class helps you create interactive visualizations by adding GUI elements (like sliders, dropdowns, etc.) that update your plot in real-time. To use it:
Create a subclass and implement the plot() method
Add parameters using add_* methods before deploying
Use on_change() to make parameters update the plot
Use update_* methods to update parameter values and properties
Deploy the app to show the interactive figure
Examples
>>> class MyViewer(Viewer): ... def plot(self, state: Dict[str, Any]): ... fig = plt.figure() ... plt.plot([0, state['x']]) ... return fig ... ... def update_based_on_x(self, state: Dict[str, Any]): ... self.update_float('x', value=state['x']) ... >>> viewer = MyViewer() >>> viewer.add_float('x', value=1.0, min=0, max=10) >>> viewer.on_change('x', viewer.update_based_on_x) >>> viewer.show()
Methods
Create and return a matplotlib figure.
Get the current values of all parameters.
Register a function to run when parameters change.
Update a parameter's value and trigger any callbacks.
Parameter Registration
Add a text input parameter to the viewer.
Add a boolean parameter to the viewer.
Add a single-selection parameter to the viewer.
Add a multiple-selection parameter to the viewer.
Add an integer parameter to the viewer.
Add a float parameter to the viewer.
Add an integer range parameter to the viewer.
Add a float range parameter to the viewer.
Add an unbounded integer parameter to the viewer.
Add an unbounded decimal number parameter to the viewer.
Parameter Updates
Update a text parameter's value.
Update a boolean parameter's value.
Update a selection parameter's value and/or options.
Update a multiple selection parameter's values and/or options.
Update an integer parameter.
Update a float parameter.
Update an integer range parameter.
Update a float range parameter.
Update an unbounded integer parameter's value and/or bounds.
Update an unbounded float parameter's value, bounds, and/or step size.
- add_boolean(name: str, *, value: bool | NoInitialValue = NotInitialized) None[source]¶
Add a boolean parameter to the viewer.
Creates a checkbox in the GUI that can be toggled on/off. See
BooleanParameterfor details.- Parameters:
name (str) – Name of the parameter (used as label in GUI)
value (Union[bool, NoInitialValue]) – Initial state (True=checked, False=unchecked) If not provided, the parameter will be checked.
Examples
>>> viewer.add_boolean('show_grid', value=True) >>> viewer.state['show_grid'] True
- add_button(name: str, *, label: str | NoInitialValue = NotInitialized, callback: Callable[[], None], replot: bool = True) None[source]¶
Add a button parameter to the viewer.
Creates a clickable button in the GUI that triggers the provided callback function when clicked. The button’s display text can be different from its parameter name. See
ButtonParameterfor details.- Parameters:
name (str) – Name of the parameter (internal identifier)
label (Union[str, NoInitialValue]) – Text to display on the button If not provided, the parameter’s label will be set to the name.
callback (callable) – Function to call when the button is clicked (takes state as a single argument)
replot (bool, optional) – Whether to replot the figure after the callback is called. (default: True)
Examples
>>> def save_figure(state): ... print("Saving figure...") ... viewer.figure.savefig('last_figure.png') >>> viewer.add_button('save', label='Save Figure', callback=save_figure, replot=False)
>>> def print_plot_info(state): ... print(f"Current plot info: {state['plot_info']}") >>> viewer.add_button('print_info', label='Print Plot Info', callback=print_plot_info, replot=False)
>>> def reset_plot(state): ... print("Resetting plot...") >>> viewer.add_button('reset', label='Reset Plot', callback=reset_plot)
- add_float(name: str, *, value: float | int | NoInitialValue = NotInitialized, min: float | int, max: float | int, step: float = 0.01) None[source]¶
Add a float parameter to the viewer.
Creates a slider to select decimal numbers between a minimum and maximum. See
FloatParameterfor details.- Parameters:
name (str) – Name of the parameter (internal identifier)
value (Union[float, NoInitialValue]) – Initial value (default position of the slider) If not provided, the parameter will be set to the minimum value.
min (float) – Minimum allowed value
max (float) – Maximum allowed value
step (float, optional) – Step size for the slider (default: 0.01)
Examples
>>> viewer.add_float('temperature', value=98.6, min=95.0, max=105.0, step=0.1)
>>> viewer.add_float('price', value=9.99, min=0.0, max=100.0, step=0.01)
- add_float_range(name: str, *, value: Tuple[float | int, float | int] | NoInitialValue = NotInitialized, min: float | int, max: float | int, step: float = 0.01) None[source]¶
Add a float range parameter to the viewer.
Creates a range slider to select a range of decimal numbers between bounds. See
FloatRangeParameterfor details.- Parameters:
name (str) – Name of the parameter (internal identifier)
value (Union[tuple[float, float], NoInitialValue]) – Initial (low, high) values for the range If not provided, the parameter will be set to the full range.
min (float) – Minimum allowed value for the range
max (float) – Maximum allowed value for the range
step (float, optional) – Step size for the slider (default: 0.01)
Examples
>>> viewer.add_float_range('temp_range', value=(97.0, 99.0), min=95.0, max=105.0, step=0.1)
>>> viewer.add_float_range('price_range', value=(10.0, 50.0), min=0.0, max=100.0, step=0.01)
- add_integer(name: str, *, value: float | int | NoInitialValue = NotInitialized, min: float | int, max: float | int) None[source]¶
Add an integer parameter to the viewer.
Creates a slider to select whole numbers between a minimum and maximum. See
IntegerParameterfor details.- Parameters:
name (str) – Name of the parameter (used as label in GUI and internal identifier)
value (Union[int, NoInitialValue]) – Initial value (default position of the slider) If not provided, the parameter will be set to the minimum value.
min (int) – Minimum allowed value
max (int) – Maximum allowed value
Examples
>>> viewer.add_integer('age', value=25, min=0, max=120)
>>> viewer.add_integer('year', value=2023, min=1900, max=2100)
- add_integer_range(name: str, *, value: Tuple[float | int, float | int] | NoInitialValue = NotInitialized, min: float | int, max: float | int) None[source]¶
Add an integer range parameter to the viewer.
Creates a range slider to select a range of whole numbers between bounds. See
IntegerRangeParameterfor details.- Parameters:
name (str) – Name of the parameter (internal identifier)
value (Union[tuple[int, int], NoInitialValue]) – Initial (low, high) values for the range If not provided, the parameter will be set to the full range.
min (int) – Minimum allowed value for the range
max (int) – Maximum allowed value for the range
Examples
>>> viewer.add_integer_range('age_range', value=(25, 45), min=18, max=100)
>>> viewer.add_integer_range('year_range', value=(2000, 2020), min=1900, max=2100)
- add_multiple_selection(name: str, *, value: List[Any] | NoInitialValue = NotInitialized, options: List[Any]) None[source]¶
Add a multiple-selection parameter to the viewer.
Creates a set of checkboxes or a multi-select dropdown in the GUI where users can select any number of options. See
MultipleSelectionParameterfor details.- Parameters:
name (str) – Name of the parameter (used as label in GUI)
value (Union[list, NoInitialValue]) – Initially selected values (must all be in options) If not provided, the parameter will be empty.
options (list) – List of values that can be selected
Examples
>>> viewer.add_multiple_selection('toppings', ... value=['cheese'], ... options=['cheese', 'pepperoni', 'mushrooms']) >>> viewer.state['toppings'] ['cheese']
- add_selection(name: str, *, value: Any | NoInitialValue = NotInitialized, options: List[Any]) None[source]¶
Add a single-selection parameter to the viewer.
Creates a dropdown menu in the GUI where users can select one option. See
SelectionParameterfor details.- Parameters:
name (str) – Name of the parameter (used as label in GUI)
value (Any) – Initially selected value (must be one of the options)
options (list) – List of values that can be selected
Examples
>>> viewer.add_selection('color', value='red', ... options=['red', 'green', 'blue']) >>> viewer.state['color'] 'red'
- add_text(name: str, *, value: str | NoInitialValue = NotInitialized) None[source]¶
Add a text input parameter to the viewer.
Creates a text box in the GUI that accepts any string input. See
TextParameterfor details.- Parameters:
name (str) – Name of the parameter (used as label in GUI)
value (Union[str, NoInitialValue]) – Initial text value If not provided, the parameter will be empty.
Examples
>>> viewer.add_text('title', value='My Plot') >>> viewer.state['title'] 'My Plot'
- add_unbounded_float(name: str, *, value: float | int | NoInitialValue = NotInitialized, step: float | None = None) None[source]¶
Add an unbounded decimal number parameter to the viewer.
Creates a text input box in the GUI for entering numbers. Unlike add_float(), this allows very large or precise numbers without bounds. Values can optionally be rounded to a step size. See
UnboundedFloatParameterfor details.- Parameters:
name (str) – Name of the parameter (used as label in GUI)
value (Union[float, NoInitialValue]) – Initial value If not provided, the parameter will be set to 0.
step (float, optional) – Size of each increment (or None for no rounding)
Examples
>>> viewer.add_unbounded_float('wavelength', value=550e-9, step=1e-9) >>> viewer.state['wavelength'] 5.5e-07 >>> # Values will be rounded if step is provided >>> viewer.update_unbounded_float('wavelength', value=550.7e-9) >>> viewer.state['wavelength'] 5.51e-07
- add_unbounded_integer(name: str, *, value: float | int | NoInitialValue = NotInitialized) None[source]¶
Add an unbounded integer parameter to the viewer.
Creates a text input box in the GUI for entering whole numbers. Unlike add_integer(), this allows very large numbers without bounds. See
UnboundedIntegerParameterfor details.- Parameters:
name (str) – Name of the parameter (used as label in GUI)
value (Union[int, NoInitialValue]) – Initial value If not provided, the parameter will be set to 0.
Examples
>>> viewer.add_unbounded_integer('population', value=1000000) >>> viewer.state['population'] 1000000
- deploy(env: str = 'notebook', **kwargs)[source]¶
Deploy the app in a notebook or standalone environment
- property figure: Figure¶
Get the last opened figure. Returns None if no figure has been opened yet.
- on_change(parameter_name: str | List[str], callback: Callable)[source]¶
Register a function to run when parameters change.
The callback function will receive a dictionary of all current parameter values whenever any of the specified parameters change.
- Parameters:
parameter_name (str or list of str) – Name(s) of parameters to watch for changes
callback (callable) – Function to call when changes occur. Should accept a single dict argument containing the current state.
Examples
>>> def update_plot(state): ... print(f"x changed to {state['x']}") >>> viewer.on_change('x', update_plot) >>> viewer.on_change(['x', 'y'], lambda s: viewer.plot()) # Update on either change
- plot(state: Dict[str, Any]) Figure[source]¶
Create and return a matplotlib figure.
Hello user! This is a placeholder that raises a NotImplementedError. You must either:
1. Call set_plot() with your plotting function This will look like this: >>> def plot(state): >>> … generate figure, plot stuff … >>> return fig >>> viewer.set_plot(plot))
2. Subclass Viewer and override this method This will look like this: >>> class YourViewer(Viewer): >>> def plot(self, state): >>> … generate figure, plot stuff … >>> return fig
- Parameters:
state (dict) – Current parameter values
- Returns:
The figure to display
- Return type:
matplotlib.figure.Figure
Notes
Create a new figure each time, don’t reuse old ones
Access parameter values using state[‘param_name’]
Access your viewer class using self (or viewer for the set_plot() method)
Return the figure object, don’t call plt.show()!
- remove_parameter(name: str) None[source]¶
Remove a parameter from the viewer.
- Parameters:
name (str) – Name of the parameter to remove
- set_parameter_value(name: str, value: Any) None[source]¶
Update a parameter’s value and trigger any callbacks.
This is a lower-level method - usually you’ll want to use the update_* methods instead (e.g., update_float, update_text, etc.).
- Parameters:
name (str) – Name of the parameter to update
value (Any) – New value for the parameter
- Raises:
ValueError – If the parameter doesn’t exist or the value is invalid
- set_plot(func: Callable) None[source]¶
Set the plot method for the viewer.
For viewers created with make_viewer(), this function is used to set the plot method. The input must be a callable function that takes a state dictionary and returns a matplotlib figure.
Examples
>>> def plot(state): >>> ... generate figure, plot stuff ... >>> return fig >>> viewer = make_viewer() >>> viewer.set_plot(plot)
Share the viewer on a web browser using Flask.
- Parameters:
controls_position (str, optional) – Position of the controls relative to the plot (default is ‘left’).
fig_dpi (int, optional) – Dots per inch for the figure resolution (default is 300).
controls_width_percent (int, optional) – Width of the controls as a percentage of the total viewer width (default is 20).
plot_margin_percent (float, optional) – Margin around the plot as a percentage of the plot size (default is 2.5).
suppress_warnings (bool, optional) – If True, suppress warnings during deployment (default is True).
debug (bool, optional) – If True, run the server in debug mode (default is False).
host (str, optional) – Hostname to use for the server (default is None, which uses ‘localhost’).
port (int, optional) – Port number to use for the server (default is None, which selects the first available port).
open_browser (bool, optional) – If True, automatically open the web browser to the viewer (default is True).
update_threshold (float, optional) – Minimum time in seconds between updates to the viewer (default is 1.0).
timeout_threshold (float, optional) – Maximum time in seconds to wait for a response before timing out (default is 10.0).
Notes
This method is equivalent to calling deploy(env=”browser”) but does not return the viewer object.
- show(controls_position: Literal['left', 'top', 'right', 'bottom'] = 'left', controls_width_percent: int = 20, suppress_warnings: bool = True, update_threshold: float = 1.0)[source]¶
Show the viewer locally in a notebook.
This method displays the viewer in a Jupyter notebook environment with interactive controls.
- Parameters:
controls_position ({'left', 'top', 'right', 'bottom'}, optional) – Position of the controls relative to the plot (default is ‘left’).
controls_width_percent (int, optional) – Width of the controls as a percentage of the total viewer width (default is 20).
suppress_warnings (bool, optional) – If True, suppress warnings during deployment (default is True).
update_threshold (float, optional) – Minimum time in seconds between updates to the viewer (default is 1.0).
Notes
This method is equivalent to calling deploy(env=”notebook”) but does not return the viewer object.
- property state: Dict[str, Any]¶
Get the current values of all parameters.
- Returns:
Dictionary mapping parameter names to their current values
- Return type:
dict
Examples
>>> viewer.add_float('x', value=1.0, min=0, max=10) >>> viewer.add_text('label', value='data') >>> viewer.state {'x': 1.0, 'label': 'data'}
- update_boolean(name: str, *, value: bool | NoUpdate = NotUpdated) None[source]¶
Update a boolean parameter’s value.
Updates a parameter created by
add_boolean(). SeeBooleanParameterfor details about value validation.- Parameters:
name (str) – Name of the boolean parameter to update
value (Union[bool, NoUpdate], optional) – New state (True/False) (if not provided, no change)
Examples
>>> viewer.add_boolean('show_grid', value=True) >>> viewer.update_boolean('show_grid', value=False) >>> viewer.state['show_grid'] False
- update_button(name: str, *, label: str | NoUpdate = NotUpdated, callback: Callable[[], None] | NoUpdate = NotUpdated, replot: bool | NoUpdate = NotUpdated) None[source]¶
Update a button parameter’s label and/or callback function.
Updates a parameter created by
add_button(). SeeButtonActionfor details.- Parameters:
name (str) – Name of the button parameter to update
label (Union[str, NoUpdate], optional) – New text to display on the button (if not provided, no change)
callback (Union[callable, NoUpdate], optional) – New function to call when clicked (if not provided, no change)
replot (Union[bool, NoUpdate], optional) – Whether to replot the figure after the callback is called. (default: True)
Examples
>>> def new_callback(state): ... print("New action...") >>> viewer.update_button('reset', ... label='New Action!', ... callback=new_callback, ... replot=False)
- update_float(name: str, *, value: float | NoUpdate = NotUpdated, min: float | NoUpdate = NotUpdated, max: float | NoUpdate = NotUpdated, step: float | NoUpdate = NotUpdated) None[source]¶
Update a float parameter.
Change the value, bounds, or step size of an existing float parameter. See
FloatParameterfor details.- Parameters:
name (str) – Name of the parameter to update
value (Union[float, NoUpdate], optional) – New value
min (Union[float, NoUpdate], optional) – New minimum allowed value
max (Union[float, NoUpdate], optional) – New maximum allowed value
step (Union[float, NoUpdate], optional) – New step size for the slider
Examples
>>> viewer.update_float('temperature', value=99.5) # Update just the value
>>> viewer.update_float('price', min=5.0, max=200.0, step=0.05) # Update bounds and step
- update_float_range(name: str, *, value: Tuple[float, float] | NoUpdate = NotUpdated, min: float | NoUpdate = NotUpdated, max: float | NoUpdate = NotUpdated, step: float | NoUpdate = NotUpdated) None[source]¶
Update a float range parameter.
Change the range values, bounds, or step size of an existing float range parameter. See
FloatRangeParameterfor details.- Parameters:
name (str) – Name of the parameter to update
value (Union[tuple[float, float], NoUpdate], optional) – New (low, high) values
min (Union[float, NoUpdate], optional) – New minimum allowed value
max (Union[float, NoUpdate], optional) – New maximum allowed value
step (Union[float, NoUpdate], optional) – New step size for the slider
Examples
>>> viewer.update_float_range('temp_range', value=(97.5, 98.5)) # Update just the values
>>> viewer.update_float_range( ... 'price_range', ... min=10.0, ... max=500.0, ... step=0.5 ... ) # Update bounds and step
- update_integer(name: str, *, value: int | NoUpdate = NotUpdated, min: int | NoUpdate = NotUpdated, max: int | NoUpdate = NotUpdated) None[source]¶
Update an integer parameter.
Change the value or bounds of an existing integer parameter. See
IntegerParameterfor details.- Parameters:
Examples
>>> viewer.update_integer('age', value=30) # Update just the value
>>> viewer.update_integer('year', min=2000, max=2023) # Update just the bounds
- update_integer_range(name: str, *, value: Tuple[int, int] | NoUpdate = NotUpdated, min: int | NoUpdate = NotUpdated, max: int | NoUpdate = NotUpdated) None[source]¶
Update an integer range parameter.
Change the range values or bounds of an existing integer range parameter. See
IntegerRangeParameterfor details.- Parameters:
Examples
>>> viewer.update_integer_range('age_range', value=(30, 50)) # Update just the values
>>> viewer.update_integer_range('year_range', min=1950, max=2023) # Update just the bounds
- update_multiple_selection(name: str, *, value: List[Any] | NoUpdate = NotUpdated, options: List[Any] | NoUpdate = NotUpdated) None[source]¶
Update a multiple selection parameter’s values and/or options.
Updates a parameter created by
add_multiple_selection(). SeeMultipleSelectionParameterfor details about value validation.- Parameters:
Examples
>>> viewer.add_multiple_selection('toppings', ... value=['cheese'], ... options=['cheese', 'pepperoni', 'mushrooms']) >>> # Update selected values >>> viewer.update_multiple_selection('toppings', ... value=['cheese', 'mushrooms']) >>> # Update options (will reset value if current selections not in new options) >>> viewer.update_multiple_selection('toppings', ... options=['cheese', 'bacon', 'olives'], ... value=['cheese', 'bacon'])
- update_selection(name: str, *, value: Any | NoUpdate = NotUpdated, options: List[Any] | NoUpdate = NotUpdated) None[source]¶
Update a selection parameter’s value and/or options.
Updates a parameter created by
add_selection(). SeeSelectionParameterfor details about value validation.- Parameters:
Examples
>>> viewer.add_selection('color', value='red', ... options=['red', 'green', 'blue']) >>> # Update just the value >>> viewer.update_selection('color', value='blue') >>> # Update options and value together >>> viewer.update_selection('color', ... options=['purple', 'orange'], ... value='purple')
- update_text(name: str, *, value: str | NoUpdate = NotUpdated) None[source]¶
Update a text parameter’s value.
Updates a parameter created by
add_text(). SeeTextParameterfor details about value validation.- Parameters:
name (str) – Name of the text parameter to update
value (Union[str, NoUpdate], optional) – New text value (if not provided, no change)
Examples
>>> viewer.add_text('title', value='Original Title') >>> viewer.update_text('title', value='New Title') >>> viewer.state['title'] 'New Title'
- update_unbounded_float(name: str, *, value: float | NoUpdate = NotUpdated, step: float | None | NoUpdate = NotUpdated) None[source]¶
Update an unbounded float parameter’s value, bounds, and/or step size.
Updates a parameter created by
add_unbounded_float(). SeeUnboundedFloatParameterfor details about value validation.- Parameters:
name (str) – Name of the unbounded float parameter to update
value (Union[float, NoUpdate], optional) – New value (will be rounded if step is set) (if not provided, no change)
step (Union[Optional[float], NoUpdate], optional) – New step size for rounding, or None for no rounding (if not provided, no change)
Examples
>>> viewer.add_unbounded_float('wavelength', value=550e-9, step=1e-9) >>> # Update value (will be rounded if step is set) >>> viewer.update_unbounded_float('wavelength', value=632.8e-9) >>> # Change step size >>> viewer.update_unbounded_float('wavelength', step=0.1e-9) >>> # Remove step size (allow any precision) >>> viewer.update_unbounded_float('wavelength', step=None)
- update_unbounded_integer(name: str, *, value: int | NoUpdate = NotUpdated) None[source]¶
Update an unbounded integer parameter’s value and/or bounds.
Updates a parameter created by
add_unbounded_integer(). SeeUnboundedIntegerParameterfor details about value validation.- Parameters:
name (str) – Name of the unbounded integer parameter to update
value (Union[int, NoUpdate], optional) – New value (if not provided, no change)
Examples
>>> viewer.add_unbounded_integer('population', value=1000000) >>> # Update just the value >>> viewer.update_unbounded_integer('population', value=2000000)