ecallistolib 0.2.2__tar.gz → 0.2.3.1__tar.gz
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-0.2.2/src/ecallistolib.egg-info → ecallistolib-0.2.3.1}/PKG-INFO +138 -37
- {ecallistolib-0.2.2 → ecallistolib-0.2.3.1}/README.md +137 -36
- {ecallistolib-0.2.2 → ecallistolib-0.2.3.1}/pyproject.toml +1 -1
- {ecallistolib-0.2.2 → ecallistolib-0.2.3.1}/src/ecallistolib/__init__.py +6 -1
- {ecallistolib-0.2.2 → ecallistolib-0.2.3.1}/src/ecallistolib/combine.py +3 -3
- {ecallistolib-0.2.2 → ecallistolib-0.2.3.1}/src/ecallistolib/crop.py +1 -1
- {ecallistolib-0.2.2 → ecallistolib-0.2.3.1}/src/ecallistolib/download.py +1 -1
- {ecallistolib-0.2.2 → ecallistolib-0.2.3.1}/src/ecallistolib/exceptions.py +6 -1
- {ecallistolib-0.2.2 → ecallistolib-0.2.3.1}/src/ecallistolib/io.py +1 -1
- {ecallistolib-0.2.2 → ecallistolib-0.2.3.1}/src/ecallistolib/models.py +1 -1
- ecallistolib-0.2.3.1/src/ecallistolib/plotting.py +618 -0
- {ecallistolib-0.2.2 → ecallistolib-0.2.3.1}/src/ecallistolib/processing.py +3 -3
- {ecallistolib-0.2.2 → ecallistolib-0.2.3.1/src/ecallistolib.egg-info}/PKG-INFO +138 -37
- {ecallistolib-0.2.2 → ecallistolib-0.2.3.1}/tests/test_crop.py +1 -1
- {ecallistolib-0.2.2 → ecallistolib-0.2.3.1}/tests/test_exceptions.py +6 -1
- {ecallistolib-0.2.2 → ecallistolib-0.2.3.1}/tests/test_imports.py +1 -1
- {ecallistolib-0.2.2 → ecallistolib-0.2.3.1}/tests/test_integration.py +3 -3
- {ecallistolib-0.2.2 → ecallistolib-0.2.3.1}/tests/test_io.py +1 -1
- {ecallistolib-0.2.2 → ecallistolib-0.2.3.1}/tests/test_models.py +1 -1
- {ecallistolib-0.2.2 → ecallistolib-0.2.3.1}/tests/test_plotting.py +150 -6
- {ecallistolib-0.2.2 → ecallistolib-0.2.3.1}/tests/test_processing.py +1 -1
- {ecallistolib-0.2.2 → ecallistolib-0.2.3.1}/tests/test_smoke.py +1 -1
- ecallistolib-0.2.2/src/ecallistolib/plotting.py +0 -406
- {ecallistolib-0.2.2 → ecallistolib-0.2.3.1}/LICENSE +0 -0
- {ecallistolib-0.2.2 → ecallistolib-0.2.3.1}/setup.cfg +0 -0
- {ecallistolib-0.2.2 → ecallistolib-0.2.3.1}/src/ecallistolib.egg-info/SOURCES.txt +0 -0
- {ecallistolib-0.2.2 → ecallistolib-0.2.3.1}/src/ecallistolib.egg-info/dependency_links.txt +0 -0
- {ecallistolib-0.2.2 → ecallistolib-0.2.3.1}/src/ecallistolib.egg-info/requires.txt +0 -0
- {ecallistolib-0.2.2 → ecallistolib-0.2.3.1}/src/ecallistolib.egg-info/top_level.txt +0 -0
|
@@ -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
|
|
|
@@ -97,11 +97,14 @@ import ecallistolib as ecl
|
|
|
97
97
|
# Read a FITS file
|
|
98
98
|
spectrum = ecl.read_fits("ALASKA_20230101_120000_01.fit.gz")
|
|
99
99
|
|
|
100
|
-
#
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
100
|
+
# Plot with different processing modes
|
|
101
|
+
fig, ax, im = ecl.plot_dynamic_spectrum(
|
|
102
|
+
spectrum,
|
|
103
|
+
process="noise_reduced",
|
|
104
|
+
clip_low=-5,
|
|
105
|
+
clip_high=20,
|
|
106
|
+
title="Solar Radio Burst"
|
|
107
|
+
)
|
|
105
108
|
```
|
|
106
109
|
|
|
107
110
|
---
|
|
@@ -180,14 +183,11 @@ import ecallistolib as ecl
|
|
|
180
183
|
|
|
181
184
|
spectrum = ecl.read_fits("my_spectrum.fit.gz")
|
|
182
185
|
|
|
183
|
-
# Apply noise reduction with
|
|
184
|
-
cleaned = ecl.noise_reduce_mean_clip(spectrum)
|
|
185
|
-
|
|
186
|
-
# Or customize the parameters
|
|
186
|
+
# Apply noise reduction with required clipping values
|
|
187
187
|
cleaned = ecl.noise_reduce_mean_clip(
|
|
188
188
|
spectrum,
|
|
189
|
-
clip_low=-5.0, # Lower clipping threshold
|
|
190
|
-
clip_high=20.0, # Upper clipping threshold
|
|
189
|
+
clip_low=-5.0, # Lower clipping threshold (required)
|
|
190
|
+
clip_high=20.0, # Upper clipping threshold (required)
|
|
191
191
|
scale=2500.0 / 255.0 / 25.4 # Scaling factor (None to disable)
|
|
192
192
|
)
|
|
193
193
|
|
|
@@ -313,28 +313,28 @@ if ecl.can_combine_time(files):
|
|
|
313
313
|
|
|
314
314
|
### Plotting
|
|
315
315
|
|
|
316
|
-
Create dynamic spectrum visualizations with
|
|
316
|
+
Create dynamic spectrum visualizations with selectable processing modes:
|
|
317
317
|
|
|
318
318
|
```python
|
|
319
319
|
import ecallistolib as ecl
|
|
320
320
|
import matplotlib.pyplot as plt
|
|
321
321
|
|
|
322
322
|
spectrum = ecl.read_fits("my_spectrum.fit.gz")
|
|
323
|
-
cleaned = ecl.noise_reduce_mean_clip(spectrum)
|
|
324
323
|
|
|
325
|
-
#
|
|
326
|
-
fig, ax, im = ecl.plot_dynamic_spectrum(
|
|
324
|
+
# Plot raw spectrum
|
|
325
|
+
fig, ax, im = ecl.plot_dynamic_spectrum(spectrum, process="raw")
|
|
327
326
|
plt.show()
|
|
328
327
|
|
|
329
|
-
#
|
|
328
|
+
# Plot noise-reduced spectrum with required clipping values
|
|
330
329
|
fig, ax, im = ecl.plot_dynamic_spectrum(
|
|
331
|
-
|
|
330
|
+
spectrum,
|
|
331
|
+
process="noise_reduced", # Apply noise reduction
|
|
332
|
+
clip_low=-5, # Lower clipping bound (required)
|
|
333
|
+
clip_high=20, # Upper clipping bound (required)
|
|
332
334
|
title="Type III Solar Burst",
|
|
333
|
-
cmap="magma",
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
figsize=(12, 6), # Figure size in inches
|
|
337
|
-
interpolation="bilinear" # Any matplotlib imshow kwarg
|
|
335
|
+
cmap="magma",
|
|
336
|
+
figsize=(12, 6),
|
|
337
|
+
interpolation="bilinear"
|
|
338
338
|
)
|
|
339
339
|
plt.savefig("spectrum.png", dpi=150, bbox_inches="tight")
|
|
340
340
|
```
|
|
@@ -365,8 +365,8 @@ spectrum = ecl.read_fits("my_spectrum.fit.gz")
|
|
|
365
365
|
# Plot after background subtraction but before clipping
|
|
366
366
|
fig, ax, im = ecl.plot_background_subtracted(
|
|
367
367
|
spectrum,
|
|
368
|
-
|
|
369
|
-
|
|
368
|
+
clip_low=-10,
|
|
369
|
+
clip_high=30,
|
|
370
370
|
cmap="RdBu_r" # Diverging colormap for +/- values
|
|
371
371
|
)
|
|
372
372
|
```
|
|
@@ -387,6 +387,24 @@ ecl.plot_dynamic_spectrum(spectrum, time_format="seconds")
|
|
|
387
387
|
ecl.plot_dynamic_spectrum(spectrum, time_format="ut")
|
|
388
388
|
```
|
|
389
389
|
|
|
390
|
+
#### Intensity Units
|
|
391
|
+
|
|
392
|
+
Choose between raw digital values (Digits/ADU) or pseudo-calibrated dB:
|
|
393
|
+
|
|
394
|
+
```python
|
|
395
|
+
import ecallistolib as ecl
|
|
396
|
+
|
|
397
|
+
spectrum = ecl.read_fits("my_spectrum.fit.gz")
|
|
398
|
+
|
|
399
|
+
# Default: intensity in Digits (raw ADU values)
|
|
400
|
+
ecl.plot_dynamic_spectrum(spectrum, intensity_units="digits")
|
|
401
|
+
|
|
402
|
+
# Convert to dB using: dB = Digits * 0.384 (pseudo-calibration)
|
|
403
|
+
ecl.plot_dynamic_spectrum(spectrum, intensity_units="dB")
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
> **Note:** The dB conversion uses the formula: dB = Digits × 2500 / 256 / 25.4 ≈ Digits × 0.384
|
|
407
|
+
|
|
390
408
|
#### Time Axis Converter
|
|
391
409
|
|
|
392
410
|
Convert between elapsed seconds and UT time programmatically:
|
|
@@ -419,12 +437,65 @@ fig, axes = plt.subplots(1, 2, figsize=(14, 5))
|
|
|
419
437
|
spectrum1 = ecl.read_fits("file1.fit.gz")
|
|
420
438
|
spectrum2 = ecl.read_fits("file2.fit.gz")
|
|
421
439
|
|
|
422
|
-
ecl.
|
|
440
|
+
ecl.plot_dynamic_spectrum(spectrum1, process="raw", ax=axes[0], title="Raw")
|
|
423
441
|
ecl.plot_dynamic_spectrum(
|
|
424
|
-
|
|
442
|
+
spectrum2,
|
|
443
|
+
process="noise_reduced",
|
|
425
444
|
ax=axes[1],
|
|
426
445
|
title="Noise Reduced",
|
|
427
|
-
|
|
446
|
+
clip_low=-5, clip_high=20
|
|
447
|
+
)
|
|
448
|
+
|
|
449
|
+
plt.tight_layout()
|
|
450
|
+
plt.show()
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
#### Light Curve Plotting
|
|
454
|
+
|
|
455
|
+
Plot intensity vs time at a specific frequency:
|
|
456
|
+
|
|
457
|
+
```python
|
|
458
|
+
import ecallistolib as ecl
|
|
459
|
+
import matplotlib.pyplot as plt
|
|
460
|
+
|
|
461
|
+
spectrum = ecl.read_fits("my_spectrum.fit.gz")
|
|
462
|
+
|
|
463
|
+
# Plot raw light curve at 60 MHz
|
|
464
|
+
fig, ax, line = ecl.plot_light_curve(spectrum, frequency_mhz=60, process="raw")
|
|
465
|
+
plt.show()
|
|
466
|
+
|
|
467
|
+
# Plot background-subtracted light curve
|
|
468
|
+
fig, ax, line = ecl.plot_light_curve(
|
|
469
|
+
spectrum, frequency_mhz=60, process="background_subtracted"
|
|
470
|
+
)
|
|
471
|
+
plt.show()
|
|
472
|
+
|
|
473
|
+
# Plot noise-reduced light curve (must provide clip values)
|
|
474
|
+
fig, ax, line = ecl.plot_light_curve(
|
|
475
|
+
spectrum,
|
|
476
|
+
frequency_mhz=60,
|
|
477
|
+
process="noise_reduced",
|
|
478
|
+
clip_low=-5,
|
|
479
|
+
clip_high=20
|
|
480
|
+
)
|
|
481
|
+
plt.show()
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
Compare all three processing modes:
|
|
485
|
+
|
|
486
|
+
```python
|
|
487
|
+
import ecallistolib as ecl
|
|
488
|
+
import matplotlib.pyplot as plt
|
|
489
|
+
|
|
490
|
+
spectrum = ecl.read_fits("my_spectrum.fit.gz")
|
|
491
|
+
|
|
492
|
+
fig, axes = plt.subplots(3, 1, figsize=(12, 10))
|
|
493
|
+
|
|
494
|
+
ecl.plot_light_curve(spectrum, 60, process="raw", ax=axes[0], title="Raw")
|
|
495
|
+
ecl.plot_light_curve(spectrum, 60, process="background_subtracted", ax=axes[1], title="BG Sub")
|
|
496
|
+
ecl.plot_light_curve(
|
|
497
|
+
spectrum, 60, process="noise_reduced", ax=axes[2], title="Noise Reduced",
|
|
498
|
+
clip_low=-5, clip_high=20
|
|
428
499
|
)
|
|
429
500
|
|
|
430
501
|
plt.tight_layout()
|
|
@@ -632,36 +703,65 @@ Concatenate spectra horizontally (time concatenation).
|
|
|
632
703
|
|
|
633
704
|
### Plotting Functions
|
|
634
705
|
|
|
635
|
-
#### `plot_dynamic_spectrum(ds,
|
|
706
|
+
#### `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)`
|
|
636
707
|
|
|
637
|
-
Plot a dynamic spectrum with
|
|
708
|
+
Plot a dynamic spectrum with selectable processing mode.
|
|
638
709
|
|
|
639
710
|
| Parameter | Type | Default | Description |
|
|
640
711
|
|-----------|------|---------|-------------|
|
|
641
712
|
| `ds` | `DynamicSpectrum` | — | Spectrum to plot |
|
|
642
|
-
| `
|
|
713
|
+
| `process` | `str` | `"raw"` | Processing mode: `"raw"`, `"background_subtracted"`, or `"noise_reduced"` |
|
|
714
|
+
| `clip_low` | `float \| None` | `None` | Lower clipping bound (required for `"noise_reduced"`) |
|
|
715
|
+
| `clip_high` | `float \| None` | `None` | Upper clipping bound (required for `"noise_reduced"`) |
|
|
716
|
+
| `title` | `str \| None` | `None` | Plot title (auto-generated if `None`) |
|
|
643
717
|
| `cmap` | `str` | `"inferno"` | Matplotlib colormap |
|
|
644
718
|
| `figsize` | `tuple \| None` | `None` | Figure size as `(width, height)` in inches |
|
|
645
|
-
| `vmin` | `float \| None` | `None` | Colormap lower bound (clipping) |
|
|
646
|
-
| `vmax` | `float \| None` | `None` | Colormap upper bound (clipping) |
|
|
647
719
|
| `ax` | `Axes \| None` | `None` | Existing axes (creates new if `None`) |
|
|
648
720
|
| `show_colorbar` | `bool` | `True` | Whether to display colorbar |
|
|
649
721
|
| `time_format` | `str` | `"seconds"` | `"seconds"` or `"ut"` for time axis format |
|
|
722
|
+
| `intensity_units` | `str` | `"digits"` | `"digits"` (raw ADU) or `"dB"` (pseudo-calibrated) |
|
|
650
723
|
| `**imshow_kwargs` | — | — | Additional kwargs passed to `matplotlib.imshow()` |
|
|
651
724
|
|
|
652
725
|
**Returns:** Tuple of `(fig, ax, im)`.
|
|
653
726
|
|
|
727
|
+
**Raises:** `ValueError` if `process="noise_reduced"` without `clip_low` and `clip_high`.
|
|
728
|
+
|
|
729
|
+
---
|
|
730
|
+
|
|
731
|
+
#### `plot_raw_spectrum(ds, clip_low=None, clip_high=None, title=None, cmap="viridis", ...)`
|
|
732
|
+
|
|
733
|
+
Convenience function that calls `plot_dynamic_spectrum` with `process="raw"`.
|
|
734
|
+
|
|
654
735
|
---
|
|
655
736
|
|
|
656
|
-
#### `
|
|
737
|
+
#### `plot_background_subtracted(ds, clip_low=None, clip_high=None, title=None, cmap="jet", ...)`
|
|
657
738
|
|
|
658
|
-
|
|
739
|
+
Convenience function that calls `plot_dynamic_spectrum` with `process="background_subtracted"`.
|
|
659
740
|
|
|
660
741
|
---
|
|
661
742
|
|
|
662
|
-
#### `
|
|
743
|
+
#### `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)`
|
|
744
|
+
|
|
745
|
+
Plot a light curve (intensity vs time) at a specific frequency.
|
|
746
|
+
|
|
747
|
+
| Parameter | Type | Default | Description |
|
|
748
|
+
|-----------|------|---------|-------------|
|
|
749
|
+
| `ds` | `DynamicSpectrum` | — | Spectrum to extract light curve from |
|
|
750
|
+
| `frequency_mhz` | `float` | — | Target frequency in MHz |
|
|
751
|
+
| `process` | `str` | `"raw"` | Processing mode: `"raw"`, `"background_subtracted"`, or `"noise_reduced"` |
|
|
752
|
+
| `title` | `str \| None` | `None` | Plot title (auto-generated if `None`) |
|
|
753
|
+
| `figsize` | `tuple \| None` | `None` | Figure size as `(width, height)` in inches |
|
|
754
|
+
| `ax` | `Axes \| None` | `None` | Existing axes (creates new if `None`) |
|
|
755
|
+
| `time_format` | `str` | `"seconds"` | `"seconds"` or `"ut"` for time axis format |
|
|
756
|
+
| `clip_low` | `float \| None` | `None` | Lower clip threshold (required for `"noise_reduced"`) |
|
|
757
|
+
| `clip_high` | `float \| None` | `None` | Upper clip threshold (required for `"noise_reduced"`) |
|
|
758
|
+
| `**plot_kwargs` | — | — | Additional kwargs passed to `matplotlib.plot()` |
|
|
759
|
+
|
|
760
|
+
**Returns:** Tuple of `(fig, ax, line)`.
|
|
663
761
|
|
|
664
|
-
|
|
762
|
+
**Raises:**
|
|
763
|
+
- `FrequencyOutOfRangeError` if frequency is outside spectrum's range.
|
|
764
|
+
- `ValueError` if `process="noise_reduced"` without `clip_low` and `clip_high`.
|
|
665
765
|
|
|
666
766
|
---
|
|
667
767
|
|
|
@@ -695,6 +795,7 @@ The library provides a hierarchy of custom exceptions for robust error handling:
|
|
|
695
795
|
| `DownloadError` | Raised when downloading files from the archive fails |
|
|
696
796
|
| `CombineError` | Raised when spectra cannot be combined |
|
|
697
797
|
| `CropError` | Raised when cropping parameters are invalid |
|
|
798
|
+
| `FrequencyOutOfRangeError` | Raised when the requested frequency is outside the spectrum's range |
|
|
698
799
|
|
|
699
800
|
#### Error Handling Example
|
|
700
801
|
|
|
@@ -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
|
|
|
@@ -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
|
|
|
@@ -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
|