lime-stable 2.0.dev3__tar.gz → 2.0.dev4__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 (50) hide show
  1. {lime_stable-2.0.dev3/src/lime_stable.egg-info → lime_stable-2.0.dev4}/PKG-INFO +1 -1
  2. {lime_stable-2.0.dev3 → lime_stable-2.0.dev4}/pyproject.toml +1 -1
  3. {lime_stable-2.0.dev3 → lime_stable-2.0.dev4}/src/lime/archives/tables.py +3 -0
  4. {lime_stable-2.0.dev3 → lime_stable-2.0.dev4}/src/lime/changelog.txt +5 -1
  5. {lime_stable-2.0.dev3 → lime_stable-2.0.dev4}/src/lime/fitting/lines.py +3 -1
  6. {lime_stable-2.0.dev3 → lime_stable-2.0.dev4}/src/lime/fitting/redshift.py +3 -0
  7. {lime_stable-2.0.dev3 → lime_stable-2.0.dev4}/src/lime/io.py +18 -20
  8. {lime_stable-2.0.dev3 → lime_stable-2.0.dev4}/src/lime/lime.toml +1 -1
  9. {lime_stable-2.0.dev3 → lime_stable-2.0.dev4}/src/lime/observations.py +3 -1
  10. {lime_stable-2.0.dev3 → lime_stable-2.0.dev4}/src/lime/plotting/bokeh_plots.py +9 -1
  11. {lime_stable-2.0.dev3 → lime_stable-2.0.dev4}/src/lime/plotting/plots.py +22 -7
  12. {lime_stable-2.0.dev3 → lime_stable-2.0.dev4}/src/lime/plotting/plots_interactive.py +53 -34
  13. {lime_stable-2.0.dev3 → lime_stable-2.0.dev4}/src/lime/plotting/theme_lime.toml +3 -1
  14. {lime_stable-2.0.dev3 → lime_stable-2.0.dev4}/src/lime/transitions.py +77 -70
  15. {lime_stable-2.0.dev3 → lime_stable-2.0.dev4}/src/lime/workflow.py +250 -184
  16. {lime_stable-2.0.dev3 → lime_stable-2.0.dev4/src/lime_stable.egg-info}/PKG-INFO +1 -1
  17. {lime_stable-2.0.dev3 → lime_stable-2.0.dev4}/tests/test_cube.py +2 -2
  18. {lime_stable-2.0.dev3 → lime_stable-2.0.dev4}/tests/test_io.py +46 -0
  19. {lime_stable-2.0.dev3 → lime_stable-2.0.dev4}/tests/test_spectrum.py +49 -5
  20. {lime_stable-2.0.dev3 → lime_stable-2.0.dev4}/tests/test_tools.py +102 -4
  21. {lime_stable-2.0.dev3 → lime_stable-2.0.dev4}/LICENSE.rst +0 -0
  22. {lime_stable-2.0.dev3 → lime_stable-2.0.dev4}/MANIFEST.in +0 -0
  23. {lime_stable-2.0.dev3 → lime_stable-2.0.dev4}/README.rst +0 -0
  24. {lime_stable-2.0.dev3 → lime_stable-2.0.dev4}/setup.cfg +0 -0
  25. {lime_stable-2.0.dev3 → lime_stable-2.0.dev4}/src/lime/__init__.py +0 -0
  26. {lime_stable-2.0.dev3 → lime_stable-2.0.dev4}/src/lime/archives/__init__.py +0 -0
  27. {lime_stable-2.0.dev3 → lime_stable-2.0.dev4}/src/lime/archives/read_fits.py +0 -0
  28. {lime_stable-2.0.dev3 → lime_stable-2.0.dev4}/src/lime/fitting/__init__.py +0 -0
  29. {lime_stable-2.0.dev3 → lime_stable-2.0.dev4}/src/lime/inference/detection.py +0 -0
  30. {lime_stable-2.0.dev3 → lime_stable-2.0.dev4}/src/lime/inference/intensity_threshold.py +0 -0
  31. {lime_stable-2.0.dev3 → lime_stable-2.0.dev4}/src/lime/plotting/__init__.py +0 -0
  32. {lime_stable-2.0.dev3 → lime_stable-2.0.dev4}/src/lime/plotting/format.py +0 -0
  33. {lime_stable-2.0.dev3 → lime_stable-2.0.dev4}/src/lime/plotting/utils.py +0 -0
  34. {lime_stable-2.0.dev3 → lime_stable-2.0.dev4}/src/lime/resources/__init__.py +0 -0
  35. {lime_stable-2.0.dev3 → lime_stable-2.0.dev4}/src/lime/resources/lines_database_formatting.py +0 -0
  36. {lime_stable-2.0.dev3 → lime_stable-2.0.dev4}/src/lime/resources/lines_database_v2.0.0.txt +0 -0
  37. {lime_stable-2.0.dev3 → lime_stable-2.0.dev4}/src/lime/resources/logo.py +0 -0
  38. {lime_stable-2.0.dev3 → lime_stable-2.0.dev4}/src/lime/resources/types_params.txt +0 -0
  39. {lime_stable-2.0.dev3 → lime_stable-2.0.dev4}/src/lime/retrieve/__init__.py +0 -0
  40. {lime_stable-2.0.dev3 → lime_stable-2.0.dev4}/src/lime/retrieve/peaks.py +0 -0
  41. {lime_stable-2.0.dev3 → lime_stable-2.0.dev4}/src/lime/tools.py +0 -0
  42. {lime_stable-2.0.dev3 → lime_stable-2.0.dev4}/src/lime_stable.egg-info/SOURCES.txt +0 -0
  43. {lime_stable-2.0.dev3 → lime_stable-2.0.dev4}/src/lime_stable.egg-info/dependency_links.txt +0 -0
  44. {lime_stable-2.0.dev3 → lime_stable-2.0.dev4}/src/lime_stable.egg-info/requires.txt +0 -0
  45. {lime_stable-2.0.dev3 → lime_stable-2.0.dev4}/src/lime_stable.egg-info/top_level.txt +0 -0
  46. {lime_stable-2.0.dev3 → lime_stable-2.0.dev4}/tests/test_astro.py +0 -0
  47. {lime_stable-2.0.dev3 → lime_stable-2.0.dev4}/tests/test_line.py +0 -0
  48. {lime_stable-2.0.dev3 → lime_stable-2.0.dev4}/tests/test_model.py +0 -0
  49. {lime_stable-2.0.dev3 → lime_stable-2.0.dev4}/tests/test_read_fits.py +0 -0
  50. {lime_stable-2.0.dev3 → lime_stable-2.0.dev4}/tests/test_sample.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lime-stable
