lime-stable 2.0.dev3__py3-none-any.whl → 2.0.dev4__py3-none-any.whl

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/archives/tables.py CHANGED
@@ -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
 
lime/changelog.txt CHANGED
@@ -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
lime/fitting/lines.py CHANGED
@@ -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
 
lime/fitting/redshift.py CHANGED
@@ -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']
lime/io.py CHANGED
@@ -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 = {}
lime/lime.toml CHANGED
@@ -1,3 +1,3 @@
1
1
  [metadata]
2
2
  name = 'lime-stable'
3
- version = "2.0.dev3"
3
+ version = "2.0.dev4"
lime/observations.py CHANGED
@@ -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.",
lime/plotting/plots.py CHANGED
@@ -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"
lime/transitions.py CHANGED
@@ -749,6 +749,7 @@ class Line:
749
749
  self.kinem = None
750
750
  self.profile_comp = profile
751
751
  self.transition_comp = None
752
+ self.core = None
752
753
 
753
754
  self._ref_idx = None
754
755
  self._p_type = None
@@ -843,9 +844,11 @@ class Line:
843
844
  else:
844
845
  self._ref_idx = 0
845
846
 
847
+ # Core component definition
848
+ self.core = f'{comps_list[0]}_{comps_list[1]}'
849
+
846
850
  # Provide a bands from the log if possible
847
- core_comp = f'{comps_list[0]}_{comps_list[1]}'
848
- self.mask = label_mask_assigning(self.label, band, self.blended_check, self.merged_check, core_comp)
851
+ self.mask = label_mask_assigning(self.label, band, self.blended_check, self.merged_check, self.core)
849
852
 
850
853
  # Check if there are masked pixels in the line
851
854
  self.pixel_mask = 'no' if fit_conf is None else fit_conf.get(f'{self.label}_mask', 'no')
@@ -1039,89 +1042,93 @@ class Line:
1039
1042
  else:
1040
1043
  return idcs_bands
1041
1044
 
