spectre-core 0.0.8__py3-none-any.whl → 0.0.10__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/__init__.py +0 -3
- spectre_core/_file_io/__init__.py +15 -0
- spectre_core/_file_io/file_handlers.py +128 -0
- spectre_core/capture_configs/__init__.py +29 -0
- spectre_core/capture_configs/_capture_config.py +85 -0
- spectre_core/capture_configs/_capture_templates.py +222 -0
- spectre_core/capture_configs/_parameters.py +110 -0
- spectre_core/capture_configs/_pconstraints.py +82 -0
- spectre_core/capture_configs/_ptemplates.py +450 -0
- spectre_core/capture_configs/_pvalidators.py +173 -0
- spectre_core/chunks/__init__.py +17 -201
- spectre_core/chunks/{base.py → _base.py} +15 -60
- spectre_core/chunks/_chunks.py +200 -0
- spectre_core/chunks/{factory.py → _factory.py} +6 -7
- spectre_core/chunks/library/{callisto/chunk.py → _callisto.py} +4 -7
- spectre_core/chunks/library/{fixed/chunk.py → _fixed_center_frequency.py} +7 -64
- spectre_core/chunks/library/_swept_center_frequency.py +103 -0
- spectre_core/config/__init__.py +20 -0
- spectre_core/config/_paths.py +77 -0
- spectre_core/config/_time_formats.py +15 -0
- spectre_core/exceptions.py +4 -5
- spectre_core/logging/__init__.py +11 -0
- spectre_core/logging/_configure.py +35 -0
- spectre_core/logging/_decorators.py +19 -0
- spectre_core/{logging.py → logging/_log_handlers.py} +13 -58
- spectre_core/plotting/__init__.py +7 -1
- spectre_core/plotting/{base.py → _base.py} +40 -20
- spectre_core/plotting/_format.py +18 -0
- spectre_core/plotting/{panel_stack.py → _panel_stack.py} +50 -48
- spectre_core/plotting/_panels.py +234 -0
- spectre_core/post_processing/__init__.py +14 -0
- spectre_core/post_processing/_base.py +119 -0
- spectre_core/post_processing/_factory.py +23 -0
- spectre_core/post_processing/_post_processor.py +40 -0
- spectre_core/post_processing/library/_fixed_center_frequency.py +115 -0
- spectre_core/post_processing/library/_swept_center_frequency.py +382 -0
- spectre_core/receivers/__init__.py +12 -2
- spectre_core/receivers/_base.py +352 -0
- spectre_core/receivers/{factory.py → _factory.py} +2 -2
- spectre_core/receivers/_spec_names.py +20 -0
- spectre_core/receivers/gr/__init__.py +3 -0
- spectre_core/receivers/gr/_base.py +33 -0
- spectre_core/receivers/gr/_rsp1a.py +158 -0
- spectre_core/receivers/gr/_test.py +123 -0
- spectre_core/receivers/library/_rsp1a.py +61 -0
- spectre_core/receivers/library/_test.py +221 -0
- spectre_core/spectrograms/__init__.py +18 -0
- spectre_core/spectrograms/{analytical.py → _analytical.py} +29 -27
- spectre_core/spectrograms/{array_operations.py → _array_operations.py} +47 -1
- spectre_core/spectrograms/{spectrogram.py → _spectrogram.py} +62 -35
- spectre_core/spectrograms/{transform.py → _transform.py} +76 -89
- spectre_core/{receivers/library → wgetting}/__init__.py +4 -2
- spectre_core/wgetting/_callisto.py +155 -0
- {spectre_core-0.0.8.dist-info → spectre_core-0.0.10.dist-info}/METADATA +1 -1
- spectre_core-0.0.10.dist-info/RECORD +63 -0
- spectre_core/cfg.py +0 -116
- spectre_core/chunks/library/__init__.py +0 -8
- spectre_core/chunks/library/sweep/__init__.py +0 -0
- spectre_core/chunks/library/sweep/chunk.py +0 -400
- spectre_core/dynamic_imports.py +0 -22
- spectre_core/file_handlers/base.py +0 -68
- spectre_core/file_handlers/configs.py +0 -271
- spectre_core/file_handlers/json.py +0 -40
- spectre_core/file_handlers/text.py +0 -21
- spectre_core/plotting/factory.py +0 -26
- spectre_core/plotting/format.py +0 -19
- spectre_core/plotting/library/__init__.py +0 -7
- spectre_core/plotting/library/frequency_cuts/panel.py +0 -74
- spectre_core/plotting/library/integral_over_frequency/panel.py +0 -34
- spectre_core/plotting/library/spectrogram/panel.py +0 -92
- spectre_core/plotting/library/time_cuts/panel.py +0 -77
- spectre_core/plotting/panel_register.py +0 -13
- spectre_core/receivers/base.py +0 -415
- spectre_core/receivers/library/rsp1a/__init__.py +0 -0
- spectre_core/receivers/library/rsp1a/gr/__init__.py +0 -0
- spectre_core/receivers/library/rsp1a/gr/fixed.py +0 -104
- spectre_core/receivers/library/rsp1a/gr/sweep.py +0 -129
- spectre_core/receivers/library/rsp1a/receiver.py +0 -68
- spectre_core/receivers/library/rspduo/__init__.py +0 -0
- spectre_core/receivers/library/rspduo/gr/__init__.py +0 -0
- spectre_core/receivers/library/rspduo/gr/tuner_1_fixed.py +0 -114
- spectre_core/receivers/library/rspduo/gr/tuner_1_sweep.py +0 -131
- spectre_core/receivers/library/rspduo/gr/tuner_2_fixed.py +0 -120
- spectre_core/receivers/library/rspduo/gr/tuner_2_sweep.py +0 -119
- spectre_core/receivers/library/rspduo/receiver.py +0 -97
- spectre_core/receivers/library/test/__init__.py +0 -0
- spectre_core/receivers/library/test/gr/__init__.py +0 -0
- spectre_core/receivers/library/test/gr/cosine_signal_1.py +0 -83
- spectre_core/receivers/library/test/gr/tagged_staircase.py +0 -93
- spectre_core/receivers/library/test/receiver.py +0 -178
- spectre_core/receivers/validators.py +0 -193
- spectre_core/watchdog/__init__.py +0 -6
- spectre_core/watchdog/base.py +0 -105
- spectre_core/watchdog/factory.py +0 -22
- spectre_core/watchdog/library/__init__.py +0 -10
- spectre_core/watchdog/library/fixed/__init__.py +0 -0
- spectre_core/watchdog/library/fixed/event_handler.py +0 -41
- spectre_core/watchdog/library/sweep/event_handler.py +0 -55
- spectre_core/watchdog/post_processor.py +0 -50
- spectre_core/web_fetch/callisto.py +0 -101
- spectre_core-0.0.8.dist-info/RECORD +0 -74
- /spectre_core/chunks/{chunk_register.py → _register.py} +0 -0
- /spectre_core/{watchdog/event_handler_register.py → post_processing/_register.py} +0 -0
- /spectre_core/receivers/{receiver_register.py → _register.py} +0 -0
- /spectre_core/{chunks/library/callisto/__init__.py → receivers/gr/_rspduo.py} +0 -0
- /spectre_core/{chunks/library/fixed/__init__.py → receivers/library/_rspduo.py} +0 -0
- {spectre_core-0.0.8.dist-info → spectre_core-0.0.10.dist-info}/LICENSE +0 -0
- {spectre_core-0.0.8.dist-info → spectre_core-0.0.10.dist-info}/WHEEL +0 -0
- {spectre_core-0.0.8.dist-info → spectre_core-0.0.10.dist-info}/top_level.txt +0 -0
@@ -1,77 +0,0 @@
|
|
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 typing import Optional
|
6
|
-
|
7
|
-
from spectre_core.spectrograms.spectrogram import TimeCut
|
8
|
-
from spectre_core.spectrograms.spectrogram import Spectrogram
|
9
|
-
from spectre_core.plotting.base import BaseTimeSeriesPanel, CutsPanel
|
10
|
-
from spectre_core.plotting.format import DEFAULT_FORMATS
|
11
|
-
from spectre_core.plotting.panel_register import register_panel
|
12
|
-
|
13
|
-
TIME_CUTS_PANEL_NAME = "time_cuts"
|
14
|
-
|
15
|
-
@register_panel(TIME_CUTS_PANEL_NAME)
|
16
|
-
class Panel(BaseTimeSeriesPanel, CutsPanel):
|
17
|
-
def __init__(self,
|
18
|
-
name: str,
|
19
|
-
spectrogram: Spectrogram,
|
20
|
-
time_type: str = "seconds",
|
21
|
-
*frequencies: list[float],
|
22
|
-
dBb: bool = False,
|
23
|
-
peak_normalise: bool = False,
|
24
|
-
background_subtract: bool = False,
|
25
|
-
cmap: str = DEFAULT_FORMATS.cuts_cmap,
|
26
|
-
**kwargs):
|
27
|
-
super().__init__(name,
|
28
|
-
spectrogram,
|
29
|
-
time_type,
|
30
|
-
**kwargs)
|
31
|
-
self._frequencies = frequencies
|
32
|
-
self._cmap = cmap
|
33
|
-
self._dBb = dBb
|
34
|
-
self._peak_normalise = peak_normalise
|
35
|
-
self._background_subtract = background_subtract
|
36
|
-
# map each cut frequency to the corresponding TimeCut dataclass
|
37
|
-
self._time_cuts: Optional[dict[float, TimeCut]] = {}
|
38
|
-
|
39
|
-
|
40
|
-
@property
|
41
|
-
def time_cuts(self) -> dict[float, TimeCut]:
|
42
|
-
if not self._time_cuts:
|
43
|
-
for frequency in self._frequencies:
|
44
|
-
time_cut = self._spectrogram.get_time_cut(frequency,
|
45
|
-
dBb = self._dBb,
|
46
|
-
peak_normalise = self._peak_normalise,
|
47
|
-
correct_background = self._background_subtract,
|
48
|
-
return_time_type=self._time_type)
|
49
|
-
self._time_cuts[time_cut.frequency] = time_cut
|
50
|
-
return self._time_cuts
|
51
|
-
|
52
|
-
|
53
|
-
@property
|
54
|
-
def frequencies(self) -> list[float]:
|
55
|
-
return list(self.time_cuts.keys())
|
56
|
-
|
57
|
-
|
58
|
-
def draw(self):
|
59
|
-
for frequency, color in self.bind_to_colors():
|
60
|
-
time_cut = self.time_cuts[frequency]
|
61
|
-
self.ax.step(self.times,
|
62
|
-
time_cut.cut,
|
63
|
-
where='mid',
|
64
|
-
color = color)
|
65
|
-
|
66
|
-
|
67
|
-
def annotate_y_axis(self) -> None:
|
68
|
-
if self._dBb:
|
69
|
-
self.ax.set_ylabel('dBb')
|
70
|
-
elif self._peak_normalise:
|
71
|
-
return # no y-axis label
|
72
|
-
else:
|
73
|
-
self.ax.set_ylabel(f'{self._spectrogram.spectrum_type.capitalize()}')
|
74
|
-
|
75
|
-
|
76
|
-
def bind_to_colors(self):
|
77
|
-
return super().bind_to_colors(self.frequencies, cmap = self._cmap)
|
@@ -1,13 +0,0 @@
|
|
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
|
-
|
6
|
-
# Global dictionaries to hold the mappings
|
7
|
-
panels = {}
|
8
|
-
|
9
|
-
def register_panel(panel_name: str):
|
10
|
-
def decorator(cls):
|
11
|
-
panels[panel_name] = cls
|
12
|
-
return cls
|
13
|
-
return decorator
|
spectre_core/receivers/base.py
DELETED
@@ -1,415 +0,0 @@
|
|
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 abc import ABC, abstractmethod
|
6
|
-
from typing import Callable, Any, Optional
|
7
|
-
|
8
|
-
from spectre_core.receivers import validators
|
9
|
-
from spectre_core.file_handlers.configs import (
|
10
|
-
CaptureConfig,
|
11
|
-
validate_against_type_template,
|
12
|
-
type_cast_params
|
13
|
-
)
|
14
|
-
from spectre_core.exceptions import (
|
15
|
-
TemplateNotFoundError,
|
16
|
-
ModeNotFoundError,
|
17
|
-
SpecificationNotFoundError
|
18
|
-
)
|
19
|
-
|
20
|
-
|
21
|
-
class BaseReceiver(ABC):
|
22
|
-
def __init__(self, name: str, mode: Optional[str] = None):
|
23
|
-
self._name = name
|
24
|
-
|
25
|
-
self._capture_methods: dict[str, Callable] = None
|
26
|
-
self._set_capture_methods()
|
27
|
-
|
28
|
-
self._type_templates: dict[str, dict[str, Any]] = None
|
29
|
-
self._set_type_templates()
|
30
|
-
|
31
|
-
self._validators: dict[str, Callable] = None
|
32
|
-
self._set_validators()
|
33
|
-
|
34
|
-
self._specifications: dict[str, Any] = None
|
35
|
-
self._set_specifications()
|
36
|
-
|
37
|
-
self.mode = mode
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
@abstractmethod
|
42
|
-
def _set_capture_methods(self) -> None:
|
43
|
-
pass
|
44
|
-
|
45
|
-
|
46
|
-
@abstractmethod
|
47
|
-
def _set_validators(self) -> None:
|
48
|
-
pass
|
49
|
-
|
50
|
-
@abstractmethod
|
51
|
-
def _set_type_templates(self) -> None:
|
52
|
-
pass
|
53
|
-
|
54
|
-
|
55
|
-
@abstractmethod
|
56
|
-
def _set_specifications(self) -> None:
|
57
|
-
pass
|
58
|
-
|
59
|
-
|
60
|
-
@property
|
61
|
-
def name(self) -> str:
|
62
|
-
return self._name
|
63
|
-
|
64
|
-
|
65
|
-
@property
|
66
|
-
def capture_methods(self) -> dict[str, Callable]:
|
67
|
-
return self._capture_methods
|
68
|
-
|
69
|
-
|
70
|
-
@property
|
71
|
-
def validators(self) -> dict[str, Callable]:
|
72
|
-
return self._validators
|
73
|
-
|
74
|
-
|
75
|
-
@property
|
76
|
-
def type_templates(self) -> dict[str, dict[str, Any]]:
|
77
|
-
return self._type_templates
|
78
|
-
|
79
|
-
|
80
|
-
@property
|
81
|
-
def specifications(self) -> dict[dict, Any]:
|
82
|
-
return self._specifications
|
83
|
-
|
84
|
-
|
85
|
-
@property
|
86
|
-
def valid_modes(self) -> None:
|
87
|
-
capture_method_modes = list(self.capture_methods.keys())
|
88
|
-
validator_modes = list(self.validators.keys())
|
89
|
-
type_template_modes = list(self.type_templates.keys())
|
90
|
-
|
91
|
-
if capture_method_modes == validator_modes == type_template_modes:
|
92
|
-
return capture_method_modes
|
93
|
-
else:
|
94
|
-
raise ValueError(f"Mode mismatch for the receiver {self.name}. Could not define valid modes")
|
95
|
-
|
96
|
-
@property
|
97
|
-
def mode(self) -> str:
|
98
|
-
return self._mode
|
99
|
-
|
100
|
-
|
101
|
-
@mode.setter
|
102
|
-
def mode(self, value: Optional[str]) -> None:
|
103
|
-
if (value is not None) and value not in self.valid_modes:
|
104
|
-
raise ModeNotFoundError((f"{value} is not a defined mode for the receiver {self.name}. "
|
105
|
-
f"Expected one of {self.valid_modes}"))
|
106
|
-
self._mode = value
|
107
|
-
|
108
|
-
|
109
|
-
@property
|
110
|
-
def mode_is_set(self) -> bool:
|
111
|
-
return (self._mode is not None)
|
112
|
-
|
113
|
-
|
114
|
-
@property
|
115
|
-
def capture_method(self) -> Callable:
|
116
|
-
return self.capture_methods[self.mode]
|
117
|
-
|
118
|
-
|
119
|
-
@property
|
120
|
-
def validator(self) -> Callable:
|
121
|
-
return self.validators[self.mode]
|
122
|
-
|
123
|
-
|
124
|
-
@property
|
125
|
-
def type_template(self) -> dict[str, Any]:
|
126
|
-
return self._type_templates[self.mode]
|
127
|
-
|
128
|
-
|
129
|
-
def get_specification(self,
|
130
|
-
specification_key: str) -> Any:
|
131
|
-
specification = self.specifications.get(specification_key)
|
132
|
-
if specification is None:
|
133
|
-
expected_specifications = list(self.specifications.keys())
|
134
|
-
raise SpecificationNotFoundError(f"Invalid specification '{specification_key}'. Expected one of {expected_specifications}")
|
135
|
-
return specification
|
136
|
-
|
137
|
-
|
138
|
-
def validate_capture_config(self,
|
139
|
-
capture_config: CaptureConfig) -> None:
|
140
|
-
# validate against the active type template
|
141
|
-
validate_against_type_template(capture_config,
|
142
|
-
self.type_template,
|
143
|
-
ignore_keys=["receiver", "mode", "tag"])
|
144
|
-
# validate against receiver-specific constraints
|
145
|
-
self.validator(capture_config)
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
def start_capture(self,
|
150
|
-
tag: str) -> None:
|
151
|
-
capture_config = self.load_capture_config(tag)
|
152
|
-
self.capture_method(capture_config)
|
153
|
-
|
154
|
-
|
155
|
-
def save_params(self,
|
156
|
-
params: list[str],
|
157
|
-
tag: str,
|
158
|
-
force: bool = False) -> None:
|
159
|
-
d = type_cast_params(params,
|
160
|
-
self.type_template)
|
161
|
-
|
162
|
-
validate_against_type_template(d,
|
163
|
-
self.type_template)
|
164
|
-
|
165
|
-
self.save_capture_config(d,
|
166
|
-
tag,
|
167
|
-
force = force)
|
168
|
-
|
169
|
-
|
170
|
-
def save_capture_config(self,
|
171
|
-
d: dict[str, Any],
|
172
|
-
tag: str,
|
173
|
-
force: bool = False) -> None:
|
174
|
-
|
175
|
-
self.validate_capture_config(d)
|
176
|
-
|
177
|
-
d.update({"receiver": self.name,
|
178
|
-
"mode": self.mode,
|
179
|
-
"tag": tag})
|
180
|
-
|
181
|
-
capture_config = CaptureConfig(tag)
|
182
|
-
capture_config.save(d,
|
183
|
-
force = force)
|
184
|
-
|
185
|
-
|
186
|
-
def load_capture_config(self,
|
187
|
-
tag: str) -> CaptureConfig:
|
188
|
-
|
189
|
-
capture_config = CaptureConfig(tag)
|
190
|
-
|
191
|
-
if capture_config["receiver"] != self.name:
|
192
|
-
raise ValueError(f"Capture config receiver mismatch for tag {tag}. Expected {self.name}, got {capture_config['receiver']}")
|
193
|
-
|
194
|
-
if capture_config["mode"] != self.mode:
|
195
|
-
raise ValueError(f"Mode mismatch for the tag {tag}. Expected {self.mode}, got {capture_config['mode']}")
|
196
|
-
|
197
|
-
self.validate_capture_config(capture_config)
|
198
|
-
return capture_config
|
199
|
-
|
200
|
-
|
201
|
-
def get_create_capture_config_cmd(self,
|
202
|
-
tag: str,
|
203
|
-
as_string: bool = False) -> str:
|
204
|
-
"""Get a command which can be used to create a capture config with the SPECTRE CLI."""
|
205
|
-
command_as_list = ["spectre", "create", "capture-config",
|
206
|
-
"--tag", tag,
|
207
|
-
"--receiver", self.name,
|
208
|
-
"--mode", self.mode]
|
209
|
-
for key, value in self.type_template.items():
|
210
|
-
command_as_list.extend(["-p", f"{key}={value.__name__}"])
|
211
|
-
|
212
|
-
return " ".join(command_as_list) if as_string else command_as_list
|
213
|
-
|
214
|
-
|
215
|
-
# optional parent class which provides default templates and validators
|
216
|
-
class SPECTREReceiver(BaseReceiver):
|
217
|
-
def __init__(self, *args, **kwargs):
|
218
|
-
self.__set_default_type_templates()
|
219
|
-
super().__init__(*args, **kwargs)
|
220
|
-
|
221
|
-
|
222
|
-
@property
|
223
|
-
def default_type_templates(self) -> dict[str, dict[str, Any]]:
|
224
|
-
return self._default_type_templates
|
225
|
-
|
226
|
-
|
227
|
-
def __set_default_type_templates(self) -> None:
|
228
|
-
self._default_type_templates = {
|
229
|
-
"fixed": {
|
230
|
-
"center_freq": float, # [Hz]
|
231
|
-
"bandwidth": float, # [Hz]
|
232
|
-
"samp_rate": int, # [Hz]
|
233
|
-
"IF_gain": int, # [dB]
|
234
|
-
"RF_gain": int, # [dB]
|
235
|
-
"chunk_size": int, # [s]
|
236
|
-
"joining_time": int, # [s]
|
237
|
-
"time_resolution": float, # [s]
|
238
|
-
"frequency_resolution": float, # [Hz]
|
239
|
-
"window_type": str, # window type for STFFT
|
240
|
-
"window_kwargs": dict, # keyword arguments for window function, must be in order as in scipy documentation.
|
241
|
-
"window_size": int, # number of samples in STFFT window
|
242
|
-
"hop": int, # STFFT window hops by so many samples
|
243
|
-
"chunk_key": str, # maps to the corresponding chunk class
|
244
|
-
"event_handler_key": str, # maps to the event handler used in post processing
|
245
|
-
},
|
246
|
-
"sweep": {
|
247
|
-
"min_freq": float, # [Hz]
|
248
|
-
"max_freq": float, # [Hz]
|
249
|
-
"samples_per_step": int,
|
250
|
-
"freq_step": float, # [Hz]
|
251
|
-
"bandwidth": float, # [Hz]
|
252
|
-
"samp_rate": int, # [Hz]
|
253
|
-
"IF_gain": int, # [dB]
|
254
|
-
"RF_gain": int, # [dB]
|
255
|
-
"chunk_size": int, # [s]
|
256
|
-
"joining_time": int, # [s]
|
257
|
-
"time_resolution": float, # [s]
|
258
|
-
"frequency_resolution": float, # [Hz]
|
259
|
-
"window_type": str, # window type for STFFT
|
260
|
-
"window_kwargs": dict, # keyword arguments for window function, must be in order as in scipy documentation.
|
261
|
-
"window_size": int, # number of samples in STFFT window
|
262
|
-
"hop": int, # keyword arguments for the scipy STFFT class
|
263
|
-
"chunk_key": str, # maps to the corresponding chunk class
|
264
|
-
"event_handler_key": str, # maps to the event handler used in post processing
|
265
|
-
}
|
266
|
-
}
|
267
|
-
|
268
|
-
|
269
|
-
def _get_default_type_template(self,
|
270
|
-
mode: str) -> dict:
|
271
|
-
default_type_template = self.default_type_templates[mode]
|
272
|
-
if default_type_template is None:
|
273
|
-
raise TemplateNotFoundError(f"No default template found for the mode {mode}")
|
274
|
-
return default_type_template
|
275
|
-
|
276
|
-
|
277
|
-
def _default_sweep_validator(self,
|
278
|
-
capture_config: CaptureConfig) -> None:
|
279
|
-
min_freq = capture_config["min_freq"]
|
280
|
-
max_freq = capture_config["max_freq"]
|
281
|
-
samples_per_step = capture_config["samples_per_step"]
|
282
|
-
freq_step = capture_config["freq_step"]
|
283
|
-
bandwidth = capture_config["bandwidth"]
|
284
|
-
samp_rate = capture_config["samp_rate"]
|
285
|
-
IF_gain = capture_config["IF_gain"]
|
286
|
-
RF_gain = capture_config["RF_gain"]
|
287
|
-
chunk_size = capture_config["chunk_size"]
|
288
|
-
time_resolution = capture_config["time_resolution"]
|
289
|
-
window_type = capture_config["window_type"]
|
290
|
-
window_kwargs = capture_config["window_kwargs"]
|
291
|
-
window_size = capture_config["window_size"]
|
292
|
-
hop = capture_config["hop"]
|
293
|
-
chunk_key = capture_config["chunk_key"]
|
294
|
-
event_handler_key = capture_config[ "event_handler_key"]
|
295
|
-
|
296
|
-
validators.center_freq_strictly_positive(min_freq)
|
297
|
-
validators.center_freq_strictly_positive(max_freq)
|
298
|
-
validators.samp_rate_strictly_positive(samp_rate)
|
299
|
-
validators.bandwidth_strictly_positive(bandwidth)
|
300
|
-
validators.nyquist_criterion(samp_rate,
|
301
|
-
bandwidth)
|
302
|
-
validators.chunk_size_strictly_positive(chunk_size)
|
303
|
-
validators.time_resolution(time_resolution,
|
304
|
-
chunk_size)
|
305
|
-
validators.window(window_type,
|
306
|
-
window_kwargs,
|
307
|
-
window_size,
|
308
|
-
chunk_size,
|
309
|
-
samp_rate)
|
310
|
-
validators.hop(hop)
|
311
|
-
validators.chunk_key(chunk_key, "sweep")
|
312
|
-
validators.event_handler_key(event_handler_key, "sweep")
|
313
|
-
validators.gain_is_negative(IF_gain)
|
314
|
-
validators.gain_is_negative(RF_gain)
|
315
|
-
validators.num_steps_per_sweep(min_freq,
|
316
|
-
max_freq,
|
317
|
-
samp_rate,
|
318
|
-
freq_step)
|
319
|
-
validators.sweep_interval(min_freq,
|
320
|
-
max_freq,
|
321
|
-
samp_rate,
|
322
|
-
freq_step,
|
323
|
-
samples_per_step,
|
324
|
-
chunk_size)
|
325
|
-
validators.non_overlapping_steps(freq_step,
|
326
|
-
samp_rate)
|
327
|
-
validators.num_samples_per_step(samples_per_step,
|
328
|
-
window_size)
|
329
|
-
|
330
|
-
# if the api latency is defined, raise a warning if the step interval is of the same order
|
331
|
-
api_latency = self.specifications.get("api_latency")
|
332
|
-
if api_latency:
|
333
|
-
validators.step_interval(samples_per_step,
|
334
|
-
samp_rate,
|
335
|
-
api_latency)
|
336
|
-
|
337
|
-
|
338
|
-
def _default_fixed_validator(self,
|
339
|
-
capture_config: CaptureConfig) -> None:
|
340
|
-
center_freq = capture_config["center_freq"]
|
341
|
-
bandwidth = capture_config["bandwidth"]
|
342
|
-
samp_rate = capture_config["samp_rate"]
|
343
|
-
IF_gain = capture_config["IF_gain"]
|
344
|
-
RF_gain = capture_config["RF_gain"]
|
345
|
-
chunk_size = capture_config["chunk_size"]
|
346
|
-
time_resolution = capture_config["time_resolution"]
|
347
|
-
window_type = capture_config["window_type"]
|
348
|
-
window_kwargs = capture_config["window_kwargs"]
|
349
|
-
window_size = capture_config["window_size"]
|
350
|
-
hop = capture_config["hop"]
|
351
|
-
chunk_key = capture_config["chunk_key"]
|
352
|
-
event_handler_key = capture_config["event_handler_key"]
|
353
|
-
|
354
|
-
validators.center_freq_strictly_positive(center_freq)
|
355
|
-
validators.samp_rate_strictly_positive(samp_rate)
|
356
|
-
validators.bandwidth_strictly_positive(bandwidth)
|
357
|
-
validators.nyquist_criterion(samp_rate, bandwidth)
|
358
|
-
validators.chunk_size_strictly_positive(chunk_size)
|
359
|
-
validators.time_resolution(time_resolution, chunk_size)
|
360
|
-
validators.window(window_type,
|
361
|
-
window_kwargs,
|
362
|
-
window_size,
|
363
|
-
chunk_size,
|
364
|
-
samp_rate)
|
365
|
-
validators.hop(hop)
|
366
|
-
validators.chunk_key(chunk_key,
|
367
|
-
"fixed")
|
368
|
-
validators.event_handler_key(event_handler_key,
|
369
|
-
"fixed")
|
370
|
-
validators.gain_is_negative(IF_gain)
|
371
|
-
validators.gain_is_negative(RF_gain)
|
372
|
-
|
373
|
-
|
374
|
-
# parent class for shared methods and attributes of SDRPlay receivers
|
375
|
-
class SDRPlayReceiver(SPECTREReceiver):
|
376
|
-
def __init__(self, *args, **kwargs):
|
377
|
-
super().__init__(*args, **kwargs)
|
378
|
-
|
379
|
-
def _sdrplay_validator(self,
|
380
|
-
capture_config: CaptureConfig) -> None:
|
381
|
-
# RSPduo specific validations in single tuner mode
|
382
|
-
center_freq_lower_bound = self.get_specification("center_freq_lower_bound")
|
383
|
-
center_freq_upper_bound = self.get_specification("center_freq_upper_bound")
|
384
|
-
center_freq = capture_config.get("center_freq")
|
385
|
-
min_freq = capture_config.get("min_freq")
|
386
|
-
max_freq = capture_config.get("max_freq")
|
387
|
-
|
388
|
-
if center_freq:
|
389
|
-
validators.closed_confine_center_freq(center_freq,
|
390
|
-
center_freq_lower_bound,
|
391
|
-
center_freq_upper_bound)
|
392
|
-
|
393
|
-
if min_freq:
|
394
|
-
validators.closed_confine_center_freq(min_freq,
|
395
|
-
center_freq_lower_bound,
|
396
|
-
center_freq_upper_bound)
|
397
|
-
if max_freq:
|
398
|
-
validators.closed_confine_center_freq(max_freq,
|
399
|
-
center_freq_lower_bound,
|
400
|
-
center_freq_upper_bound)
|
401
|
-
|
402
|
-
validators.closed_confine_samp_rate(capture_config["samp_rate"],
|
403
|
-
self.get_specification("samp_rate_lower_bound"),
|
404
|
-
self.get_specification("samp_rate_upper_bound"))
|
405
|
-
|
406
|
-
|
407
|
-
validators.closed_confine_bandwidth(capture_config["bandwidth"],
|
408
|
-
self.get_specification("bandwidth_lower_bound"),
|
409
|
-
self.get_specification("bandwidth_upper_bound"))
|
410
|
-
|
411
|
-
validators.closed_upper_bound_IF_gain(capture_config["IF_gain"],
|
412
|
-
self.get_specification("IF_gain_upper_bound"))
|
413
|
-
|
414
|
-
validators.closed_upper_bound_RF_gain(capture_config["RF_gain"],
|
415
|
-
self.get_specification("RF_gain_upper_bound"))
|
File without changes
|
File without changes
|
@@ -1,104 +0,0 @@
|
|
1
|
-
#!/usr/bin/env python3
|
2
|
-
# -*- coding: utf-8 -*-
|
3
|
-
|
4
|
-
# SPDX-License-Identifier: GPL-3.0
|
5
|
-
#
|
6
|
-
# GNU Radio Python Flow Graph
|
7
|
-
# Title: Not titled yet
|
8
|
-
# GNU Radio version: 3.10.1.1
|
9
|
-
|
10
|
-
# SPDX-FileCopyrightText: © 2024 Jimmy Fitzpatrick <jcfitzpatrick12@gmail.com>
|
11
|
-
# This file is part of SPECTRE
|
12
|
-
# SPDX-License-Identifier: GPL-3.0-or-later
|
13
|
-
|
14
|
-
import sys
|
15
|
-
import signal
|
16
|
-
from argparse import ArgumentParser
|
17
|
-
from typing import Any
|
18
|
-
|
19
|
-
from gnuradio import gr
|
20
|
-
from gnuradio.filter import firdes
|
21
|
-
from gnuradio.fft import window
|
22
|
-
from gnuradio.eng_arg import eng_float, intx
|
23
|
-
from gnuradio import eng_notation
|
24
|
-
from gnuradio import sdrplay3
|
25
|
-
from gnuradio import spectre
|
26
|
-
|
27
|
-
from spectre_core.cfg import CHUNKS_DIR_PATH
|
28
|
-
from spectre_core.file_handlers.configs import CaptureConfig
|
29
|
-
|
30
|
-
class fixed(gr.top_block):
|
31
|
-
|
32
|
-
def __init__(self,
|
33
|
-
capture_config: CaptureConfig):
|
34
|
-
gr.top_block.__init__(self, "fixed", catch_exceptions=True)
|
35
|
-
|
36
|
-
##################################################
|
37
|
-
# Unpack capture config
|
38
|
-
##################################################
|
39
|
-
samp_rate = capture_config['samp_rate']
|
40
|
-
tag = capture_config['tag']
|
41
|
-
chunk_size = capture_config['chunk_size']
|
42
|
-
center_freq = capture_config['center_freq']
|
43
|
-
bandwidth = capture_config['bandwidth']
|
44
|
-
IF_gain = capture_config['IF_gain']
|
45
|
-
RF_gain = capture_config['RF_gain']
|
46
|
-
is_sweeping = False
|
47
|
-
|
48
|
-
##################################################
|
49
|
-
# Blocks
|
50
|
-
##################################################
|
51
|
-
self.spectre_batched_file_sink_0 = spectre.batched_file_sink(CHUNKS_DIR_PATH, tag, chunk_size, samp_rate, is_sweeping)
|
52
|
-
self.sdrplay3_rsp1a_0 = sdrplay3.rsp1a(
|
53
|
-
'',
|
54
|
-
stream_args=sdrplay3.stream_args(
|
55
|
-
output_type='fc32',
|
56
|
-
channels_size=1
|
57
|
-
),
|
58
|
-
)
|
59
|
-
self.sdrplay3_rsp1a_0.set_sample_rate(samp_rate)
|
60
|
-
self.sdrplay3_rsp1a_0.set_center_freq(center_freq)
|
61
|
-
self.sdrplay3_rsp1a_0.set_bandwidth(bandwidth)
|
62
|
-
self.sdrplay3_rsp1a_0.set_gain_mode(False)
|
63
|
-
self.sdrplay3_rsp1a_0.set_gain(IF_gain, 'IF')
|
64
|
-
self.sdrplay3_rsp1a_0.set_gain(RF_gain, 'RF')
|
65
|
-
self.sdrplay3_rsp1a_0.set_freq_corr(0)
|
66
|
-
self.sdrplay3_rsp1a_0.set_dc_offset_mode(False)
|
67
|
-
self.sdrplay3_rsp1a_0.set_iq_balance_mode(False)
|
68
|
-
self.sdrplay3_rsp1a_0.set_agc_setpoint(-30)
|
69
|
-
self.sdrplay3_rsp1a_0.set_rf_notch_filter(False)
|
70
|
-
self.sdrplay3_rsp1a_0.set_dab_notch_filter(False)
|
71
|
-
self.sdrplay3_rsp1a_0.set_biasT(False)
|
72
|
-
self.sdrplay3_rsp1a_0.set_debug_mode(False)
|
73
|
-
self.sdrplay3_rsp1a_0.set_sample_sequence_gaps_check(False)
|
74
|
-
self.sdrplay3_rsp1a_0.set_show_gain_changes(False)
|
75
|
-
|
76
|
-
|
77
|
-
##################################################
|
78
|
-
# Connections
|
79
|
-
##################################################
|
80
|
-
self.connect((self.sdrplay3_rsp1a_0, 0), (self.spectre_batched_file_sink_0, 0))
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
def main(capture_config: CaptureConfig,
|
87
|
-
top_block_cls=fixed,
|
88
|
-
options=None):
|
89
|
-
|
90
|
-
tb = top_block_cls(capture_config)
|
91
|
-
|
92
|
-
def sig_handler(sig=None, frame=None):
|
93
|
-
tb.stop()
|
94
|
-
tb.wait()
|
95
|
-
|
96
|
-
sys.exit(0)
|
97
|
-
|
98
|
-
signal.signal(signal.SIGINT, sig_handler)
|
99
|
-
signal.signal(signal.SIGTERM, sig_handler)
|
100
|
-
|
101
|
-
tb.start()
|
102
|
-
|
103
|
-
tb.wait()
|
104
|
-
|