Source code for lotus_nlte.gcogs.gcog

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Tue Nov  9 15:12:58 2021

@author: yangyangli
"""
__all__ = ['SingleGCOG']

import numpy as np
import pandas as pd
import h5py

import warnings

from .utils import get_keys_and_atmos_pars, find_closest_model
from ..config import GCOG_LTE_LIB, GCOG_NLTE_LIB

[docs]class SingleGCOG: """Base class for General Curve of Growth (GCOG) This intends for assemble discrete relationship between theoretical EW with other atsmopheric stellar parameters. Parameters ---------- wavelength: float Target line wavelength ep: float Target line excitation potential , in unit of ev element: str "FeI" or "FeII" stellar_type: str The stellar type of your star, like: {spectral type, e.g. F, G, K}/{giant or subgiant or dwarf}/{metal_rich or metal_poor or very_metal_poor} or the estimation of your atmospheric parameters in such form: {T_low}_{T_high}/{logg_low}_{logg_high}/{[Fe/H]_low}_{[Fe/H]_high} cal: str Types of EW, e.g. "lte" or "nlte" interpolated: bool, optional True: use interpolated GCOG False: get GCOG from EW library ewlibpath: None or str if ``interpolted==False``, this must be assigned for assemble GCOG as the path for the libary of EW, it must be a h5 file if ``interpolated==True``, this can be None keys: None or list of str if ``interpolted==False``, this should be the target keys of ewlib if ``interpolated=True``, this can be None atmos_pars: None or list if ``interpolted==False``, this should be the target keys of ewlib, the shape of the list is (N_selected_gridpoints, 4) if ``interpolated==True``, this can be None """ __slots__ = ["wavelength", "ep", "element", "stellar_type", "interpolated", "ewlibpath", "interptar", "cal", "_keys", "_atmos_pars", "_hyper_surface"] def __init__(self, wavelength, ep, element, stellar_type, cal, interpolated=False, ewlibpath=None, keys=None, atmos_pars=None): self.wavelength = wavelength self.ep = ep self.element = element self.stellar_type = stellar_type self.cal = cal self.interpolated = interpolated if interpolated: import tarfile if self.cal == "lte": self.interptar = tarfile.open(GCOG_LTE_LIB) else: self.interptar = tarfile.open(GCOG_NLTE_LIB) else: if not ewlibpath: raise ValueError("Please assign your EW library!") self.ewlibpath = ewlibpath if keys==None or atmos_pars==None: self._keys, self._atmos_pars = get_keys_and_atmos_pars(ewlibpath, stellar_type) else: self._keys = keys self._atmos_pars = atmos_pars self._hyper_surface = None
[docs] def load_model(self): """ Load interpolated model for a single line Raises ------ ValueError ``interpolated==False``, there is no interpolated model to import Returns ------- m : sklearn.pipeline.Pipeline interpolated model """ if not self.interpolated: raise ValueError("Your model hasn't been interpolated yet") import joblib working_dir = self.interptar.getnames()[0] + "/" + self.stellar_type + "/" fname = find_closest_model(self.wavelength, self.ep, self.element, working_dir, "*", False, self.interptar) m = joblib.load(self.interptar.extractfile(fname[0])) return m
[docs] def plot_interpolated_cog(self, teff, logg, vt, ews=None): """ Plot interpolated Curve of Growth Parameters ---------- teff : int or float which Teff the COG is at logg : int or float which logg the COG is at vt : int or float which microturbulen velocity the COG is at ews : list or ndarray, optional . The default is None, then EWs are using from 1 $m\overset{\circ}A$ to 100$m\overset{\circ}A$. Raises ------ ValueError ``interpolated==False``, there is no interpolated model to import Returns ------- fig : matplotlib.figure.Figure plot for COG """ if not self.interpolated: raise ValueError("Your model hasn't been interpolated yet") import matplotlib.pyplot as plt if not ews: ews = np.arange(1, 100, 0.1) generated_mets = [self.load_model().predict([[teff, logg, vt, ew]])[0] for ew in ews] fig = plt.plot(ews, generated_mets) plt.xlabel("EW(m$\AA$)") plt.ylabel("A(Fe)") return fig
[docs] def assemble_hyper_surface(self): """ Collect EW and other stellar parameters from library and assemble them into an array Returns ------- ndarray An array with a shape of (N, 5), N is the number of grid points in your targerted region of library, this depends on the parameter of stellar_type """ def get_row_no(k0): hdf = pd.HDFStore(self.ewlibpath, 'r') hdf0 = hdf.get(k0) idx = np.where((np.abs(hdf0.th_wavelength-self.wavelength)<=0.025) & (np.abs(hdf0.th_EP - self.ep)<=0.02) & (hdf0.element == self.element))[0] if idx.size!=0: idx = idx[0] else: idx = -1 hdf.close() return idx if self.interpolated: raise NotImplementedError("Interpolated model doesn't have such method!") row_no = get_row_no(self._keys[0]) if row_no == -1: warnings.warn("Data for interpolation is not enough!") self._hyper_surface = None return self._hyper_surface else: f = h5py.File(self.ewlibpath, 'r') if self.cal == "nlte": ews = [np.array(f[k+"/table"])[row_no][1][3] for k in self._keys] else: ews = [np.array(f[k+"/table"])[row_no][1][2] for k in self._keys] f.close() datapoints = np.concatenate((np.array(self._atmos_pars), np.transpose([ews])), axis=1) datapoints = datapoints[~np.isnan(datapoints).any(axis=1)] if datapoints.shape[0] <= 3: warnings.warn("Data for interpolation is not enough!") self._hyper_surface = None del datapoints return self._hyper_surface else: self._hyper_surface = datapoints print("Grid is prepared!") del datapoints return self._hyper_surface