syd 0.1.7__py3-none-any.whl → 0.2.0__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/viewer.py CHANGED
@@ -4,36 +4,18 @@ import inspect
4
4
  from contextlib import contextmanager
5
5
  from matplotlib.figure import Figure
6
6
 
7
- from .parameters import (
8
- ParameterType,
9
- ActionType,
10
- Parameter,
11
- ParameterAddError,
12
- ParameterUpdateError,
13
- )
7
+ from .parameters import ParameterType, ActionType, Parameter
8
+ from .support import NoUpdate, NoInitialValue, ParameterAddError, ParameterUpdateError
14
9
 
15
10
 
16
- class _NoUpdate:
17
- """Singleton class to represent a non-update in parameter operations."""
18
-
19
- _instance = None
20
-
21
- def __new__(cls):
22
- if cls._instance is None:
23
- cls._instance = super().__new__(cls)
24
- return cls._instance
25
-
26
- def __eq__(self, other):
27
- """This makes sure all comparisons of _NoUpdate objects return True"""
28
- return isinstance(other, _NoUpdate)
29
-
30
-
31
- # Create the singleton instance
32
- _NO_UPDATE = _NoUpdate()
11
+ # Create the singleton instances
12
+ NO_UPDATE = NoUpdate()
13
+ NO_INITIAL_VALUE = NoInitialValue()
33
14
 
34
15
 
35
16
  def validate_parameter_operation(
36
- operation: str, parameter_type: Union[ParameterType, ActionType]
17
+ operation: str,
18
+ parameter_type: Union[ParameterType, ActionType],
37
19
  ) -> Callable:
38
20
  """
39
21
  Decorator that validates parameter operations for the viewer class.
@@ -112,15 +94,7 @@ def validate_parameter_operation(
112
94
  msg = f"Parameter called {name} was found but is registered as a different parameter type ({type(self.parameters[name])}). Expecting {parameter_type.value}."
113
95
  raise ParameterUpdateError(name, parameter_type.name, msg)
114
96
 
115
- try:
116
- return func(self, name, *args, **kwargs)
117
- except Exception as e:
118
- if operation == "add":
119
- raise ParameterAddError(name, parameter_type.name, str(e))
120
- elif operation == "update":
121
- raise ParameterUpdateError(name, parameter_type.name, str(e))
122
- else:
123
- raise e
97
+ return func(self, name, *args, **kwargs)
124
98
 
125
99
  return wrapper
126
100
 
@@ -152,7 +126,7 @@ class Viewer:
152
126
  ... self.update_float('x', value=state['x'])
153
127
  ...
154
128
  >>> viewer = MyViewer()
155
- >>> viewer.add_float('x', value=1.0, min_value=0, max_value=10)
129
+ >>> viewer.add_float('x', value=1.0, min=0, max=10)
156
130
  >>> viewer.on_change('x', viewer.update_based_on_x)
157
131
  """
158
132
 
@@ -182,7 +156,7 @@ class Viewer:
182
156
 
183
157
  Examples
184
158
  --------
185
- >>> viewer.add_float('x', value=1.0, min_value=0, max_value=10)
159
+ >>> viewer.add_float('x', value=1.0, min=0, max=10)
186
160
  >>> viewer.add_text('label', value='data')
187
161
  >>> viewer.state
188
162
  {'x': 1.0, 'label': 'data'}
@@ -241,6 +215,7 @@ class Viewer:
241
215
 
242
216
  def deploy(self, env: str = "notebook", **kwargs):
243
217
  """Deploy the app in a notebook or standalone environment"""
218
+ env = env.lower()
244
219
  if env == "notebook":
245
220
  from .notebook_deployment import NotebookDeployer
246
221
 
@@ -248,25 +223,14 @@ class Viewer:
248
223
  deployer.deploy()
249
224
  return self
250
225
 
251
- elif env == "plotly":
252
- from .plotly_deployment import PlotlyDeployer
253
-
254
- deployer = PlotlyDeployer(self, **kwargs)
255
- deployer.deploy(mode="server")
256
- return self
226
+ elif env == "browser" or env == "flask":
227
+ from .flask_deployment import deploy_flask
257
228
 
258
- elif env == "plotly-inline":
259
- from .plotly_deployment import PlotlyDeployer
229
+ # Ensure port is None by default if not specified
230
+ if "port" not in kwargs:
231
+ kwargs["port"] = None
260
232
 
261
- deployer = PlotlyDeployer(self, **kwargs)
262
- deployer.deploy(mode="notebook")
263
- return self
264
-
265
- elif env == "flask":
266
- from .flask_deployment import FlaskDeployer
267
-
268
- deployer = FlaskDeployer(self, **kwargs)
269
- deployer.deploy()
233
+ deployer = deploy_flask(self, **kwargs)
270
234
  return self
271
235
  else:
272
236
  raise ValueError(
@@ -483,8 +447,25 @@ class Viewer:
483
447
  self.perform_callbacks(name)
484
448
 
485
449
  # -------------------- parameter registration methods --------------------
450
+ def remove_parameter(self, name: str) -> None:
451
+ """
452
+ Remove a parameter from the viewer.
453
+
454
+ Parameters
455
+ ----------
456
+ name : str
457
+ Name of the parameter to remove
458
+ """
459
+ if name in self.parameters:
460
+ del self.parameters[name]
461
+
486
462
  @validate_parameter_operation("add", ParameterType.text)
487
- def add_text(self, name: str, *, value: str) -> None:
463
+ def add_text(
464
+ self,
465
+ name: str,
466
+ *,
467
+ value: Union[str, NoInitialValue] = NO_INITIAL_VALUE,
468
+ ) -> None:
488
469
  """
489
470
  Add a text input parameter to the viewer.
490
471
 
@@ -495,8 +476,9 @@ class Viewer:
495
476
  ----------
496
477
  name : str
497
478
  Name of the parameter (used as label in GUI)
498
- value : str
479
+ value : Union[str, NoInitialValue]
499
480
  Initial text value
481
+ If not provided, the parameter will be empty.
500
482
 
501
483
  Examples
502
484
  --------
@@ -512,7 +494,12 @@ class Viewer:
512
494
  self.parameters[name] = new_param
513
495
 
514
496
  @validate_parameter_operation("add", ParameterType.boolean)
515
- def add_boolean(self, name: str, *, value: bool) -> None:
497
+ def add_boolean(
498
+ self,
499
+ name: str,
500
+ *,
501
+ value: Union[bool, NoInitialValue] = NO_INITIAL_VALUE,
502
+ ) -> None:
516
503
  """
517
504
  Add a boolean parameter to the viewer.
518
505
 
@@ -523,8 +510,9 @@ class Viewer:
523
510
  ----------
524
511
  name : str
525
512
  Name of the parameter (used as label in GUI)
526
- value : bool
513
+ value : Union[bool, NoInitialValue]
527
514
  Initial state (True=checked, False=unchecked)
515
+ If not provided, the parameter will be checked.
528
516
 
529
517
  Examples
530
518
  --------
@@ -540,7 +528,13 @@ class Viewer:
540
528
  self.parameters[name] = new_param
541
529
 
542
530
  @validate_parameter_operation("add", ParameterType.selection)
543
- def add_selection(self, name: str, *, value: Any, options: List[Any]) -> None:
531
+ def add_selection(
532
+ self,
533
+ name: str,
534
+ *,
535
+ value: Union[Any, NoInitialValue] = NO_INITIAL_VALUE,
536
+ options: List[Any],
537
+ ) -> None:
544
538
  """
545
539
  Add a single-selection parameter to the viewer.
546
540
 
@@ -572,7 +566,11 @@ class Viewer:
572
566
 
573
567
  @validate_parameter_operation("add", ParameterType.multiple_selection)
574
568
  def add_multiple_selection(
575
- self, name: str, *, value: List[Any], options: List[Any]
569
+ self,
570
+ name: str,
571
+ *,
572
+ value: Union[List[Any], NoInitialValue] = NO_INITIAL_VALUE,
573
+ options: List[Any],
576
574
  ) -> None:
577
575
  """
578
576
  Add a multiple-selection parameter to the viewer.
@@ -585,8 +583,9 @@ class Viewer:
585
583
  ----------
586
584
  name : str
587
585
  Name of the parameter (used as label in GUI)
588
- value : list
586
+ value : Union[list, NoInitialValue]
589
587
  Initially selected values (must all be in options)
588
+ If not provided, the parameter will be empty.
590
589
  options : list
591
590
  List of values that can be selected
592
591
 
@@ -610,46 +609,38 @@ class Viewer:
610
609
  self,
611
610
  name: str,
612
611
  *,
613
- value: Union[float, int],
614
- min_value: Union[float, int],
615
- max_value: Union[float, int],
612
+ value: Union[Union[float, int], NoInitialValue] = NO_INITIAL_VALUE,
613
+ min: Union[float, int],
614
+ max: Union[float, int],
616
615
  ) -> None:
617
616
  """
618
617
  Add an integer parameter to the viewer.
619
618
 
620
- Creates a slider in the GUI that lets users select whole numbers between
621
- min_value and max_value. Values will be clamped to stay within bounds.
619
+ Creates a slider to select whole numbers between a minimum and maximum.
622
620
  See :class:`~syd.parameters.IntegerParameter` for details.
623
621
 
624
622
  Parameters
625
623
  ----------
626
624
  name : str
627
- Name of the parameter (used as label in GUI)
628
- value : int
629
- Initial value (will be clamped between min_value and max_value)
630
- min_value : int
625
+ Name of the parameter (used as label in GUI and internal identifier)
626
+ value : Union[int, NoInitialValue]
627
+ Initial value (default position of the slider)
628
+ If not provided, the parameter will be set to the minimum value.
629
+ min : int
631
630
  Minimum allowed value
632
- max_value : int
631
+ max : int
633
632
  Maximum allowed value
634
633
 
635
634
  Examples
636
635
  --------
637
- >>> viewer.add_integer('count', value=5, min_value=0, max_value=10)
638
- >>> viewer.state['count']
639
- 5
640
- >>> viewer.update_integer('count', value=15) # Will be clamped to 10
641
- >>> viewer.state['count']
642
- 10
636
+ >>> viewer.add_integer('age', value=25, min=0, max=120)
637
+
638
+ >>> viewer.add_integer('year', value=2023, min=1900, max=2100)
643
639
  """
644
640
  try:
645
- new_param = ParameterType.integer.value(
646
- name,
647
- value,
648
- min_value,
649
- max_value,
650
- )
641
+ new_param = ParameterType.integer.value(name, value, min, max)
651
642
  except Exception as e:
652
- raise ParameterAddError(name, "number", str(e))
643
+ raise ParameterAddError(name, "integer", str(e)) from e
653
644
  else:
654
645
  self.parameters[name] = new_param
655
646
 
@@ -658,52 +649,41 @@ class Viewer:
658
649
  self,
659
650
  name: str,
660
651
  *,
661
- value: Union[float, int],
662
- min_value: Union[float, int],
663
- max_value: Union[float, int],
652
+ value: Union[Union[float, int], NoInitialValue] = NO_INITIAL_VALUE,
653
+ min: Union[float, int],
654
+ max: Union[float, int],
664
655
  step: float = 0.01,
665
656
  ) -> None:
666
657
  """
667
- Add a decimal number parameter to the viewer.
658
+ Add a float parameter to the viewer.
668
659
 
669
-
670
- Creates a slider in the GUI that lets users select numbers between
671
- min_value and max_value. Values will be rounded to the nearest step
672
- and clamped to stay within bounds.
660
+ Creates a slider to select decimal numbers between a minimum and maximum.
661
+ See :class:`~syd.parameters.FloatParameter` for details.
673
662
 
674
663
  Parameters
675
664
  ----------
676
665
  name : str
677
- Name of the parameter (used as label in GUI)
678
- value : float
679
- Initial value (will be clamped between min_value and max_value)
680
- min_value : float
666
+ Name of the parameter (internal identifier)
667
+ value : Union[float, NoInitialValue]
668
+ Initial value (default position of the slider)
669
+ If not provided, the parameter will be set to the minimum value.
670
+ min : float
681
671
  Minimum allowed value
682
- max_value : float
672
+ max : float
683
673
  Maximum allowed value
684
674
  step : float, optional
685
- Size of each increment (default: 0.01)
675
+ Step size for the slider (default: 0.01)
686
676
 
687
677
  Examples
688
678
  --------
689
- >>> viewer.add_float('temperature', value=20.0,
690
- ... min_value=0.0, max_value=100.0, step=0.5)
691
- >>> viewer.state['temperature']
692
- 20.0
693
- >>> viewer.update_float('temperature', value=20.7) # Will round to 20.5
694
- >>> viewer.state['temperature']
695
- 20.5
679
+ >>> viewer.add_float('temperature', value=98.6, min=95.0, max=105.0, step=0.1)
680
+
681
+ >>> viewer.add_float('price', value=9.99, min=0.0, max=100.0, step=0.01)
696
682
  """
697
683
  try:
698
- new_param = ParameterType.float.value(
699
- name,
700
- value,
701
- min_value,
702
- max_value,
703
- step,
704
- )
684
+ new_param = ParameterType.float.value(name, value, min, max, step)
705
685
  except Exception as e:
706
- raise ParameterAddError(name, "number", str(e)) from e
686
+ raise ParameterAddError(name, "float", str(e)) from e
707
687
  else:
708
688
  self.parameters[name] = new_param
709
689
 
@@ -712,48 +692,38 @@ class Viewer:
712
692
  self,
713
693
  name: str,
714
694
  *,
715
- value: Tuple[Union[float, int], Union[float, int]],
716
- min_value: Union[float, int],
717
- max_value: Union[float, int],
695
+ value: Union[
696
+ Tuple[Union[float, int], Union[float, int]], NoInitialValue
697
+ ] = NO_INITIAL_VALUE,
698
+ min: Union[float, int],
699
+ max: Union[float, int],
718
700
  ) -> None:
719
701
  """
720
- Add a range parameter for whole numbers to the viewer.
702
+ Add an integer range parameter to the viewer.
721
703
 
722
- Creates a range slider in the GUI that lets users select a range of integers
723
- between min_value and max_value. The range is specified as (low, high) and
724
- both values will be clamped to stay within bounds.
704
+ Creates a range slider to select a range of whole numbers between bounds.
725
705
  See :class:`~syd.parameters.IntegerRangeParameter` for details.
726
706
 
727
707
  Parameters
728
708
  ----------
729
709
  name : str
730
- Name of the parameter (used as label in GUI)
731
- value : tuple[int, int]
732
- Initial (low, high) values
733
- min_value : int
734
- Minimum allowed value for both low and high
735
- max_value : int
736
- Maximum allowed value for both low and high
710
+ Name of the parameter (internal identifier)
711
+ value : Union[tuple[int, int], NoInitialValue]
712
+ Initial (low, high) values for the range
713
+ If not provided, the parameter will be set to the full range.
714
+ min : int
715
+ Minimum allowed value for the range
716
+ max : int
717
+ Maximum allowed value for the range
737
718
 
738
719
  Examples
739
720
  --------
740
- >>> viewer.add_integer_range('age_range',
741
- ... value=(25, 35),
742
- ... min_value=18, max_value=100)
743
- >>> viewer.state['age_range']
744
- (25, 35)
745
- >>> # Values will be swapped if low > high
746
- >>> viewer.update_integer_range('age_range', value=(40, 30))
747
- >>> viewer.state['age_range']
748
- (30, 40)
721
+ >>> viewer.add_integer_range('age_range', value=(25, 45), min=18, max=100)
722
+
723
+ >>> viewer.add_integer_range('year_range', value=(2000, 2020), min=1900, max=2100)
749
724
  """
750
725
  try:
751
- new_param = ParameterType.integer_range.value(
752
- name,
753
- value,
754
- min_value,
755
- max_value,
756
- )
726
+ new_param = ParameterType.integer_range.value(name, value, min, max)
757
727
  except Exception as e:
758
728
  raise ParameterAddError(name, "integer_range", str(e)) from e
759
729
  else:
@@ -764,52 +734,41 @@ class Viewer:
764
734
  self,
765
735
  name: str,
766
736
  *,
767
- value: Tuple[Union[float, int], Union[float, int]],
768
- min_value: Union[float, int],
769
- max_value: Union[float, int],
737
+ value: Union[
738
+ Tuple[Union[float, int], Union[float, int]], NoInitialValue
739
+ ] = NO_INITIAL_VALUE,
740
+ min: Union[float, int],
741
+ max: Union[float, int],
770
742
  step: float = 0.01,
771
743
  ) -> None:
