syd 0.1.6__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 +3 -3
- syd/flask_deployment/__init__.py +7 -0
- syd/flask_deployment/deployer.py +594 -291
- syd/flask_deployment/static/__init__.py +1 -0
- syd/flask_deployment/static/css/styles.css +226 -19
- syd/flask_deployment/static/js/viewer.js +744 -0
- syd/flask_deployment/templates/__init__.py +1 -0
- syd/flask_deployment/templates/index.html +34 -0
- syd/flask_deployment/testing_principles.md +300 -0
- syd/notebook_deployment/__init__.py +1 -1
- syd/notebook_deployment/deployer.py +139 -53
- syd/notebook_deployment/widgets.py +214 -123
- syd/parameters.py +295 -393
- syd/support.py +168 -0
- syd/{interactive_viewer.py → viewer.py} +393 -470
- syd-0.2.0.dist-info/METADATA +126 -0
- syd-0.2.0.dist-info/RECORD +19 -0
- syd/flask_deployment/components.py +0 -497
- syd/flask_deployment/static/js/components.js +0 -51
- syd/flask_deployment/templates/base.html +0 -26
- syd/flask_deployment/templates/viewer.html +0 -97
- syd-0.1.6.dist-info/METADATA +0 -106
- syd-0.1.6.dist-info/RECORD +0 -18
- {syd-0.1.6.dist-info → syd-0.2.0.dist-info}/WHEEL +0 -0
- {syd-0.1.6.dist-info → syd-0.2.0.dist-info}/licenses/LICENSE +0 -0
syd/parameters.py
CHANGED
|
@@ -1,124 +1,23 @@
|
|
|
1
|
-
from typing import
|
|
2
|
-
List,
|
|
3
|
-
Any,
|
|
4
|
-
Tuple,
|
|
5
|
-
Generic,
|
|
6
|
-
TypeVar,
|
|
7
|
-
Optional,
|
|
8
|
-
Dict,
|
|
9
|
-
Callable,
|
|
10
|
-
Union,
|
|
11
|
-
Sequence,
|
|
12
|
-
)
|
|
1
|
+
from typing import List, Any, Tuple, Generic, TypeVar, Optional, Dict, Callable, Union
|
|
13
2
|
from dataclasses import dataclass, field
|
|
14
3
|
from abc import ABC, abstractmethod
|
|
15
4
|
from enum import Enum
|
|
16
5
|
from copy import deepcopy
|
|
17
6
|
from warnings import warn
|
|
18
|
-
import numpy as np
|
|
19
|
-
|
|
20
|
-
T = TypeVar("T")
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
# Keep original Parameter class and exceptions unchanged
|
|
24
|
-
class ParameterAddError(Exception):
|
|
25
|
-
"""
|
|
26
|
-
Exception raised when there is an error creating a new parameter.
|
|
27
|
-
|
|
28
|
-
Parameters
|
|
29
|
-
----------
|
|
30
|
-
parameter_name : str
|
|
31
|
-
Name of the parameter that failed to be created
|
|
32
|
-
parameter_type : str
|
|
33
|
-
Type of the parameter that failed to be created
|
|
34
|
-
message : str, optional
|
|
35
|
-
Additional error details
|
|
36
|
-
"""
|
|
37
|
-
|
|
38
|
-
def __init__(self, parameter_name: str, parameter_type: str, message: str = None):
|
|
39
|
-
self.parameter_name = parameter_name
|
|
40
|
-
self.parameter_type = parameter_type
|
|
41
|
-
super().__init__(
|
|
42
|
-
f"Failed to create {parameter_type} parameter '{parameter_name}'"
|
|
43
|
-
+ (f": {message}" if message else "")
|
|
44
|
-
)
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
class ParameterUpdateError(Exception):
|
|
48
|
-
"""
|
|
49
|
-
Exception raised when there is an error updating an existing parameter.
|
|
50
|
-
|
|
51
|
-
Parameters
|
|
52
|
-
----------
|
|
53
|
-
parameter_name : str
|
|
54
|
-
Name of the parameter that failed to update
|
|
55
|
-
parameter_type : str
|
|
56
|
-
Type of the parameter that failed to update
|
|
57
|
-
message : str, optional
|
|
58
|
-
Additional error details
|
|
59
|
-
"""
|
|
60
|
-
|
|
61
|
-
def __init__(self, parameter_name: str, parameter_type: str, message: str = None):
|
|
62
|
-
self.parameter_name = parameter_name
|
|
63
|
-
self.parameter_type = parameter_type
|
|
64
|
-
super().__init__(
|
|
65
|
-
f"Failed to update {parameter_type} parameter '{parameter_name}'"
|
|
66
|
-
+ (f": {message}" if message else "")
|
|
67
|
-
)
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
class ParameterUpdateWarning(Warning):
|
|
71
|
-
"""
|
|
72
|
-
Warning raised when there is a non-critical issue updating a parameter.
|
|
73
|
-
|
|
74
|
-
Parameters
|
|
75
|
-
----------
|
|
76
|
-
parameter_name : str
|
|
77
|
-
Name of the parameter that had the warning
|
|
78
|
-
parameter_type : str
|
|
79
|
-
Type of the parameter
|
|
80
|
-
message : str, optional
|
|
81
|
-
Additional warning details
|
|
82
|
-
"""
|
|
83
|
-
|
|
84
|
-
def __init__(self, parameter_name: str, parameter_type: str, message: str = None):
|
|
85
|
-
self.parameter_name = parameter_name
|
|
86
|
-
self.parameter_type = parameter_type
|
|
87
|
-
super().__init__(
|
|
88
|
-
f"Warning updating {parameter_type} parameter '{parameter_name}'"
|
|
89
|
-
+ (f": {message}" if message else "")
|
|
90
|
-
)
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
def get_parameter_attributes(param_class) -> List[str]:
|
|
94
|
-
"""
|
|
95
|
-
Get all valid attributes for a parameter class.
|
|
96
|
-
|
|
97
|
-
Parameters
|
|
98
|
-
----------
|
|
99
|
-
param_class : class
|
|
100
|
-
The parameter class to inspect
|
|
101
7
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
# Walk through class hierarchy in reverse (most specific to most general)
|
|
110
|
-
for cls in reversed(param_class.__mro__):
|
|
111
|
-
if hasattr(cls, "__annotations__"):
|
|
112
|
-
# Only add annotations that haven't been specified by a more specific class
|
|
113
|
-
for name in cls.__annotations__:
|
|
114
|
-
if not name.startswith("_"):
|
|
115
|
-
attributes.append(name)
|
|
8
|
+
from .support import (
|
|
9
|
+
NoInitialValue,
|
|
10
|
+
ParameterMeta,
|
|
11
|
+
ParameterUpdateError,
|
|
12
|
+
ParameterUpdateWarning,
|
|
13
|
+
get_parameter_attributes,
|
|
14
|
+
)
|
|
116
15
|
|
|
117
|
-
|
|
16
|
+
T = TypeVar("T")
|
|
118
17
|
|
|
119
18
|
|
|
120
19
|
@dataclass
|
|
121
|
-
class Parameter(Generic[T], ABC):
|
|
20
|
+
class Parameter(Generic[T], ABC, metaclass=ParameterMeta):
|
|
122
21
|
"""
|
|
123
22
|
Base class for all parameter types. Parameters are the building blocks
|
|
124
23
|
for creating interactive GUI elements.
|
|
@@ -196,8 +95,8 @@ class Parameter(Generic[T], ABC):
|
|
|
196
95
|
|
|
197
96
|
Examples
|
|
198
97
|
--------
|
|
199
|
-
>>> param = FloatParameter("temperature", 20.0,
|
|
200
|
-
>>> param.update({"value": 25.0, "
|
|
98
|
+
>>> param = FloatParameter("temperature", 20.0, min=0, max=100)
|
|
99
|
+
>>> param.update({"value": 25.0, "max": 150})
|
|
201
100
|
"""
|
|
202
101
|
param_copy = deepcopy(self)
|
|
203
102
|
|
|
@@ -265,14 +164,14 @@ class TextParameter(Parameter[str]):
|
|
|
265
164
|
Parameter for text input.
|
|
266
165
|
|
|
267
166
|
Creates a text box in the GUI that accepts any string input.
|
|
268
|
-
See :meth:`~syd.
|
|
269
|
-
:meth:`~syd.
|
|
167
|
+
See :meth:`~syd.viewer.Viewer.add_text` and
|
|
168
|
+
:meth:`~syd.viewer.Viewer.update_text` for usage.
|
|
270
169
|
|
|
271
170
|
Parameters
|
|
272
171
|
----------
|
|
273
172
|
name : str
|
|
274
173
|
The name of the parameter
|
|
275
|
-
value : str
|
|
174
|
+
value : Union[str, NoInitialValue]
|
|
276
175
|
The initial text value
|
|
277
176
|
|
|
278
177
|
Examples
|
|
@@ -285,8 +184,10 @@ class TextParameter(Parameter[str]):
|
|
|
285
184
|
'Bob'
|
|
286
185
|
"""
|
|
287
186
|
|
|
288
|
-
def __init__(self, name: str, value: str):
|
|
187
|
+
def __init__(self, name: str, value: Union[str, NoInitialValue]):
|
|
289
188
|
self.name = name
|
|
189
|
+
if isinstance(value, NoInitialValue):
|
|
190
|
+
value = ""
|
|
290
191
|
self._value = self._validate(value)
|
|
291
192
|
|
|
292
193
|
def _validate(self, new_value: Any) -> str:
|
|
@@ -308,14 +209,14 @@ class BooleanParameter(Parameter[bool]):
|
|
|
308
209
|
Parameter for boolean values.
|
|
309
210
|
|
|
310
211
|
Creates a checkbox in the GUI that can be toggled on/off.
|
|
311
|
-
See :meth:`~syd.
|
|
312
|
-
:meth:`~syd.
|
|
212
|
+
See :meth:`~syd.viewer.Viewer.add_boolean` and
|
|
213
|
+
:meth:`~syd.viewer.Viewer.update_boolean` for usage.
|
|
313
214
|
|
|
314
215
|
Parameters
|
|
315
216
|
----------
|
|
316
217
|
name : str
|
|
317
218
|
The name of the parameter
|
|
318
|
-
value : bool,
|
|
219
|
+
value : Union[bool, NoInitialValue]
|
|
319
220
|
The initial state (default is True)
|
|
320
221
|
|
|
321
222
|
Examples
|
|
@@ -328,8 +229,10 @@ class BooleanParameter(Parameter[bool]):
|
|
|
328
229
|
False
|
|
329
230
|
"""
|
|
330
231
|
|
|
331
|
-
def __init__(self, name: str, value: bool
|
|
232
|
+
def __init__(self, name: str, value: Union[bool, NoInitialValue]):
|
|
332
233
|
self.name = name
|
|
234
|
+
if isinstance(value, NoInitialValue):
|
|
235
|
+
value = True
|
|
333
236
|
self._value = self._validate(value)
|
|
334
237
|
|
|
335
238
|
def _validate(self, new_value: Any) -> bool:
|
|
@@ -351,14 +254,14 @@ class SelectionParameter(Parameter[Any]):
|
|
|
351
254
|
Parameter for single selection from a list of options.
|
|
352
255
|
|
|
353
256
|
Creates a dropdown menu in the GUI where users can select one option.
|
|
354
|
-
See :meth:`~syd.
|
|
355
|
-
:meth:`~syd.
|
|
257
|
+
See :meth:`~syd.viewer.Viewer.add_selection` and
|
|
258
|
+
:meth:`~syd.viewer.Viewer.update_selection` for usage.
|
|
356
259
|
|
|
357
260
|
Parameters
|
|
358
261
|
----------
|
|
359
262
|
name : str
|
|
360
263
|
The name of the parameter
|
|
361
|
-
value : Any
|
|
264
|
+
value : Union[Any, NoInitialValue]
|
|
362
265
|
The initially selected value (must be one of the options)
|
|
363
266
|
options : sequence
|
|
364
267
|
List, tuple, or 1D numpy array of valid choices that can be selected
|
|
@@ -381,9 +284,13 @@ class SelectionParameter(Parameter[Any]):
|
|
|
381
284
|
|
|
382
285
|
options: List[Any]
|
|
383
286
|
|
|
384
|
-
def __init__(
|
|
287
|
+
def __init__(
|
|
288
|
+
self, name: str, value: Union[Any, NoInitialValue], options: Union[List, Tuple]
|
|
289
|
+
):
|
|
385
290
|
self.name = name
|
|
386
291
|
self.options = self._validate_options(options)
|
|
292
|
+
if isinstance(value, NoInitialValue):
|
|
293
|
+
value = self.options[0]
|
|
387
294
|
self._value = self._validate(value)
|
|
388
295
|
|
|
389
296
|
def _validate_options(self, options: Any) -> List[Any]:
|
|
@@ -412,6 +319,9 @@ class SelectionParameter(Parameter[Any]):
|
|
|
412
319
|
f"Options for parameter {self.name} must be a list or tuple"
|
|
413
320
|
)
|
|
414
321
|
|
|
322
|
+
if not options:
|
|
323
|
+
raise ValueError(f"Options for parameter {self.name} must not be empty")
|
|
324
|
+
|
|
415
325
|
# Verify all options are hashable (needed for comparison)
|
|
416
326
|
try:
|
|
417
327
|
for opt in options:
|
|
@@ -435,9 +345,42 @@ class SelectionParameter(Parameter[Any]):
|
|
|
435
345
|
Raises:
|
|
436
346
|
ValueError: If value is not in options list
|
|
437
347
|
"""
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
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}")
|
|
441
384
|
|
|
442
385
|
def _validate_update(self) -> None:
|
|
443
386
|
"""
|
|
@@ -450,12 +393,51 @@ class SelectionParameter(Parameter[Any]):
|
|
|
450
393
|
TypeError: If options is not a list or tuple
|
|
451
394
|
"""
|
|
452
395
|
self.options = self._validate_options(self.options)
|
|
453
|
-
|
|
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:
|
|
454
436
|
warn(
|
|
455
437
|
ParameterUpdateWarning(
|
|
456
438
|
self.name,
|
|
457
439
|
type(self).__name__,
|
|
458
|
-
f"Value {self.value} not in options
|
|
440
|
+
f"Value {self.value} not in options, setting to first option ({self.options[0]})",
|
|
459
441
|
)
|
|
460
442
|
)
|
|
461
443
|
self.value = self.options[0]
|
|
@@ -467,15 +449,15 @@ class MultipleSelectionParameter(Parameter[List[Any]]):
|
|
|
467
449
|
Parameter for multiple selections from a list of options.
|
|
468
450
|
|
|
469
451
|
Creates a set of checkboxes or multi-select dropdown in the GUI.
|
|
470
|
-
See :meth:`~syd.
|
|
471
|
-
:meth:`~syd.
|
|
452
|
+
See :meth:`~syd.viewer.Viewer.add_multiple_selection` and
|
|
453
|
+
:meth:`~syd.viewer.Viewer.update_multiple_selection` for usage.
|
|
472
454
|
|
|
473
455
|
Parameters
|
|
474
456
|
----------
|
|
475
457
|
name : str
|
|
476
458
|
The name of the parameter
|
|
477
|
-
value :
|
|
478
|
-
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)
|
|
479
461
|
options : sequence
|
|
480
462
|
List, tuple, or 1D numpy array of valid choices that can be selected
|
|
481
463
|
|
|
@@ -497,9 +479,16 @@ class MultipleSelectionParameter(Parameter[List[Any]]):
|
|
|
497
479
|
|
|
498
480
|
options: List[Any]
|
|
499
481
|
|
|
500
|
-
def __init__(
|
|
482
|
+
def __init__(
|
|
483
|
+
self,
|
|
484
|
+
name: str,
|
|
485
|
+
value: Union[List[Any], NoInitialValue],
|
|
486
|
+
options: Union[List, Tuple],
|
|
487
|
+
):
|
|
501
488
|
self.name = name
|
|
502
489
|
self.options = self._validate_options(options)
|
|
490
|
+
if isinstance(value, NoInitialValue):
|
|
491
|
+
value = []
|
|
503
492
|
self._value = self._validate(value)
|
|
504
493
|
|
|
505
494
|
def _validate_options(self, options: Any) -> List[Any]:
|
|
@@ -525,9 +514,12 @@ class MultipleSelectionParameter(Parameter[List[Any]]):
|
|
|
525
514
|
"""
|
|
526
515
|
if not isinstance(options, (list, tuple)):
|
|
527
516
|
raise TypeError(
|
|
528
|
-
f"Options for parameter {self.name} must be a list or tuple"
|
|
517
|
+
f"Options for parameter {self.name} must be a list or tuple, received {type(options)}"
|
|
529
518
|
)
|
|
530
519
|
|
|
520
|
+
if not options:
|
|
521
|
+
raise ValueError(f"Options for parameter {self.name} must not be empty")
|
|
522
|
+
|
|
531
523
|
# Verify all options are hashable (needed for comparison)
|
|
532
524
|
try:
|
|
533
525
|
for opt in options:
|
|
@@ -580,7 +572,7 @@ class MultipleSelectionParameter(Parameter[List[Any]]):
|
|
|
580
572
|
ParameterUpdateWarning(
|
|
581
573
|
self.name,
|
|
582
574
|
type(self).__name__,
|
|
583
|
-
f"For parameter {self.name}, value {self.value} contains invalid
|
|
575
|
+
f"For parameter {self.name}, value {self.value} contains invalid selections: {invalid}. Setting to empty list.",
|
|
584
576
|
)
|
|
585
577
|
)
|
|
586
578
|
self.value = []
|
|
@@ -595,46 +587,48 @@ class IntegerParameter(Parameter[int]):
|
|
|
595
587
|
Parameter for bounded integer values.
|
|
596
588
|
|
|
597
589
|
Creates a slider in the GUI for selecting whole numbers between bounds.
|
|
598
|
-
See :meth:`~syd.
|
|
599
|
-
:meth:`~syd.
|
|
590
|
+
See :meth:`~syd.viewer.Viewer.add_integer` and
|
|
591
|
+
:meth:`~syd.viewer.Viewer.update_integer` for usage.
|
|
600
592
|
|
|
601
593
|
Parameters
|
|
602
594
|
----------
|
|
603
595
|
name : str
|
|
604
596
|
The name of the parameter
|
|
605
|
-
value : int
|
|
606
|
-
Initial value (will be clamped to fit between
|
|
607
|
-
|
|
597
|
+
value : Union[int, NoInitialValue]
|
|
598
|
+
Initial value (will be clamped to fit between min and max)
|
|
599
|
+
min : int
|
|
608
600
|
Minimum allowed value
|
|
609
|
-
|
|
601
|
+
max : int
|
|
610
602
|
Maximum allowed value
|
|
611
603
|
|
|
612
604
|
Examples
|
|
613
605
|
--------
|
|
614
|
-
>>> age = IntegerParameter("age", value=25,
|
|
606
|
+
>>> age = IntegerParameter("age", value=25, min=0, max=120)
|
|
615
607
|
>>> age.value
|
|
616
608
|
25
|
|
617
|
-
>>> age.update({"value": 150}) # Will be clamped to
|
|
609
|
+
>>> age.update({"value": 150}) # Will be clamped to max
|
|
618
610
|
>>> age.value
|
|
619
611
|
120
|
|
620
|
-
>>> age.update({"value": -10}) # Will be clamped to
|
|
612
|
+
>>> age.update({"value": -10}) # Will be clamped to min
|
|
621
613
|
>>> age.value
|
|
622
614
|
0
|
|
623
615
|
"""
|
|
624
616
|
|
|
625
|
-
|
|
626
|
-
|
|
617
|
+
min: int
|
|
618
|
+
max: int
|
|
627
619
|
|
|
628
620
|
def __init__(
|
|
629
621
|
self,
|
|
630
622
|
name: str,
|
|
631
|
-
value: int,
|
|
632
|
-
|
|
633
|
-
|
|
623
|
+
value: Union[int, NoInitialValue],
|
|
624
|
+
min: int,
|
|
625
|
+
max: int,
|
|
634
626
|
):
|
|
635
627
|
self.name = name
|
|
636
|
-
self.
|
|
637
|
-
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
|
|
638
632
|
self._value = self._validate(value)
|
|
639
633
|
|
|
640
634
|
def _validate(self, new_value: Any, compare_to_range: bool = True) -> int:
|
|
@@ -657,43 +651,43 @@ class IntegerParameter(Parameter[int]):
|
|
|
657
651
|
raise ValueError(f"Value {new_value} cannot be converted to int")
|
|
658
652
|
|
|
659
653
|
if compare_to_range:
|
|
660
|
-
if new_value < self.
|
|
654
|
+
if new_value < self.min:
|
|
661
655
|
warn(
|
|
662
656
|
ParameterUpdateWarning(
|
|
663
657
|
self.name,
|
|
664
658
|
type(self).__name__,
|
|
665
|
-
f"Value {new_value} below minimum {self.
|
|
659
|
+
f"Value {new_value} below minimum {self.min}, clamping",
|
|
666
660
|
)
|
|
667
661
|
)
|
|
668
|
-
new_value = self.
|
|
669
|
-
if new_value > self.
|
|
662
|
+
new_value = self.min
|
|
663
|
+
if new_value > self.max:
|
|
670
664
|
warn(
|
|
671
665
|
ParameterUpdateWarning(
|
|
672
666
|
self.name,
|
|
673
667
|
type(self).__name__,
|
|
674
|
-
f"Value {new_value} above maximum {self.
|
|
668
|
+
f"Value {new_value} above maximum {self.max}, clamping",
|
|
675
669
|
)
|
|
676
670
|
)
|
|
677
|
-
new_value = self.
|
|
671
|
+
new_value = self.max
|
|
678
672
|
return int(new_value)
|
|
679
673
|
|
|
680
674
|
def _validate_update(self) -> None:
|
|
681
675
|
"""
|
|
682
676
|
Validate complete parameter state after updates.
|
|
683
677
|
|
|
684
|
-
Ensures
|
|
678
|
+
Ensures min <= max, swapping if needed.
|
|
685
679
|
Re-validates current value against potentially updated bounds.
|
|
686
680
|
|
|
687
681
|
Raises:
|
|
688
682
|
ParameterUpdateError: If bounds are invalid (e.g. None when required)
|
|
689
683
|
"""
|
|
690
|
-
if self.
|
|
684
|
+
if self.min is None or self.max is None:
|
|
691
685
|
raise ParameterUpdateError(
|
|
692
686
|
self.name,
|
|
693
687
|
type(self).__name__,
|
|
694
|
-
"IntegerParameter must have both
|
|
688
|
+
"IntegerParameter must have both min and max bounds",
|
|
695
689
|
)
|
|
696
|
-
if self.
|
|
690
|
+
if self.min > self.max:
|
|
697
691
|
warn(
|
|
698
692
|
ParameterUpdateWarning(
|
|
699
693
|
self.name,
|
|
@@ -701,7 +695,7 @@ class IntegerParameter(Parameter[int]):
|
|
|
701
695
|
f"Min value greater than max value, swapping",
|
|
702
696
|
)
|
|
703
697
|
)
|
|
704
|
-
self.
|
|
698
|
+
self.min, self.max = self.max, self.min
|
|
705
699
|
self.value = self._validate(self.value)
|
|
706
700
|
|
|
707
701
|
|
|
@@ -711,32 +705,32 @@ class FloatParameter(Parameter[float]):
|
|
|
711
705
|
Parameter for bounded decimal numbers.
|
|
712
706
|
|
|
713
707
|
Creates a slider in the GUI for selecting numbers between bounds.
|
|
714
|
-
See :meth:`~syd.
|
|
715
|
-
:meth:`~syd.
|
|
708
|
+
See :meth:`~syd.viewer.Viewer.add_float` and
|
|
709
|
+
:meth:`~syd.viewer.Viewer.update_float` for usage.
|
|
716
710
|
|
|
717
711
|
Parameters
|
|
718
712
|
----------
|
|
719
713
|
name : str
|
|
720
714
|
The name of the parameter
|
|
721
|
-
value : float
|
|
722
|
-
Initial value (will be clamped to fit between
|
|
723
|
-
|
|
715
|
+
value : Union[float, NoInitialValue]
|
|
716
|
+
Initial value (will be clamped to fit between min and max)
|
|
717
|
+
min : float
|
|
724
718
|
Minimum allowed value
|
|
725
|
-
|
|
719
|
+
max : float
|
|
726
720
|
Maximum allowed value
|
|
727
721
|
step : float, optional
|
|
728
|
-
Size of each increment (default is 0.
|
|
722
|
+
Size of each increment (default is 0.001)
|
|
729
723
|
|
|
730
724
|
Examples
|
|
731
725
|
--------
|
|
732
726
|
>>> temp = FloatParameter("temperature", value=98.6,
|
|
733
|
-
...
|
|
727
|
+
... min=95.0, max=105.0, step=0.1)
|
|
734
728
|
>>> temp.value
|
|
735
729
|
98.6
|
|
736
730
|
>>> temp.update({"value": 98.67}) # Will be rounded to nearest step
|
|
737
731
|
>>> temp.value
|
|
738
732
|
98.7
|
|
739
|
-
>>> temp.update({"value": 110.0}) # Will be clamped to
|
|
733
|
+
>>> temp.update({"value": 110.0}) # Will be clamped to max
|
|
740
734
|
>>> temp.value
|
|
741
735
|
105.0
|
|
742
736
|
|
|
@@ -748,22 +742,24 @@ class FloatParameter(Parameter[float]):
|
|
|
748
742
|
- step=5.0 allows values like 0.0, 5.0, 10.0, etc.
|
|
749
743
|
"""
|
|
750
744
|
|
|
751
|
-
|
|
752
|
-
|
|
745
|
+
min: float
|
|
746
|
+
max: float
|
|
753
747
|
step: float
|
|
754
748
|
|
|
755
749
|
def __init__(
|
|
756
750
|
self,
|
|
757
751
|
name: str,
|
|
758
|
-
value: float,
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
step: float = 0.
|
|
752
|
+
value: Union[float, NoInitialValue],
|
|
753
|
+
min: float,
|
|
754
|
+
max: float,
|
|
755
|
+
step: float = 0.001,
|
|
762
756
|
):
|
|
763
757
|
self.name = name
|
|
764
758
|
self.step = step
|
|
765
|
-
self.
|
|
766
|
-
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
|
|
767
763
|
self._value = self._validate(value)
|
|
768
764
|
|
|
769
765
|
def _validate(self, new_value: Any, compare_to_range: bool = True) -> float:
|
|
@@ -791,24 +787,24 @@ class FloatParameter(Parameter[float]):
|
|
|
791
787
|
new_value = round(new_value / self.step) * self.step
|
|
792
788
|
|
|
793
789
|
if compare_to_range:
|
|
794
|
-
if new_value < self.
|
|
790
|
+
if new_value < self.min:
|
|
795
791
|
warn(
|
|
796
792
|
ParameterUpdateWarning(
|
|
797
793
|
self.name,
|
|
798
794
|
type(self).__name__,
|
|
799
|
-
f"Value {new_value} below minimum {self.
|
|
795
|
+
f"Value {new_value} below minimum {self.min}, clamping",
|
|
800
796
|
)
|
|
801
797
|
)
|
|
802
|
-
new_value = self.
|
|
803
|
-
if new_value > self.
|
|
798
|
+
new_value = self.min
|
|
799
|
+
if new_value > self.max:
|
|
804
800
|
warn(
|
|
805
801
|
ParameterUpdateWarning(
|
|
806
802
|
self.name,
|
|
807
803
|
type(self).__name__,
|
|
808
|
-
f"Value {new_value} above maximum {self.
|
|
804
|
+
f"Value {new_value} above maximum {self.max}, clamping",
|
|
809
805
|
)
|
|
810
806
|
)
|
|
811
|
-
new_value = self.
|
|
807
|
+
new_value = self.max
|
|
812
808
|
|
|
813
809
|
return float(new_value)
|
|
814
810
|
|
|
@@ -816,19 +812,19 @@ class FloatParameter(Parameter[float]):
|
|
|
816
812
|
"""
|
|
817
813
|
Validate complete parameter state after updates.
|
|
818
814
|
|
|
819
|
-
Ensures
|
|
815
|
+
Ensures min <= max, swapping if needed.
|
|
820
816
|
Re-validates current value against potentially updated bounds.
|
|
821
817
|
|
|
822
818
|
Raises:
|
|
823
819
|
ParameterUpdateError: If bounds are invalid (e.g. None when required)
|
|
824
820
|
"""
|
|
825
|
-
if self.
|
|
821
|
+
if self.min is None or self.max is None:
|
|
826
822
|
raise ParameterUpdateError(
|
|
827
823
|
self.name,
|
|
828
824
|
type(self).__name__,
|
|
829
|
-
"FloatParameter must have both
|
|
825
|
+
"FloatParameter must have both min and max bounds",
|
|
830
826
|
)
|
|
831
|
-
if self.
|
|
827
|
+
if self.min > self.max:
|
|
832
828
|
warn(
|
|
833
829
|
ParameterUpdateWarning(
|
|
834
830
|
self.name,
|
|
@@ -836,7 +832,7 @@ class FloatParameter(Parameter[float]):
|
|
|
836
832
|
f"Min value greater than max value, swapping",
|
|
837
833
|
)
|
|
838
834
|
)
|
|
839
|
-
self.
|
|
835
|
+
self.min, self.max = self.max, self.min
|
|
840
836
|
self.value = self._validate(self.value)
|
|
841
837
|
|
|
842
838
|
|
|
@@ -846,24 +842,24 @@ class IntegerRangeParameter(Parameter[Tuple[int, int]]):
|
|
|
846
842
|
Parameter for a range of bounded integer values.
|
|
847
843
|
|
|
848
844
|
Creates a range slider in the GUI for selecting a range of whole numbers.
|
|
849
|
-
See :meth:`~syd.
|
|
850
|
-
:meth:`~syd.
|
|
845
|
+
See :meth:`~syd.viewer.Viewer.add_integer_range` and
|
|
846
|
+
:meth:`~syd.viewer.Viewer.update_integer_range` for usage.
|
|
851
847
|
|
|
852
848
|
Parameters
|
|
853
849
|
----------
|
|
854
850
|
name : str
|
|
855
851
|
The name of the parameter
|
|
856
|
-
value :
|
|
852
|
+
value : Union[Tuple[int, int], NoInitialValue]
|
|
857
853
|
Initial (low, high) values
|
|
858
|
-
|
|
854
|
+
min : int
|
|
859
855
|
Minimum allowed value for both low and high
|
|
860
|
-
|
|
856
|
+
max : int
|
|
861
857
|
Maximum allowed value for both low and high
|
|
862
858
|
|
|
863
859
|
Examples
|
|
864
860
|
--------
|
|
865
861
|
>>> age_range = IntegerRangeParameter("age_range",
|
|
866
|
-
... value=(25, 35),
|
|
862
|
+
... value=(25, 35), min=18, max=100)
|
|
867
863
|
>>> age_range.value
|
|
868
864
|
(25, 35)
|
|
869
865
|
>>> age_range.update({"value": (35, 25)}) # Values will be swapped
|
|
@@ -874,22 +870,24 @@ class IntegerRangeParameter(Parameter[Tuple[int, int]]):
|
|
|
874
870
|
(18, 40)
|
|
875
871
|
"""
|
|
876
872
|
|
|
877
|
-
|
|
878
|
-
|
|
873
|
+
min: int
|
|
874
|
+
max: int
|
|
879
875
|
|
|
880
876
|
def __init__(
|
|
881
877
|
self,
|
|
882
878
|
name: str,
|
|
883
|
-
value: Tuple[int, int],
|
|
884
|
-
|
|
885
|
-
|
|
879
|
+
value: Union[Tuple[int, int], NoInitialValue],
|
|
880
|
+
min: int,
|
|
881
|
+
max: int,
|
|
886
882
|
):
|
|
887
883
|
self.name = name
|
|
888
|
-
self.
|
|
889
|
-
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)
|
|
890
888
|
self._value = self._validate(value)
|
|
891
889
|
|
|
892
|
-
def _validate_single(self, new_value: Any) -> int:
|
|
890
|
+
def _validate_single(self, new_value: Any, context: Optional[str] = None) -> int:
|
|
893
891
|
"""
|
|
894
892
|
Validate and convert a single numeric value.
|
|
895
893
|
|
|
@@ -907,8 +905,11 @@ class IntegerRangeParameter(Parameter[Tuple[int, int]]):
|
|
|
907
905
|
"""
|
|
908
906
|
try:
|
|
909
907
|
return int(new_value)
|
|
910
|
-
except
|
|
911
|
-
|
|
908
|
+
except Exception:
|
|
909
|
+
msg = f"Value {new_value} cannot be converted to int"
|
|
910
|
+
if context:
|
|
911
|
+
msg += f" for {context}"
|
|
912
|
+
raise ValueError(msg)
|
|
912
913
|
|
|
913
914
|
def _validate(self, new_value: Any) -> Tuple[int, int]:
|
|
914
915
|
"""
|
|
@@ -940,24 +941,24 @@ class IntegerRangeParameter(Parameter[Tuple[int, int]]):
|
|
|
940
941
|
)
|
|
941
942
|
low, high = high, low
|
|
942
943
|
|
|
943
|
-
if low < self.
|
|
944
|
+
if low < self.min:
|
|
944
945
|
warn(
|
|
945
946
|
ParameterUpdateWarning(
|
|
946
947
|
self.name,
|
|
947
948
|
type(self).__name__,
|
|
948
|
-
f"Low value {low} below minimum {self.
|
|
949
|
+
f"Low value {low} below minimum {self.min}, clamping",
|
|
949
950
|
)
|
|
950
951
|
)
|
|
951
|
-
low = self.
|
|
952
|
-
if high > self.
|
|
952
|
+
low = self.min
|
|
953
|
+
if high > self.max:
|
|
953
954
|
warn(
|
|
954
955
|
ParameterUpdateWarning(
|
|
955
956
|
self.name,
|
|
956
957
|
type(self).__name__,
|
|
957
|
-
f"High value {high} above maximum {self.
|
|
958
|
+
f"High value {high} above maximum {self.max}, clamping",
|
|
958
959
|
)
|
|
959
960
|
)
|
|
960
|
-
high = self.
|
|
961
|
+
high = self.max
|
|
961
962
|
|
|
962
963
|
return (low, high)
|
|
963
964
|
|
|
@@ -965,19 +966,19 @@ class IntegerRangeParameter(Parameter[Tuple[int, int]]):
|
|
|
965
966
|
"""
|
|
966
967
|
Validate complete parameter state after updates.
|
|
967
968
|
|
|
968
|
-
Ensures
|
|
969
|
+
Ensures min <= max, swapping if needed.
|
|
969
970
|
Re-validates current value against potentially updated bounds.
|
|
970
971
|
|
|
971
972
|
Raises:
|
|
972
973
|
ParameterUpdateError: If bounds are invalid (e.g. None when required)
|
|
973
974
|
"""
|
|
974
|
-
if self.
|
|
975
|
+
if self.min is None or self.max is None:
|
|
975
976
|
raise ParameterUpdateError(
|
|
976
977
|
self.name,
|
|
977
978
|
type(self).__name__,
|
|
978
|
-
"IntegerRangeParameter must have both
|
|
979
|
+
"IntegerRangeParameter must have both min and max bounds",
|
|
979
980
|
)
|
|
980
|
-
if self.
|
|
981
|
+
if self.min > self.max:
|
|
981
982
|
warn(
|
|
982
983
|
ParameterUpdateWarning(
|
|
983
984
|
self.name,
|
|
@@ -985,7 +986,7 @@ class IntegerRangeParameter(Parameter[Tuple[int, int]]):
|
|
|
985
986
|
f"Min value greater than max value, swapping",
|
|
986
987
|
)
|
|
987
988
|
)
|
|
988
|
-
self.
|
|
989
|
+
self.min, self.max = self.max, self.min
|
|
989
990
|
self.value = self._validate(self.value)
|
|
990
991
|
|
|
991
992
|
|
|
@@ -995,26 +996,26 @@ class FloatRangeParameter(Parameter[Tuple[float, float]]):
|
|
|
995
996
|
Parameter for a range of bounded decimal numbers.
|
|
996
997
|
|
|
997
998
|
Creates a range slider in the GUI for selecting a range of numbers.
|
|
998
|
-
See :meth:`~syd.
|
|
999
|
-
:meth:`~syd.
|
|
999
|
+
See :meth:`~syd.viewer.Viewer.add_float_range` and
|
|
1000
|
+
:meth:`~syd.viewer.Viewer.update_float_range` for usage.
|
|
1000
1001
|
|
|
1001
1002
|
Parameters
|
|
1002
1003
|
----------
|
|
1003
1004
|
name : str
|
|
1004
1005
|
The name of the parameter
|
|
1005
|
-
value :
|
|
1006
|
+
value : Union[Tuple[float, float], NoInitialValue]
|
|
1006
1007
|
Initial (low, high) values
|
|
1007
|
-
|
|
1008
|
+
min : float
|
|
1008
1009
|
Minimum allowed value for both low and high
|
|
1009
|
-
|
|
1010
|
+
max : float
|
|
1010
1011
|
Maximum allowed value for both low and high
|
|
1011
1012
|
step : float, optional
|
|
1012
|
-
Size of each increment (default is 0.
|
|
1013
|
+
Size of each increment (default is 0.001)
|
|
1013
1014
|
|
|
1014
1015
|
Examples
|
|
1015
1016
|
--------
|
|
1016
1017
|
>>> temp_range = FloatRangeParameter("temperature_range",
|
|
1017
|
-
... value=(98.6, 100.4),
|
|
1018
|
+
... value=(98.6, 100.4), min=95.0, max=105.0, step=0.1)
|
|
1018
1019
|
>>> temp_range.value
|
|
1019
1020
|
(98.6, 100.4)
|
|
1020
1021
|
>>> temp_range.update({"value": (98.67, 100.0)}) # Low will be rounded
|
|
@@ -1032,25 +1033,27 @@ class FloatRangeParameter(Parameter[Tuple[float, float]]):
|
|
|
1032
1033
|
- step=5.0 allows values like 0.0, 5.0, 10.0, etc.
|
|
1033
1034
|
"""
|
|
1034
1035
|
|
|
1035
|
-
|
|
1036
|
-
|
|
1036
|
+
min: float
|
|
1037
|
+
max: float
|
|
1037
1038
|
step: float
|
|
1038
1039
|
|
|
1039
1040
|
def __init__(
|
|
1040
1041
|
self,
|
|
1041
1042
|
name: str,
|
|
1042
|
-
value: Tuple[float, float],
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
step: float = 0.
|
|
1043
|
+
value: Union[Tuple[float, float], NoInitialValue],
|
|
1044
|
+
min: float,
|
|
1045
|
+
max: float,
|
|
1046
|
+
step: float = 0.001,
|
|
1046
1047
|
):
|
|
1047
1048
|
self.name = name
|
|
1048
1049
|
self.step = step
|
|
1049
|
-
self.
|
|
1050
|
-
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)
|
|
1051
1054
|
self._value = self._validate(value)
|
|
1052
1055
|
|
|
1053
|
-
def _validate_single(self, new_value: Any) -> float:
|
|
1056
|
+
def _validate_single(self, new_value: Any, context: Optional[str] = None) -> float:
|
|
1054
1057
|
"""
|
|
1055
1058
|
Validate and convert a single numeric value.
|
|
1056
1059
|
|
|
@@ -1068,8 +1071,11 @@ class FloatRangeParameter(Parameter[Tuple[float, float]]):
|
|
|
1068
1071
|
"""
|
|
1069
1072
|
try:
|
|
1070
1073
|
new_value = float(new_value)
|
|
1071
|
-
except
|
|
1072
|
-
|
|
1074
|
+
except Exception:
|
|
1075
|
+
msg = f"Value {new_value} cannot be converted to float"
|
|
1076
|
+
if context:
|
|
1077
|
+
msg += f" for {context}"
|
|
1078
|
+
raise ValueError(msg)
|
|
1073
1079
|
|
|
1074
1080
|
# Round to the nearest step
|
|
1075
1081
|
new_value = round(new_value / self.step) * self.step
|
|
@@ -1105,24 +1111,24 @@ class FloatRangeParameter(Parameter[Tuple[float, float]]):
|
|
|
1105
1111
|
)
|
|
1106
1112
|
low, high = high, low
|
|
1107
1113
|
|
|
1108
|
-
if low < self.
|
|
1114
|
+
if low < self.min:
|
|
1109
1115
|
warn(
|
|
1110
1116
|
ParameterUpdateWarning(
|
|
1111
1117
|
self.name,
|
|
1112
1118
|
type(self).__name__,
|
|
1113
|
-
f"Low value {low} below minimum {self.
|
|
1119
|
+
f"Low value {low} below minimum {self.min}, clamping",
|
|
1114
1120
|
)
|
|
1115
1121
|
)
|
|
1116
|
-
low = self.
|
|
1117
|
-
if high > self.
|
|
1122
|
+
low = self.min
|
|
1123
|
+
if high > self.max:
|
|
1118
1124
|
warn(
|
|
1119
1125
|
ParameterUpdateWarning(
|
|
1120
1126
|
self.name,
|
|
1121
1127
|
type(self).__name__,
|
|
1122
|
-
f"High value {high} above maximum {self.
|
|
1128
|
+
f"High value {high} above maximum {self.max}, clamping",
|
|
1123
1129
|
)
|
|
1124
1130
|
)
|
|
1125
|
-
high = self.
|
|
1131
|
+
high = self.max
|
|
1126
1132
|
|
|
1127
1133
|
return (low, high)
|
|
1128
1134
|
|
|
@@ -1130,19 +1136,19 @@ class FloatRangeParameter(Parameter[Tuple[float, float]]):
|
|
|
1130
1136
|
"""
|
|
1131
1137
|
Validate complete parameter state after updates.
|
|
1132
1138
|
|
|
1133
|
-
Ensures
|
|
1139
|
+
Ensures min <= max, swapping if needed.
|
|
1134
1140
|
Re-validates current value against potentially updated bounds.
|
|
1135
1141
|
|
|
1136
1142
|
Raises:
|
|
1137
1143
|
ParameterUpdateError: If bounds are invalid (e.g. None when required)
|
|
1138
1144
|
"""
|
|
1139
|
-
if self.
|
|
1145
|
+
if self.min is None or self.max is None:
|
|
1140
1146
|
raise ParameterUpdateError(
|
|
1141
1147
|
self.name,
|
|
1142
1148
|
type(self).__name__,
|
|
1143
|
-
"FloatRangeParameter must have both
|
|
1149
|
+
"FloatRangeParameter must have both min and max bounds",
|
|
1144
1150
|
)
|
|
1145
|
-
if self.
|
|
1151
|
+
if self.min > self.max:
|
|
1146
1152
|
warn(
|
|
1147
1153
|
ParameterUpdateWarning(
|
|
1148
1154
|
self.name,
|
|
@@ -1150,7 +1156,7 @@ class FloatRangeParameter(Parameter[Tuple[float, float]]):
|
|
|
1150
1156
|
f"Min value greater than max value, swapping",
|
|
1151
1157
|
)
|
|
1152
1158
|
)
|
|
1153
|
-
self.
|
|
1159
|
+
self.min, self.max = self.max, self.min
|
|
1154
1160
|
self.value = self._validate(self.value)
|
|
1155
1161
|
|
|
1156
1162
|
|
|
@@ -1160,28 +1166,21 @@ class UnboundedIntegerParameter(Parameter[int]):
|
|
|
1160
1166
|
Parameter for optionally bounded integer values.
|
|
1161
1167
|
|
|
1162
1168
|
Creates a text input box in the GUI for entering whole numbers.
|
|
1163
|
-
See :meth:`~syd.
|
|
1164
|
-
:meth:`~syd.
|
|
1169
|
+
See :meth:`~syd.viewer.Viewer.add_unbounded_integer` and
|
|
1170
|
+
:meth:`~syd.viewer.Viewer.update_unbounded_integer` for usage.
|
|
1165
1171
|
|
|
1166
1172
|
Parameters
|
|
1167
1173
|
----------
|
|
1168
1174
|
name : str
|
|
1169
1175
|
The name of the parameter
|
|
1170
|
-
value : int
|
|
1176
|
+
value : Union[int, NoInitialValue]
|
|
1171
1177
|
Initial value
|
|
1172
|
-
min_value : int, optional
|
|
1173
|
-
Minimum allowed value (or None for no minimum)
|
|
1174
|
-
max_value : int, optional
|
|
1175
|
-
Maximum allowed value (or None for no maximum)
|
|
1176
1178
|
|
|
1177
1179
|
Examples
|
|
1178
1180
|
--------
|
|
1179
|
-
>>> count = UnboundedIntegerParameter("count", value=10
|
|
1181
|
+
>>> count = UnboundedIntegerParameter("count", value=10)
|
|
1180
1182
|
>>> count.value
|
|
1181
1183
|
10
|
|
1182
|
-
>>> count.update({"value": -5}) # Will be clamped to min_value
|
|
1183
|
-
>>> count.value
|
|
1184
|
-
0
|
|
1185
1184
|
>>> count.update({"value": 1000000}) # No maximum, so this is allowed
|
|
1186
1185
|
>>> count.value
|
|
1187
1186
|
1000000
|
|
@@ -1189,43 +1188,26 @@ class UnboundedIntegerParameter(Parameter[int]):
|
|
|
1189
1188
|
Notes
|
|
1190
1189
|
-----
|
|
1191
1190
|
Use this instead of IntegerParameter when you:
|
|
1192
|
-
- Don't
|
|
1193
|
-
- Only want to enforce a minimum or maximum, but not both
|
|
1191
|
+
- Don't have any reason to bound the value
|
|
1194
1192
|
- Need to allow very large numbers that would be impractical with a slider
|
|
1195
1193
|
"""
|
|
1196
1194
|
|
|
1197
|
-
min_value: Optional[int]
|
|
1198
|
-
max_value: Optional[int]
|
|
1199
|
-
|
|
1200
1195
|
def __init__(
|
|
1201
1196
|
self,
|
|
1202
1197
|
name: str,
|
|
1203
|
-
value: int,
|
|
1204
|
-
min_value: Optional[int] = None,
|
|
1205
|
-
max_value: Optional[int] = None,
|
|
1198
|
+
value: Union[int, NoInitialValue],
|
|
1206
1199
|
):
|
|
1207
1200
|
self.name = name
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
if min_value is not None
|
|
1211
|
-
else None
|
|
1212
|
-
)
|
|
1213
|
-
self.max_value = (
|
|
1214
|
-
self._validate(max_value, compare_to_range=False)
|
|
1215
|
-
if max_value is not None
|
|
1216
|
-
else None
|
|
1217
|
-
)
|
|
1201
|
+
if isinstance(value, NoInitialValue):
|
|
1202
|
+
value = 0
|
|
1218
1203
|
self._value = self._validate(value)
|
|
1219
1204
|
|
|
1220
|
-
def _validate(self, new_value: Any
|
|
1205
|
+
def _validate(self, new_value: Any) -> int:
|
|
1221
1206
|
"""
|
|
1222
|
-
Validate and convert value to integer
|
|
1223
|
-
|
|
1224
|
-
Handles None min/max values by skipping those bound checks.
|
|
1207
|
+
Validate and convert value to integer.
|
|
1225
1208
|
|
|
1226
1209
|
Args:
|
|
1227
1210
|
new_value: Value to validate
|
|
1228
|
-
compare_to_range: If True, clamps value to any defined min/max bounds
|
|
1229
1211
|
|
|
1230
1212
|
Returns:
|
|
1231
1213
|
Validated integer value
|
|
@@ -1238,50 +1220,15 @@ class UnboundedIntegerParameter(Parameter[int]):
|
|
|
1238
1220
|
except ValueError:
|
|
1239
1221
|
raise ValueError(f"Value {new_value} cannot be converted to int")
|
|
1240
1222
|
|
|
1241
|
-
if compare_to_range:
|
|
1242
|
-
if self.min_value is not None and new_value < self.min_value:
|
|
1243
|
-
warn(
|
|
1244
|
-
ParameterUpdateWarning(
|
|
1245
|
-
self.name,
|
|
1246
|
-
type(self).__name__,
|
|
1247
|
-
f"Value {new_value} below minimum {self.min_value}, clamping",
|
|
1248
|
-
)
|
|
1249
|
-
)
|
|
1250
|
-
new_value = self.min_value
|
|
1251
|
-
if self.max_value is not None and new_value > self.max_value:
|
|
1252
|
-
warn(
|
|
1253
|
-
ParameterUpdateWarning(
|
|
1254
|
-
self.name,
|
|
1255
|
-
type(self).__name__,
|
|
1256
|
-
f"Value {new_value} above maximum {self.max_value}, clamping",
|
|
1257
|
-
)
|
|
1258
|
-
)
|
|
1259
|
-
new_value = self.max_value
|
|
1260
1223
|
return int(new_value)
|
|
1261
1224
|
|
|
1262
1225
|
def _validate_update(self) -> None:
|
|
1263
1226
|
"""
|
|
1264
1227
|
Validate complete parameter state after updates.
|
|
1265
1228
|
|
|
1266
|
-
Ensures min_value <= max_value, swapping if needed.
|
|
1267
|
-
Re-validates current value against potentially updated bounds.
|
|
1268
|
-
|
|
1269
1229
|
Raises:
|
|
1270
1230
|
ParameterUpdateError: If bounds are invalid (e.g. None when required)
|
|
1271
1231
|
"""
|
|
1272
|
-
if (
|
|
1273
|
-
self.min_value is not None
|
|
1274
|
-
and self.max_value is not None
|
|
1275
|
-
and self.min_value > self.max_value
|
|
1276
|
-
):
|
|
1277
|
-
warn(
|
|
1278
|
-
ParameterUpdateWarning(
|
|
1279
|
-
self.name,
|
|
1280
|
-
type(self).__name__,
|
|
1281
|
-
f"Min value greater than max value, swapping",
|
|
1282
|
-
)
|
|
1283
|
-
)
|
|
1284
|
-
self.min_value, self.max_value = self.max_value, self.min_value
|
|
1285
1232
|
self.value = self._validate(self.value)
|
|
1286
1233
|
|
|
1287
1234
|
|
|
@@ -1291,30 +1238,23 @@ class UnboundedFloatParameter(Parameter[float]):
|
|
|
1291
1238
|
Parameter for optionally bounded decimal numbers.
|
|
1292
1239
|
|
|
1293
1240
|
Creates a text input box in the GUI for entering numbers.
|
|
1294
|
-
See :meth:`~syd.
|
|
1295
|
-
:meth:`~syd.
|
|
1241
|
+
See :meth:`~syd.viewer.Viewer.add_unbounded_float` and
|
|
1242
|
+
:meth:`~syd.viewer.Viewer.update_unbounded_float` for usage.
|
|
1296
1243
|
|
|
1297
1244
|
Parameters
|
|
1298
1245
|
----------
|
|
1299
1246
|
name : str
|
|
1300
1247
|
The name of the parameter
|
|
1301
|
-
value : float
|
|
1248
|
+
value : Union[float, NoInitialValue]
|
|
1302
1249
|
Initial value
|
|
1303
|
-
min_value : float, optional
|
|
1304
|
-
Minimum allowed value (or None for no minimum)
|
|
1305
|
-
max_value : float, optional
|
|
1306
|
-
Maximum allowed value (or None for no maximum)
|
|
1307
1250
|
step : float, optional
|
|
1308
1251
|
Size of each increment (default is None, meaning no rounding)
|
|
1309
1252
|
|
|
1310
1253
|
Examples
|
|
1311
1254
|
--------
|
|
1312
|
-
>>> price = UnboundedFloatParameter("price", value=19.99
|
|
1255
|
+
>>> price = UnboundedFloatParameter("price", value=19.99)
|
|
1313
1256
|
>>> price.value
|
|
1314
1257
|
19.99
|
|
1315
|
-
>>> price.update({"value": -5.0}) # Will be clamped to min_value
|
|
1316
|
-
>>> price.value
|
|
1317
|
-
0.0
|
|
1318
1258
|
>>> price.update({"value": 19.987}) # Will be rounded to step
|
|
1319
1259
|
>>> price.value
|
|
1320
1260
|
19.99
|
|
@@ -1323,7 +1263,6 @@ class UnboundedFloatParameter(Parameter[float]):
|
|
|
1323
1263
|
-----
|
|
1324
1264
|
Use this instead of FloatParameter when you:
|
|
1325
1265
|
- Don't know a reasonable maximum value
|
|
1326
|
-
- Only want to enforce a minimum or maximum, but not both
|
|
1327
1266
|
- Need to allow very large or precise numbers that would be impractical with a slider
|
|
1328
1267
|
|
|
1329
1268
|
If step is provided, values will be rounded:
|
|
@@ -1332,42 +1271,27 @@ class UnboundedFloatParameter(Parameter[float]):
|
|
|
1332
1271
|
- step=5.0 rounds to 0.0, 5.0, 10.0, etc.
|
|
1333
1272
|
"""
|
|
1334
1273
|
|
|
1335
|
-
|
|
1336
|
-
max_value: Optional[float]
|
|
1337
|
-
step: float
|
|
1274
|
+
step: Optional[float]
|
|
1338
1275
|
|
|
1339
1276
|
def __init__(
|
|
1340
1277
|
self,
|
|
1341
1278
|
name: str,
|
|
1342
|
-
value: float,
|
|
1343
|
-
min_value: Optional[float] = None,
|
|
1344
|
-
max_value: Optional[float] = None,
|
|
1279
|
+
value: Union[float, NoInitialValue],
|
|
1345
1280
|
step: Optional[float] = None,
|
|
1346
1281
|
):
|
|
1347
1282
|
self.name = name
|
|
1348
1283
|
self.step = step
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
if min_value is not None
|
|
1352
|
-
else None
|
|
1353
|
-
)
|
|
1354
|
-
self.max_value = (
|
|
1355
|
-
self._validate(max_value, compare_to_range=False)
|
|
1356
|
-
if max_value is not None
|
|
1357
|
-
else None
|
|
1358
|
-
)
|
|
1284
|
+
if isinstance(value, NoInitialValue):
|
|
1285
|
+
value = 0
|
|
1359
1286
|
self._value = self._validate(value)
|
|
1360
1287
|
|
|
1361
|
-
def _validate(self, new_value: Any
|
|
1288
|
+
def _validate(self, new_value: Any) -> float:
|
|
1362
1289
|
"""
|
|
1363
|
-
Validate and convert value to float
|
|
1364
|
-
|
|
1365
|
-
Handles None min/max values by skipping those bound checks.
|
|
1290
|
+
Validate and convert value to float.
|
|
1366
1291
|
Only rounds to step if step is not None.
|
|
1367
1292
|
|
|
1368
1293
|
Args:
|
|
1369
1294
|
new_value: Value to validate
|
|
1370
|
-
compare_to_range: If True, clamps value to any defined min/max bounds
|
|
1371
1295
|
|
|
1372
1296
|
Returns:
|
|
1373
1297
|
Validated and potentially rounded float value
|
|
@@ -1384,51 +1308,18 @@ class UnboundedFloatParameter(Parameter[float]):
|
|
|
1384
1308
|
if self.step is not None:
|
|
1385
1309
|
new_value = round(new_value / self.step) * self.step
|
|
1386
1310
|
|
|
1387
|
-
if compare_to_range:
|
|
1388
|
-
if self.min_value is not None and new_value < self.min_value:
|
|
1389
|
-
warn(
|
|
1390
|
-
ParameterUpdateWarning(
|
|
1391
|
-
self.name,
|
|
1392
|
-
type(self).__name__,
|
|
1393
|
-
f"Value {new_value} below minimum {self.min_value}, clamping",
|
|
1394
|
-
)
|
|
1395
|
-
)
|
|
1396
|
-
new_value = self.min_value
|
|
1397
|
-
if self.max_value is not None and new_value > self.max_value:
|
|
1398
|
-
warn(
|
|
1399
|
-
ParameterUpdateWarning(
|
|
1400
|
-
self.name,
|
|
1401
|
-
type(self).__name__,
|
|
1402
|
-
f"Value {new_value} above maximum {self.max_value}, clamping",
|
|
1403
|
-
)
|
|
1404
|
-
)
|
|
1405
|
-
new_value = self.max_value
|
|
1406
|
-
|
|
1407
1311
|
return float(new_value)
|
|
1408
1312
|
|
|
1409
1313
|
def _validate_update(self) -> None:
|
|
1410
1314
|
"""
|
|
1411
1315
|
Validate complete parameter state after updates.
|
|
1412
1316
|
|
|
1413
|
-
Ensures
|
|
1317
|
+
Ensures min <= max, swapping if needed.
|
|
1414
1318
|
Re-validates current value against potentially updated bounds.
|
|
1415
1319
|
|
|
1416
1320
|
Raises:
|
|
1417
1321
|
ParameterUpdateError: If bounds are invalid (e.g. None when required)
|
|
1418
1322
|
"""
|
|
1419
|
-
if (
|
|
1420
|
-
self.min_value is not None
|
|
1421
|
-
and self.max_value is not None
|
|
1422
|
-
and self.min_value > self.max_value
|
|
1423
|
-
):
|
|
1424
|
-
warn(
|
|
1425
|
-
ParameterUpdateWarning(
|
|
1426
|
-
self.name,
|
|
1427
|
-
type(self).__name__,
|
|
1428
|
-
f"Min value greater than max value, swapping",
|
|
1429
|
-
)
|
|
1430
|
-
)
|
|
1431
|
-
self.min_value, self.max_value = self.max_value, self.min_value
|
|
1432
1323
|
self.value = self._validate(self.value)
|
|
1433
1324
|
|
|
1434
1325
|
|
|
@@ -1438,15 +1329,15 @@ class ButtonAction(Parameter[None]):
|
|
|
1438
1329
|
Parameter for creating clickable buttons with callbacks.
|
|
1439
1330
|
|
|
1440
1331
|
Creates a button in the GUI that executes a callback function when clicked.
|
|
1441
|
-
See :meth:`~syd.
|
|
1442
|
-
:meth:`~syd.
|
|
1332
|
+
See :meth:`~syd.viewer.Viewer.add_button` and
|
|
1333
|
+
:meth:`~syd.viewer.Viewer.update_button` for usage.
|
|
1443
1334
|
|
|
1444
1335
|
Parameters
|
|
1445
1336
|
----------
|
|
1446
1337
|
name : str
|
|
1447
1338
|
The name of the parameter
|
|
1448
|
-
label : str
|
|
1449
|
-
Text to display on the button
|
|
1339
|
+
label : Union[str, NoInitialValue]
|
|
1340
|
+
Text to display on the button (default is the button's name)
|
|
1450
1341
|
callback : callable
|
|
1451
1342
|
Function to execute when the button is clicked
|
|
1452
1343
|
|
|
@@ -1478,16 +1369,27 @@ class ButtonAction(Parameter[None]):
|
|
|
1478
1369
|
value: None = field(default=None, repr=False)
|
|
1479
1370
|
_is_action: bool = field(default=True, repr=False)
|
|
1480
1371
|
|
|
1481
|
-
def __init__(
|
|
1372
|
+
def __init__(
|
|
1373
|
+
self,
|
|
1374
|
+
name: str,
|
|
1375
|
+
label: Union[str, NoInitialValue],
|
|
1376
|
+
callback: Callable,
|
|
1377
|
+
):
|
|
1482
1378
|
"""
|
|
1483
1379
|
Initialize a button.
|
|
1484
1380
|
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
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
|
|
1489
1389
|
"""
|
|
1490
1390
|
self.name = name
|
|
1391
|
+
if isinstance(label, NoInitialValue):
|
|
1392
|
+
label = name
|
|
1491
1393
|
self.label = label
|
|
1492
1394
|
self.callback = callback
|
|
1493
1395
|
self._value = None
|