spectre-core 0.0.21__py3-none-any.whl → 0.0.23__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 (77) hide show
  1. spectre_core/_file_io/__init__.py +5 -5
  2. spectre_core/_file_io/file_handlers.py +61 -107
  3. spectre_core/batches/__init__.py +21 -4
  4. spectre_core/batches/_base.py +86 -135
  5. spectre_core/batches/_batches.py +56 -100
  6. spectre_core/batches/_factory.py +22 -21
  7. spectre_core/batches/_register.py +9 -9
  8. spectre_core/batches/plugins/_batch_keys.py +8 -7
  9. spectre_core/batches/plugins/_callisto.py +66 -98
  10. spectre_core/batches/plugins/_iq_stream.py +106 -170
  11. spectre_core/capture_configs/__init__.py +47 -18
  12. spectre_core/capture_configs/_capture_config.py +26 -53
  13. spectre_core/capture_configs/_capture_modes.py +9 -7
  14. spectre_core/capture_configs/_capture_templates.py +51 -111
  15. spectre_core/capture_configs/_parameters.py +38 -75
  16. spectre_core/capture_configs/_pconstraints.py +41 -41
  17. spectre_core/capture_configs/_pnames.py +37 -35
  18. spectre_core/capture_configs/_ptemplates.py +261 -348
  19. spectre_core/capture_configs/_pvalidators.py +99 -102
  20. spectre_core/config/__init__.py +14 -9
  21. spectre_core/config/_paths.py +19 -36
  22. spectre_core/config/_time_formats.py +7 -6
  23. spectre_core/exceptions.py +39 -1
  24. spectre_core/jobs/__init__.py +4 -7
  25. spectre_core/jobs/_duration.py +12 -0
  26. spectre_core/jobs/_jobs.py +73 -44
  27. spectre_core/jobs/_workers.py +56 -106
  28. spectre_core/logs/__init__.py +8 -3
  29. spectre_core/logs/_configure.py +14 -18
  30. spectre_core/logs/_decorators.py +7 -5
  31. spectre_core/logs/_logs.py +38 -90
  32. spectre_core/logs/_process_types.py +6 -4
  33. spectre_core/plotting/__init__.py +14 -4
  34. spectre_core/plotting/_base.py +65 -139
  35. spectre_core/plotting/_format.py +11 -9
  36. spectre_core/plotting/_panel_names.py +8 -6
  37. spectre_core/plotting/_panel_stack.py +83 -116
  38. spectre_core/plotting/_panels.py +121 -156
  39. spectre_core/post_processing/__init__.py +7 -4
  40. spectre_core/post_processing/_base.py +69 -69
  41. spectre_core/post_processing/_factory.py +15 -12
  42. spectre_core/post_processing/_post_processor.py +17 -13
  43. spectre_core/post_processing/_register.py +11 -8
  44. spectre_core/post_processing/plugins/_event_handler_keys.py +5 -4
  45. spectre_core/post_processing/plugins/_fixed_center_frequency.py +55 -48
  46. spectre_core/post_processing/plugins/_swept_center_frequency.py +200 -175
  47. spectre_core/receivers/__init__.py +10 -3
  48. spectre_core/receivers/_base.py +83 -149
  49. spectre_core/receivers/_factory.py +21 -31
  50. spectre_core/receivers/_register.py +8 -11
  51. spectre_core/receivers/_spec_names.py +18 -16
  52. spectre_core/receivers/plugins/_b200mini.py +48 -61
  53. spectre_core/receivers/plugins/_receiver_names.py +9 -7
  54. spectre_core/receivers/plugins/_rsp1a.py +45 -41
  55. spectre_core/receivers/plugins/_rspduo.py +60 -45
  56. spectre_core/receivers/plugins/_sdrplay_receiver.py +68 -84
  57. spectre_core/receivers/plugins/_test.py +137 -130
  58. spectre_core/receivers/plugins/_usrp.py +94 -86
  59. spectre_core/receivers/plugins/gr/__init__.py +2 -2
  60. spectre_core/receivers/plugins/gr/_base.py +15 -23
  61. spectre_core/receivers/plugins/gr/_rsp1a.py +53 -60
  62. spectre_core/receivers/plugins/gr/_rspduo.py +78 -90
  63. spectre_core/receivers/plugins/gr/_test.py +50 -58
  64. spectre_core/receivers/plugins/gr/_usrp.py +61 -59
  65. spectre_core/spectrograms/__init__.py +22 -14
  66. spectre_core/spectrograms/_analytical.py +109 -100
  67. spectre_core/spectrograms/_array_operations.py +40 -47
  68. spectre_core/spectrograms/_spectrogram.py +290 -323
  69. spectre_core/spectrograms/_transform.py +107 -74
  70. spectre_core/wgetting/__init__.py +2 -4
  71. spectre_core/wgetting/_callisto.py +88 -94
  72. {spectre_core-0.0.21.dist-info → spectre_core-0.0.23.dist-info}/METADATA +9 -23
  73. spectre_core-0.0.23.dist-info/RECORD +79 -0
  74. {spectre_core-0.0.21.dist-info → spectre_core-0.0.23.dist-info}/WHEEL +1 -1
  75. spectre_core-0.0.21.dist-info/RECORD +0 -78
  76. {spectre_core-0.0.21.dist-info → spectre_core-0.0.23.dist-info}/licenses/LICENSE +0 -0
  77. {spectre_core-0.0.21.dist-info → spectre_core-0.0.23.dist-info}/top_level.txt +0 -0