772
744
  """
773
- Add a range parameter for decimal numbers to the viewer.
745
+ Add a float range parameter to the viewer.
774
746
 
775
- Creates a range slider in the GUI that lets users select a range of numbers
776
- between min_value and max_value. The range is specified as (low, high) and
777
- both values will be rounded to the nearest step and clamped to stay within bounds.
747
+ Creates a range slider to select a range of decimal numbers between bounds.
778
748
  See :class:`~syd.parameters.FloatRangeParameter` for details.
779
749
 
780
750
  Parameters
781
751
  ----------
782
752
  name : str
783
- Name of the parameter (used as label in GUI)
784
- value : tuple[float, float]
785
- Initial (low, high) values
786
- min_value : float
787
- Minimum allowed value for both low and high
788
- max_value : float
789
- Maximum allowed value for both low and high
753
+ Name of the parameter (internal identifier)
754
+ value : Union[tuple[float, float], NoInitialValue]
755
+ Initial (low, high) values for the range
756
+ If not provided, the parameter will be set to the full range.
757
+ min : float
758
+ Minimum allowed value for the range
759
+ max : float
760
+ Maximum allowed value for the range
790
761
  step : float, optional
791
- Size of each increment (default: 0.01)
762
+ Step size for the slider (default: 0.01)
792
763
 
793
764
  Examples
794
765
  --------
795
- >>> viewer.add_float_range('price_range',
796
- ... value=(10.0, 20.0),
797
- ... min_value=0.0, max_value=100.0, step=0.5)
798
- >>> viewer.state['price_range']
799
- (10.0, 20.0)
800
- >>> # Values will be rounded to nearest step
801
- >>> viewer.update_float_range('price_range', value=(10.7, 19.2))
802
- >>> viewer.state['price_range']
803
- (10.5, 19.0)
766
+ >>> viewer.add_float_range('temp_range', value=(97.0, 99.0), min=95.0, max=105.0, step=0.1)
767
+
768
+ >>> viewer.add_float_range('price_range', value=(10.0, 50.0), min=0.0, max=100.0, step=0.01)
804
769
  """
805
770
  try:
806
- new_param = ParameterType.float_range.value(
807
- name,
808
- value,
809
- min_value,
810
- max_value,
811
- step,
812
- )
771
+ new_param = ParameterType.float_range.value(name, value, min, max, step)
813
772
  except Exception as e:
814
773
  raise ParameterAddError(name, "float_range", str(e)) from e
815
774
  else:
@@ -820,7 +779,7 @@ class Viewer:
820
779
  self,
821
780
  name: str,
822
781
  *,
823
- value: Union[float, int],
782
+ value: Union[Union[float, int], NoInitialValue] = NO_INITIAL_VALUE,
824
783
  ) -> None:
825
784
  """
826
785
  Add an unbounded integer parameter to the viewer.
@@ -833,8 +792,9 @@ class Viewer:
833
792
  ----------
834
793
  name : str
835
794
  Name of the parameter (used as label in GUI)
836
- value : int
795
+ value : Union[int, NoInitialValue]
837
796
  Initial value
797
+ If not provided, the parameter will be set to 0.
838
798
 
839
799
  Examples
840
800
  --------
@@ -843,10 +803,7 @@ class Viewer:
843
803
  1000000
844
804
  """
845
805
  try:
846
- new_param = ParameterType.unbounded_integer.value(
847
- name,
848
- value,
849
- )
806
+ new_param = ParameterType.unbounded_integer.value(name, value)
850
807
  except Exception as e:
851
808
  raise ParameterAddError(name, "unbounded_integer", str(e)) from e
852
809
  else:
@@ -857,7 +814,7 @@ class Viewer:
857
814
  self,
858
815
  name: str,
859
816
  *,
860
- value: Union[float, int],
817
+ value: Union[Union[float, int], NoInitialValue] = NO_INITIAL_VALUE,
861
818
  step: Optional[float] = None,
862
819
  ) -> None:
863
820
  """
@@ -872,8 +829,9 @@ class Viewer:
872
829
  ----------
873
830
  name : str
874
831
  Name of the parameter (used as label in GUI)
875
- value : float
832
+ value : Union[float, NoInitialValue]
876
833
  Initial value
834
+ If not provided, the parameter will be set to 0.
877
835
  step : float, optional
878
836
  Size of each increment (or None for no rounding)
879
837
 
@@ -888,11 +846,7 @@ class Viewer:
888
846
  5.51e-07
889
847
  """
890
848
  try:
891
- new_param = ParameterType.unbounded_float.value(
892
- name,
893
- value,
894
- step,
895
- )
849
+ new_param = ParameterType.unbounded_float.value(name, value, step)
896
850
  except Exception as e:
897
851
  raise ParameterAddError(name, "unbounded_float", str(e)) from e
898
852
  else:
@@ -903,7 +857,7 @@ class Viewer:
903
857
  self,
904
858
  name: str,
905
859
  *,
906
- label: str,
860
+ label: Union[str, NoInitialValue] = NO_INITIAL_VALUE,
907
861
  callback: Callable[[], None],
908
862
  ) -> None:
909
863
  """
@@ -917,8 +871,9 @@ class Viewer:
917
871
  ----------
918
872
  name : str
919
873
  Name of the parameter (internal identifier)
920
- label : str
874
+ label : Union[str, NoInitialValue]
921
875
  Text to display on the button
876
+ If not provided, the parameter's label will be set to the name.
922
877
  callback : callable
923
878
  Function to call when the button is clicked (takes state as a single argument)
924
879
 
@@ -947,7 +902,7 @@ class Viewer:
947
902
  # -------------------- parameter update methods --------------------
948
903
  @validate_parameter_operation("update", ParameterType.text)
949
904
  def update_text(
950
- self, name: str, *, value: Union[str, _NoUpdate] = _NO_UPDATE
905
+ self, name: str, *, value: Union[str, NoUpdate] = NO_UPDATE
951
906
  ) -> None:
952
907
  """
953
908
  Update a text parameter's value.
@@ -959,7 +914,7 @@ class Viewer:
959
914
  ----------
960
915
  name : str
961
916
  Name of the text parameter to update
962
- value : str, optional
917
+ value : Union[str, NoUpdate], optional
963
918
  New text value (if not provided, no change)
964
919
 
965
920
  Examples
@@ -970,14 +925,14 @@ class Viewer:
970
925
  'New Title'
971
926
  """
972
927
  updates = {}
973
- if not value == _NO_UPDATE:
928
+ if not value == NO_UPDATE:
974
929
  updates["value"] = value
975
930
  if updates:
976
931
  self.parameters[name].update(updates)
977
932
 
978
933
  @validate_parameter_operation("update", ParameterType.boolean)
979
934
  def update_boolean(
980
- self, name: str, *, value: Union[bool, _NoUpdate] = _NO_UPDATE
935
+ self, name: str, *, value: Union[bool, NoUpdate] = NO_UPDATE
981
936
  ) -> None:
982
937
  """
