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
@@ -7,145 +7,200 @@ import subprocess
7
7
  import shutil
8
8
  import gzip
9
9
  from datetime import datetime
10
- from typing import Optional
11
-
12
- from spectre_core.config import get_spectre_data_dir_path, get_batches_dir_path, TimeFormats
13
-
14
- CALLISTO_INSTRUMENT_CODES = [
15
- "ALASKA-ANCHORAGE",
16
- "ALASKA-COHOE",
17
- "ALASKA-HAARP",
18
- "ALGERIA-CRAAG",
19
- "ALMATY",
20
- "AUSTRIA-Krumbach",
21
- "AUSTRIA-MICHELBACH",
22
- "AUSTRIA-OE3FLB",
23
- "AUSTRIA-UNIGRAZ",
24
- "Australia-ASSA",
25
- "BIR",
26
- "Croatia-Visnjan",
27
- "DENMARK",
28
- "EGYPT-Alexandria",
29
- "EGYPT-SpaceAgency",
30
- "FINLAND-Siuntio",
31
- "Finland-Kempele",
32
- "GERMANY-DLR",
33
- "GLASGOW",
34
- "GREENLAND",
35
- "HUMAIN",
36
- "HURBANOVO",
37
- "INDIA-GAURI",
38
- "INDIA-OOTY",
39
- "INDIA-UDAIPUR",
40
- "JAPAN-IBARAKI",
41
- "KASI",
42
- "MEXART",
43
- "MEXICO-FCFM-UANL",
44
- "MEXICO-LANCE-A",
45
- "MEXICO-LANCE-B",
46
- "MONGOLIA-UB",
47
- "MRO",
48
- "MRT3",
49
- "Malaysia-Banting",
50
- "NORWAY-EGERSUND",
51
- "NORWAY-NY-AALESUND",
52
- "NORWAY-RANDABERG",
53
- "POLAND-Grotniki",
54
- "ROMANIA",
55
- "ROSWELL-NM",
56
- "SPAIN-PERALEJOS",
57
- "SSRT",
58
- "SWISS-HB9SCT",
59
- "SWISS-HEITERSWIL",
60
- "SWISS-IRSOL",
61
- "SWISS-Landschlacht",
62
- "SWISS-MUHEN",
63
- "TRIEST",
64
- "TURKEY",
65
- "UNAM",
66
- "URUGUAY",
67
- "USA-BOSTON",
68
- ]
69
-
70
- _temp_dir = os.path.join(get_spectre_data_dir_path(), "temp")
71
-
72
-
73
- def _get_batch_name(station: str, date: str, time: str, instrument_code: str) -> str:
74
- dt = datetime.strptime(f"{date}T{time}", '%Y%m%dT%H%M%S')
75
- formatted_time = dt.strftime(TimeFormats.DATETIME)
76
- return f"{formatted_time}_callisto-{station.lower()}-{instrument_code}.fits"
77
-
78
-
79
- def _get_batch_components(gz_path: str):
10
+
11
+ from spectre_core.config import get_spectre_data_dir_path, get_batches_dir_path, TimeFormat
12
+
13
+ from enum import Enum
14
+
15
+ class CallistoInstrumentCode(Enum):
16
+ """e-Callisto network station codes."""
17
+ ALASKA_ANCHORAGE = "ALASKA-ANCHORAGE"
18
+ ALASKA_COHOE = "ALASKA-COHOE"
19
+ ALASKA_HAARP = "ALASKA-HAARP"
20
+ ALGERIA_CRAAG = "ALGERIA-CRAAG"
21
+ ALMATY = "ALMATY"
22
+ AUSTRIA_KRUMBACH = "AUSTRIA-Krumbach"
23
+ AUSTRIA_MICHELBACH = "AUSTRIA-MICHELBACH"
24
+ AUSTRIA_OE3FLB = "AUSTRIA-OE3FLB"
25
+ AUSTRIA_UNIGRAZ = "AUSTRIA-UNIGRAZ"
26
+ AUSTRALIA_ASSA = "Australia-ASSA"
27
+ BIR = "BIR"
28
+ CROATIA_VISNJAN = "Croatia-Visnjan"
29
+ DENMARK = "DENMARK"
30
+ EGYPT_ALEXANDRIA = "EGYPT-Alexandria"
31
+ EGYPT_SPACEAGENCY = "EGYPT-SpaceAgency"
32
+ FINLAND_SIUNTIO = "FINLAND-Siuntio"
33
+ FINLAND_KEMPELE = "Finland-Kempele"
34
+ GERMANY_DLR = "GERMANY-DLR"
35
+ GLASGOW = "GLASGOW"
36
+ GREENLAND = "GREENLAND"
37
+ HUMAIN = "HUMAIN"
38
+ HURBANOVO = "HURBANOVO"
39
+ INDIA_GAURI = "INDIA-GAURI"
40
+ INDIA_OOTY = "INDIA-OOTY"
41
+ INDIA_UDAIPUR = "INDIA-UDAIPUR"
42
+ JAPAN_IBARAKI = "JAPAN-IBARAKI"
43
+ KASI = "KASI"
44
+ MEXART = "MEXART"
45
+ MEXICO_FCFM_UANL = "MEXICO-FCFM-UANL"
46
+ MEXICO_LANCE_A = "MEXICO-LANCE-A"
47
+ MEXICO_LANCE_B = "MEXICO-LANCE-B"
48
+ MONGOLIA_UB = "MONGOLIA-UB"
49
+ MRO = "MRO"
50
+ MRT3 = "MRT3"
51
+ MALAYSIA_BANTING = "Malaysia-Banting"
52
+ NORWAY_EGERSUND = "NORWAY-EGERSUND"
53
+ NORWAY_NY_AALESUND = "NORWAY-NY-AALESUND"
54
+ NORWAY_RANDABERG = "NORWAY-RANDABERG"
55
+ POLAND_GROTNIKI = "POLAND-Grotniki"
56
+ ROMANIA = "ROMANIA"
57
+ ROSWELL_NM = "ROSWELL-NM"
58
+ SPAIN_PERALEJOS = "SPAIN-PERALEJOS"
59
+ SSRT = "SSRT"
60
+ SWISS_HB9SCT = "SWISS-HB9SCT"
61
+ SWISS_HEITERSWIL = "SWISS-HEITERSWIL"
62
+ SWISS_IRSOL = "SWISS-IRSOL"
63
+ SWISS_LANDSCHLACHT = "SWISS-Landschlacht"
64
+ SWISS_MUHEN = "SWISS-MUHEN"
65
+ TRIEST = "TRIEST"
66
+ TURKEY = "TURKEY"
67
+ UNAM = "UNAM"
68
+ URUGUAY = "URUGUAY"
69
+ USA_BOSTON = "USA-BOSTON"
70
+
71
+
72
+ def _get_batch_name(
73
+ station: str,
74
+ date: str,
75
+ time: str,
76
+ code: str
77
+ ) -> str:
78
+ """
79
+ Create a standardised batch file name for a `spectre` batch file.
80
+
81
+ :param station: Station name.
82
+ :param date: Observation date in 'YYYYMMDD' format.
83
+ :param time: Observation time in 'HHMMSS' format.
84
+ :param code: Numeric instrument code.
85
+ :return: Formatted batch file name.
86
+ """
87
+ dt = datetime.strptime(f"{date}T{time}", "%Y%m%dT%H%M%S")
88
+ formatted_time = dt.strftime(TimeFormat.DATETIME)
89
+ return f"{formatted_time}_callisto-{station.lower()}-{code}.fits"
90
+
91
+
92
+ def _get_batch_components(
93
+ gz_path: str
94
+ ) -> list[str]:
95
+ """
96
+ Extract station, date, time, and instrument code from the `.fit.gz` file name.
97
+
98
+ :param gz_path: Path to the `.fit.gz` file.
99
+ :return: List of [station, date, time, instrument_code].
100
+ :raises ValueError: If file format is invalid.
101
+ """
80
102
  file_name = os.path.basename(gz_path)
