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/parameters.py CHANGED
@@ -1,140 +1,19 @@
1
1
  from typing import List, Any, Tuple, Generic, TypeVar, Optional, Dict, Callable, Union
2
2
  from dataclasses import dataclass, field
3
- from abc import ABC, ABCMeta, abstractmethod
3
+ from abc import ABC, abstractmethod
4
4
  from enum import Enum
5
5
  from copy import deepcopy
6
6
  from warnings import warn
7
- import numpy as np
8
7
 
9
- T = TypeVar("T")
10
-
11
-
12
- # Keep original Parameter class and exceptions unchanged
13
- class ParameterAddError(Exception):
14
- """
15
- Exception raised when there is an error creating a new parameter.
16
-
17
- Parameters
18
- ----------
19
- parameter_name : str
20
- Name of the parameter that failed to be created
21
- parameter_type : str
22
- Type of the parameter that failed to be created
23
- message : str, optional
24
- Additional error details
25
- """
26
-
27
- def __init__(self, parameter_name: str, parameter_type: str, message: str = None):
28
- self.parameter_name = parameter_name
29
- self.parameter_type = parameter_type
30
- super().__init__(
31
- f"Failed to create {parameter_type} parameter '{parameter_name}'"
32
- + (f": {message}" if message else "")
33
- )
34
-
35
-
36
- class ParameterUpdateError(Exception):
37
- """
38
- Exception raised when there is an error updating an existing parameter.
39
-
40
- Parameters
41
- ----------
42
- parameter_name : str
43
- Name of the parameter that failed to update
44
- parameter_type : str
45
- Type of the parameter that failed to update
46
- message : str, optional
47
- Additional error details
48
- """
49
-
50
- def __init__(self, parameter_name: str, parameter_type: str, message: str = None):
51
- self.parameter_name = parameter_name
52
- self.parameter_type = parameter_type
53
- super().__init__(
54
- f"Failed to update {parameter_type} parameter '{parameter_name}'"
55
- + (f": {message}" if message else "")
56
- )
57
-
58
-
59
- class ParameterUpdateWarning(Warning):
60
- """
61
- Warning raised when there is a non-critical issue updating a parameter.
62
-
63
- Parameters
64
- ----------
65
- parameter_name : str
66
- Name of the parameter that had the warning
67
- parameter_type : str
68
- Type of the parameter
69
- message : str, optional
70
- Additional warning details
71
- """
72
-
73
- def __init__(self, parameter_name: str, parameter_type: str, message: str = None):
74
- self.parameter_name = parameter_name
75
- self.parameter_type = parameter_type
76
- super().__init__(
77
- f"Warning updating {parameter_type} parameter '{parameter_name}'"
78
- + (f": {message}" if message else "")
79
- )
80
-
81
-
82
- def get_parameter_attributes(param_class) -> List[str]:
83
- """
84
- Get all valid attributes for a parameter class.
85
-
86
- Parameters
87
- ----------
88
- param_class : class
89
- The parameter class to inspect
90
-
91
- Returns
92
- -------
93
- list of str
94
- Names of all valid attributes for the parameter class
95
- """
96
- attributes = []
97
-
98
- # Walk through class hierarchy in reverse (most specific to most general)
99
- for cls in reversed(param_class.__mro__):
100
- if hasattr(cls, "__annotations__"):
101
- # Only add annotations that haven't been specified by a more specific class
102
- for name in cls.__annotations__:
103
- if not name.startswith("_"):
104
- attributes.append(name)
105
-
106
- return attributes
107
-
108
-
109
- class ParameterMeta(ABCMeta):
110
- _parameter_types = {}
111
- _parameter_ids = {} # Store unique identifiers for our parameter types
8
+ from .support import (
9
+ NoInitialValue,
10
+ ParameterMeta,
11
+ ParameterUpdateError,
12
+ ParameterUpdateWarning,
13
+ get_parameter_attributes,
14
+ )
112
15
 
113
- def __new__(cls, name, bases, namespace):
114
- parameter_class = super().__new__(cls, name, bases, namespace)
115
- if name != "Parameter":
116
- # Generate a unique ID for this parameter type
117
- type_id = f"syd.parameters.{name}" # Using fully qualified name
118
- cls._parameter_ids[name] = type_id
119
-
120
- # Add ID to the class
121
- if not hasattr(parameter_class, "_parameter_type_id"):
122
- setattr(parameter_class, "_parameter_type_id", type_id)
123
- else:
124
- if getattr(parameter_class, "_parameter_type_id") != type_id:
125
- raise ValueError(
126
- f"Parameter type {name} has multiple IDs: {type_id} and {getattr(parameter_class, '_parameter_type_id')}"
127
- )
128
- cls._parameter_types[name] = parameter_class
129
- return parameter_class
130
-
131
- def __instancecheck__(cls, instance):
132
- type_id = cls._parameter_ids.get(cls.__name__)
133
- if not type_id:
134
- return False
135
-
136
- # Check if instance has our type ID
137
- return getattr(instance.__class__, "_parameter_type_id", None) == type_id
16
+ T = TypeVar("T")
138
17
 