983
938
  Update a boolean parameter's value.
@@ -989,7 +944,7 @@ class Viewer:
989
944
  ----------
990
945
  name : str
991
946
  Name of the boolean parameter to update
992
- value : bool, optional
947
+ value : Union[bool, NoUpdate], optional
993
948
  New state (True/False) (if not provided, no change)
994
949
 
995
950
  Examples
@@ -1000,7 +955,7 @@ class Viewer:
1000
955
  False
1001
956
  """
1002
957
  updates = {}
1003
- if not value == _NO_UPDATE:
958
+ if not value == NO_UPDATE:
1004
959
  updates["value"] = value
1005
960
  if updates:
1006
961
  self.parameters[name].update(updates)
@@ -1010,8 +965,8 @@ class Viewer:
1010
965
  self,
1011
966
  name: str,
1012
967
  *,
1013
- value: Union[Any, _NoUpdate] = _NO_UPDATE,
1014
- options: Union[List[Any], _NoUpdate] = _NO_UPDATE,
968
+ value: Union[Any, NoUpdate] = NO_UPDATE,
969
+ options: Union[List[Any], NoUpdate] = NO_UPDATE,
1015
970
  ) -> None:
1016
971
  """
1017
972
  Update a selection parameter's value and/or options.
@@ -1023,9 +978,9 @@ class Viewer:
1023
978
  ----------
1024
979
  name : str
1025
980
  Name of the selection parameter to update
1026
- value : Any, optional
981
+ value : Union[Any, NoUpdate], optional
1027
982
  New selected value (must be in options) (if not provided, no change)
1028
- options : list, optional
983
+ options : Union[list, NoUpdate], optional
1029
984
  New list of selectable options (if not provided, no change)
1030
985
 
1031
986
  Examples
@@ -1040,9 +995,9 @@ class Viewer:
1040
995
  ... value='purple')
1041
996
  """
1042
997
  updates = {}
1043
- if not value == _NO_UPDATE:
998
+ if not value == NO_UPDATE:
1044
999
  updates["value"] = value
1045
- if not options == _NO_UPDATE:
1000
+ if not options == NO_UPDATE:
1046
1001
  updates["options"] = options
1047
1002
  if updates:
1048
1003
  self.parameters[name].update(updates)
@@ -1052,8 +1007,8 @@ class Viewer:
1052
1007
  self,
1053
1008
  name: str,
1054
1009
  *,
1055
- value: Union[List[Any], _NoUpdate] = _NO_UPDATE,
1056
- options: Union[List[Any], _NoUpdate] = _NO_UPDATE,
1010
+ value: Union[List[Any], NoUpdate] = NO_UPDATE,
1011
+ options: Union[List[Any], NoUpdate] = NO_UPDATE,
1057
1012
  ) -> None:
1058
1013
  """
1059
1014
  Update a multiple selection parameter's values and/or options.
@@ -1065,9 +1020,9 @@ class Viewer:
1065
1020
  ----------
1066
1021
  name : str
1067
1022
  Name of the multiple selection parameter to update
1068
- value : list, optional
1023
+ value : Union[list, NoUpdate], optional
1069
1024
  New list of selected values (all must be in options) (if not provided, no change)
1070
- options : list, optional
1025
+ options : Union[list, NoUpdate], optional
1071
1026
  New list of selectable options (if not provided, no change)
1072
1027
 
1073
1028
  Examples
@@ -1084,9 +1039,9 @@ class Viewer:
1084
1039
  ... value=['cheese', 'bacon'])
1085
1040
  """
1086
1041
  updates = {}
1087
- if not value == _NO_UPDATE:
1042
+ if not value == NO_UPDATE:
1088
1043
  updates["value"] = value
1089
- if not options == _NO_UPDATE:
1044
+ if not options == NO_UPDATE:
1090
1045
  updates["options"] = options
1091
1046
  if updates:
1092
1047
  self.parameters[name].update(updates)
@@ -1096,200 +1051,196 @@ class Viewer:
1096
1051
  self,
1097
1052
  name: str,
1098
1053
  *,
1099
- value: Union[int, _NoUpdate] = _NO_UPDATE,
1100
- min_value: Union[int, _NoUpdate] = _NO_UPDATE,
1101
- max_value: Union[int, _NoUpdate] = _NO_UPDATE,
1054
+ value: Union[int, NoUpdate] = NO_UPDATE,
1055
+ min: Union[int, NoUpdate] = NO_UPDATE,
1056
+ max: Union[int, NoUpdate] = NO_UPDATE,
1102
1057
  ) -> None:
1103
1058
  """
1104
- Update an integer parameter's value and/or bounds.
1059
+ Update an integer parameter.
1105
1060
 
1106
- Updates a parameter created by :meth:`~syd.viewer.Viewer.add_integer`.
1107
- See :class:`~syd.parameters.IntegerParameter` for details about value validation.
1061
+ Change the value or bounds of an existing integer parameter.
1062
+ See :class:`~syd.parameters.IntegerParameter` for details.
1108
1063
 
1109
1064
  Parameters
1110
1065
  ----------
1111
1066
  name : str
1112
- Name of the integer parameter to update
1113
- value : int, optional
1114
- New value (will be clamped to bounds) (if not provided, no change)
1115
- min_value : int, optional
1116
- New minimum value (if not provided, no change)
1117
- max_value : int, optional
1118
- New maximum value (if not provided, no change)
1067
+ Name of the parameter to update
1068
+ value : Union[int, NoUpdate], optional
1069
+ New value
1070
+ min : Union[int, NoUpdate], optional
1071
+ New minimum allowed value
1072
+ max : Union[int, NoUpdate], optional
1073
+ New maximum allowed value
1119
1074
 
1120
1075
  Examples
1121
1076
  --------
