Source code for lezargus.library.data

"""Data file functions.

This file deals with the loading in and saving of data files which are in
the /data/ directory of Lezargus. Moreover, the contents of the data
are accessed using attributes of this module.

Also, custom functions are provided to make things which are similarly
contained in the data directory. You can find all of these functions under the
`custom_*` namespace.
"""

import numpy as np

import lezargus
from lezargus.library import hint
from lezargus.library import logging


[docs] def add_data_object(name: str, data: object, force: bool = False) -> None: """Add a data variable to the library data module. If the addition of a new data object with the same name as one already present, we raise an error as these values are technically constants. Parameters ---------- name : str The name of the data object to be added, it will be coerced to be all capitalized as it ought to be effectively a constant. data : object The data object to be added to the data module. force : bool Force the loading of the data object regardless of any critical errors. """ # We fix the name. name = name.upper() # Check the current global namespace for any already-existing data objects. for namedex in globals(): if name == namedex: # A name conflict is detected, so, we need to give an error. If # we are not forcing it to be loaded, we use a critical error # instead. if force: logging.error( error_type=logging.InputError, message=( f"Object name {name} already exists in the data module." " We force its overwriting." ), ) else: logging.critical( critical_type=logging.InputError, message=( f"Object name {name} already exists in the data module." " We cannot assign a name to the data object." ), ) # We add the name and the object. logging.debug( message=( f"Added {name} to the lezargus.library.data module; it is of type" f" {type(data)}." ), ) globals().update({name: data})
[docs] def _zero_buffer_custom_filters( wavelength: hint.ndarray, transmission: hint.ndarray, ) -> tuple[hint.ndarray, hint.ndarray]: """Create a zero transmission buffer on either side of the filter. This function is a convenience function for creating tail ends of created custom filter profiles with zero transmission, as expected. Parameters ---------- wavelength : ndarray The original wavelength of the filter. transmission : ndarray The original transmission wavelength of the filter. Returns ------- zero_wavelength : ndarray The wavelength, with added points for the zero section. zero_transmission : ndarray The transmission, with added points for the zero section, of zero. """ # The number of buffer points we have to make on each side. n_buffer_points = 5 + 1 # Creating the buffer points. spacing = np.ptp(wavelength) / n_buffer_points # This helps the profiles be sharp by have a new data point very close to # the defined ones. delta = 10 ** np.floor(np.log10(spacing)) * 1e-5 # The actual points. extra_zero_blue_wave = ( np.min(wavelength) - ((np.arange(n_buffer_points)) * spacing) - delta ) extra_zero_red_wave = ( np.max(wavelength) + ((np.arange(n_buffer_points)) * spacing) + delta ) extra_zero_wave = np.append(extra_zero_blue_wave, extra_zero_red_wave) extra_zero_trans = np.zeros_like(extra_zero_wave) # Now adding them to the original spectra. new_zero_wavelength = np.append(wavelength, extra_zero_wave) new_zero_transmission = np.append(transmission, extra_zero_trans) # Sorting as well. sort_index = np.argsort(new_zero_wavelength) zero_wavelength = new_zero_wavelength[sort_index] zero_transmission = new_zero_transmission[sort_index] # All done. return zero_wavelength, zero_transmission
[docs] def custom_rectangular_filter( lower_limit: float, upper_limit: float, ) -> hint.LezargusSpectra: """Make a custom rectangular filter profile. Parameters ---------- lower_limit : float The lower limit of the rectangular filter. This value is typically a wavelength, in meters. upper_limit : float The upper limit of the rectangular filter. This value is typically a wavelength, in meters. Returns ------- rectangular_filter : LezargusSpectra The filter, as defined. """ # Wavelength and data. The 100 data points are arbitrary but we think it # is enough. n_data_points = 100 filter_wave = np.linspace(lower_limit, upper_limit, n_data_points) filter_trans = np.ones_like(filter_wave) # Customarily, filters have a little bit of data outside their band pass # for zeros. buffer_filter_wave, buffer_filter_trans = _zero_buffer_custom_filters( wavelength=filter_wave, transmission=filter_trans, ) # Now we construct the filter object. rectangular_filter = lezargus.container.LezargusSpectra( wavelength=buffer_filter_wave, data=buffer_filter_trans, uncertainty=None, wavelength_unit="m", data_unit="", header={"LZO_NAME": "Custom_rect_photon"}, ) # All done. return rectangular_filter