Source code for casper.interface.gisic.segment
import numpy as np
from numpy.typing import ArrayLike
from casper.utils.logger_config import setup_logger
logger = setup_logger(__name__)
[docs]
class Segment:
def __init__(self, wl: ArrayLike = None, flux: ArrayLike = None):
"""
Initialize a Segment object with wavelength and flux values.
Parameters
----------
wl : array_like
Wavelength values that define the x-axis of the segment.
flux : array_like
Flux values corresponding to each wavelength in `wl`, defining the y-axis
of the segment.
Attributes
----------
midpoint : float
The median value of the wavelength array, used to represent the segment's center.
"""
self.wl = np.array([]) if wl is None else np.array(wl)
self.flux = np.array([]) if flux is None else np.array(flux)
self.midpoint = np.median(self.wl)
[docs]
def is_edge(self, which: str) -> None:
"""
Set the midpoint of the segment to either the first or last wavelength value,
depending on whether the segment is at the start or end of the spectrum.
Parameters
----------
which : str
Indicates which edge the segment belongs to.
Must be one of:
- "left": sets midpoint to the first wavelength.
- "right": sets midpoint to the last wavelength.
Raises
------
Prints an error message if `which` is not "left" or "right".
"""
if which == "left":
self.midpoint = np.array(self.wl)[0]
elif which == "right":
self.midpoint = np.array(self.wl)[-1]
else:
logger.error(f"Invalid value for 'which': {which}. Must be 'left' or 'right'.")
raise ValueError(f"Invalid value for 'which': {which}. Must be 'left' or 'right'.")
[docs]
def get_statistics(self, flux_min: float = 70) -> None:
"""
Compute robust statistical measures of flux variability for the segment.
Parameters
----------
flux_min : float, optional
The lower percentile threshold used for clipping the flux distribution.
Default is 70.
Sets
----
self.mad : float
Median Absolute Deviation (MAD) of the flux values.
self.mad_normal : float
Normalized MAD, calculated as MAD divided by the median flux.
self.flux_med : float
Median flux value computed from the central clipped range
[flux_min percentile, 98th percentile].
self.flux_min : float
Flux value at the `flux_min` percentile.
self.flux_max : float
Flux value at the 98th percentile.
"""
self.mad = np.median(np.absolute(self.flux - np.median(self.flux)))
if self.mad != 0:
self.mad_normal = self.mad / np.median(self.flux)
else:
self.mad_normal = 0.0
self.flux_med = np.median(
self.flux[
np.where(
(self.flux >= np.percentile(self.flux, flux_min)) & (self.flux <= np.percentile(self.flux, 98))
)
]
)
self.flux_min = np.percentile(self.flux, flux_min)
self.flux_max = np.percentile(self.flux, 98)
[docs]
def define_cont_point(self, mad_min: float, mad_range: float, boost: bool = True) -> None:
"""
Define a continuum point based on the flux variability within the segment.
Parameters
----------
mad_min : float
Minimum normalized MAD value used as a baseline.
mad_range : float
Range used to scale the influence of flux variation on the continuum point.
boost : bool, optional
If True, adjust the continuum point toward the segment's maximum flux based
on relative variation. If False, use the median flux as the continuum point.
Sets
----
self.mad_relative : float
Relative MAD used to determine how strongly to bias the continuum point.
self.continuum_point : float
Estimated continuum level for this segment.
"""
self.mad_relative = (self.mad_normal - mad_min) / mad_range
if boost:
self.continuum_point = (self.flux_max - self.flux_med) * self.mad_relative + self.flux_med
else:
self.continuum_point = self.flux_med
return