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,13 +1,13 @@
|
|
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
|
|
5
5
|
"""Basic internal file handling capabilities."""
|
6
6
|
|
7
7
|
from .file_handlers import (
|
8
|
-
BaseFileHandler,
|
8
|
+
BaseFileHandler,
|
9
|
+
JsonHandler,
|
10
|
+
TextHandler,
|
9
11
|
)
|
10
12
|
|
11
|
-
__all__ = [
|
12
|
-
"BaseFileHandler", "JsonHandler", "TextHandler"
|
13
|
-
]
|
13
|
+
__all__ = ["BaseFileHandler", "JsonHandler", "TextHandler"]
|
@@ -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
|
|
@@ -7,14 +7,15 @@ import json
|
|
7
7
|
from abc import ABC, abstractmethod
|
8
8
|
from typing import Any, Optional, TypeVar, Generic
|
9
9
|
|
10
|
-
T = TypeVar(
|
10
|
+
T = TypeVar("T")
|
11
|
+
|
11
12
|
|
12
13
|
class BaseFileHandler(ABC, Generic[T]):
|
13
14
|
"""
|
14
15
|
Base class for handling file operations.
|
15
16
|
|
16
|
-
When subclassing, specify the return type of `_read`
|
17
|
-
using `Generic[T]`.
|
17
|
+
When subclassing, specify the return type of `_read`
|
18
|
+
using `Generic[T]`.
|
18
19
|
|
19
20
|
Example:
|
20
21
|
.. code-block:: python
|
@@ -26,11 +27,9 @@ class BaseFileHandler(ABC, Generic[T]):
|
|
26
27
|
# Implementation here
|
27
28
|
...
|
28
29
|
"""
|
30
|
+
|
29
31
|
def __init__(
|
30
|
-
self,
|
31
|
-
parent_dir_path: str,
|
32
|
-
base_file_name: str,
|
33
|
-
extension: Optional[str] = None
|
32
|
+
self, parent_dir_path: str, base_file_name: str, extension: Optional[str] = None
|
34
33
|
) -> None:
|
35
34
|
"""Initialise a `BaseFileHandler` instance.
|
36
35
|
|
@@ -39,130 +38,101 @@ class BaseFileHandler(ABC, Generic[T]):
|
|
39
38
|
:param extension: The file extension (without the dot), defaults to None
|
40
39
|
"""
|
41
40
|
self._data_cache: Optional[T] = None
|
42
|
-
|
41
|
+
|
43
42
|
self._parent_dir_path = parent_dir_path
|
44
|
-
self._base_file_name
|
45
|
-
|
43
|
+
self._base_file_name = base_file_name
|
44
|
+
|
46
45
|
if extension == "":
|
47
46
|
extension = None
|
48
47
|
self._extension = extension
|
49
48
|
|
50
|
-
|
51
49
|
@abstractmethod
|
52
|
-
def _read(
|
53
|
-
self
|
54
|
-
) -> T:
|
50
|
+
def _read(self) -> T:
|
55
51
|
"""The grunt work to return the file contents.
|
56
52
|
|
57
53
|
:return: The file contents.
|
58
54
|
"""
|
59
|
-
|
60
|
-
|
55
|
+
|
61
56
|
@property
|
62
|
-
def parent_dir_path(
|
63
|
-
self
|
64
|
-
) -> str:
|
57
|
+
def parent_dir_path(self) -> str:
|
65
58
|
"""Return the parent directory path for the file."""
|
66
59
|
return self._parent_dir_path
|
67
|
-
|
68
60
|
|
69
61
|
@property
|
70
|
-
def base_file_name(
|
71
|
-
self
|
72
|
-
) -> str:
|
62
|
+
def base_file_name(self) -> str:
|
73
63
|
"""Return the file name, stripped of the file extension."""
|
74
64
|
return self._base_file_name
|
75
|
-
|
76
65
|
|
77
66
|
@property
|
78
|
-
def extension(
|
79
|
-
self
|
80
|
-
) -> Optional[str]:
|
67
|
+
def extension(self) -> Optional[str]:
|
81
68
|
"""Return the file path suffix, excluding the dot."""
|
82
69
|
return self._extension
|
83
|
-
|
84
70
|
|
85
71
|
@property
|
86
|
-
def file_name(
|
87
|
-
self
|
88
|
-
) -> str:
|
72
|
+
def file_name(self) -> str:
|
89
73
|
"""Generate the file name based on the base name and extension.
|
90
74
|
|
91
75
|
:return: The file name with the extension (including the dot), or the base name if no extension is set.
|
92
76
|
"""
|
93
|
-
return
|
94
|
-
|
77
|
+
return (
|
78
|
+
self._base_file_name
|
79
|
+
if (self._extension is None)
|
80
|
+
else f"{self._base_file_name}.{self._extension}"
|
81
|
+
)
|
95
82
|
|
96
83
|
@property
|
97
|
-
def file_path(
|
98
|
-
self
|
99
|
-
) -> str:
|
84
|
+
def file_path(self) -> str:
|
100
85
|
"""The absolute or relative file path as defined by the parent directory path,
|
101
86
|
base file name and extension."""
|
102
87
|
return os.path.join(self._parent_dir_path, self.file_name)
|
103
|
-
|
104
|
-
|
88
|
+
|
105
89
|
@property
|
106
|
-
def exists(
|
107
|
-
self
|
108
|
-
) -> bool:
|
90
|
+
def exists(self) -> bool:
|
109
91
|
"""Check if the file exists in the filesystem."""
|
110
|
-
return os.path.exists(self.file_path)
|
111
|
-
|
92
|
+
return os.path.exists(self.file_path)
|
112
93
|
|
113
|
-
def read(
|
114
|
-
self,
|
115
|
-
cache: bool = True
|
116
|
-
) -> T:
|
94
|
+
def read(self, cache: bool = True) -> T:
|
117
95
|
"""Read the file contents.
|
118
|
-
|
96
|
+
|
119
97
|
:param cache: If False, bypasses the cache and reads the file directly on each `read` call, defaults to True
|
120
98
|
:return: The file contents.
|
121
99
|
"""
|
122
100
|
# if the user has specified to ignore the cache, simply read the file.
|
123
101
|
if not cache:
|
124
102
|
return self._read()
|
125
|
-
|
103
|
+
|
126
104
|
# otherwise make use of the cache
|
127
105
|
if self._data_cache is None:
|
128
106
|
self._data_cache = self._read()
|
129
107
|
return self._data_cache
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
self
|
134
|
-
) -> None:
|
135
|
-
"""Make the parent directory path of the file. No error is raised if the target
|
108
|
+
|
109
|
+
def make_parent_dir_path(self) -> None:
|
110
|
+
"""Make the parent directory path of the file. No error is raised if the target
|
136
111
|
directory already exists.
|
137
112
|
"""
|
138
|
-
os.makedirs(self.parent_dir_path, exist_ok=True)
|
139
|
-
|
113
|
+
os.makedirs(self.parent_dir_path, exist_ok=True)
|
140
114
|
|
141
|
-
def delete(
|
142
|
-
self,
|
143
|
-
ignore_if_missing: bool = False
|
144
|
-
) -> None:
|
115
|
+
def delete(self, ignore_if_missing: bool = False) -> None:
|
145
116
|
"""Delete the file from the filesystem.
|
146
117
|
|
147
118
|
:param ignore_if_missing: If True, skips deletion if the file does not exist, defaults to False
|
148
119
|
:raises FileNotFoundError: If the file is missing and `ignore_if_missing` is False.
|
149
120
|
"""
|
150
121
|
if not self.exists and not ignore_if_missing:
|
151
|
-
raise FileNotFoundError(
|
122
|
+
raise FileNotFoundError(
|
123
|
+
f"{self.file_name} does not exist, and so cannot be deleted"
|
124
|
+
)
|
152
125
|
else:
|
153
126
|
os.remove(self.file_path)
|
154
|
-
|
155
127
|
|
156
|
-
def cat(
|
157
|
-
self
|
158
|
-
) -> None:
|
128
|
+
def cat(self) -> None:
|
159
129
|
"""Display the file contents on the standard output."""
|
160
130
|
print(self.read())
|
161
131
|
|
162
132
|
|
163
133
|
class JsonHandler(BaseFileHandler[dict[str, Any]]):
|
164
134
|
"""File handler for JSON formatted files.
|
165
|
-
|
135
|
+
|
166
136
|
We assume that the files are of the form
|
167
137
|
{
|
168
138
|
"foo": <JSON compatable structure>
|
@@ -170,29 +140,17 @@ class JsonHandler(BaseFileHandler[dict[str, Any]]):
|
|
170
140
|
}
|
171
141
|
|
172
142
|
"""
|
143
|
+
|
173
144
|
def __init__(
|
174
|
-
self,
|
175
|
-
parent_dir_path: str,
|
176
|
-
base_file_name: str,
|
177
|
-
extension: str = "json"
|
145
|
+
self, parent_dir_path: str, base_file_name: str, extension: str = "json"
|
178
146
|
) -> None:
|
179
|
-
super().__init__(parent_dir_path,
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
def _read(
|
185
|
-
self
|
186
|
-
) -> dict[str, Any]:
|
187
|
-
with open(self.file_path, 'r') as f:
|
147
|
+
super().__init__(parent_dir_path, base_file_name, extension)
|
148
|
+
|
149
|
+
def _read(self) -> dict[str, Any]:
|
150
|
+
with open(self.file_path, "r") as f:
|
188
151
|
return json.load(f)
|
189
|
-
|
190
|
-
|
191
|
-
def save(
|
192
|
-
self,
|
193
|
-
d: dict[str, Any],
|
194
|
-
force: bool = False
|
195
|
-
) -> None:
|
152
|
+
|
153
|
+
def save(self, d: dict[str, Any], force: bool = False) -> None:
|
196
154
|
"""Save the input dictionary to file in the JSON file format.
|
197
155
|
|
198
156
|
:param d: The dictionary to save.
|
@@ -205,29 +163,25 @@ class JsonHandler(BaseFileHandler[dict[str, Any]]):
|
|
205
163
|
if force:
|
206
164
|
pass
|
207
165
|
else:
|
208
|
-
raise FileExistsError(
|
209
|
-
|
166
|
+
raise FileExistsError(
|
167
|
+
(
|
168
|
+
f"{self.file_name} already exists, write has been abandoned. "
|
169
|
+
f"You can override this functionality with `force`"
|
170
|
+
)
|
171
|
+
)
|
210
172
|
|
211
|
-
with open(self.file_path,
|
212
|
-
|
173
|
+
with open(self.file_path, "w") as file:
|
174
|
+
json.dump(d, file, indent=4)
|
213
175
|
|
214
|
-
|
215
176
|
|
216
177
|
class TextHandler(BaseFileHandler[str]):
|
217
178
|
"""File handler for text formatted files."""
|
179
|
+
|
218
180
|
def __init__(
|
219
|
-
self,
|
220
|
-
parent_dir_path: str,
|
221
|
-
base_file_name: str,
|
222
|
-
extension: str = "txt"
|
181
|
+
self, parent_dir_path: str, base_file_name: str, extension: str = "txt"
|
223
182
|
) -> None:
|
224
|
-
super().__init__(parent_dir_path,
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
def _read(
|
230
|
-
self
|
231
|
-
) -> str:
|
232
|
-
with open(self.file_path, 'r') as f:
|
233
|
-
return f.read()
|
183
|
+
super().__init__(parent_dir_path, base_file_name, extension)
|
184
|
+
|
185
|
+
def _read(self) -> str:
|
186
|
+
with open(self.file_path, "r") as f:
|
187
|
+
return f.read()
|
spectre_core/batches/__init__.py
CHANGED
@@ -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
|
|
@@ -10,12 +10,29 @@ from .plugins._batch_keys import BatchKey
|
|
10
10
|
from .plugins._iq_stream import IQStreamBatch, IQMetadata
|
11
11
|
from .plugins._callisto import CallistoBatch
|
12
12
|
|
13
|
-
from ._base import
|
13
|
+
from ._base import (
|
14
|
+
BaseBatch,
|
15
|
+
BatchFile,
|
16
|
+
parse_batch_file_name,
|
17
|
+
parse_batch_base_file_name,
|
18
|
+
)
|
14
19
|
from ._batches import Batches
|
15
20
|
from ._factory import get_batch_cls, get_batch_cls_from_tag
|
16
21
|
|
17
22
|
__all__ = [
|
18
|
-
"IQStreamBatch",
|
19
|
-
"
|
23
|
+
"IQStreamBatch",
|
24
|
+
"IQMetadata",
|
25
|
+
"CallistoBatch",
|
26
|
+
"BaseBatch",
|
27
|
+
"BatchFile",
|
28
|
+
"Batches",
|
29
|
+
"get_batch_cls",
|
30
|
+
"BatchKey",
|
31
|
+
"get_batch_cls_from_tag",
|
32
|
+
"parse_batch_file_name",
|
20
33
|
]
|
21
34
|
|
35
|
+
# To be deprecated.
|
36
|
+
__all__ += [
|
37
|
+
"parse_batch_base_file_name",
|
38
|
+
]
|