1042
- def index_bands_orig(self, wavelength_array, redshift, merge_continua=True, just_band_edges=False):
1043
-
1044
- if self.mask is None:
1045
- raise LiMe_Error(f'The line {self.label} does include bands. Please select another line or update the database.')
1046
-
1047
- # Make sure it is a matrix
1048
- bands_arr = np.atleast_2d(self.mask) * (1 + redshift)
1049
-
1050
- # if np.any(bands_arr[:, 0] < wavelength_array[0]) or np.any(bands_arr[:, 5] > wavelength_array[-1]):
1051
- # _logger.warning(f'The {self.label} bands do not match the spectrum wavelength range (observed):')
1052
- # _logger.warning( f'-- The spectrum wavelength range is: ({wavelength_array[0]:0.2f}, {wavelength_array[-1]:0.2f}) (observed frame)')
1053
- # _logger.warning(f'-- The {self.label} bands are: {bands_arr} (rest frame * (1 + z))')
1054
-
1055
- # Check if it is a masked array
1056
- wave_arr = wavelength_array.data
1057
-
1058
- # Remove masked pixels from this function wavelength array
1059
- if self.pixel_mask != 'no':
1060
-
1061
- # Convert cfg mask string to limits
1062
- line_mask_limits = format_line_mask_option(self.pixel_mask, wave_arr)
1063
-
1064
- # Get masked indeces
1065
- idcsMask = (wave_arr[:, None] >= line_mask_limits[:, 0]) & (wave_arr[:, None] <= line_mask_limits[:, 1])
1066
- idcsValid = ~idcsMask.sum(axis=1).astype(bool)[:, None]
1067
-
1068
- else:
1069
- idcsValid = np.ones(wave_arr.size).astype(bool)[:, None]
1070
-
1071
- # Find indeces for six points in spectrum
1072
- idcsW = np.searchsorted(wave_arr, bands_arr)
1045
+ # def index_bands_orig(self, wavelength_array, redshift, merge_continua=True, just_band_edges=False):
1046
+ #
1047
+ # if self.mask is None:
1048
+ # raise LiMe_Error(f'The line {self.label} does include bands. Please select another line or update the database.')
1049
+ #
1050
+ # # Make sure it is a matrix
1051
+ # bands_arr = np.atleast_2d(self.mask) * (1 + redshift)
1052
+ #
1053
+ # # if np.any(bands_arr[:, 0] < wavelength_array[0]) or np.any(bands_arr[:, 5] > wavelength_array[-1]):
1054
+ # # _logger.warning(f'The {self.label} bands do not match the spectrum wavelength range (observed):')
1055
+ # # _logger.warning( f'-- The spectrum wavelength range is: ({wavelength_array[0]:0.2f}, {wavelength_array[-1]:0.2f}) (observed frame)')
1056
+ # # _logger.warning(f'-- The {self.label} bands are: {bands_arr} (rest frame * (1 + z))')
1057
+ #
1058
+ # # Check if it is a masked array
1059
+ # wave_arr = wavelength_array.data
1060
+ #
1061
+ # # Remove masked pixels from this function wavelength array
1062
+ # if self.pixel_mask != 'no':
1063
+ #
1064
+ # # Convert cfg mask string to limits
1065
+ # line_mask_limits = format_line_mask_option(self.pixel_mask, wave_arr)
1066
+ #
1067
+ # # Get masked indeces
1068
+ # idcsMask = (wave_arr[:, None] >= line_mask_limits[:, 0]) & (wave_arr[:, None] <= line_mask_limits[:, 1])
1069
+ # idcsValid = ~idcsMask.sum(axis=1).astype(bool)[:, None]
1070
+ #
1071
+ # else:
1072
+ # idcsValid = np.ones(wave_arr.size).astype(bool)[:, None]
1073
+ #
1074
+ # # Find indeces for six points in spectrum
1075
+ # idcsW = np.searchsorted(wave_arr, bands_arr)
1076
+ #
1077
+ # # Return just the edges of the bands
1078
+ # if just_band_edges:
1079
+ # outputs = idcsW[0]
1080
+ #
1081
+ # # Return the indeces of all the pixels within the bands
1082
+ # else:
1083
+ #
1084
+ # # Emission region
1085
+ # idcsLineRegion = ((wave_arr[idcsW[:, 2]] <= wave_arr[:, None]) & (
1086
+ # wave_arr[:, None] <= wave_arr[idcsW[:, 3]]) & idcsValid).squeeze()
1087
+ #
1088
+ # # Return left and right continua merged in one array
1089
+ # if merge_continua:
1090
+ # idcsContRegion = (((wave_arr[idcsW[:, 0]] <= wave_arr[:, None]) &
1091
+ # (wave_arr[:, None] <= wave_arr[idcsW[:, 1]])) |
1092
+ # ((wave_arr[idcsW[:, 4]] <= wave_arr[:, None]) & (
1093
+ # wave_arr[:, None] <= wave_arr[idcsW[:, 5]])) & idcsValid).squeeze()
1094
+ #
1095
+ # outputs = idcsLineRegion, idcsContRegion
1096
+ #
1097
+ # # Return left and right continua in separated arrays
1098
+ # else:
1099
+ # idcsContLeft = ((wave_arr[idcsW[:, 0]] <= wave_arr[:, None]) & (
1100
+ # wave_arr[:, None] <= wave_arr[idcsW[:, 1]]) & idcsValid).squeeze()
1101
+ # idcsContRight = ((wave_arr[idcsW[:, 4]] <= wave_arr[:, None]) & (
1102
+ # wave_arr[:, None] <= wave_arr[idcsW[:, 5]]) & idcsValid).squeeze()
1103
+ #
1104
+ # outputs = idcsLineRegion, idcsContLeft, idcsContRight
1105
+ #
1106
+ # return outputs
1073
1107
 