139
18
 
140
19
  @dataclass
@@ -216,8 +95,8 @@ class Parameter(Generic[T], ABC, metaclass=ParameterMeta):
216
95
 
217
96
  Examples
218
97
  --------
219
- >>> param = FloatParameter("temperature", 20.0, min_value=0, max_value=100)
220
- >>> param.update({"value": 25.0, "max_value": 150})
98
+ >>> param = FloatParameter("temperature", 20.0, min=0, max=100)
99
+ >>> param.update({"value": 25.0, "max": 150})
221
100
  """
222
101
  param_copy = deepcopy(self)
223
102
 
@@ -292,7 +171,7 @@ class TextParameter(Parameter[str]):
292
171
  ----------
293
172
  name : str
294
173
  The name of the parameter
295
- value : str
174
+ value : Union[str, NoInitialValue]
296
175
  The initial text value
297
176
 
298
177
  Examples
@@ -305,8 +184,10 @@ class TextParameter(Parameter[str]):
305
184
  'Bob'
306
185
  """
307
186
 
308
- def __init__(self, name: str, value: str):
187
+ def __init__(self, name: str, value: Union[str, NoInitialValue]):
309
188
  self.name = name
189
+ if isinstance(value, NoInitialValue):
190
+ value = ""
310
191
  self._value = self._validate(value)
311
192
 
312
193
  def _validate(self, new_value: Any) -> str:
@@ -335,7 +216,7 @@ class BooleanParameter(Parameter[bool]):
335
216
  ----------
336
217
  name : str
337
218
  The name of the parameter
338
- value : bool, optional
219
+ value : Union[bool, NoInitialValue]
339
220
  The initial state (default is True)
340
221
 
341
222
  Examples
@@ -348,8 +229,10 @@ class BooleanParameter(Parameter[bool]):
348
229
  False
349
230
  """
350
231
 
351
- def __init__(self, name: str, value: bool = True):
232
+ def __init__(self, name: str, value: Union[bool, NoInitialValue]):
352
233
  self.name = name
234
+ if isinstance(value, NoInitialValue):
235
+ value = True
353
236
  self._value = self._validate(value)
354
237
 
355
238
  def _validate(self, new_value: Any) -> bool:
@@ -378,7 +261,7 @@ class SelectionParameter(Parameter[Any]):
378
261
  ----------
379
262
  name : str
380
263
  The name of the parameter
381
- value : Any
264
+ value : Union[Any, NoInitialValue]
382
265
  The initially selected value (must be one of the options)
383
266
  options : sequence
384
267
  List, tuple, or 1D numpy array of valid choices that can be selected
@@ -401,9 +284,13 @@ class SelectionParameter(Parameter[Any]):
401
284
 
402
285
  options: List[Any]
403
286
 
404
- def __init__(self, name: str, value: Any, options: Union[List, Tuple]):
287
+ def __init__(
288
+ self, name: str, value: Union[Any, NoInitialValue], options: Union[List, Tuple]
289
+ ):
405
290
  self.name = name
406
291
  self.options = self._validate_options(options)
292
+ if isinstance(value, NoInitialValue):
293
+ value = self.options[0]
407
294
  self._value = self._validate(value)
408
295
 
409
296
  def _validate_options(self, options: Any) -> List[Any]:
@@ -458,9 +345,42 @@ class SelectionParameter(Parameter[Any]):
458
345
  Raises:
459
346
  ValueError: If value is not in options list
460
347
  """