3
- Version: 2.0.dev3
3
+ Version: 2.0.dev4
4
4
  Summary: Line measuring algorithm for astronomical spectra
5
5
  Author-email: Vital Fernández <vgf@umich.edu>
6
6
  License-Expression: GPL-3.0-or-later
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "lime-stable"
7
- version = "2.0.dev3"
7
+ version = "2.0.dev4"
8
8
  readme = "README.rst"
9
9
  requires-python = ">=3.11"
10
10
  license = "GPL-3.0-or-later"
@@ -122,6 +122,9 @@ def table_fluxes(lines_df, table_address, header_format_latex, table_type='pdf',
122
122
  except:
123
123
  print('\n-- PDF compilation failure')
124
124
 
125
+ elif table_type == 'tex':
126
+ pdf.pdfDoc.generate_tex(table_address.as_posix())
127
+
125
128
  return
126
129
 
127
130
 
@@ -105,4 +105,8 @@ LiMe Mayor update - 2.0.0 - XX/XX/XXXX
105
105
  - The central wavelenght bands are now calculated assuming a bands_vsigma=70 and n_sigma=4
106
106
  - The function lime.Spectrum.retrieve.spectrum() returns the spectrum axes as a recarray or saves it into a text file if the user provides a file address.
107
107
  - lime.Spectrum.from_file("fname", instrument='text') can now read the file from a text file following the format from the lime.Spectrum.retrieve.spectrum() function.
108
- - Bug the .plot.spectrum(include_fittings) does not show the combined profile
108
+ - Bug the .plot.spectrum(include_fittings) does not show the combined profile
109
+ - Rename term "_conf" to "_cfg" across function names and arguments for uniformity
110
+ - Fitting functions now have the update_default=True argument. In the default behaviour the default configuration updates the default one. If set to update_default=False only the obj_cfg is used if available else the default one.
111
+ - Creating a spectrum object where all the entries are masked now produces a critical warning instead of raising an error.
112
+ - By default line_bands
@@ -418,7 +418,9 @@ def sigma_corrections(line, idcs_line, wave_arr, R_arr, temperature):
418
418
  if np.isscalar(R_arr):
419
419
  line.sigma_instr = np.mean(wave_arr.compressed() / (R_arr * k_gFWHM))
420
420
  else:
421
- line.sigma_instr = np.mean(wave_arr[idcs_line].compressed() / (R_arr[idcs_line] * k_gFWHM))
421
+ mask_data = ~wave_arr.mask
422
+ line.sigma_instr = np.mean(wave_arr[mask_data] / (R_arr[idcs_line][mask_data] * k_gFWHM))
423
+ wave_arr[mask_data] / (R_arr[idcs_line][mask_data] * k_gFWHM)
422
424
  else:
423
425
  line.sigma_instr = np.nan
424
426
 
@@ -283,6 +283,9 @@ class RedshiftFitting:
283
283
  else:
284
284
  pred_arr, conf_arr = self._spec.infer.pred_arr, self._spec.infer.conf_arr
285
285
 
286
+ # Resolving power # TODO this should be read at another point...
287
+ res_power = self._spec.res_power if res_power is None else res_power
288
+
286
289
  # Set the type of fitting and the components to use
287
290
  if mode == 'key':
288
291
  components = components if components is not None else ['emission', 'doublet']
@@ -446,8 +446,8 @@ def save_frame(fname, dataframe, page='FRAME', parameters='all', header=None, co
446
446
  output_file.write(string_DF.encode('UTF-8'))
447
447
 
448
448
  # Pdf fluxes table
449
- elif file_type == '.pdf':
450
- table_fluxes(lines_log, log_path.parent / log_path.stem, header_format_latex=_LOG_COLUMNS_LATEX,
449
+ elif file_type == '.pdf' or file_type == '.tex':
450
+ table_fluxes(lines_log, log_path.parent / log_path.stem, table_type=file_type[1:], header_format_latex=_LOG_COLUMNS_LATEX,
451
451
  lines_notation=log.latex_label.values, **kwargs)
452
452
 
453
453
  # Log in a fits format
@@ -601,7 +601,8 @@ def check_file_dataframe(df_variable, variable_type=pd.DataFrame, ext='FRAME', s
601
601
  return output
602
602
 
603
603
 
604
- def check_fit_conf(fit_conf, default_key, group_key, group_list=None, fit_cfg_suffix='_line_fitting', line_detection=False):
604
+ def check_fit_conf(fit_conf, default_key, obj_key, update_default=True, group_list=None, fit_cfg_suffix='_line_fitting',
605
+ line_detection=False):
605
606
 
606
607
  # Check that there is an input configuration
607
608
  if fit_conf is not None:
@@ -634,33 +635,30 @@ def check_fit_conf(fit_conf, default_key, group_key, group_list=None, fit_cfg_su
634
635
 
635
636
  # Recover the configuration expected for the object
636
637
  default_cfg = input_cfg.get(f'{default_key}_line_fitting') if default_key is not None else None
637
- mask_cfg = input_cfg.get(f'{group_key}_line_fitting') if group_key is not None else None
638
+ custom_cfg = input_cfg.get(f'{obj_key}_line_fitting') if obj_key is not None else None
638
639
 
639
- # Case there are not leveled entries
640
- if (default_cfg is None) and (mask_cfg is None):
640
+ # Case there are not level entries
641
+ if (default_cfg is None) and (custom_cfg is None):
641
642
  output_cfg = input_cfg
642
643
 
643
644
  # Proceed to update the levels
644
645
  else:
645
646
 
646
647
  # Default configuration
647
- output_cfg = {} if default_cfg is None else default_cfg
648
- default_detect = output_cfg.get('line_detection')
648
+ default_cfg = {} if default_cfg is None else default_cfg
649
+ default_detect = default_cfg.get('line_detection', {})
649
650
 
650
- # Mask conf
651
- mask_conf = {} if mask_cfg is None else mask_cfg
652
- mask_detect = mask_conf.get('line_detection')
651
+ # Custom configuration
652
+ custom_cfg = {} if custom_cfg is None else custom_cfg
653
+ custom_detect = custom_cfg.get('line_detection', {})
653
654
 
654
- # Update the levels
655
- output_cfg = {**output_cfg, **mask_conf}
655
+ # Update default configuration if requested else use only custom
656
+ output_cfg = {**default_cfg, **custom_cfg} if update_default else (custom_cfg if custom_cfg else default_cfg)
656
657
 
657
- # If no line detection don't add it # TODO this is wrong lower should update upper
658
- if mask_detect is not None:
659
- output_cfg['line_detection'] = mask_detect
660
- elif default_detect is not None:
661
- output_cfg['line_detection'] = default_detect
662
- else:
663
- pass
658
+ # Update default detection if requested else use only custom
659
+ if line_detection:
660
+ output_cfg['line_detection'] = default_detect.update(custom_detect) if update_default else\
661
+ (custom_detect if custom_detect else default_detect)
664
662
 
665
663
  else:
666
664
  output_cfg = {}
@@ -1,3 +1,3 @@
1
1
  [metadata]
2
2
  name = 'lime-stable'
3
- version = "2.0.dev3"
3
+ version = "2.0.dev4"
@@ -142,7 +142,7 @@ def check_inputs_arrays(wave, flux, err_flux, pixel_mask, lime_object):
142
142
  # Check not all the pixels are masked
143
143
  if mask_check:
144
144
  if np.all(output_pixel_mask):
145
- raise LiMe_Error(f'All the input observation pixels are masked. Please check that only bad pixels entries'
145
+ _logger.critical(f'All the input observation pixels are masked. Please check that only bad pixels entries'
146
146
  f' are masked (in numpy arrays flux_arr[pixel_mask] = bad_entries)')
147
147
 
148
148
  return output_pixel_mask
@@ -1347,6 +1347,8 @@ class Sample(UserDict, OpenFits):
1347
1347
  else:
1348
1348
  obs = load_function_output
1349
1349
 
1350
+
1351
+
1350
1352
  return obs
1351
1353
 
1352
1354
  def __getitem__(self, id_key):
@@ -270,7 +270,7 @@ class BokehFigures:
270
270
 
271
271
  def spectrum(self, output_address=None, label=None, bands=None, rest_frame=False, log_scale=False,
272
272
  include_fits=True, include_cont=False, include_components=False, return_fig=False, fig_cfg=None, ax_cfg=None, maximize=False,
273
- detection_band=None, show_masks=True, show_categories=False):
273
+ detection_band=None, show_masks=True, show_categories=False, show_err=False):
274
274
 
275
275
 
276
276
  # Set figure format with the user inputs overwriting the default conf
@@ -298,6 +298,14 @@ class BokehFigures:
298
298
  if bands is not None:
299
299
  bokeh_bands(fig, bands, wave_plot, flux_plot, z_corr, self._spec.redshift)
300
300
 
301
+ # Show uncertainty
302
+ if show_err and (self._spec.err_flux is not None):
303
+ err_plot = self._spec.err_flux.data
304
+ fig.varea_step(x=wave_plot / z_corr,
305
+ y1=(flux_plot - err_plot) * z_corr,
306
+ y2=(flux_plot + err_plot) * z_corr,
307
+ step_mode="center", fill_alpha=0.2, color=theme.colors['err_area'])
308
+
301
309
  # Include the continuum
302
310
  if include_cont and self._spec.cont is not None:
303
311
  fig.line(wave_plot/z_corr, self._spec.cont*z_corr, legend_label="Continuum.",
@@ -654,7 +654,7 @@ def redshift_permu_evaluation(spectrum, z_infered, obs_wave_arr, theo_wave_arr,
654
654
  return
655
655
 
656
656
 
657
- def bands_filling_plot(axis, x, y, z_corr, idcs_mask, label, exclude_continua=False, color_dict=theme.colors):
657
+ def bands_filling_plot(axis, x, y, z_corr, idcs_mask, label, exclude_continua=False, color_dict=theme.colors, show_central=True):
658
658
 
659
659
  # Security check for low selection
660
660
  if len(x[idcs_mask[2]:idcs_mask[3]]) > 1:
@@ -673,8 +673,9 @@ def bands_filling_plot(axis, x, y, z_corr, idcs_mask, label, exclude_continua=Fa
673
673
  low_lim = m * x_interval + n
674
674
 
675
675
  # Central bands
676
- axis.fill_between(x_interval/z_corr, low_lim*z_corr, y_interval*z_corr,
677
- facecolor=color_dict['line_band'], step='mid', alpha=0.25)
676
+ if show_central:
677
+ axis.fill_between(x_interval/z_corr, low_lim*z_corr, y_interval*z_corr,
678
+ facecolor=color_dict['line_band'], step='mid', alpha=0.25)
678
679
 
679
680
  # Continua bands exclusion
680
681
  if exclude_continua is False:
@@ -767,8 +768,8 @@ class Plotter:
767
768
  def _line_matching_plot(self, axis, bands, x, y, z_corr, redshift):
768
769
 
769
770
  # Open the bands file the bands
770
- match_log = self._spec.retrieve.line_bands(ref_bands=bands, fit_conf=None, instrumental_correction=False,
771
- adjust_central_bands=False)
771
+ match_log = self._spec.retrieve.line_bands(ref_bands=bands, fit_cfg=None, instrumental_correction=False,
772
+ adjust_central_band=False)
772
773
  # Compute bands limits
773
774
  w3 = match_log.w3.values * (1 + redshift)
774
775
  w4 = match_log.w4.values * (1 + redshift)
@@ -782,6 +783,7 @@ class Plotter:
782
783
 
783
784
  # Loop through the detections and plot the names
784
785
  for i, line_label in enumerate(match_log.index):
786
+ print(line_label)
785
787
  line = Line(line_label, match_log)
786
788
 
787
789
  # Get the max flux on the region making the exception for 1 pixel bands
@@ -1274,7 +1276,7 @@ class SpectrumFigures(Plotter):
1274
1276
  return in_fig
1275
1277
 
1276
1278
  def bands(self, label=None, output_address=None, ref_bands=None, include_fits=True, rest_frame=False, y_scale='auto', fig_cfg=None,
1277
- ax_cfg=None, in_fig=None, maximize=False):
1279
+ ax_cfg=None, in_fig=None, maximize=False, show_err=True):
1278
1280
 
1279
1281
  """
1280
1282
 
@@ -1333,6 +1335,12 @@ class SpectrumFigures(Plotter):
1333
1335
  # Check which line should be plotted
1334
1336
  line = parse_bands_arguments(label, log, ref_bands, norm_flux)
1335
1337
 
1338
+ # Check the observation has uncertainty to display
1339
+ if show_err and (self._spec.err_flux is None):
1340
+ if self._spec.err_flux is None:
1341
+ _logger.info('Input observation does not include uncertainty to display')
1342
+ show_err = False
1343
+
1336
1344
  # Proceed to plot
1337
1345
  if line is not None:
1338
1346
 
@@ -1375,7 +1383,14 @@ class SpectrumFigures(Plotter):
1375
1383
  where='mid', color=theme.colors['fg'], label=label_leg, linewidth=theme.plt['spectrum_width'])
1376
1384
 
1377
1385
  # Continuum bands
1378
- bands_filling_plot(in_ax[0], wave_plot, flux_plot, z_corr, idcs_bands, line, color_dict=theme.colors)
1386
+ bands_filling_plot(in_ax[0], wave_plot, flux_plot, z_corr, idcs_bands, line, color_dict=theme.colors,
1387
+ show_central=not show_err)
1388
+
1389
+ if show_err:
1390
+ err_plot = self._spec.err_flux.data
1391
+ in_ax[0].fill_between(x=wave_plot[idcs_bands[2]:idcs_bands[3]] / z_corr, y1=(flux_plot[idcs_bands[2]:idcs_bands[3]] - err_plot[idcs_bands[2]:idcs_bands[3]]) * z_corr,
1392
+ y2=(flux_plot[idcs_bands[2]:idcs_bands[3]] + err_plot[idcs_bands[2]:idcs_bands[3]]) * z_corr,
1393
+ step='mid', alpha=1, color=theme.colors['line_band'], ec=None)
1379
1394
 
1380
1395
  # Add the fitting results
1381
1396
  if include_fits:
@@ -20,23 +20,31 @@ from ..transitions import label_decomposition, Line
20
20
  _logger = logging.getLogger('LiMe')
21
21
 
22
22
 
23
- def establish_selection_lines(spec, input_log, band_vsigma=70, n_sigma=4, fit_conf=None,
24
- default_conf_prefix='default', obj_conf_prefix=None, adjust_central_bands=True,
25
- instrumental_correction=True, components_detection=False, line_list=None,
26
- particle_list=None, sig_digits=None, vacuum_waves=False, ref_bands=None, update_labels=True,
27
- update_latex=False):
23
+ def establish_selection_lines(spec, input_log, band_vsigma, n_sigma, adjust_central_band, instrumental_correction,
24
+ components_detection, composite_lines, fit_cfg, default_cfg_prefix, obj_cfg_prefix,
25
+ update_default, line_list, particle_list, decimals, vacuum_waves, ref_bands, update_labels,
26
+ update_latex, vacuum_label):
28
27
 
29
28
  # Use the default database crop for the observation if none provided
30
- ref_bands = spec.retrieve.line_bands(band_vsigma, n_sigma, None, None, None,
31
- adjust_central_bands, instrumental_correction, False, line_list,
32
- particle_list, sig_digits, vacuum_waves, ref_bands, update_labels, update_latex)
29
+ ref_bands = spec.retrieve.line_bands(band_vsigma=band_vsigma, n_sigma=n_sigma, adjust_central_band=adjust_central_band,
30
+ instrumental_correction=instrumental_correction, components_detection=False,
31
+ composite_lines=None, fit_cfg=None, default_cfg_prefix=None,
32
+ obj_cfg_prefix=None, update_default=True,
33
+ line_list=line_list, particle_list=particle_list, decimals=decimals,
34
+ vacuum_waves=vacuum_waves, ref_bands=ref_bands, update_labels=update_labels,
35
+ update_latex=update_latex, vacuum_label=vacuum_label)
36
+
33
37
 
34
38
  # Load input log or copy the reference one
35
39
  in_bands = check_file_dataframe(input_log, verbose=False)
36
40
  if in_bands is None:
37
- in_bands = spec.retrieve.line_bands(band_vsigma, n_sigma, fit_conf, default_conf_prefix, obj_conf_prefix,
38
- adjust_central_bands, instrumental_correction, components_detection, line_list,
39
- particle_list, sig_digits, vacuum_waves, ref_bands, update_labels, update_latex)
41
+ in_bands = spec.retrieve.line_bands(band_vsigma=band_vsigma, n_sigma=n_sigma, adjust_central_band=adjust_central_band,
42
+ instrumental_correction=instrumental_correction, components_detection=components_detection,
43
+ composite_lines=composite_lines, fit_cfg=fit_cfg, default_cfg_prefix=default_cfg_prefix,
44
+ obj_cfg_prefix=obj_cfg_prefix, update_default=update_default,
45
+ line_list=line_list, particle_list=particle_list, decimals=decimals,
46
+ vacuum_waves=vacuum_waves, ref_bands=ref_bands, update_labels=update_labels,
47
+ update_latex=update_latex, vacuum_label=vacuum_label)
40
48
  default_status = 1 if components_detection else 0
41
49
  else:
42
50
  default_status = 1
@@ -78,6 +86,11 @@ def establish_selection_lines(spec, input_log, band_vsigma=70, n_sigma=4, fit_co
78
86
  active_lines = active_lines[sorted_indexes].astype(bool)
79
87
  labels_arr = labels_arr[sorted_indexes]
80
88
 
89
+ # Set NaN entries in dataframe as None
90
+ if 'group_label' in log.columns:
91
+ idcs_nan = log.group_label.isnull()
92
+ log.loc[idcs_nan, 'group_label'] = 'none'
93
+
81
94
  return log, labels_arr, active_lines
82
95
 
83
96
 
@@ -180,17 +193,20 @@ class BandsInspection:
180
193
  self._color_bg = {True: theme.colors['inspection_positive'],
181
194
  False: theme.colors['inspection_negative']}
182
195
 
196
+ self._out_params = ["wavelength", "wave_vac", "w1", "w2", "w3", "w4", "w5", "w6",
197
+ "units_wave", "particle", "transition", "rel_int"]
198
+
183
199
  return
184
200
 
185
- def bands(self, bands_file, band_vsigma=70, n_sigma=4, fit_conf=None, default_conf_prefix='default', obj_conf_prefix=None,
186
- adjust_central_bands=True, instrumental_correction=True, components_detection=False, line_list=None,
187
- particle_list=None, sig_digits=None, vacuum_waves=False, ref_bands=None, update_labels=True,
188
- update_latex=False, y_scale='auto', n_cols=6, n_rows=None, col_row_scale=(1, 0.5),
189
- exclude_continua=False, n_pixels=10, fig_cfg=None, in_fig=None, maximize=False):
201
+ def bands(self, bands_file, band_vsigma=70, n_sigma=4, adjust_central_band=True, instrumental_correction=True,
202
+ components_detection=False, composite_lines=None, fit_cfg=None, default_cfg_prefix='default',
203
+ obj_cfg_prefix=None, update_default=True, line_list=None, particle_list=None, decimals=None,
204
+ vacuum_waves=False, ref_bands=None, update_labels=False, update_latex=False, vacuum_label=False,
205
+ y_scale='auto', n_cols=6, n_rows=None, col_row_scale=(1, 0.5),
206
+ exclude_continua=False, n_pixels=10, fig_cfg=None, in_fig=None, maximize=False):
190
207
 
191
208
 
192
209
  """
193
-
194
210
  This function launches an interactive plot from which to select the line bands on the observed spectrum. If this
195
211
  function is run a second time, the user selections won't be overwritten.
196
212
 
@@ -266,10 +282,11 @@ class BandsInspection:
266
282
  raise LiMe_Error(f'Input bands file directory does not exist ({self._log_address.parent.as_posix()})')
267
283
 
268
284
  # Establish the reference lines log to inspect the mask
269
- self.log, self.line_list, self.active_lines = establish_selection_lines(self._spec, self._log_address, band_vsigma, n_sigma, fit_conf,
270
- default_conf_prefix, obj_conf_prefix, adjust_central_bands,
271
- instrumental_correction, components_detection, line_list, particle_list,
272
- sig_digits, vacuum_waves, ref_bands, update_labels, update_latex)
285
+ self.log, self.line_list, self.active_lines = establish_selection_lines(self._spec, self._log_address,
286
+ band_vsigma, n_sigma, adjust_central_band, instrumental_correction,
287
+ components_detection, composite_lines, fit_cfg, default_cfg_prefix,
288
+ obj_cfg_prefix, update_default, line_list, particle_list, decimals,
289
+ vacuum_waves, ref_bands, update_labels, update_latex, vacuum_label)
273
290
 
274
291
  # Proceed if there are lines in the mask for the object spectrum wavelength range
275
292
  if len(self.log.index) > 0:
@@ -430,7 +447,7 @@ class BandsInspection:
430
447
  _logger.info(f'Unsuccessful line selection: {self.line}: w_low: {w_low}, w_high: {w_high}')
431
448
 
432
449
  # Save the log to the file
433
- save_or_clear_log(self.log, self._log_address, self.active_lines)
450
+ save_or_clear_log(self.log, self._log_address, self.active_lines, self._out_params)
434
451
 
435
452
  # Redraw the line measurement
436
453
  self._ax.clear()
@@ -470,7 +487,7 @@ class BandsInspection:
470
487
  self.active_lines[idx] = np.invert(self.active_lines[idx])
471
488
 
472
489
  # Save the log to the file
473
- save_or_clear_log(self.log, self._log_address, self.active_lines)
490
+ save_or_clear_log(self.log, self._log_address, self.active_lines, self._out_params)
474
491
 
475
492
  # Plot the line selection with the new Background
476
493
  self._ax.clear()
@@ -516,7 +533,7 @@ class BandsInspection:
516
533
  self._fig.canvas.draw()
517
534
 
518
535
  # Save the log to the file
519
- save_or_clear_log(self.log, self._log_address, self.active_lines)
536
+ save_or_clear_log(self.log, self._log_address, self.active_lines, self._out_params)
520
537
 
521
538
  return
522
539
 
@@ -821,8 +838,12 @@ class RedshiftInspection:
821
838
 
822
839
  def redshift(self, obj_idcs, reference_lines, output_file_log=None, output_idcs=None, redshift_column='redshift',
823
840
  initial_z=None, none_value=np.nan, unknown_value=0.0, legend_handle='levels', maximize=False, title=None,
824
- output_address=None, n_pixels=10, fig_cfg={}, ax_cfg={}, in_fig=None):
841
+ output_address=None, n_pixels=10, fig_cfg={}, ax_cfg={}, in_fig=None, **kwargs):
842
+
825
843
 
844
+ # Check if input tuple
845
+ if isinstance(obj_idcs, tuple):
846
+ obj_idcs = pd.MultiIndex.from_tuples([obj_idcs], names=self._sample.index.names)
826
847
 
827
848
  # Assign the attributes
828
849
  self._obj_idcs = obj_idcs if isinstance(obj_idcs, pd.MultiIndex) else self._sample.loc[obj_idcs].index
@@ -833,6 +854,10 @@ class RedshiftInspection:
833
854
  self._legend_handle = legend_handle
834
855
  self._user_point = None
835
856
 
857
+ # Parameters for the load function
858
+ self._load_params = {**self._sample.load_params, **kwargs}
859
+ self._load_params['redshift'] = 0
860
+
836
861
  # Output Log params
837
862
  self._log_address = output_file_log
838
863
 
@@ -904,9 +929,6 @@ class RedshiftInspection:
904
929
  # Plot on screen unless an output address is provided
905
930
  save_close_fig_swicth(output_address, 'tight', self._fig, maximise=maximize)
906
931
 
907
- # else:
908
- # _logger.warning(f'The sample does not have objects. The redshift check could not be done')
909
-
910
932
  return
911
933
 
912
934
  def _launch_plots_ZI(self):
@@ -944,8 +966,7 @@ class RedshiftInspection:
944
966
  for i, obj_idx in enumerate(self._obj_idcs):
945
967
 
946
968
  # Load the spectrum with a zero redshift
947
- load_params = {**self._sample.load_params, **{'redshift': 0}}
948
- spec = self._sample.load_function(self._sample.frame, obj_idx, self._sample.file_address, **load_params)
969
+ spec = self._sample.load_function(self._sample.frame, obj_idx, self._sample.file_address, **self._load_params)
949
970
 
950
971
  # Plot on the observed frame with reshift = 0
951
972
  wave_plot, flux_plot, z_corr, idcs_mask = frame_mask_switch(spec.wave, spec.flux, spec.redshift, 'observed')
@@ -966,8 +987,7 @@ class RedshiftInspection:
966
987
  for obj_idx in self._obj_idcs:
967
988
 
968
989
  # Load the spectrum
969
- load_params = {**self._sample.load_params, **{'redshift': 0}}
970
- spec = self._sample.load_function(self._sample.frame, obj_idx, self._sample.file_address, **load_params)
990
+ spec = self._sample.load_function(self._sample.frame, obj_idx, self._sample.file_address, **self._load_params)
971
991
 
972
992
  wavelength = spec.wave.data
973
993
  wavelength = wavelength[~np.isnan(wavelength)]
@@ -1042,13 +1062,12 @@ class RedshiftInspection:
1042
1062
  _redshift_pred = redshift_output
1043
1063
 
1044
1064
  # Store the new redshift
1045
- #
1065
+
1046
1066
  self._sample.loc[self._output_idcs, self._column_log] = _redshift_pred
1047
1067
 
1048
1068
  # Save to file if provided
1049
1069
  if self._log_address is not None:
1050
1070
  save_frame(self._log_address, self._sample.frame)
1051
-
1052
1071
  return
1053
1072
 
1054
1073
  def _button_ZI(self, line_selection):
@@ -109,6 +109,7 @@ mask_marker = '#FF0000'
109
109
  inspection_positive = '#FFFFFF'
110
110
  inspection_negative = '#ff796c' # 'xkcd:salmon'
111
111
  fade_fg = "#FFE5B4"
112
+ err_area = "#00FF00"
112
113
 
113
114
  [colors.dark] # Dark theme
114
115
  bg = "#2B2B2B"
@@ -128,4 +129,5 @@ comps_map = 'PuRd'
128
129
  mask_marker = '#FF0000'
129
130
  inspection_positive = "#2B2B2B"
130
131
  inspection_negative = '#840000'
131
- fade_fg = "#73879B"
132
+ fade_fg = "#73879B"
133
+ err_area = "#00FF00"