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.
Files changed (29) hide show
  1. {ecallistolib-0.2.2/src/ecallistolib.egg-info → ecallistolib-0.2.3.1}/PKG-INFO +138 -37
  2. {ecallistolib-0.2.2 → ecallistolib-0.2.3.1}/README.md +137 -36
  3. {ecallistolib-0.2.2 → ecallistolib-0.2.3.1}/pyproject.toml +1 -1
  4. {ecallistolib-0.2.2 → ecallistolib-0.2.3.1}/src/ecallistolib/__init__.py +6 -1
  5. {ecallistolib-0.2.2 → ecallistolib-0.2.3.1}/src/ecallistolib/combine.py +3 -3
  6. {ecallistolib-0.2.2 → ecallistolib-0.2.3.1}/src/ecallistolib/crop.py +1 -1
  7. {ecallistolib-0.2.2 → ecallistolib-0.2.3.1}/src/ecallistolib/download.py +1 -1
  8. {ecallistolib-0.2.2 → ecallistolib-0.2.3.1}/src/ecallistolib/exceptions.py +6 -1
  9. {ecallistolib-0.2.2 → ecallistolib-0.2.3.1}/src/ecallistolib/io.py +1 -1
  10. {ecallistolib-0.2.2 → ecallistolib-0.2.3.1}/src/ecallistolib/models.py +1 -1
  11. ecallistolib-0.2.3.1/src/ecallistolib/plotting.py +618 -0
  12. {ecallistolib-0.2.2 → ecallistolib-0.2.3.1}/src/ecallistolib/processing.py +3 -3
  13. {ecallistolib-0.2.2 → ecallistolib-0.2.3.1/src/ecallistolib.egg-info}/PKG-INFO +138 -37
  14. {ecallistolib-0.2.2 → ecallistolib-0.2.3.1}/tests/test_crop.py +1 -1
  15. {ecallistolib-0.2.2 → ecallistolib-0.2.3.1}/tests/test_exceptions.py +6 -1
  16. {ecallistolib-0.2.2 → ecallistolib-0.2.3.1}/tests/test_imports.py +1 -1
  17. {ecallistolib-0.2.2 → ecallistolib-0.2.3.1}/tests/test_integration.py +3 -3
  18. {ecallistolib-0.2.2 → ecallistolib-0.2.3.1}/tests/test_io.py +1 -1
  19. {ecallistolib-0.2.2 → ecallistolib-0.2.3.1}/tests/test_models.py +1 -1
  20. {ecallistolib-0.2.2 → ecallistolib-0.2.3.1}/tests/test_plotting.py +150 -6
  21. {ecallistolib-0.2.2 → ecallistolib-0.2.3.1}/tests/test_processing.py +1 -1
  22. {ecallistolib-0.2.2 → ecallistolib-0.2.3.1}/tests/test_smoke.py +1 -1
  23. ecallistolib-0.2.2/src/ecallistolib/plotting.py +0 -406
  24. {ecallistolib-0.2.2 → ecallistolib-0.2.3.1}/LICENSE +0 -0
  25. {ecallistolib-0.2.2 → ecallistolib-0.2.3.1}/setup.cfg +0 -0
  26. {ecallistolib-0.2.2 → ecallistolib-0.2.3.1}/src/ecallistolib.egg-info/SOURCES.txt +0 -0
  27. {ecallistolib-0.2.2 → ecallistolib-0.2.3.1}/src/ecallistolib.egg-info/dependency_links.txt +0 -0
  28. {ecallistolib-0.2.2 → ecallistolib-0.2.3.1}/src/ecallistolib.egg-info/requires.txt +0 -0
  29. {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.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
- # Apply noise reduction
121
- cleaned = ecl.noise_reduce_mean_clip(spectrum)
122
-
123
- # Plot the result
124
- fig, ax, im = ecl.plot_dynamic_spectrum(cleaned, title="Solar Radio Burst")
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 default parameters
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 full customization:
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
- # Basic plot
346
- fig, ax, im = ecl.plot_dynamic_spectrum(cleaned, title="Solar Radio Observation")
344
+ # Plot raw spectrum
345
+ fig, ax, im = ecl.plot_dynamic_spectrum(spectrum, process="raw")
347
346
  plt.show()
348
347
 
349
- # Customized plot with clipping values, colormap, and figure size
348
+ # Plot noise-reduced spectrum with required clipping values
350
349
  fig, ax, im = ecl.plot_dynamic_spectrum(
351
- cleaned,
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", # Matplotlib colormap
354
- vmin=-5, # Colormap lower bound
355
- vmax=20, # Colormap upper bound
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
- vmin=-10,
389
- vmax=30,
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.plot_raw_spectrum(spectrum1, ax=axes[0], title="Raw")
460
+ ecl.plot_dynamic_spectrum(spectrum1, process="raw", ax=axes[0], title="Raw")
443
461
  ecl.plot_dynamic_spectrum(
444
- ecl.noise_reduce_mean_clip(spectrum2),
462
+ spectrum2,
463
+ process="noise_reduced",
445
464
  ax=axes[1],
446
465
  title="Noise Reduced",
447
- vmin=-5, vmax=20
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, title="...", cmap="inferno", figsize=None, vmin=None, vmax=None, ax=None, show_colorbar=True, time_format="seconds", **imshow_kwargs)`
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 full customization.
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
- | `title` | `str` | `"Dynamic Spectrum"` | Plot title |
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
- #### `plot_raw_spectrum(ds, title="Raw Spectrum", cmap="viridis", ...)`
757
+ #### `plot_background_subtracted(ds, clip_low=None, clip_high=None, title=None, cmap="jet", ...)`
677
758
 
678
- Plot raw spectrum data without any processing. Accepts the same parameters as `plot_dynamic_spectrum`.
759
+ Convenience function that calls `plot_dynamic_spectrum` with `process="background_subtracted"`.
679
760
 
680
761
  ---
681
762
 
682
- #### `plot_background_subtracted(ds, title="Background Subtracted", cmap="RdBu_r", ...)`
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
- Plot spectrum after background subtraction (before clipping). Automatically applies `background_subtract()` and plots the result. Accepts the same parameters as `plot_dynamic_spectrum`.
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
- # Apply noise reduction
101
- cleaned = ecl.noise_reduce_mean_clip(spectrum)
102
-
103
- # Plot the result
104
- fig, ax, im = ecl.plot_dynamic_spectrum(cleaned, title="Solar Radio Burst")
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 default parameters
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 full customization:
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
- # Basic plot
326
- fig, ax, im = ecl.plot_dynamic_spectrum(cleaned, title="Solar Radio Observation")
324
+ # Plot raw spectrum
325
+ fig, ax, im = ecl.plot_dynamic_spectrum(spectrum, process="raw")
327
326
  plt.show()
328
327
 
329
- # Customized plot with clipping values, colormap, and figure size
328
+ # Plot noise-reduced spectrum with required clipping values
330
329
  fig, ax, im = ecl.plot_dynamic_spectrum(
331
- cleaned,
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", # Matplotlib colormap
334
- vmin=-5, # Colormap lower bound
335
- vmax=20, # Colormap upper bound
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
- vmin=-10,
369
- vmax=30,
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.plot_raw_spectrum(spectrum1, ax=axes[0], title="Raw")
440
+ ecl.plot_dynamic_spectrum(spectrum1, process="raw", ax=axes[0], title="Raw")
423
441
  ecl.plot_dynamic_spectrum(
424
- ecl.noise_reduce_mean_clip(spectrum2),
442
+ spectrum2,
443
+ process="noise_reduced",
425
444
  ax=axes[1],
426
445
  title="Noise Reduced",
427
- vmin=-5, vmax=20
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, title="...", cmap="inferno", figsize=None, vmin=None, vmax=None, ax=None, show_colorbar=True, time_format="seconds", **imshow_kwargs)`
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 full customization.
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
- | `title` | `str` | `"Dynamic Spectrum"` | Plot title |
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
- #### `plot_raw_spectrum(ds, title="Raw Spectrum", cmap="viridis", ...)`
737
+ #### `plot_background_subtracted(ds, clip_low=None, clip_high=None, title=None, cmap="jet", ...)`
657
738
 
658
- Plot raw spectrum data without any processing. Accepts the same parameters as `plot_dynamic_spectrum`.
739
+ Convenience function that calls `plot_dynamic_spectrum` with `process="background_subtracted"`.
659
740
 
660
741
  ---
661
742
 
662
- #### `plot_background_subtracted(ds, title="Background Subtracted", cmap="RdBu_r", ...)`
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
- Plot spectrum after background subtraction (before clipping). Automatically applies `background_subtract()` and plots the result. Accepts the same parameters as `plot_dynamic_spectrum`.
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
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "ecallistolib"
7
- version = "0.2.2"
7
+ version = "0.2.3.1"
8
8
  description = "Tools to download, read, process, and plot e-CALLISTO FITS dynamic spectra."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -1,7 +1,7 @@
1
1
 
2
2
  """
3
3
  e-callistolib: Tools for e-CALLISTO FITS dynamic spectra.
4
- Version 0.2.1
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.1
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=None, meta=meta)
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=None, meta=meta)
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.1
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
  """
@@ -1,6 +1,6 @@
1
1
  """
2
2
  e-callistolib: Tools for e-CALLISTO FITS dynamic spectra.
3
- Version 0.2.1
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
  """
@@ -1,6 +1,6 @@
1
1
  """
2
2
  e-callistolib: Tools for e-CALLISTO FITS dynamic spectra.
3
- Version 0.2.1
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
@@ -1,6 +1,6 @@
1
1
  """
2
2
  e-callistolib: Tools for e-CALLISTO FITS dynamic spectra.
3
- Version 0.2.1
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
  """
@@ -1,6 +1,6 @@
1
1
  """
2
2
  e-callistolib: Tools for e-CALLISTO FITS dynamic spectra.
3
- Version 0.2.1
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
  """