lime-stable 2.2.dev6__tar.gz → 2.4.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.
- {lime_stable-2.2.dev6/src/lime_stable.egg-info → lime_stable-2.4.1}/PKG-INFO +19 -19
- {lime_stable-2.2.dev6 → lime_stable-2.4.1}/pyproject.toml +23 -19
- {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/archives/read_fits.py +86 -9
- {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/archives/tables.py +1 -1
- {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/changelog.txt +30 -0
- {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/fitting/lines.py +47 -30
- {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/fitting/redshift.py +0 -1
- {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/io.py +2 -2
- {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/lime.toml +16 -1
- {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/observations.py +145 -3
- {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/plotting/bokeh_plots.py +17 -1
- {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/plotting/plots.py +131 -30
- {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/plotting/plots_interactive.py +11 -10
- {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/resources/generator_db.py +7 -4
- {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/resources/lines_database_v2.0.6.txt +4 -1
- {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/retrieve/line_bands.py +2 -52
- {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/tools.py +4 -5
- {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/transitions.py +105 -23
- {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/workflow.py +127 -88
- {lime_stable-2.2.dev6 → lime_stable-2.4.1/src/lime_stable.egg-info}/PKG-INFO +19 -19
- {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime_stable.egg-info/SOURCES.txt +1 -1
- lime_stable-2.4.1/src/lime_stable.egg-info/requires.txt +28 -0
- {lime_stable-2.2.dev6 → lime_stable-2.4.1}/tests/test_io.py +1 -1
- {lime_stable-2.2.dev6 → lime_stable-2.4.1}/tests/test_line.py +39 -6
- lime_stable-2.4.1/tests/test_model.py +268 -0
- lime_stable-2.4.1/tests/test_plots.py +318 -0
- {lime_stable-2.2.dev6 → lime_stable-2.4.1}/tests/test_sample.py +1 -1
- {lime_stable-2.2.dev6 → lime_stable-2.4.1}/tests/test_spectrum.py +241 -73
- lime_stable-2.4.1/tests/test_tables.py +294 -0
- {lime_stable-2.2.dev6 → lime_stable-2.4.1}/tests/test_tools.py +56 -18
- lime_stable-2.2.dev6/src/lime/resources/lines_database_v2.0.0.txt +0 -153
- lime_stable-2.2.dev6/src/lime_stable.egg-info/requires.txt +0 -30
- lime_stable-2.2.dev6/tests/test_model.py +0 -110
- lime_stable-2.2.dev6/tests/test_plots.py +0 -46
- {lime_stable-2.2.dev6 → lime_stable-2.4.1}/LICENSE.rst +0 -0
- {lime_stable-2.2.dev6 → lime_stable-2.4.1}/MANIFEST.in +0 -0
- {lime_stable-2.2.dev6 → lime_stable-2.4.1}/README.md +0 -0
- {lime_stable-2.2.dev6 → lime_stable-2.4.1}/setup.cfg +0 -0
- {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/__init__.py +0 -0
- {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/archives/__init__.py +0 -0
- {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/fitting/__init__.py +0 -0
- {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/inference/detection.py +0 -0
- {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/inference/intensity_threshold.py +0 -0
- {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/plotting/__init__.py +0 -0
- {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/plotting/format.py +0 -0
- {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/plotting/theme_lime.toml +0 -0
- {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/plotting/utils.py +0 -0
- {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/resources/__init__.py +0 -0
- {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/resources/generator_logo.py +0 -0
- {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/resources/types_params.txt +0 -0
- {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/retrieve/__init__.py +0 -0
- {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/rsrc_manager.py +0 -0
- {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime_stable.egg-info/dependency_links.txt +0 -0
- {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime_stable.egg-info/top_level.txt +0 -0
- {lime_stable-2.2.dev6 → lime_stable-2.4.1}/tests/test_astro.py +0 -0
- {lime_stable-2.2.dev6 → lime_stable-2.4.1}/tests/test_cube.py +0 -0
- {lime_stable-2.2.dev6 → lime_stable-2.4.1}/tests/test_read_fits.py +0 -0
- {lime_stable-2.2.dev6 → lime_stable-2.4.1}/tests/test_redshift.py +0 -0
- {lime_stable-2.2.dev6 → lime_stable-2.4.1}/tests/test_resources.py +0 -0
|
@@ -1,39 +1,39 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: lime-stable
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.4.1
|
|
4
4
|
Summary: Line measuring algorithm for astronomical spectra
|
|
5
5
|
Author-email: Vital Fernández <vgf@stsci.edu>
|
|
6
6
|
License: GPL-3.0-or-later
|
|
7
7
|
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
|
|
8
|
-
Classifier: Programming Language :: Python :: 3.
|
|
9
|
-
Requires-Python: >=3.
|
|
8
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
9
|
+
Requires-Python: >=3.12
|
|
10
10
|
Description-Content-Type: text/markdown
|
|
11
11
|
License-File: LICENSE.rst
|
|
12
|
-
Requires-Dist: astropy~=
|
|
13
|
-
Requires-Dist: lmfit~=1.3
|
|
12
|
+
Requires-Dist: astropy~=8.0.0
|
|
13
|
+
Requires-Dist: lmfit~=1.3.4
|
|
14
14
|
Requires-Dist: matplotlib~=3.10
|
|
15
|
-
Requires-Dist: numpy~=2.
|
|
16
|
-
Requires-Dist: pandas~=
|
|
17
|
-
Requires-Dist: scipy~=1.
|
|
18
|
-
Requires-Dist: tomli>=2.0.0; python_version < "3.11"
|
|
15
|
+
Requires-Dist: numpy~=2.5
|
|
16
|
+
Requires-Dist: pandas~=3.0.3
|
|
17
|
+
Requires-Dist: scipy~=1.18
|
|
19
18
|
Provides-Extra: full
|
|
20
19
|
Requires-Dist: asdf~=4.1; extra == "full"
|
|
21
|
-
Requires-Dist: aspect-stable~=0.
|
|
22
|
-
Requires-Dist: bokeh~=3.
|
|
20
|
+
Requires-Dist: aspect-stable~=0.8; extra == "full"
|
|
21
|
+
Requires-Dist: bokeh~=3.9.1; extra == "full"
|
|
23
22
|
Requires-Dist: mplcursors~=0.6; extra == "full"
|
|
24
23
|
Requires-Dist: openpyxl~=3.1; extra == "full"
|
|
25
24
|
Requires-Dist: PyLaTeX~=1.4; extra == "full"
|
|
26
25
|
Requires-Dist: toml~=0.10; extra == "full"
|
|
27
26
|
Provides-Extra: docs
|
|
28
|
-
Requires-Dist: sphinx
|
|
29
|
-
Requires-Dist:
|
|
30
|
-
Requires-Dist:
|
|
31
|
-
Requires-Dist:
|
|
32
|
-
Requires-Dist:
|
|
27
|
+
Requires-Dist: sphinx~=9.1.0; extra == "docs"
|
|
28
|
+
Requires-Dist: sphinx-rtd-theme~=3.1; extra == "docs"
|
|
29
|
+
Requires-Dist: sphinx_togglebutton~=0.4.5; extra == "docs"
|
|
30
|
+
Requires-Dist: sphinx_book_theme~=1.2; extra == "docs"
|
|
31
|
+
Requires-Dist: ipympl~=0.10; extra == "docs"
|
|
32
|
+
Requires-Dist: myst-nb~=1.4; extra == "docs"
|
|
33
33
|
Provides-Extra: tests
|
|
34
|
-
Requires-Dist: pytest~=
|
|
35
|
-
Requires-Dist: pytest-cov~=7.0; extra == "tests"
|
|
36
|
-
Requires-Dist: pytest-mpl~=0.
|
|
34
|
+
Requires-Dist: pytest~=9.1.1; extra == "tests"
|
|
35
|
+
Requires-Dist: pytest-cov~=7.1.0; extra == "tests"
|
|
36
|
+
Requires-Dist: pytest-mpl~=0.19.0; extra == "tests"
|
|
37
37
|
Dynamic: license-file
|
|
38
38
|
|
|
39
39
|
[]()
|
|
@@ -4,42 +4,42 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "lime-stable"
|
|
7
|
-
version = "2.
|
|
7
|
+
version = "2.4.1"
|
|
8
8
|
readme = { file = "README.md", content-type = "text/markdown" }
|
|
9
|
-
requires-python = ">=3.
|
|
9
|
+
requires-python = ">=3.12"
|
|
10
10
|
license = {text = "GPL-3.0-or-later"}
|
|
11
11
|
classifiers = ["License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
|
|
12
|
-
"Programming Language :: Python :: 3.
|
|
12
|
+
"Programming Language :: Python :: 3.12"]
|
|
13
13
|
|
|
14
14
|
authors = [{name = "Vital Fernández", email = "vgf@stsci.edu"}]
|
|
15
15
|
description = "Line measuring algorithm for astronomical spectra"
|
|
16
16
|
|
|
17
|
-
dependencies = ["astropy~=
|
|
18
|
-
"lmfit~=1.3",
|
|
17
|
+
dependencies = ["astropy~=8.0.0",
|
|
18
|
+
"lmfit~=1.3.4",
|
|
19
19
|
"matplotlib~=3.10",
|
|
20
|
-
"numpy~=2.
|
|
21
|
-
"pandas~=
|
|
22
|
-
"scipy~=1.
|
|
23
|
-
"tomli >= 2.0.0 ; python_version < '3.11'"]
|
|
20
|
+
"numpy~=2.5",
|
|
21
|
+
"pandas~=3.0.3",
|
|
22
|
+
"scipy~=1.18"]
|
|
24
23
|
|
|
25
24
|
[project.optional-dependencies]
|
|
26
25
|
full = ["asdf~=4.1",
|
|
27
|
-
"aspect-stable~=0.
|
|
28
|
-
"bokeh~=3.
|
|
26
|
+
"aspect-stable~=0.8",
|
|
27
|
+
"bokeh~=3.9.1",
|
|
29
28
|
"mplcursors~=0.6",
|
|
30
29
|
"openpyxl~=3.1",
|
|
31
30
|
"PyLaTeX~=1.4",
|
|
32
31
|
"toml~=0.10",]
|
|
33
32
|
|
|
34
|
-
docs = ["sphinx
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"
|
|
33
|
+
docs = ["sphinx~=9.1.0",
|
|
34
|
+
"sphinx-rtd-theme~=3.1",
|
|
35
|
+
"sphinx_togglebutton~=0.4.5",
|
|
36
|
+
"sphinx_book_theme~=1.2",
|
|
37
|
+
"ipympl~=0.10",
|
|
38
|
+
"myst-nb~=1.4"]
|
|
39
39
|
|
|
40
|
-
tests = ["pytest~=
|
|
41
|
-
"pytest-cov~=7.0",
|
|
42
|
-
"pytest-mpl~=0.
|
|
40
|
+
tests = ["pytest~=9.1.1",
|
|
41
|
+
"pytest-cov~=7.1.0",
|
|
42
|
+
"pytest-mpl~=0.19.0"]
|
|
43
43
|
|
|
44
44
|
[tool.pytest.ini_options]
|
|
45
45
|
pythonpath = ["src"]
|
|
@@ -48,3 +48,7 @@ mpl-results-path = 'tests/outputs'
|
|
|
48
48
|
mpl-results-always = false
|
|
49
49
|
markers = ["mpl: matplotlib image comparison tests"]
|
|
50
50
|
addopts = "-p no:asdf_schema_tester"
|
|
51
|
+
|
|
52
|
+
[tool.coverage.run]
|
|
53
|
+
omit = ["src/lime/resources/generator_db.py",
|
|
54
|
+
"src/lime/resources/generator_logo.py"]
|
|
@@ -610,11 +610,89 @@ class OpenFits:
|
|
|
610
610
|
pixel_mask = np.isnan(flux_array) | np.isnan(err_array)
|
|
611
611
|
|
|
612
612
|
# Spectrum properties
|
|
613
|
-
params_dict = SPECTRUM_FITS_PARAMS['nirspec']
|
|
614
|
-
params_dict['pixel_mask'] = pixel_mask
|
|
613
|
+
params_dict = {**SPECTRUM_FITS_PARAMS['nirspec'], 'pixel_mask': pixel_mask}
|
|
615
614
|
|
|
616
615
|
return wave_array, flux_array, err_array, header_list, params_dict
|
|
617
616
|
|
|
617
|
+
|
|
618
|
+
@staticmethod
|
|
619
|
+
def lzlcs_miri_merged(fits_address, data_ext_list=(1), hdr_ext_list=(1), **kwargs):
|
|
620
|
+
|
|
621
|
+
"""
|
|
622
|
+
|
|
623
|
+
This method returns the spectrum array data and headers from a MUSE observation.
|
|
624
|
+
|
|
625
|
+
The function returns numpy arrays with the wavelength, flux and uncertainty flux (if available this is the
|
|
626
|
+
standard deviation available), a list with the requested headers and a dictionary with the parameters to
|
|
627
|
+
construct a LiMe Cube. These parameters include the observation wavelength/flux units, normalization and wcs
|
|
628
|
+
from the input fits file.
|
|
629
|
+
|
|
630
|
+
:param fits_address: File location address for the observation .fits file.
|
|
631
|
+
:type fits_address: str, Path
|
|
632
|
+
|
|
633
|
+
:param data_ext_list: Data extension number or name to extract from the .fits file.
|
|
634
|
+
:type fits_address: int, str or list of either, optional
|
|
635
|
+
|
|
636
|
+
:param hdr_ext_list: header extension number or name to extract from the .fits file.
|
|
637
|
+
:type hdr_ext_list: int, str or list of either, optional
|
|
638
|
+
|
|
639
|
+
:return: wavelength array, flux array, uncertainty array, header list, observation parameter dict
|
|
640
|
+
|
|
641
|
+
"""
|
|
642
|
+
|
|
643
|
+
# Get data table and header dict lists
|
|
644
|
+
data_list, header_list = load_fits(fits_address, data_ext_list, hdr_ext_list, url_check=False)
|
|
645
|
+
|
|
646
|
+
# Re-construct spectrum arrays
|
|
647
|
+
wave_array = data_list[0]['WAVE']
|
|
648
|
+
flux_array = data_list[0]['FLUX']
|
|
649
|
+
err_array = data_list[0]['FLUX_ERROR']
|
|
650
|
+
|
|
651
|
+
# Fits properties
|
|
652
|
+
fits_params = {**SPECTRUM_FITS_PARAMS['lzlcs_miri_merged'], 'pixel_mask': None}
|
|
653
|
+
|
|
654
|
+
return wave_array, flux_array, err_array, header_list, fits_params
|
|
655
|
+
|
|
656
|
+
@staticmethod
|
|
657
|
+
def lzlcs_miri_x1d(fits_address, data_ext_list=(1), hdr_ext_list=(1), **kwargs):
|
|
658
|
+
|
|
659
|
+
"""
|
|
660
|
+
|
|
661
|
+
This method returns the spectrum array data and headers from a MUSE observation.
|
|
662
|
+
|
|
663
|
+
The function returns numpy arrays with the wavelength, flux and uncertainty flux (if available this is the
|
|
664
|
+
standard deviation available), a list with the requested headers and a dictionary with the parameters to
|
|
665
|
+
construct a LiMe Cube. These parameters include the observation wavelength/flux units, normalization and wcs
|
|
666
|
+
from the input fits file.
|
|
667
|
+
|
|
668
|
+
:param fits_address: File location address for the observation .fits file.
|
|
669
|
+
:type fits_address: str, Path
|
|
670
|
+
|
|
671
|
+
:param data_ext_list: Data extension number or name to extract from the .fits file.
|
|
672
|
+
:type fits_address: int, str or list of either, optional
|
|
673
|
+
|
|
674
|
+
:param hdr_ext_list: header extension number or name to extract from the .fits file.
|
|
675
|
+
:type hdr_ext_list: int, str or list of either, optional
|
|
676
|
+
|
|
677
|
+
:return: wavelength array, flux array, uncertainty array, header list, observation parameter dict
|
|
678
|
+
|
|
679
|
+
"""
|
|
680
|
+
|
|
681
|
+
# Get data table and header dict lists
|
|
682
|
+
data_list, header_list = load_fits(fits_address, data_ext_list, hdr_ext_list, url_check=False)
|
|
683
|
+
|
|
684
|
+
# Re-construct spectrum arrays
|
|
685
|
+
wave_array = data_list[0]['WAVELENGTH']
|
|
686
|
+
flux_array = data_list[0]['FLUX']
|
|
687
|
+
err_array = data_list[0]['FLUX_ERROR']
|
|
688
|
+
|
|
689
|
+
# Fits properties
|
|
690
|
+
fits_params = {**SPECTRUM_FITS_PARAMS['lzlcs_miri_x1d'], 'pixel_mask': None}
|
|
691
|
+
|
|
692
|
+
return wave_array, flux_array, err_array, header_list, fits_params
|
|
693
|
+
|
|
694
|
+
|
|
695
|
+
|
|
618
696
|
@staticmethod
|
|
619
697
|
def nirspec_grizli(fits_address, data_ext_list=1, hdr_ext_list=(0, 1), **kwargs):
|
|
620
698
|
|
|
@@ -649,8 +727,7 @@ class OpenFits:
|
|
|
649
727
|
pixel_mask = np.isnan(flux_array) | np.isnan(err_array)
|
|
650
728
|
|
|
651
729
|
# Spectrum properties
|
|
652
|
-
params_dict = SPECTRUM_FITS_PARAMS['nirspec_grizli']
|
|
653
|
-
params_dict['pixel_mask'] = pixel_mask
|
|
730
|
+
params_dict = {**SPECTRUM_FITS_PARAMS['nirspec_grizli'], 'pixel_mask': pixel_mask}
|
|
654
731
|
|
|
655
732
|
return wave_array, flux_array, err_array, header_list, params_dict
|
|
656
733
|
|
|
@@ -695,7 +772,7 @@ class OpenFits:
|
|
|
695
772
|
flux_array, err_array = data_list[0], None
|
|
696
773
|
|
|
697
774
|
# Spectrum properties
|
|
698
|
-
params_dict = SPECTRUM_FITS_PARAMS['isis']
|
|
775
|
+
params_dict = {**SPECTRUM_FITS_PARAMS['isis']}
|
|
699
776
|
|
|
700
777
|
return wave_array, flux_array, err_array, header_list, params_dict
|
|
701
778
|
|
|
@@ -776,7 +853,7 @@ class OpenFits:
|
|
|
776
853
|
flux_array, err_array = data_list[0], None
|
|
777
854
|
|
|
778
855
|
# Spectrum properties
|
|
779
|
-
params_dict = SPECTRUM_FITS_PARAMS['osiris']
|
|
856
|
+
params_dict = {**SPECTRUM_FITS_PARAMS['osiris']}
|
|
780
857
|
|
|
781
858
|
return wave_array, flux_array, err_array, header_list, params_dict
|
|
782
859
|
|
|
@@ -843,7 +920,7 @@ class OpenFits:
|
|
|
843
920
|
# # print(key_arr, np.any(np.isnan(cont_arr)))
|
|
844
921
|
|
|
845
922
|
# Spectrum properties
|
|
846
|
-
params_dict = SPECTRUM_FITS_PARAMS['cos']
|
|
923
|
+
params_dict = {**SPECTRUM_FITS_PARAMS['cos']}
|
|
847
924
|
|
|
848
925
|
return wave_arr, flux_arr, err_arr, header_list, params_dict
|
|
849
926
|
|
|
@@ -894,8 +971,7 @@ class OpenFits:
|
|
|
894
971
|
err_array = np.sqrt(1 / ivar_array)
|
|
895
972
|
|
|
896
973
|
# Spectrum properties
|
|
897
|
-
params_dict = SPECTRUM_FITS_PARAMS['sdss']
|
|
898
|
-
params_dict['redshift'] = redshift
|
|
974
|
+
params_dict = {**SPECTRUM_FITS_PARAMS['sdss'], 'redshift': redshift}
|
|
899
975
|
|
|
900
976
|
return wave_array, flux_array, err_array, header_list, params_dict
|
|
901
977
|
|
|
@@ -1124,6 +1200,7 @@ class OpenFits:
|
|
|
1124
1200
|
|
|
1125
1201
|
return wave_array, flux_cube, err_cube, header_list, fits_params
|
|
1126
1202
|
|
|
1203
|
+
|
|
1127
1204
|
@staticmethod
|
|
1128
1205
|
def desi(target_id, root_url='https://data.desi.lbl.gov/public/edr/spectro/redux', **kwargs):
|
|
1129
1206
|
|
|
@@ -122,4 +122,34 @@ LiMe minor update - 2.0.4 - 12/05/2025
|
|
|
122
122
|
- Further development for the functions involving redshift a line fitting using aspect
|
|
123
123
|
- The spatial masking functions should not require the 'PARAM', 'PARAMIDX', 'PARAMVAL' and 'NUMSPAXE' in the .fits headers to plot the mask overlays
|
|
124
124
|
|
|
125
|
+
LiMe medium update - 2.4.0 - 26/06/2026
|
|
126
|
+
- Added new ultraviolet and infrared lines to the database `lines_database_v2.0.6.txt`
|
|
127
|
+
- Major updates to `observations.py`: expanded spectrum observation handling
|
|
128
|
+
- Major updates to `workflow.py`: significant refactoring of the fitting workflow
|
|
129
|
+
- The Transition and Line classes are been update to have an `origin`, `redshift` and `atomic_data` as attributes. This will be documented in a future major update
|
|
130
|
+
- Changes to the matplotlib and bokeh plot functions to use common theme structure
|
|
131
|
+
- The `Spectrum.retrieve.lines_frame` has been update to include an origin as an input. This will be documented in a future major update
|
|
132
|
+
- The `Spectrum.retrieve.lines_frame` documentation added to the API.
|
|
133
|
+
- Added SDSS complete spectrum example script (`3_complete_spectrum_SDSS.py`)
|
|
134
|
+
- Added line groups prediction example script (`3_line_groups_prediction.py`)
|
|
135
|
+
- Updated `fitting/redshift.py` function to correct a bug issue with non-line measurements
|
|
136
|
+
- Updated `archives/read_fits.py`: FITS reading improvements
|
|
137
|
+
- Updated `pyproject.toml` updated dependencies to include ASPECT features
|
|
138
|
+
- The computation of the line continua now takes into account the covariance of the fitting. The nominal values remain constant but the uncertainty predicted is smaller
|
|
139
|
+
- Expanded the tests for the latex/pdf table making functions from the `test_tables.py` script
|
|
140
|
+
- Expanded the tests to compare the line measurements with synthetic lines for more profile parameters (including the line continuum levels)
|
|
141
|
+
- Improvement of the descriptions in the measurements documentation page and correction of wrong terms
|
|
142
|
+
- Updated plot baselines across multiple tests
|
|
143
|
+
- Added paper citation on the documentation
|
|
144
|
+
- Added more integration with aspect functions (next medium release will focus on documenting these updgrades)
|
|
145
|
+
- Adding releases on the github page to mark medium / major updates
|
|
146
|
+
- Bump minimum python to 3.12 version for uniform requirements with readthedocs compilation
|
|
147
|
+
|
|
148
|
+
LiMe small update - 2.4.1 - 08/07/2026
|
|
149
|
+
- Now all instrument fits loading functions copy the configuration dictionary to avoid possible corruptions.
|
|
150
|
+
- Added lines to lines database.
|
|
151
|
+
- The lines database version now follows the current lime version.
|
|
152
|
+
- Renamed internal function "continuum_calculation" to "_cont_level_profile" in order to avoid confusion with external "Spectrum.fit.continuum"
|
|
153
|
+
- Bump the dependencies to the current versions. At the current state, LiMe should be compatible with Pandas 3.0.0 but more changes will be necessary to take full advantage of the library upgrades"
|
|
154
|
+
|
|
125
155
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
|
|
3
|
+
import matplotlib.pyplot as plt
|
|
3
4
|
import numpy as np
|
|
4
5
|
from lmfit.models import Model
|
|
5
6
|
from lmfit import fit_report
|
|
@@ -91,6 +92,7 @@ def const_cont_model(cont_array, prefix='cont_', allow_scale=False):
|
|
|
91
92
|
# freeze at 1.0 -> truly constant
|
|
92
93
|
return m, params
|
|
93
94
|
|
|
95
|
+
|
|
94
96
|
def linear_model(x, m_cont, n_cont):
|
|
95
97
|
"""Linear line formulation"""
|
|
96
98
|
return m_cont * x + n_cont
|
|
@@ -252,9 +254,9 @@ def power_area(line, idx, n_steps):
|
|
|
252
254
|
def exp_area(line, idx, n_steps):
|
|
253
255
|
|
|
254
256
|
amp = np.random.normal(line.amp[idx], line.amp_err[idx], n_steps)
|
|
255
|
-
alpha = np.random.normal(line.alpha[idx], line.
|
|
257
|
+
alpha = np.random.normal(line.alpha[idx], line.alpha_err[idx], n_steps)
|
|
256
258
|
|
|
257
|
-
return 2
|
|
259
|
+
return 2 * amp / alpha
|
|
258
260
|
|
|
259
261
|
|
|
260
262
|
def pseudo_power_area(line, idx, n_steps):
|
|
@@ -938,9 +940,18 @@ class LineFitting:
|
|
|
938
940
|
line.measurements.peak_wave = emis_wave[peakIdx]
|
|
939
941
|
line.measurements.peak_flux = emis_flux[peakIdx]
|
|
940
942
|
line.measurements.pixelWidth = np.diff(emis_wave).mean()
|
|
941
|
-
|
|
943
|
+
|
|
944
|
+
# Continuum level and uncertainty at peak
|
|
942
945
|
line.measurements.cont = cont_arr[peakIdx]
|
|
943
|
-
|
|
946
|
+
|
|
947
|
+
if self.cov_linear is None:
|
|
948
|
+
line.measurements.cont_err = np.sqrt(((emis_wave[-1] - emis_wave[peakIdx]) / (emis_wave[-1]-emis_wave[0]) * emis_err[0]) ** 2
|
|
949
|
+
+ ((emis_wave[peakIdx] - emis_wave[0]) / (emis_wave[-1]-emis_wave[0]) * emis_err[-1]) ** 2)
|
|
950
|
+
else:
|
|
951
|
+
line.measurements.cont_err = np.sqrt(self.cov_linear[0, 0] * emis_wave[peakIdx] ** 2 + self.cov_linear[1, 1]
|
|
952
|
+
+ 2 * self.cov_linear[0, 1] * emis_wave[peakIdx])
|
|
953
|
+
|
|
954
|
+
# y_val_err = np.sqrt(((emis_wave[-1] - emis_wave[peakIdx]) / (emis_wave[-1]-emis_wave[0]) * emis_err[0]) ** 2 + ((emis_wave[peakIdx] - emis_wave[0]) / (emis_wave[-1]-emis_wave[0]) * emis_err[-1]) ** 2)
|
|
944
955
|
|
|
945
956
|
# Warning if continuum above or below line peak/through
|
|
946
957
|
if emission_check and (cont_arr[peakIdx] > emis_flux[peakIdx]):
|
|
@@ -997,67 +1008,73 @@ class LineFitting:
|
|
|
997
1008
|
|
|
998
1009
|
return
|
|
999
1010
|
|
|
1000
|
-
def
|
|
1011
|
+
def _cont_level_profile(self, idcs_emis, idcs_cont, user_cont_source, err_from_bands):
|
|
1001
1012
|
|
|
1002
1013
|
# Use the continuum bands for the calculation
|
|
1003
1014
|
match user_cont_source:
|
|
1004
1015
|
|
|
1005
1016
|
case 'adjacent':
|
|
1006
|
-
|
|
1007
|
-
# Check for zero err
|
|
1008
1017
|
err_cont = self._spec.err_flux[idcs_cont].compressed() if self._spec.err_flux is not None else None
|
|
1009
|
-
err_cont = err_cont if np.any(err_cont) else None
|
|
1018
|
+
# err_cont = err_cont if np.any(err_cont) else None
|
|
1010
1019
|
|
|
1011
1020
|
# Fit the model, including uncertainties
|
|
1012
|
-
params,
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
self.line.measurements.
|
|
1019
|
-
|
|
1021
|
+
params, self.cov_linear = curve_fit(linear_model, xdata=self._spec.wave[idcs_cont].compressed(),
|
|
1022
|
+
ydata=self._spec.flux[idcs_cont].compressed(), sigma=err_cont,
|
|
1023
|
+
absolute_sigma=True, check_finite=False)
|
|
1024
|
+
|
|
1025
|
+
self.line.measurements.m_cont = params[0]
|
|
1026
|
+
self.line.measurements.n_cont = params[1]
|
|
1027
|
+
self.line.measurements.m_cont_err_intg, self.line.measurements.n_cont_err_intg = np.sqrt(np.diag(self.cov_linear))
|
|
1028
|
+
|
|
1020
1029
|
cont_arr = self._spec.wave * self.line.measurements.m_cont + self.line.measurements.n_cont
|
|
1021
1030
|
|
|
1022
1031
|
case 'central':
|
|
1023
|
-
|
|
1024
1032
|
x, y = self._spec.wave[idcs_emis].compressed(), self._spec.flux[idcs_emis].compressed()
|
|
1025
1033
|
err = self._spec.err_flux[idcs_emis].compressed() if self._spec.err_flux is not None else [0, 0]
|
|
1026
1034
|
|
|
1027
|
-
|
|
1035
|
+
dx = x[-1] - x[0]
|
|
1036
|
+
self.line.measurements.m_cont = (y[-1] - y[0]) / dx
|
|
1028
1037
|
self.line.measurements.n_cont = y[0] - self.line.measurements.m_cont * x[0]
|
|
1029
1038
|
|
|
1030
|
-
self.line.measurements.m_cont_err_intg = np.sqrt((err[0]
|
|
1031
|
-
self.line.measurements.n_cont_err_intg = np.sqrt(err[0] ** 2 + (
|
|
1039
|
+
self.line.measurements.m_cont_err_intg = np.sqrt((err[0] / dx) ** 2 + (err[-1] / dx) ** 2)
|
|
1040
|
+
self.line.measurements.n_cont_err_intg = np.sqrt((err[0] * x[-1] / dx) ** 2 + (err[-1] * x[0] / dx) ** 2)
|
|
1041
|
+
|
|
1032
1042
|
cont_arr = self._spec.wave * self.line.measurements.m_cont + self.line.measurements.n_cont
|
|
1033
1043
|
|
|
1034
|
-
case 'fit':
|
|
1035
1044
|
|
|
1045
|
+
case 'fit':
|
|
1036
1046
|
x, y = self._spec.wave[idcs_cont].compressed(), self._spec.cont[idcs_cont].compressed()
|
|
1037
1047
|
err = self._spec.err_flux[idcs_cont].compressed() if self._spec.err_flux is not None else [0, 0]
|
|
1038
1048
|
|
|
1039
|
-
|
|
1049
|
+
dx = x[-1] - x[0]
|
|
1050
|
+
self.line.measurements.m_cont = (y[-1] - y[0]) / dx
|
|
1040
1051
|
self.line.measurements.n_cont = y[0] - self.line.measurements.m_cont * x[0]
|
|
1041
1052
|
|
|
1042
|
-
self.line.measurements.m_cont_err_intg = np.sqrt((err[0]
|
|
1043
|
-
self.line.measurements.n_cont_err_intg = np.sqrt(err[0] ** 2 + (
|
|
1053
|
+
self.line.measurements.m_cont_err_intg = np.sqrt((err[0] / dx) ** 2 + (err[-1] / dx) ** 2)
|
|
1054
|
+
self.line.measurements.n_cont_err_intg = np.sqrt((err[0] * x[-1] / dx) ** 2 + (err[-1] * x[0] / dx) ** 2)
|
|
1055
|
+
|
|
1056
|
+
# TODO here with the uncertainty from the spectrum fitted
|
|
1044
1057
|
cont_arr = self._spec.cont
|
|
1045
1058
|
|
|
1046
1059
|
case _:
|
|
1047
1060
|
raise LiMe_Error(f'Continuum source "{user_cont_source}" is not recognized. '
|
|
1048
1061
|
f'Please use "central", "adjacent" and "fit".')
|
|
1049
1062
|
|
|
1050
|
-
#
|
|
1051
|
-
|
|
1052
|
-
|
|
1063
|
+
# Bands constant pixel error
|
|
1064
|
+
if err_from_bands:
|
|
1065
|
+
err_arr = self._spec.wave * 0 + np.std(self._spec.flux[idcs_cont] - (self.line.measurements.m_cont * self._spec.wave[idcs_cont] + self.line.measurements.n_cont), ddof=2)
|
|
1066
|
+
|
|
1067
|
+
# Spectrum error
|
|
1068
|
+
else:
|
|
1069
|
+
err_arr = self._spec.err_flux
|
|
1053
1070
|
|
|
1054
|
-
return cont_arr
|
|
1071
|
+
return cont_arr, err_arr
|
|
1055
1072
|
|
|
1056
1073
|
def pixel_error_calculation(self, idcs_continua, user_error_from_bands):
|
|
1057
|
-
|
|
1074
|
+
# TODO delete this one
|
|
1058
1075
|
# Constant pixel error array from adjacent bands
|
|
1059
1076
|
if user_error_from_bands:
|
|
1060
|
-
return np.ma.array(np.full(self._spec.wave.shape, np.std(self._spec.flux[idcs_continua] - (self.line.measurements.m_cont * self._spec.wave[idcs_continua] + self.line.measurements.n_cont))), mask=
|
|
1077
|
+
return np.ma.array(np.full(self._spec.wave.shape, np.std(self._spec.flux[idcs_continua] - (self.line.measurements.m_cont * self._spec.wave[idcs_continua] + self.line.measurements.n_cont), ddof=2)), mask=self._spec.wave.mask)
|
|
1061
1078
|
|
|
1062
1079
|
# Pixel array
|
|
1063
1080
|
else:
|
|
@@ -134,7 +134,6 @@ def redshift_key_method(spec, bands, z_min, z_max, delta_z, pred_arr, components
|
|
|
134
134
|
|
|
135
135
|
# If there is only one line return nan
|
|
136
136
|
if not (method_flux and not detection_only):
|
|
137
|
-
# match np.count_nonzero(np.diff(np.r_[False, idcs_lines])):
|
|
138
137
|
match comp_counter(idcs_lines):
|
|
139
138
|
case 0:
|
|
140
139
|
return None # No components
|
|
@@ -205,7 +205,7 @@ def load_cfg(file_address, fit_cfg_suffix='_line_fitting'):
|
|
|
205
205
|
return cfg_lime
|
|
206
206
|
|
|
207
207
|
|
|
208
|
-
def save_cfg(output_file, param_dict, section_name=None, clear_section=False):
|
|
208
|
+
def save_cfg(output_file, param_dict, section_name=None, clear_section=False, overwrite_file=False):
|
|
209
209
|
|
|
210
210
|
"""
|
|
211
211
|
This function safes the input dictionary into a configuration file. If no section is provided the input dictionary
|
|
@@ -224,7 +224,7 @@ def save_cfg(output_file, param_dict, section_name=None, clear_section=False):
|
|
|
224
224
|
output_data = param_dict if section_name is None else {section_name: param_dict}
|
|
225
225
|
|
|
226
226
|
# If the file does not exist create a new file
|
|
227
|
-
if not output_path.is_file():
|
|
227
|
+
if not output_path.is_file() or overwrite_file:
|
|
228
228
|
with open(output_file, "w") as f:
|
|
229
229
|
toml.dump(output_data, f)
|
|
230
230
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
[metadata]
|
|
2
2
|
name = 'lime-stable'
|
|
3
|
-
version = "2.
|
|
3
|
+
version = "2.4.1"
|
|
4
|
+
lines_database = 'lines_database_v2.4.1.txt'
|
|
4
5
|
|
|
5
6
|
# =====================
|
|
6
7
|
# Spectrum / Long-slit
|
|
@@ -42,6 +43,20 @@ cos.units_flux = "FLAM"
|
|
|
42
43
|
cos.pixel_mask = "nan"
|
|
43
44
|
cos.id_label = 'null'
|
|
44
45
|
|
|
46
|
+
lzlcs_miri_merged.norm_flux = 'null'
|
|
47
|
+
lzlcs_miri_merged.res_power = 'null'
|
|
48
|
+
lzlcs_miri_merged.units_wave = "um"
|
|
49
|
+
lzlcs_miri_merged.units_flux = "Jy"
|
|
50
|
+
lzlcs_miri_merged.pixel_mask = "nan"
|
|
51
|
+
lzlcs_miri_merged.id_label = 'null'
|
|
52
|
+
|
|
53
|
+
lzlcs_miri_x1d.norm_flux = 'null'
|
|
54
|
+
lzlcs_miri_x1d.res_power = 'null'
|
|
55
|
+
lzlcs_miri_x1d.units_wave = "um"
|
|
56
|
+
lzlcs_miri_x1d.units_flux = "Jy"
|
|
57
|
+
lzlcs_miri_x1d.pixel_mask = "nan"
|
|
58
|
+
lzlcs_miri_x1d.id_label = 'null'
|
|
59
|
+
|
|
45
60
|
sdss.norm_flux = 'null'
|
|
46
61
|
sdss.res_power = 'null'
|
|
47
62
|
sdss.units_wave = "Angstrom"
|