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.
- spectre_core/_file_io/__init__.py +5 -5
- spectre_core/_file_io/file_handlers.py +61 -107
- spectre_core/batches/__init__.py +21 -4
- spectre_core/batches/_base.py +86 -135
- spectre_core/batches/_batches.py +56 -100
- spectre_core/batches/_factory.py +22 -21
- spectre_core/batches/_register.py +9 -9
- spectre_core/batches/plugins/_batch_keys.py +8 -7
- spectre_core/batches/plugins/_callisto.py +66 -98
- spectre_core/batches/plugins/_iq_stream.py +106 -170
- spectre_core/capture_configs/__init__.py +47 -18
- spectre_core/capture_configs/_capture_config.py +26 -53
- spectre_core/capture_configs/_capture_modes.py +9 -7
- spectre_core/capture_configs/_capture_templates.py +51 -111
- spectre_core/capture_configs/_parameters.py +38 -75
- spectre_core/capture_configs/_pconstraints.py +41 -41
- spectre_core/capture_configs/_pnames.py +37 -35
- spectre_core/capture_configs/_ptemplates.py +261 -348
- spectre_core/capture_configs/_pvalidators.py +99 -102
- spectre_core/config/__init__.py +14 -9
- spectre_core/config/_paths.py +19 -36
- spectre_core/config/_time_formats.py +7 -6
- spectre_core/exceptions.py +39 -1
- spectre_core/jobs/__init__.py +4 -7
- spectre_core/jobs/_duration.py +12 -0
- spectre_core/jobs/_jobs.py +73 -44
- spectre_core/jobs/_workers.py +56 -106
- spectre_core/logs/__init__.py +8 -3
- spectre_core/logs/_configure.py +14 -18
- spectre_core/logs/_decorators.py +7 -5
- spectre_core/logs/_logs.py +38 -90
- spectre_core/logs/_process_types.py +6 -4
- spectre_core/plotting/__init__.py +14 -4
- spectre_core/plotting/_base.py +65 -139
- spectre_core/plotting/_format.py +11 -9
- spectre_core/plotting/_panel_names.py +8 -6
- spectre_core/plotting/_panel_stack.py +83 -116
- spectre_core/plotting/_panels.py +121 -156
- spectre_core/post_processing/__init__.py +7 -4
- spectre_core/post_processing/_base.py +69 -69
- spectre_core/post_processing/_factory.py +15 -12
- spectre_core/post_processing/_post_processor.py +17 -13
- spectre_core/post_processing/_register.py +11 -8
- spectre_core/post_processing/plugins/_event_handler_keys.py +5 -4
- spectre_core/post_processing/plugins/_fixed_center_frequency.py +55 -48
- spectre_core/post_processing/plugins/_swept_center_frequency.py +200 -175
- spectre_core/receivers/__init__.py +10 -3
- spectre_core/receivers/_base.py +83 -149
- spectre_core/receivers/_factory.py +21 -31
- spectre_core/receivers/_register.py +8 -11
- spectre_core/receivers/_spec_names.py +18 -16
- spectre_core/receivers/plugins/_b200mini.py +48 -61
- spectre_core/receivers/plugins/_receiver_names.py +9 -7
- spectre_core/receivers/plugins/_rsp1a.py +45 -41
- spectre_core/receivers/plugins/_rspduo.py +60 -45
- spectre_core/receivers/plugins/_sdrplay_receiver.py +68 -84
- spectre_core/receivers/plugins/_test.py +137 -130
- spectre_core/receivers/plugins/_usrp.py +94 -86
- spectre_core/receivers/plugins/gr/__init__.py +2 -2
- spectre_core/receivers/plugins/gr/_base.py +15 -23
- spectre_core/receivers/plugins/gr/_rsp1a.py +53 -60
- spectre_core/receivers/plugins/gr/_rspduo.py +78 -90
- spectre_core/receivers/plugins/gr/_test.py +50 -58
- spectre_core/receivers/plugins/gr/_usrp.py +61 -59
- spectre_core/spectrograms/__init__.py +22 -14
- spectre_core/spectrograms/_analytical.py +109 -100
- spectre_core/spectrograms/_array_operations.py +40 -47
- spectre_core/spectrograms/_spectrogram.py +290 -323
- spectre_core/spectrograms/_transform.py +107 -74
- spectre_core/wgetting/__init__.py +2 -4
- spectre_core/wgetting/_callisto.py +88 -94
- {spectre_core-0.0.21.dist-info → spectre_core-0.0.23.dist-info}/METADATA +9 -23
- spectre_core-0.0.23.dist-info/RECORD +79 -0
- {spectre_core-0.0.21.dist-info → spectre_core-0.0.23.dist-info}/WHEEL +1 -1
- spectre_core-0.0.21.dist-info/RECORD +0 -78
- {spectre_core-0.0.21.dist-info → spectre_core-0.0.23.dist-info}/licenses/LICENSE +0 -0
- {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(
|
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:
|
36
|
-
raise ValueError(
|
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=
|
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
|
-
|
85
|
-
|
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(
|
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(
|
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(
|
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(
|
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(
|
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(
|
190
|
-
|
183
|
+
return (datetimes - datetimes[0]).astype("timedelta64[us]") / np.timedelta64(1, "s")
|