spectre-core 0.0.19__py3-none-any.whl → 0.0.21__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.
@@ -10,12 +10,12 @@ 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 BaseBatch, BatchFile
13
+ from ._base import BaseBatch, BatchFile, parse_batch_base_file_name
14
14
  from ._batches import Batches
15
15
  from ._factory import get_batch_cls, get_batch_cls_from_tag
16
16
 
17
17
  __all__ = [
18
18
  "IQStreamBatch", "IQMetadata", "CallistoBatch", "BaseBatch", "BatchFile",
19
- "Batches", "get_batch_cls", "BatchKey", "get_batch_cls_from_tag"
19
+ "Batches", "get_batch_cls", "BatchKey", "get_batch_cls_from_tag", "parse_batch_base_file_name"
20
20
  ]
21
21
 
@@ -3,17 +3,33 @@
3
3
  # SPDX-License-Identifier: GPL-3.0-or-later
4
4
 
5
5
  from datetime import datetime
6
- from typing import TypeVar
6
+ from typing import TypeVar, Tuple
7
+ from base64 import b64encode
7
8
  from functools import cached_property
8
9
  from abc import ABC, abstractmethod
10
+ from dataclasses import dataclass
11
+ from os.path import splitext
9
12
 
10
13
  from spectre_core._file_io import BaseFileHandler
11
14
  from spectre_core.config import get_batches_dir_path, TimeFormat
12
15
  from spectre_core.spectrograms import Spectrogram
13
16
 
14
17
 
18
+ def parse_batch_base_file_name(
19
+ base_file_name: str
20
+ ) -> Tuple[str, str, str]:
21
+ """Parse the base file name of a batch file into a start time, tag and extension.
22
+ """
23
+ batch_name, extension = splitext(base_file_name)
24
+ # strip the dot from the extension
25
+ extension = extension.lstrip('.')
26
+ start_time, tag = batch_name.split("_", 1)
27
+ return start_time, tag, extension
28
+
29
+
15
30
  T = TypeVar('T')
16
31
 
32
+
17
33
  class BatchFile(BaseFileHandler[T]):
18
34
  """Abstract base class for files belonging to a batch, identified by their file extension.
19
35
 
@@ -64,6 +80,40 @@ class BatchFile(BaseFileHandler[T]):
64
80
  ) -> str:
65
81
  """The batch name tag."""
66
82
  return self._tag
83
+
84
+
85
+ @dataclass(frozen=True)
86
+ class _BatchExtension:
87
+ """Supported extensions for a `BaseBatch`, inherited by all derived classes.
88
+
89
+ :ivar PNG: Corresponds to the `.png` file extension.
90
+ """
91
+ PNG: str = "png"
92
+
93
+
94
+ class _PngFile(BatchFile[str]):
95
+ """Stores an image visualising the data for the batch."""
96
+ def __init__(
97
+ self,
98
+ batch_parent_dir_path: str,
99
+ batch_name: str
100
+ ) -> None:
101
+ """Initialise a `_PngFile` instance.
102
+
103
+ :param batch_parent_dir_path: The parent directory for the batch.
104
+ :param batch_name: The batch name.
105
+ """
106
+ super().__init__(batch_parent_dir_path, batch_name, _BatchExtension.PNG)
107
+
108
+
109
+ def _read(self) -> str:
110
+ """Reads the PNG file and returns it base64-encoded.
111
+
112
+ :return: Base64-encoded string representation of the image.
113
+ """
114
+ with open(self.file_path, "rb") as f:
115
+ encoded = b64encode(f.read())
116
+ return encoded.decode("ascii")
67
117
 
68
118
 
69
119
  class BaseBatch(ABC):
@@ -98,6 +148,10 @@ class BaseBatch(ABC):
98
148
  # internal register of batch files
99
149
  self._batch_files: dict[str, BatchFile] = {}
100
150
 
151
+ # Add the files shared by all derived classes
152
+ self._png_file = _PngFile(self.parent_dir_path, self.name)
153
+ self.add_file( self._png_file )
154
+
101
155
 
102
156
  @property
103
157
  @abstractmethod
@@ -166,6 +220,14 @@ class BaseBatch(ABC):
166
220
  """
167
221
  return self._batch_files
168
222
 
