spectre-core 0.0.12__py3-none-any.whl → 0.0.13__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.
Files changed (88) hide show
  1. spectre_core/_file_io/__init__.py +1 -3
  2. spectre_core/_file_io/file_handlers.py +163 -58
  3. spectre_core/batches/__init__.py +10 -11
  4. spectre_core/batches/_base.py +170 -78
  5. spectre_core/batches/_batches.py +149 -99
  6. spectre_core/batches/_factory.py +56 -14
  7. spectre_core/batches/_register.py +23 -8
  8. spectre_core/batches/plugins/_batch_keys.py +16 -0
  9. spectre_core/batches/plugins/_callisto.py +183 -0
  10. spectre_core/batches/plugins/_iq_stream.py +354 -0
  11. spectre_core/capture_configs/__init__.py +17 -13
  12. spectre_core/capture_configs/_capture_config.py +93 -34
  13. spectre_core/capture_configs/_capture_modes.py +22 -0
  14. spectre_core/capture_configs/_capture_templates.py +207 -122
  15. spectre_core/capture_configs/_parameters.py +115 -42
  16. spectre_core/capture_configs/_pconstraints.py +86 -35
  17. spectre_core/capture_configs/_pnames.py +49 -0
  18. spectre_core/capture_configs/_ptemplates.py +389 -346
  19. spectre_core/capture_configs/_pvalidators.py +117 -73
  20. spectre_core/config/__init__.py +6 -8
  21. spectre_core/config/_paths.py +65 -25
  22. spectre_core/config/_time_formats.py +15 -10
  23. spectre_core/exceptions.py +2 -4
  24. spectre_core/jobs/__init__.py +14 -0
  25. spectre_core/jobs/_jobs.py +111 -0
  26. spectre_core/jobs/_workers.py +171 -0
  27. spectre_core/logs/__init__.py +17 -0
  28. spectre_core/logs/_configure.py +67 -0
  29. spectre_core/logs/_decorators.py +33 -0
  30. spectre_core/logs/_logs.py +228 -0
  31. spectre_core/logs/_process_types.py +14 -0
  32. spectre_core/plotting/__init__.py +4 -2
  33. spectre_core/plotting/_base.py +204 -102
  34. spectre_core/plotting/_format.py +17 -4
  35. spectre_core/plotting/_panel_names.py +18 -0
  36. spectre_core/plotting/_panel_stack.py +167 -53
  37. spectre_core/plotting/_panels.py +341 -141
  38. spectre_core/post_processing/__init__.py +8 -6
  39. spectre_core/post_processing/_base.py +70 -44
  40. spectre_core/post_processing/_factory.py +42 -12
  41. spectre_core/post_processing/_post_processor.py +24 -26
  42. spectre_core/post_processing/_register.py +22 -6
  43. spectre_core/post_processing/plugins/_event_handler_keys.py +16 -0
  44. spectre_core/post_processing/plugins/_fixed_center_frequency.py +129 -0
  45. spectre_core/post_processing/{library → plugins}/_swept_center_frequency.py +215 -143
  46. spectre_core/py.typed +0 -0
  47. spectre_core/receivers/__init__.py +10 -7
  48. spectre_core/receivers/_base.py +220 -69
  49. spectre_core/receivers/_factory.py +53 -7
  50. spectre_core/receivers/_register.py +30 -9
  51. spectre_core/receivers/_spec_names.py +26 -15
  52. spectre_core/receivers/plugins/__init__.py +0 -0
  53. spectre_core/receivers/plugins/_receiver_names.py +16 -0
  54. spectre_core/receivers/plugins/_rsp1a.py +59 -0
  55. spectre_core/receivers/plugins/_rspduo.py +67 -0
  56. spectre_core/receivers/plugins/_sdrplay_receiver.py +190 -0
  57. spectre_core/receivers/plugins/_test.py +218 -0
  58. spectre_core/receivers/plugins/gr/_base.py +80 -0
  59. spectre_core/receivers/{gr → plugins/gr}/_rsp1a.py +42 -52
  60. spectre_core/receivers/{gr → plugins/gr}/_rspduo.py +61 -74
  61. spectre_core/receivers/{gr → plugins/gr}/_test.py +33 -31
  62. spectre_core/spectrograms/__init__.py +5 -3
  63. spectre_core/spectrograms/_analytical.py +121 -66
  64. spectre_core/spectrograms/_array_operations.py +103 -36
  65. spectre_core/spectrograms/_spectrogram.py +380 -207
  66. spectre_core/spectrograms/_transform.py +197 -169
  67. spectre_core/wgetting/__init__.py +4 -2
  68. spectre_core/wgetting/_callisto.py +173 -118
  69. {spectre_core-0.0.12.dist-info → spectre_core-0.0.13.dist-info}/METADATA +14 -7
  70. spectre_core-0.0.13.dist-info/RECORD +75 -0
  71. {spectre_core-0.0.12.dist-info → spectre_core-0.0.13.dist-info}/WHEEL +1 -1
  72. spectre_core/batches/library/_callisto.py +0 -96
  73. spectre_core/batches/library/_fixed_center_frequency.py +0 -133
  74. spectre_core/batches/library/_swept_center_frequency.py +0 -105
  75. spectre_core/logging/__init__.py +0 -11
  76. spectre_core/logging/_configure.py +0 -35
  77. spectre_core/logging/_decorators.py +0 -19
  78. spectre_core/logging/_log_handlers.py +0 -176
  79. spectre_core/post_processing/library/_fixed_center_frequency.py +0 -114
  80. spectre_core/receivers/gr/_base.py +0 -33
  81. spectre_core/receivers/library/_rsp1a.py +0 -61
  82. spectre_core/receivers/library/_rspduo.py +0 -69
  83. spectre_core/receivers/library/_sdrplay_receiver.py +0 -185
  84. spectre_core/receivers/library/_test.py +0 -221
  85. spectre_core-0.0.12.dist-info/RECORD +0 -64
  86. /spectre_core/receivers/{gr → plugins/gr}/__init__.py +0 -0
  87. {spectre_core-0.0.12.dist-info → spectre_core-0.0.13.dist-info}/LICENSE +0 -0
  88. {spectre_core-0.0.12.dist-info → spectre_core-0.0.13.dist-info}/top_level.txt +0 -0
