ecallistolib 0.2.2__py3-none-any.whl → 0.2.3.1__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.
- ecallistolib/__init__.py +6 -1
- ecallistolib/combine.py +3 -3
- ecallistolib/crop.py +1 -1
- ecallistolib/download.py +1 -1
- ecallistolib/exceptions.py +6 -1
- ecallistolib/io.py +1 -1
- ecallistolib/models.py +1 -1
- ecallistolib/plotting.py +304 -92
- ecallistolib/processing.py +3 -3
- {ecallistolib-0.2.2.dist-info → ecallistolib-0.2.3.1.dist-info}/METADATA +138 -37
- ecallistolib-0.2.3.1.dist-info/RECORD +14 -0
- {ecallistolib-0.2.2.dist-info → ecallistolib-0.2.3.1.dist-info}/WHEEL +1 -1
- ecallistolib-0.2.2.dist-info/RECORD +0 -14
- {ecallistolib-0.2.2.dist-info → ecallistolib-0.2.3.1.dist-info}/licenses/LICENSE +0 -0
- {ecallistolib-0.2.2.dist-info → ecallistolib-0.2.3.1.dist-info}/top_level.txt +0 -0
ecallistolib/__init__.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
"""
|
|
3
3
|
e-callistolib: Tools for e-CALLISTO FITS dynamic spectra.
|
|
4
|
-
Version 0.2.
|
|
4
|
+
Version 0.2.3
|
|
5
5
|
Sahan S Liyanage (sahanslst@gmail.com)
|
|
6
6
|
Astronomical and Space Science Unit, University of Colombo, Sri Lanka.
|
|
7
7
|
"""
|
|
@@ -14,6 +14,7 @@ from .exceptions import (
|
|
|
14
14
|
CropError,
|
|
15
15
|
DownloadError,
|
|
16
16
|
ECallistoError,
|
|
17
|
+
FrequencyOutOfRangeError,
|
|
17
18
|
InvalidFilenameError,
|
|
18
19
|
InvalidFITSError,
|
|
19
20
|
)
|
|
@@ -50,6 +51,7 @@ __all__ = [
|
|
|
50
51
|
"DownloadError",
|
|
51
52
|
"CombineError",
|
|
52
53
|
"CropError",
|
|
54
|
+
"FrequencyOutOfRangeError",
|
|
53
55
|
]
|
|
54
56
|
|
|
55
57
|
|
|
@@ -86,12 +88,14 @@ def __getattr__(name: str):
|
|
|
86
88
|
"plot_dynamic_spectrum",
|
|
87
89
|
"plot_raw_spectrum",
|
|
88
90
|
"plot_background_subtracted",
|
|
91
|
+
"plot_light_curve",
|
|
89
92
|
"TimeAxisConverter",
|
|
90
93
|
}:
|
|
91
94
|
from .plotting import (
|
|
92
95
|
TimeAxisConverter,
|
|
93
96
|
plot_background_subtracted,
|
|
94
97
|
plot_dynamic_spectrum,
|
|
98
|
+
plot_light_curve,
|
|
95
99
|
plot_raw_spectrum,
|
|
96
100
|
)
|
|
97
101
|
|
|
@@ -99,6 +103,7 @@ def __getattr__(name: str):
|
|
|
99
103
|
"plot_dynamic_spectrum": plot_dynamic_spectrum,
|
|
100
104
|
"plot_raw_spectrum": plot_raw_spectrum,
|
|
101
105
|
"plot_background_subtracted": plot_background_subtracted,
|
|
106
|
+
"plot_light_curve": plot_light_curve,
|
|
102
107
|
"TimeAxisConverter": TimeAxisConverter,
|
|
103
108
|
}[name]
|
|
104
109
|
|
ecallistolib/combine.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""
|
|
2
2
|
e-callistolib: Tools for e-CALLISTO FITS dynamic spectra.
|
|
3
|
-
Version 0.2.
|
|
3
|
+
Version 0.2.3
|
|
4
4
|
Sahan S Liyanage (sahanslst@gmail.com)
|
|
5
5
|
Astronomical and Space Science Unit, University of Colombo, Sri Lanka.
|
|
6
6
|
"""
|
|
@@ -48,7 +48,7 @@ def combine_frequency(path1: str | Path, path2: str | Path) -> DynamicSpectrum:
|
|
|
48
48
|
|
|
49
49
|
meta = dict(ds1.meta)
|
|
50
50
|
meta["combined"] = {"mode": "frequency", "sources": [str(ds1.source), str(ds2.source)]}
|
|
51
|
-
return DynamicSpectrum(data=data, freqs_mhz=freqs, time_s=ds1.time_s, source=
|
|
51
|
+
return DynamicSpectrum(data=data, freqs_mhz=freqs, time_s=ds1.time_s, source=ds1.source, meta=meta)
|
|
52
52
|
|
|
53
53
|
|
|
54
54
|
def can_combine_time(paths: Iterable[str | Path], freq_atol: float = 0.01) -> bool:
|
|
@@ -106,5 +106,5 @@ def combine_time(paths: Iterable[str | Path]) -> DynamicSpectrum:
|
|
|
106
106
|
|
|
107
107
|
meta = dict(ds0.meta)
|
|
108
108
|
meta["combined"] = {"mode": "time", "sources": [str(Path(p)) for p in paths]}
|
|
109
|
-
return DynamicSpectrum(data=combined_data, freqs_mhz=freqs, time_s=combined_time, source=
|
|
109
|
+
return DynamicSpectrum(data=combined_data, freqs_mhz=freqs, time_s=combined_time, source=ds0.source, meta=meta)
|
|
110
110
|
|
ecallistolib/crop.py
CHANGED
ecallistolib/download.py
CHANGED
ecallistolib/exceptions.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""
|
|
2
2
|
e-callistolib: Tools for e-CALLISTO FITS dynamic spectra.
|
|
3
|
-
Version 0.2.
|
|
3
|
+
Version 0.2.3
|
|
4
4
|
Sahan S Liyanage (sahanslst@gmail.com)
|
|
5
5
|
Astronomical and Space Science Unit, University of Colombo, Sri Lanka.
|
|
6
6
|
"""
|
|
@@ -36,3 +36,8 @@ class CombineError(ECallistoError):
|
|
|
36
36
|
class CropError(ECallistoError):
|
|
37
37
|
"""Raised when cropping parameters are invalid."""
|
|
38
38
|
pass
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class FrequencyOutOfRangeError(ECallistoError):
|
|
42
|
+
"""Raised when the requested frequency is outside the spectrum's frequency range."""
|
|
43
|
+
pass
|
ecallistolib/io.py
CHANGED
ecallistolib/models.py
CHANGED
ecallistolib/plotting.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""
|
|
2
2
|
e-callistolib: Tools for e-CALLISTO FITS dynamic spectra.
|
|
3
|
-
Version 0.2.
|
|
3
|
+
Version 0.2.3
|
|
4
4
|
Sahan S Liyanage (sahanslst@gmail.com)
|
|
5
5
|
Astronomical and Space Science Unit, University of Colombo, Sri Lanka.
|
|
6
6
|
"""
|
|
@@ -155,39 +155,60 @@ def _get_filename_title(ds: DynamicSpectrum, suffix: str) -> str:
|
|
|
155
155
|
"""Generate plot title from DynamicSpectrum source filename."""
|
|
156
156
|
if ds.source is not None:
|
|
157
157
|
filename = ds.source.stem # Get filename without extension
|
|
158
|
+
# Also strip .fit if it's a double extension like .fit.gz
|
|
159
|
+
if filename.endswith(".fit"):
|
|
160
|
+
filename = filename[:-4]
|
|
158
161
|
return f"{filename}_{suffix}"
|
|
159
162
|
return suffix
|
|
160
163
|
|
|
161
164
|
|
|
162
|
-
|
|
165
|
+
# Conversion factor for Digits to dB (pseudo-calibration)
|
|
166
|
+
# dB = Digits * 2500 / 256 / 25.4 = Digits * 0.384
|
|
167
|
+
DIGITS_TO_DB_FACTOR = 2500.0 / 256.0 / 25.4 # ~0.384
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def plot_dynamic_spectrum(
|
|
163
171
|
ds: DynamicSpectrum,
|
|
172
|
+
process: Literal["raw", "background_subtracted", "noise_reduced"] = "raw",
|
|
173
|
+
clip_low: float | None = None,
|
|
174
|
+
clip_high: float | None = None,
|
|
164
175
|
title: str | None = None,
|
|
165
|
-
cmap: str = "
|
|
176
|
+
cmap: str = "inferno",
|
|
166
177
|
figsize: tuple[float, float] | None = None,
|
|
167
|
-
vmin: float | None = None,
|
|
168
|
-
vmax: float | None = None,
|
|
169
178
|
ax: Optional[plt.Axes] = None,
|
|
170
179
|
show_colorbar: bool = True,
|
|
171
180
|
time_format: Literal["seconds", "ut"] = "seconds",
|
|
181
|
+
intensity_units: Literal["digits", "dB"] = "digits",
|
|
172
182
|
**imshow_kwargs,
|
|
173
183
|
) -> tuple["Figure", "Axes", "AxesImage"]:
|
|
174
184
|
"""
|
|
175
|
-
Plot a
|
|
185
|
+
Plot a DynamicSpectrum with selectable processing mode.
|
|
186
|
+
|
|
187
|
+
This is the main plotting function that supports raw, background-subtracted,
|
|
188
|
+
and noise-reduced visualization modes with full matplotlib customization.
|
|
176
189
|
|
|
177
190
|
Parameters
|
|
178
191
|
----------
|
|
179
192
|
ds : DynamicSpectrum
|
|
180
193
|
The dynamic spectrum to plot.
|
|
181
|
-
|
|
182
|
-
|
|
194
|
+
process : {"raw", "background_subtracted", "noise_reduced"}
|
|
195
|
+
Processing mode to apply before plotting:
|
|
196
|
+
- "raw": Plot the original data without any processing.
|
|
197
|
+
- "background_subtracted": Subtract mean over time for each frequency.
|
|
198
|
+
- "noise_reduced": Apply background subtraction and clipping (requires
|
|
199
|
+
clip_low and clip_high).
|
|
200
|
+
clip_low : float | None
|
|
201
|
+
Lower clipping threshold. Required when process="noise_reduced".
|
|
202
|
+
Also used for colormap normalization in all modes if provided.
|
|
203
|
+
clip_high : float | None
|
|
204
|
+
Upper clipping threshold. Required when process="noise_reduced".
|
|
205
|
+
Also used for colormap normalization in all modes if provided.
|
|
206
|
+
title : str | None
|
|
207
|
+
Plot title. If None, auto-generates from filename and process mode.
|
|
183
208
|
cmap : str
|
|
184
|
-
Matplotlib colormap name.
|
|
209
|
+
Matplotlib colormap name (e.g., "inferno", "viridis", "jet").
|
|
185
210
|
figsize : tuple[float, float] | None
|
|
186
211
|
Figure size as (width, height) in inches. Ignored if ax is provided.
|
|
187
|
-
vmin : float | None
|
|
188
|
-
Minimum value for colormap normalization.
|
|
189
|
-
vmax : float | None
|
|
190
|
-
Maximum value for colormap normalization.
|
|
191
212
|
ax : plt.Axes | None
|
|
192
213
|
Existing axes to plot on. If None, creates a new figure.
|
|
193
214
|
show_colorbar : bool
|
|
@@ -195,19 +216,60 @@ def plot_raw_spectrum(
|
|
|
195
216
|
time_format : {"seconds", "ut"}
|
|
196
217
|
Format for the time axis. "seconds" shows elapsed seconds,
|
|
197
218
|
"ut" shows Universal Time (requires ut_start_sec in metadata).
|
|
219
|
+
intensity_units : {"digits", "dB"}
|
|
220
|
+
Units for the intensity axis. "digits" shows raw ADU values,
|
|
221
|
+
"dB" converts using dB = Digits * 0.384 (pseudo-calibration).
|
|
198
222
|
**imshow_kwargs
|
|
199
223
|
Additional keyword arguments passed to matplotlib's imshow().
|
|
224
|
+
Common options include:
|
|
225
|
+
- interpolation: str ("nearest", "bilinear", "bicubic", etc.)
|
|
226
|
+
- origin: str ("upper", "lower")
|
|
227
|
+
- alpha: float (transparency)
|
|
200
228
|
|
|
201
229
|
Returns
|
|
202
230
|
-------
|
|
203
231
|
tuple[Figure, Axes, AxesImage]
|
|
204
232
|
The figure, axes, and image objects.
|
|
205
233
|
|
|
234
|
+
Raises
|
|
235
|
+
------
|
|
236
|
+
ValueError
|
|
237
|
+
If process="noise_reduced" but clip_low or clip_high is not provided.
|
|
238
|
+
|
|
206
239
|
Example
|
|
207
240
|
-------
|
|
208
241
|
>>> ds = read_fits("spectrum.fit.gz")
|
|
209
|
-
>>>
|
|
242
|
+
>>> # Plot raw spectrum
|
|
243
|
+
>>> fig, ax, im = plot_dynamic_spectrum(ds, process="raw")
|
|
244
|
+
>>> # Plot noise-reduced spectrum
|
|
245
|
+
>>> fig, ax, im = plot_dynamic_spectrum(
|
|
246
|
+
... ds, process="noise_reduced",
|
|
247
|
+
... clip_low=-5, clip_high=20,
|
|
248
|
+
... cmap="jet"
|
|
249
|
+
... )
|
|
210
250
|
"""
|
|
251
|
+
from .processing import background_subtract, noise_reduce_mean_clip
|
|
252
|
+
|
|
253
|
+
# Validate parameters for noise_reduced mode
|
|
254
|
+
if process == "noise_reduced":
|
|
255
|
+
if clip_low is None or clip_high is None:
|
|
256
|
+
raise ValueError(
|
|
257
|
+
"When process='noise_reduced', both clip_low and clip_high must be provided."
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
# Apply processing
|
|
261
|
+
if process == "background_subtracted":
|
|
262
|
+
ds_plot = background_subtract(ds)
|
|
263
|
+
title_suffix = "background_subtracted"
|
|
264
|
+
elif process == "noise_reduced":
|
|
265
|
+
ds_plot = noise_reduce_mean_clip(
|
|
266
|
+
ds, clip_low=clip_low, clip_high=clip_high, scale=None
|
|
267
|
+
)
|
|
268
|
+
title_suffix = "noise_clipped"
|
|
269
|
+
else: # raw
|
|
270
|
+
ds_plot = ds
|
|
271
|
+
title_suffix = "raw"
|
|
272
|
+
|
|
211
273
|
if ax is None:
|
|
212
274
|
fig, ax = plt.subplots(figsize=figsize)
|
|
213
275
|
else:
|
|
@@ -215,8 +277,18 @@ def plot_raw_spectrum(
|
|
|
215
277
|
|
|
216
278
|
extent, converter = _compute_extent(ds, time_format)
|
|
217
279
|
|
|
280
|
+
# Convert to dB if requested
|
|
281
|
+
plot_data = ds_plot.data
|
|
282
|
+
vmin, vmax = clip_low, clip_high
|
|
283
|
+
if intensity_units == "dB":
|
|
284
|
+
plot_data = plot_data * DIGITS_TO_DB_FACTOR
|
|
285
|
+
if vmin is not None:
|
|
286
|
+
vmin = vmin * DIGITS_TO_DB_FACTOR
|
|
287
|
+
if vmax is not None:
|
|
288
|
+
vmax = vmax * DIGITS_TO_DB_FACTOR
|
|
289
|
+
|
|
218
290
|
im = ax.imshow(
|
|
219
|
-
|
|
291
|
+
plot_data,
|
|
220
292
|
aspect="auto",
|
|
221
293
|
extent=extent,
|
|
222
294
|
cmap=cmap,
|
|
@@ -226,65 +298,64 @@ def plot_raw_spectrum(
|
|
|
226
298
|
)
|
|
227
299
|
# Use filename-based title if not provided
|
|
228
300
|
if title is None:
|
|
229
|
-
title = _get_filename_title(ds,
|
|
301
|
+
title = _get_filename_title(ds, title_suffix)
|
|
230
302
|
ax.set_title(title)
|
|
231
303
|
_format_time_axis(ax, converter, time_format)
|
|
232
304
|
ax.set_ylabel("Frequency [MHz]")
|
|
233
305
|
|
|
234
306
|
if show_colorbar:
|
|
235
307
|
cbar = fig.colorbar(im, ax=ax)
|
|
236
|
-
|
|
308
|
+
if intensity_units == "dB":
|
|
309
|
+
cbar.set_label("Intensity [dB]")
|
|
310
|
+
else:
|
|
311
|
+
cbar.set_label("Intensity [Digits]")
|
|
237
312
|
|
|
238
313
|
return fig, ax, im
|
|
239
314
|
|
|
240
315
|
|
|
241
|
-
def
|
|
316
|
+
def plot_raw_spectrum(
|
|
242
317
|
ds: DynamicSpectrum,
|
|
243
318
|
title: str | None = None,
|
|
244
|
-
cmap: str = "
|
|
319
|
+
cmap: str = "viridis",
|
|
245
320
|
figsize: tuple[float, float] | None = None,
|
|
246
|
-
|
|
247
|
-
|
|
321
|
+
clip_low: float | None = None,
|
|
322
|
+
clip_high: float | None = None,
|
|
248
323
|
ax: Optional[plt.Axes] = None,
|
|
249
324
|
show_colorbar: bool = True,
|
|
250
325
|
time_format: Literal["seconds", "ut"] = "seconds",
|
|
326
|
+
intensity_units: Literal["digits", "dB"] = "digits",
|
|
251
327
|
**imshow_kwargs,
|
|
252
328
|
) -> tuple["Figure", "Axes", "AxesImage"]:
|
|
253
329
|
"""
|
|
254
|
-
Plot a DynamicSpectrum
|
|
330
|
+
Plot a raw DynamicSpectrum without any processing.
|
|
255
331
|
|
|
256
|
-
This is
|
|
257
|
-
|
|
258
|
-
and custom time axis formats.
|
|
332
|
+
This is a convenience function that calls plot_dynamic_spectrum with
|
|
333
|
+
process="raw" and a default colormap suitable for raw data.
|
|
259
334
|
|
|
260
335
|
Parameters
|
|
261
336
|
----------
|
|
262
337
|
ds : DynamicSpectrum
|
|
263
338
|
The dynamic spectrum to plot.
|
|
264
|
-
title : str
|
|
339
|
+
title : str | None
|
|
265
340
|
Plot title.
|
|
266
341
|
cmap : str
|
|
267
|
-
Matplotlib colormap name
|
|
342
|
+
Matplotlib colormap name. Default is "viridis".
|
|
268
343
|
figsize : tuple[float, float] | None
|
|
269
|
-
Figure size as (width, height) in inches.
|
|
270
|
-
|
|
271
|
-
Minimum value for colormap normalization
|
|
272
|
-
|
|
273
|
-
Maximum value for colormap normalization
|
|
344
|
+
Figure size as (width, height) in inches.
|
|
345
|
+
clip_low : float | None
|
|
346
|
+
Minimum value for colormap normalization.
|
|
347
|
+
clip_high : float | None
|
|
348
|
+
Maximum value for colormap normalization.
|
|
274
349
|
ax : plt.Axes | None
|
|
275
350
|
Existing axes to plot on. If None, creates a new figure.
|
|
276
351
|
show_colorbar : bool
|
|
277
352
|
Whether to show a colorbar.
|
|
278
353
|
time_format : {"seconds", "ut"}
|
|
279
|
-
Format for the time axis.
|
|
280
|
-
|
|
354
|
+
Format for the time axis.
|
|
355
|
+
intensity_units : {"digits", "dB"}
|
|
356
|
+
Units for the intensity axis.
|
|
281
357
|
**imshow_kwargs
|
|
282
358
|
Additional keyword arguments passed to matplotlib's imshow().
|
|
283
|
-
Common options include:
|
|
284
|
-
- interpolation: str ("nearest", "bilinear", "bicubic", etc.)
|
|
285
|
-
- origin: str ("upper", "lower")
|
|
286
|
-
- alpha: float (transparency)
|
|
287
|
-
- norm: matplotlib.colors.Normalize (custom normalization)
|
|
288
359
|
|
|
289
360
|
Returns
|
|
290
361
|
-------
|
|
@@ -294,43 +365,22 @@ def plot_dynamic_spectrum(
|
|
|
294
365
|
Example
|
|
295
366
|
-------
|
|
296
367
|
>>> ds = read_fits("spectrum.fit.gz")
|
|
297
|
-
>>>
|
|
298
|
-
>>> fig, ax, im = plot_dynamic_spectrum(
|
|
299
|
-
... ds_reduced,
|
|
300
|
-
... title="Noise Reduced",
|
|
301
|
-
... vmin=-5, vmax=20,
|
|
302
|
-
... figsize=(12, 6),
|
|
303
|
-
... cmap="magma"
|
|
304
|
-
... )
|
|
368
|
+
>>> fig, ax, im = plot_raw_spectrum(ds, figsize=(12, 6), cmap="plasma")
|
|
305
369
|
"""
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
im = ax.imshow(
|
|
314
|
-
ds.data,
|
|
315
|
-
aspect="auto",
|
|
316
|
-
extent=extent,
|
|
370
|
+
return plot_dynamic_spectrum(
|
|
371
|
+
ds,
|
|
372
|
+
process="raw",
|
|
373
|
+
clip_low=clip_low,
|
|
374
|
+
clip_high=clip_high,
|
|
375
|
+
title=title,
|
|
317
376
|
cmap=cmap,
|
|
318
|
-
|
|
319
|
-
|
|
377
|
+
figsize=figsize,
|
|
378
|
+
ax=ax,
|
|
379
|
+
show_colorbar=show_colorbar,
|
|
380
|
+
time_format=time_format,
|
|
381
|
+
intensity_units=intensity_units,
|
|
320
382
|
**imshow_kwargs,
|
|
321
383
|
)
|
|
322
|
-
# Use filename-based title if not provided
|
|
323
|
-
if title is None:
|
|
324
|
-
title = _get_filename_title(ds, "dynamic_spectrum")
|
|
325
|
-
ax.set_title(title)
|
|
326
|
-
_format_time_axis(ax, converter, time_format)
|
|
327
|
-
ax.set_ylabel("Frequency [MHz]")
|
|
328
|
-
|
|
329
|
-
if show_colorbar:
|
|
330
|
-
cbar = fig.colorbar(im, ax=ax)
|
|
331
|
-
cbar.set_label("Intensity [DN]")
|
|
332
|
-
|
|
333
|
-
return fig, ax, im
|
|
334
384
|
|
|
335
385
|
|
|
336
386
|
def plot_background_subtracted(
|
|
@@ -338,34 +388,34 @@ def plot_background_subtracted(
|
|
|
338
388
|
title: str | None = None,
|
|
339
389
|
cmap: str = "jet",
|
|
340
390
|
figsize: tuple[float, float] | None = None,
|
|
341
|
-
|
|
342
|
-
|
|
391
|
+
clip_low: float | None = None,
|
|
392
|
+
clip_high: float | None = None,
|
|
343
393
|
ax: Optional[plt.Axes] = None,
|
|
344
394
|
show_colorbar: bool = True,
|
|
345
395
|
time_format: Literal["seconds", "ut"] = "seconds",
|
|
396
|
+
intensity_units: Literal["digits", "dB"] = "digits",
|
|
346
397
|
**imshow_kwargs,
|
|
347
398
|
) -> tuple["Figure", "Axes", "AxesImage"]:
|
|
348
399
|
"""
|
|
349
400
|
Plot a DynamicSpectrum after background subtraction (before clipping).
|
|
350
401
|
|
|
351
|
-
This is a convenience function that
|
|
352
|
-
|
|
353
|
-
the intermediate step before clipping is applied in noise reduction.
|
|
402
|
+
This is a convenience function that calls plot_dynamic_spectrum with
|
|
403
|
+
process="background_subtracted".
|
|
354
404
|
|
|
355
405
|
Parameters
|
|
356
406
|
----------
|
|
357
407
|
ds : DynamicSpectrum
|
|
358
408
|
The raw dynamic spectrum (will be background-subtracted internally).
|
|
359
|
-
title : str
|
|
409
|
+
title : str | None
|
|
360
410
|
Plot title.
|
|
361
411
|
cmap : str
|
|
362
|
-
Matplotlib colormap name. Default is "
|
|
363
|
-
|
|
412
|
+
Matplotlib colormap name. Default is "jet" which works well for
|
|
413
|
+
showing positive/negative deviations.
|
|
364
414
|
figsize : tuple[float, float] | None
|
|
365
415
|
Figure size as (width, height) in inches.
|
|
366
|
-
|
|
416
|
+
clip_low : float | None
|
|
367
417
|
Minimum value for colormap normalization.
|
|
368
|
-
|
|
418
|
+
clip_high : float | None
|
|
369
419
|
Maximum value for colormap normalization.
|
|
370
420
|
ax : plt.Axes | None
|
|
371
421
|
Existing axes to plot on. If None, creates a new figure.
|
|
@@ -373,6 +423,8 @@ def plot_background_subtracted(
|
|
|
373
423
|
Whether to show a colorbar.
|
|
374
424
|
time_format : {"seconds", "ut"}
|
|
375
425
|
Format for the time axis.
|
|
426
|
+
intensity_units : {"digits", "dB"}
|
|
427
|
+
Units for the intensity axis.
|
|
376
428
|
**imshow_kwargs
|
|
377
429
|
Additional keyword arguments passed to matplotlib's imshow().
|
|
378
430
|
|
|
@@ -384,23 +436,183 @@ def plot_background_subtracted(
|
|
|
384
436
|
Example
|
|
385
437
|
-------
|
|
386
438
|
>>> ds = read_fits("spectrum.fit.gz")
|
|
387
|
-
>>> fig, ax, im = plot_background_subtracted(ds,
|
|
439
|
+
>>> fig, ax, im = plot_background_subtracted(ds, clip_low=-10, clip_high=30)
|
|
388
440
|
"""
|
|
389
|
-
from .processing import background_subtract
|
|
390
|
-
|
|
391
|
-
ds_bg = background_subtract(ds)
|
|
392
|
-
# Use filename-based title if not provided
|
|
393
|
-
if title is None:
|
|
394
|
-
title = _get_filename_title(ds, "background_subtracted")
|
|
395
441
|
return plot_dynamic_spectrum(
|
|
396
|
-
|
|
442
|
+
ds,
|
|
443
|
+
process="background_subtracted",
|
|
444
|
+
clip_low=clip_low,
|
|
445
|
+
clip_high=clip_high,
|
|
397
446
|
title=title,
|
|
398
447
|
cmap=cmap,
|
|
399
448
|
figsize=figsize,
|
|
400
|
-
vmin=vmin,
|
|
401
|
-
vmax=vmax,
|
|
402
449
|
ax=ax,
|
|
403
450
|
show_colorbar=show_colorbar,
|
|
404
451
|
time_format=time_format,
|
|
452
|
+
intensity_units=intensity_units,
|
|
405
453
|
**imshow_kwargs,
|
|
406
454
|
)
|
|
455
|
+
|
|
456
|
+
|
|
457
|
+
def plot_light_curve(
|
|
458
|
+
ds: DynamicSpectrum,
|
|
459
|
+
frequency_mhz: float,
|
|
460
|
+
process: Literal["raw", "background_subtracted", "noise_reduced"] = "raw",
|
|
461
|
+
title: str | None = None,
|
|
462
|
+
figsize: tuple[float, float] | None = None,
|
|
463
|
+
ax: Optional[plt.Axes] = None,
|
|
464
|
+
time_format: Literal["seconds", "ut"] = "seconds",
|
|
465
|
+
clip_low: float | None = None,
|
|
466
|
+
clip_high: float | None = None,
|
|
467
|
+
intensity_units: Literal["digits", "dB"] = "digits",
|
|
468
|
+
**plot_kwargs,
|
|
469
|
+
) -> tuple["Figure", "Axes", "plt.Line2D"]:
|
|
470
|
+
"""
|
|
471
|
+
Plot a light curve (intensity vs time) at a specific frequency.
|
|
472
|
+
|
|
473
|
+
This function extracts the intensity values at the frequency channel closest
|
|
474
|
+
to the specified frequency and plots them against time. The data can be
|
|
475
|
+
plotted raw, after background subtraction, or after full noise reduction.
|
|
476
|
+
|
|
477
|
+
Parameters
|
|
478
|
+
----------
|
|
479
|
+
ds : DynamicSpectrum
|
|
480
|
+
The dynamic spectrum to extract the light curve from.
|
|
481
|
+
frequency_mhz : float
|
|
482
|
+
The target frequency in MHz. The function will use the closest
|
|
483
|
+
available frequency channel in the spectrum.
|
|
484
|
+
process : {"raw", "background_subtracted", "noise_reduced"}
|
|
485
|
+
Processing to apply before plotting:
|
|
486
|
+
- "raw": Use the original data without any processing.
|
|
487
|
+
- "background_subtracted": Subtract mean over time for each frequency.
|
|
488
|
+
- "noise_reduced": Apply full noise reduction (requires clip_low/clip_high).
|
|
489
|
+
title : str | None
|
|
490
|
+
Plot title. If None, generates title from filename and frequency.
|
|
491
|
+
figsize : tuple[float, float] | None
|
|
492
|
+
Figure size as (width, height) in inches. Ignored if ax is provided.
|
|
493
|
+
ax : plt.Axes | None
|
|
494
|
+
Existing axes to plot on. If None, creates a new figure.
|
|
495
|
+
time_format : {"seconds", "ut"}
|
|
496
|
+
Format for the time axis. "seconds" shows elapsed seconds,
|
|
497
|
+
"ut" shows Universal Time (requires ut_start_sec in metadata).
|
|
498
|
+
clip_low : float | None
|
|
499
|
+
Lower clipping threshold for noise reduction. Required if process="noise_reduced".
|
|
500
|
+
clip_high : float | None
|
|
501
|
+
Upper clipping threshold for noise reduction. Required if process="noise_reduced".
|
|
502
|
+
intensity_units : {"digits", "dB"}
|
|
503
|
+
Units for the intensity axis. "digits" shows raw ADU values,
|
|
504
|
+
"dB" converts using dB = Digits * 0.384 (pseudo-calibration).
|
|
505
|
+
**plot_kwargs
|
|
506
|
+
Additional keyword arguments passed to matplotlib's plot().
|
|
507
|
+
|
|
508
|
+
Returns
|
|
509
|
+
-------
|
|
510
|
+
tuple[Figure, Axes, Line2D]
|
|
511
|
+
The figure, axes, and line objects.
|
|
512
|
+
|
|
513
|
+
Raises
|
|
514
|
+
------
|
|
515
|
+
FrequencyOutOfRangeError
|
|
516
|
+
If the requested frequency is outside the spectrum's frequency range.
|
|
517
|
+
ValueError
|
|
518
|
+
If process="noise_reduced" but clip_low or clip_high is not provided.
|
|
519
|
+
|
|
520
|
+
Example
|
|
521
|
+
-------
|
|
522
|
+
>>> ds = read_fits("spectrum.fit.gz")
|
|
523
|
+
>>> # Plot raw light curve at 60 MHz
|
|
524
|
+
>>> fig, ax, line = plot_light_curve(ds, frequency_mhz=60, process="raw")
|
|
525
|
+
>>> # Plot noise-reduced light curve with custom clipping
|
|
526
|
+
>>> fig, ax, line = plot_light_curve(
|
|
527
|
+
... ds, frequency_mhz=60, process="noise_reduced",
|
|
528
|
+
... clip_low=-5, clip_high=20
|
|
529
|
+
... )
|
|
530
|
+
"""
|
|
531
|
+
from .exceptions import FrequencyOutOfRangeError
|
|
532
|
+
from .processing import background_subtract, noise_reduce_mean_clip
|
|
533
|
+
|
|
534
|
+
# Validate frequency is within range
|
|
535
|
+
freq_min = float(ds.freqs_mhz.min())
|
|
536
|
+
freq_max = float(ds.freqs_mhz.max())
|
|
537
|
+
|
|
538
|
+
if frequency_mhz < freq_min or frequency_mhz > freq_max:
|
|
539
|
+
raise FrequencyOutOfRangeError(
|
|
540
|
+
f"Requested frequency {frequency_mhz} MHz is outside the spectrum's "
|
|
541
|
+
f"frequency range [{freq_min:.2f}, {freq_max:.2f}] MHz."
|
|
542
|
+
)
|
|
543
|
+
|
|
544
|
+
# Validate clip parameters for noise_reduced
|
|
545
|
+
if process == "noise_reduced":
|
|
546
|
+
if clip_low is None or clip_high is None:
|
|
547
|
+
raise ValueError(
|
|
548
|
+
"When process='noise_reduced', both clip_low and clip_high must be provided."
|
|
549
|
+
)
|
|
550
|
+
|
|
551
|
+
# Find the closest frequency channel
|
|
552
|
+
freq_idx = int(np.argmin(np.abs(ds.freqs_mhz - frequency_mhz)))
|
|
553
|
+
actual_freq = float(ds.freqs_mhz[freq_idx])
|
|
554
|
+
|
|
555
|
+
# Apply processing
|
|
556
|
+
if process == "background_subtracted":
|
|
557
|
+
ds_processed = background_subtract(ds)
|
|
558
|
+
elif process == "noise_reduced":
|
|
559
|
+
ds_processed = noise_reduce_mean_clip(
|
|
560
|
+
ds, clip_low=clip_low, clip_high=clip_high, scale=None
|
|
561
|
+
)
|
|
562
|
+
else: # raw
|
|
563
|
+
ds_processed = ds
|
|
564
|
+
|
|
565
|
+
# Extract light curve data
|
|
566
|
+
light_curve = ds_processed.data[freq_idx, :]
|
|
567
|
+
|
|
568
|
+
# Convert to dB if requested
|
|
569
|
+
if intensity_units == "dB":
|
|
570
|
+
light_curve = light_curve * DIGITS_TO_DB_FACTOR
|
|
571
|
+
|
|
572
|
+
# Create figure and axes
|
|
573
|
+
if ax is None:
|
|
574
|
+
fig, ax = plt.subplots(figsize=figsize)
|
|
575
|
+
else:
|
|
576
|
+
fig = ax.figure
|
|
577
|
+
|
|
578
|
+
# Prepare time axis
|
|
579
|
+
if time_format == "ut":
|
|
580
|
+
converter = TimeAxisConverter.from_dynamic_spectrum(ds)
|
|
581
|
+
time_values = ds.time_s + converter.ut_start_sec
|
|
582
|
+
ax.set_xlabel("Time [UT]")
|
|
583
|
+
# Format x-tick labels as UT times
|
|
584
|
+
from matplotlib.ticker import FuncFormatter
|
|
585
|
+
|
|
586
|
+
def fmt(x, pos):
|
|
587
|
+
return converter.seconds_to_ut(x - converter.ut_start_sec)
|
|
588
|
+
|
|
589
|
+
ax.xaxis.set_major_formatter(FuncFormatter(fmt))
|
|
590
|
+
else:
|
|
591
|
+
time_values = ds.time_s
|
|
592
|
+
ax.set_xlabel("Time [s]")
|
|
593
|
+
|
|
594
|
+
# Plot the light curve
|
|
595
|
+
(line,) = ax.plot(time_values, light_curve, **plot_kwargs)
|
|
596
|
+
|
|
597
|
+
# Set title
|
|
598
|
+
if title is None:
|
|
599
|
+
# Map process name to title suffix
|
|
600
|
+
title_suffix = "noise_clipped" if process == "noise_reduced" else process
|
|
601
|
+
if ds.source is not None:
|
|
602
|
+
filename = ds.source.stem
|
|
603
|
+
# Strip .fit if it's a double extension like .fit.gz
|
|
604
|
+
if filename.endswith(".fit"):
|
|
605
|
+
filename = filename[:-4]
|
|
606
|
+
title = f"{filename}_light_curve_{actual_freq:.1f}MHz_{title_suffix}"
|
|
607
|
+
else:
|
|
608
|
+
title = f"Light Curve @ {actual_freq:.1f} MHz ({title_suffix})"
|
|
609
|
+
|
|
610
|
+
ax.set_title(title)
|
|
611
|
+
|
|
612
|
+
if intensity_units == "dB":
|
|
613
|
+
ax.set_ylabel("Intensity [dB]")
|
|
614
|
+
else:
|
|
615
|
+
ax.set_ylabel("Intensity [Digits]")
|
|
616
|
+
|
|
617
|
+
return fig, ax, line
|
|
618
|
+
|
ecallistolib/processing.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""
|
|
2
2
|
e-callistolib: Tools for e-CALLISTO FITS dynamic spectra.
|
|
3
|
-
Version 0.2.
|
|
3
|
+
Version 0.2.3
|
|
4
4
|
Sahan S Liyanage (sahanslst@gmail.com)
|
|
5
5
|
Astronomical and Space Science Unit, University of Colombo, Sri Lanka.
|
|
6
6
|
"""
|
|
@@ -14,8 +14,8 @@ from .models import DynamicSpectrum
|
|
|
14
14
|
|
|
15
15
|
def noise_reduce_mean_clip(
|
|
16
16
|
ds: DynamicSpectrum,
|
|
17
|
-
clip_low: float
|
|
18
|
-
clip_high: float
|
|
17
|
+
clip_low: float,
|
|
18
|
+
clip_high: float,
|
|
19
19
|
scale: float | None = (2500.0 / 255.0 / 25.4),
|
|
20
20
|
) -> DynamicSpectrum:
|
|
21
21
|
"""
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ecallistolib
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.3.1
|
|
4
4
|
Summary: Tools to download, read, process, and plot e-CALLISTO FITS dynamic spectra.
|
|
5
5
|
Author: Sahan S. Liyanage
|
|
6
6
|
License: MIT
|
|
@@ -117,11 +117,14 @@ import ecallistolib as ecl
|
|
|
117
117
|
# Read a FITS file
|
|
118
118
|
spectrum = ecl.read_fits("ALASKA_20230101_120000_01.fit.gz")
|
|
119
119
|
|
|
120
|
-
#
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
120
|
+
# Plot with different processing modes
|
|
121
|
+
fig, ax, im = ecl.plot_dynamic_spectrum(
|
|
122
|
+
spectrum,
|
|
123
|
+
process="noise_reduced",
|
|
124
|
+
clip_low=-5,
|
|
125
|
+
clip_high=20,
|
|
126
|
+
title="Solar Radio Burst"
|
|
127
|
+
)
|
|
125
128
|
```
|
|
126
129
|
|
|
127
130
|
---
|
|
@@ -200,14 +203,11 @@ import ecallistolib as ecl
|
|
|
200
203
|
|
|
201
204
|
spectrum = ecl.read_fits("my_spectrum.fit.gz")
|
|
202
205
|
|
|
203
|
-
# Apply noise reduction with
|
|
204
|
-
cleaned = ecl.noise_reduce_mean_clip(spectrum)
|
|
205
|
-
|
|
206
|
-
# Or customize the parameters
|
|
206
|
+
# Apply noise reduction with required clipping values
|
|
207
207
|
cleaned = ecl.noise_reduce_mean_clip(
|
|
208
208
|
spectrum,
|
|
209
|
-
clip_low=-5.0, # Lower clipping threshold
|
|
210
|
-
clip_high=20.0, # Upper clipping threshold
|
|
209
|
+
clip_low=-5.0, # Lower clipping threshold (required)
|
|
210
|
+
clip_high=20.0, # Upper clipping threshold (required)
|
|
211
211
|
scale=2500.0 / 255.0 / 25.4 # Scaling factor (None to disable)
|
|
212
212
|
)
|
|
213
213
|
|
|
@@ -333,28 +333,28 @@ if ecl.can_combine_time(files):
|
|
|
333
333
|
|
|
334
334
|
### Plotting
|
|
335
335
|
|
|
336
|
-
Create dynamic spectrum visualizations with
|
|
336
|
+
Create dynamic spectrum visualizations with selectable processing modes:
|
|
337
337
|
|
|
338
338
|
```python
|
|
339
339
|
import ecallistolib as ecl
|
|
340
340
|
import matplotlib.pyplot as plt
|
|
341
341
|
|
|
342
342
|
spectrum = ecl.read_fits("my_spectrum.fit.gz")
|
|
343
|
-
cleaned = ecl.noise_reduce_mean_clip(spectrum)
|
|
344
343
|
|
|
345
|
-
#
|
|
346
|
-
fig, ax, im = ecl.plot_dynamic_spectrum(
|
|
344
|
+
# Plot raw spectrum
|
|
345
|
+
fig, ax, im = ecl.plot_dynamic_spectrum(spectrum, process="raw")
|
|
347
346
|
plt.show()
|
|
348
347
|
|
|
349
|
-
#
|
|
348
|
+
# Plot noise-reduced spectrum with required clipping values
|
|
350
349
|
fig, ax, im = ecl.plot_dynamic_spectrum(
|
|
351
|
-
|
|
350
|
+
spectrum,
|
|
351
|
+
process="noise_reduced", # Apply noise reduction
|
|
352
|
+
clip_low=-5, # Lower clipping bound (required)
|
|
353
|
+
clip_high=20, # Upper clipping bound (required)
|
|
352
354
|
title="Type III Solar Burst",
|
|
353
|
-
cmap="magma",
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
figsize=(12, 6), # Figure size in inches
|
|
357
|
-
interpolation="bilinear" # Any matplotlib imshow kwarg
|
|
355
|
+
cmap="magma",
|
|
356
|
+
figsize=(12, 6),
|
|
357
|
+
interpolation="bilinear"
|
|
358
358
|
)
|
|
359
359
|
plt.savefig("spectrum.png", dpi=150, bbox_inches="tight")
|
|
360
360
|
```
|
|
@@ -385,8 +385,8 @@ spectrum = ecl.read_fits("my_spectrum.fit.gz")
|
|
|
385
385
|
# Plot after background subtraction but before clipping
|
|
386
386
|
fig, ax, im = ecl.plot_background_subtracted(
|
|
387
387
|
spectrum,
|
|
388
|
-
|
|
389
|
-
|
|
388
|
+
clip_low=-10,
|
|
389
|
+
clip_high=30,
|
|
390
390
|
cmap="RdBu_r" # Diverging colormap for +/- values
|
|
391
391
|
)
|
|
392
392
|
```
|
|
@@ -407,6 +407,24 @@ ecl.plot_dynamic_spectrum(spectrum, time_format="seconds")
|
|
|
407
407
|
ecl.plot_dynamic_spectrum(spectrum, time_format="ut")
|
|
408
408
|
```
|
|
409
409
|
|
|
410
|
+
#### Intensity Units
|
|
411
|
+
|
|
412
|
+
Choose between raw digital values (Digits/ADU) or pseudo-calibrated dB:
|
|
413
|
+
|
|
414
|
+
```python
|
|
415
|
+
import ecallistolib as ecl
|
|
416
|
+
|
|
417
|
+
spectrum = ecl.read_fits("my_spectrum.fit.gz")
|
|
418
|
+
|
|
419
|
+
# Default: intensity in Digits (raw ADU values)
|
|
420
|
+
ecl.plot_dynamic_spectrum(spectrum, intensity_units="digits")
|
|
421
|
+
|
|
422
|
+
# Convert to dB using: dB = Digits * 0.384 (pseudo-calibration)
|
|
423
|
+
ecl.plot_dynamic_spectrum(spectrum, intensity_units="dB")
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
> **Note:** The dB conversion uses the formula: dB = Digits × 2500 / 256 / 25.4 ≈ Digits × 0.384
|
|
427
|
+
|
|
410
428
|
#### Time Axis Converter
|
|
411
429
|
|
|
412
430
|
Convert between elapsed seconds and UT time programmatically:
|
|
@@ -439,12 +457,65 @@ fig, axes = plt.subplots(1, 2, figsize=(14, 5))
|
|
|
439
457
|
spectrum1 = ecl.read_fits("file1.fit.gz")
|
|
440
458
|
spectrum2 = ecl.read_fits("file2.fit.gz")
|
|
441
459
|
|
|
442
|
-
ecl.
|
|
460
|
+
ecl.plot_dynamic_spectrum(spectrum1, process="raw", ax=axes[0], title="Raw")
|
|
443
461
|
ecl.plot_dynamic_spectrum(
|
|
444
|
-
|
|
462
|
+
spectrum2,
|
|
463
|
+
process="noise_reduced",
|
|
445
464
|
ax=axes[1],
|
|
446
465
|
title="Noise Reduced",
|
|
447
|
-
|
|
466
|
+
clip_low=-5, clip_high=20
|
|
467
|
+
)
|
|
468
|
+
|
|
469
|
+
plt.tight_layout()
|
|
470
|
+
plt.show()
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
#### Light Curve Plotting
|
|
474
|
+
|
|
475
|
+
Plot intensity vs time at a specific frequency:
|
|
476
|
+
|
|
477
|
+
```python
|
|
478
|
+
import ecallistolib as ecl
|
|
479
|
+
import matplotlib.pyplot as plt
|
|
480
|
+
|
|
481
|
+
spectrum = ecl.read_fits("my_spectrum.fit.gz")
|
|
482
|
+
|
|
483
|
+
# Plot raw light curve at 60 MHz
|
|
484
|
+
fig, ax, line = ecl.plot_light_curve(spectrum, frequency_mhz=60, process="raw")
|
|
485
|
+
plt.show()
|
|
486
|
+
|
|
487
|
+
# Plot background-subtracted light curve
|
|
488
|
+
fig, ax, line = ecl.plot_light_curve(
|
|
489
|
+
spectrum, frequency_mhz=60, process="background_subtracted"
|
|
490
|
+
)
|
|
491
|
+
plt.show()
|
|
492
|
+
|
|
493
|
+
# Plot noise-reduced light curve (must provide clip values)
|
|
494
|
+
fig, ax, line = ecl.plot_light_curve(
|
|
495
|
+
spectrum,
|
|
496
|
+
frequency_mhz=60,
|
|
497
|
+
process="noise_reduced",
|
|
498
|
+
clip_low=-5,
|
|
499
|
+
clip_high=20
|
|
500
|
+
)
|
|
501
|
+
plt.show()
|
|
502
|
+
```
|
|
503
|
+
|
|
504
|
+
Compare all three processing modes:
|
|
505
|
+
|
|
506
|
+
```python
|
|
507
|
+
import ecallistolib as ecl
|
|
508
|
+
import matplotlib.pyplot as plt
|
|
509
|
+
|
|
510
|
+
spectrum = ecl.read_fits("my_spectrum.fit.gz")
|
|
511
|
+
|
|
512
|
+
fig, axes = plt.subplots(3, 1, figsize=(12, 10))
|
|
513
|
+
|
|
514
|
+
ecl.plot_light_curve(spectrum, 60, process="raw", ax=axes[0], title="Raw")
|
|
515
|
+
ecl.plot_light_curve(spectrum, 60, process="background_subtracted", ax=axes[1], title="BG Sub")
|
|
516
|
+
ecl.plot_light_curve(
|
|
517
|
+
spectrum, 60, process="noise_reduced", ax=axes[2], title="Noise Reduced",
|
|
518
|
+
clip_low=-5, clip_high=20
|
|
448
519
|
)
|
|
449
520
|
|
|
450
521
|
plt.tight_layout()
|
|
@@ -652,36 +723,65 @@ Concatenate spectra horizontally (time concatenation).
|
|
|
652
723
|
|
|
653
724
|
### Plotting Functions
|
|
654
725
|
|
|
655
|
-
#### `plot_dynamic_spectrum(ds,
|
|
726
|
+
#### `plot_dynamic_spectrum(ds, process="raw", clip_low=None, clip_high=None, title=None, cmap="inferno", figsize=None, ax=None, show_colorbar=True, time_format="seconds", intensity_units="digits", **imshow_kwargs)`
|
|
656
727
|
|
|
657
|
-
Plot a dynamic spectrum with
|
|
728
|
+
Plot a dynamic spectrum with selectable processing mode.
|
|
658
729
|
|
|
659
730
|
| Parameter | Type | Default | Description |
|
|
660
731
|
|-----------|------|---------|-------------|
|
|
661
732
|
| `ds` | `DynamicSpectrum` | — | Spectrum to plot |
|
|
662
|
-
| `
|
|
733
|
+
| `process` | `str` | `"raw"` | Processing mode: `"raw"`, `"background_subtracted"`, or `"noise_reduced"` |
|
|
734
|
+
| `clip_low` | `float \| None` | `None` | Lower clipping bound (required for `"noise_reduced"`) |
|
|
735
|
+
| `clip_high` | `float \| None` | `None` | Upper clipping bound (required for `"noise_reduced"`) |
|
|
736
|
+
| `title` | `str \| None` | `None` | Plot title (auto-generated if `None`) |
|
|
663
737
|
| `cmap` | `str` | `"inferno"` | Matplotlib colormap |
|
|
664
738
|
| `figsize` | `tuple \| None` | `None` | Figure size as `(width, height)` in inches |
|
|
665
|
-
| `vmin` | `float \| None` | `None` | Colormap lower bound (clipping) |
|
|
666
|
-
| `vmax` | `float \| None` | `None` | Colormap upper bound (clipping) |
|
|
667
739
|
| `ax` | `Axes \| None` | `None` | Existing axes (creates new if `None`) |
|
|
668
740
|
| `show_colorbar` | `bool` | `True` | Whether to display colorbar |
|
|
669
741
|
| `time_format` | `str` | `"seconds"` | `"seconds"` or `"ut"` for time axis format |
|
|
742
|
+
| `intensity_units` | `str` | `"digits"` | `"digits"` (raw ADU) or `"dB"` (pseudo-calibrated) |
|
|
670
743
|
| `**imshow_kwargs` | — | — | Additional kwargs passed to `matplotlib.imshow()` |
|
|
671
744
|
|
|
672
745
|
**Returns:** Tuple of `(fig, ax, im)`.
|
|
673
746
|
|
|
747
|
+
**Raises:** `ValueError` if `process="noise_reduced"` without `clip_low` and `clip_high`.
|
|
748
|
+
|
|
749
|
+
---
|
|
750
|
+
|
|
751
|
+
#### `plot_raw_spectrum(ds, clip_low=None, clip_high=None, title=None, cmap="viridis", ...)`
|
|
752
|
+
|
|
753
|
+
Convenience function that calls `plot_dynamic_spectrum` with `process="raw"`.
|
|
754
|
+
|
|
674
755
|
---
|
|
675
756
|
|
|
676
|
-
#### `
|
|
757
|
+
#### `plot_background_subtracted(ds, clip_low=None, clip_high=None, title=None, cmap="jet", ...)`
|
|
677
758
|
|
|
678
|
-
|
|
759
|
+
Convenience function that calls `plot_dynamic_spectrum` with `process="background_subtracted"`.
|
|
679
760
|
|
|
680
761
|
---
|
|
681
762
|
|
|
682
|
-
#### `
|
|
763
|
+
#### `plot_light_curve(ds, frequency_mhz, process="raw", title=None, figsize=None, ax=None, time_format="seconds", clip_low=None, clip_high=None, **plot_kwargs)`
|
|
764
|
+
|
|
765
|
+
Plot a light curve (intensity vs time) at a specific frequency.
|
|
766
|
+
|
|
767
|
+
| Parameter | Type | Default | Description |
|
|
768
|
+
|-----------|------|---------|-------------|
|
|
769
|
+
| `ds` | `DynamicSpectrum` | — | Spectrum to extract light curve from |
|
|
770
|
+
| `frequency_mhz` | `float` | — | Target frequency in MHz |
|
|
771
|
+
| `process` | `str` | `"raw"` | Processing mode: `"raw"`, `"background_subtracted"`, or `"noise_reduced"` |
|
|
772
|
+
| `title` | `str \| None` | `None` | Plot title (auto-generated if `None`) |
|
|
773
|
+
| `figsize` | `tuple \| None` | `None` | Figure size as `(width, height)` in inches |
|
|
774
|
+
| `ax` | `Axes \| None` | `None` | Existing axes (creates new if `None`) |
|
|
775
|
+
| `time_format` | `str` | `"seconds"` | `"seconds"` or `"ut"` for time axis format |
|
|
776
|
+
| `clip_low` | `float \| None` | `None` | Lower clip threshold (required for `"noise_reduced"`) |
|
|
777
|
+
| `clip_high` | `float \| None` | `None` | Upper clip threshold (required for `"noise_reduced"`) |
|
|
778
|
+
| `**plot_kwargs` | — | — | Additional kwargs passed to `matplotlib.plot()` |
|
|
779
|
+
|
|
780
|
+
**Returns:** Tuple of `(fig, ax, line)`.
|
|
683
781
|
|
|
684
|
-
|
|
782
|
+
**Raises:**
|
|
783
|
+
- `FrequencyOutOfRangeError` if frequency is outside spectrum's range.
|
|
784
|
+
- `ValueError` if `process="noise_reduced"` without `clip_low` and `clip_high`.
|
|
685
785
|
|
|
686
786
|
---
|
|
687
787
|
|
|
@@ -715,6 +815,7 @@ The library provides a hierarchy of custom exceptions for robust error handling:
|
|
|
715
815
|
| `DownloadError` | Raised when downloading files from the archive fails |
|
|
716
816
|
| `CombineError` | Raised when spectra cannot be combined |
|
|
717
817
|
| `CropError` | Raised when cropping parameters are invalid |
|
|
818
|
+
| `FrequencyOutOfRangeError` | Raised when the requested frequency is outside the spectrum's range |
|
|
718
819
|
|
|
719
820
|
#### Error Handling Example
|
|
720
821
|
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
ecallistolib/__init__.py,sha256=MOEjuYi132aHYdFNN8ReRcu95eXOVWFsyRvX2zPb6Os,3003
|
|
2
|
+
ecallistolib/combine.py,sha256=G1ySitPAFbKVNL3u_-Fva4prdYXzq4glIpf8YC8aF5g,3327
|
|
3
|
+
ecallistolib/crop.py,sha256=DactJZ9DtZ50zj7Cp6Ii0F6sCieVloGyzWqMY7HmJ9I,6383
|
|
4
|
+
ecallistolib/download.py,sha256=XbqcLqptKS16D8MP9bWZZprFviQdw1hbt9ctsW1N91s,4114
|
|
5
|
+
ecallistolib/exceptions.py,sha256=e993ColPiVOyOP7Dh7RY4GlRoClwFCPABLiWaS5cLuk,1027
|
|
6
|
+
ecallistolib/io.py,sha256=_uSw6L6Bm1t5GjpVMGtdoF_5NmgEVVDzCXW2nRVFbV8,3686
|
|
7
|
+
ecallistolib/models.py,sha256=Mv8fRWKsbNlMQi20_6oxUz9UX6wkckZAcS9Tj0kH-b4,1299
|
|
8
|
+
ecallistolib/plotting.py,sha256=rEItUrxAXfMj76_MPmoycgfxcbsuWztc3cduWKppkSU,20616
|
|
9
|
+
ecallistolib/processing.py,sha256=enwu8KSome09u4Iv5zjhY80t1HbnGFz3xXf2Wr3Lp7k,1962
|
|
10
|
+
ecallistolib-0.2.3.1.dist-info/licenses/LICENSE,sha256=WunjkzsBGyy9vIQxfNe_GDV1yKBQJ-0WbFt4AXZ5Rvc,1073
|
|
11
|
+
ecallistolib-0.2.3.1.dist-info/METADATA,sha256=DKCz6dCWETaMp-LGv3nzlJmeurCal8zfljHeK8uc0YQ,26292
|
|
12
|
+
ecallistolib-0.2.3.1.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
13
|
+
ecallistolib-0.2.3.1.dist-info/top_level.txt,sha256=DmLjR5jlE2i2mQXou5gyCpaHOOlNs4DIQyCPoGXhsbc,13
|
|
14
|
+
ecallistolib-0.2.3.1.dist-info/RECORD,,
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
ecallistolib/__init__.py,sha256=9O277WBX99gg3MqWcv-tiaQxB6IKeMfHM91uDJP_9O0,2833
|
|
2
|
-
ecallistolib/combine.py,sha256=79LuR2HngpTbaM2xBg7aqUGK_1xkK3RomKmomWG2FpE,3315
|
|
3
|
-
ecallistolib/crop.py,sha256=zcAsd5XP-_lG9exBPUFYt4PJslzxLabjSLvbdSADhDk,6383
|
|
4
|
-
ecallistolib/download.py,sha256=gUmDLZDjyVIElzqZnGoAREkpOaxYNsAUDeujlGwd_o4,4114
|
|
5
|
-
ecallistolib/exceptions.py,sha256=F0EdRCi54ut8qQDtDVZxhGn3P_JbsoQ8hNVxKCFpO5s,879
|
|
6
|
-
ecallistolib/io.py,sha256=e-BMtWvILsqs2ua89Ysa2vwZ9s4mDukDGVPYDA3ed-E,3686
|
|
7
|
-
ecallistolib/models.py,sha256=v8bl1fN3jKHVbQmpfVSv3ZusFrkWZJ1ciZkuufygmjE,1299
|
|
8
|
-
ecallistolib/plotting.py,sha256=RhTJK5qGwCcBRRJP-mDNyGoWzd5diHCbx1IyXK8PraU,12296
|
|
9
|
-
ecallistolib/processing.py,sha256=eBH3uGt3RmGM1NRdH_wJ7AAcVeadk9te-pHc9pWy2Lo,1976
|
|
10
|
-
ecallistolib-0.2.2.dist-info/licenses/LICENSE,sha256=WunjkzsBGyy9vIQxfNe_GDV1yKBQJ-0WbFt4AXZ5Rvc,1073
|
|
11
|
-
ecallistolib-0.2.2.dist-info/METADATA,sha256=rYRt_P0-XByK08F3UfgEaFlZSDyyALh7Ot4EFPkr4Rc,22765
|
|
12
|
-
ecallistolib-0.2.2.dist-info/WHEEL,sha256=qELbo2s1Yzl39ZmrAibXA2jjPLUYfnVhUNTlyF1rq0Y,92
|
|
13
|
-
ecallistolib-0.2.2.dist-info/top_level.txt,sha256=DmLjR5jlE2i2mQXou5gyCpaHOOlNs4DIQyCPoGXhsbc,13
|
|
14
|
-
ecallistolib-0.2.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|