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.
Files changed (59) hide show
  1. {lime_stable-2.2.dev6/src/lime_stable.egg-info → lime_stable-2.4.1}/PKG-INFO +19 -19
  2. {lime_stable-2.2.dev6 → lime_stable-2.4.1}/pyproject.toml +23 -19
  3. {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/archives/read_fits.py +86 -9
  4. {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/archives/tables.py +1 -1
  5. {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/changelog.txt +30 -0
  6. {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/fitting/lines.py +47 -30
  7. {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/fitting/redshift.py +0 -1
  8. {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/io.py +2 -2
  9. {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/lime.toml +16 -1
  10. {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/observations.py +145 -3
  11. {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/plotting/bokeh_plots.py +17 -1
  12. {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/plotting/plots.py +131 -30
  13. {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/plotting/plots_interactive.py +11 -10
  14. {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/resources/generator_db.py +7 -4
  15. {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/resources/lines_database_v2.0.6.txt +4 -1
  16. {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/retrieve/line_bands.py +2 -52
  17. {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/tools.py +4 -5
  18. {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/transitions.py +105 -23
  19. {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/workflow.py +127 -88
  20. {lime_stable-2.2.dev6 → lime_stable-2.4.1/src/lime_stable.egg-info}/PKG-INFO +19 -19
  21. {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime_stable.egg-info/SOURCES.txt +1 -1
  22. lime_stable-2.4.1/src/lime_stable.egg-info/requires.txt +28 -0
  23. {lime_stable-2.2.dev6 → lime_stable-2.4.1}/tests/test_io.py +1 -1
  24. {lime_stable-2.2.dev6 → lime_stable-2.4.1}/tests/test_line.py +39 -6
  25. lime_stable-2.4.1/tests/test_model.py +268 -0
  26. lime_stable-2.4.1/tests/test_plots.py +318 -0
  27. {lime_stable-2.2.dev6 → lime_stable-2.4.1}/tests/test_sample.py +1 -1
  28. {lime_stable-2.2.dev6 → lime_stable-2.4.1}/tests/test_spectrum.py +241 -73
  29. lime_stable-2.4.1/tests/test_tables.py +294 -0
  30. {lime_stable-2.2.dev6 → lime_stable-2.4.1}/tests/test_tools.py +56 -18
  31. lime_stable-2.2.dev6/src/lime/resources/lines_database_v2.0.0.txt +0 -153
  32. lime_stable-2.2.dev6/src/lime_stable.egg-info/requires.txt +0 -30
  33. lime_stable-2.2.dev6/tests/test_model.py +0 -110
  34. lime_stable-2.2.dev6/tests/test_plots.py +0 -46
  35. {lime_stable-2.2.dev6 → lime_stable-2.4.1}/LICENSE.rst +0 -0
  36. {lime_stable-2.2.dev6 → lime_stable-2.4.1}/MANIFEST.in +0 -0
  37. {lime_stable-2.2.dev6 → lime_stable-2.4.1}/README.md +0 -0
  38. {lime_stable-2.2.dev6 → lime_stable-2.4.1}/setup.cfg +0 -0
  39. {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/__init__.py +0 -0
  40. {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/archives/__init__.py +0 -0
  41. {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/fitting/__init__.py +0 -0
  42. {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/inference/detection.py +0 -0
  43. {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/inference/intensity_threshold.py +0 -0
  44. {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/plotting/__init__.py +0 -0
  45. {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/plotting/format.py +0 -0
  46. {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/plotting/theme_lime.toml +0 -0
  47. {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/plotting/utils.py +0 -0
  48. {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/resources/__init__.py +0 -0
  49. {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/resources/generator_logo.py +0 -0
  50. {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/resources/types_params.txt +0 -0
  51. {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/retrieve/__init__.py +0 -0
  52. {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime/rsrc_manager.py +0 -0
  53. {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime_stable.egg-info/dependency_links.txt +0 -0
  54. {lime_stable-2.2.dev6 → lime_stable-2.4.1}/src/lime_stable.egg-info/top_level.txt +0 -0
  55. {lime_stable-2.2.dev6 → lime_stable-2.4.1}/tests/test_astro.py +0 -0
  56. {lime_stable-2.2.dev6 → lime_stable-2.4.1}/tests/test_cube.py +0 -0
  57. {lime_stable-2.2.dev6 → lime_stable-2.4.1}/tests/test_read_fits.py +0 -0
  58. {lime_stable-2.2.dev6 → lime_stable-2.4.1}/tests/test_redshift.py +0 -0
  59. {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.2.dev6
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.11
9
- Requires-Python: >=3.11
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~=7.1
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.3
16
- Requires-Dist: pandas~=2.2
17
- Requires-Dist: scipy~=1.16
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.7.dev3; extra == "full"
22
- Requires-Dist: bokeh~=3.8; extra == "full"
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-rtd-theme~=3.0; extra == "docs"
29
- Requires-Dist: sphinx_togglebutton~=0.3; extra == "docs"
30
- Requires-Dist: sphinx_book_theme~=1.1; extra == "docs"
31
- Requires-Dist: ipympl~=0.9; extra == "docs"
32
- Requires-Dist: myst-nb~=1.3; extra == "docs"
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~=8.4; extra == "tests"
35
- Requires-Dist: pytest-cov~=7.0; extra == "tests"
36
- Requires-Dist: pytest-mpl~=0.17; extra == "tests"
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
  [![Line Measurer (LiMe) library.](https://github.com/Vital-Fernandez/lime/blob/0afedb150b0169deec6c7f159def99750a3a30da/docs/source/_static/logo_transparent.png?raw=true)]()
@@ -4,42 +4,42 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "lime-stable"
7
- version = "2.2.dev6"
7
+ version = "2.4.1"
8
8
  readme = { file = "README.md", content-type = "text/markdown" }
9
- requires-python = ">=3.11"
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.11"]
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~=7.1",
18
- "lmfit~=1.3",
17
+ dependencies = ["astropy~=8.0.0",
18
+ "lmfit~=1.3.4",
19
19
  "matplotlib~=3.10",
20
- "numpy~=2.3",
21
- "pandas~=2.2",
22
- "scipy~=1.16",
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.7.dev3",
28
- "bokeh~=3.8",
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-rtd-theme~=3.0",
35
- "sphinx_togglebutton~=0.3",
36
- "sphinx_book_theme~=1.1",
37
- "ipympl~=0.9",
38
- "myst-nb~=1.3"]
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~=8.4",
41
- "pytest-cov~=7.0",
42
- "pytest-mpl~=0.17"]
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
 
@@ -25,7 +25,7 @@ def format_for_table(entry, rounddig=4, rounddig_er=2, scientific_notation=False
25
25
  rounddig_er = rounddig
26
26
 
27
27
  # Check None entry
28
- if entry != None:
28
+ if entry is not None:
29
29
 
30
30
  # Check string entry
31
31
  if isinstance(entry, (str, bytes)):
@@ -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.alpha[idx], n_steps)
257
+ alpha = np.random.normal(line.alpha[idx], line.alpha_err[idx], n_steps)
256
258
 
257
- return 2.5066282746 * amp * 1/alpha
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
- # line.measurements.cont = line.measurements.peak_wave * line.measurements.m_cont + line.measurements.n_cont
943
+
944
+ # Continuum level and uncertainty at peak
942
945
  line.measurements.cont = cont_arr[peakIdx]
943
- line.measurements.cont_err = emis_err[peakIdx]
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 continuum_calculation(self, idcs_emis, idcs_cont, user_cont_source, err_from_bands):
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, covariance = curve_fit(linear_model,
1013
- xdata=self._spec.wave[idcs_cont].compressed(),
1014
- ydata=self._spec.flux[idcs_cont].compressed(),
1015
- sigma=err_cont,
1016
- absolute_sigma=True, check_finite=False)
1017
-
1018
- self.line.measurements.m_cont, self.line.measurements.n_cont = params
1019
- self.line.measurements.m_cont_err_intg, self.line.measurements.n_cont_err_intg = np.sqrt(np.diag(covariance))
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
- self.line.measurements.m_cont = (y[-1] - y[0]) / (x[-1] - x[0])
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] * (-1 / (x[-1] - x[0]))) ** 2 + (err[-1] * (1/(x[-1] - x[0]))) ** 2)
1031
- self.line.measurements.n_cont_err_intg = np.sqrt(err[0] ** 2 + (self.line.measurements.m_cont_err_intg * (-x[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
- self.line.measurements.m_cont = (y[-1] - y[0]) / (x[-1] - x[0])
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] * (-1 / (x[-1] - x[0]))) ** 2 + (err[-1] * (1/(x[-1] - x[0]))) ** 2)
1043
- self.line.measurements.n_cont_err_intg = np.sqrt(err[0] ** 2 + (self.line.measurements.m_cont_err_intg * (-x[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
- # # Initial continuum level value
1051
- # self.line.measurements.cont = (self.line.measurements.m_cont * self._spec.wave[idcs_emis].compressed().mean() +
1052
- # self.line.measurements.n_cont)
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=np.zeros(self._spec.wave.shape, dtype=bool))
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.2.dev6"
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"