461
- if new_value not in self.options:
462
- raise ValueError(f"Value {new_value} not in options: {self.options}")
463
- return new_value
348
+ # Direct check for non-float values or when new_value is exactly in options
349
+ if new_value in self.options:
350
+ return new_value
351
+
352
+ # Special handling for numeric values to account for type mismatches
353
+ if isinstance(new_value, (int, float)):
354
+ for option in self.options:
355
+ # For numeric options, compare as floats
356
+ if (
357
+ isinstance(option, (int, float))
358
+ and abs(float(new_value) - float(option)) < 1e-10
359
+ ):
360
+ return option
361
+ # Also try string conversion for numeric strings
362
+ elif isinstance(option, str):
363
+ try:
364
+ if abs(float(new_value) - float(option)) < 1e-10:
365
+ return option
366
+ except ValueError:
367
+ pass
368
+
369
+ # Handle string conversion - when new_value is a string but options might be numeric
370
+ if isinstance(new_value, str):
371
+ try:
372
+ # Try to convert to float if possible
373
+ float_value = float(new_value)
374
+ for option in self.options:
375
+ if (
376
+ isinstance(option, (int, float))
377
+ and abs(float_value - float(option)) < 1e-10
378
+ ):
379
+ return option
380
+ except ValueError:
381
+ pass
382
+
383
+ raise ValueError(f"Value {new_value} not in options: {self.options}")
464
384
 
465
385
  def _validate_update(self) -> None:
466
386
  """
@@ -473,7 +393,46 @@ class SelectionParameter(Parameter[Any]):
473
393
  TypeError: If options is not a list or tuple
474
394
  """
475
395
  self.options = self._validate_options(self.options)