223
+
224
+ @property
225
+ def png_file(
226
+ self
227
+ ) -> _PngFile:
228
+ """The batch file corresponding to the `.png` extension."""
229
+ return self._png_file
230
+
169
231
 
170
232
  def add_file(
171
233
  self,
@@ -235,4 +297,12 @@ class BaseBatch(ABC):
235
297
  :return: The spectrogram stored by the batch `spectrogram_file`.
236
298
  """
237
299
  return self.spectrogram_file.read()
238
-
300
+
301
+
302
+
303
+
304
+
305
+
306
+
307
+
308
+
@@ -13,7 +13,7 @@ from spectre_core.config import get_batches_dir_path
13
13
  from spectre_core.exceptions import (
14
14
  BatchNotFoundError
15
15
  )
16
- from ._base import BaseBatch
16
+ from ._base import BaseBatch, parse_batch_base_file_name
17
17
 
18
18
  T = TypeVar('T', bound=BaseBatch)
19
19
  class Batches(Generic[T]):
@@ -144,9 +144,7 @@ class Batches(Generic[T]):
144
144
  # get a list of all batch file names in the batches directory path
145
145
  batch_file_names = [f for (_, _, files) in os.walk(self.batches_dir_path) for f in files]
146
146
  for batch_file_name in batch_file_names:
147
- # strip the extension
148
- batch_name, _ = os.path.splitext(batch_file_name)
149
- start_time, tag = batch_name.split("_", 1)
147
+ start_time, tag, _ = parse_batch_base_file_name(batch_file_name)
150
148
  if tag == self._tag:
151
149
  self._batch_map[start_time] = self.batch_cls(start_time, tag)
152
150
 
@@ -207,25 +205,22 @@ class Batches(Generic[T]):
207
205
  return self._get_from_start_time(subscript)
208
206
  elif isinstance(subscript, int):
209
207
  return self._get_from_index(subscript)
208
+
210
209
 
211
-
212
- def get_spectrogram_from_range(
210
+ def get_spectrogram(
213
211
  self,
214
- start_time: str,
215
- end_time: str
212
+ start_datetime: datetime,
213
+ end_datetime: datetime
216
214
  ) -> Spectrogram:
217
215
  """
218
216
  Retrieve a spectrogram spanning the specified time range.
219
217
 
220
- :param start_time: The start time of the range (inclusive).
221
- :param end_time: The end time of the range (inclusive).
218
+ :param start_datetime: The start time of the range (inclusive).
219
+ :param end_datetime: The end time of the range (inclusive).
222
220
  :raises FileNotFoundError: If no spectrogram data is available within the specified time range.
223
221
  :return: A spectrogram created by stitching together data from all matching batches.
224
222
  """
225
- # Convert input strings to datetime objects
226
- start_datetime = datetime.strptime(start_time, TimeFormat.DATETIME)
227
- end_datetime = datetime.strptime(end_time, TimeFormat.DATETIME)
228
-
223
+
229
224
  spectrograms = []
230
225
  for batch in self:
231
226
  # skip batches without spectrogram data
@@ -238,10 +233,10 @@ class Batches(Generic[T]):
238
233
 
239
234
  # Check if the batch overlaps with the input time range
240
235
  if start_datetime <= upper_bound and lower_bound <= end_datetime:
241
- spectrograms.append( time_chop(spectrogram, start_time, end_time) )
236
+ spectrograms.append( time_chop(spectrogram, start_datetime, end_datetime) )
242
237
 
243
238
  if spectrograms:
244
239
  return join_spectrograms(spectrograms)
245
240
  else:
246
241
  raise FileNotFoundError(f"No spectrogram data found for the time range "
247
- f"{start_time} to {end_time}.")
242
+ f"{start_datetime} to {end_datetime}.")
@@ -317,7 +317,6 @@ class IQStreamBatch(BaseBatch):
317
317
  :param tag: The batch name tag.
318
318
  """
319
319
  super().__init__(start_time, tag)
320
- self._batch_files = {}
321
320
  self._fits_file = _FitsFile(self.parent_dir_path, self.name)
322
321
  self._bin_file = _BinFile (self.parent_dir_path, self.name)
323
322
  self._hdr_file = _HdrFile (self.parent_dir_path, self.name)
@@ -42,7 +42,7 @@ class CaptureConfig(JsonHandler):
42
42
  self._validate_tag(tag)
43
43
  self._tag = tag
44
44
  super().__init__(get_configs_dir_path(),
45
- f"capture_{tag}")
45
+ tag)
46
46
 