1122
- >>> viewer.add_integer('count', value=5, min_value=0, max_value=10)
1123
- >>> # Update just the value
1124
- >>> viewer.update_integer('count', value=8)
1125
- >>> # Update bounds (current value will be clamped if needed)
1126
- >>> viewer.update_integer('count', min_value=7, max_value=15)
1077
+ >>> viewer.update_integer('age', value=30) # Update just the value
1078
+
1079
+ >>> viewer.update_integer('year', min=2000, max=2023) # Update just the bounds
1127
1080
  """
1128
1081
  updates = {}
1129
- if not value == _NO_UPDATE:
1130
- updates["value"] = value
1131
- if not min_value == _NO_UPDATE:
1132
- updates["min_value"] = min_value
1133
- if not max_value == _NO_UPDATE:
1134
- updates["max_value"] = max_value
1135
- if updates:
1136
- self.parameters[name].update(updates)
1082
+ if not isinstance(value, NoUpdate):
1083
+ updates["value"] = int(value)
1084
+ if not isinstance(min, NoUpdate):
1085
+ updates["min"] = int(min)
1086
+ if not isinstance(max, NoUpdate):
1087
+ updates["max"] = int(max)
1088
+
1089
+ parameter = self.parameters[name]
1090
+ parameter.update(updates)
1137
1091
 
1138
1092
  @validate_parameter_operation("update", ParameterType.float)
1139
1093
  def update_float(
1140
1094
  self,
1141
1095
  name: str,
1142
1096
  *,
1143
- value: Union[float, _NoUpdate] = _NO_UPDATE,
1144
- min_value: Union[float, _NoUpdate] = _NO_UPDATE,
1145
- max_value: Union[float, _NoUpdate] = _NO_UPDATE,
1146
- step: Union[float, _NoUpdate] = _NO_UPDATE,
1097
+ value: Union[float, NoUpdate] = NO_UPDATE,
1098
+ min: Union[float, NoUpdate] = NO_UPDATE,
1099
+ max: Union[float, NoUpdate] = NO_UPDATE,
1100
+ step: Union[float, NoUpdate] = NO_UPDATE,
1147
1101
  ) -> None:
1148
1102
  """
1149
- Update a float parameter's value, bounds, and/or step size.
1103
+ Update a float parameter.
1150
1104
 
1151
- Updates a parameter created by :meth:`~syd.viewer.Viewer.add_float`.
1152
- See :class:`~syd.parameters.FloatParameter` for details about value validation.
1105
+ Change the value, bounds, or step size of an existing float parameter.
1106
+ See :class:`~syd.parameters.FloatParameter` for details.
1153
1107
 
1154
1108
  Parameters
1155
1109
  ----------
1156
1110
  name : str
1157
- Name of the float parameter to update
1158
- value : float, optional
1159
- New value (will be rounded and clamped) (if not provided, no change)
1160
- min_value : float, optional
1161
- New minimum value (if not provided, no change)
1162
- max_value : float, optional
1163
- New maximum value (if not provided, no change)
1164
- step : float, optional
1165
- New step size (if not provided, no change)
1111
+ Name of the parameter to update
1112
+ value : Union[float, NoUpdate], optional
1113
+ New value
1114
+ min : Union[float, NoUpdate], optional
1115
+ New minimum allowed value
1116
+ max : Union[float, NoUpdate], optional
1117
+ New maximum allowed value
1118
+ step : Union[float, NoUpdate], optional
1119
+ New step size for the slider
1166
1120
 
1167
1121
  Examples
1168
1122
  --------
1169
- >>> viewer.add_float('temperature', value=20.0,
1170
- ... min_value=0.0, max_value=100.0, step=0.5)
1171
- >>> # Update just the value (will round to step)
1172
- >>> viewer.update_float('temperature', value=20.7) # Becomes 20.5
1173
- >>> # Update bounds and step size
1174
- >>> viewer.update_float('temperature',
1175
- ... min_value=15.0, max_value=30.0, step=0.1)
1123
+ >>> viewer.update_float('temperature', value=99.5) # Update just the value
1124
+
1125
+ >>> viewer.update_float('price', min=5.0, max=200.0, step=0.05) # Update bounds and step
1176
1126
  """
1177
1127
  updates = {}
1178
- if not value == _NO_UPDATE:
1179
- updates["value"] = value
1180
- if not min_value == _NO_UPDATE:
1181
- updates["min_value"] = min_value
1182
- if not max_value == _NO_UPDATE:
1183
- updates["max_value"] = max_value
1184
- if not step == _NO_UPDATE:
1185
- updates["step"] = step
1186
- if updates:
1187
- self.parameters[name].update(updates)
1128
+ if not isinstance(value, NoUpdate):
1129
+ updates["value"] = float(value)
1130
+ if not isinstance(min, NoUpdate):
1131
+ updates["min"] = float(min)
1132
+ if not isinstance(max, NoUpdate):
1133
+ updates["max"] = float(max)
1134
+ if not isinstance(step, NoUpdate):
1135
+ updates["step"] = float(step)
1136
+
1137
+ parameter = self.parameters[name]
1138
+ parameter.update(updates)
1188
1139
 
1189
1140
  @validate_parameter_operation("update", ParameterType.integer_range)
1190
1141
  def update_integer_range(
1191
1142
  self,
1192
1143
  name: str,
1193
1144
  *,
1194
- value: Union[Tuple[int, int], _NoUpdate] = _NO_UPDATE,
1195
- min_value: Union[int, _NoUpdate] = _NO_UPDATE,
1196
- max_value: Union[int, _NoUpdate] = _NO_UPDATE,
1145
+ value: Union[Tuple[int, int], NoUpdate] = NO_UPDATE,
1146
+ min: Union[int, NoUpdate] = NO_UPDATE,
1147
+ max: Union[int, NoUpdate] = NO_UPDATE,
1197
1148
  ) -> None:
1198
1149
  """
1199
- Update an integer range parameter's values and/or bounds.
1150
+ Update an integer range parameter.
1200
1151
 