81
103
  if not file_name.endswith(".fit.gz"):
82
- raise ValueError(f"Unexpected file extension in {file_name}. Expected .fit.gz")
83
-
104
+ raise ValueError(f"Invalid file extension: {file_name}. Expected .fit.gz")
84
105
  file_base_name = file_name.rstrip(".fit.gz")
85
106
  parts = file_base_name.split('_')
86
107
  if len(parts) != 4:
87
- raise ValueError("Filename does not conform to the expected format of [station]_[date]_[time]_[instrument_code]")
88
-
108
+ raise ValueError("Invalid file name format. Expected '[station]_[date]_[time]_[code].fit.gz'")
89
109
  return parts
90
110
 
91
111
 
92
- def _get_batch_path(gz_path: str) -> str:
93
- station, date, time, instrument_code = _get_batch_components(gz_path)
94
- fits_batch_name = _get_batch_name(station, date, time, instrument_code)
95
- batch_start_time = fits_batch_name.split('_')[0]
96
- batch_start_datetime = datetime.strptime(batch_start_time, TimeFormats.DATETIME)
97
- batch_parent_path = get_batches_dir_path(year = batch_start_datetime.year,
98
- month = batch_start_datetime.month,
99
- day = batch_start_datetime.day)
100
- if not os.path.exists(batch_parent_path):
101
- os.makedirs(batch_parent_path)
102
- return os.path.join(batch_parent_path, fits_batch_name)
103
-
104
-
105
- def _unzip_file_to_batches(gz_path: str):
112
+ def _get_batch_path(
113
+ gz_path: str
114
+ ) -> str:
115
+ """
116
+ Generate the full path for the `spectre` batch file.
117
+
118
+ :param gz_path: Path to the raw `.fit.gz` file.
119
+ :return: Path to the corresponding batch file.
120
+ """
121
+ station, date, time, code = _get_batch_components(gz_path)
122
+ batch_name = _get_batch_name(station, date, time, code)
123
+ batch_start_time = batch_name.split("_")[0]
124
+ dt = datetime.strptime(batch_start_time, TimeFormat.DATETIME)
125
+ batch_dir = get_batches_dir_path(year=dt.year, month=dt.month, day=dt.day)
126
+ os.makedirs(batch_dir, exist_ok=True)
127
+ return os.path.join(batch_dir, batch_name)
128
+
129
+
130
+ def _unzip_file_to_batches(
131
+ gz_path: str
132
+ ) -> None:
133
+ """
134
+ Decompress a `.fit.gz` file and save it as a `.fits` batch file.
135
+
136
+ :param gz_path: Path to the `.fit.gz` file.
137
+ """
106
138
  fits_path = _get_batch_path(gz_path)
