# !/usr/bin/env python
# -*- coding: utf-8 -*-
# License: MIT
# Copyright (c) 2023, Cerdosino Candela, Fiore J.Manuel, Martinez J.Luis,
# Tapia-Reina Martina
# All rights reserved.
# =============================================================================
# IMPORTS
# =============================================================================
import attrs
import numpy as np
import pandas as pd
from ..utils.bunch import Bunch
# =============================================================================
# CONSTANTS
# =============================================================================
#: Z sun (cite)
Z_SUN = 0.019
# =============================================================================
# USEFUL FUNCTIONS
# =============================================================================
def _header_to_dataframe(header):
"""
Converts a given header (in dictionary form) into a pandas DataFrame.
Parameters
----------
header : dict
Dictionary containing the header keys and values.
Returns
-------
pandas.DataFrame
DataFrame with header keys as the index and values in a column named
"value".
"""
keys = list(header.keys())
values = list(header.values())
df = pd.DataFrame(values, index=keys)
df.columns = ["value"]
return df
# =============================================================================
# CLASSES
# =============================================================================
[docs]
@attrs.define
class SpectralSummary:
"""
Class that encapsulates all the data obtained from an input file.
Attributes
----------
obj_name : str
Object name.
header : dict
Header information from the input file.
data : dict
Spectra information in QTable format.
age : float
Object's age.
err_age : float
Error associated with the age.
reddening : float
Value of reddening
av_value : float
Extinction value.
normalization_point : float
Value of the normalization point.
z_value : float
Metallicity value.
spectra : dict
Set of spectra extracted from the input file.
extra_info : dict
Additional information.
"""
obj_name: str = attrs.field(converter=str)
header: dict = attrs.field(converter=lambda v: Bunch("header", v))
data: dict = attrs.field(converter=lambda v: Bunch("data", v))
age: float = attrs.field(converter=float)
err_age: float = attrs.field(converter=float)
reddening: float = attrs.field(converter=float)
av_value: float = attrs.field(converter=float)
normalization_point: float = attrs.field(converter=float)
z_value: float = attrs.field(converter=float)
spectra: dict = attrs.field(converter=lambda v: Bunch("spectra", v))
extra_info: dict = attrs.field(converter=lambda v: Bunch("extra", v))
@property
def header_info_df(self) -> pd.DataFrame:
"""
Converts the information stored in the 'header' attribute into a pandas
DataFrame.
Returns
-------
pandas.DataFrame
A DataFrame containing the header information, where the header
keys are the index and the values are stored in a column named
"value".
"""
return _header_to_dataframe(self.header)
[docs]
def get_spectrum(self, name: str):
"""
Retrieves a specific spectrum from the 'spectra' attribute.
Parameters
----------
name : str
The Name of the spectrum to retrieve.
Returns
-------
Spectrum
The spectrum corresponding to the specified name.
"""
return self.spectra[name]
def __getitem__(self, k: str):
"""
Allows access to the class attributes using dictionary-like syntax.
Parameters
----------
k : str
The name of the attribute to retrieve.
Returns
-------
Any
The value of the requested attribute.
Raises
------
KeyError
If the attribute does not exist.
"""
try:
return getattr(self, k)
except AttributeError:
raise KeyError(k)
def __len__(self) -> int:
"""
Returns the number of attributes defined in the class.
Returns
-------
int
The total number of attributes defined in the class.
"""
return len(attrs.fields(SpectralSummary))
def __repr__(self) -> str:
"""
Returns a string representation of the class instance, including a
summary of the main attributes: header, data, spectra, and
additional information.
Returns
-------
str
A string representation of the instance.
"""
header_keys = ", ".join(self.header.keys())
data_keys = ", ".join(self.data.keys())
spectra_keys = ", ".join(self.spectra.keys())
extra_info_keys = ", ".join(self.extra_info.keys())
return (
f"<SpectralSummary(\n"
f" header={{{header_keys}}},\n"
f" data={{{data_keys}}},\n"
" age, reddening, av_value, normalization_point, z_value,\n"
f" spectra={{{spectra_keys}}},\n"
f" extra_info={{{extra_info_keys}}})>"
)
@property
def feh_ratio(self):
"""
Calculates the metallicity ratio [Fe/H] using the instance's Z value
and the solar constant ('Z_SUN').
Returns
-------
float
Metallicity ratio [Fe/H].
"""
feh_ratio = np.log10(self.z_value / Z_SUN)
return feh_ratio
@property
def plot(self):
"""
Generates a 'SpectralPlotter' object for plotting the spectra stored
in the instance.
Uses the 'SpectralPlotter' class to handle plotting functionalities.
Returns
-------
SpectralPlotter
Object that enables generating plots of the spectra.
"""
from .plot import SpectralPlotter
return SpectralPlotter(self)
@property
def get_all_properties(self) -> pd.DataFrame:
"""
Creates a DataFrame containing all relevant parameters of the instance.
Numerical values are formatted to display in scientific notation where
necessary.
Returns
-------
pandas.DataFrame
A DataFrame with two columns: "Property" and "Value".
"""
age = f"{self.age:.2e}"
err_age = f"{self.err_age:.2e}"
properties = {
"object_name": self.obj_name,
"age": age,
"err_age": err_age,
"reddening": self.reddening,
"av_value": self.av_value,
"z_value": self.z_value,
"feh_ratio": self.feh_ratio,
"normalization_point": self.normalization_point,
}
df = pd.DataFrame(
list(properties.items()), columns=["Property", "Value"]
)
return df