@@ -4,37 +4,63 @@
4
4
 
5
5
  from dataclasses import dataclass
6
6
  from abc import ABC, abstractmethod
7
- from typing import TypeVar, Optional, Any
8
- from numbers import Number
7
+ from typing import TypeVar, Optional, Any, Generic
9
8
 
10
- T = TypeVar('T')
11
-
12
- class PConstraint(ABC):
13
- """Abstract base class for parameter constraints."""
9
+ # value type
10
+ VT = TypeVar('VT')
14
11
 
12
+ class BasePConstraint(ABC, Generic[VT]):
13
+ """An abstract base class for an arbitary parameter constraint."""
15
14
  @abstractmethod
16
- def constrain(self, value: T) -> None:
17
- """Apply a constraint to the input parameter."""
18
- pass
19
-
20
- def __format__(self, format_spec: str = "") -> str:
15
+ def constrain(
16
+ self,
17
+ value: VT
18
+ ) -> None:
19
+ """Apply a constraint to the input parameter. Implementations must raise a `ValueError` for
20
+ if the input value fails the constraint.
21
+
22
+ :param value: The value to be constrained.
23
+ """
24
+
25
+
26
+ def __format__(
27
+ self,
28
+ format_spec: str = ""
29
+ ) -> str:
21
30
  attrs = ", ".join(f"{key}={value!r}" for key, value in vars(self).items())
22
31
  return f"{self.__class__.__name__}({attrs})"
23
32
 