107
- with gzip.open(gz_path, 'rb') as f_in, open(fits_path, 'wb') as f_out:
139
+ with gzip.open(gz_path, "rb") as f_in, open(fits_path, "wb") as f_out:
108
140
  shutil.copyfileobj(f_in, f_out)
109
141
 
110
142
 
111
- def _unzip_to_batches():
112
- for entry in os.scandir(_temp_dir):
113
- if entry.is_file() and entry.name.endswith('.gz'):
143
+ def _unzip_to_batches(
144
+ tmp_dir: str
145
+ ) -> None:
146
+ """
147
+ Decompress all `.gz` files in a temporary directory and save them as `spectre`
148
+ batch files.
149
+
150
+ :param tmp_dir: Path to the temporary directory containing `.gz` files.
151
+ """
152
+ for entry in os.scandir(tmp_dir):
153
+ if entry.is_file() and entry.name.endswith(".gz"):
114
154
  _unzip_file_to_batches(entry.path)
115
155
  os.remove(entry.path)
116
156
 
117
157
 
118
- def _wget_callisto_data(instrument_code: str,
119
- year: int,
120
- month: int,
121
- day: int):
158
+ def _wget_callisto_data(
159
+ instrument_code: str,
160
+ year: int,
161
+ month: int,
162
+ day: int,
163
+ tmp_dir: str
164
+ ) -> None:
165
+ """
166
+ Download raw `.fit.gz` files from the e-Callisto network using `wget`.
167
+
168
+ :param instrument_code: Instrument code for filtering files.
169
+ :param year: Observation year.
170
+ :param month: Observation month.
171
+ :param day: Observation day.
172
+ :param tmp_dir: Path to the temporary directory for downloads.
173
+ """
122
174
  date_str = f"{year:04d}/{month:02d}/{day:02d}"
123
175
  base_url = f"http://soleil.i4ds.ch/solarradio/data/2002-20yy_Callisto/{date_str}/"
