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:

Viewer

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:

  1. Create a subclass and implement the plot() method

  2. Add parameters using add_* methods before deploying

  3. Use on_change() to make parameters update the plot

  4. Use update_* methods to update parameter values and properties

  5. 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

plot

Create and return a matplotlib figure.

state

Get the current values of all parameters.

on_change

Register a function to run when parameters change.

set_parameter_value

Update a parameter's value and trigger any callbacks.

Parameter Registration

add_text

Add a text input parameter to the viewer.

add_boolean

Add a boolean parameter to the viewer.

add_selection

Add a single-selection parameter to the viewer.

add_multiple_selection

Add a multiple-selection parameter to the viewer.

add_integer

Add an integer parameter to the viewer.

add_float

Add a float parameter to the viewer.

add_integer_range

Add an integer range parameter to the viewer.

add_float_range

Add a float range parameter to the viewer.

add_unbounded_integer

Add an unbounded integer parameter to the viewer.

add_unbounded_float

Add an unbounded decimal number parameter to the viewer.

Parameter Updates

update_text

Update a text parameter's value.

update_boolean

Update a boolean parameter's value.

update_selection

Update a selection parameter's value and/or options.

update_multiple_selection

Update a multiple selection parameter's values and/or options.

update_integer

Update an integer parameter.

update_float

Update a float parameter.

update_integer_range

Update an integer range parameter.

update_float_range

Update a float range parameter.

update_unbounded_integer

Update an unbounded integer parameter's value and/or bounds.

update_unbounded_float

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 BooleanParameter for 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 ButtonParameter for 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 FloatParameter for 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 FloatRangeParameter for 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 IntegerParameter for 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 IntegerRangeParameter for 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 MultipleSelectionParameter for 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 SelectionParameter for 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 TextParameter for 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 UnboundedFloatParameter for 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 UnboundedIntegerParameter for 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
perform_callbacks(name: str) bool[source]

Perform callbacks for all parameters that have changed

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(controls_position: str = 'left', fig_dpi: int = 300, controls_width_percent: int = 20, plot_margin_percent: float = 2.5, suppress_warnings: bool = True, debug: bool = False, host: str | None = None, port: int | None = None, open_browser: bool = True, update_threshold: float = 1.0, timeout_threshold: float = 10.0)[source]

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(). See BooleanParameter for 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(). See ButtonAction for 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 FloatParameter for 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 FloatRangeParameter for 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 IntegerParameter for details.

Parameters:
  • name (str) – Name of the parameter to update

  • value (Union[int, NoUpdate], optional) – New value

  • min (Union[int, NoUpdate], optional) – New minimum allowed value

  • max (Union[int, NoUpdate], optional) – New maximum allowed value

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 IntegerRangeParameter for details.

Parameters:
  • name (str) – Name of the parameter to update

  • value (Union[tuple[int, int], NoUpdate], optional) – New (low, high) values

  • min (Union[int, NoUpdate], optional) – New minimum allowed value

  • max (Union[int, NoUpdate], optional) – New maximum allowed value

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(). See MultipleSelectionParameter for details about value validation.

Parameters:
  • name (str) – Name of the multiple selection parameter to update

  • value (Union[list, NoUpdate], optional) – New list of selected values (all must be in options) (if not provided, no change)

  • options (Union[list, NoUpdate], optional) – New list of selectable options (if not provided, no change)

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(). See SelectionParameter for details about value validation.

Parameters:
  • name (str) – Name of the selection parameter to update

  • value (Union[Any, NoUpdate], optional) – New selected value (must be in options) (if not provided, no change)

  • options (Union[list, NoUpdate], optional) – New list of selectable options (if not provided, no change)

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(). See TextParameter for 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(). See UnboundedFloatParameter for 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(). See UnboundedIntegerParameter for 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)