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
@@ -2,15 +2,28 @@
2
2
  # This file is part of SPECTRE
3
3
  # SPDX-License-Identifier: GPL-3.0-or-later
4
4
 
5
- from datetime import datetime
5
+ from typing import TypeVar
6
6
 
7
7
  import numpy as np
8
-
9
- def average_array(array: np.ndarray, average_over: int, axis=0) -> np.ndarray:
10
-
11
- # Check if average_over is an integer
12
- if type(average_over) != int:
13
- raise TypeError(f"average_over must be an integer. Got {type(average_over)}")
8
+ import numpy.typing as npt
9
+
10
+
11
+ def average_array(
12
+ array: npt.NDArray[np.float32],
13
+ average_over: int,
14
+ axis: int = 0
15
+ ) -> npt.NDArray[np.float32]:
16
+ """
17
+ Averages elements of an array in blocks along a specified axis.
18
+
19
+ :param array: Input array to be averaged.
20
+ :param average_over: Number of elements in each averaging block.
21
+ :param axis: Axis along which to perform the averaging, defaults to 0.
22
+ :raises TypeError: If `average_over` is not an integer.
23
+ :raises ValueError: If `average_over` is not in the range [1, size of the axis].
24
+ :raises ValueError: If `axis` is out of bounds for the array.
25
+ :return: Array of averaged values along the specified axis.
26
+ """
14
27
 
15
28
  # Get the size of the specified axis which we will average over
16
29
  axis_size = array.shape[axis]
@@ -54,30 +67,39 @@ def average_array(array: np.ndarray, average_over: int, axis=0) -> np.ndarray:
54
67
  return averaged_array
55
68
 
56
69
 
57
- def is_close(ar: np.ndarray,
58
- ar_comparison: np.ndarray,
59
- absolute_tolerance: float) -> bool:
60
- """Close enough accounts for wiggle-room equating floats."""
61
- return np.all(np.isclose(ar,
62
- ar_comparison,
63
- atol=absolute_tolerance))
70
+ def is_close(
71
+ ar: npt.NDArray[np.float32],
72
+ ar_comparison: npt.NDArray[np.float32],
73
+ absolute_tolerance: float
74
+ ) -> bool:
75
+ """
76
+ Checks if all elements in two arrays are element-wise close within a given tolerance.
77
+
78
+ :param ar: First array for comparison.
79
+ :param ar_comparison: Second array for comparison.
80
+ :param absolute_tolerance: Absolute tolerance for element-wise comparison.
81
+ :return: `True` if all elements are close within the specified tolerance, otherwise `False`.
82
+ """
83
+ return bool(np.all(np.isclose(ar,
84
+ ar_comparison,
85
+ atol=absolute_tolerance)))
64
86
 
87
+
88
+ T = TypeVar('T', np.float32, np.datetime64)
65
89
  def find_closest_index(
66
- target_value: float | datetime,
67
- array: np.ndarray,
90
+ target_value: T,
91
+ array: npt.NDArray[T],
68
92
  enforce_strict_bounds: bool = False
69
93
  ) -> int:
70
- # Ensure input array is a numpy array
71
- array = np.asarray(array)
72
-
73
- # Convert to datetime64 if necessary
74
- if isinstance(target_value, datetime) or np.issubdtype(array.dtype, np.datetime64):
75
- target_value = np.datetime64(target_value)
76
- array = array.astype('datetime64[ns]')
77
- else:
78
- target_value = float(target_value)
79
- array = array.astype(float)
80
-
94
+ """
95
+ Finds the index of the closest value to a target in a given array, with optional bounds enforcement.
96
+
97
+ :param target_value: The value to find the closest match for.
98
+ :param array: The array to search within.
99
+ :param enforce_strict_bounds: If True, raises an error if the target value is outside the array bounds. Defaults to False.
100
+ :return: The index of the closest value in the array.
101
+ :raises ValueError: If `enforce_strict_bounds` is True and `target_value` is outside the array bounds.
102
+ """
81
103
  # Check bounds if strict enforcement is required