124
176
  command = [
125
- 'wget', '-r', '-l1', '-nd', '-np',
126
- '-R', '.tmp',
127
- '-A', f'{instrument_code}*.fit.gz',
128
- '-P', _temp_dir,
129
- base_url
177
+ "wget", "-r", "-l1", "-nd", "-np",
178
+ "-R", ".tmp", "-A", f"{instrument_code}*.fit.gz",
179
+ "-P", tmp_dir, base_url
130
180
  ]
131
181
  subprocess.run(command, check=True)
132
182
 
133
183
 
134
- def download_callisto_data(instrument_code: Optional[str],
135
- year: Optional[int],
136
- month: Optional[int],
137
- day: Optional[int]):
138
-
139
-
140
- if (year is None) or (month is None) or (day is None):
141
- raise ValueError(f"All of year, month and day should be specified")
184
+ def download_callisto_data(
185
+ instrument_code: CallistoInstrumentCode,
186
+ year: int,
187
+ month: int,
188
+ day: int
189
+ ) -> None:
190
+ """
191
+ Download and decompress e-Callisto FITS files, saving them as `spectre` batch files.
192
+
193
+ :param instrument_code: e-Callisto station instrument code.
194
+ :param year: Year of the observation.
195
+ :param month: Month of the observation.
196
+ :param day: Day of the observation.
197
+ """
198
+ tmp_dir = os.path.join(get_spectre_data_dir_path(), "tmp")
199
+ # if there are any residual files in the temporary directory, remove them.
200
+ if os.path.exists(tmp_dir):
201
+ shutil.rmtree(tmp_dir)
202
+ os.makedirs(tmp_dir, exist_ok=True)
142
203
 
143
- if not os.path.exists(_temp_dir):
144
- os.mkdir(_temp_dir)
145
-
146
- if instrument_code not in CALLISTO_INSTRUMENT_CODES:
147
- raise ValueError(f"No match found for '{instrument_code}'. Expected one of {CALLISTO_INSTRUMENT_CODES}")
148
-
149
- _wget_callisto_data(instrument_code, year, month, day)
150
- _unzip_to_batches()
151
- shutil.rmtree(_temp_dir)
204
+ _wget_callisto_data(instrument_code.value, year, month, day, tmp_dir)
205
+ _unzip_to_batches(tmp_dir)
206
+ shutil.rmtree(tmp_dir)
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: spectre-core
3
- Version: 0.0.12
3
+ Version: 0.0.13
4
4
  Summary: The core Python package used by the spectre program.
5
5
  Maintainer-email: Jimmy Fitzpatrick <jcfitzpatrick12@gmail.com>
6
6
  License: GNU GENERAL PUBLIC LICENSE
@@ -691,6 +691,7 @@ Requires-Dist: scipy==1.12.0
691
691
  Requires-Dist: astropy==6.0.1
692
692
  Requires-Dist: matplotlib==3.5.0
693
693
  Requires-Dist: watchdog==4.0.0
694
+ Requires-Dist: mypy==1.14.1
694
695
 
695
696
  # spectre-core
696
697
 
@@ -698,18 +699,24 @@ Requires-Dist: watchdog==4.0.0
698
699
 
699
700
  :loudspeaker: **This project is under active development. Contributors welcome.** :loudspeaker:
700
701
 