@@ -1,4 +1,4 @@
1
- # SPDX-FileCopyrightText: © 2024 Jimmy Fitzpatrick <jcfitzpatrick12@gmail.com>
1
+ # SPDX-FileCopyrightText: © 2024-2025 Jimmy Fitzpatrick <jcfitzpatrick12@gmail.com>
2
2
  # This file is part of SPECTRE
3
3
  # SPDX-License-Identifier: GPL-3.0-or-later
4
4
 
@@ -9,9 +9,7 @@ import numpy.typing as npt
9
9
 
10
10
 
11
11
  def average_array(
12
- array: npt.NDArray[np.float32],
13
- average_over: int,
14
- axis: int = 0
12
+ array: npt.NDArray[np.float32], average_over: int, axis: int = 0
15
13
  ) -> npt.NDArray[np.float32]:
16
14
  """
17
15
  Averages elements of an array in blocks along a specified axis.
@@ -29,11 +27,15 @@ def average_array(
29
27
  axis_size = array.shape[axis]
30
28
  # Check if average_over is within the valid range
31
29
  if not 1 <= average_over <= axis_size:
32
- raise ValueError(f"average_over must be between 1 and the length of the axis ({axis_size})")
33
-
30
+ raise ValueError(
31
+ f"average_over must be between 1 and the length of the axis ({axis_size})"
32
+ )
33
+
34
34
  max_axis_index = len(np.shape(array)) - 1
35
- if axis > max_axis_index: # zero indexing on specifying axis, so minus one
36
- raise ValueError(f"Requested axis is out of range of array dimensions. Axis: {axis}, max axis index: {max_axis_index}")
35
+ if axis > max_axis_index: # zero indexing on specifying axis, so minus one
36
+ raise ValueError(
37
+ f"Requested axis is out of range of array dimensions. Axis: {axis}, max axis index: {max_axis_index}"
38
+ )
37
39
 
38
40
  # find the number of elements in the requested axis
39
41
  num_elements = array.shape[axis]
@@ -43,7 +45,7 @@ def average_array(
43
45
  # if num_elements is not exactly divisible by average_over, we will have some elements left over
44
46
  # these remaining elements will be padded with nans to become another full block
45
47
  remainder = num_elements % average_over
46
-
48
+
47
49
  # if there exists a remainder, pad the last block
48
50
  if remainder != 0:
49
51
  # initialise an array to hold the padding shape
@@ -51,8 +53,8 @@ def average_array(
51
53
  # pad after the last column in the requested axis
52
54
  padding_shape[axis] = (0, average_over - remainder)
53
55
  # pad with nan values (so to not contribute towards the mean computation)
54
- array = np.pad(array, padding_shape, mode='constant', constant_values=np.nan)
55
-
56
+ array = np.pad(array, padding_shape, mode="constant", constant_values=np.nan)
57
+
56
58
  # initalise a list to hold the new shape
57
59
  new_shape = list(array.shape)
58
60
  # update the shape on the requested access (to the number of blocks we will average over)
@@ -68,9 +70,9 @@ def average_array(
68
70
 
69
71
 
70
72
  def is_close(
71
- ar: npt.NDArray[np.float32],
73
+ ar: npt.NDArray[np.float32],
72
74
  ar_comparison: npt.NDArray[np.float32],
73
- absolute_tolerance: float
75
+ absolute_tolerance: float,
74
76
  ) -> bool:
75
77
  """
76
78
  Checks if all elements in two arrays are element-wise close within a given tolerance.
