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/__init__.py +1 -1
- syd/flask_deployment/__init__.py +7 -1
- syd/flask_deployment/deployer.py +548 -209
- syd/flask_deployment/static/__init__.py +1 -0
- syd/flask_deployment/static/css/styles.css +246 -0
- syd/flask_deployment/static/js/viewer.js +710 -140
- syd/flask_deployment/templates/__init__.py +1 -0
- syd/flask_deployment/templates/index.html +34 -0
- syd/flask_deployment/testing_principles.md +4 -4
- syd/notebook_deployment/deployer.py +15 -5
- syd/notebook_deployment/widgets.py +76 -58
- syd/parameters.py +239 -250
- syd/support.py +168 -0
- syd/viewer.py +305 -346
- syd-0.2.0.dist-info/METADATA +126 -0
- syd-0.2.0.dist-info/RECORD +19 -0
- syd/flask_deployment/components.py +0 -510
- syd/flask_deployment/static/css/viewer.css +0 -82
- syd/flask_deployment/templates/base.html +0 -29
- syd/flask_deployment/templates/viewer.html +0 -51
- syd/notebook_deployment/_ipympl_deployer.py +0 -258
- syd/plotly_deployment/__init__.py +0 -1
- syd/plotly_deployment/components.py +0 -531
- syd/plotly_deployment/deployer.py +0 -376
- syd-0.1.7.dist-info/METADATA +0 -120
- syd-0.1.7.dist-info/RECORD +0 -22
- {syd-0.1.7.dist-info → syd-0.2.0.dist-info}/WHEEL +0 -0
- {syd-0.1.7.dist-info → syd-0.2.0.dist-info}/licenses/LICENSE +0 -0
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,
|
|
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
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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
|
-
|
|
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,
|
|
220
|
-
>>> param.update({"value": 25.0, "
|
|
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,
|
|
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
|
|
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__(
|
|
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
|
-
|
|
462
|
-
|
|
463
|
-
|
|
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
|
-
|
|
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 :
|
|
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__(
|
|
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
|
|
633
|
-
|
|
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
|
-
|
|
601
|
+
max : int
|
|
636
602
|
Maximum allowed value
|
|
637
603
|
|
|
638
604
|
Examples
|
|
639
605
|
--------
|
|
640
|
-
>>> age = IntegerParameter("age", value=25,
|
|
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
|
|
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
|
|
612
|
+
>>> age.update({"value": -10}) # Will be clamped to min
|
|
647
613
|
>>> age.value
|
|
648
614
|
0
|
|
649
615
|
"""
|
|
650
616
|
|
|
651
|
-
|
|
652
|
-
|
|
617
|
+
min: int
|
|
618
|
+
max: int
|
|
653
619
|
|
|
654
620
|
def __init__(
|
|
655
621
|
self,
|
|
656
622
|
name: str,
|
|
657
|
-
value: int,
|
|
658
|
-
|
|
659
|
-
|
|
623
|
+
value: Union[int, NoInitialValue],
|
|
624
|
+
min: int,
|
|
625
|
+
max: int,
|
|
660
626
|
):
|
|
661
627
|
self.name = name
|
|
662
|
-
self.
|
|
663
|
-
self.
|
|
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.
|
|
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.
|
|
659
|
+
f"Value {new_value} below minimum {self.min}, clamping",
|
|
692
660
|
)
|
|
693
661
|
)
|
|
694
|
-
new_value = self.
|
|
695
|
-
if new_value > self.
|
|
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.
|
|
668
|
+
f"Value {new_value} above maximum {self.max}, clamping",
|
|
701
669
|
)
|
|
702
670
|
)
|
|
703
|
-
new_value = self.
|
|
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
|
|
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.
|
|
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
|
|
688
|
+
"IntegerParameter must have both min and max bounds",
|
|
721
689
|
)
|
|
722
|
-
if self.
|
|
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.
|
|
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
|
|
749
|
-
|
|
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
|
-
|
|
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
|
-
...
|
|
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
|
|
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
|
-
|
|
778
|
-
|
|
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
|
-
|
|
786
|
-
|
|
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.
|
|
792
|
-
self.
|
|
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.
|
|
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.
|
|
795
|
+
f"Value {new_value} below minimum {self.min}, clamping",
|
|
826
796
|
)
|
|
827
797
|
)
|
|
828
|
-
new_value = self.
|
|
829
|
-
if new_value > self.
|
|
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.
|
|
804
|
+
f"Value {new_value} above maximum {self.max}, clamping",
|
|
835
805
|
)
|
|
836
806
|
)
|
|
837
|
-
new_value = self.
|
|
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
|
|
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.
|
|
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
|
|
825
|
+
"FloatParameter must have both min and max bounds",
|
|
856
826
|
)
|
|
857
|
-
if self.
|
|
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.
|
|
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 :
|
|
852
|
+
value : Union[Tuple[int, int], NoInitialValue]
|
|
883
853
|
Initial (low, high) values
|
|
884
|
-
|
|
854
|
+
min : int
|
|
885
855
|
Minimum allowed value for both low and high
|
|
886
|
-
|
|
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),
|
|
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
|
-
|
|
904
|
-
|
|
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
|
-
|
|
911
|
-
|
|
879
|
+
value: Union[Tuple[int, int], NoInitialValue],
|
|
880
|
+
min: int,
|
|
881
|
+
max: int,
|
|
912
882
|
):
|
|
913
883
|
self.name = name
|
|
914
|
-
self.
|
|
915
|
-
self.
|
|
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.
|
|
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.
|
|
949
|
+
f"Low value {low} below minimum {self.min}, clamping",
|
|
978
950
|
)
|
|
979
951
|
)
|
|
980
|
-
low = self.
|
|
981
|
-
if high > self.
|
|
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.
|
|
958
|
+
f"High value {high} above maximum {self.max}, clamping",
|
|
987
959
|
)
|
|
988
960
|
)
|
|
989
|
-
high = self.
|
|
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
|
|
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.
|
|
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
|
|
979
|
+
"IntegerRangeParameter must have both min and max bounds",
|
|
1008
980
|
)
|
|
1009
|
-
if self.
|
|
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.
|
|
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 :
|
|
1006
|
+
value : Union[Tuple[float, float], NoInitialValue]
|
|
1035
1007
|
Initial (low, high) values
|
|
1036
|
-
|
|
1008
|
+
min : float
|
|
1037
1009
|
Minimum allowed value for both low and high
|
|
1038
|
-
|
|
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),
|
|
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
|
-
|
|
1065
|
-
|
|
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
|
-
|
|
1073
|
-
|
|
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.
|
|
1079
|
-
self.
|
|
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.
|
|
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.
|
|
1119
|
+
f"Low value {low} below minimum {self.min}, clamping",
|
|
1146
1120
|
)
|
|
1147
1121
|
)
|
|
1148
|
-
low = self.
|
|
1149
|
-
if high > self.
|
|
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.
|
|
1128
|
+
f"High value {high} above maximum {self.max}, clamping",
|
|
1155
1129
|
)
|
|
1156
1130
|
)
|
|
1157
|
-
high = self.
|
|
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
|
|
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.
|
|
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
|
|
1149
|
+
"FloatRangeParameter must have both min and max bounds",
|
|
1176
1150
|
)
|
|
1177
|
-
if self.
|
|
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.
|
|
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
|
|
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__(
|
|
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
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
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
|