476
- if self.value not in self.options:
396
+
397
+ # Check if value is directly in options
398
+ if self.value in self.options:
399
+ return
400
+
401
+ # For numeric values, try flexible comparison
402
+ value_found = False
403
+ if isinstance(self.value, (int, float)):
404
+ for option in self.options:
405
+ if (
406
+ isinstance(option, (int, float))
407
+ and abs(float(self.value) - float(option)) < 1e-10
408
+ ):
409
+ # Don't update self.value here as we want to keep the original type if possible
410
+ value_found = True
411
+ break
412
+ elif isinstance(option, str):
413
+ try:
414
+ if abs(float(self.value) - float(option)) < 1e-10:
415
+ value_found = True
416
+ break
417
+ except ValueError:
418
+ pass
419
+
420
+ # For string values that might be numeric
421
+ if not value_found and isinstance(self.value, str):
422
+ try:
423
+ float_value = float(self.value)
424
+ for option in self.options:
425
+ if (
426
+ isinstance(option, (int, float))
427
+ and abs(float_value - float(option)) < 1e-10
428
+ ):
429
+ value_found = True
430
+ break
431
+ except ValueError:
432
+ pass
433
+
434
+ # If value is not found after all checks, reset to first option
435
+ if not value_found:
477
436
  warn(
478
437
  ParameterUpdateWarning(
479
438
  self.name,
@@ -497,8 +456,8 @@ class MultipleSelectionParameter(Parameter[List[Any]]):
497
456
  ----------
498
457
  name : str
499
458
  The name of the parameter
500
- value : list
501
- List of initially selected values (must all be from options)
459
+ value : Union[List[Any], NoInitialValue]
460
+ List of initially selected values (must all be from options, can be empty)
502
461
  options : sequence
503
462
  List, tuple, or 1D numpy array of valid choices that can be selected
504
463
 
@@ -520,9 +479,16 @@ class MultipleSelectionParameter(Parameter[List[Any]]):
520
479
 
521
480
  options: List[Any]
522
481
 
523
- def __init__(self, name: str, value: List[Any], options: Union[List, Tuple]):
482
+ def __init__(
483
+ self,
484
+ name: str,
485
+ value: Union[List[Any], NoInitialValue],
486
+ options: Union[List, Tuple],
487
+ ):
524
488
  self.name = name
525
489
  self.options = self._validate_options(options)
490
+ if isinstance(value, NoInitialValue):
491
+ value = []
526
492
  self._value = self._validate(value)
527
493
 
528
494
  def _validate_options(self, options: Any) -> List[Any]:
@@ -628,39 +594,41 @@ class IntegerParameter(Parameter[int]):
628
594
  ----------
629
595
  name : str
630
596
  The name of the parameter
631
- value : int
632
- Initial value (will be clamped to fit between min_value and max_value)
633
- min_value : int
597
+ value : Union[int, NoInitialValue]
598
+ Initial value (will be clamped to fit between min and max)
599
+ min : int
634
600
  Minimum allowed value
635
- max_value : int
601
+ max : int
636
602
  Maximum allowed value
637
603
 
638
604
  Examples
639
605
  --------
640
- >>> age = IntegerParameter("age", value=25, min_value=0, max_value=120)
606
+ >>> age = IntegerParameter("age", value=25, min=0, max=120)
641
607
  >>> age.value
642
608
  25
643
- >>> age.update({"value": 150}) # Will be clamped to max_value
609
+ >>> age.update({"value": 150}) # Will be clamped to max
644
610
  >>> age.value
645
611
  120
646
- >>> age.update({"value": -10}) # Will be clamped to min_value
612
+ >>> age.update({"value": -10}) # Will be clamped to min
647
613
  >>> age.value
648
614
  0
649
615
  """
650
616
 
651
- min_value: int
652
- max_value: int
617
+ min: int
618
+ max: int
653
619
 
654
620
  def __init__(
655
621
  self,
656
622
  name: str,
657
- value: int,
658
- min_value: int,
659
- max_value: int,
623
+ value: Union[int, NoInitialValue],
624
+ min: int,
625
+ max: int,
660
626
  ):
661
627
  self.name = name
662
- self.min_value = self._validate(min_value, compare_to_range=False)
663
- self.max_value = self._validate(max_value, compare_to_range=False)
628
+ self.min = self._validate(min, compare_to_range=False)
629
+ self.max = self._validate(max, compare_to_range=False)
630
+ if isinstance(value, NoInitialValue):
631
+ value = self.min
664
632
  self._value = self._validate(value)
665
633
 
666
634
  def _validate(self, new_value: Any, compare_to_range: bool = True) -> int:
@@ -683,43 +651,43 @@ class IntegerParameter(Parameter[int]):
683
651
  raise ValueError(f"Value {new_value} cannot be converted to int")
684
652
 
685
653
  if compare_to_range:
686
- if new_value < self.min_value:
654
+ if new_value < self.min:
687
655
  warn(
688
656
  ParameterUpdateWarning(
689
657
  self.name,
690
658
  type(self).__name__,
691
- f"Value {new_value} below minimum {self.min_value}, clamping",
659
+ f"Value {new_value} below minimum {self.min}, clamping",
692
660
  )
693
661
  )
694
- new_value = self.min_value
695
- if new_value > self.max_value:
662
+ new_value = self.min
663
+ if new_value > self.max:
696
664
  warn(
697
665
  ParameterUpdateWarning(
698
666
  self.name,
699
667
  type(self).__name__,
700
- f"Value {new_value} above maximum {self.max_value}, clamping",
668
+ f"Value {new_value} above maximum {self.max}, clamping",
701
669
  )
702
670
  )
703
- new_value = self.max_value
671
+ new_value = self.max
704
672
  return int(new_value)
705
673
 
706
674
  def _validate_update(self) -> None:
707
675
  """
708
676
  Validate complete parameter state after updates.
709
677
 
710
- Ensures min_value <= max_value, swapping if needed.
678
+ Ensures min <= max, swapping if needed.
711
679
  Re-validates current value against potentially updated bounds.
712
680
 
713
681
  Raises:
714
682
  ParameterUpdateError: If bounds are invalid (e.g. None when required)
715
683
  """
716
- if self.min_value is None or self.max_value is None:
684
+ if self.min is None or self.max is None:
717
685
  raise ParameterUpdateError(
718
686
  self.name,
719
687
  type(self).__name__,
720
- "IntegerParameter must have both min_value and max_value bounds",
688
+ "IntegerParameter must have both min and max bounds",
721
689
  )
722
- if self.min_value > self.max_value:
690
+ if self.min > self.max:
723
691
  warn(
724
692
  ParameterUpdateWarning(
725
693
  self.name,
@@ -727,7 +695,7 @@ class IntegerParameter(Parameter[int]):
727
695
  f"Min value greater than max value, swapping",
728
696
  )
729
697
  )
730
- self.min_value, self.max_value = self.max_value, self.min_value
698
+ self.min, self.max = self.max, self.min
731
699
  self.value = self._validate(self.value)
732
700
 
733
701
 
@@ -744,11 +712,11 @@ class FloatParameter(Parameter[float]):
744
712
  ----------
745
713
  name : str
746
714
  The name of the parameter
747
- value : float
748
- Initial value (will be clamped to fit between min_value and max_value)
749
- min_value : float
715
+ value : Union[float, NoInitialValue]
716
+ Initial value (will be clamped to fit between min and max)
717
+ min : float
750
718
  Minimum allowed value
751
- max_value : float
719
+ max : float
752
720
  Maximum allowed value
753
721
  step : float, optional
754
722
  Size of each increment (default is 0.001)
@@ -756,13 +724,13 @@ class FloatParameter(Parameter[float]):
756
724
  Examples
757
725
  --------
758
726
  >>> temp = FloatParameter("temperature", value=98.6,
759
- ... min_value=95.0, max_value=105.0, step=0.1)
727
+ ... min=95.0, max=105.0, step=0.1)
760
728
  >>> temp.value
761
729
  98.6
762
730
  >>> temp.update({"value": 98.67}) # Will be rounded to nearest step
763
731
  >>> temp.value
764
732
  98.7
765
- >>> temp.update({"value": 110.0}) # Will be clamped to max_value
733
+ >>> temp.update({"value": 110.0}) # Will be clamped to max
766
734
  >>> temp.value
767
735
  105.0
768
736
 
@@ -774,22 +742,24 @@ class FloatParameter(Parameter[float]):
774
742
  - step=5.0 allows values like 0.0, 5.0, 10.0, etc.
775
743
  """
776
744
 
777
- min_value: float
778
- max_value: float
745
+ min: float
746
+ max: float
779
747
  step: float
780
748
 
781
749
  def __init__(
782
750
  self,
783
751
  name: str,
784
- value: float,
785
- min_value: float,
786
- max_value: float,
752
+ value: Union[float, NoInitialValue],
753
+ min: float,
754
+ max: float,
787
755
  step: float = 0.001,
788
756
  ):
789
757
  self.name = name
790
758
  self.step = step
791
- self.min_value = self._validate(min_value, compare_to_range=False)
792
- self.max_value = self._validate(max_value, compare_to_range=False)
759
+ self.min = self._validate(min, compare_to_range=False)
760
+ self.max = self._validate(max, compare_to_range=False)
761
+ if isinstance(value, NoInitialValue):
762
+ value = self.min
793
763
  self._value = self._validate(value)
794
764
 
795
765
  def _validate(self, new_value: Any, compare_to_range: bool = True) -> float:
@@ -817,24 +787,24 @@ class FloatParameter(Parameter[float]):
817
787
  new_value = round(new_value / self.step) * self.step
818
788
 
819
789
  if compare_to_range:
820
- if new_value < self.min_value:
790
+ if new_value < self.min:
821
791
  warn(
822
792
  ParameterUpdateWarning(
823
793
  self.name,
824
794
  type(self).__name__,
825
- f"Value {new_value} below minimum {self.min_value}, clamping",
795
+ f"Value {new_value} below minimum {self.min}, clamping",
826
796
  )
827
797
  )
828
- new_value = self.min_value
829
- if new_value > self.max_value:
798
+ new_value = self.min
799
+ if new_value > self.max:
830
800
  warn(
831
801
  ParameterUpdateWarning(
832
802
  self.name,
833
803
  type(self).__name__,
834
- f"Value {new_value} above maximum {self.max_value}, clamping",
804
+ f"Value {new_value} above maximum {self.max}, clamping",
835
805
  )
836
806
  )
837
- new_value = self.max_value
807
+ new_value = self.max
838
808
 
839
809
  return float(new_value)
840
810
 
@@ -842,19 +812,19 @@ class FloatParameter(Parameter[float]):
842
812
  """
843
813
  Validate complete parameter state after updates.
844
814
 
845
- Ensures min_value <= max_value, swapping if needed.
815
+ Ensures min <= max, swapping if needed.
846
816
  Re-validates current value against potentially updated bounds.
847
817
 
848
818
  Raises:
849
819
  ParameterUpdateError: If bounds are invalid (e.g. None when required)
850
820
  """
851
- if self.min_value is None or self.max_value is None:
821
+ if self.min is None or self.max is None:
852
822
  raise ParameterUpdateError(
853
823
  self.name,
854
824
  type(self).__name__,
855
- "FloatParameter must have both min_value and max_value bounds",
825
+ "FloatParameter must have both min and max bounds",
856
826
  )
857
- if self.min_value > self.max_value:
827
+ if self.min > self.max:
858
828
  warn(
859
829
  ParameterUpdateWarning(
860
830
  self.name,
@@ -862,7 +832,7 @@ class FloatParameter(Parameter[float]):
862
832
  f"Min value greater than max value, swapping",
863
833
  )
864
834
  )
865
- self.min_value, self.max_value = self.max_value, self.min_value
835
+ self.min, self.max = self.max, self.min
866
836
  self.value = self._validate(self.value)
867
837
 
868
838
 
@@ -879,17 +849,17 @@ class IntegerRangeParameter(Parameter[Tuple[int, int]]):
879
849
  ----------
880
850
  name : str
881
851
  The name of the parameter
882
- value : tuple[int, int]
852
+ value : Union[Tuple[int, int], NoInitialValue]
883
853
  Initial (low, high) values
884
- min_value : int
854
+ min : int
885
855
  Minimum allowed value for both low and high
886
- max_value : int
856
+ max : int
887
857
  Maximum allowed value for both low and high
888
858
 
889
859
  Examples
890
860
  --------
891
861
  >>> age_range = IntegerRangeParameter("age_range",
892
- ... value=(25, 35), min_value=18, max_value=100)
862
+ ... value=(25, 35), min=18, max=100)
893
863
  >>> age_range.value
894
864
  (25, 35)
895
865
  >>> age_range.update({"value": (35, 25)}) # Values will be swapped
@@ -900,19 +870,21 @@ class IntegerRangeParameter(Parameter[Tuple[int, int]]):
900
870
  (18, 40)
901
871
  """
902
872
 
903
- min_value: int
904
- max_value: int
873
+ min: int
874
+ max: int
905
875
 
906
876
  def __init__(
907
877
  self,
908
878
  name: str,
909
- value: Tuple[int, int],
910
- min_value: int,
911
- max_value: int,
879
+ value: Union[Tuple[int, int], NoInitialValue],
880
+ min: int,
881
+ max: int,
912
882
  ):
913
883
  self.name = name
914
- self.min_value = self._validate_single(min_value, context="min_value")
915
- self.max_value = self._validate_single(max_value, context="max_value")
884
+ self.min = self._validate_single(min, context="min")
885
+ self.max = self._validate_single(max, context="max")
886
+ if isinstance(value, NoInitialValue):
887
+ value = (self.min, self.max)
916
888
  self._value = self._validate(value)
917
889
 
918
890
  def _validate_single(self, new_value: Any, context: Optional[str] = None) -> int:
@@ -969,24 +941,24 @@ class IntegerRangeParameter(Parameter[Tuple[int, int]]):
969
941
  )
970
942
  low, high = high, low
971
943
 
972
- if low < self.min_value:
944
+ if low < self.min:
973
945
  warn(
974
946
  ParameterUpdateWarning(
975
947
  self.name,
976
948
  type(self).__name__,
977
- f"Low value {low} below minimum {self.min_value}, clamping",
949
+ f"Low value {low} below minimum {self.min}, clamping",
978
950
  )
979
951
  )
980
- low = self.min_value
981
- if high > self.max_value:
952
+ low = self.min
953
+ if high > self.max:
982
954
  warn(
983
955
  ParameterUpdateWarning(
984
956
  self.name,
985
957
  type(self).__name__,
986
- f"High value {high} above maximum {self.max_value}, clamping",
958
+ f"High value {high} above maximum {self.max}, clamping",
987
959
  )
988
960
  )
989
- high = self.max_value
961
+ high = self.max
990
962
 
991
963
  return (low, high)
992
964
 
@@ -994,19 +966,19 @@ class IntegerRangeParameter(Parameter[Tuple[int, int]]):
994
966
  """
995
967
  Validate complete parameter state after updates.
996
968
 
997
- Ensures min_value <= max_value, swapping if needed.
969
+ Ensures min <= max, swapping if needed.
998
970
  Re-validates current value against potentially updated bounds.
999
971
 
1000
972
  Raises:
1001
973
  ParameterUpdateError: If bounds are invalid (e.g. None when required)
1002
974
  """
1003
- if self.min_value is None or self.max_value is None:
975
+ if self.min is None or self.max is None:
1004
976
  raise ParameterUpdateError(
1005
977
  self.name,
1006
978
  type(self).__name__,
1007
- "IntegerRangeParameter must have both min_value and max_value bounds",
979
+ "IntegerRangeParameter must have both min and max bounds",
1008
980
  )
1009
- if self.min_value > self.max_value:
981
+ if self.min > self.max:
1010
982
  warn(
1011
983
  ParameterUpdateWarning(
1012
984
  self.name,
@@ -1014,7 +986,7 @@ class IntegerRangeParameter(Parameter[Tuple[int, int]]):
1014
986
  f"Min value greater than max value, swapping",
1015
987
  )
1016
988
  )
1017
- self.min_value, self.max_value = self.max_value, self.min_value
989
+ self.min, self.max = self.max, self.min
1018
990
  self.value = self._validate(self.value)
1019
991
 
1020
992
 
@@ -1031,11 +1003,11 @@ class FloatRangeParameter(Parameter[Tuple[float, float]]):
1031
1003
  ----------
1032
1004
  name : str
1033
1005
  The name of the parameter
1034
- value : tuple[float, float]
1006
+ value : Union[Tuple[float, float], NoInitialValue]
1035
1007
  Initial (low, high) values
1036
- min_value : float
1008
+ min : float
1037
1009
  Minimum allowed value for both low and high
1038
- max_value : float
1010
+ max : float
1039
1011
  Maximum allowed value for both low and high
1040
1012
  step : float, optional
1041
1013
  Size of each increment (default is 0.001)
@@ -1043,7 +1015,7 @@ class FloatRangeParameter(Parameter[Tuple[float, float]]):
1043
1015
  Examples
1044
1016
  --------
1045
1017
  >>> temp_range = FloatRangeParameter("temperature_range",
1046
- ... value=(98.6, 100.4), min_value=95.0, max_value=105.0, step=0.1)
1018
+ ... value=(98.6, 100.4), min=95.0, max=105.0, step=0.1)
1047
1019
  >>> temp_range.value
1048
1020
  (98.6, 100.4)
1049
1021
  >>> temp_range.update({"value": (98.67, 100.0)}) # Low will be rounded
@@ -1061,22 +1033,24 @@ class FloatRangeParameter(Parameter[Tuple[float, float]]):
1061
1033
  - step=5.0 allows values like 0.0, 5.0, 10.0, etc.
1062
1034
  """
1063
1035
 
1064
- min_value: float
1065
- max_value: float
1036
+ min: float
1037
+ max: float
1066
1038
  step: float
1067
1039
 
1068
1040
  def __init__(
1069
1041
  self,
1070
1042
  name: str,
1071
- value: Tuple[float, float],
1072
- min_value: float,
1073
- max_value: float,
1043
+ value: Union[Tuple[float, float], NoInitialValue],
1044
+ min: float,
1045
+ max: float,
1074
1046
  step: float = 0.001,
1075
1047
  ):
1076
1048
  self.name = name
1077
1049
  self.step = step
1078
- self.min_value = self._validate_single(min_value, context="min_value")
1079
- self.max_value = self._validate_single(max_value, context="max_value")
1050
+ self.min = self._validate_single(min, context="min")
1051
+ self.max = self._validate_single(max, context="max")
1052
+ if isinstance(value, NoInitialValue):
1053
+ value = (self.min, self.max)
1080
1054
  self._value = self._validate(value)
1081
1055
 
1082
1056
  def _validate_single(self, new_value: Any, context: Optional[str] = None) -> float:
@@ -1137,24 +1111,24 @@ class FloatRangeParameter(Parameter[Tuple[float, float]]):
1137
1111
  )