1201
- Updates a parameter created by :meth:`~syd.viewer.Viewer.add_integer_range`.
1202
- See :class:`~syd.parameters.IntegerRangeParameter` for details about value validation.
1152
+ Change the range values or bounds of an existing integer range parameter.
1153
+ See :class:`~syd.parameters.IntegerRangeParameter` for details.
1203
1154
 
1204
1155
  Parameters
1205
1156
  ----------
1206
1157
  name : str
1207
- Name of the integer range parameter to update
1208
- value : tuple[int, int], optional
1209
- New (low, high) values (will be clamped) (if not provided, no change)
1210
- min_value : int, optional
1211
- New minimum value for both low and high (if not provided, no change)
1212
- max_value : int, optional
1213
- New maximum value for both low and high (if not provided, no change)
1158
+ Name of the parameter to update
1159
+ value : Union[tuple[int, int], NoUpdate], optional
1160
+ New (low, high) values
1161
+ min : Union[int, NoUpdate], optional
1162
+ New minimum allowed value
1163
+ max : Union[int, NoUpdate], optional
1164
+ New maximum allowed value
1214
1165
 
1215
1166
  Examples
1216
1167
  --------
1217
- >>> viewer.add_integer_range('age_range',
1218
- ... value=(25, 35),
1219
- ... min_value=18, max_value=100)
1220
- >>> # Update just the range (values will be swapped if needed)
1221
- >>> viewer.update_integer_range('age_range', value=(40, 30)) # Becomes (30, 40)
1222
- >>> # Update bounds (current values will be clamped if needed)
1223
- >>> viewer.update_integer_range('age_range', min_value=20, max_value=80)
1168
+ >>> viewer.update_integer_range('age_range', value=(30, 50)) # Update just the values
1169
+
1170
+ >>> viewer.update_integer_range('year_range', min=1950, max=2023) # Update just the bounds
1224
1171
  """
1225
1172
  updates = {}
1226
- if not value == _NO_UPDATE:
1227
- updates["value"] = value
1228
- if not min_value == _NO_UPDATE:
1229
- updates["min_value"] = min_value
1230
- if not max_value == _NO_UPDATE:
1231
- updates["max_value"] = max_value
1232
- if updates:
1233
- self.parameters[name].update(updates)
1173
+ if not isinstance(value, NoUpdate):
1174
+ val_low, val_high = value
1175
+ updates["value"] = (int(val_low), int(val_high))
1176
+ if not isinstance(min, NoUpdate):
1177
+ updates["min"] = int(min)
1178
+ if not isinstance(max, NoUpdate):
1179
+ updates["max"] = int(max)
1180
+
1181
+ parameter = self.parameters[name]
1182
+ parameter.update(updates)
1234
1183
 
1235
1184
  @validate_parameter_operation("update", ParameterType.float_range)
1236
1185
  def update_float_range(
1237
1186
  self,
1238
1187
  name: str,
1239
1188
  *,
1240
- value: Union[Tuple[float, float], _NoUpdate] = _NO_UPDATE,
1241
- min_value: Union[float, _NoUpdate] = _NO_UPDATE,
1242
- max_value: Union[float, _NoUpdate] = _NO_UPDATE,
1243
- step: Union[float, _NoUpdate] = _NO_UPDATE,
1189
+ value: Union[Tuple[float, float], NoUpdate] = NO_UPDATE,
1190
+ min: Union[float, NoUpdate] = NO_UPDATE,
1191
+ max: Union[float, NoUpdate] = NO_UPDATE,
1192
+ step: Union[float, NoUpdate] = NO_UPDATE,
1244
1193
  ) -> None:
1245
1194
  """
1246
- Update a float range parameter's values, bounds, and/or step size.
1195
+ Update a float range parameter.
1247
1196
 
1248
- Updates a parameter created by :meth:`~syd.viewer.Viewer.add_float_range`.
1249
- See :class:`~syd.parameters.FloatRangeParameter` for details about value validation.
1197
+ Change the range values, bounds, or step size of an existing float range parameter.
1198
+ See :class:`~syd.parameters.FloatRangeParameter` for details.
1250
1199
 
1251
1200
  Parameters
1252
1201
  ----------
1253
1202
  name : str
1254
- Name of the float range parameter to update
1255
- value : tuple[float, float], optional
1256
- New (low, high) values (will be rounded and clamped) (if not provided, no change)
1257
- min_value : float, optional
1258
- New minimum value for both low and high (if not provided, no change)
1259
- max_value : float, optional
1260
- New maximum value for both low and high (if not provided, no change)
1261
- step : float, optional
1262
- New step size for rounding values (if not provided, no change)
1203
+ Name of the parameter to update
1204
+ value : Union[tuple[float, float], NoUpdate], optional
1205
+ New (low, high) values
1206
+ min : Union[float, NoUpdate], optional
1207
+ New minimum allowed value
1208
+ max : Union[float, NoUpdate], optional
1209
+ New maximum allowed value
1210
+ step : Union[float, NoUpdate], optional
1211
+ New step size for the slider
1263
1212
 
1264
1213
  Examples
1265
1214
  --------