701
- ```spectre-core``` provides a SDR receiver-agnostic digital signal processing framework. It is the core Python package used by the [`spectre`](https://github.com/jcfitzpatrick12/spectre.git) program.
702
+ ```spectre-core``` provides an extensible, receiver-agnostic toolkit for generating radio spectrograms in real-time. It is the core Python package used by the [`spectre`](https://github.com/jcfitzpatrick12/spectre.git) program.
702
703
 
703
704
 
704
705
  ## Installation
705
- Typically, installation of ```spectre-core``` is managed in the ```spectre``` back-end. In any case, if you would like, simply call:
706
- ```pip install spectre-core```.
706
+ Simply call:
707
+ ```bash
708
+ pip install spectre-core
709
+ ```
707
710
 
708
711
  Alternatively, you can clone the repository in your preferred directory:
709
- ```git clone https://github.com/jcfitzpatrick12/spectre-core.git && cd spectre-core```
712
+ ```bash
713
+ git clone https://github.com/jcfitzpatrick12/spectre-core.git && cd spectre-core
714
+ ```
710
715
 
711
716
  Then run:
712
- ```pip install -e .```
717
+ ```
718
+ pip install -e .
719
+ ```
713
720
 
714
721
 
715
722
  ## Contributing
@@ -0,0 +1,75 @@
1
+ spectre_core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ spectre_core/exceptions.py,sha256=ccr-n88W0c_DKcsKMAe09QHX1iG2LUEqOMYHcGB-_do,451
3
+ spectre_core/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ spectre_core/_file_io/__init__.py,sha256=RZAtX8pFtdtTlxoxxttxJf1Wcg8lDFXgKMe1rcgaFP8,351
5
+ spectre_core/_file_io/file_handlers.py,sha256=dJ3rMcTGbNnEXbYZgVoaos4p6qKGs-rWNeY8nmluQCQ,6402
6
+ spectre_core/batches/__init__.py,sha256=nEEGLB9TnCKrP1VHQxYlU6U5MBt_4CHBcrRDnB-9GIU,685
7
+ spectre_core/batches/_base.py,sha256=KI3f5ZDKC_HrLtMDqqXiVLOF5InAQnk5QkyUuCXyAGI,7237
8
+ spectre_core/batches/_batches.py,sha256=CrfCjEhBO16SVfKbAvpxRsl0cjBxkiVOCSXegCuG0JM,7877
9
+ spectre_core/batches/_factory.py,sha256=ApshWhbhZ-CSoQBrlcYaC5W5p_w_v4pxOdOdlrF7YIA,2277
10
+ spectre_core/batches/_register.py,sha256=dSQC8KXj_jG8EiPwmKPdV0HSSalIZLaWt-8E29sczJM,1085
11
+ spectre_core/batches/plugins/_batch_keys.py,sha256=8v0KE1n0NAQX0i9SwwB4Lgkct7Q_jna-H5S0Gs6p1qg,544
12
+ spectre_core/batches/plugins/_callisto.py,sha256=ijm-VzGGlLQJjB2eQWw-04R6belCJ_NzSL9Jr7VTu2Q,6259
13
+ spectre_core/batches/plugins/_iq_stream.py,sha256=DSto5ZzPk7A4VAe_HUAKNd2M9NuWqxcL--_Vneo08Bc,12583
14
+ spectre_core/capture_configs/__init__.py,sha256=sUgwilZvQHAexAw_wao49qoBnu0CEBHIicI1kNfvCHg,1645
15
+ spectre_core/capture_configs/_capture_config.py,sha256=ngbIzySgjsgBRJyrfgYZrJtr0wqcKDn8xBH0T1vi-yY,4546
16
+ spectre_core/capture_configs/_capture_modes.py,sha256=uFBMwHYJCDqqQfYJvAUKzKXTmSBANRZMLlRSKV8WRb8,898
17
+ spectre_core/capture_configs/_capture_templates.py,sha256=nSAxhOh1DeBzYY16evgOTkDuxRugGG5weJsICUouLPQ,10353
18
+ spectre_core/capture_configs/_parameters.py,sha256=9KoNuwzDKtnyeju53fkImi1SeUjDn89cNwDL8zxX-YU,5563
19
+ spectre_core/capture_configs/_pconstraints.py,sha256=bnl1m6M9iyo5KOsPKT_arwrrAZbxRKXVwTHQACzvs2g,5227
20
+ spectre_core/capture_configs/_pnames.py,sha256=05mrrGfYHudaD2dYyukijbW-YtUnifZRn05xcBGv-fI,1852
21
+ spectre_core/capture_configs/_ptemplates.py,sha256=p4lOi6W5B9gWv0d6ryNK9f_zxLHsj5PWW8Lmdco9ofg,24508
22
+ spectre_core/capture_configs/_pvalidators.py,sha256=0W-OMDY1lifRPonwgEAwoMYkA0PWbqlK5nE0zsYVcTw,9596
23
+ spectre_core/config/__init__.py,sha256=CVddibAIWU4cNerXCxfeUn_cvnWWDBm4pWeUifqM6Ko,502
24
+ spectre_core/config/_paths.py,sha256=Qn0KVe27P6Bo65MfHe4LpH_ryPvLgbTxKjc4MTw1BB8,4090
25
+ spectre_core/config/_time_formats.py,sha256=gS0j5zIvBhnV7KMYvTloloIbVwmCYn8MMKn3zNeQ4Xc,857
26
+ spectre_core/jobs/__init__.py,sha256=WKTvxvpciedm6tsKjU02iXJhIdNsMDt-BnMVwVme2Bo,412
27
+ spectre_core/jobs/_jobs.py,sha256=gGpxsLZZ7EdXBYGH-r_pKnRGWSapr78E5SK_VnulaGg,3844
28
+ spectre_core/jobs/_workers.py,sha256=9GPEJVqIFuOAXpY9gfJxX-0_UPJ6RBtUe5qC5JLiYNw,5023
29
+ spectre_core/logs/__init__.py,sha256=BHZTru9KyOUDPBnanM1EJK5E1BN6YAGrjhdKFZ1ysUM,484
30
+ spectre_core/logs/_configure.py,sha256=NlR3BEwhj5k0qlTooOLb6OFRbYcDT05eWN-9Sl9Hkbk,2208
31
+ spectre_core/logs/_decorators.py,sha256=u_Ixpr6aeKiSjM0mtqHuGXVGawNjgJPRvIpAj0zPSdQ,1169
32
+ spectre_core/logs/_logs.py,sha256=M6sIsb2xxos9Ytj509qqp2jXZtvFU5uon9jIwEHLEI8,6578
33
+ spectre_core/logs/_process_types.py,sha256=qnKfeXPk-6NOlNf4XtD8D3tYbA_ZVhHSZAKSd2MiVmY,488
34
+ spectre_core/plotting/__init__.py,sha256=9zhmCphR4DSHlWfJhHeWPbvIrh8Kycov5Ta6woSrUZg,517
35
+ spectre_core/plotting/_base.py,sha256=51125B7OwvVvDXU2utZ_z0xuUkaKMeJ55Jsp2I-SORg,8226
36
+ spectre_core/plotting/_format.py,sha256=gWnj12PfgODQRTCCEyH2_mY7GY0brFbmolBEJfDtO6c,1393
37
+ spectre_core/plotting/_panel_names.py,sha256=xeXUXAhzDoPYCgtjy_6zbwADHBtB0-jARnFOW-YTcAc,830
38
+ spectre_core/plotting/_panel_stack.py,sha256=ZlVhAzb5Go4PdjR3-TeeaRA8T2-spqQHvFHLJVx1Weg,8732
39
+ spectre_core/plotting/_panels.py,sha256=IaJ8EDLu5pvsN6kklNWc1ectCfgUsxwN0EKwT2wiFNo,16030
40
+ spectre_core/post_processing/__init__.py,sha256=PVr7AhKK5at0o3BzNlJeC_Z_J8ZNATjGVY7PYg7fSew,624
41
+ spectre_core/post_processing/_base.py,sha256=gtycVjtAStN5sW4KuzxVQngLzYCx3k-9B5IfmMZnu_g,5815
42
+ spectre_core/post_processing/_factory.py,sha256=fnabYFy7Qe3EkJcR7baj1VyPdikw-xTSuNC01w7VupU,2193
43
+ spectre_core/post_processing/_post_processor.py,sha256=0WLOwtx-FHK4t6dv-I6_1K9sRNn-625wPS11lqJ8Kho,1300
44
+ spectre_core/post_processing/_register.py,sha256=chK5bCQ-0bpMhplbKT3cdS5anLhIA5Tt_ONzThJHrw0,1249
45
+ spectre_core/post_processing/plugins/_event_handler_keys.py,sha256=LPA71kKsaLPyT2vpPJwm88-RWfX-AU0_T9H8-GdjINQ,614
46
+ spectre_core/post_processing/plugins/_fixed_center_frequency.py,sha256=24LB3iDMa2KvgM7jyRnEr7Y45VK46bUT7Nj8bXGiGwc,5231
47
+ spectre_core/post_processing/plugins/_swept_center_frequency.py,sha256=fzPAZ4zK1DRAHushUB-JS2IgKAuXyP4hdBLZJX6jBmo,20971
48
+ spectre_core/receivers/__init__.py,sha256=A-BuCrnIRdRZe6HGXlLzKHGm8Zjfb8I9dzslBTeUHn4,660
49
+ spectre_core/receivers/_base.py,sha256=E2aSYmveSMYxLrm5Uv235KlsehOyq82DvSolCIF6xug,10096
50
+ spectre_core/receivers/_factory.py,sha256=5NdwZzBmUEHZQHltggDmuEoi-DRS6fHPSBzxvmq50zs,1843
51
+ spectre_core/receivers/_register.py,sha256=jWS3Q_ZOZcqUFunxJwR5VRZN4_eS3LzcP-5edQdmj4c,1366
52
+ spectre_core/receivers/_spec_names.py,sha256=pLYM9rMoZkT3JmRvSNfWKFiIJmj07vrphDbw-fNhpO8,1611
53
+ spectre_core/receivers/plugins/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
54
+ spectre_core/receivers/plugins/_receiver_names.py,sha256=GZi4xznxscLBJXbfkZLtQ-m0U3GH362HiI5-y_FQO1k,426
55
+ spectre_core/receivers/plugins/_rsp1a.py,sha256=LAvjxcxIkZRPpc96wqkco7rQ-H3AvUowsp0WG8vgAkw,2438
56
+ spectre_core/receivers/plugins/_rspduo.py,sha256=ypr4xiEMOq4EJKFECz01PZjUJ2UcsWJVZRou8Ln5Ogw,3049
57
+ spectre_core/receivers/plugins/_sdrplay_receiver.py,sha256=QpQ2sRc9Tz2IZRL_LyBX3UPCQ270RQMHH2mP6Y_n1-o,6899
58
+ spectre_core/receivers/plugins/_test.py,sha256=t8oE4zQLYYWJV6SMIZAlNHs9mig263QJmP6XRLyF0RU,8277
59
+ spectre_core/receivers/plugins/gr/__init__.py,sha256=oFSWmGoXQLK5X5xHvWzTdNr9amuaiiGjZirXZVogACU,154
60
+ spectre_core/receivers/plugins/gr/_base.py,sha256=woFF6498aLIDf4EC7aD-TolY9LtZBqlLy-Vai_gfIvc,2571
61
+ spectre_core/receivers/plugins/gr/_rsp1a.py,sha256=Nq0VNWjzfTd4Mruz4FSk6bfso6zh1cMw-C-qn5LpPv8,6614
62
+ spectre_core/receivers/plugins/gr/_rspduo.py,sha256=s5g5nOQHiVHCESaHdj2VmgXl_LaiMaqXhTJfUbC7Iew,9811
63
+ spectre_core/receivers/plugins/gr/_test.py,sha256=YA3JKdJ_CT3J93pqHUjltKrQUoaDXzUloEJEXVHH718,5780
64
+ spectre_core/spectrograms/__init__.py,sha256=AsiOmn9XrAAHUvK-fdhRddAxX4M1Wd6TCtdmxGkl3FA,763
65
+ spectre_core/spectrograms/_analytical.py,sha256=Axnt9JOJnWXRRuVU5nHPz5QU09KoWqNZkR5NnTX6kMY,11356
66
+ spectre_core/spectrograms/_array_operations.py,sha256=rhiHjnqFGT1bffJygMbeYWb1H9VGBK6-uAgFh8I9owc,7547
67
+ spectre_core/spectrograms/_spectrogram.py,sha256=WhHEt_QpmzspDqYlzdZcJ8CAXxRfs8-JfP0T3NHpjLQ,28205
68
+ spectre_core/spectrograms/_transform.py,sha256=WZ5jAe3bOpNldxHDSHPf8Q_1ifBdWqXB_mlF6DL1VuE,11734
69
+ spectre_core/wgetting/__init__.py,sha256=UkS0Z0wuuqpoZ1EL35wJcDpjBiAaZgdZ7064yGESxNE,341
70
+ spectre_core/wgetting/_callisto.py,sha256=m9II6ayswrY4h_ST3TodioZ4C865lN_uOF-BozvjZAg,6952
71
+ spectre_core-0.0.13.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
72
+ spectre_core-0.0.13.dist-info/METADATA,sha256=1PBd2ql6_9g9BGrwb1bWhnY4MSqRV1hdkXne6uE184o,42100
73
+ spectre_core-0.0.13.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
74
+ spectre_core-0.0.13.dist-info/top_level.txt,sha256=-UsyjpFohXgZpgcZ9QbVeXhsIyF3Am8RxNFNDV_Ta2Y,13
75
+ spectre_core-0.0.13.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.6.0)
2
+ Generator: setuptools (75.8.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,96 +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 datetime import datetime, timedelta
6
- from typing import Tuple
7
-
8
- import numpy as np
9
- from astropy.io import fits
10
- from astropy.io.fits.hdu.image import PrimaryHDU
11
- from astropy.io.fits.hdu.table import BinTableHDU
12
- from astropy.io.fits.hdu.hdulist import HDUList
13
-
14
- from spectre_core.spectrograms import Spectrogram, SpectrumTypes
15
- from .._register import register_batch
16
- from .._base import BaseBatch, BatchFile
17
-
18
-
19
- @register_batch('callisto')
20
- class _Batch(BaseBatch):
21
- def __init__(self,
22
- start_time: str,
23
- tag: str):
24
- super().__init__(start_time, tag)
25
- self.add_file( FitsFile(self.parent_dir_path, self.name) )
26
-
27
-
28
- class FitsFile(BatchFile):
29
- def __init__(self,
30
- parent_dir_path: str,
31
- base_file_name: str):
32
- super().__init__(parent_dir_path, base_file_name, "fits")
33
-
34
-
35
- def read(self) -> Spectrogram:
36
- with fits.open(self.file_path, mode='readonly') as hdulist:
37
- primary_hdu = self._get_primary_hdu(hdulist)
38
- dynamic_spectra = self._get_dynamic_spectra(primary_hdu)
39
- spectrogram_start_datetime = self._get_spectrogram_start_datetime(primary_hdu)
40
- bintable_hdu = self._get_bintable_hdu(hdulist)
41
- times, frequencies = self._get_time_and_frequency(bintable_hdu)
42
- spectrum_type = self._get_spectrum_type(primary_hdu)
43
-
44
- if spectrum_type == SpectrumTypes.DIGITS:
45
- dynamic_spectra_linearised = self._convert_units_to_linearised(dynamic_spectra)
46
- return Spectrogram(dynamic_spectra_linearised[::-1, :], # reverse the spectra along the frequency axis
47
- times,
48
- frequencies[::-1], # sort the frequencies in ascending order
49
- self.tag,
50
- spectrogram_start_datetime,
51
- spectrum_type)
52
- else:
53
- raise NotImplementedError(f"SPECTRE does not currently support spectrum type with BUNITS '{spectrum_type}'")
54
-
55
-
56
- @property
57
- def datetimes(self) -> np.ndarray:
58
- with fits.open(self.file_path, mode='readonly') as hdulist:
59
- bintable_data = hdulist[1].data
60
- times = bintable_data['TIME'][0]
61
- return [self.start_datetime + timedelta(seconds=t) for t in times]
62
-
63
-
64
- def _get_primary_hdu(self, hdulist: HDUList) -> PrimaryHDU:
65
- return hdulist['PRIMARY']
66
-
67
-
68
- def _get_dynamic_spectra(self, primary_hdu: PrimaryHDU) -> np.ndarray:
69
- return primary_hdu.data
70
-
71
-
72
- def _get_spectrogram_start_datetime(self, primary_hdu: PrimaryHDU) -> datetime:
73
- date_obs = primary_hdu.header['DATE-OBS']
74
- time_obs = primary_hdu.header['TIME-OBS']
75
- return datetime.strptime(f"{date_obs}T{time_obs}", "%Y-%m-%dT%H:%M:%S.%f")
76
-
77
-
78
- def _get_bintable_hdu(self, hdulist: HDUList) -> BinTableHDU:
79
- return hdulist[1]
80
-
81
-
82
- def _get_time_and_frequency(self, bintable_hdu: BinTableHDU) -> Tuple[np.ndarray, np.ndarray]:
83
- data = bintable_hdu.data
84
- times = data['TIME'][0]
85
- frequencies_MHz = data['FREQUENCY'][0]
86
- frequencies = frequencies_MHz * 1e6 # convert to Hz
87
- return times, frequencies
88
-
89
-
90
- def _convert_units_to_linearised(self, dynamic_spectra: np.ndarray) -> np.ndarray:
91
- digits_floats = np.array(dynamic_spectra, dtype='float')
92
- # conversion as per ADC specs [see email from C. Monstein]
93
- dB = (digits_floats / 255) * (2500 / 25)
94
- return 10 ** (dB / 10)
95
-
96
-