1138
1112
  low, high = high, low
1139
1113
 
1140
- if low < self.min_value:
1114
+ if low < self.min:
1141
1115
  warn(
1142
1116
  ParameterUpdateWarning(
1143
1117
  self.name,
1144
1118
  type(self).__name__,
1145
- f"Low value {low} below minimum {self.min_value}, clamping",
1119
+ f"Low value {low} below minimum {self.min}, clamping",
1146
1120
  )
1147
1121
  )
1148
- low = self.min_value
1149
- if high > self.max_value:
1122
+ low = self.min
1123
+ if high > self.max:
1150
1124
  warn(
1151
1125
  ParameterUpdateWarning(
1152
1126
  self.name,
1153
1127
  type(self).__name__,
1154
- f"High value {high} above maximum {self.max_value}, clamping",
1128
+ f"High value {high} above maximum {self.max}, clamping",
1155
1129
  )
1156
1130
  )
1157
- high = self.max_value
1131
+ high = self.max
1158
1132
 
1159
1133
  return (low, high)
1160
1134
 
@@ -1162,19 +1136,19 @@ class FloatRangeParameter(Parameter[Tuple[float, float]]):
1162
1136
  """
1163
1137
  Validate complete parameter state after updates.
1164
1138
 
1165
- Ensures min_value <= max_value, swapping if needed.
1139
+ Ensures min <= max, swapping if needed.
1166
1140
  Re-validates current value against potentially updated bounds.
1167
1141
 
1168
1142
  Raises:
1169
1143
  ParameterUpdateError: If bounds are invalid (e.g. None when required)
1170
1144
  """