82
104
  if enforce_strict_bounds:
83
105
  max_value, min_value = np.nanmax(array), np.nanmin(array)
@@ -87,14 +109,31 @@ def find_closest_index(
87
109
  raise ValueError(f"Target value {target_value} is less than min array value {min_value}")
88
110
 
89
111
  # Find the index of the closest value
90
- return np.argmin(np.abs(array - target_value))
112
+ return int( np.argmin(np.abs(array - target_value)) )
91
113
 
92
114
 
93
- def normalise_peak_intensity(array: np.ndarray) -> np.ndarray:
115
+ def normalise_peak_intensity(
116
+ array: npt.NDArray[np.float32]
117
+ ) -> npt.NDArray[np.float32]:
118
+ """
119
+ Normalises an array by its peak intensity.
120
+
121
+ :param array: Input array to normalise.
122
+ :return: Array normalised such that its maximum value is 1. NaN values are ignored.
123
+ """
94
124
  return array/np.nanmax(array)
95
125
 
96
126
 
97
- def compute_resolution(array: np.ndarray) -> float:
127
+ def compute_resolution(
128
+ array: npt.NDArray[np.float32]
129
+ ) -> float:
130
+ """
131
+ Computes the median resolution of a one-dimensional array.
132
+
133
+ :param array: Input one-dimensional array of values.
134
+ :return: The median of differences between consecutive elements in the array.
135
+ :raises ValueError: If the input array is not one-dimensional or contains fewer than two elements.
136
+ """
98
137
  # Check that the array is one-dimensional
99
138
  if array.ndim != 1:
100
139
  raise ValueError("Input array must be one-dimensional")
@@ -104,20 +143,48 @@ def compute_resolution(array: np.ndarray) -> float:
104
143
 
105
144
  # Calculate differences between consecutive elements.
106
145
  resolutions = np.diff(array)
146
+ return float( np.nanmedian(resolutions) )
107
147
 
108
- return np.nanmedian(resolutions)
109
148
 
149
+ def compute_range(
150
+ array: npt.NDArray[np.float32]
151
+ ) -> float:
152
+ """
153
+ Computes the range of a one-dimensional array as the difference between its last and first elements.
110
154
 
111
- def compute_range(array: np.ndarray) -> float:
155
+ :param array: Input one-dimensional array of values.
156
+ :return: The range of the array (last element minus first element).
157
+ :raises ValueError: If the input array is not one-dimensional or contains fewer than two elements.
158
+ """
112
159
  # Check that the array is one-dimensional
113
160
  if array.ndim != 1:
114
161
  raise ValueError("Input array must be one-dimensional")
115
162
 
116
163
  if len(array) < 2:
117
164
  raise ValueError("Input array must contain at least two elements")
118
- return array[-1] - array[0]
165
+ return float( array[-1] - array[0] )
166
+
167
+
168
+ def subtract_background(
169
+ array: npt.NDArray[np.float32],
170
+ start_index: int,
171
+ end_index: int
172
+ ) -> npt.NDArray[np.float32]:
173
+ """
174
+ Subtracts the mean of a specified background range from all elements in an array.
175
+
176
+ :param array: Input array from which the background mean will be subtracted.
177
+ :param start_index: Start index of the background range (inclusive).
178
+ :param end_index: End index of the background range (inclusive).
179
+ :return: Array with the background mean subtracted.
180
+ """
181
+ array -= np.nanmean(array[start_index:end_index+1])
182
+ return array
119
183
 
120
184
 
121
- def subtract_background(array: np.ndarray, start_index: int, end_index: int) -> np.ndarray:
122
- array -= np.nanmean(array[start_index:end_index+1])
123
- return array
185
+ def time_elapsed(
186
+ datetimes: npt.NDArray[np.datetime64]
187
+ ) -> npt.NDArray[np.float32]:
188
+ """Convert an array of datetimes to seconds elapsed."""
189
+ return (datetimes - datetimes[0]).astype('timedelta64[us]').astype(np.float32)
190
+