@@ -80,16 +82,14 @@ def is_close(
80
82
  :param absolute_tolerance: Absolute tolerance for element-wise comparison.
81
83
  :return: `True` if all elements are close within the specified tolerance, otherwise `False`.
82
84
  """
83
- return bool(np.all(np.isclose(ar,
84
- ar_comparison,
85
- atol=absolute_tolerance)))
85
+ return bool(np.all(np.isclose(ar, ar_comparison, atol=absolute_tolerance)))
86
+
87
+
88
+ T = TypeVar("T", np.float32, np.datetime64)
86
89
 
87
90
 
88
- T = TypeVar('T', np.float32, np.datetime64)
89
91
  def find_closest_index(
90
- target_value: T,
91
- array: npt.NDArray[T],
92
- enforce_strict_bounds: bool = False
92
+ target_value: T, array: npt.NDArray[T], enforce_strict_bounds: bool = False
93
93
  ) -> int:
94
94
  """
95
95
  Finds the index of the closest value to a target in a given array, with optional bounds enforcement.
@@ -104,29 +104,29 @@ def find_closest_index(
104
104
  if enforce_strict_bounds:
105
105
  max_value, min_value = np.nanmax(array), np.nanmin(array)
106
106
  if target_value > max_value:
107
- raise ValueError(f"Target value {target_value} exceeds max array value {max_value}")
107
+ raise ValueError(
108
+ f"Target value {target_value} exceeds max array value {max_value}"
109
+ )
108
110
  if target_value < min_value:
109
- raise ValueError(f"Target value {target_value} is less than min array value {min_value}")
111
+ raise ValueError(
112
+ f"Target value {target_value} is less than min array value {min_value}"
113
+ )
110
114
 
111
115
  # Find the index of the closest value
112
- return int( np.argmin(np.abs(array - target_value)) )
116
+ return int(np.argmin(np.abs(array - target_value)))
113
117
 
114
118
 
115
- def normalise_peak_intensity(
116
- array: npt.NDArray[np.float32]
117
- ) -> npt.NDArray[np.float32]:
119
+ def normalise_peak_intensity(array: npt.NDArray[np.float32]) -> npt.NDArray[np.float32]:
118
120
  """
119
121
  Normalises an array by its peak intensity.
120
122
 
121
123
  :param array: Input array to normalise.
122
124
  :return: Array normalised such that its maximum value is 1. NaN values are ignored.
123
125
  """
124
- return array/np.nanmax(array)
126
+ return array / np.nanmax(array)
125
127
 
126
128
 
127
- def compute_resolution(
128
- array: npt.NDArray[np.float32]
129
- ) -> float:
129
+ def compute_resolution(array: npt.NDArray[np.float32]) -> float:
130
130
  """
131
131
  Computes the median resolution of a one-dimensional array.
132
132
 
@@ -137,18 +137,16 @@ def compute_resolution(
137
137
  # Check that the array is one-dimensional
138
138
  if array.ndim != 1:
139
139
  raise ValueError("Input array must be one-dimensional")
140
-
140
+
141
141
  if len(array) < 2:
142
142
  raise ValueError("Input array must contain at least two elements")
143
-
143
+
144
144
  # Calculate differences between consecutive elements.
145
145
  resolutions = np.diff(array)
146
- return float( np.nanmedian(resolutions) )
146
+ return float(np.nanmedian(resolutions))
147
147
 
148
148
 
149
- def compute_range(
150
- array: npt.NDArray[np.float32]
151
- ) -> float:
149
+ def compute_range(array: npt.NDArray[np.float32]) -> float:
152
150
  """
153
151
  Computes the range of a one-dimensional array as the difference between its last and first elements.
154
152
 
@@ -159,16 +157,14 @@ def compute_range(
159
157
  # Check that the array is one-dimensional
160
158
  if array.ndim != 1:
161
159
  raise ValueError("Input array must be one-dimensional")
162
-
160
+
163
161
  if len(array) < 2:
164
162
  raise ValueError("Input array must contain at least two elements")
165
- return float( array[-1] - array[0] )
163
+ return float(array[-1] - array[0])
166
164
 
167
165
 
168
166
  def subtract_background(
169
- array: npt.NDArray[np.float32],
170
- start_index: int,
171
- end_index: int
167
+ array: npt.NDArray[np.float32], start_index: int, end_index: int
172
168
  ) -> npt.NDArray[np.float32]:
173
169
  """
174
170
  Subtracts the mean of a specified background range from all elements in an array.
@@ -178,13 +174,10 @@ def subtract_background(
178
174
  :param end_index: End index of the background range (inclusive).
179
175
  :return: Array with the background mean subtracted.
180
176
  """
181
- array -= np.nanmean(array[start_index:end_index+1])
177
+ array -= np.nanmean(array[start_index : end_index + 1])
182
178
  return array
183
179
 
184
180
 
185
- def time_elapsed(
186
- datetimes: npt.NDArray[np.datetime64]
187
- ) -> npt.NDArray[np.float32]:
181
+ def time_elapsed(datetimes: npt.NDArray[np.datetime64]) -> npt.NDArray[np.float32]:
188
182
  """Convert an array of datetimes to seconds elapsed."""
189
- return (datetimes - datetimes[0]).astype('timedelta64[us]') / np.timedelta64(1, 's')
190
-
183
+ return (datetimes - datetimes[0]).astype("timedelta64[us]") / np.timedelta64(1, "s")