1171
- if self.min_value is None or self.max_value is None:
1145
+ if self.min is None or self.max is None:
1172
1146
  raise ParameterUpdateError(
1173
1147
  self.name,
1174
1148
  type(self).__name__,
1175
- "FloatRangeParameter must have both min_value and max_value bounds",
1149
+ "FloatRangeParameter must have both min and max bounds",
1176
1150
  )
1177
- if self.min_value > self.max_value:
1151
+ if self.min > self.max:
1178
1152
  warn(
1179
1153
  ParameterUpdateWarning(
1180
1154
  self.name,
@@ -1182,7 +1156,7 @@ class FloatRangeParameter(Parameter[Tuple[float, float]]):
1182
1156
  f"Min value greater than max value, swapping",
1183
1157
  )
1184
1158
  )
1185
- self.min_value, self.max_value = self.max_value, self.min_value
1159
+ self.min, self.max = self.max, self.min
1186
1160
  self.value = self._validate(self.value)
1187
1161
 
1188
1162
 
@@ -1199,7 +1173,7 @@ class UnboundedIntegerParameter(Parameter[int]):
1199
1173
  ----------
1200
1174
  name : str
1201
1175
  The name of the parameter
1202
- value : int
1176
+ value : Union[int, NoInitialValue]
1203
1177
  Initial value