24
- class Bound(PConstraint):
25
- """Constrain a parameter value to a specific range."""
26
33
 
27
- def __init__(self,
28
- lower_bound: Optional[Number] = None,
29
- upper_bound: Optional[Number] = None,
30
- strict_lower: bool = False,
31
- strict_upper: bool = False):
34
+ class Bound(BasePConstraint[float | int]):
35
+ """Bound a numeric parameter value to a some specified interval."""
36
+ def __init__(
37
+ self,
38
+ lower_bound: Optional[float | int] = None,
39
+ upper_bound: Optional[float | int] = None,
40
+ strict_lower: bool = False,
41
+ strict_upper: bool = False
42
+ ) -> None:
43
+ """Create an instance of `Bound`.
44
+
45
+ :param lower_bound: The value must be greater than `lower_bound`. Inclusive if `strict_lower` is False. Defaults to None.
46
+ :param upper_bound: The value must be less than `upper_bound`. Inclusive if `strict_upper` is False. Defaults to None.
47
+ :param strict_lower: If true, the value must be strictly greater than `lower_bound`. Defaults to False.
48
+ :param strict_upper: If true, the value must be strictly less than `upper_bound`. Defaults to False.
49
+ """
32
50
  self._lower_bound = lower_bound
33
51
  self._upper_bound = upper_bound
34
52
  self._strict_lower = strict_lower
35
53
  self._strict_upper = strict_upper
36
54
 
37
- def constrain(self, value: Number) -> None:
55
+ def constrain(
56
+ self,
57
+ value: float | int
58
+ ) -> None:
59
+ """Bound the parameter value to a specified interval.
60
+
61
+ :param value: The value to be constrained.
62
+ :raises ValueError: If the value is outside the specified interval.
63
+ """
38
64
  if self._lower_bound is not None:
39
65
  if self._strict_lower and value <= self._lower_bound:
40
66
  raise ValueError(f"Value must be strictly greater than {self._lower_bound}. "
@@ -51,32 +77,57 @@ class Bound(PConstraint):
51
77
  raise ValueError(f"Value must be less than or equal to {self._upper_bound}. "
52
78
  f"Got {value}.")
53
79
 
80
+ # option type
81
+ OT = TypeVar('OT')
82
+ class OneOf(BasePConstraint[OT]):
83
+ """Constrain a parameter value to be one of a pre-defined list of options."""
84
+ def __init__(
85
+ self,
86
+ options: Optional[list[OT]] = None
87
+ ) -> None:
88
+ """Initialise an instance of `OneOf`.
54
89
 
55
- class OneOf(PConstraint):
56
- """Constrain a parameter to one of a set of defined options."""
90
+ :param options: Input values are required to be one of `options`. If no options are provided,
91
+ it is assumed to be an empty list. Defaults to None.
92
+ """
93
+ self._options = options or []
57
94
 
58
- def __init__(self, options: list[Any] = None):
59
- self._options = options
60
95
 
96
+ def constrain(self, value: OT) -> None:
97
+ """Constrain the input value to be one of a list of pre-defined options.
61
98
 
62
- def constrain(self, value: Any) -> None:
99
+ :param value: The value to be constrained.
100
+ :raises ValueError: If the input value is not one of the pre-defined options.
101
+ """
63
102
  if value not in self._options:
64
103
  raise ValueError(f"Value must be one of {self._options}. Got {value}.")
65
104
 
66
105
 
67
- class _PowerOfTwo(PConstraint):
68
- """Constrain a parameter value to be a power of two."""
69
-
70
- def constrain(self, value: Number) -> None:
106
+ class PowerOfTwo(BasePConstraint[int]):
107
+ """Constrain a numeric parameter value to be a power of two."""
108
+ def constrain(
109
+ self,
110
+ value: int
111
+ ) -> None:
112
+ """Constrain the input value to be a power of two.
113
+
114
+ :param value: The input value to be constrained.
115
+ :raises ValueError: If the input value is not exactly some power of two.
116
+ """
71
117
  if value <= 0 or (value & (value - 1)) != 0:
72
118
  raise ValueError(f"Value must be a power of two. Got {value}.")
73
119
 
74
120
 
75
121
  @dataclass(frozen=True)
76
- class PConstraints:
77
- """Ready-made pconstraint instances for frequent use-cases."""
78
- power_of_two = _PowerOfTwo()
79
- enforce_positive = Bound(lower_bound=0, strict_lower=True)
80
- enforce_negative = Bound(upper_bound=0, strict_upper=True)
81
- enforce_non_negative = Bound(lower_bound=0, strict_lower=False)
82
- enforce_non_positive = Bound(upper_bound=0, strict_upper=False)
122
+ class EnforceSign:
123
+ """Enforce the sign of some value.
124
+
125
+ :ivar positive: Enforce the value to be strictly positive.
126
+ :ivar negative: Enforce the value to be strictly negative.
127
+ :ivar non_negative: Enforce the value to be zero or positive.
128
+ :ivar non_positive: Enforce the value to be zero or negative.
129
+ """
130
+ positive = Bound(lower_bound=0, strict_lower=True)
131
+ negative = Bound(upper_bound=0, strict_upper=True)
132
+ non_negative = Bound(lower_bound=0, strict_lower=False)
133
+ non_positive = Bound(upper_bound=0, strict_upper=False)
@@ -0,0 +1,49 @@
1
+ # SPDX-FileCopyrightText: © 2024 Jimmy Fitzpatrick <jcfitzpatrick12@gmail.com>
2
+ # This file is part of SPECTRE
3
+ # SPDX-License-Identifier: GPL-3.0-or-later
4
+
5
+ from enum import Enum
6
+
7
+ class PName(Enum):
8
+ """A `spectre` capture config parameter name.
9
+
10
+ Each `PName` has an associated base parameter template which can be fetched
11
+ using:
12
+
13
+ `get_base_ptemplate`
14
+
15
+ All parameters and parameter templates must take on some name in `PName`.
16
+ To introduce a new parameter/parameter template, you need to create a new `PName`
17
+ constant.
18
+ """
19
+ CENTER_FREQUENCY = "center_frequency"
20
+ MIN_FREQUENCY = "min_frequency"
21
+ MAX_FREQUENCY = "max_frequency"
22
+ FREQUENCY_STEP = "frequency_step"
23
+ FREQUENCY = "frequency"
24
+ BANDWIDTH = "bandwidth"
25
+ SAMPLE_RATE = "sample_rate"
26
+ IF_GAIN = "if_gain"
27
+ RF_GAIN = "rf_gain"
28
+ AMPLITUDE = "amplitude"
29
+ TIME_RESOLUTION = "time_resolution"
30
+ FREQUENCY_RESOLUTION = "frequency_resolution"
31
+ TIME_RANGE = "time_range"
32
+ BATCH_SIZE = "batch_size"
33
+ WINDOW_TYPE = "window_type"
34
+ WINDOW_HOP = "window_hop"
35
+ WINDOW_SIZE = "window_size"
36
+ EVENT_HANDLER_KEY = "event_handler_key"
37
+ WATCH_EXTENSION = "watch_extension"
38
+ BATCH_KEY = "batch_key"
39
+ SAMPLES_PER_STEP = "samples_per_step"
40
+ MIN_SAMPLES_PER_STEP = "min_samples_per_step"
41
+ MAX_SAMPLES_PER_STEP = "max_samples_per_step"
42
+ STEP_INCREMENT = "step_increment"
43
+ ORIGIN = "origin"
44
+ TELESCOPE = "telescope"
45
+ INSTRUMENT = "instrument"
46
+ OBJECT = "object"
47
+ OBS_LAT = "obs_lat"
48
+ OBS_LON = "obs_lon"
49
+ OBS_ALT = "obs_alt"