1266
- >>> viewer.add_float_range('price_range',
1267
- ... value=(10.0, 20.0),
1268
- ... min_value=0.0, max_value=100.0, step=0.5)
1269
- >>> # Update just the range (values will be rounded and swapped if needed)
1270
- >>> viewer.update_float_range('price_range', value=(15.7, 14.2)) # Becomes (14.0, 15.5)
1271
- >>> # Update bounds and step size
1272
- >>> viewer.update_float_range('price_range',
1273
- ... min_value=5.0, max_value=50.0, step=0.1)
1215
+ >>> viewer.update_float_range('temp_range', value=(97.5, 98.5)) # Update just the values
1216
+
1217
+ >>> viewer.update_float_range(
1218
+ ... 'price_range',
1219
+ ... min=10.0,
1220
+ ... max=500.0,
1221
+ ... step=0.5
1222
+ ... ) # Update bounds and step
1274
1223
  """
1275
1224
  updates = {}
1276
- if not value == _NO_UPDATE:
1277
- updates["value"] = value
1278
- if not min_value == _NO_UPDATE:
1279
- updates["min_value"] = min_value
1280
- if not max_value == _NO_UPDATE:
1281
- updates["max_value"] = max_value
1282
- if not step == _NO_UPDATE:
1283
- updates["step"] = step
1284
- if updates:
1285
- self.parameters[name].update(updates)
1225
+ if not isinstance(value, NoUpdate):
1226
+ val_low, val_high = value
1227
+ updates["value"] = (float(val_low), float(val_high))
1228
+ if not isinstance(min, NoUpdate):
1229
+ updates["min"] = float(min)
1230
+ if not isinstance(max, NoUpdate):
1231
+ updates["max"] = float(max)
1232
+ if not isinstance(step, NoUpdate):
1233
+ updates["step"] = float(step)
1234
+
1235
+ parameter = self.parameters[name]
1236
+ parameter.update(updates)
1286
1237
 
1287
1238
  @validate_parameter_operation("update", ParameterType.unbounded_integer)
1288
1239
  def update_unbounded_integer(
1289
1240
  self,
1290
1241
  name: str,
1291
1242
  *,
1292
- value: Union[int, _NoUpdate] = _NO_UPDATE,
1243
+ value: Union[int, NoUpdate] = NO_UPDATE,
1293
1244
  ) -> None:
1294
1245
  """
1295
1246
  Update an unbounded integer parameter's value and/or bounds.
@@ -1301,7 +1252,7 @@ class Viewer:
1301
1252
  ----------
1302
1253
  name : str
1303
1254
  Name of the unbounded integer parameter to update
1304
- value : int, optional
1255
+ value : Union[int, NoUpdate], optional
1305
1256
  New value (if not provided, no change)
1306
1257
 
1307
1258
  Examples
@@ -1311,7 +1262,7 @@ class Viewer:
1311
1262
  >>> viewer.update_unbounded_integer('population', value=2000000)
1312
1263
  """
1313
1264
  updates = {}
1314
- if not value == _NO_UPDATE:
1265
+ if not value == NO_UPDATE:
1315
1266
  updates["value"] = value
1316
1267
  if updates:
1317
1268
  self.parameters[name].update(updates)
@@ -1321,8 +1272,8 @@ class Viewer:
1321
1272
  self,
1322
1273
  name: str,
1323
1274
  *,
1324
- value: Union[float, _NoUpdate] = _NO_UPDATE,
1325
- step: Union[Optional[float], _NoUpdate] = _NO_UPDATE,
1275
+ value: Union[float, NoUpdate] = NO_UPDATE,
1276
+ step: Union[Optional[float], NoUpdate] = NO_UPDATE,
1326
1277
  ) -> None:
1327
1278
  """
1328
1279
  Update an unbounded float parameter's value, bounds, and/or step size.
@@ -1334,9 +1285,9 @@ class Viewer:
1334
1285
  ----------
1335
1286
  name : str
1336
1287
  Name of the unbounded float parameter to update
1337
- value : float, optional
1288
+ value : Union[float, NoUpdate], optional
1338
1289
  New value (will be rounded if step is set) (if not provided, no change)
1339
- step : float or None, optional
1290
+ step : Union[Optional[float], NoUpdate], optional
1340
1291
  New step size for rounding, or None for no rounding (if not provided, no change)
1341
1292
 
1342
1293
  Examples
@@ -1350,9 +1301,9 @@ class Viewer:
1350
1301
  >>> viewer.update_unbounded_float('wavelength', step=None)
1351
1302
  """
1352
1303
  updates = {}
1353
- if not value == _NO_UPDATE:
1304
+ if not value == NO_UPDATE:
1354
1305
  updates["value"] = value
1355
- if not step == _NO_UPDATE:
1306
+ if not step == NO_UPDATE:
1356
1307
  updates["step"] = step
1357
1308
  if updates:
1358
1309
  self.parameters[name].update(updates)
@@ -1362,8 +1313,8 @@ class Viewer:
1362
1313
  self,
1363
1314
  name: str,
1364
1315
  *,
1365
- label: Union[str, _NoUpdate] = _NO_UPDATE,
1366
- callback: Union[Callable[[], None], _NoUpdate] = _NO_UPDATE,
1316
+ label: Union[str, NoUpdate] = NO_UPDATE,
1317
+ callback: Union[Callable[[], None], NoUpdate] = NO_UPDATE,
1367
1318
  ) -> None:
1368
1319
  """
1369
1320
  Update a button parameter's label and/or callback function.
@@ -1375,9 +1326,9 @@ class Viewer:
1375
1326
  ----------
1376
1327
  name : str
1377
1328
  Name of the button parameter to update
1378
- label : str, optional
1329
+ label : Union[str, NoUpdate], optional
1379
1330
  New text to display on the button (if not provided, no change)
1380
- callback : callable, optional
1331
+ callback : Union[callable, NoUpdate], optional
1381
1332
  New function to call when clicked (if not provided, no change)
1382
1333
 
1383
1334
  Examples
@@ -1389,13 +1340,21 @@ class Viewer:
1389
1340
  ... callback=new_callback)
1390
1341
  """
1391
1342
  updates = {}
1392
- if not label == _NO_UPDATE:
1343
+ if not label == NO_UPDATE:
1393
1344
  updates["label"] = label
1394
- if not callback == _NO_UPDATE:
1395
- callback = self._prepare_function(
1396
- callback,
1397
- context="Updating button callback:",
1398
- )
1399
- updates["callback"] = callback
1345
+ if not callback == NO_UPDATE:
1346
+ try:
1347
+ callback = self._prepare_function(
1348
+ callback,
1349
+ context="Updating button callback:",
1350
+ )
1351
+ except Exception as e:
1352
+ raise ParameterUpdateError(
1353
+ name,
1354
+ "button",
1355
+ str(e),
1356
+ ) from e
1357
+ else:
1358
+ updates["callback"] = callback
1400
1359
  if updates:
1401
1360
  self.parameters[name].update(updates)