1204
1178
 
1205
1179
  Examples
@@ -1221,9 +1195,11 @@ class UnboundedIntegerParameter(Parameter[int]):
1221
1195
  def __init__(
1222
1196
  self,
1223
1197
  name: str,
1224
- value: int,
1198
+ value: Union[int, NoInitialValue],
1225
1199
  ):
1226
1200
  self.name = name
1201
+ if isinstance(value, NoInitialValue):
1202
+ value = 0
1227
1203
  self._value = self._validate(value)
1228
1204
 
1229
1205
  def _validate(self, new_value: Any) -> int:
@@ -1269,7 +1245,7 @@ class UnboundedFloatParameter(Parameter[float]):
1269
1245
  ----------
1270
1246
  name : str
1271
1247
  The name of the parameter
1272
- value : float
1248
+ value : Union[float, NoInitialValue]
1273
1249
  Initial value
1274
1250
  step : float, optional
1275
1251
  Size of each increment (default is None, meaning no rounding)
@@ -1300,11 +1276,13 @@ class UnboundedFloatParameter(Parameter[float]):
1300
1276
  def __init__(
1301
1277
  self,
1302
1278
  name: str,
1303
- value: float,
1279
+ value: Union[float, NoInitialValue],
1304
1280
  step: Optional[float] = None,
1305
1281
  ):