47
47
  @property
48
48
  def tag(
@@ -60,11 +60,8 @@ class CaptureConfig(JsonHandler):
60
60
 
61
61
  Some substrings are reserved for third-party spectrogram data.
62
62
  """
63
- if "_" in tag:
64
- raise InvalidTagError(f"Tags cannot contain an underscore. Received {tag}")
65
-
66
63
  if "callisto" in tag:
67
- raise ValueError(f"The substring `callisto` is not allowed in a capture config tag.")
64
+ raise ValueError(f"The substring `callisto` is reserved, and is not allowed in a capture config tag.")
68
65
 
69
66
 
70
67
  @property
@@ -8,10 +8,10 @@
8
8
  from ._process_types import ProcessType
9
9
  from ._decorators import log_call
10
10
  from ._configure import configure_root_logger, get_root_logger_state
11
- from ._logs import Log, Logs
11
+ from ._logs import Log, Logs, parse_log_base_file_name
12
12
 
13
13
 
14
14
  __all__ = [
15
15
  "log_call", "configure_root_logger", "Log", "Logs", "ProcessType",
16
- "get_root_logger_state"
17
- ]
16
+ "get_root_logger_state", "parse_log_base_file_name"
17
+ ]
@@ -6,7 +6,7 @@ from logging import getLogger
6
6
  _LOGGER = getLogger(__name__)
7
7
 
8
8
  import os
9
- from typing import Optional, Iterator
9
+ from typing import Optional, Iterator, Tuple
10
10
  from collections import OrderedDict
11
11
  from datetime import datetime
12
12
 
@@ -14,6 +14,17 @@ from spectre_core._file_io import TextHandler
14
14
  from spectre_core.config import get_logs_dir_path, TimeFormat
15
15
  from ._process_types import ProcessType
16
16
 
17
+
18
+ def parse_log_base_file_name(
19
+ base_file_name: str
20
+ ) -> Tuple[str, str, str]:
21
+ """Parse the base file name of a log into a start time, process ID and process type.
22
+ """
23
+ file_name, _ = os.path.splitext(base_file_name)
24
+ log_start_time, pid, process_type = file_name.split("_")
25
+ return log_start_time, pid, process_type
26
+
27
+
17
28
  class Log(TextHandler):
18
29
  """Interface to read log files generated by `spectre`."""
19
30
  def __init__(
@@ -177,13 +188,13 @@ class Logs:
177
188
  log_files = [f for (_, _, files) in os.walk(self.logs_dir_path) for f in files]
178
189
 
179
190
  for log_file in log_files:
180
- file_name, _ = os.path.splitext(log_file)
181
- log_start_time, pid, process_type = file_name.split("_")
191
+
192
+ log_start_time, pid, process_type = parse_log_base_file_name(log_file)
182
193
 
183
194
  if self.process_type and process_type != self.process_type:
184
195
  continue
185
196
 
186
- self._log_map[file_name] = Log(log_start_time, pid, ProcessType(process_type))
197
+ self._log_map[log_file] = Log(log_start_time, pid, ProcessType(process_type))
187
198
 
188
199
  self._log_map = OrderedDict(sorted(self._log_map.items()))
189
200
 
@@ -225,4 +236,4 @@ class Logs:
225
236
  for log in self.log_list:
226
237
  if log.pid == pid:
227
238
  return log
228
- raise FileNotFoundError(f"Log handler for PID '{pid}' not found in log map")
239
+ raise FileNotFoundError(f"Log handler for PID '{pid}' could not be identified")
@@ -5,6 +5,7 @@
5
5
  from abc import ABC, abstractmethod
6
6
  from typing import Optional, Literal
7
7
  from enum import Enum
8
+ from datetime import datetime
8
9
 
9
10
  import numpy.typing as npt
10
11
  import numpy as np
@@ -13,6 +14,7 @@ from matplotlib.axes import Axes
13
14
  from matplotlib.figure import Figure
14
15
 
15
16
  from spectre_core.spectrograms import Spectrogram, TimeType
17
+ from spectre_core.config import TimeFormat
16
18
  from ._format import PanelFormat
17
19
  from ._panel_names import PanelName
18
20
 
@@ -284,8 +286,11 @@ class BaseTimeSeriesPanel(BasePanel):
284
286
  if self.time_type == TimeType.RELATIVE:
285
287
  self.ax.set_xlabel('Time [s]')
286
288
  else:
287
- self.ax.set_xlabel('Time [UTC]')
288
- self.ax.xaxis.set_major_formatter(mdates.DateFormatter('%H:%M:%S'))
289
+ #TODO: Adapt for time ranges greater than one day
290
+ start_date = datetime.strftime(self.spectrogram.start_datetime.astype(datetime),
291
+ TimeFormat.DATE)
292
+ self.ax.set_xlabel(f'Time [UTC] (Start Date: {start_date})')
293
+ self.ax.xaxis.set_major_formatter(mdates.DateFormatter(TimeFormat.TIME))
289
294
 
290
295
 
291
296
 
@@ -2,18 +2,22 @@
2
2
  # This file is part of SPECTRE
3
3
  # SPDX-License-Identifier: GPL-3.0-or-later
4
4
 
5
+ import os
5
6
  import numpy as np
6
- import numpy.typing as npt
7
7
  from typing import Optional, Tuple, cast
8
8
  import matplotlib.pyplot as plt
9
9
  from matplotlib.figure import Figure
10
10
  from matplotlib.axes import Axes
11
+ from matplotlib import use
12
+ from datetime import datetime
11
13
 
12
14
  from spectre_core.spectrograms import TimeType
15
+ from spectre_core.config import TimeFormat, get_batches_dir_path
13
16
  from ._base import BasePanel, XAxisType
14
17
  from ._format import PanelFormat
15
- from ._panels import PanelName, SpectrogramPanel, TimeCutsPanel, FrequencyCutsPanel
16
-
18
+ from ._panels import (
19
+ PanelName, SpectrogramPanel, TimeCutsPanel, FrequencyCutsPanel
20
+ )
17
21
 
18
22
  def _is_cuts_panel(
19
23
  panel: BasePanel
@@ -43,17 +47,22 @@ class PanelStack:
43
47
  self,
44
48
  panel_format: PanelFormat = PanelFormat(),
45
49
  time_type: TimeType = TimeType.RELATIVE,
46
- figsize: Tuple[int, int] = (10, 10)
50
+ figsize: Tuple[int, int] = (15, 8),
51
+ non_interactive: bool = False
47
52
  ) -> None:
48
53
  """Initialize an instance of `PanelStack`.
49
54
 
50
55
  :param panel_format: Formatting applied across all panels in the stack. Defaults to `PanelFormat()`.
51
56
  :param time_type: The type of time assigned to spectrograms, defaults to `TimeType.RELATIVE`.
52
- :param figsize: The size of the `matplotlib` figure as (width, height). Defaults to (10, 10).
57
+ :param figsize: The size of the `matplotlib` figure as (width, height). Defaults to (15, 8).
53
58
  """
54
59
  self._panel_format = panel_format
55
60
  self._time_type = time_type
56
61
  self._figsize = figsize
62
+
63
+ if non_interactive:
64
+ # Use a non-interactive matplotlib backend, which can only write files.
65
+ use('agg')
57
66
 
58
67
  self._panels : list[BasePanel] = []
59
68
  self._superimposed_panels: list[BasePanel] = []
@@ -116,14 +125,15 @@ class PanelStack:
116
125
  def add_panel(
117
126
  self,
118
127
  panel: BasePanel,
119
- identifier: Optional[str] = None
128
+ identifier: Optional[str] = None,
129
+ panel_format: Optional[PanelFormat] = None
120
130
  ) -> None:
121
131
  """Add a panel to the stack.
122
132
 
123
133
  :param panel: An instance of a `BasePanel` subclass to be added to the stack.
124
134
  :param identifier: An optional string to link the panel with others for superimposing.
125
135
  """
126
- panel.panel_format = self._panel_format
136
+ panel.panel_format = panel_format or self._panel_format
127
137
  panel.time_type = self._time_type
128
138
  if identifier:
129
139
  panel.identifier = identifier
@@ -133,7 +143,8 @@ class PanelStack:
133
143
  def superimpose_panel(
134
144
  self,
135
145
  panel: BasePanel,
136
- identifier: Optional[str] = None
146
+ identifier: Optional[str] = None,
147
+ panel_format: Optional[PanelFormat] = None
137
148
  ) -> None:
138
149
  """Superimpose a panel onto an existing panel in the stack.
139
150
 
@@ -142,7 +153,8 @@ class PanelStack:
142
153
  """
143
154
  if identifier:
144
155
  panel.identifier = identifier
145
- panel.panel_format = self._panel_format
156
+ panel.panel_format = panel_format or self._panel_format
157
+ panel.time_type = self._time_type
146
158
  self._superimposed_panels.append(panel)
147
159
 
148
160
 
@@ -234,11 +246,13 @@ class PanelStack:
234
246
  if _is_cuts_panel(super_panel):
235
247
  self._overlay_cuts(super_panel)
236
248
 
237
-
238
- def show(
249
+ def _make_figure(
239
250
  self
240
251
  ) -> None:
241
- """Display the panel stack figure."""
252
+ """Make the panel stack figure."""
253
+ if self.num_panels < 1:
254
+ raise ValueError(f"There must be at least one panel in the stack.")
255
+
242
256
  self._init_plot_style()
243
257
  self._create_figure_and_axes()
244
258
  self._assign_axes()
@@ -258,4 +272,34 @@ class PanelStack:
258
272
  self._overlay_cuts(panel)
259
273
 
260
274
  self._overlay_superimposed_panels()
275
+
276
+ def show(
277
+ self
278
+ ) -> None:
279
+ """Display the panel stack figure."""
280
+ self._make_figure()
261
281
  plt.show()
282
+
283
+
284
+ def save(
285
+ self,
286
+ ) -> str:
287
+ """Save the panel stack figure as a batch file under the tag of the first
288
+ panel in the stack. The file format is `png`.
289
+
290
+ :return: The file path of the newly created batch file containing the figure.
291
+ """
292
+ self._make_figure()
293
+ first_panel = self._panels[0]
294
+
295
+ start_dt = cast(datetime, first_panel.spectrogram.start_datetime.astype(datetime))
296
+ batch_name = f"{start_dt.strftime(TimeFormat.DATETIME)}_{first_panel.spectrogram.tag}"
297
+ batch_file_path = os.path.join(
298
+ get_batches_dir_path(start_dt.year, start_dt.month, start_dt.day),
299
+ f"{batch_name}.png"
300
+ )
301
+ plt.savefig(batch_file_path)
302
+ return batch_file_path
303
+
304
+
305
+
@@ -58,30 +58,30 @@ def frequency_chop(
58
58
 
59
59
  def time_chop(
60
60
  spectrogram: Spectrogram,
61
- start_time: str,
62
- end_time: str
61
+ start_datetime: datetime,
62
+ end_datetime: datetime
63
63
  ) -> Spectrogram:
64
64
  """
65
65
  Extracts a portion of the spectrogram within the specified time range.
66
66
 
67
67
  :param spectrogram: The input spectrogram to process.
68
- :param start_time: The starting time of the desired range.
69
- :param end_time: The ending time of the desired range.
68
+ :param start_datetime: The starting time of the desired range.
69
+ :param end_datetime: The ending time of the desired range.
70
70
  :raises ValueError: If the specified time range is entirely outside the spectrogram's time range.
71
71
  :raises ValueError: If the start and end indices for the time range are identical.
72
72
  :return: A new spectrogram containing only the specified time range.
73
73
  """
74
- start_datetime = np.datetime64( datetime.strptime(start_time, TimeFormat.DATETIME) )
75
- end_datetime = np.datetime64( datetime.strptime(end_time , TimeFormat.DATETIME) )
74
+ start_datetime64 = np.datetime64(start_datetime)
75
+ end_datetime64 = np.datetime64(end_datetime)
76
76
 
77
- is_entirely_below_time_range = (start_datetime < spectrogram.datetimes[0] and end_datetime < spectrogram.datetimes[0])
78
- is_entirely_above_time_range = (start_datetime > spectrogram.datetimes[-1] and end_datetime > spectrogram.datetimes[-1])
77
+ is_entirely_below_time_range = (start_datetime64 < spectrogram.datetimes[0] and end_datetime64 < spectrogram.datetimes[0])
78
+ is_entirely_above_time_range = (start_datetime64 > spectrogram.datetimes[-1] and end_datetime64 > spectrogram.datetimes[-1])
79
79
  if is_entirely_below_time_range or is_entirely_above_time_range:
80
80
  raise ValueError(f"Requested time interval is entirely out of range of the input spectrogram.")
81
81
 
82
82
  # find the index of the nearest matching spectrums in the spectrogram.
83
- start_index = find_closest_index(start_datetime, spectrogram.datetimes)
84
- end_index = find_closest_index(end_datetime, spectrogram.datetimes)
83
+ start_index = find_closest_index(start_datetime64, spectrogram.datetimes)
84
+ end_index = find_closest_index(end_datetime64, spectrogram.datetimes)
85
85
 
86
86
  # enforce distinct start and end indices
87
87
  if start_index == end_index:
@@ -6,10 +6,11 @@ import os
6
6
  import subprocess
7
7
  import shutil
8
8
  import gzip
9
- from datetime import datetime
9
+ from datetime import datetime, date
10
+ from typing import Tuple
10
11
 
11
12
  from spectre_core.config import (
12
- get_spectre_data_dir_path, get_batches_dir_path, TimeFormat, trim_spectre_data_dir_path
13
+ get_spectre_data_dir_path, get_batches_dir_path, TimeFormat
13
14
  )
14
15
 
15
16
  from enum import Enum
@@ -136,12 +137,12 @@ def _unzip_file_to_batches(
136
137
  Decompress a `.fit.gz` file and save it as a `.fits` batch file.
137
138
 
138
139
  :param gz_path: Path to the `.fit.gz` file.
139
- :return: The file path of the newly created batch file, relative to the mounted volume.
140
+ :return: The file path of the newly created batch file, as absolute paths within the container's file system.
140
141
  """
141
142
  fits_path = _get_batch_path(gz_path)
142
143
  with gzip.open(gz_path, "rb") as f_in, open(fits_path, "wb") as f_out:
143
144
  shutil.copyfileobj(f_in, f_out)
144
- return trim_spectre_data_dir_path(f_out.name)
145
+ return f_out.name
145
146
 
146
147
 
147
148
  def _unzip_to_batches(
@@ -152,7 +153,7 @@ def _unzip_to_batches(
152
153
  batch files.
153
154
 
154
155
  :param tmp_dir: Path to the temporary directory containing `.gz` files.
155
- :return: A list of file names of all newly created batch files, relative to the mounted volume.
156
+ :return: A list of file names of all newly created batch files, as absolute paths within the container's file system.
156
157
  """
157
158
  batch_file_names = []
158
159
  for entry in os.scandir(tmp_dir):
@@ -195,7 +196,7 @@ def download_callisto_data(
195
196
  year: int,
196
197
  month: int,
197
198
  day: int
198
- ) -> list[str]:
199
+ ) -> Tuple[list[str], date]:
199
200
  """
200
201
  Download and decompress e-Callisto FITS files, saving them as `spectre` batch files.
201
202
 
@@ -203,7 +204,7 @@ def download_callisto_data(
203
204
  :param year: Year of the observation.
204
205
  :param month: Month of the observation.
205
206
  :param day: Day of the observation.
206
- :return: A list of file names of all newly created batch files, relative to the mounted volume.
207
+ :return: A list of file names of all newly created batch files, as absolute paths within the container's file system. Additionally, return the start date shared by all batch files.
207
208
  """
208
209
  tmp_dir = os.path.join(get_spectre_data_dir_path(), "tmp")
209
210
  # if there are any residual files in the temporary directory, remove them.
@@ -212,4 +213,4 @@ def download_callisto_data(
212
213
  os.makedirs(tmp_dir, exist_ok=True)
213
214
 
214
215
  _wget_callisto_data(instrument_code.value, year, month, day, tmp_dir)
215
- return sorted( _unzip_to_batches(tmp_dir) )
216
+ return sorted( _unzip_to_batches(tmp_dir) ), date(year, month, day)
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: spectre-core
3
- Version: 0.0.19
3
+ Version: 0.0.21
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,7 +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
+ Dynamic: license-file
695
695
 
696
696
  # spectre-core
697
697
 
@@ -3,16 +3,16 @@ spectre_core/exceptions.py,sha256=ccr-n88W0c_DKcsKMAe09QHX1iG2LUEqOMYHcGB-_do,45
3
3
  spectre_core/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  spectre_core/_file_io/__init__.py,sha256=RZAtX8pFtdtTlxoxxttxJf1Wcg8lDFXgKMe1rcgaFP8,351
5
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
6
+ spectre_core/batches/__init__.py,sha256=AIE3S3D3z__Ox557W95EILiv-BYoxjyRODMo2vu7My0,743
7
+ spectre_core/batches/_base.py,sha256=0-eYk7AINGMMUyecAqBEQ97tWi765MUHysGi2gvdVTI,9079
8
+ spectre_core/batches/_batches.py,sha256=2tgP2Mfwlay2bkblruS2mAfgfmdP3Doq841tKb8rq1U,7670
9
9
  spectre_core/batches/_factory.py,sha256=ApshWhbhZ-CSoQBrlcYaC5W5p_w_v4pxOdOdlrF7YIA,2277
10
10
  spectre_core/batches/_register.py,sha256=dSQC8KXj_jG8EiPwmKPdV0HSSalIZLaWt-8E29sczJM,1085
11
11
  spectre_core/batches/plugins/_batch_keys.py,sha256=8v0KE1n0NAQX0i9SwwB4Lgkct7Q_jna-H5S0Gs6p1qg,544
12
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
13
+ spectre_core/batches/plugins/_iq_stream.py,sha256=YnNMrsD-K_otgN_4cR1pPJaddXpEaP4KkVVv0zIDs8w,12552
14
14
  spectre_core/capture_configs/__init__.py,sha256=bhwp1Kf2llzd8HpkMPxeM_ZJoIoCFLQoMZJ44AAH6s0,1738
15
- spectre_core/capture_configs/_capture_config.py,sha256=ngbIzySgjsgBRJyrfgYZrJtr0wqcKDn8xBH0T1vi-yY,4546
15
+ spectre_core/capture_configs/_capture_config.py,sha256=VdiHvv5vdFKaB15EwNYyizFmtkoJHrzTiumDvHLI9HM,4430
16
16
  spectre_core/capture_configs/_capture_modes.py,sha256=uFBMwHYJCDqqQfYJvAUKzKXTmSBANRZMLlRSKV8WRb8,898
17
17
  spectre_core/capture_configs/_capture_templates.py,sha256=nSAxhOh1DeBzYY16evgOTkDuxRugGG5weJsICUouLPQ,10353
18
18
  spectre_core/capture_configs/_parameters.py,sha256=9KoNuwzDKtnyeju53fkImi1SeUjDn89cNwDL8zxX-YU,5563
@@ -26,16 +26,16 @@ spectre_core/config/_time_formats.py,sha256=gS0j5zIvBhnV7KMYvTloloIbVwmCYn8MMKn3
26
26
  spectre_core/jobs/__init__.py,sha256=WKTvxvpciedm6tsKjU02iXJhIdNsMDt-BnMVwVme2Bo,412
27
27
  spectre_core/jobs/_jobs.py,sha256=gGpxsLZZ7EdXBYGH-r_pKnRGWSapr78E5SK_VnulaGg,3844
28
28
  spectre_core/jobs/_workers.py,sha256=9GPEJVqIFuOAXpY9gfJxX-0_UPJ6RBtUe5qC5JLiYNw,5023
29
- spectre_core/logs/__init__.py,sha256=BHZTru9KyOUDPBnanM1EJK5E1BN6YAGrjhdKFZ1ysUM,484
29
+ spectre_core/logs/__init__.py,sha256=cUIjKXzxT9pzITVOsv5zkX97WnMZNHEUt9_orKuaHMw,539
30
30
  spectre_core/logs/_configure.py,sha256=NlR3BEwhj5k0qlTooOLb6OFRbYcDT05eWN-9Sl9Hkbk,2208
31
31
  spectre_core/logs/_decorators.py,sha256=u_Ixpr6aeKiSjM0mtqHuGXVGawNjgJPRvIpAj0zPSdQ,1169
32
- spectre_core/logs/_logs.py,sha256=M6sIsb2xxos9Ytj509qqp2jXZtvFU5uon9jIwEHLEI8,6578
32
+ spectre_core/logs/_logs.py,sha256=ZNYtJN_A_StRfJJFkv5rTmQ2z2427YIxXGkd_6NQY1Y,6900
33
33
  spectre_core/logs/_process_types.py,sha256=qnKfeXPk-6NOlNf4XtD8D3tYbA_ZVhHSZAKSd2MiVmY,488
34
34
  spectre_core/plotting/__init__.py,sha256=9zhmCphR4DSHlWfJhHeWPbvIrh8Kycov5Ta6woSrUZg,517
35
- spectre_core/plotting/_base.py,sha256=51125B7OwvVvDXU2utZ_z0xuUkaKMeJ55Jsp2I-SORg,8226
35
+ spectre_core/plotting/_base.py,sha256=yRZ6pf_d1mm35yn4AU8Hu2X50rCeB0KX1yEygDbpYo4,8547
36
36
  spectre_core/plotting/_format.py,sha256=gWnj12PfgODQRTCCEyH2_mY7GY0brFbmolBEJfDtO6c,1393
37
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
38
+ spectre_core/plotting/_panel_stack.py,sha256=M2gKJf9Uxr6nf2KldGfVa5TDa1n-wEk-ZS5svE3D7Qo,10263
39
39
  spectre_core/plotting/_panels.py,sha256=IaJ8EDLu5pvsN6kklNWc1ectCfgUsxwN0EKwT2wiFNo,16030
40
40
  spectre_core/post_processing/__init__.py,sha256=PVr7AhKK5at0o3BzNlJeC_Z_J8ZNATjGVY7PYg7fSew,624
41
41
  spectre_core/post_processing/_base.py,sha256=gtycVjtAStN5sW4KuzxVQngLzYCx3k-9B5IfmMZnu_g,5815
@@ -68,11 +68,11 @@ spectre_core/spectrograms/__init__.py,sha256=AsiOmn9XrAAHUvK-fdhRddAxX4M1Wd6TCtd
68
68
  spectre_core/spectrograms/_analytical.py,sha256=Axnt9JOJnWXRRuVU5nHPz5QU09KoWqNZkR5NnTX6kMY,11356
69
69
  spectre_core/spectrograms/_array_operations.py,sha256=79vddwWqR5i6OkeD5L_84t8svslpmzW4b8uxbiCQl0I,7553
70
70
  spectre_core/spectrograms/_spectrogram.py,sha256=WhHEt_QpmzspDqYlzdZcJ8CAXxRfs8-JfP0T3NHpjLQ,28205
71
- spectre_core/spectrograms/_transform.py,sha256=WZ5jAe3bOpNldxHDSHPf8Q_1ifBdWqXB_mlF6DL1VuE,11734
71
+ spectre_core/spectrograms/_transform.py,sha256=_Kw9XfGNuhBqHfwPxNL4d-KIZJgzEX449ew1e17_k00,11698
72
72
  spectre_core/wgetting/__init__.py,sha256=UkS0Z0wuuqpoZ1EL35wJcDpjBiAaZgdZ7064yGESxNE,341
73
- spectre_core/wgetting/_callisto.py,sha256=WetoQByBOzimDYX9bs3Wjiy1U44X7dkal1bPq_m1XKg,7454
74
- spectre_core-0.0.19.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
75
- spectre_core-0.0.19.dist-info/METADATA,sha256=vgFQ1cpODqJc0SY-GnpIRh-hzA2gt6xUY14vMq9czZw,42100
76
- spectre_core-0.0.19.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
77
- spectre_core-0.0.19.dist-info/top_level.txt,sha256=-UsyjpFohXgZpgcZ9QbVeXhsIyF3Am8RxNFNDV_Ta2Y,13
78
- spectre_core-0.0.19.dist-info/RECORD,,
73
+ spectre_core/wgetting/_callisto.py,sha256=jMvv75d6152KmasZlydc4nXxuX0nAl4snSXzXOVwVGU,7597
74
+ spectre_core-0.0.21.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
75
+ spectre_core-0.0.21.dist-info/METADATA,sha256=HcteVzzTLeZCUSUnCfqHNud70AutsvI6tgztzBPokzE,42094
76
+ spectre_core-0.0.21.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
77
+ spectre_core-0.0.21.dist-info/top_level.txt,sha256=-UsyjpFohXgZpgcZ9QbVeXhsIyF3Am8RxNFNDV_Ta2Y,13
78
+ spectre_core-0.0.21.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (76.0.0)
2
+ Generator: setuptools (78.1.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5