1074
- # Return just the edges of the bands
1075
- if just_band_edges:
1076
- outputs = idcsW[0]
1108
+ def update_label(self, decimals=None, update_latex=True, bands_df=None, vacuum_label=False):
1077
1109
 
1078
- # Return the indeces of all the pixels within the bands
1110
+ # Reference wavelength
1111
+ if (vacuum_label is True) and (bands_df is not None):
1112
+ wave_ref = pd_get(bands_df, self.label, 'wave_vac')
1079
1113
  else:
1114
+ wave_ref = self.wavelength[self._ref_idx]
1080
1115
 
1081
- # Emission region
1082
- idcsLineRegion = ((wave_arr[idcsW[:, 2]] <= wave_arr[:, None]) & (
1083
- wave_arr[:, None] <= wave_arr[idcsW[:, 3]]) & idcsValid).squeeze()
1084
-
1085
- # Return left and right continua merged in one array
1086
- if merge_continua:
1087
- idcsContRegion = (((wave_arr[idcsW[:, 0]] <= wave_arr[:, None]) &
1088
- (wave_arr[:, None] <= wave_arr[idcsW[:, 1]])) |
1089
- ((wave_arr[idcsW[:, 4]] <= wave_arr[:, None]) & (
1090
- wave_arr[:, None] <= wave_arr[idcsW[:, 5]])) & idcsValid).squeeze()
1091
-
1092
- outputs = idcsLineRegion, idcsContRegion
1093
-
1094
- # Return left and right continua in separated arrays
1095
- else:
1096
- idcsContLeft = ((wave_arr[idcsW[:, 0]] <= wave_arr[:, None]) & (
1097
- wave_arr[:, None] <= wave_arr[idcsW[:, 1]]) & idcsValid).squeeze()
1098
- idcsContRight = ((wave_arr[idcsW[:, 4]] <= wave_arr[:, None]) & (
1099
- wave_arr[:, None] <= wave_arr[idcsW[:, 5]]) & idcsValid).squeeze()
1100
-
1101
- outputs = idcsLineRegion, idcsContLeft, idcsContRight
1102
-
1103
- return outputs
1104
-
1105
- def update_label(self, decimals=None, update_latex=True, bands_df=None):
1106
-
1107
- # Convert core transition particle
1116
+ # Core transition particle
1108
1117
  part_str = self.particle[self._ref_idx]
1109
- wave_str = np.round(self.wavelength[self._ref_idx], 0).astype(int) if decimals is None else np.round(self.wavelength[self._ref_idx], decimals)
1118
+ wave_str = np.round(wave_ref, 0).astype(int) if decimals is None else np.round(wave_ref, decimals)
1110
1119
  units_str = f'{self.units_wave[self._ref_idx]}' if self.units_wave[self._ref_idx] != 'Angstrom' else 'A'
1111
1120
  module_str = "_b" if self.blended_check else "_m" if self.merged_check else ""
1121
+
1122
+ # Optional components
1112
1123
  kinem_str = f'_k-{self.kinem[self._ref_idx]}' if self.kinem[self._ref_idx] != 0 else ''
1113
1124
  profile_str = f'_p-{self.profile_comp[self._ref_idx]}' if self.profile_comp[self._ref_idx] != 'g-emi' else ''
1114
1125
  trans_str = f'_t-{self.kinem[self._ref_idx]}' if not self.profile_comp[self._ref_idx] not in ['rec', 'col'] else ''
1115
1126
 
1116
- # New label
1127
+ # Set label
1117
1128
  self.label = f'{part_str}_{wave_str}{units_str}{module_str}{kinem_str}{profile_str}{trans_str}'
1118
1129
 
1119
1130
  # Update latex notation
1120
1131
  if update_latex:
1121
1132
  self.latex_label = self._review_science_notation(bands_df, update_latex, decimals=decimals)
1122
1133
 
1123
- return
1124
-
1125
- def get_latex_label(self):
1126
-
1127
1134
  return