1306
1282
  self.name = name
1307
1283
  self.step = step
1284
+ if isinstance(value, NoInitialValue):
1285
+ value = 0
1308
1286
  self._value = self._validate(value)
1309
1287
 
1310
1288
  def _validate(self, new_value: Any) -> float:
@@ -1336,7 +1314,7 @@ class UnboundedFloatParameter(Parameter[float]):
1336
1314
  """
1337
1315
  Validate complete parameter state after updates.
1338
1316
 
1339
- Ensures min_value <= max_value, swapping if needed.
1317
+ Ensures min <= max, swapping if needed.
1340
1318
  Re-validates current value against potentially updated bounds.
1341
1319
 
1342
1320
  Raises:
@@ -1358,8 +1336,8 @@ class ButtonAction(Parameter[None]):
1358
1336
  ----------
1359
1337
  name : str
1360
1338
  The name of the parameter
1361
- label : str
1362
- Text to display on the button
1339
+ label : Union[str, NoInitialValue]
1340
+ Text to display on the button (default is the button's name)
1363
1341
  callback : callable
1364
1342
  Function to execute when the button is clicked
1365
1343
 
@@ -1391,16 +1369,27 @@ class ButtonAction(Parameter[None]):
1391
1369
  value: None = field(default=None, repr=False)
1392
1370
  _is_action: bool = field(default=True, repr=False)
1393
1371
 
1394
- def __init__(self, name: str, label: str, callback: Callable):
1372
+ def __init__(
1373
+ self,
1374
+ name: str,
1375
+ label: Union[str, NoInitialValue],
1376
+ callback: Callable,
1377
+ ):
1395
1378
  """
1396
1379
  Initialize a button.
1397
1380
 
1398
- Args:
1399
- name: Internal name of the parameter
1400
- label: Text to display on the button
1401
- callback: Function to call when button is clicked
1381
+ Parameters
1382
+ ----------
1383
+ name : str
1384
+ The name of the parameter
1385
+ label : Union[str, NoInitialValue]
1386
+ Text to display on the button (default is the button's name)
1387
+ callback : callable
1388
+ Function to execute when the button is clicked
1402
1389
  """
1403
1390
  self.name = name
1391
+ if isinstance(label, NoInitialValue):
1392
+ label = name
1404
1393
  self.label = label
1405
1394
  self.callback = callback
1406
1395
  self._value = None