def __init__(self):

        # Declare Hydrogen and Helium collisional lines for the analysis
        self.Hydrogen_Lines = ["Hdelta_6_2", "Hgamma_5_2", "Hbeta_4_2", "Halpha_3_2"]
        self.Hydrogen_Labels = ["6_2", "5_2", "4_2", "3_2"]
        self.Hydrogen_Wavelengths = [4101.742, 4340.471, 4862.683, 6562.819]

        self.Helium_Lines = ["He1_3889", "He1_4026.0", "He1_4471.0", "He1_5876.0", "He1_6678.0", "He1_7065.0"]
        self.Helium_Labels = ["3889.0", "4026.0", "4471.0", "5876.0", "6678.0", "7065.0"]
        self.Helium_Wavelengths = [3889.0, 4026.0, 4471.0, 5876.0, 6678.0, 7065.0]

        # Define indexes and labels to speed up the code
        self.HBeta_label = "4_2"
        self.HBeta_Index = self.Hydrogen_Lines.index("Hbeta_4_2")
        self.nHydrogen = range(len(self.Hydrogen_Lines))
        self.nHelium = range(len(self.Helium_Lines))

        # THIS TRICK IS NECCESARY SO THAT WE DO NOT INCLUDE THE HBETA LINE IN THE CALCULATION
        self.nHydrogen.remove(self.HBeta_Index)
        Valid_H_Lines = list(self.Hydrogen_Wavelengths)
        del Valid_H_Lines[self.HBeta_Index]

        # Declare pyneb Hydrogen and Helium atoms to calculate emissivities
        self.H1 = RecAtom("H", 1)
        self.He1 = RecAtom("He", 1)
        self.H_emissivity_Vector = zeros(len(self.nHydrogen))  # Array to store the emissivities for each of the labels
        self.He_emissivity_Vector = zeros(
            len(self.Helium_Labels)
        )  # Array to store the emissivities for each of the labels

        # Import collisional coefficients table
        self.H_CollCoeff_Matrix = self.Import_Coll_Coeff_Table("H")
        self.He_CollCoeff_Matrix = self.Import_Coll_Coeff_Table("He")
        self.H_CRratio_Vector = zeros(len(self.nHydrogen))  # Array to store the C/R for each of the HydrogenLines
        self.He_CRratio_Vector = zeros(len(self.Helium_Labels))  # Array to store the C/R for each of the HydrogenLines

        # Import Optical depth function for He lines
        self.He_OpticalDepth_Matrix = self.Import_OpticalDepth_Coeff_Table("He")
        self.f_Hetau_vector = zeros(len(self.Helium_Labels))

        # Calculate f_lambda in advance law configuration (from Cardelli, Clayton and Mathis law)
        self.R_v = 3.1
        self.a_coeffs = array([1.0, 0.17699, -0.50447, -0.02427, 0.72085, 0.01979, -0.77530, 0.32999])
        self.b_coeffs = array([0.0, 1.41338, 2.28305, 1.07233, -5.38434, -0.62251, 5.30260, -2.09002])

        self.f_H_vector = self.get_flambda_vector(array(Valid_H_Lines))
        self.f_He_vector = self.get_flambda_vector(array(self.Helium_Wavelengths))

        # Extra
        self.EmptyRowFormat = "nan"
    def __init__(self):
        
        #Import Dazer_Files Class to import data from lines_logs
        Txt_Files_Manager.__init__(self)
        
        #Declare Hydrogen and Helium collisional lines for the analysis
        #self.posHydrogen_Ions      = ['Hdelta_6_2',    'Hgamma_5_2',   'Hbeta_4_2',    'Halpha_3_2']
        self.posHydrogen_Lines      = ['H1_4102A',      'H1_4340A',     'H1_4861A',     'H1_6563A']
        self.Hydrogen_Wavelengths   = [4101.742,        4340.471,       4862.683,        6562.819]
        
        self.posHelium_Lines        = ['H1_3889A',  'He1_4026A',    'He1_4387A',    'He1_4471A',    'He1_4686A',    'He1_4714A',    'He1_4922A',   'He1_5876A',    'He1_6678A',   'He1_7065A',    'He1_7281A',      'He1_10830A']     
        self.Helium_Wavelengths     = [3889.0,        4026.0,         4387.0,         4471.0,         4686.0,         4714.0,         4922.0,         5876.0,         6678.0,         7065.0,         7281.0,         10830.0]
        
        self.Cand_Hydrogen_Lines    = []
        self.Cand_Helium_Lines      = []
        
        self.nHydrogen              = None
        self.nHelium                = None
    
        #Define indexes and labels to speed up the code
        self.H13889A_label          = 'H1_3889A'          
        self.HBeta_label            = 'H1_4861A'
        self.He3889_label           = 'He1_3889A'
        self.He3889blended_label    = 'He1_3889A_blended'
        self.He3889_check           = None
        
        #Declare pyneb Hydrogen and Helium atoms to calculate emissivities
        self.H1                     = RecAtom('H', 1)
        self.He1                    = RecAtom('He', 1) 
        
        #Import collisional coefficients table
        self.Coef_Kalpha_dict       = self.Import_Coll_Coeff_Table(self.posHydrogen_Lines, None)

        #Import Optical depth function
        self.Coef_ftau_dict         = self.Import_OpticalDepth_Coeff_Table(self.posHelium_Lines) 
               
        #Declare dictionaries to store the data
        #WARNING: In this analysis flambda is mantained constant
        self.Flux_dict              = OrderedDict()
        self.Error_dict             = OrderedDict()
        self.Wave_dict              = OrderedDict()
        self.PynebCode_dict         = OrderedDict()
        self.EqW_dict               = OrderedDict()
        self.EqWerror_dict          = OrderedDict()
        self.hlambda_dict           = OrderedDict()
        self.flambda_dict           = self.get_flambda_dict(self.posHydrogen_Lines + self.posHelium_Lines, self.Hydrogen_Wavelengths + self.Helium_Wavelengths)
        
        #Extra
        self.EmptyRowFormat         = 'nan'            
示例#3
0
    return TotalWave, TotalInt

Pv                                      = plotMan.myPickle()
CatalogueFolder, DataType, Log_Format   = DataToTreat()              #First batch process for untreated spectra
Pattern                                 = '_' + DataType + '.fits'                
Emission_DataLog_Suffix                 = '_' + DataType + '_LinesLog_v3.txt'   

#Find and organize files from terminal command or .py file
FilesList = Pv.FindAndOrganize(Pattern, CatalogueFolder, CheckComputer=True)

# Generate figures
Pv.FigFormat_One(ColorConf='Night1')

Coefficients = []

H1 = RecAtom('H', 1)

# Loop through files
for m in range(len(FilesList)):     
    for j in range(len(FilesList[m])):

        CodeName, FileName, FileFolder = Pv.FileAnalyzer(FilesList[m][j])
        SetLogFile(CodeName + '_log.txt', FileFolder, Pv.ComputerRoot + 'Dropbox/Astrophysics/Data/WHT_HII_Galaxies/WHT_Log_Format.txt')

        if DataType == 'WHT':

            Blue_Filename   = 'obj' + CodeName + '_Blue_t_z_EBV.fits'
            Red_FileName    = 'obj' + CodeName +  '_Red_t_tell_z_EBV.fits'
            
            Wave_Total, Int_Total, ExtraData_Comb    = Pv.File2Data(FileFolder, FileName)
            Wave_Blue, Int_Blue, ExtraData_Blue = Pv.File2Data(FileFolder, Blue_Filename)
class HeAbundance_InferenceMethods(Dazer_Files):
    
    def __init__(self):
        
        #Import Dazer_Files Class to import data from lines_logs
        Dazer_Files.__init__(self)
        
        #Declare Hydrogen and Helium collisional lines for the analysis
        self.posHydrogen_Lines      = ['Hdelta_6_2',    'Hgamma_5_2',   'Hbeta_4_2',    'Halpha_3_2']
        self.Hydrogen_Wavelengths   = [4101.742,        4340.471,       4862.683,        6562.819]
        
        self.posHelium_Lines        = ['He1_3889A',  'He1_4026A',    'He1_4387A',    'He1_4471A',    'He1_4686A',    'He1_4714A',    'He1_4922A',   'He1_5876A',    'He1_6678A',   'He1_7065A',    'He1_7281A',      'He1_10380A']     
        self.Helium_Wavelengths     = [3889.0,        4026.0,         4387.0,         4471.0,         4686.0,         4714.0,         4922.0,         5876.0,         6678.0,         7065.0,         7281.0,         10380.0]
        
        self.Cand_Hydrogen_Lines    = []
        self.Cand_Helium_Lines      = []
        
        self.nHydrogen              = None
        self.nHelium                = None
    
        #Define indexes and labels to speed up the code               
        self.HBeta_label            = 'Hbeta_4_2'
                
        #Declare pyneb Hydrogen and Helium atoms to calculate emissivities
        self.H1                     = RecAtom('H', 1)
        self.He1                    = RecAtom('He', 1) 
        
        #Import collisional coefficients table
        self.Coef_Kalpha_dict       = self.Import_Coll_Coeff_Table(self.posHydrogen_Lines, None)

        #Import Optical depth function
        self.Coef_ftau_dict         = self.Import_OpticalDepth_Coeff_Table(self.posHelium_Lines) 
               
        #Declare dictionaries to store the data
        #WARNING: In this analysis flambda is mantained constant
        self.Flux_dict              = OrderedDict()
        self.Error_dict             = OrderedDict()
        self.Wave_dict              = OrderedDict()
        self.PynebCode_dict         = OrderedDict()
        self.EqW_dict               = OrderedDict()
        self.EqWerror_dict          = OrderedDict()
        self.hlambda_dict           = OrderedDict()
        self.flambda_dict           = self.get_flambda_dict(self.posHydrogen_Lines + self.posHelium_Lines, self.Hydrogen_Wavelengths + self.Helium_Wavelengths)
        
        #Extra
        self.EmptyRowFormat         = 'nan'            
            
    def Import_TableData(self, Address, Columns):
        
        Imported_Array  = genfromtxt(Address, dtype=float, usecols = Columns, skiprows = 2).T
        Datarray = Imported_Array[:,~isnan(Imported_Array).all(0)]
                
        return Datarray
     
    def Import_Coll_Coeff_Table(self, HydrogenLines, HeliumLines):
        
        data_dict = OrderedDict()
                
        for i in range(len(HydrogenLines)):
            
            Line            = HydrogenLines[i]
            Data_Columns    = [0 + 3*i, 1 + 3*i, 2 + 3*i]
            data_dict[Line] = self.Import_TableData(self.Hydrogen_CollCoeff_TableAddress, Data_Columns)
        
        #We ignore since the emissivities from PFM already have the collisional contribution accounted
#         for j in range(len(HeliumLines)):
#             
#             Line            = HeliumLines[i]
#             Data_Columns    = [0 + 3*j, 1 + 3*j, 2 + 3*j]
#             data_dict[Line] = self.Import_TableData(self.Helium_CollCoeff_TableAddress, Data_Columns)
            
        return data_dict
     
    def Import_OpticalDepth_Coeff_Table(self, HeliumLines):
        
        data_dict = OrderedDict()

        for i in range(len(HeliumLines)):
            
            Line            = HeliumLines[i]
            data_dict[Line] = loadtxt(self.Helium_OpticalDepth_TableAddress, dtype = float, skiprows = 2, usecols = (i,))
            
        return data_dict
    
    def Import_Synthetic_Fluxes(self, Model = 'Model2'):

        self.SyntheticData_dict = OrderedDict()

        if Model == 'Model1':
#             self.SyntheticData_dict['He_Flux']      = array([ 0.0891384,    0.01283333,     0.03187135, 0.09890274, 0.02582588, 0.02366021])   
#             self.SyntheticData_dict['He_Flux']      = array([ 0.0891384,    0.01283333,     0.03187135, 0.09890274, 0.02582588, 0.02366021])
            
            self.SyntheticData_dict['H_Flux']       = array([ 0.24685935,   0.45526236,     1.0,            2.96988502])
            self.SyntheticData_dict['H_wave']       = array([4101.742,      4340.471,      4862.683,       6562.819])
            self.SyntheticData_dict['H_labels']     = ['Hdelta_6_2',    'Hgamma_5_2',   'Hbeta_4_2',    'Halpha_3_2']
            self.SyntheticData_dict['H_Eqw']        = [50.0,            50.0,           250,             300.0]
            self.SyntheticData_dict['H_EqwErr']     = [1.0,             1.0,            12.5,            14]
            self.SyntheticData_dict['H_hlambda']    = [1.0,             1.0,            1.0,             1.0]
            self.SyntheticData_dict['H_error']      = self.SyntheticData_dict['H_Flux'] * 0.01
            
            self.SyntheticData_dict['He_Flux']      = array([ 0.08951096,    0.01290066,     0.03201484, 0.09931435, 0.02594518, 0.02377085])   
            self.SyntheticData_dict['He_wave']      = array([ 3889.0,       4026.0,         4471.0,        5876.0,     6678.0,     7065.0])
            self.SyntheticData_dict['He_labels']    =       ['He1_3889A',   'He1_4026A',   'He1_4471A',   'He1_5876A','He1_6678A','He1_7065A']
            self.SyntheticData_dict['He_Eqw']       = [10.0,                10.0,           10.0,           10.0,        10.0,          10.0]
            self.SyntheticData_dict['He_EqwErr']    = [1.0,                 1.0,            1.0,            1.0,         1.0,           1.0]
            self.SyntheticData_dict['He_hlambda']   = [1.0,                 1.0,            1.0,            1.0,         1.0,           1.0] 
            self.SyntheticData_dict['He_error']     = self.SyntheticData_dict['He_Flux'] * 0.02
                        
            self.SyntheticData_dict['TOIII']        = 19000
            self.SyntheticData_dict['y_plus']       = 0.08
            self.SyntheticData_dict['n_e']          = 100.0
            self.SyntheticData_dict['a_He']         = 1.0
            self.SyntheticData_dict['tau']          = 0.2
            self.SyntheticData_dict['Te_0']         = 18000.0
            self.SyntheticData_dict['cHbeta']       = 0.1
            self.SyntheticData_dict['a_H']          = 1.0
            self.SyntheticData_dict['xi']           = 1.0

        if Model == 'Model2':
            
            #These are the ones from the version 0
            #self.SyntheticData_dict['H_Flux']       = array([ 0.24585991,  0.45343263,  2.95803687])
            #self.SyntheticData_dict['He_Flux']      = array([ 0.10059744,  0.01684244,  0.03908421,  0.12673761,  0.03538569,  0.04145339])
            #These are the ones from the version 1
            self.SyntheticData_dict['H_Flux']       = array([0.24625485, 0.454443,      1,              2.98352834])
            self.SyntheticData_dict['H_wave']       = array([4101.742,   4340.471,      4862.683,       6562.819])
            self.SyntheticData_dict['H_labels']     = ['Hdelta_6_2',    'Hgamma_5_2',   'Hbeta_4_2',    'Halpha_3_2']
            self.SyntheticData_dict['H_Eqw']        = [50.0,            50.0,           250,             300.0]
            self.SyntheticData_dict['H_EqwErr']     = [1.0,             1.0,            12.5,            14]
            self.SyntheticData_dict['H_hlambda']    = [1.0,             1.0,            1.0,             1.0]
            self.SyntheticData_dict['H_error']      = self.SyntheticData_dict['H_Flux'] * 0.01
            
            self.SyntheticData_dict['He_Flux']      = array([0.10100783,    0.01691781,     0.03924855,     0.12725256,  0.03553524,    0.04162797])
            self.SyntheticData_dict['He_wave']      = array([ 3889.0,       4026.0,         4471.0,         5876.0,      6678.0,        7065.0])
            self.SyntheticData_dict['He_labels']    = ['He1_3889A',         'He1_4026A',   'He1_4471A',   'He1_5876A',  'He1_6678A',    'He1_7065A']
            self.SyntheticData_dict['He_Eqw']       = [10.0,                10.0,           10.0,           10.0,        10.0,          10.0]
            self.SyntheticData_dict['He_EqwErr']    = [1.0,                 1.0,            1.0,            1.0,         1.0,           1.0]
            self.SyntheticData_dict['He_hlambda']   = [1.0,                 1.0,            1.0,            1.0,         1.0,           1.0] 
            self.SyntheticData_dict['He_error']     = self.SyntheticData_dict['He_Flux'] * 0.02

            self.SyntheticData_dict['TOIII']        = 17000
            self.SyntheticData_dict['y_plus']       = 0.085
            self.SyntheticData_dict['n_e']          = 500.0
            self.SyntheticData_dict['a_He']         = 0.5
            self.SyntheticData_dict['tau']          = 1.0
            self.SyntheticData_dict['Te_0']         = 16000.0
            self.SyntheticData_dict['cHbeta']       = 0.1
            self.SyntheticData_dict['a_H']          = 1.0
            self.SyntheticData_dict['xi']           = 1.0
                                   
        return
    
    def Check_EmissionLinesObserved(self, Data_Dict):
        
        #Empty the lists of candidate lines for Hydrogen and Helium
        del self.Cand_Hydrogen_Lines[:]
        del self.Cand_Helium_Lines[:]
                
        #Loop through the hydrogen lines to store the properties of those we can use to perform the analysis
        Obs_HydrogenLabels          = Data_Dict['H_labels']
        for i in range(len(self.posHydrogen_Lines)):
            Line_Label                      = self.posHydrogen_Lines[i]
            if Line_Label in Obs_HydrogenLabels:
                Line_Index                      = Obs_HydrogenLabels.index(Line_Label)
                self.Flux_dict[Line_Label]      = Data_Dict['H_Flux'][Line_Index]   
                self.Error_dict[Line_Label]     = Data_Dict['H_error'][Line_Index]
                self.Wave_dict[Line_Label]      = Data_Dict['H_wave'][Line_Index]
                self.EqW_dict[Line_Label]       = Data_Dict['H_Eqw'][Line_Index]
                self.EqWerror_dict[Line_Label]  = Data_Dict['H_EqwErr'][Line_Index]
                self.hlambda_dict[Line_Label]   = Data_Dict['H_hlambda'][Line_Index]
                self.PynebCode_dict[Line_Label] = Line_Label[Line_Label.find('_')+1:len(Line_Label)]
                self.Cand_Hydrogen_Lines.append(Line_Label)
                
        #Loop through the helium lines to store the properties of those we can use to perform the analysis
        Obs_HeliumLabels                        = Data_Dict['He_labels']
        for i in range(len(self.posHelium_Lines)):
            Line_Label                          = self.posHelium_Lines[i]
            if Line_Label in Obs_HeliumLabels:
                Line_Index                      = Obs_HeliumLabels.index(Line_Label)
                self.Flux_dict[Line_Label]      = Data_Dict['He_Flux'][Line_Index]   
                self.Error_dict[Line_Label]     = Data_Dict['He_error'][Line_Index]
                self.Wave_dict[Line_Label]      = Data_Dict['He_wave'][Line_Index]
                self.EqW_dict[Line_Label]       = Data_Dict['He_Eqw'][Line_Index]
                self.EqWerror_dict[Line_Label]  = Data_Dict['He_EqwErr'][Line_Index]
                self.hlambda_dict[Line_Label]   = Data_Dict['He_hlambda'][Line_Index]
                self.PynebCode_dict[Line_Label] = Line_Label[Line_Label.find('_')+1:-1]+'.0'
                self.Cand_Helium_Lines.append(Line_Label)
        
        #Since the Hbeta line is not used for the fitting we remove it from the candidates lines list. However, its properties are still stored in the dictionaries
        self.Cand_Hydrogen_Lines.remove(self.HBeta_label)
        
        #Define number of lines variables to speed up the calculation
        self.nHydrogen              = len(self.Cand_Hydrogen_Lines)
        self.nHelium                = len(self.Cand_Helium_Lines)
        
        self.nHydrogen_range        = range(self.nHydrogen)
        self.nHelium_range          = range(self.nHelium)
                
        #Oxygen temperature prior
        self.TOIIIprior             = Data_Dict['TOIII']
        self.TOIIIprior_sigma       = self.TOIIIprior * 0.2
        
    def Preload_Data(self, Hbeta_Normalized = True):

        #Define the vectors where we store the physical parameters
        self.Flux_H_vector                          = zeros(self.nHydrogen)
        self.Error_H_vector                         = zeros(self.nHydrogen)
        self.Emissivity_H_vector                    = zeros(self.nHydrogen)
        self.Kalpha_vector                          = zeros(self.nHydrogen)
        self.flambda_H_vector                       = zeros(self.nHydrogen)
        #self.Eqw_H_vector                         = zeros(self.nHydrogen)
        #self.EqwError_H_vector                    = zeros(self.nHydrogen)
        self.hlambda_H_vector                       = ones(self.nHydrogen)

        self.Flux_He_vector                         = zeros(self.nHelium)
        self.Error_He_vector                        = zeros(self.nHelium)
        self.Emissivity_He_vector                   = zeros(self.nHelium)
        self.ftau_He_vector                         = zeros(self.nHelium)
        self.flambda_He_vector                      = zeros(self.nHelium)
        #self.Eqw_He_vector                        = zeros(self.nHelium)
        #self.EqwError_He_vector                   = zeros(self.nHelium)
        self.hlambda_He_vector                      = ones(self.nHelium)
      
        #Define HBeta values in advance
        self.Hbeta_Flux                             = self.Flux_dict[self.HBeta_label]
        self.Hbeta_error                            = self.Error_dict[self.HBeta_label]
        self.Hbeta_EW                               = self.EqW_dict[self.HBeta_label]
        self.Hbeta_EWerror                          = self.EqWerror_dict[self.HBeta_label]      
        self.hbeta_hlambda                          = self.hlambda_dict[self.HBeta_label]
      
        #Calculate in advance observed physical parameters vectors for Hydrogen lines
        for i in range(self.nHydrogen):
            Line_Label                              = self.Cand_Hydrogen_Lines[i]        
            self.Flux_H_vector[i]                   = self.Flux_dict[Line_Label]
            self.Error_H_vector[i]                  = self.Error_dict[Line_Label]
            self.hlambda_H_vector[i]                = self.hlambda_dict[Line_Label]
            self.flambda_H_vector[i]                = self.flambda_dict[Line_Label]

        for i in range(self.nHelium):
            Line_Label                              = self.Cand_Helium_Lines[i]
            self.Flux_He_vector[i]                  = self.Flux_dict[Line_Label]
            self.Error_He_vector[i]                 = self.Error_dict[Line_Label]
            self.flambda_He_vector[i]               = self.flambda_dict[Line_Label]
            self.hlambda_He_vector[i]               = self.hlambda_dict[Line_Label]             

        #Combine Hydrogen and Helium values into a single vector
        if Hbeta_Normalized: 
            self.H_He_Obs_Flux                      = concatenate([self.Flux_H_vector, self.Flux_He_vector])
            self.H_He_Obs_Error                     = concatenate([self.Error_H_vector, self.Error_He_vector])

        else:
            self.H_He_Obs_Flux                      = concatenate([self.Flux_H_vector, self.Flux_He_vector])    / self.Hbeta_Flux
            self.H_He_Obs_Error                     = concatenate([self.Error_H_vector, self.Error_He_vector])  
        
        #Dictionary with the vectors
        self.Data_Dict = {'Hbeta_Kalpha'    : None, 
                     'Hbeta_emis'           : None,
                     'Emissivity_H_vector'  : None,
                     'Kalpha_vector'        : None,
                     'Emissivity_He_vector' : None,
                     'ftau_He_vector'       : None,
                     'T_4'                  : None} 
        
    def Calculate_Parameters_Vectors(self, T_e, n_e, tau):    
        
        #Calculate in advance the T_4 parameter
        T_4 = T_e / 10000.0
        
        #Calculate the hbeta parameters
        self.Data_Dict['Hbeta_Kalpha']              = self.Kalpha_Ratio_H(T_4 = T_4, H_label=self.HBeta_label)
        self.Data_Dict['Hbeta_emis']                = self.H1.getEmissivity(T_e, n_e, label = self.PynebCode_dict[self.HBeta_label])

        #Calculate physical parameters for Hydrogen lines
        for i in self.nHydrogen_range:
            self.Emissivity_H_vector[i]             = self.H1.getEmissivity(T_e, n_e, label = self.PynebCode_dict[self.Cand_Hydrogen_Lines[i]])
            self.Kalpha_vector[i]                   = self.Kalpha_Ratio_H(T_4 = T_4, H_label=self.Cand_Hydrogen_Lines[i])
            
        #Calculate physical parameters for Helium lines
        for i in self.nHelium_range:
            self.Emissivity_He_vector[i]            = self.He1.getEmissivity(T_e, n_e, label = self.PynebCode_dict[self.Cand_Helium_Lines[i]])
            self.ftau_He_vector[i]                  = self.OpticalDepth_He(tau = tau, T_4 = T_4, n_e = n_e, He_label = self.Cand_Helium_Lines[i])

# #         self.Data_Dict = {'Hbeta_Kalpha'         : self.Hbeta_Kalpha, 
# #                      'Hbeta_emis'           : self.Hbeta_emis,
# #                      'Emissivity_H_vector'  : self.Emissivity_H_vector,
# #                      'Kalpha_vector'        : self.Kalpha_vector,
# #                      'Emissivity_He_vector' : self.Emissivity_He_vector,
# #                      'ftau_He_vector'       : self.ftau_He_vector} 
#        
#         self.Data_Dict['Emissivity_H_vector']   = self.Emissivity_H_vector
#         self.Data_Dict['Kalpha_vector']         = self.Kalpha_vector     
#         self.Data_Dict['Emissivity_He_vector']  = self.Emissivity_He_vector
#         self.Data_Dict['ftau_He_vector']        = self.ftau_He_vector
        
        return self.Data_Dict
    
    def Calculate_H_Parameters_Vectors(self, T_e, n_e, tau):    
        
        #Calculate in advance the T_4 parameter
        self.Data_Dict['T_4'] = T_e / 10000.0
        
        #Calculate the hbeta parameters
        self.Data_Dict['Hbeta_Kalpha']              = self.Kalpha_Ratio_H(T_4 = self.Data_Dict['T_4'], H_label=self.HBeta_label)
        self.Data_Dict['Hbeta_emis']                = self.H1.getEmissivity(T_e, n_e, label = self.PynebCode_dict[self.HBeta_label])

        #Calculate physical parameters for Hydrogen lines
        for i in self.nHydrogen_range:
            self.Emissivity_H_vector[i]             = self.H1.getEmissivity(T_e, n_e, label = self.PynebCode_dict[self.Cand_Hydrogen_Lines[i]])
            self.Kalpha_vector[i]                   = self.Kalpha_Ratio_H(T_4 = self.Data_Dict['T_4'], H_label=self.Cand_Hydrogen_Lines[i])
        
        self.Data_Dict['Emissivity_H_vector']       = self.Emissivity_H_vector
        self.Data_Dict['Kalpha_vector']             = self.Kalpha_vector
                
        return self.Data_Dict    
    
    def Calculate_He_Parameters_Vectors(self, T_e, n_e, tau):
    
        #Calculate physical parameters for Helium lines
        for i in self.nHelium_range:
            self.Emissivity_He_vector[i]            = self.He1.getEmissivity(T_e, n_e, label = self.PynebCode_dict[self.Cand_Helium_Lines[i]])
            self.ftau_He_vector[i]                  = self.OpticalDepth_He(tau = tau, T_4 = self.Data_Dict['T_4'], n_e = n_e, He_label = self.Cand_Helium_Lines[i])    
        
        self.Data_Dict['Emissivity_He_vector']      = self.Emissivity_He_vector
        self.Data_Dict['ftau_He_vector']            = self.ftau_He_vector
        
        return self.Data_Dict

    def H_Flux_theo(self, xi, cHbeta, a_H, data_dict):
                
        #Calculate the emissivities for each of the lines for the given temperature and density
        Emissivities_module = data_dict['Emissivity_H_vector'] / data_dict['Hbeta_emis'] 
        
        #Calculate the Collisional excitation fraction
        CR_Module           = (1.0 + 0.0001* xi *data_dict['Kalpha_vector']) / (1.0 + 0.0001* xi * data_dict['Hbeta_Kalpha'] )
        
        #Calculate the reddening component
        f_module            = power(10, -1 * self.flambda_H_vector * cHbeta)
        
        #Calculate the Hbeta normalization module
        EW_Hbeta_module     = (self.Hbeta_EW + a_H) / self.Hbeta_EW
        
        #Calculate stellar absorption module
        a_H_module          = (a_H * self.hlambda_H_vector) / (self.Hbeta_EW * self.hbeta_hlambda)
        
        #Calculate theoretical Hydrogen flux for each emission line
        H_Flux              = Emissivities_module * CR_Module * f_module * EW_Hbeta_module - a_H_module
             
        return H_Flux

    def He_Flux_theo_nof(self, xi, cHbeta, a_H, a_He, y_plus, data_dict):
                      
        #Calculate the emissivities for each of the lines for the given temperature and density
        Emissivities_module = data_dict['Emissivity_He_vector'] / data_dict['Hbeta_emis']
        
        #Calculate the collisional excitation fraction
        CR_Module           = 1 / (1.0 + 0.0001* xi * data_dict['Hbeta_Kalpha'])

        #Calculate the reddening component
        f_module            = power(10, -1 * self.flambda_He_vector * cHbeta)

        #Calculate the Hbeta normalization module
        EW_Hbeta_module     = (self.Hbeta_EW + a_H) / self.Hbeta_EW
        
        #Calculate stellar absorption module
        a_He_module         = (a_He * self.hlambda_He_vector) / (self.Hbeta_EW * self.hbeta_hlambda)
             
        #Calculate theoretical Hydrogen flux for each emission line
        He_Flux             = y_plus * Emissivities_module * data_dict['ftau_He_vector'] * CR_Module * f_module * EW_Hbeta_module - a_He_module

        return He_Flux
               
    def get_flambda_dict(self, lines_labels, lines_wavelengths, R_v=3.1):
    
        x_true          = 1.0 / (array(lines_wavelengths) / 10000.0)
        y               = x_true - 1.82
    
        y_coeffs        = array([ones(len(y)), y, power(y, 2), power(y, 3), power(y, 4), power(y, 5), power(y, 6), power(y, 7)])
        a_coeffs        = array([1, 0.17699,    -0.50447,   -0.02427,   0.72085,    0.01979,    -0.77530,   0.32999])
        b_coeffs        = array([0, 1.41338,    2.28305,   1.07233,   -5.38434,    -0.62251,    5.30260,   -2.09002])
        
        a_x             = dot(a_coeffs,y_coeffs)
        b_x             = dot(b_coeffs,y_coeffs)
        
        X_x             = a_x + b_x / R_v
        
        y_beta          = (1 / (4862.683 / 10000)) - 1.82
        y_beta_coeffs   = array([1, y_beta, power(y_beta, 2), power(y_beta, 3), power(y_beta, 4), power(y_beta, 5), power(y_beta, 6), power(y_beta, 7)])
        
        X_x_beta        = dot(a_coeffs,y_beta_coeffs) + dot(b_coeffs,y_beta_coeffs) / R_v
    
        f               = X_x / X_x_beta - 1
        
        return dict(zip(lines_labels , f))
         
    def Kalpha_Ratio_H(self, T_4, H_label):
                
        K_alpha_Ratio   = sum(self.Coef_Kalpha_dict[H_label][0] * exp(self.Coef_Kalpha_dict[H_label][1] / T_4) * power(T_4, self.Coef_Kalpha_dict[H_label][2]))
        
        return K_alpha_Ratio
    
    def OpticalDepth_He(self, tau, T_4, n_e, He_label):
                        
        f_tau   = 1 + (tau/2) * (self.Coef_ftau_dict[He_label][0] + (self.Coef_ftau_dict[He_label][1] + self.Coef_ftau_dict[He_label][2]*n_e + self.Coef_ftau_dict[He_label][3]*n_e*n_e) * T_4)

        return f_tau       
示例#5
0
    def load_elements(self):

        #Set atomic data
        #atomicData.setDataFile('he_i_rec_Pal12-Pal13.fits')
        atomicData.setDataFile('s_iii_coll_HRS12.dat')

        #Default: 's_iii_atom_PKW09.dat'
        'S3: All energy and A values: Podobedova, Kelleher, and Wiese 2009, J. Phys. Chem. Ref. Data, Vol.'
        'S3: collision strengths: Tayal & Gupta 1999, ApJ, 526, 544'

        #New Atomic data s_iii_coll_HRS12.dat
        'S3: All energy and A values: Podobedova, Kelleher, and Wiese 2009, J. Phys. Chem. Ref. Data, Vol.'
        'S3: collision strengths: Hudson, Ramsbottom & Scott 2012, ApJ, 750, 65'

        #Declare ions
        self.S2_atom = Atom('S', 2)
        self.S3_atom = Atom('S', 3)
        self.Ar3_atom = Atom('Ar', 3)
        self.Ar4_atom = Atom('Ar', 4)
        self.N2_atom = Atom('N', 2)
        self.O2_atom = Atom('O', 2)
        self.O3_atom = Atom('O', 3)
        self.H1_atom = RecAtom('H', 1)
        self.He1_atom = RecAtom('He', 1)
        self.He2_atom = RecAtom('He', 2)

        #Pyneb objects
        self.diags = Diagnostics()

        #Ohrs 2016 relation for the OI_SI gradient
        self.logSI_OI_Gradient = random.normal(
            -1.53, 0.05, size=self.MC_array_len
        )  # random.normal(-1.78,  0.03, size = self.MC_array_len)
        self.OI_SI = power(10, -self.logSI_OI_Gradient)

        #Theoretical ratios
        self.S3_ratio = self.S3_atom.getEmissivity(
            10000, 100, wave=9531) / self.S3_atom.getEmissivity(
                10000, 100, wave=9069)
        self.S3_9000_ratio = random.normal(
            self.S3_atom.getEmissivity(10000, 100, wave=9531) /
            self.S3_atom.getEmissivity(10000, 100, wave=9069),
            0.01,
            size=self.MC_array_len)
        self.N2_6000_ratio = self.N2_atom.getEmissivity(
            10000, 100, wave=6584) / self.N2_atom.getEmissivity(
                10000, 100, wave=6548)
        self.O3_5000_ratio = self.O3_atom.getEmissivity(
            10000, 100, wave=5007) / self.O3_atom.getEmissivity(
                10000, 100, wave=4959)

        #Factors to speed calculations
        self.lines_factors = {}
        self.lines_factors['S3_9069A'] = 1 + self.S3_ratio
        self.lines_factors['S3_9531A'] = 1 + 1 / self.S3_ratio

        #Cloudy models for the SIV contribution

        self.m_SIV_correction = random.normal(1.1628,
                                              0.00559,
                                              size=self.MC_array_len)
        self.n_SIV_correction = random.normal(0.0470,
                                              0.0097,
                                              size=self.MC_array_len)
        #self.m_SIV_correction   = random.normal(1.109,  0.01, size = self.MC_array_len)
        #self.n_SIV_correction   = random.normal(0.135,  0.0173, size = self.MC_array_len)

        #CHAOS relation TNII-TSIII
        #T[SIII]  = 1.312(+-0.075)T[NII]-0.313(+-0.058)
        #TNII     = (0.762+-0.044)*TSIII  + 0.239+-0.046
        self.m_TNII_correction = random.normal(0.762,
                                               0.044,
                                               size=self.MC_array_len)
        self.n_TNII_correction = random.normal(0.239,
                                               0.046,
                                               size=self.MC_array_len)

        #Truncated gaussian for the density
        lower_trunc, upper_trunc = (1.0 - 50.0) / 25.0, (100 - 50) / 25.0
        self.Truncated_gaussian = truncnorm(lower_trunc,
                                            upper_trunc,
                                            loc=50,
                                            scale=25)

        print '-Elements loaded\n'

        return
示例#6
0
class Chemical_Analysis_pyneb():
    def __init__(self):

        self.MC_array_len = 1000
        self.MC_warning_limit = self.MC_array_len * 0.1

        self.Hbeta_label = 'H1_4861A'

    def load_elements(self):

        #Set atomic data
        #atomicData.setDataFile('he_i_rec_Pal12-Pal13.fits')
        atomicData.setDataFile('s_iii_coll_HRS12.dat')

        #Default: 's_iii_atom_PKW09.dat'
        'S3: All energy and A values: Podobedova, Kelleher, and Wiese 2009, J. Phys. Chem. Ref. Data, Vol.'
        'S3: collision strengths: Tayal & Gupta 1999, ApJ, 526, 544'

        #New Atomic data s_iii_coll_HRS12.dat
        'S3: All energy and A values: Podobedova, Kelleher, and Wiese 2009, J. Phys. Chem. Ref. Data, Vol.'
        'S3: collision strengths: Hudson, Ramsbottom & Scott 2012, ApJ, 750, 65'

        #Declare ions
        self.S2_atom = Atom('S', 2)
        self.S3_atom = Atom('S', 3)
        self.Ar3_atom = Atom('Ar', 3)
        self.Ar4_atom = Atom('Ar', 4)
        self.N2_atom = Atom('N', 2)
        self.O2_atom = Atom('O', 2)
        self.O3_atom = Atom('O', 3)
        self.H1_atom = RecAtom('H', 1)
        self.He1_atom = RecAtom('He', 1)
        self.He2_atom = RecAtom('He', 2)

        #Pyneb objects
        self.diags = Diagnostics()

        #Ohrs 2016 relation for the OI_SI gradient
        self.logSI_OI_Gradient = random.normal(
            -1.53, 0.05, size=self.MC_array_len
        )  # random.normal(-1.78,  0.03, size = self.MC_array_len)
        self.OI_SI = power(10, -self.logSI_OI_Gradient)

        #Theoretical ratios
        self.S3_ratio = self.S3_atom.getEmissivity(
            10000, 100, wave=9531) / self.S3_atom.getEmissivity(
                10000, 100, wave=9069)
        self.S3_9000_ratio = random.normal(
            self.S3_atom.getEmissivity(10000, 100, wave=9531) /
            self.S3_atom.getEmissivity(10000, 100, wave=9069),
            0.01,
            size=self.MC_array_len)
        self.N2_6000_ratio = self.N2_atom.getEmissivity(
            10000, 100, wave=6584) / self.N2_atom.getEmissivity(
                10000, 100, wave=6548)
        self.O3_5000_ratio = self.O3_atom.getEmissivity(
            10000, 100, wave=5007) / self.O3_atom.getEmissivity(
                10000, 100, wave=4959)

        #Factors to speed calculations
        self.lines_factors = {}
        self.lines_factors['S3_9069A'] = 1 + self.S3_ratio
        self.lines_factors['S3_9531A'] = 1 + 1 / self.S3_ratio

        #Cloudy models for the SIV contribution

        self.m_SIV_correction = random.normal(1.1628,
                                              0.00559,
                                              size=self.MC_array_len)
        self.n_SIV_correction = random.normal(0.0470,
                                              0.0097,
                                              size=self.MC_array_len)
        #self.m_SIV_correction   = random.normal(1.109,  0.01, size = self.MC_array_len)
        #self.n_SIV_correction   = random.normal(0.135,  0.0173, size = self.MC_array_len)

        #CHAOS relation TNII-TSIII
        #T[SIII]  = 1.312(+-0.075)T[NII]-0.313(+-0.058)
        #TNII     = (0.762+-0.044)*TSIII  + 0.239+-0.046
        self.m_TNII_correction = random.normal(0.762,
                                               0.044,
                                               size=self.MC_array_len)
        self.n_TNII_correction = random.normal(0.239,
                                               0.046,
                                               size=self.MC_array_len)

        #Truncated gaussian for the density
        lower_trunc, upper_trunc = (1.0 - 50.0) / 25.0, (100 - 50) / 25.0
        self.Truncated_gaussian = truncnorm(lower_trunc,
                                            upper_trunc,
                                            loc=50,
                                            scale=25)

        print '-Elements loaded\n'

        return

    def declare_object(self, lines_log_frame):

        #List of all parameters
        #         lineRatios      = ['R_SII', 'R_SII_prime', 'R_SIII', 'R_NII', 'R_OII', 'R_OII_prime', 'R_OIII']
        #         elecProperties  = ['neSII', 'neOII', 'TeOII', 'TeSII', 'TeNII', 'TeOIII', 'TeSIII', 'TeOII_from_TeOIII', 'TeNII_from_TeOIII', 'TeSIII_from_TeOIII', 'TeOIII_from_TeSIII']
        #         ionicAbund      = ['SII_HII', 'SIII_HII', 'SIV_HII', 'OII_HII', 'OII_HII_3279A', 'OII_HII_7319A', 'NII_HII', 'ArIII_HII', 'ArIV_HII', 'HeII_HII_from_O',
        #                             'HeIII_HII_from_O', 'HeII_HII_from_S', 'HeIII_HII_from_S']
        #         elemAbund       = ['SI_HI', 'OI_HI', 'NI_OI', 'NI_HI', 'HeI_HI_from_O', 'HeI_HI_from_S', 'Ymass_O', 'Ymass_S']

        self.abunData = Series()

        self.Hbeta_flux = random.normal(
            lines_log_frame.loc['H1_4861A', 'line_Int'].nominal_value,
            lines_log_frame.loc['H1_4861A', 'line_Int'].std_dev,
            size=self.MC_array_len)

        self.low_density_dist = self.Truncated_gaussian.rvs(self.MC_array_len)

        #Generate a dictionary to store the random array for all lines
        self.lines_dict = OrderedDict()

        #Dictionary with lines which my need special treatements
        Blended_lines = {}
        Blended_lines['O2_3726A'] = ('O2_3726A', 'O2_3729A')
        Blended_lines['O2_7319A'] = ('O2_7319A', 'O2_7330A')
        NoError_lines = {}
        NoError_lines['N2_6548A'] = ('N2_6548A')

        #Generate
        for line in lines_log_frame.index.values:

            #Start with the particular cases: Blended lines
            if line in Blended_lines:
                blended_lines = Blended_lines[line]

                if set(lines_log_frame.index) >= set(blended_lines):
                    label_line = line + '+'

                    #Lines are blended we use integrated flux else we add the individual integrated
                    if lines_log_frame.loc[blended_lines[0],
                                           'flux_intg'] == lines_log_frame.loc[
                                               blended_lines[1]]['flux_intg']:
                        flux_line = lines_log_frame.loc[
                            blended_lines[0],
                            'line_IntBrute_dered'].nominal_value
                        error_line = lines_log_frame.loc[
                            blended_lines[0], 'line_IntBrute_dered'].std_dev

                    else:
                        line_sum = lines_log_frame.loc[
                            blended_lines[0],
                            'line_IntBrute_dered'] + lines_log_frame.loc[
                                blended_lines[1], 'line_IntBrute_dered']
                        flux_line = line_sum.nominal_value
                        error_line = line_sum.std_dev

                #Case only one of the lines was measured
                else:
                    label_line = line
                    flux_line = lines_log_frame.loc[line,
                                                    'line_Int'].nominal_value
                    error_line = lines_log_frame.loc[line, 'line_Int'].std_dev

            #Lines with not error
            elif (line in NoError_lines) and (
                    lines_log_frame.loc[line, 'line_Int'].std_dev == 0.0):
                label_line = line
                flux_line = lines_log_frame.loc[line, 'line_Int'].nominal_value
                error_line = lines_log_frame.loc[
                    'N2_6584A', 'line_Int'].std_dev / self.N2_6000_ratio

            #None-issue lines
            else:
                label_line = line
                flux_line = lines_log_frame.loc[line, 'line_Int'].nominal_value
                error_line = lines_log_frame.loc[line, 'line_Int'].std_dev

            #Generate line gaussian shaped array
            self.lines_dict[label_line] = random.normal(flux_line,
                                                        error_line,
                                                        size=self.MC_array_len)

        return

    def den_temp_diagnostic_pair(self,
                                 diagProperties,
                                 den_distribution=None,
                                 atom_temp=None):

        #Check if all necessary lines are there
        if self.lines_dict.viewkeys() >= set(
                diagProperties['required_denlines'] +
                diagProperties['required_temlines']):

            if den_distribution is None:
                den_ratio = numexpr.evaluate(diagProperties['den_ratio'],
                                             self.lines_dict)
                tem_ratio = numexpr.evaluate(diagProperties['tem_ratio'],
                                             self.lines_dict)

                Te, ne = self.diags.getCrossTemDen(
                    diag_tem=diagProperties['diag_tem'],
                    diag_den=diagProperties['diag_den'],
                    value_tem=tem_ratio,
                    value_den=den_ratio)

            else:
                tem_ratio = numexpr.evaluate(diagProperties['tem_ratio'],
                                             self.lines_dict)
                Te = atom_temp.getTemDen(
                    tem_ratio,
                    den=den_distribution,
                    to_eval=diagProperties['atom_temdiag'])
                ne = den_distribution

        #else empty (nan) arrays
        else:
            Te, ne = empty(self.MC_array_len), empty(self.MC_array_len)
            Te[:], ne[:] = np_nan, np_nan

        return Te, ne

    def determine_electron_parameters(self, objectData):

        #----------To start make sure we are not in the very low density regimes,
        low_density_dist = None
        if self.lines_dict.viewkeys() >= {'S2_6716A', 'S2_6731A'}:
            S2_ratio = mean(self.lines_dict['S2_6716A']) / mean(
                self.lines_dict['S2_6731A'])
            if S2_ratio > 1.35:
                print '--Low density object'
                lower, upper, mu, sigma = 1.0, 100.0, 50.0, 25.0
                X_func = truncnorm((lower - mu) / sigma, (upper - mu) / sigma,
                                   loc=mu,
                                   scale=sigma)
                low_density_dist = X_func.rvs(self.MC_array_len)
                self.abunData['neSII'] = low_density_dist
                if low_density_dist is None:
                    print 'WARNING: QUE PASA!!!!!!'
                    print lower, upper, mu, sigma
                    print xrange

        #-----------Sulfur
        diagProperties = {}
        diagProperties['required_denlines'] = ['S2_6716A', 'S2_6731A']
        diagProperties['required_temlines'] = [
            'S3_9069A', 'S3_9531A', 'S3_6312A'
        ] if objectData.SIII_lines == 'BOTH' else [objectData.SIII_lines
                                                   ] + ['S3_6312A']
        diagProperties['diag_den'] = '[SII] 6731/6716'
        diagProperties['diag_tem'] = '[SIII] 6312/9200+'
        diagProperties['atom_temdiag'] = 'L(6312)/(L(9069)+L(9531))'
        diagProperties['den_ratio'] = 'S2_6731A/S2_6716A'
        diagProperties[
            'tem_ratio'] = 'S3_6312A/(S3_9069A+S3_9531A)' if objectData.SIII_lines == 'BOTH' else 'S3_6312A/({valid_line} * {line_factor})'.format(
                valid_line=objectData.SIII_lines,
                line_factor=self.lines_factors[objectData.SIII_lines])

        if '*' in diagProperties['tem_ratio']:
            print '-- Using factor', diagProperties['tem_ratio']

        S3_lines = [
            'S3_9069A', 'S3_9531A', 'S3_6312A'
        ] if objectData.SIII_lines == 'BOTH' else [objectData.SIII_lines
                                                   ] + ['S3_6312A']

        #--Calculate NeSII and TeSIII
        self.abunData['TeSIII'], neSII_TSIII = self.den_temp_diagnostic_pair(
            diagProperties, low_density_dist, atom_temp=self.S3_atom)

        #--Determine empirical TOIII from TSIII  #Epm & Diaz 2005
        self.abunData['TeOIII_from_TeSIII'] = (
            0.95 * self.abunData.TeSIII / 10000 + 0.076) * 10000

        diagProperties = {}
        diagProperties['required_denlines'] = ['S2_6716A', 'S2_6731A']
        diagProperties['required_temlines'] = ['S2_4069A', 'S2_4076A']
        diagProperties['diag_den'] = '[SII] 6731/6716'
        diagProperties['diag_tem'] = '[SII] 4069/4076'
        diagProperties['atom_temdiag'] = 'L(4069)/L(4076)'
        diagProperties['den_ratio'] = 'S2_6731A/S2_6716A'
        diagProperties['tem_ratio'] = 'S2_4069A/S2_4076A'

        #       #--Calculate NeSII and TeSII
        self.abunData['TeSII'], neSII_TSII = self.den_temp_diagnostic_pair(
            diagProperties, low_density_dist, atom_temp=self.S2_atom)

        #-----------Oxygen
        diagProperties = {}
        diagProperties['required_denlines'] = ['S2_6716A', 'S2_6731A']
        diagProperties['required_temlines'] = [
            'O3_4363A', 'O3_4959A', 'O3_5007A'
        ]
        diagProperties['diag_den'] = '[SII] 6731/6716'
        diagProperties['diag_tem'] = '[OIII] 4363/5007+'
        diagProperties['atom_temdiag'] = 'L(4363)/(L(5007)+L(4959))'
        diagProperties['den_ratio'] = 'S2_6731A/S2_6716A'
        diagProperties['tem_ratio'] = 'O3_4363A/(O3_4959A+O3_5007A)'

        #--Calculate NeSII and TeOIII
        self.abunData['TeOIII'], neSII_OIII = self.den_temp_diagnostic_pair(
            diagProperties, low_density_dist, atom_temp=self.O3_atom)

        #--Determine empirical TOIII from TSIII #Epm & Diaz 2005
        self.abunData['TeSIII_from_TeOIII'] = (
            1.05 * self.abunData.TeOIII / 10000 - 0.08) * 10000

        #--Determine empirical TOII from TOIII #Dors Jr 2006
        self.abunData['TeOII_from_TeOIII'] = (1.397 / (
            (1 / (self.abunData.TeOIII / 10000)) + 0.385)) * 10000

        #--Determine empirical TNII from TOIII #Epm 2014
        self.abunData['TeNII_from_TeOIII'] = (1.452 / (
            (1 / (self.abunData.TeOIII / 10000)) + 0.479)) * 10000

        #-----------Nitrogen
        diagProperties = {}
        diagProperties['required_denlines'] = ['S2_6716A', 'S2_6731A']
        diagProperties['required_temlines'] = [
            'N2_5755A', 'N2_6548A', 'N2_6584A'
        ]
        diagProperties['diag_den'] = '[SII] 6731/6716'
        diagProperties['diag_tem'] = '[NII] 5755/6584+'
        diagProperties['atom_temdiag'] = '(L(6584) + L(6548)) / L(5755)'
        diagProperties['den_ratio'] = 'S2_6731A/S2_6716A'
        diagProperties['tem_ratio'] = '(N2_6548A+N2_6584A)/N2_5755A'

        #--Calculate Ne_SII and Te_NII
        self.abunData['TeNII'], neSII_TNII = self.den_temp_diagnostic_pair(
            diagProperties, low_density_dist, atom_temp=self.N2_atom)

        #Assign object density from lines or from the low density distribution
        #--This code favors the neSII calculated from SIII-SII line pai+
        if 'neSII' not in self.abunData:
            if np_sum(isnan(neSII_TSIII)) < self.MC_array_len:
                self.abunData['neSII'] = neSII_TSIII
            elif np_sum(isnan(neSII_OIII)) < self.MC_array_len:
                self.abunData['neSII'] = neSII_OIII
            else:
                self.abunData['neSII'] = neSII_TSIII

        #--Check if some results contain nan entries
        nanCount = OrderedDict()
        for electron_parameter in self.abunData.index:
            variable_array = self.abunData[electron_parameter]
            nan_count = np_sum(isnan(variable_array))
            if nan_count > self.MC_array_len * 0.90:
                self.abunData.drop(electron_parameter, inplace=True)
            elif nan_count > 0:
                mag, error = nanmean(
                    self.abunData[electron_parameter]), nanstd(
                        self.abunData[electron_parameter])
                self.abunData[electron_parameter] = random.normal(
                    mag, error, size=self.MC_array_len)
                if nan_count > self.MC_warning_limit:
                    nanCount[electron_parameter] = nan_count

        #Display calculations with issues
        if len(nanCount) > 0:
            print '-Issues calculating:'
            for element in nanCount:
                print '--', element, nanCount[element]

        return

    def determine_ionic_abundance(self, abund_code, atom, diagnos_eval,
                                  diagnos_mag, tem, den):

        try:
            hbeta_flux = self.Hbeta_flux
        except AttributeError:
            hbeta_flux = self.H1_atom.getEmissivity(tem=tem,
                                                    den=den,
                                                    label='4_2',
                                                    product=False)
            print '--Warning using theoretical Hbeta emissivity'

        #Ionic abundance calculation using pyneb
        ionic_abund = atom.getIonAbundance(int_ratio=diagnos_mag,
                                           tem=tem,
                                           den=den,
                                           to_eval=diagnos_eval,
                                           Hbeta=hbeta_flux)

        #Evaluate the nan array
        nan_idcs = isnan(ionic_abund)
        nan_count = np_sum(nan_idcs)

        #Directly save if not nan
        if nan_count == 0:
            self.abunData[abund_code] = ionic_abund

        #Remove the nan entries performing a normal distribution
        elif nan_count < 0.90 * self.MC_array_len:
            mag, error = nanmean(ionic_abund), nanstd(ionic_abund)

            #Generate truncated array to store the data
            a, b = (0 - mag) / error, (1000 * mag - mag) / error
            new_samples = truncnorm(a, b, loc=mag,
                                    scale=error).rvs(size=nan_count)

            #Replace nan entries
            ionic_abund[nan_idcs] = new_samples
            self.abunData[abund_code] = ionic_abund

            if nan_count > self.MC_warning_limit:
                print '-- {} calculated with {}'.format(abund_code, nan_count)

        return

    def check_obsLines(self, lines_list, just_one_line=False):

        #WARNING it would be better something that reads a standard preference over some.
        eval_lines = map(
            lambda x: 'L({})'.format(x[x.find('_') + 1:len(x) - 1]),
            lines_list)  #Right format for pyneb eval: Ar3_7751A -> L(7751)
        diagnos_eval = None

        #Case all lines are there
        if self.lines_dict.viewkeys() >= set(lines_list):
            diagnos_mag = zeros(self.MC_array_len)
            for i in range(len(lines_list)):
                diagnos_mag += self.lines_dict[lines_list[i]]
            diagnos_eval = '+'.join(eval_lines)

        #Case we can use any line: #WARNING last line is favoured
        elif just_one_line:
            diagnos_mag = zeros(self.MC_array_len)
            for i in range(len(lines_list)):
                if lines_list[i] in self.lines_dict:
                    diagnos_mag = self.lines_dict[lines_list[i]]
                    diagnos_eval = eval_lines[i]

        #Case none of the lines
        if diagnos_eval is None:
            diagnos_mag = self.generate_nan_array()
            diagnos_eval = '+'.join(eval_lines)

        return diagnos_eval, diagnos_mag

    def argon_abundance_scheme(self, Tlow, Thigh, ne):

        #Calculate the Ar_+2 abundance according to the lines observed
        Ar3_lines = ['Ar3_7136A', 'Ar3_7751A']
        diagnos_eval, diagnos_mag = self.check_obsLines(Ar3_lines,
                                                        just_one_line=True)
        self.determine_ionic_abundance('ArIII_HII', self.Ar3_atom,
                                       diagnos_eval, diagnos_mag, Tlow, ne)

        #Calculate the Ar_+3 abundance according to the lines observed
        Ar4_lines = ['Ar4_4740A', 'Ar4_4711A']
        diagnos_eval, diagnos_mag = self.check_obsLines(Ar4_lines,
                                                        just_one_line=True)
        self.determine_ionic_abundance('ArIV_HII', self.Ar4_atom, diagnos_eval,
                                       diagnos_mag, Thigh, ne)

    def oxygen_abundance_scheme(self, Tlow, Thigh, ne):

        #Calculate the O_+1 abundances from 3200+ lines
        O2_lines = ['O2_3726A+']
        diagnos_eval, diagnos_mag = self.check_obsLines(O2_lines)
        diagnos_eval = 'L(3726)+L(3729)'
        self.determine_ionic_abundance('OII_HII_3279A', self.O2_atom,
                                       diagnos_eval, diagnos_mag, Tlow, ne)

        #Calculate the O_+1 abundances from 7300+ lines
        O2_lines = ['O2_7319A+']
        diagnos_eval, diagnos_mag = self.check_obsLines(O2_lines)
        diagnos_eval = 'L(7319)+L(7330)'
        self.determine_ionic_abundance('OII_HII_7319A', self.O2_atom,
                                       diagnos_eval, diagnos_mag, Tlow, ne)

        #--Correction for recombination contribution Liu2000
        if 'OII_HII_7319A' in self.abunData:

            try:
                hbeta_flux = self.Hbeta_flux
            except AttributeError:
                hbeta_flux = self.H1_atom.getEmissivity(tem=Tlow,
                                                        den=ne,
                                                        label='4_2',
                                                        product=False)
                print '--Warning using theoretical Hbeta emissivity'

            Lines_Correction = (9.36 * power((Tlow / 10000), 0.44) *
                                self.abunData.OII_HII_7319A) * hbeta_flux
            ratio = self.lines_dict['O2_7319A+'] - Lines_Correction
            self.determine_ionic_abundance('OII_HII_7319A', self.O2_atom,
                                           diagnos_eval, ratio, Tlow, ne)

        #Get the ratios for empirical relation between OII lines
        if 'O2_3726A+' in self.lines_dict:
            self.abunData[
                'O_R3200'] = self.lines_dict['O2_3726A+'] / self.Hbeta_flux
            print 'O_R3200', mean(self.abunData['O_R3200'])
            print 'OII_HII_3279A', mean(self.abunData['OII_HII_3279A'])
            print 'Original flux', mean(self.lines_dict['O2_3726A+'])

        if 'O2_7319A+' in self.lines_dict:
            self.abunData[
                'O_R7300'] = self.lines_dict['O2_7319A+'] / self.Hbeta_flux
            print 'OII_HII_7319A', mean(self.abunData['OII_HII_7319A'])
        if self.lines_dict.viewkeys() >= set(['O3_5007A']):
            self.abunData[
                'O_R3'] = self.lines_dict['O3_5007A'] / self.Hbeta_flux

        #Calculate the abundance from the empirical O_R3200_ffO2
        if set(self.abunData.index) >= {'O_R7300', 'O_R3'}:
            logRO2 = 1.913 + log10(self.abunData['O_R7300']) - 0.374 * log10(
                self.abunData['O_R3']) / 0.806
            print 'logRO2', mean(logRO2)
            RO2 = power(10, logRO2)
            self.abunData['O_R3200_ffO2'] = RO2
            print 'O_R3200_ffO2', mean(self.abunData['O_R3200_ffO2'])
            print 'RO2*Hbeta', mean(RO2 * self.Hbeta_flux)
            diagnos_eval = 'L(3726)+L(3729)'
            self.determine_ionic_abundance('OII_HII_ffO2', self.O2_atom,
                                           diagnos_eval, RO2 * self.Hbeta_flux,
                                           Tlow, ne)
            print 'OII_HII_ffO2', mean(self.abunData['OII_HII_ffO2'])

        #Calculate the O_+2 abundance
        O3_lines = ['O3_4959A', 'O3_5007A']
        diagnos_eval, diagnos_mag = self.check_obsLines(O3_lines)
        self.determine_ionic_abundance('OIII_HII', self.O3_atom, diagnos_eval,
                                       diagnos_mag, Thigh, ne)

        #Determine the O/H abundance (favoring the value from OII_HII
        if set(self.abunData.index) >= {'OII_HII_3279A', 'OIII_HII'}:
            self.abunData['OII_HII'] = self.abunData['OII_HII_3279A']
            self.abunData['OI_HI'] = self.abunData[
                'OII_HII_3279A'] + self.abunData['OIII_HII']
        elif set(self.abunData.index) >= {'OII_HII_7319A', 'OIII_HII'}:
            self.abunData['OII_HII'] = self.abunData['OII_HII_7319A']
            self.abunData['OI_HI'] = self.abunData[
                'OII_HII_7319A'] + self.abunData['OIII_HII']

        if set(self.abunData.index) >= {'OII_HII_ffO2', 'OIII_HII'}:
            if set(self.abunData.index) >= {'OII_HII_3279A'}:
                self.abunData['OI_HI_ff02'] = self.abunData[
                    'OII_HII_3279A'] + self.abunData['OIII_HII']
            else:
                self.abunData['OI_HI_ff02'] = self.abunData[
                    'OII_HII_ffO2'] + self.abunData['OIII_HII']

        return

    def nitrogen_abundance_scheme(self, Tlow, ne):

        #Calculate TNII temperature from the CHAOS relation
        T_NII = Tlow  #self.m_TNII_correction * Tlow + self.n_TNII_correction

        #Calculate the N+1 abundance
        N2_lines = ['N2_6548A', 'N2_6584A']
        diagnos_eval, diagnos_mag = self.check_obsLines(N2_lines)
        self.determine_ionic_abundance('NII_HII', self.N2_atom, diagnos_eval,
                                       diagnos_mag, T_NII, ne)

        #Calculate NI_HI using the OI_HI
        if set(self.abunData.index) >= {'NII_HII', 'OI_HI'}:

            #Compute  NI_OI
            self.abunData[
                'NI_OI'] = self.abunData['NII_HII'] / self.abunData['OII_HII']
            self.abunData[
                'NI_HI'] = self.abunData['NI_OI'] * self.abunData['OI_HI']

#             #Repeat calculation if 5755 line was observed to include the recombination contribution
#             if self.lines_dict.viewkeys() >= {'N2_5755A'}:
#
#                 NIII_HI             = self.abunData.NI_HI - self.abunData['NII_HII']
#                 Lines_Correction    = 3.19 * power((Thigh/10000), 0.30) * NIII_HI * self.Hbeta_flux
#                 self.abunData['TNII'], nSII = self.diags.getCrossTemDen(diag_tem = '[NII] 5755/6584+',
#                                                                         diag_den  = '[SII] 6731/6716',
#                                                                         value_tem = (self.lines_dict['N2_5755A'] - Lines_Correction)/(self.lines_dict['N2_6548A'] + self.lines_dict['N2_6584A']),
#                                                                         value_den = self.lines_dict['S2_6731A']/self.lines_dict['S2_6716A'])
#
#                 Ratio = self.lines_dict['N2_6548A'] + self.lines_dict['N2_6584A']
#                 self.determine_ionic_abundance('NII_HII', self.N2_atom, Ratio, diagnos_mag, self.abunData['TNII'], ne)
#
#                 self.abunData['NI_OI'] = self.abunData['NII_HII'] / self.abunData['OII_HII']
#                 self.abunData['NI_HI'] = self.abunData['NI_OI'] * self.abunData['OI_HI']

        return

    def sulfur_abundance_scheme(self, Tlow, ne, SIII_lines_to_use):

        print 'Metiendo esto', SIII_lines_to_use

        #Calculate the S+1 abundance
        S2_lines = ['S2_6716A', 'S2_6731A']
        diagnos_eval, diagnos_mag = self.check_obsLines(S2_lines)
        self.determine_ionic_abundance('SII_HII', self.S2_atom, diagnos_eval,
                                       diagnos_mag, Tlow, ne)

        #Calculate the S+2 abundance
        S3_lines = ['S3_9069A', 'S3_9531A'
                    ] if SIII_lines_to_use == 'BOTH' else [SIII_lines_to_use]
        diagnos_eval, diagnos_mag = self.check_obsLines(S3_lines)
        if set(S3_lines) != set(['S3_9069A', 'S3_9531A']):
            print '-- Using SIII lines', diagnos_eval

        self.determine_ionic_abundance('SIII_HII', self.S3_atom, diagnos_eval,
                                       diagnos_mag, Tlow, ne)

        #Calculate the total sulfur abundance
        if set(self.abunData.index) >= {'SII_HII', 'SIII_HII'}:

            self.abunData[
                'SI_HI'] = self.abunData['SII_HII'] + self.abunData['SIII_HII']

            #Add the S+3 component if the argon correction is found
            if set(self.abunData.index) >= {'ArIII_HII', 'ArIV_HII'}:

                logAr2Ar3 = log10(self.abunData['ArIII_HII'] /
                                  self.abunData['ArIV_HII'])
                logSIV = log10(self.abunData['SIII_HII']) - (
                    logAr2Ar3 - self.n_SIV_correction) / self.m_SIV_correction
                SIV_HII = power(10, logSIV)

                # Evaluate the nan array
                nan_idcs = isnan(SIV_HII)
                nan_count = np_sum(nan_idcs)

                # Directly save if not nan
                if nan_count == 0:
                    self.abunData['SIV_HII'] = SIV_HII

                # Remove the nan entries performing a normal distribution
                elif nan_count < 0.90 * self.MC_array_len:
                    mag, error = nanmean(SIV_HII), nanstd(SIV_HII)

                    # Generate truncated array to store the data
                    a, b = (0 - mag) / error, (1000 * mag - mag) / error
                    new_samples = truncnorm(a, b, loc=mag,
                                            scale=error).rvs(size=nan_count)

                    # Replace nan entries
                    SIV_HII[nan_idcs] = new_samples
                    self.abunData['SIV_HII'] = SIV_HII

                    if nan_count > self.MC_warning_limit:
                        print '-- {} calculated with {}'.format(
                            'SIV_HII', nan_count)

                self.abunData[
                    'SI_HI'] = self.abunData['SII_HII'] + self.abunData[
                        'SIII_HII'] + self.abunData['SIV_HII']
                self.abunData['ICF_SIV'] = self.abunData['SI_HI'] / (
                    self.abunData['SII_HII'] + self.abunData['SIII_HII'])

        return

    def helium_abundance_elementalScheme(self,
                                         Te,
                                         ne,
                                         lineslog_frame,
                                         metal_ext=''):

        #Check temperatures are not nan before starting the treatment
        if (not isinstance(Te, float)) and (not isinstance(ne, float)):

            #HeI_indices = (lineslog_frame.Ion.str.contains('HeI_')) & (lineslog_frame.index != 'He1_8446A')  & (lineslog_frame.index != 'He1_7818A') & (lineslog_frame.index != 'He1_5016A')
            HeI_indices = (lineslog_frame.Ion.str.contains('HeI_')) & (
                lineslog_frame.index.isin(
                    ['He1_4472A', 'He1_5876A', 'He1_6678A']))
            HeI_labels = lineslog_frame.loc[HeI_indices].index.values
            HeI_ions = lineslog_frame.loc[HeI_indices].Ion.values

            Emis_Hbeta = self.H1_atom.getEmissivity(tem=Te,
                                                    den=ne,
                                                    label='4_2',
                                                    product=False)

            #--Generating matrices with fluxes and emissivities
            for i in range(len(HeI_labels)):

                pyneb_code = float(HeI_ions[i][HeI_ions[i].find('_') +
                                               1:len(HeI_ions[i])])
                line_relative_Flux = self.lines_dict[
                    HeI_labels[i]] / self.Hbeta_flux
                line_relative_emissivity = self.He1_atom.getEmissivity(
                    tem=Te, den=ne, wave=pyneb_code,
                    product=False) / Emis_Hbeta
                line_relative_emissivity = self.check_nan_entries(
                    line_relative_emissivity)

                if i == 0:
                    matrix_HeI_fluxes = copy(line_relative_Flux)
                    matrix_HeI_emis = copy(line_relative_emissivity)
                else:
                    matrix_HeI_fluxes = vstack(
                        (matrix_HeI_fluxes, line_relative_Flux))
                    matrix_HeI_emis = vstack(
                        (matrix_HeI_emis, line_relative_emissivity))

            matrix_HeI_fluxes = transpose(matrix_HeI_fluxes)
            matrix_HeI_emis = transpose(matrix_HeI_emis)

            #Perform the fit
            params = Parameters()
            params.add('Y', value=0.01)
            HeII_HII_array = zeros(len(matrix_HeI_fluxes))
            HeII_HII_error = zeros(len(matrix_HeI_fluxes))
            for i in range(len(matrix_HeI_fluxes)):
                fit_Output = lmfit_minimmize(residual_Y_v3,
                                             params,
                                             args=(matrix_HeI_emis[i],
                                                   matrix_HeI_fluxes[i]))
                HeII_HII_array[i] = fit_Output.params['Y'].value
                HeII_HII_error[i] = fit_Output.params['Y'].stderr

            #NO SUMANDO LOS ERRORES CORRECTOS?
            #self.abunData['HeII_HII_from_' + metal_ext] = random.normal(mean(HeII_HII_array), mean(HeII_HII_error), size = self.MC_array_len)
            ionic_abund = random.normal(mean(HeII_HII_array),
                                        mean(HeII_HII_error),
                                        size=self.MC_array_len)

            #Evaluate the nan array
            nan_count = np_sum(isnan(ionic_abund))
            if nan_count == 0:
                self.abunData['HeII_HII_from_' + metal_ext] = ionic_abund
            #Remove the nan entries performing a normal distribution
            elif nan_count < 0.90 * self.MC_array_len:
                mag, error = nanmean(ionic_abund), nanstd(ionic_abund)
                self.abunData['HeII_HII_from_' + metal_ext] = random.normal(
                    mag, error, size=self.MC_array_len)
                if nan_count > self.MC_warning_limit:
                    print '-- {} calculated with {}'.format(
                        'HeII_HII_from_' + metal_ext, nan_count)

            #Calculate the He+2 abundance
            if self.lines_dict.viewkeys() >= {'He2_4686A'}:
                #self.abunData['HeIII_HII_from_' + metal_ext] = self.He2_atom.getIonAbundance(int_ratio = self.lines_dict['He2_4686A'], tem=Te, den=ne, wave = 4685.6, Hbeta = self.Hbeta_flux)
                self.determine_ionic_abundance('HeIII_HII_from_' + metal_ext,
                                               self.He2_atom, 'L(4685)',
                                               self.lines_dict['He2_4686A'],
                                               Te, ne)

            #Calculate elemental abundance
            Helium_element_keys = [
                'HeII_HII_from_' + metal_ext, 'HeIII_HII_from_' + metal_ext
            ]
            if set(self.abunData.index) >= set(Helium_element_keys):
                self.abunData['HeI_HI_from_' +
                              metal_ext] = self.abunData[Helium_element_keys[
                                  0]] + self.abunData[Helium_element_keys[1]]
            else:
                self.abunData['HeI_HI_from_' + metal_ext] = self.abunData[
                    Helium_element_keys[0]]

            #Proceed to get the Helium mass fraction Y
            Element_abund = metal_ext + 'I_HI'
            Y_fraction, Helium_abund = 'Ymass_' + metal_ext, 'HeI_HI_from_' + metal_ext
            if set(self.abunData.index) >= {Helium_abund, Element_abund}:
                self.abunData[Y_fraction] = (
                    4 * self.abunData[Helium_abund] *
                    (1 - 20 * self.abunData[Element_abund])) / (
                        1 + 4 * self.abunData[Helium_abund])

    def store_abundances_excel(self, objCode, catalogue_df, extension=''):

        #Store the values using the mean and the std from the array
        for parameter in self.abunData.index:

            mean_value, std_value = mean(self.abunData[parameter]), std(
                self.abunData[parameter])

            if (~isnan(mean_value)) & (~isnan(std_value)):
                catalogue_df.loc[objCode, parameter + extension] = ufloat(
                    mean_value, std_value)
            else:
                catalogue_df.loc[objCode, parameter + extension] = np_nan

            print parameter, mean_value, std_value

        return

    def generate_nan_array(self):

        nan_array = empty(self.MC_array_len)
        nan_array[:] = np_nan

        return nan_array

    def check_nan_entries(self, input_array):

        nan_count = np_sum(isnan(input_array))

        if nan_count > 0:
            mag, error = nanmean(input_array), nanstd(input_array)
            new_distr = random.normal(mag, error, size=self.MC_array_len)
            if nan_count > 0.1 * self.MC_array_len:
                print '--Helium issue with {} nans'.format(nan_count)
        else:
            new_distr = input_array

        return new_distr
示例#7
0
    def compare_RecombCoeffs(self,
                             obj_data,
                             lineslog_frame,
                             spectral_limit=200):

        # Create hidrogen atom object
        self.H1_atom = RecAtom('H', 1)

        linformat_df = read_csv(
            '/home/vital/workspace/dazer/format/emlines_pyneb_optical_infrared.dz',
            index_col=0,
            names=['ion', 'lambda_theo', 'latex_format'],
            delim_whitespace=True)
        lineslog_frame['latex_format'] = 'none'

        for line in lineslog_frame.index:
            if '_w' not in line:  # Structure to avoid wide components
                lineslog_frame.loc[line, 'latex_format'] = r'${}$'.format(
                    linformat_df.loc[line, 'latex_format'])

        # Load electron temperature and density (if not available it will use Te = 10000K and ne = 100cm^-3)
        T_e = self.checking_for_ufloat(obj_data.TeSIII) if ~isnan(
            self.checking_for_ufloat(obj_data.TeSIII)) else 10000.0
        n_e = self.checking_for_ufloat(obj_data.neSII) if ~isnan(
            self.checking_for_ufloat(obj_data.neSII)) else 100.0

        # Get the Hidrogen recombination lines that we have observed in this object
        Obs_Hindx = lineslog_frame.Ion.isin(self.RecombRatios_Ions)

        # Calculate recombination coefficients and reddening curve values
        Obs_H_Emis = empty(len(Obs_Hindx))
        Obs_Ions = lineslog_frame.loc[Obs_Hindx, 'Ion'].values

        for i in range(len(Obs_Ions)):
            TransitionCode = Obs_Ions[i][Obs_Ions[i].find('_') +
                                         1:len(Obs_Ions[i])]
            Obs_H_Emis[i] = self.H1_atom.getEmissivity(tem=T_e,
                                                       den=n_e,
                                                       label=TransitionCode)

            # Normalize by Hbeta (this new constant is necessary to avoid a zero sigma)
        Hbeta_Emis = self.H1_atom.getEmissivity(tem=T_e, den=n_e, label='4_2')
        Fbeta_flux = ufloat(
            lineslog_frame.loc['H1_4861A']['line_Flux'].nominal_value,
            lineslog_frame.loc['H1_4861A']['line_Flux'].std_dev)

        # Load theoretical and observational recombination ratios to data frame
        lineslog_frame.loc[Obs_Hindx, 'line_Emissivity'] = Obs_H_Emis
        lineslog_frame.loc[Obs_Hindx,
                           'line_TheoRecombRatio'] = Obs_H_Emis / Hbeta_Emis
        lineslog_frame.loc[Obs_Hindx,
                           'line_ObsRecombRatio'] = lineslog_frame.loc[
                               Obs_Hindx, 'line_Flux'].values / Fbeta_flux

        # Get indeces of emissions in each arm
        ObsBlue_Hindx = Obs_Hindx & (lineslog_frame.lambda_theo <
                                     obj_data.join_wavelength)
        ObsRed_Hindx = Obs_Hindx & (lineslog_frame.lambda_theo >
                                    obj_data.join_wavelength)

        # Recalculate red arm coefficients so they are normalized by red arm line (the most intense)
        if (ObsRed_Hindx.sum()
            ) > 0:  # Can only work if there is at least one line
            idx_Redmax = lineslog_frame.loc[ObsRed_Hindx]['flux_intg'].idxmax(
            )  # We do not use line_flux because it is a ufloat and it does not work with idxmax
            H_Redmax_flux = lineslog_frame.loc[idx_Redmax, 'line_Flux']
            H_Redmax_emis = lineslog_frame.loc[idx_Redmax, 'line_Emissivity']
            Flux_Redmax = ufloat(
                H_Redmax_flux.nominal_value * Hbeta_Emis / H_Redmax_emis,
                H_Redmax_flux.std_dev * Hbeta_Emis / H_Redmax_emis)
            lineslog_frame.loc[ObsRed_Hindx,
                               'line_ObsRecombRatio'] = lineslog_frame.loc[
                                   ObsRed_Hindx,
                                   'line_Flux'].values / Flux_Redmax

        # Load x axis values: (f_lambda - f_Hbeta) and y axis values: log(F/Fbeta)_theo - log(F/Fbeta)_obs to dataframe
        lineslog_frame.loc[Obs_Hindx, 'x axis values'] = lineslog_frame.loc[Obs_Hindx, 'line_f'].values - \
                                                         lineslog_frame.loc['H1_4861A']['line_f']
        lineslog_frame.loc[Obs_Hindx, 'y axis values'] = unum_log10(
            lineslog_frame.loc[Obs_Hindx, 'line_TheoRecombRatio'].values
        ) - unum_log10(lineslog_frame.loc[Obs_Hindx,
                                          'line_ObsRecombRatio'].values)

        # Compute all the possible configuration of points and store them
        output_dict = {}

        # --- All points:
        output_dict['all_x'] = lineslog_frame.loc[Obs_Hindx,
                                                  'x axis values'].values
        output_dict['all_y'] = lineslog_frame.loc[Obs_Hindx,
                                                  'y axis values'].values
        output_dict['all_ions'] = list(
            lineslog_frame.loc[Obs_Hindx, 'latex_format'].values)

        # --- By arm
        output_dict['blue_x'] = lineslog_frame.loc[ObsBlue_Hindx,
                                                   'x axis values'].values
        output_dict['blue_y'] = lineslog_frame.loc[ObsBlue_Hindx,
                                                   'y axis values'].values
        output_dict['blue_ions'] = list(
            lineslog_frame.loc[ObsBlue_Hindx, 'latex_format'].values)
        output_dict['red_x'] = lineslog_frame.loc[ObsRed_Hindx,
                                                  'x axis values'].values
        output_dict['red_y'] = lineslog_frame.loc[ObsRed_Hindx,
                                                  'y axis values'].values
        output_dict['red_ions'] = list(
            lineslog_frame.loc[ObsRed_Hindx, 'latex_format'].values)

        # --- Store fluxes
        output_dict['Blue_ObsRatio'] = unum_log10(
            lineslog_frame.loc[ObsBlue_Hindx, 'line_ObsRecombRatio'].values)
        output_dict['Red_ObsRatio'] = unum_log10(
            lineslog_frame.loc[ObsRed_Hindx, 'line_ObsRecombRatio'].values)
        output_dict['line_Flux_Blue'] = lineslog_frame.loc[ObsBlue_Hindx,
                                                           'line_Flux'].values
        output_dict['line_Flux_Red'] = lineslog_frame.loc[ObsRed_Hindx,
                                                          'line_Flux'].values
        output_dict['line_wave_Blue'] = lineslog_frame.loc[
            ObsBlue_Hindx, 'lambda_theo'].values
        output_dict['line_wave_Red'] = lineslog_frame.loc[ObsRed_Hindx,
                                                          'lambda_theo'].values

        # --- Inside limits
        if obj_data.h_gamma_valid == 'yes':
            in_idcs = Obs_Hindx
        elif obj_data.h_gamma_valid == 'no':
            wave_idx = ((lineslog_frame.lambda_theo > (obj_data.Wmin_Blue + spectral_limit)) & (
                        lineslog_frame.lambda_theo < (obj_data.join_wavelength - spectral_limit))) \
                       | ((lineslog_frame.lambda_theo > (obj_data.join_wavelength + spectral_limit)) & (
                        lineslog_frame.lambda_theo < (obj_data.Wmax_Red - spectral_limit)))
            in_idcs = Obs_Hindx & wave_idx

        output_dict['in_x'] = lineslog_frame.loc[in_idcs,
                                                 'x axis values'].values
        output_dict['in_y'] = lineslog_frame.loc[in_idcs,
                                                 'y axis values'].values
        output_dict['in_ions'] = list(
            lineslog_frame.loc[in_idcs, 'latex_format'].values)

        # --- Outside limis
        if obj_data.h_gamma_valid == 'no':
            wave_idx = (lineslog_frame.lambda_theo <
                        (obj_data.Wmin_Blue + spectral_limit)) | (
                            lineslog_frame.lambda_theo >
                            (obj_data.Wmax_Red - spectral_limit))
            out_idcs = Obs_Hindx & wave_idx
            output_dict['out_x'] = lineslog_frame.loc[out_idcs,
                                                      'x axis values'].values
            output_dict['out_y'] = lineslog_frame.loc[out_idcs,
                                                      'y axis values'].values
            output_dict['out_ions'] = list(
                lineslog_frame.loc[out_idcs, 'latex_format'].values)
        else:
            output_dict['out_x'] = None
            output_dict['out_y'] = None
            output_dict['out_ions'] = None

        return output_dict
示例#8
0
class ReddeningLaws():
    def __init__(self, Rv_model=None, reddedning_curve_model=None):

        self.SpectraEdges_Limit = 200
        self.Hbeta_wavelength = 4861.3316598713955

        # List of hydrogen recombination lines in our EmissionLines coordinates log. WARNING: We have removed the very blended ones
        self.RecombRatios_Ions = array([
            'HBal_20_2', 'HBal_19_2', 'HBal_18_2', 'HBal_17_2', 'HBal_16_2',
            'HBal_15_2', 'HBal_12_2', 'HBal_11_2', 'HBal_9_2', 'Hdelta_6_2',
            'Hgamma_5_2', 'Hbeta_4_2', 'Halpha_3_2', 'HPas_20_3', 'HPas19_3',
            'HPas_18_3', 'HPas_17_3', 'HPas_16_3', 'HPas_15_3', 'HPas_14_3',
            'HPas13_3', 'HPas12_3', 'HPas_11_3', 'HPas_10_3', 'HPas_9_3',
            'HPas_8_3', 'HPas_7_3'
        ])

        # Dictionary with the reddening curves
        self.reddening_curves_calc = {
            'MM72': self.f_Miller_Mathews1972,
            'CCM89': self.X_x_Cardelli1989,
            'G03_bar': self.X_x_Gordon2003_bar,
            'G03_average': self.X_x_Gordon2003_average,
            'G03_supershell': self.X_x_Gordon2003_supershell
        }

        __location__ = path.realpath(
            path.join(getcwd(), path.dirname(__file__)))
        self.red_laws_folder = __location__[0:__location__.find('dazer'
                                                                )] + 'dazer/'

        # Set default values
        if Rv_model is not None:
            self.Rv_model = Rv_model

        if reddedning_curve_model is not None:
            self.reddedning_curve_model = reddedning_curve_model

    def checking_for_ufloat(self, x):

        if isinstance(x, UFloat):
            param = x.nominal_value

        else:
            param = x

        return param

    def compare_RecombCoeffs(self,
                             obj_data,
                             lineslog_frame,
                             spectral_limit=200):

        # Create hidrogen atom object
        self.H1_atom = RecAtom('H', 1)

        linformat_df = read_csv(
            '/home/vital/workspace/dazer/format/emlines_pyneb_optical_infrared.dz',
            index_col=0,
            names=['ion', 'lambda_theo', 'latex_format'],
            delim_whitespace=True)
        lineslog_frame['latex_format'] = 'none'

        for line in lineslog_frame.index:
            if '_w' not in line:  # Structure to avoid wide components
                lineslog_frame.loc[line, 'latex_format'] = r'${}$'.format(
                    linformat_df.loc[line, 'latex_format'])

        # Load electron temperature and density (if not available it will use Te = 10000K and ne = 100cm^-3)
        T_e = self.checking_for_ufloat(obj_data.TeSIII) if ~isnan(
            self.checking_for_ufloat(obj_data.TeSIII)) else 10000.0
        n_e = self.checking_for_ufloat(obj_data.neSII) if ~isnan(
            self.checking_for_ufloat(obj_data.neSII)) else 100.0

        # Get the Hidrogen recombination lines that we have observed in this object
        Obs_Hindx = lineslog_frame.Ion.isin(self.RecombRatios_Ions)

        # Calculate recombination coefficients and reddening curve values
        Obs_H_Emis = empty(len(Obs_Hindx))
        Obs_Ions = lineslog_frame.loc[Obs_Hindx, 'Ion'].values

        for i in range(len(Obs_Ions)):
            TransitionCode = Obs_Ions[i][Obs_Ions[i].find('_') +
                                         1:len(Obs_Ions[i])]
            Obs_H_Emis[i] = self.H1_atom.getEmissivity(tem=T_e,
                                                       den=n_e,
                                                       label=TransitionCode)

            # Normalize by Hbeta (this new constant is necessary to avoid a zero sigma)
        Hbeta_Emis = self.H1_atom.getEmissivity(tem=T_e, den=n_e, label='4_2')
        Fbeta_flux = ufloat(
            lineslog_frame.loc['H1_4861A']['line_Flux'].nominal_value,
            lineslog_frame.loc['H1_4861A']['line_Flux'].std_dev)

        # Load theoretical and observational recombination ratios to data frame
        lineslog_frame.loc[Obs_Hindx, 'line_Emissivity'] = Obs_H_Emis
        lineslog_frame.loc[Obs_Hindx,
                           'line_TheoRecombRatio'] = Obs_H_Emis / Hbeta_Emis
        lineslog_frame.loc[Obs_Hindx,
                           'line_ObsRecombRatio'] = lineslog_frame.loc[
                               Obs_Hindx, 'line_Flux'].values / Fbeta_flux

        # Get indeces of emissions in each arm
        ObsBlue_Hindx = Obs_Hindx & (lineslog_frame.lambda_theo <
                                     obj_data.join_wavelength)
        ObsRed_Hindx = Obs_Hindx & (lineslog_frame.lambda_theo >
                                    obj_data.join_wavelength)

        # Recalculate red arm coefficients so they are normalized by red arm line (the most intense)
        if (ObsRed_Hindx.sum()
            ) > 0:  # Can only work if there is at least one line
            idx_Redmax = lineslog_frame.loc[ObsRed_Hindx]['flux_intg'].idxmax(
            )  # We do not use line_flux because it is a ufloat and it does not work with idxmax
            H_Redmax_flux = lineslog_frame.loc[idx_Redmax, 'line_Flux']
            H_Redmax_emis = lineslog_frame.loc[idx_Redmax, 'line_Emissivity']
            Flux_Redmax = ufloat(
                H_Redmax_flux.nominal_value * Hbeta_Emis / H_Redmax_emis,
                H_Redmax_flux.std_dev * Hbeta_Emis / H_Redmax_emis)
            lineslog_frame.loc[ObsRed_Hindx,
                               'line_ObsRecombRatio'] = lineslog_frame.loc[
                                   ObsRed_Hindx,
                                   'line_Flux'].values / Flux_Redmax

        # Load x axis values: (f_lambda - f_Hbeta) and y axis values: log(F/Fbeta)_theo - log(F/Fbeta)_obs to dataframe
        lineslog_frame.loc[Obs_Hindx, 'x axis values'] = lineslog_frame.loc[Obs_Hindx, 'line_f'].values - \
                                                         lineslog_frame.loc['H1_4861A']['line_f']
        lineslog_frame.loc[Obs_Hindx, 'y axis values'] = unum_log10(
            lineslog_frame.loc[Obs_Hindx, 'line_TheoRecombRatio'].values
        ) - unum_log10(lineslog_frame.loc[Obs_Hindx,
                                          'line_ObsRecombRatio'].values)

        # Compute all the possible configuration of points and store them
        output_dict = {}

        # --- All points:
        output_dict['all_x'] = lineslog_frame.loc[Obs_Hindx,
                                                  'x axis values'].values
        output_dict['all_y'] = lineslog_frame.loc[Obs_Hindx,
                                                  'y axis values'].values
        output_dict['all_ions'] = list(
            lineslog_frame.loc[Obs_Hindx, 'latex_format'].values)

        # --- By arm
        output_dict['blue_x'] = lineslog_frame.loc[ObsBlue_Hindx,
                                                   'x axis values'].values
        output_dict['blue_y'] = lineslog_frame.loc[ObsBlue_Hindx,
                                                   'y axis values'].values
        output_dict['blue_ions'] = list(
            lineslog_frame.loc[ObsBlue_Hindx, 'latex_format'].values)
        output_dict['red_x'] = lineslog_frame.loc[ObsRed_Hindx,
                                                  'x axis values'].values
        output_dict['red_y'] = lineslog_frame.loc[ObsRed_Hindx,
                                                  'y axis values'].values
        output_dict['red_ions'] = list(
            lineslog_frame.loc[ObsRed_Hindx, 'latex_format'].values)

        # --- Store fluxes
        output_dict['Blue_ObsRatio'] = unum_log10(
            lineslog_frame.loc[ObsBlue_Hindx, 'line_ObsRecombRatio'].values)
        output_dict['Red_ObsRatio'] = unum_log10(
            lineslog_frame.loc[ObsRed_Hindx, 'line_ObsRecombRatio'].values)
        output_dict['line_Flux_Blue'] = lineslog_frame.loc[ObsBlue_Hindx,
                                                           'line_Flux'].values
        output_dict['line_Flux_Red'] = lineslog_frame.loc[ObsRed_Hindx,
                                                          'line_Flux'].values
        output_dict['line_wave_Blue'] = lineslog_frame.loc[
            ObsBlue_Hindx, 'lambda_theo'].values
        output_dict['line_wave_Red'] = lineslog_frame.loc[ObsRed_Hindx,
                                                          'lambda_theo'].values

        # --- Inside limits
        if obj_data.h_gamma_valid == 'yes':
            in_idcs = Obs_Hindx
        elif obj_data.h_gamma_valid == 'no':
            wave_idx = ((lineslog_frame.lambda_theo > (obj_data.Wmin_Blue + spectral_limit)) & (
                        lineslog_frame.lambda_theo < (obj_data.join_wavelength - spectral_limit))) \
                       | ((lineslog_frame.lambda_theo > (obj_data.join_wavelength + spectral_limit)) & (
                        lineslog_frame.lambda_theo < (obj_data.Wmax_Red - spectral_limit)))
            in_idcs = Obs_Hindx & wave_idx

        output_dict['in_x'] = lineslog_frame.loc[in_idcs,
                                                 'x axis values'].values
        output_dict['in_y'] = lineslog_frame.loc[in_idcs,
                                                 'y axis values'].values
        output_dict['in_ions'] = list(
            lineslog_frame.loc[in_idcs, 'latex_format'].values)

        # --- Outside limis
        if obj_data.h_gamma_valid == 'no':
            wave_idx = (lineslog_frame.lambda_theo <
                        (obj_data.Wmin_Blue + spectral_limit)) | (
                            lineslog_frame.lambda_theo >
                            (obj_data.Wmax_Red - spectral_limit))
            out_idcs = Obs_Hindx & wave_idx
            output_dict['out_x'] = lineslog_frame.loc[out_idcs,
                                                      'x axis values'].values
            output_dict['out_y'] = lineslog_frame.loc[out_idcs,
                                                      'y axis values'].values
            output_dict['out_ions'] = list(
                lineslog_frame.loc[out_idcs, 'latex_format'].values)
        else:
            output_dict['out_x'] = None
            output_dict['out_y'] = None
            output_dict['out_ions'] = None

        return output_dict

    def deredden_lines(self,
                       lines_frame,
                       reddening_curve,
                       cHbeta=None,
                       E_BV=None,
                       R_v=None):

        # cHbeta format
        if isinstance(cHbeta, float):
            cHbeta_mag = cHbeta

        elif isinstance(cHbeta, UFloat):
            cHbeta_mag = cHbeta

        # If it is negative we set it to zero
        if cHbeta_mag < 0.0:
            cHbeta_mag = 0.0

        # By default we perform the calculation using the colour excess
        E_BV = E_BV if E_BV != None else self.Ebv_from_cHbeta(
            cHbeta, reddening_curve, R_v)

        # Get reddening curves f_value
        lines_fluxes = lines_frame.line_Flux.values
        lines_wavelengths = lines_frame.lambda_theo.values
        lines_Xx = self.reddening_Xx(lines_wavelengths, reddening_curve, R_v)
        lines_frame['line_Xx'] = lines_Xx

        # Get line intensities
        lines_int = lines_fluxes * unum_pow(10, 0.4 * lines_Xx * E_BV)
        lines_frame['line_Int'] = lines_int

        # We recalculate the equivalent width using the intensity of the lines (instead of the flux)
        continua_flux = uarray(lines_frame.zerolev_mean.values,
                               lines_frame.zerolev_std.values)
        continua_int = continua_flux * unum_pow(10, 0.4 * lines_Xx * E_BV)
        lines_frame['con_dered'] = continua_int
        lines_frame['Eqw_dered'] = lines_int / continua_int

        # For extra testing we add integrated and gaussian values derredden
        lines_brut_flux = uarray(lines_frame['flux_intg'].values,
                                 lines_frame['flux_intg_er'].values)
        lines_gauss_flux = uarray(lines_frame['flux_gauss'].values,
                                  lines_frame['flux_gauss_er'].values)
        lines_frame['line_IntBrute_dered'] = lines_brut_flux * unum_pow(
            10, 0.4 * lines_Xx * E_BV)
        lines_frame['line_IntGauss_dered'] = lines_gauss_flux * unum_pow(
            10, 0.4 * lines_Xx * E_BV)

        return

    def derreddening_spectrum(self,
                              wave,
                              flux,
                              reddening_curve,
                              cHbeta=None,
                              E_BV=None,
                              R_v=None):

        # cHbeta format
        if isinstance(cHbeta, float):
            cHbeta_mag = cHbeta

        elif isinstance(cHbeta, UFloat):
            cHbeta_mag = cHbeta

        # If it is negative we set it to zero
        if cHbeta_mag < 0.0:
            cHbeta_mag = 0.0

        # By default we perform the calculation using the colour excess
        E_BV = E_BV if E_BV != None else self.Ebv_from_cHbeta(
            cHbeta, reddening_curve, R_v)

        # Perform dereddening
        wavelength_range_Xx = self.reddening_Xx(wave, reddening_curve, R_v)
        flux_range_derred = flux * np_power(10,
                                            0.4 * wavelength_range_Xx * E_BV)

        return flux_range_derred

    def reddening_spectrum(self,
                           wave,
                           flux,
                           reddening_curve,
                           cHbeta=None,
                           E_BV=None,
                           R_v=None):

        # cHbeta format
        if isinstance(cHbeta, float):
            cHbeta_mag = cHbeta

        elif isinstance(cHbeta, UFloat):
            cHbeta_mag = cHbeta

        # If it is negative we set it to zero
        if cHbeta_mag < 0.0:
            cHbeta_mag = 0.0

        # By default we perform the calculation using the colour excess
        E_BV = E_BV if E_BV != None else self.Ebv_from_cHbeta(
            cHbeta, reddening_curve, R_v)

        # Perform dereddening
        wavelength_range_Xx = self.reddening_Xx(wave, reddening_curve, R_v)
        flux_range_red = flux * np_power(10, -0.4 * wavelength_range_Xx * E_BV)

        return flux_range_red

    def Ebv_from_cHbeta(self, cHbeta, reddening_curve, R_v):

        if cHbeta == None:
            exit(
                'Warning: no cHbeta or E(B-V) provided to reddening curve, code aborted'
            )
        else:
            if cHbeta != None:
                E_BV = cHbeta * 2.5 / self.reddening_Xx(
                    array([self.Hbeta_wavelength]), reddening_curve, R_v)[0]
                return E_BV

    def flambda_from_Xx(self, Xx, reddening_curve, R_v):

        X_Hbeta = self.reddening_Xx(array([self.Hbeta_wavelength]),
                                    reddening_curve, R_v)[0]

        f_lines = Xx / X_Hbeta - 1

        return f_lines

    def reddening_Xx(self, waves, curve_methodology, R_v):

        self.R_v = R_v
        self.wavelength_rc = waves
        return self.reddening_curves_calc[curve_methodology]()

    def f_Miller_Mathews1972(self):

        if isinstance(self.wavelength_rc, ndarray):
            y = 1.0 / (self.wavelength_rc / 10000.0)
            y_beta = 1.0 / (4862.683 / 10000.0)

            ind_low = where(y <= 2.29)[0]
            ind_high = where(y > 2.29)[0]

            dm_lam_low = 0.74 * y[ind_low] - 0.34 + 0.341 * self.R_v - 1.014
            dm_lam_high = 0.43 * y[ind_high] + 0.37 + 0.341 * self.R_v - 1.014
            dm_beta = 0.74 * y_beta - 0.34 + 0.341 * self.R_v - 1.014

            dm_lam = concatenate((dm_lam_low, dm_lam_high))

            f = dm_lam / dm_beta - 1

        else:

            y = 1.0 / (self.wavelength_rc / 10000.0)
            y_beta = 1.0 / (4862.683 / 10000.0)

            if y <= 2.29:
                dm_lam = 0.74 * y - 0.34 + 0.341 * self.R_v - 1.014
            else:
                dm_lam = 0.43 * y + 0.37 + 0.341 * self.R_v - 1.014

            dm_beta = 0.74 * y_beta - 0.34 + 0.341 * self.R_v - 1.014

            f = dm_lam / dm_beta - 1

        return f

    def X_x_Cardelli1989(self):

        x_true = 1.0 / (self.wavelength_rc / 10000.0)
        y = x_true - 1.82

        y_coeffs = array([
            ones(len(y)), y,
            np_power(y, 2),
            np_power(y, 3),
            np_power(y, 4),
            np_power(y, 5),
            np_power(y, 6),
            np_power(y, 7)
        ])
        a_coeffs = array([
            1, 0.17699, -0.50447, -0.02427, 0.72085, 0.01979, -0.77530, 0.32999
        ])
        b_coeffs = array([
            0, 1.41338, 2.28305, 1.07233, -5.38434, -0.62251, 5.30260, -2.09002
        ])

        a_x = dot(a_coeffs, y_coeffs)
        b_x = dot(b_coeffs, y_coeffs)

        X_x = a_x + b_x / self.R_v

        return X_x

    def X_x_Gordon2003_bar(self):

        # Default R_V is 3.4
        R_v = self.R_v if self.R_v != None else 3.4  # This is not very nice
        x = 1.0 / (self.wavelength_rc / 10000.0)

        # This file format has 1/um in column 0 and A_x/A_V in column 1
        file_data = loadtxt(
            '/home/vital/workspace/dazer/bin/lib/Astro_Libraries/gordon_2003_SMC_bar.txt'
        )

        # This file has column
        Xx_interpolator = interp1d(file_data[:, 0], file_data[:, 1])
        X_x = R_v * Xx_interpolator(x)
        return X_x

    def X_x_Gordon2003_average(self):

        # Default R_V is 3.4
        R_v = self.R_v if self.R_v != None else 3.4  # This is not very nice
        x = 1.0 / (self.wavelength_rc / 10000.0)

        # This file format has 1/um in column 0 and A_x/A_V in column 1
        file_data = loadtxt(
            self.red_laws_folder +
            'bin/lib/Astro_Libraries/literature_data/gordon_2003_LMC_average.txt'
        )

        # This file has column
        Xx_interpolator = interp1d(file_data[:, 0], file_data[:, 1])
        X_x = R_v * Xx_interpolator(x)
        return X_x

    def X_x_Gordon2003_supershell(self):

        # Default R_V is 3.4
        R_v = self.R_v if self.R_v != None else 3.4  # This is not very nice
        x = 1.0 / (self.wavelength_rc / 10000.0)

        # This file format has 1/um in column 0 and A_x/A_V in column 1
        file_data = loadtxt(
            '/home/vital/workspace/dazer/bin/lib/Astro_Libraries/gordon_2003_LMC2_supershell.txt'
        )

        # This file has column
        Xx_interpolator = interp1d(file_data[:, 0], file_data[:, 1])
        X_x = R_v * Xx_interpolator(x)
        return X_x

    def Epm_ReddeningPoints(self):

        x_true = arange(1.0, 2.8, 0.1)  # in microns -1
        X_Angs = 1 / x_true * 1e4

        Xx = array([
            1.36, 1.44, 1.84, 2.04, 2.24, 2.44, 2.66, 2.88, 3.14, 3.36, 3.56,
            3.77, 3.96, 4.15, 4.26, 4.40, 4.52, 4.64
        ])
        f_lambda = array([
            -0.63, -0.61, -0.5, -0.45, -0.39, -0.34, -0.28, -0.22, -0.15,
            -0.09, -0.03, 0.02, 0.08, 0.13, 0.16, 0.20, 0.23, 0.26
        ])

        return x_true, X_Angs, Xx, f_lambda

    def gasExtincParams(self, wave, Rv, reddening_law, Hbeta_wave=4861.331):

        self.rcGas = pn.RedCorr(R_V=Rv, law=reddening_law)

        HbetaXx = self.rcGas.X(Hbeta_wave)
        lineXx = self.rcGas.X(wave)

        lineFlambda = lineXx / HbetaXx - 1.0

        return lineFlambda

    def contExtincParams(self, wave, Rv, reddening_law, Hbeta_wave=4861.331):

        self.rcCont = pn.RedCorr(R_V=Rv, law=reddening_law)

        lineXx = self.rcGas.X(wave)

        return lineXx
class HeAbundance_InferenceMethods(Txt_Files_Manager):
    
    def __init__(self):
        
        #Import Dazer_Files Class to import data from lines_logs
        Txt_Files_Manager.__init__(self)
        
        #Declare Hydrogen and Helium collisional lines for the analysis
        #self.posHydrogen_Ions      = ['Hdelta_6_2',    'Hgamma_5_2',   'Hbeta_4_2',    'Halpha_3_2']
        self.posHydrogen_Lines      = ['H1_4102A',      'H1_4340A',     'H1_4861A',     'H1_6563A']
        self.Hydrogen_Wavelengths   = [4101.742,        4340.471,       4862.683,        6562.819]
        
        self.posHelium_Lines        = ['He1_3889A',  'He1_4026A',    'He1_4387A',    'He1_4471A',    'He1_4686A',    'He1_4714A',    'He1_4922A',   'He1_5876A',    'He1_6678A',   'He1_7065A',    'He1_7281A',      'He1_10830A']     
        self.Helium_Wavelengths     = [3889.0,        4026.0,         4387.0,         4471.0,         4686.0,         4714.0,         4922.0,         5876.0,         6678.0,         7065.0,         7281.0,         10830.0]
        
        self.Cand_Hydrogen_Lines    = []
        self.Cand_Helium_Lines      = []
        
        self.nHydrogen              = None
        self.nHelium                = None
    
        #Define indexes and labels to speed up the code               
        self.HBeta_label            = 'H1_4861A'
        self.He3889_label           = 'He1_3889A'
        self.He3889blended_label    = 'He1_3889A_blended'
        self.He3889_check           = None
        
        #Declare pyneb Hydrogen and Helium atoms to calculate emissivities
        self.H1                     = RecAtom('H', 1)
        self.He1                    = RecAtom('He', 1) 
        
        #Import collisional coefficients table
        self.Coef_Kalpha_dict       = self.Import_Coll_Coeff_Table(self.posHydrogen_Lines, None)

        #Import Optical depth function
        self.Coef_ftau_dict         = self.Import_OpticalDepth_Coeff_Table(self.posHelium_Lines) 
               
        #Declare dictionaries to store the data
        #WARNING: In this analysis flambda is mantained constant
        self.Flux_dict              = OrderedDict()
        self.Error_dict             = OrderedDict()
        self.Wave_dict              = OrderedDict()
        self.PynebCode_dict         = OrderedDict()
        self.EqW_dict               = OrderedDict()
        self.EqWerror_dict          = OrderedDict()
        self.hlambda_dict           = OrderedDict()
        self.flambda_dict           = self.get_flambda_dict(self.posHydrogen_Lines + self.posHelium_Lines, self.Hydrogen_Wavelengths + self.Helium_Wavelengths)
        
        #Extra
        self.EmptyRowFormat         = 'nan'            
            
    def Import_TableData(self, Address, Columns):
        
        Imported_Array  = genfromtxt(Address, dtype=float, usecols = Columns, skiprows = 2).T
        Datarray = Imported_Array[:,~isnan(Imported_Array).all(0)]
                
        return Datarray
     
    def Import_Coll_Coeff_Table(self, HydrogenLines, HeliumLines):
        
        data_dict = OrderedDict()
                
        for i in range(len(HydrogenLines)):
            
            Line            = HydrogenLines[i]
            Data_Columns    = [0 + 3*i, 1 + 3*i, 2 + 3*i]
            data_dict[Line] = self.Import_TableData(self.Hydrogen_CollCoeff_TableAddress, Data_Columns)
                    
        return data_dict
     
    def Import_OpticalDepth_Coeff_Table(self, HeliumLines):
        
        data_dict = OrderedDict()

        for i in range(len(HeliumLines)):
            
            Line            = HeliumLines[i]
            data_dict[Line] = loadtxt(self.Helium_OpticalDepth_TableAddress, dtype = float, skiprows = 2, usecols = (i,))
            
        return data_dict
    
    def Import_Synthetic_Fluxes(self, Model = 'Model2'):

        self.SyntheticData_dict = OrderedDict()

        if Model == 'Model1':
            #self.SyntheticData_dict['He_Flux']      = array([ 0.0891384,    0.01283333,     0.03187135, 0.09890274, 0.02582588, 0.02366021])   
            #self.SyntheticData_dict['He_Flux']      = array([ 0.0891384,    0.01283333,     0.03187135, 0.09890274, 0.02582588, 0.02366021])
            self.SyntheticData_dict['H_Flux']       = array([ 0.24685935,   0.45526236,     1.0,            2.96988502])
            self.SyntheticData_dict['H_wave']       = array([4101.742,      4340.471,      4862.683,       6562.819])
            self.SyntheticData_dict['H_Ions']       = ['Hdelta_6_2',    'Hgamma_5_2',   'Hbeta_4_2',    'Halpha_3_2']
            self.SyntheticData_dict['H_labels']     = ['H1_4102A',      'H1_4340A',     'H1_4861A',     'H1_6563A']
            self.SyntheticData_dict['H_Eqw']        = [50.0,            50.0,           250,             300.0]
            self.SyntheticData_dict['H_EqwErr']     = [1.0,             1.0,            12.5,            14]
            self.SyntheticData_dict['H_hlambda']    = [1.0,             1.0,            1.0,             1.0]
            self.SyntheticData_dict['H_error']      = self.SyntheticData_dict['H_Flux'] * 0.01
            
            self.SyntheticData_dict['He_Flux']      = array([ 0.08951096,    0.01290066,     0.03201484, 0.09931435, 0.02594518, 0.02377085])   
            self.SyntheticData_dict['He_wave']      = array([ 3889.0,       4026.0,         4471.0,        5876.0,     6678.0,     7065.0])
            self.SyntheticData_dict['He_labels']    =       ['He1_3889A',   'He1_4026A',   'He1_4471A',   'He1_5876A','He1_6678A', 'He1_7065A']
            self.SyntheticData_dict['He_Eqw']       = [10.0,                10.0,           10.0,           10.0,        10.0,          10.0]
            self.SyntheticData_dict['He_EqwErr']    = [1.0,                 1.0,            1.0,            1.0,         1.0,           1.0]
            self.SyntheticData_dict['He_hlambda']   = [1.0,                 1.0,            1.0,            1.0,         1.0,           1.0] 
            self.SyntheticData_dict['He_error']     = self.SyntheticData_dict['He_Flux'] * 0.02
                        
            self.SyntheticData_dict['TOIII']        = 19000
            self.SyntheticData_dict['y_plus']       = 0.08
            self.SyntheticData_dict['n_e']          = 100.0
            self.SyntheticData_dict['a_He']         = 1.0
            self.SyntheticData_dict['tau']          = 0.2
            self.SyntheticData_dict['Te_0']         = 18000.0
            self.SyntheticData_dict['cHbeta']       = 0.1
            self.SyntheticData_dict['a_H']          = 1.0
            self.SyntheticData_dict['xi']           = 1.0

        if Model == 'Model2':
            
            #These are the ones from the version 0
            #self.SyntheticData_dict['H_Flux']       = array([ 0.24585991,  0.45343263,  2.95803687])
            #self.SyntheticData_dict['He_Flux']      = array([ 0.10059744,  0.01684244,  0.03908421,  0.12673761,  0.03538569,  0.04145339])
            #These are the ones from the version 1
            #self.SyntheticData_dict['H_Flux']       = array([0.24625485, 0.454443,      1,              2.98352834])
            #self.SyntheticData_dict['He_Flux']      = array([0.10100783,    0.01691781,     0.03924855,     0.12725256,  0.03553524,    0.04162797])
            
            self.SyntheticData_dict['H_Flux']       = array([0.24666367, 0.45494969,    1,              2.97990939])
            self.SyntheticData_dict['H_wave']       = array([4101.742,   4340.471,      4862.683,       6562.819])
            self.SyntheticData_dict['H_Ions']       = ['Hdelta_6_2',    'Hgamma_5_2',   'Hbeta_4_2',    'Halpha_3_2']
            self.SyntheticData_dict['H_labels']     = ['H1_4102A',      'H1_4340A',     'H1_4861A',     'H1_6563A']
            self.SyntheticData_dict['H_Eqw']        = [50.0,            50.0,           250,             300.0]
            self.SyntheticData_dict['H_EqwErr']     = [1.0,             1.0,            12.5,            14]
            self.SyntheticData_dict['H_hlambda']    = [1.0,             1.0,            1.0,             1.0]
            self.SyntheticData_dict['H_error']      = self.SyntheticData_dict['H_Flux'] * 0.01

            self.SyntheticData_dict['He_Flux']      = array([0.10121858,    0.01695164,     0.03928185,     0.12712208,  0.03548869,    0.0415693])
            self.SyntheticData_dict['He_wave']      = array([ 3889.0,       4026.0,         4471.0,         5876.0,      6678.0,        7065.0])
            self.SyntheticData_dict['He_labels']    = ['He1_3889A',         'He1_4026A',   'He1_4471A',   'He1_5876A',  'He1_6678A',    'He1_7065A']
            self.SyntheticData_dict['He_Eqw']       = [10.0,                10.0,           10.0,           10.0,        10.0,          10.0]
            self.SyntheticData_dict['He_EqwErr']    = [1.0,                 1.0,            1.0,            1.0,         1.0,           1.0]
            self.SyntheticData_dict['He_hlambda']   = [1.0,                 1.0,            1.0,            1.0,         1.0,           1.0] 
            self.SyntheticData_dict['He_error']     = self.SyntheticData_dict['He_Flux'] * 0.02

            self.SyntheticData_dict['TOIII']        = 17000
            self.SyntheticData_dict['y_plus']       = 0.085
            self.SyntheticData_dict['n_e']          = 500.0
            self.SyntheticData_dict['a_He']         = 0.5
            self.SyntheticData_dict['tau']          = 1.0
            self.SyntheticData_dict['Te_0']         = 16000.0
            self.SyntheticData_dict['cHbeta']       = 0.1
            self.SyntheticData_dict['a_H']          = 1.0
            self.SyntheticData_dict['xi']           = 1.0
                 
        if Model == 'Model3':
                 
            self.SyntheticData_dict['H_Flux']       = array([0.24666367, 0.45494969,    1,              2.97990939])
            self.SyntheticData_dict['H_wave']       = array([4101.742,   4340.471,      4862.683,       6562.819])
            self.SyntheticData_dict['H_Ions']       = ['Hdelta_6_2',    'Hgamma_5_2',   'Hbeta_4_2',    'Halpha_3_2']
            self.SyntheticData_dict['H_labels']     = ['H1_4102A',      'H1_4340A',     'H1_4861A',     'H1_6563A']
            self.SyntheticData_dict['H_Eqw']        = [50.0,            50.0,           250,             300.0]
            self.SyntheticData_dict['H_EqwErr']     = [1.0,             1.0,            12.5,            14]
            self.SyntheticData_dict['H_hlambda']    = [1.0,             1.0,            1.0,             1.0]
            self.SyntheticData_dict['H_error']      = self.SyntheticData_dict['H_Flux'] * 0.01

            self.SyntheticData_dict['He_Flux']      = array([0.10121858,    0.01695164,     0.03928185,     0.12712208,  0.03548869,    0.0415693,      0.76218916])
            self.SyntheticData_dict['He_wave']      = array([ 3889.0,       4026.0,         4471.0,         5876.0,      6678.0,        7065.0,         10830.0])
            self.SyntheticData_dict['He_labels']    = ['He1_3889A',         'He1_4026A',   'He1_4471A',   'He1_5876A',  'He1_6678A',    'He1_7065A',    'He1_10830A']
            self.SyntheticData_dict['He_Eqw']       = [10.0,                10.0,           10.0,           10.0,        10.0,          10.0,           10.0]
            self.SyntheticData_dict['He_EqwErr']    = [1.0,                 1.0,            1.0,            1.0,         1.0,           1.0,            1.0]
            self.SyntheticData_dict['He_hlambda']   = [1.0,                 1.0,            1.0,            1.0,         1.0,           1.0,            1.0] 
            self.SyntheticData_dict['He_error']     = self.SyntheticData_dict['He_Flux'] * 0.02

            self.SyntheticData_dict['TOIII']        = 17000
            self.SyntheticData_dict['y_plus']       = 0.085
            self.SyntheticData_dict['n_e']          = 500.0
            self.SyntheticData_dict['a_He']         = 0.5
            self.SyntheticData_dict['tau']          = 1.0
            self.SyntheticData_dict['Te_0']         = 16000.0
            self.SyntheticData_dict['cHbeta']       = 0.1
            self.SyntheticData_dict['a_H']          = 1.0
            self.SyntheticData_dict['xi']           = 1.0  
  
                                   
        return
    
    def Calculate_Synthetic_Fluxes(self, model):
        
        self.Import_Synthetic_Fluxes(Model = model)
        
        self.Check_EmissionLinesObserved(self.SyntheticData_dict)
        
        self.Preload_Data(Hbeta_Normalized=True, Deblend_Check=False)
        
        Hydrogen_Dict   = self.Calculate_H_Parameters_Vectors(self.SyntheticData_dict['Te_0'], self.SyntheticData_dict['n_e'], self.SyntheticData_dict['tau'])
        Helium_Dict     = self.Calculate_He_Parameters_Vectors(self.SyntheticData_dict['Te_0'], self.SyntheticData_dict['n_e'], self.SyntheticData_dict['tau'])
    
    
    
    
        H_Flux          = self.H_Flux_theo(self.SyntheticData_dict['xi'], self.SyntheticData_dict['cHbeta'], self.SyntheticData_dict['a_H'], Hydrogen_Dict)
        He_Flux         = self.He_Flux_theo_nof(self.SyntheticData_dict['xi'], self.SyntheticData_dict['cHbeta'], self.SyntheticData_dict['a_H'], self.SyntheticData_dict['a_He'], self.SyntheticData_dict['y_plus'], Helium_Dict)
    
        print 'Hydrogen fluxes', H_Flux
        print 'Helium fluxes', He_Flux
    
        return
    
    def Import_Object_Data(self, Filefolder, CodeName, Lineslog_Extension):
        
        self.ObjectData_dict = OrderedDict()
            
        String_Columns      = [self.Labels_ColumnHeader, self.Ion_ColumnHeader]
        Float_Columns       = [self.Wavelength_ColumnHeader, self.GaussianFlux_ColumnHeader, self.GaussianError_ColumnHeader, self.Line_Continuum_ColumnHeader, self.EqW_ColumnHeader, self.EqW_error_ColumnHeader]
        
        Lineslog_Address    = Filefolder + CodeName + Lineslog_Extension
        
        Labels, Ions                                                = self.get_ColumnData(String_Columns, Lineslog_Address, HeaderSize = 2, StringIndexes = True, datatype = str, unpack_check = True) 
        Wavelengths, Fluxes, Fluxes_error, h_lambda, Eqw, Eqw_error = self.get_ColumnData(Float_Columns, Lineslog_Address, HeaderSize = 2, StringIndexes = True, unpack_check = True)

        self.ObjectData_dict['H_labels']        = list(Labels)
        self.ObjectData_dict['H_Ions']          = list(Ions)
        self.ObjectData_dict['H_Flux']          = Fluxes
        self.ObjectData_dict['H_error']         = Fluxes_error
        self.ObjectData_dict['H_wave']          = Wavelengths
        self.ObjectData_dict['H_Eqw']           = Eqw
        self.ObjectData_dict['H_EqwErr']        = Eqw_error
        self.ObjectData_dict['H_hlambda']        = h_lambda
        
        self.ObjectData_dict['He_labels']       = list(Labels)
        self.ObjectData_dict['He_Ions']         = list(Ions)
        self.ObjectData_dict['He_Flux']         = Fluxes
        self.ObjectData_dict['He_error']        = Fluxes_error
        self.ObjectData_dict['He_wave']         = Wavelengths
        self.ObjectData_dict['He_Eqw']          = Eqw
        self.ObjectData_dict['He_EqwErr']       = Eqw_error
        self.ObjectData_dict['He_hlambda']      = h_lambda
        
        #TOIII calculated from TSIII, if not we use TOIII, if not we use 17000
        TOIII_from_TSIII                        = self.GetParameter_ObjLog(CodeName, Filefolder, Parameter = 'TOIII_approx_TSIII', Assumption = 'float')
        TOIII                                   = self.GetParameter_ObjLog(CodeName, Filefolder, Parameter = 'TOIII', Assumption = 'float')
        
        if TOIII_from_TSIII != None:
            self.ObjectData_dict['TOIII']   = TOIII_from_TSIII
        elif TOIII != None:
            self.ObjectData_dict['TOIII']   = TOIII
        else: 
            self.ObjectData_dict['TOIII']   = 15000.0
        
        #nSII density to be used in the priors definition. If it could not be calculated the output value is 100
        self.ObjectData_dict['nSII']        = self.GetParameter_ObjLog(CodeName, Filefolder, Parameter = 'nSII', Assumption = 'Min_Den')
        
        self.ObjectData_dict['cHbeta_obs']  = self.GetParameter_ObjLog(CodeName, Filefolder, Parameter = 'cHBeta', Assumption = 'cHbeta_min')
        
        return
    
    def Check_EmissionLinesObserved(self, Data_Dict):
        
        #Empty the lists of candidate lines for Hydrogen and Helium
        del self.Cand_Hydrogen_Lines[:]
        del self.Cand_Helium_Lines[:]
                
        #Loop through the hydrogen lines to store the properties of those we can use to perform the analysis
        Obs_HydrogenLabels                                  = Data_Dict['H_labels']
        
        for i in range(len(self.posHydrogen_Lines)):
            Line_Label                                      = self.posHydrogen_Lines[i]
            if Line_Label in Obs_HydrogenLabels:
                Line_Index                                  = Obs_HydrogenLabels.index(Line_Label)
                self.Flux_dict[Line_Label]                  = Data_Dict['H_Flux'][Line_Index]   
                self.Error_dict[Line_Label]                 = Data_Dict['H_error'][Line_Index]
                self.Wave_dict[Line_Label]                  = Data_Dict['H_wave'][Line_Index]
                self.EqW_dict[Line_Label]                   = Data_Dict['H_Eqw'][Line_Index]
                self.EqWerror_dict[Line_Label]              = Data_Dict['H_EqwErr'][Line_Index]
                self.hlambda_dict[Line_Label]               = Data_Dict['H_hlambda'][Line_Index]
                self.PynebCode_dict[Line_Label]             = Data_Dict['H_Ions'][Line_Index][Data_Dict['H_Ions'][Line_Index].find('_')+1:len(Data_Dict['H_Ions'][Line_Index])]
                self.Cand_Hydrogen_Lines.append(Line_Label)
                                
        #Loop through the helium lines to store the properties of those we can use to perform the analysis
        Obs_HeliumLabels                                    = Data_Dict['He_labels']
        for i in range(len(self.posHelium_Lines)):
            Line_Label                                      = self.posHelium_Lines[i]
            if Line_Label in Obs_HeliumLabels:
                Line_Index                                  = Obs_HeliumLabels.index(Line_Label)
                self.Flux_dict[Line_Label]                  = Data_Dict['He_Flux'][Line_Index]   
                self.Error_dict[Line_Label]                 = Data_Dict['He_error'][Line_Index]
                self.Wave_dict[Line_Label]                  = Data_Dict['He_wave'][Line_Index]
                self.EqW_dict[Line_Label]                   = Data_Dict['He_Eqw'][Line_Index]
                self.EqWerror_dict[Line_Label]              = Data_Dict['He_EqwErr'][Line_Index]
                self.hlambda_dict[Line_Label]               = Data_Dict['He_hlambda'][Line_Index]
                self.PynebCode_dict[Line_Label]             = Line_Label[Line_Label.find('_')+1:-1]+'.0'
                self.Cand_Helium_Lines.append(Line_Label)
        
        print 'Hydrogen lines'
        print self.Cand_Hydrogen_Lines
        print 'Helium lines'
        print self.Cand_Helium_Lines
        
        #Since the Hbeta line is not used for the fitting we remove it from the candidates lines list. However, its properties are still stored in the dictionaries
        self.Cand_Hydrogen_Lines.remove(self.HBeta_label)
        
        #Since the He_3889A line is blended we add new key He_3889A_blended which will be store the observed, blended, value
        if self.He3889_label in self.Cand_Helium_Lines:
            self.Flux_dict[self.He3889blended_label]        = self.Flux_dict[self.He3889_label]
            self.He3889_check = True
        else:
            self.He3889_check = False
        
        #Define number of lines variables to speed up the calculation
        self.nHydrogen                                      = len(self.Cand_Hydrogen_Lines)
        self.nHelium                                        = len(self.Cand_Helium_Lines)
        
        self.nHydrogen_range                                = range(self.nHydrogen)
        self.nHelium_range                                  = range(self.nHelium)
                
        #Oxygen temperature prior
        self.TOIIIprior                                     = Data_Dict['TOIII']
        self.TOIIIprior_sigma                               = self.TOIIIprior * 0.2
        
    def Preload_Data(self, Hbeta_Normalized = True, Deblend_Check = True):

        #Define the vectors where we store the physical parameters
        self.Flux_H_vector                          = zeros(self.nHydrogen)
        self.Error_H_vector                         = zeros(self.nHydrogen)
        self.Emissivity_H_vector                    = zeros(self.nHydrogen)
        self.Kalpha_vector                          = zeros(self.nHydrogen)
        self.flambda_H_vector                       = zeros(self.nHydrogen)
        #self.Eqw_H_vector                          = zeros(self.nHydrogen)
        #self.EqwError_H_vector                     = zeros(self.nHydrogen)
        self.hlambda_H_vector                       = ones(self.nHydrogen)

        self.Flux_He_vector                         = zeros(self.nHelium)
        self.Error_He_vector                        = zeros(self.nHelium)
        self.Emissivity_He_vector                   = zeros(self.nHelium)
        self.ftau_He_vector                         = zeros(self.nHelium)
        self.flambda_He_vector                      = zeros(self.nHelium)
        #self.Eqw_He_vector                         = zeros(self.nHelium)
        #self.EqwError_He_vector                    = zeros(self.nHelium)
        self.hlambda_He_vector                      = ones(self.nHelium)
      
        #Define HBeta values in advance
        self.Hbeta_Flux                             = self.Flux_dict[self.HBeta_label]
        self.Hbeta_error                            = self.Error_dict[self.HBeta_label]
        self.Hbeta_EW                               = self.EqW_dict[self.HBeta_label]
        self.Hbeta_EWerror                          = self.EqWerror_dict[self.HBeta_label]      
        self.hbeta_hlambda                          = self.hlambda_dict[self.HBeta_label]
      
        #Calculate in advance observed physical parameters vectors for Hydrogen lines
        for i in range(self.nHydrogen):
            Line_Label                              = self.Cand_Hydrogen_Lines[i]        
            self.Flux_H_vector[i]                   = self.Flux_dict[Line_Label]
            self.Error_H_vector[i]                  = self.Error_dict[Line_Label]
            self.hlambda_H_vector[i]                = self.hlambda_dict[Line_Label]
            self.flambda_H_vector[i]                = self.flambda_dict[Line_Label]

        for i in range(self.nHelium):
            Line_Label                              = self.Cand_Helium_Lines[i]
            self.Flux_He_vector[i]                  = self.Flux_dict[Line_Label]
            self.Error_He_vector[i]                 = self.Error_dict[Line_Label]
            self.flambda_He_vector[i]               = self.flambda_dict[Line_Label]
            self.hlambda_He_vector[i]               = self.hlambda_dict[Line_Label]             

        #Combine Hydrogen and Helium values into a single vector
        if Hbeta_Normalized: 
            self.H_He_Obs_Flux                      = concatenate([self.Flux_H_vector, self.Flux_He_vector])
            self.H_He_Obs_Error                     = concatenate([self.Error_H_vector, self.Error_He_vector])

        else:
            self.H_He_Obs_Flux                      = concatenate([self.Flux_H_vector, self.Flux_He_vector])    / self.Hbeta_Flux
            self.H_He_Obs_Error                     = concatenate([self.Error_H_vector, self.Error_He_vector])  / self.Hbeta_Flux
        
        #Getting the index for the He1_3889A line in advance
        if (self.He3889_label in self.Cand_Helium_Lines) and (Deblend_Check == True):
            self.He3889_index = where(self.H_He_Obs_Flux == self.Flux_dict[self.He3889blended_label] / self.Hbeta_Flux)[0][0]
            self.Deblend_He3889A_line(a_H = 1.0, T_4 = self.ObjectData_dict['TOIII'] / 10000, cHbeta = self.ObjectData_dict['cHbeta_obs'])
        
        #Dictionary with the vectors
        self.Data_Dict = {'Hbeta_Kalpha'    : None, 
                     'Hbeta_emis'           : None,
                     'Emissivity_H_vector'  : None,
                     'Kalpha_vector'        : None,
                     'Emissivity_He_vector' : None,
                     'ftau_He_vector'       : None,
                     'T_4'                  : None} 
        
    def Calculate_H_Parameters_Vectors(self, T_e, n_e, tau):    
        
        #Calculate in advance the T_4 parameter
        self.Data_Dict['T_4'] = T_e / 10000.0
        
        #Calculate the hbeta parameters
        self.Data_Dict['Hbeta_Kalpha']              = self.Kalpha_Ratio_H(T_4 = self.Data_Dict['T_4'], H_label=self.HBeta_label)
        self.Data_Dict['Hbeta_emis']                = self.H1.getEmissivity(T_e, n_e, label = self.PynebCode_dict[self.HBeta_label])

        #Calculate physical parameters for Hydrogen lines
        for i in self.nHydrogen_range:
            self.Emissivity_H_vector[i]             = self.H1.getEmissivity(T_e, n_e, label = self.PynebCode_dict[self.Cand_Hydrogen_Lines[i]])
            self.Kalpha_vector[i]                   = self.Kalpha_Ratio_H(T_4 = self.Data_Dict['T_4'], H_label=self.Cand_Hydrogen_Lines[i])
        
        self.Data_Dict['Emissivity_H_vector']       = self.Emissivity_H_vector
        self.Data_Dict['Kalpha_vector']             = self.Kalpha_vector
                
        return self.Data_Dict    
    
    def Calculate_He_Parameters_Vectors(self, T_e, n_e, tau):
    
        #Calculate physical parameters for Helium lines
        for i in self.nHelium_range:
            self.Emissivity_He_vector[i]            = self.He1.getEmissivity(T_e, n_e, label = self.PynebCode_dict[self.Cand_Helium_Lines[i]])
            self.ftau_He_vector[i]                  = self.OpticalDepth_He(tau = tau, T_4 = self.Data_Dict['T_4'], n_e = n_e, He_label = self.Cand_Helium_Lines[i])    
        
        self.Data_Dict['Emissivity_He_vector']      = self.Emissivity_He_vector
        self.Data_Dict['ftau_He_vector']            = self.ftau_He_vector
        
        return self.Data_Dict

    def H_Flux_theo(self, xi, cHbeta, a_H, data_dict):
                
        #Calculate the emissivities for each of the lines for the given temperature and density
        Emissivities_module = data_dict['Emissivity_H_vector'] / data_dict['Hbeta_emis'] 
                
        #Calculate the Collisional excitation fraction
        CR_Module           = (1.0 + 0.0001* xi *data_dict['Kalpha_vector']) / (1.0 + 0.0001* xi * data_dict['Hbeta_Kalpha'] )
                
        #Calculate the reddening component
        f_module            = power(10, -1 * self.flambda_H_vector * cHbeta)
          
        #Calculate the Hbeta normalization module
        EW_Hbeta_module     = (self.Hbeta_EW + a_H) / self.Hbeta_EW
        
        #Calculate stellar absorption module
        a_H_module          = (a_H * self.hlambda_H_vector) / (self.Hbeta_EW * self.hbeta_hlambda)
        
        #Calculate theoretical Hydrogen flux for each emission line
        H_Flux              = Emissivities_module * CR_Module * f_module * EW_Hbeta_module - a_H_module
                     
        return H_Flux

    def He_Flux_theo_nof(self, xi, cHbeta, a_H, a_He, y_plus, data_dict):
                      
        #Calculate the emissivities for each of the lines for the given temperature and density
        Emissivities_module = data_dict['Emissivity_He_vector'] / data_dict['Hbeta_emis']
                
        #Calculate the collisional excitation fraction
        CR_Module           = 1 / (1.0 + 0.0001* xi * data_dict['Hbeta_Kalpha'])

        #Calculate the reddening component
        f_module            = power(10, -1 * self.flambda_He_vector * cHbeta)

        #Calculate the Hbeta normalization module
        EW_Hbeta_module     = (self.Hbeta_EW + a_H) / self.Hbeta_EW
        
        #Calculate stellar absorption module
        a_He_module         = (a_He * self.hlambda_He_vector) / (self.Hbeta_EW * self.hbeta_hlambda)
             
        #Calculate theoretical Hydrogen flux for each emission line
        He_Flux             = y_plus * Emissivities_module * data_dict['ftau_He_vector'] * CR_Module * f_module * EW_Hbeta_module - a_He_module

#         if self.He3889_check:
#             self.Deblend_He3889A_line(a_H, data_dict['T_4'], cHbeta)

        return He_Flux
               
    def get_flambda_dict(self, lines_labels, lines_wavelengths, R_v=3.2):
    
        x_true          = 1.0 / (array(lines_wavelengths) / 10000.0)
        y               = x_true - 1.82
    
        y_coeffs        = array([ones(len(y)), y, power(y, 2), power(y, 3), power(y, 4), power(y, 5), power(y, 6), power(y, 7)])
        a_coeffs        = array([1, 0.17699,    -0.50447,   -0.02427,   0.72085,    0.01979,    -0.77530,   0.32999])
        b_coeffs        = array([0, 1.41338,    2.28305,   1.07233,   -5.38434,    -0.62251,    5.30260,   -2.09002])
        
        a_x             = dot(a_coeffs,y_coeffs)
        b_x             = dot(b_coeffs,y_coeffs)
        
        X_x             = a_x + b_x / R_v
        
        y_beta          = (1 / (4862.683 / 10000)) - 1.82
        y_beta_coeffs   = array([1, y_beta, power(y_beta, 2), power(y_beta, 3), power(y_beta, 4), power(y_beta, 5), power(y_beta, 6), power(y_beta, 7)])
        
        X_x_beta        = dot(a_coeffs,y_beta_coeffs) + dot(b_coeffs,y_beta_coeffs) / R_v
    
        f               = X_x / X_x_beta - 1
        
        return dict(zip(lines_labels , f))
         
    def Kalpha_Ratio_H(self, T_4, H_label):
                
        K_alpha_Ratio   = sum(self.Coef_Kalpha_dict[H_label][0] * exp(self.Coef_Kalpha_dict[H_label][1] / T_4) * power(T_4, self.Coef_Kalpha_dict[H_label][2]))
        
        return K_alpha_Ratio
    
    def OpticalDepth_He(self, tau, T_4, n_e, He_label):
                        
        f_tau   = 1 + (tau/2) * (self.Coef_ftau_dict[He_label][0] + (self.Coef_ftau_dict[He_label][1] + self.Coef_ftau_dict[He_label][2]*n_e + self.Coef_ftau_dict[He_label][3]*n_e*n_e) * T_4)

        return f_tau
    
    def Deblend_He3889A_line(self, a_H, T_4, cHbeta):
        
        self.H_He_Obs_Flux[self.He3889_index] = (self.Flux_dict[self.He3889blended_label] / self.Flux_dict[self.HBeta_label]) * ((self.EqW_dict[self.He3889_label] + a_H) / self.EqW_dict[self.He3889_label]) - (0.104 * power(T_4, 0.046)) * (power(10 ,-self.flambda_dict[self.He3889_label] * cHbeta))  
        
        return self.H_He_Obs_Flux     
class He_Inference_Abundance:
    def __init__(self):

        # Declare Hydrogen and Helium collisional lines for the analysis
        self.Hydrogen_Lines = ["Hdelta_6_2", "Hgamma_5_2", "Hbeta_4_2", "Halpha_3_2"]
        self.Hydrogen_Labels = ["6_2", "5_2", "4_2", "3_2"]
        self.Hydrogen_Wavelengths = [4101.742, 4340.471, 4862.683, 6562.819]

        self.Helium_Lines = ["He1_3889", "He1_4026.0", "He1_4471.0", "He1_5876.0", "He1_6678.0", "He1_7065.0"]
        self.Helium_Labels = ["3889.0", "4026.0", "4471.0", "5876.0", "6678.0", "7065.0"]
        self.Helium_Wavelengths = [3889.0, 4026.0, 4471.0, 5876.0, 6678.0, 7065.0]

        # Define indexes and labels to speed up the code
        self.HBeta_label = "4_2"
        self.HBeta_Index = self.Hydrogen_Lines.index("Hbeta_4_2")
        self.nHydrogen = range(len(self.Hydrogen_Lines))
        self.nHelium = range(len(self.Helium_Lines))

        # THIS TRICK IS NECCESARY SO THAT WE DO NOT INCLUDE THE HBETA LINE IN THE CALCULATION
        self.nHydrogen.remove(self.HBeta_Index)
        Valid_H_Lines = list(self.Hydrogen_Wavelengths)
        del Valid_H_Lines[self.HBeta_Index]

        # Declare pyneb Hydrogen and Helium atoms to calculate emissivities
        self.H1 = RecAtom("H", 1)
        self.He1 = RecAtom("He", 1)
        self.H_emissivity_Vector = zeros(len(self.nHydrogen))  # Array to store the emissivities for each of the labels
        self.He_emissivity_Vector = zeros(
            len(self.Helium_Labels)
        )  # Array to store the emissivities for each of the labels

        # Import collisional coefficients table
        self.H_CollCoeff_Matrix = self.Import_Coll_Coeff_Table("H")
        self.He_CollCoeff_Matrix = self.Import_Coll_Coeff_Table("He")
        self.H_CRratio_Vector = zeros(len(self.nHydrogen))  # Array to store the C/R for each of the HydrogenLines
        self.He_CRratio_Vector = zeros(len(self.Helium_Labels))  # Array to store the C/R for each of the HydrogenLines

        # Import Optical depth function for He lines
        self.He_OpticalDepth_Matrix = self.Import_OpticalDepth_Coeff_Table("He")
        self.f_Hetau_vector = zeros(len(self.Helium_Labels))

        # Calculate f_lambda in advance law configuration (from Cardelli, Clayton and Mathis law)
        self.R_v = 3.1
        self.a_coeffs = array([1.0, 0.17699, -0.50447, -0.02427, 0.72085, 0.01979, -0.77530, 0.32999])
        self.b_coeffs = array([0.0, 1.41338, 2.28305, 1.07233, -5.38434, -0.62251, 5.30260, -2.09002])

        self.f_H_vector = self.get_flambda_vector(array(Valid_H_Lines))
        self.f_He_vector = self.get_flambda_vector(array(self.Helium_Wavelengths))

        # Extra
        self.EmptyRowFormat = "nan"

    def Import_TableData(self, Address, Columns):

        Imported_Array = genfromtxt(Address, dtype=float, usecols=Columns, skiprows=2).T
        Datarray = Imported_Array[:, ~isnan(Imported_Array).all(0)]

        return Datarray

    def Import_Coll_Coeff_Table(self, Atom):

        if Atom == "H":
            # Default Hydrogen table address
            Hydrogen_CollCoeff_TableAddress = (
                "/home/vital/Workspace/Dazer/Astro_Libraries/Neutral_Hydrogen_Collisional_Correction_coef.txt"
            )

            # Empty container for the coefficient matrix
            H_Matrix = [0] * len(self.Hydrogen_Labels)

            # The Columns are stored from lower to higher wavelength values in the for of coefficients a, b, c
            for i in range(len(self.Hydrogen_Labels)):

                Data_Columns = [0 + 3 * i, 1 + 3 * i, 2 + 3 * i]

                H_Matrix[i] = self.Import_TableData(Hydrogen_CollCoeff_TableAddress, Data_Columns)

            return H_Matrix

        if Atom == "He":
            # Default Helium table address
            Helium_CollCoeff_TableAddress = (
                "/home/vital/Workspace/Dazer/Astro_Libraries/Neutral_Helium_Collisional_Correction_coef.txt"
            )

            # Empty container for the coefficient matrix
            He_Matrix = [0] * len(self.Helium_Labels)

            # The Columns are stored from lower to higher wavelength values in the for of coefficients a, b, c
            for i in range(len(self.Helium_Labels)):

                Data_Columns = [0 + 3 * i, 1 + 3 * i, 2 + 3 * i]

                He_Matrix[i] = self.Import_TableData(Helium_CollCoeff_TableAddress, Data_Columns)

            return He_Matrix

    def Import_OpticalDepth_Coeff_Table(self, Atom):

        if Atom == "He":
            # Default Helium table address
            Helium_OpticalDepth_TableAddress = (
                "/home/vital/Workspace/Dazer/Astro_Libraries/Helium_OpticalDepthFunction_Coefficients.txt"
            )

            # Empty container for the coefficient matrix
            He_Matrix_f_tauCoeffs = [0] * len(self.Helium_Labels)

            for i in range(len(self.Helium_Labels)):
                He_Matrix_f_tauCoeffs[i] = loadtxt(
                    Helium_OpticalDepth_TableAddress, dtype=float, skiprows=2, usecols=(i,)
                )

            return He_Matrix_f_tauCoeffs

    def Import_Synthetic_Fluxes(self, case="case1"):
        # Old ones
        #        H_Flux_0    = array([0.24585991, 0.45343263, 2.95803687])
        #        He_Flux_0   = array([ 0.08913865,  0.01283334,  0.0318714,   0.09890309,  0.02582589,  0.02366051])
        if case == "case1":

            H_Flux_0 = array([0.24585991, 0.45343263, 2.95803687])
            He_Flux_0 = array([0.0891384, 0.01283333, 0.03187135, 0.09890274, 0.02582588, 0.02366021])

        if case == "case2":

            H_Flux_0 = array([0.24585991, 0.45343263, 2.95803687])
            He_Flux_0 = array([0.10059744, 0.01684244, 0.03908421, 0.12673761, 0.03538569, 0.04145339])

        return H_Flux_0, He_Flux_0

    def H_Flux_theo(self, T_e, n_e, xi, cHbeta, a_H, h_Hlambda, a_Hbeta, h_Hbeta, EW_Hbeta):

        # Calculate the emissivities for each of the lines for the given temperature and density
        self.get_H_EmissivityVector(T_e, n_e)
        E_Hbeta = self.H1.getEmissivity(T_e, n_e, label=self.HBeta_label)
        Emissivities_module = self.H_emissivity_Vector / E_Hbeta

        # Calculate the Collisional excitation fraction
        self.get_H_CRratio_Vector(T_e)
        CR_Hbeta = self.H_Kalpha_Ratio(self.HBeta_Index, T_e)
        CR_Module = (1.0 + 0.0001 * xi * self.H_CRratio_Vector) / (1.0 + 0.0001 * xi * CR_Hbeta)

        # Calculate the reddening component
        f_module = power(10, -1 * self.f_H_vector * cHbeta)

        # Calculate the Hbeta normalization module
        EW_Hbeta_module = (EW_Hbeta + a_H) / EW_Hbeta

        # Calculate stellar absorption module
        a_H_module = (a_H * h_Hlambda) / (EW_Hbeta * h_Hbeta)

        # Calculate theoretical Hydrogen flux for each emission line
        H_Flux = Emissivities_module * CR_Module * f_module * EW_Hbeta_module - a_H_module

        #         print 'Emissivity ratio',   self.H_emissivity_Vector[-1] / E_Hbeta
        #         print 'C_R_Module',         CR_Module[-1]
        #         print 'H_CRratio_Vector',   self.H_CRratio_Vector
        #         print 'CR_Hbeta',           CR_Hbeta
        #         print 'f_lambda', self.f_H_vector
        #         print 'f_lambda module',    f_module
        return H_Flux

    def He_Flux_theo(self, T_e, n_e, xi, cHbeta, a_H, a_He, h_Helambda, a_Hbeta, h_Hbeta, EW_Hbeta, y_plus, tau):

        # Calculate the optical depth correction factor
        self.get_He_ftau_vector(T_e, n_e, tau)

        # Calculate the emissivities for each of the lines for the given temperature and density
        self.get_He_Emissivity_Vector(T_e, n_e)
        E_Hbeta = self.H1.getEmissivity(T_e, n_e, label=self.HBeta_label)
        Emissivities_module = self.He_emissivity_Vector / E_Hbeta

        # Calculate the collisional excitation fraction
        self.get_He_CRratio_Vector(T_e, n_e)
        CR_Hbeta = self.H_Kalpha_Ratio(self.HBeta_Index, T_e)
        CR_Module = (1.0 + 0.0001 * xi * self.He_CRratio_Vector) / (1.0 + 0.0001 * xi * CR_Hbeta)

        # Calculate the reddening component
        f_module = power(10, -1 * self.f_He_vector * cHbeta)

        # Calculate the Hbeta normalization module
        EW_Hbeta_module = (EW_Hbeta + a_H) / EW_Hbeta

        # Calculate stellar absorption module
        a_H_module = (a_He * h_Helambda) / (EW_Hbeta * h_Hbeta)

        He_Flux = (
            y_plus * self.f_Hetau_vector * Emissivities_module * CR_Module * f_module * EW_Hbeta_module - a_H_module
        )

        return He_Flux

    def He_Flux_theo_nof(self, T_e, n_e, xi, cHbeta, a_He, h_Helambda, a_Hbeta, h_Hbeta, EW_Hbeta, y_plus, tau):

        # Calculate the optical depth correction factor
        self.get_He_ftau_vector(T_e, n_e, tau)

        # Calculate the emissivities for each of the lines for the given temperature and density
        self.get_He_Emissivity_Vector(T_e, n_e)
        E_Hbeta = self.H1.getEmissivity(T_e, n_e, label=self.HBeta_label)
        Emissivities_module = self.He_emissivity_Vector / E_Hbeta

        # Calculate the collisional excitation fraction
        CR_Hbeta = self.H_Kalpha_Ratio(self.HBeta_Index, T_e)
        CR_Module = 1 / (1.0 + 0.0001 * xi * CR_Hbeta)

        # Calculate the reddening component
        f_module = power(10, -1 * self.f_He_vector * cHbeta)

        # Calculate the Hbeta normalization module
        EW_Hbeta_module = (EW_Hbeta + a_Hbeta) / EW_Hbeta

        # Calculate stellar absorption module
        a_H_module = (a_He * h_Helambda) / (EW_Hbeta * h_Hbeta)

        He_Flux = (
            y_plus * self.f_Hetau_vector * Emissivities_module * CR_Module * f_module * EW_Hbeta_module - a_H_module
        )

        return He_Flux

    def get_H_EmissivityVector(self, T_e, n_e):
        # WARNING: SHOULD WE CREATE ANOTHER LIST TO IMPROVE THIS?
        for i in range(len(self.nHydrogen)):
            self.H_emissivity_Vector[i] = self.H1.getEmissivity(T_e, n_e, label=self.Hydrogen_Labels[self.nHydrogen[i]])

    def get_He_Emissivity_Vector(self, T_e, n_e):
        for i in self.nHelium:
            self.He_emissivity_Vector[i] = self.He1.getEmissivity(T_e, n_e, label=self.Helium_Labels[i])

    def get_H_CRratio_Vector(self, T_e):

        T_4 = T_e / 10000.0

        # WARNING: SHOULD WE CREATE ANOTHER LIST TO IMPROVE THIS?
        for i in range(len(self.nHydrogen)):

            self.nHydrogen[i]
            self.H_CRratio_Vector[i] = sum(
                self.H_CollCoeff_Matrix[self.nHydrogen[i]][0]
                * exp(self.H_CollCoeff_Matrix[self.nHydrogen[i]][1] / T_4)
                * power(T_4, self.H_CollCoeff_Matrix[self.nHydrogen[i]][2])
            )

    def get_He_CRratio_Vector(self, T_e, n_e):

        T_4 = T_e / 10000.0
        for i in self.nHelium:
            self.He_CRratio_Vector[i] = (
                1
                / (1 + (3552 * power(T_4, -0.55) / n_e))
                * sum(
                    self.He_CollCoeff_Matrix[i][0]
                    * power(T_4, self.He_CollCoeff_Matrix[i][1])
                    * exp(self.He_CollCoeff_Matrix[i][2] / T_4)
                )
            )

    def get_He_ftau_vector(self, T_e, n_e, tau):

        T_4 = T_e / 10000.0

        for i in self.nHelium:
            self.f_Hetau_vector[i] = 1 + (tau / 2) * (
                self.He_OpticalDepth_Matrix[i][0]
                + (
                    self.He_OpticalDepth_Matrix[i][1]
                    + self.He_OpticalDepth_Matrix[i][2] * n_e
                    + self.He_OpticalDepth_Matrix[i][3] * n_e * n_e
                )
                * T_4
            )

    def get_flambda_vector(self, wavelengths, R_v=3.1):

        x_true = 1.0 / (wavelengths / 10000.0)
        y = x_true - 1.82

        y_coeffs = array(
            [ones(len(y)), y, power(y, 2), power(y, 3), power(y, 4), power(y, 5), power(y, 6), power(y, 7)]
        )
        a_coeffs = array([1, 0.17699, -0.50447, -0.02427, 0.72085, 0.01979, -0.77530, 0.32999])
        b_coeffs = array([0, 1.41338, 2.28305, 1.07233, -5.38434, -0.62251, 5.30260, -2.09002])

        a_x = dot(a_coeffs, y_coeffs)
        b_x = dot(b_coeffs, y_coeffs)

        X_x = a_x + b_x / R_v

        y_beta = (1 / (4862.683 / 10000)) - 1.82
        y_beta_coeffs = array(
            [
                1,
                y_beta,
                power(y_beta, 2),
                power(y_beta, 3),
                power(y_beta, 4),
                power(y_beta, 5),
                power(y_beta, 6),
                power(y_beta, 7),
            ]
        )

        X_x_beta = dot(a_coeffs, y_beta_coeffs) + dot(b_coeffs, y_beta_coeffs) / R_v

        f = X_x / X_x_beta - 1

        return f

    def Hydrogen_Emissivity(self, T_e, n_e, H_label):
        # The hydrogen labels have the format : Halpha => '3_2'
        return self.H1.getEmissivity(T_e, n_e, label=H_label)

    def Helium_Emissivity(self, T_e, n_e, He_label):
        # The Helium labels have the format : He1_5876 => '5876.0'
        return self.He1.getEmissivity(tem=T_e, den=n_e, label=He_label)

    def H_Kalpha_Ratio(self, line_label, T_e):

        Coeff_Table = self.H_CollCoeff_Matrix[line_label]
        T_4 = T_e / 10000.0

        K_alpha_Ratio = sum(Coeff_Table[0] * exp(Coeff_Table[1] / T_4) * power(T_4, Coeff_Table[2]))

        return K_alpha_Ratio

    def He_CR_ratio(self, line_label, T_e, n_e):

        Coeff_Table = self.He_CollCoeff_Matrix[line_label]
        T_4 = T_e / 10000.0

        # WARNING THE ORDER OF THE COEFFIENTS ITS DIFFERENT IN THE PAPERS OF AVER 2011 AND PORTER 2004
        CR_Ratio = (
            1.0
            / (1.0 + (3552.0 * power(T_4, -0.55) / n_e))
            * sum(Coeff_Table[0] * power(T_4, Coeff_Table[1]) * exp(Coeff_Table[2] / T_4))
        )

        return CR_Ratio

    def f_value(self, wave):
        # Based on Cardelli

        x_true = 1.0 / (wave / 10000.0)
        y = x_true - 1.82

        y_coeffs = array(
            [ones(len(y)), y, power(y, 2), power(y, 3), power(y, 4), power(y, 5), power(y, 6), power(y, 7)]
        )

        a_x = dot(self.a_coeffs, y_coeffs)
        b_x = dot(self.b_coeffs, y_coeffs)

        f = a_x + b_x / self.R_v

        return f

    def He_OpticalDepth(self, tau, T_e, n_e, He_label):

        T_4 = T_e / 10000.0

        Coeff_Table = self.He_OpticalDepth_Matrix[He_label]

        f_tau = 1 + (tau / 2) * (
            Coeff_Table[0] + (Coeff_Table[1] + Coeff_Table[2] * n_e + Coeff_Table[3] * n_e * n_e) * T_4
        )

        return f_tau

    def Example_SyntheticParameters(self):

        y_plus = 0.08  # He+/H+
        n_e = 100.0  # cm^-3
        a_He = 1.0  # Angstroms...
        tau = 0.2
        Te_0 = 18000.0  # K
        cHbeta = 0.1  #
        a_H = 1.0  # Angstroms
        xi = 1.0  # Angstroms
        EW_Hbeta = 250  # Angstroms
        err_Flux_H = 0.01  # Emission Line flux percentage
        err_Flux_He = 0.02  # Emission Line flux percentage

        return y_plus, n_e, a_He, tau, Te_0, cHbeta, a_H, xi, EW_Hbeta, err_Flux_H, err_Flux_He

    def Example_SyntheticParameters2(self):

        y_plus = 0.085  # He+/H+
        n_e = 500.0  # cm^-3
        a_He = 0.5  # Angstroms...
        tau = 1.0
        Te_0 = 16000.0  # K
        cHbeta = 0.1  #
        a_H = 1.0  # Angstroms
        xi = 1.0  # Angstroms
        EW_Hbeta = 250  # Angstroms
        err_Flux_H = 0.01  # Emission Line flux percentage
        err_Flux_He = 0.02  # Emission Line flux percentage

        return y_plus, n_e, a_He, tau, Te_0, cHbeta, a_H, xi, EW_Hbeta, err_Flux_H, err_Flux_He
示例#11
0
 def load_atom(self):
     
     #atomicData.setDataFile('h_i_rec_SH95.hdf5', 'H1', 'rec')
     self.H1_atom            =  RecAtom('H', 1)
          
     return
示例#12
0
class ReddeningLaws(Dazer_Files):

    def __init__(self):
        
        Dazer_Files.__init__(self)
                
        self.R_v = 3.2
        self.SpectraEdges_Limit = 200 
     
#         self.Flux_Header        = 'FluxGauss'
#         self.FluxError_Header   = 'ErrorEL_MCMC'        
#         self.Wavelength_Header  = 'TheoWavelength'
     
        self.Reddening_Force    = None

        #List of hydrogen recombination lines in our EmissionLines coordinates log. WARNING: We have removed the very blended ones
        self.RecombRatios_Ions =  array(['HBal_20_2', 'HBal_19_2','HBal_18_2', 'HBal_17_2', 'HBal_16_2','HBal_15_2','HBal_12_2','HBal_11_2',
                             'HBal_9_2','Hdelta_6_2','Hgamma_5_2','Hbeta_4_2','Halpha_3_2','HPas_20_3','HPas19_3','HPas_18_3','HPas_17_3','HPas_16_3','HPas_15_3','HPas_14_3',
                             'HPas13_3','HPas12_3','HPas_11_3','HPas_10_3','HPas_9_3','HPas_8_3','HPas_7_3'])

    def load_atom(self):
        
        #atomicData.setDataFile('h_i_rec_SH95.hdf5', 'H1', 'rec')
        self.H1_atom            =  RecAtom('H', 1)
             
        return

    def RecombinationCoefficients(self, FileFolder, CodeName, DataLogExtension, lineslog_frame, Mode = 'all'):
            
        #Load electron temperature and density (if not available it will use Te = 10000K and ne = 100cm^-3)                        
        T_e = self.GetParameter_ObjLog(CodeName, FileFolder, 'TSIII', Assumption = 'Min_Temp')
        n_e = self.GetParameter_ObjLog(CodeName, FileFolder, 'nSII', Assumption = 'Min_Den')
        
        #Get the Hidrogen recombination lines that we have observed in this object
        Obs_Hindx   = lineslog_frame.index[in1d(lineslog_frame['Ion'], self.RecombRatios_Ions)]   
                    
        #Determine Hbeta properties         
        Hbeta_Emis  = self.H1_atom.getEmissivity(tem = T_e, den = n_e, label = '4_2')        
        
        #Calculate recombination coefficients and reddening curve values
        Obs_H_Emis  = zeros(len(Obs_Hindx))
        Obs_Ions    = lineslog_frame.loc[Obs_Hindx, 'Ion'].values
        
        for i in range(len(Obs_Ions)):
            TransitionCode = Obs_Ions[i][Obs_Ions[i].find('_')+1:len(Obs_Ions[i])]
            Obs_H_Emis[i]  = self.H1_atom.getEmissivity(tem = T_e, den = n_e, label = TransitionCode)        

        Theo_RecomRatio = Obs_H_Emis / Hbeta_Emis #Is this an uarray en condiciones
        
        lineslog_frame.loc[Obs_Hindx,'line_Emissivity']         = Obs_H_Emis
        lineslog_frame.loc[Obs_Hindx,'line_TheoRecombRatio']    = Theo_RecomRatio

        #Get spectrum edges
        if Mode != 'all':
            Wmin            = self.GetParameter_ObjLog(CodeName, FileFolder, 'WHT_Wmin_Blue',   Assumption='float')
            Wmax            = self.GetParameter_ObjLog(CodeName, FileFolder, 'WHT_Wmax_Red',    Assumption='float')
            Lambda_Match    = self.GetParameter_ObjLog(CodeName, FileFolder, 'Spectra_Meet',    Assumption='MatchingSpectra')
        
        #-----------All coefficients--------------------------

        if Mode == 'all':

            x_total, y_total = self.compute_allpoints(lineslog_frame, Obs_Hindx)
                        
            return x_total, y_total, list(Obs_Ions)

        #-----------Points close to spectrum edges are excluded --------------------------

        if Mode == 'boundary':

            x_inboundary, y_inboundary, Obs_Ions_inBoundary, x_outboundary, y_outboundary, Obs_Ions_outBoundary = self.compute_inBoundaryPoints(lineslog_frame, Obs_Hindx, Wmin, Wmax)

            return x_inboundary, y_inboundary, list(Obs_Ions_inBoundary), x_outboundary, y_outboundary, list(Obs_Ions_outBoundary)


        #-----------Blue spectrum coefficients --------------------------

        elif Mode == 'Blue':
            
            x_Blue, y_Blue, Obs_Blue_Ions, Blue_Normalizing_Ion = self.compute_BluePoints(lineslog_frame, Wmin, Wmax, Lambda_Match)
                        
            return x_Blue, y_Blue, Obs_Blue_Ions, Blue_Normalizing_Ion
            
        #-----------Red spectrum coefficients --------------------------

        elif Mode == 'Red':
            
            x_total_Red, y_total_Red, Obs_Red_Ions, Red_Normalizing_Ion     = self.compute_RedPoints(lineslog_frame,  Wmin, Wmax, Lambda_Match)
            
            return x_total_Red, y_total_Red, Obs_Red_Ions, Red_Normalizing_Ion

    def compare_RecombCoeffs(self, obj_data, lineslog_frame, spectral_limit = 200):
        
        #Load electron temperature and density (if not available it will use Te = 10000K and ne = 100cm^-3)                        
        T_e = obj_data.TeSIII if ~isnan(obj_data.TeSIII) else 10000.0
        n_e = obj_data.neSII if ~isnan(obj_data.neSII) else 100.0
                
        #Get the Hidrogen recombination lines that we have observed in this object
        Obs_Hindx = lineslog_frame.Ion.isin(self.RecombRatios_Ions)
                            
        #Calculate recombination coefficients and reddening curve values
        Obs_H_Emis  = empty(len(Obs_Hindx))
        Obs_Ions    = lineslog_frame.loc[Obs_Hindx, 'Ion'].values
        for i in range(len(Obs_Ions)):
            TransitionCode = Obs_Ions[i][Obs_Ions[i].find('_')+1:len(Obs_Ions[i])]
            Obs_H_Emis[i]  = self.H1_atom.getEmissivity(tem = T_e, den = n_e, label = TransitionCode)        
        
        #Normalize by Hbeta (this new constant is necessary to avoid a zero sigma)
        Hbeta_Emis = self.H1_atom.getEmissivity(tem = T_e, den = n_e, label = '4_2')        
        Fbeta_flux = ufloat(lineslog_frame.loc['H1_4861A']['line_Flux'].nominal_value, lineslog_frame.loc['H1_4861A']['line_Flux'].std_dev)
        
        #Load theoretical and observational recombination ratios to data frame
        lineslog_frame.loc[Obs_Hindx,'line_Emissivity'] = Obs_H_Emis
        lineslog_frame.loc[Obs_Hindx,'line_TheoRecombRatio'] = Obs_H_Emis / Hbeta_Emis
        lineslog_frame.loc[Obs_Hindx,'line_ObsRecombRatio'] = lineslog_frame.loc[Obs_Hindx, 'line_Flux'].values / Fbeta_flux
        
        #Get indeces of emissions in each arm
        ObsBlue_Hindx = Obs_Hindx & (lineslog_frame.lambda_theo < obj_data.join_wavelength)
        ObsRed_Hindx = Obs_Hindx & (lineslog_frame.lambda_theo > obj_data.join_wavelength)
      
        #Recalculate red arm coefficients so they are normalized by red arm line (the most intense)
        if (ObsRed_Hindx.sum()) > 0: #Can only work if there is at least one line
            idx_Redmax = lineslog_frame.loc[ObsRed_Hindx]['flux_intg'].idxmax()  #We do not use line_flux because it is a ufloat and it does not work with idxmax 
            H_Redmax_flux = lineslog_frame.loc[idx_Redmax,'line_Flux']
            H_Redmax_emis = lineslog_frame.loc[idx_Redmax,'line_Emissivity']
            Flux_Redmax = ufloat(H_Redmax_flux.nominal_value * Hbeta_Emis / H_Redmax_emis, H_Redmax_flux.std_dev * Hbeta_Emis / H_Redmax_emis)
            lineslog_frame.loc[ObsRed_Hindx,'line_ObsRecombRatio'] = lineslog_frame.loc[ObsRed_Hindx, 'line_Flux'].values / Flux_Redmax
                    
        #Load x axis values: (f_lambda - f_Hbeta) and y axis values: log(F/Fbeta)_theo - log(F/Fbeta)_obs to dataframe
        lineslog_frame.loc[Obs_Hindx,'x axis values'] = lineslog_frame.loc[Obs_Hindx, 'line_f'].values - lineslog_frame.loc['H1_4861A']['line_f']
        lineslog_frame.loc[Obs_Hindx,'y axis values'] = unum_log10(lineslog_frame.loc[Obs_Hindx,'line_TheoRecombRatio'].values) - unum_log10(lineslog_frame.loc[Obs_Hindx,'line_ObsRecombRatio'].values)
            
        #Compute all the possible configuration of points and store them
        output_dict = {}
        
        #--- All points:
        output_dict['all_x'] = lineslog_frame.loc[Obs_Hindx,'x axis values'].values
        output_dict['all_y'] = lineslog_frame.loc[Obs_Hindx,'y axis values'].values
        output_dict['all_ions'] = list(lineslog_frame.loc[Obs_Hindx,'Ion'].values)
        
        #--- By arm
        output_dict['blue_x'] = lineslog_frame.loc[ObsBlue_Hindx,'x axis values'].values
        output_dict['blue_y'] = lineslog_frame.loc[ObsBlue_Hindx,'y axis values'].values
        output_dict['blue_ions'] = list(lineslog_frame.loc[ObsBlue_Hindx,'Ion'].values)        
        output_dict['red_x'] = lineslog_frame.loc[ObsRed_Hindx,'x axis values'].values
        output_dict['red_y'] = lineslog_frame.loc[ObsRed_Hindx,'y axis values'].values
        output_dict['red_ions'] = list(lineslog_frame.loc[ObsRed_Hindx,'Ion'].values)
        
        #--- Inside limits
        if obj_data.h_gamma_valid == 'yes':
            in_idcs = Obs_Hindx
        elif obj_data.h_gamma_valid == 'no':
            wave_idx = ((lineslog_frame.lambda_theo > (obj_data.Wmin_Blue + spectral_limit)) & (lineslog_frame.lambda_theo < (obj_data.join_wavelength - spectral_limit))) \
                    | ((lineslog_frame.lambda_theo > (obj_data.join_wavelength + spectral_limit)) & (lineslog_frame.lambda_theo < (obj_data.Wmax_Red - spectral_limit)))
            in_idcs = Obs_Hindx & wave_idx
           
        output_dict['in_x'] = lineslog_frame.loc[in_idcs,'x axis values'].values
        output_dict['in_y'] = lineslog_frame.loc[in_idcs,'y axis values'].values
        output_dict['in_ions'] = list(lineslog_frame.loc[in_idcs,'Ion'].values)

        #--- Outside limis
        if obj_data.h_gamma_valid == 'no':
            wave_idx = (lineslog_frame.lambda_theo < (obj_data.Wmin_Blue + spectral_limit)) | (lineslog_frame.lambda_theo > (obj_data.Wmax_Red - spectral_limit))
            out_idcs = Obs_Hindx & wave_idx
            output_dict['out_x'] = lineslog_frame.loc[out_idcs,'x axis values'].values
            output_dict['out_y'] = lineslog_frame.loc[out_idcs,'y axis values'].values
            output_dict['out_ions'] = list(lineslog_frame.loc[out_idcs,'Ion'].values)
        else:
            output_dict['out_x'] = None
            output_dict['out_y'] = None
            output_dict['out_ions'] = None
           
        return output_dict

    def compute_allpoints(self, lineslog_frame, Obs_indeces):
        
        #Generating the unumpy array for the error propagation
        Theo_RecomRatio = lineslog_frame.loc[Obs_indeces, 'line_TheoRecombRatio'].values            
        Obs_RecombRatio = lineslog_frame.loc[Obs_indeces, 'line_Flux'].values / lineslog_frame.loc['H1_4861A']['line_Flux'] 
         
        #Generate x_true and y axis arrays for the plot
        x_total = lineslog_frame.loc[Obs_indeces, 'line_f'].values - lineslog_frame.loc['H1_4861A']['line_f']
        y_total = unum_log10(Theo_RecomRatio) - unum_log10(Obs_RecombRatio)
        
        return x_total, y_total

    def compute_inBoundaryPoints(self,  lineslog_frame, Obs_indeces, Wmin, Wmax):
        
        #Generating the unumpy array for the error propagation
        Theo_RecomRatio = lineslog_frame.loc[Obs_indeces, 'line_TheoRecombRatio'].values  
        Obs_RecombRatio = lineslog_frame.loc[Obs_indeces, 'line_Flux'].values / lineslog_frame.loc['H1_4861A']['line_Flux'] 
                
        #Generate x_true and y axis arrays for the plot
        x_total         = lineslog_frame.loc[Obs_indeces, 'line_f'].values - lineslog_frame.loc['H1_4861A']['line_f']
        y_total         = unum_log10(Theo_RecomRatio) - unum_log10(Obs_RecombRatio)

        Obs_Ions        = lineslog_frame.loc[Obs_indeces, 'Ion'].values
        Obs_Wavelength  = lineslog_frame.loc[Obs_indeces, 'TheoWavelength'].values

        #Emission lines outside the edges
        Obs_InBoundary_Indx                             = where((Obs_Wavelength > (Wmin + self.SpectraEdges_Limit)) & (Obs_Wavelength < (Wmax - self.SpectraEdges_Limit)))[0]
        x_inboundary                                    = x_total[Obs_InBoundary_Indx]
        y_inboundary                                    = y_total[Obs_InBoundary_Indx]
        Obs_Ions_inBoundary                             = Obs_Ions[Obs_InBoundary_Indx]

        #Emission lines inside the edges
        Obs_OutBoundary_Indx                            = where((Obs_Wavelength < (Wmin + self.SpectraEdges_Limit)) | (Obs_Wavelength > (Wmax - self.SpectraEdges_Limit)))[0]
        x_outboundary                                   = x_total[Obs_OutBoundary_Indx]
        y_outboundary                                   = y_total[Obs_OutBoundary_Indx]
        Obs_Ions_outBoundary                            = Obs_Ions[Obs_OutBoundary_Indx]
        
        return x_inboundary, y_inboundary, Obs_Ions_inBoundary, x_outboundary, y_outboundary, Obs_Ions_outBoundary

    def compute_BluePoints(self, lineslog_frame, Wmin, Wmax, Lambda_Match):
        
        #Wavelength limits for the blue lines
        Blue_limit      = Wmin + self.SpectraEdges_Limit
        Red_limit       = Lambda_Match - self.SpectraEdges_Limit
        BlueH_indx      = lineslog_frame.index[in1d(lineslog_frame['Ion'], self.RecombRatios_Ions) & (lineslog_frame['TheoWavelength'] > Blue_limit) & (lineslog_frame['TheoWavelength'] < Red_limit)]   
                                  
        Obs_Blue_Ions   = lineslog_frame.loc[BlueH_indx, 'Ion'].values
        
        #Check in case we do not have enough emission lines
        if len(Obs_Blue_Ions) >= 2:

            #Declare normalizing emission (Blue spectra always HBeta)
            N_line_flux = lineslog_frame.loc['H1_4861A']['line_Flux'] 
            N_line_f    = lineslog_frame.loc['H1_4861A']['line_f']
            N_line_Ion  = lineslog_frame.loc['H1_4861A']['Ion']
            
            #Calculate theoretical and observational ratios
            Desplacement_constant   = ufloat(N_line_flux.nominal_value, N_line_flux.std_dev)      #This is not completelety mathematically correct but avoids a zero sigma
            Theo_RecomRatio = lineslog_frame.loc[BlueH_indx, 'line_TheoRecombRatio'].values            
            Obs_RecombRatio = lineslog_frame.loc[BlueH_indx, 'line_Flux'].values / Desplacement_constant

            #Generate x_true and y axis arrays for the plot
            x_Blue         = lineslog_frame.loc[BlueH_indx, 'line_f'].values - N_line_f
            y_Blue         = unum_log10(Theo_RecomRatio) - unum_log10(Obs_RecombRatio)
                            
            return x_Blue, y_Blue, list(Obs_Blue_Ions), N_line_Ion
        
        else:
            
            return None, None, None, None

    def compute_RedPoints(self, lineslog_frame, Wmin, Wmax, Lambda_Match):
                   
        #Wavelength limits for the red lines
        Blue_limit      = Wmax - self.SpectraEdges_Limit
        Red_limit       = Lambda_Match + self.SpectraEdges_Limit
        RedH_indx       = lineslog_frame.index[in1d(lineslog_frame['Ion'], self.RecombRatios_Ions) & (lineslog_frame['TheoWavelength'] > Red_limit) & (lineslog_frame['TheoWavelength'] < Blue_limit)]   
                                  
        Obs_Red_Ions    = lineslog_frame.loc[RedH_indx, 'Ion'].values   
        
        #Check in case we do not have enough emission lines
        if len(Obs_Red_Ions) >= 2:
            
            #Declare normalizing emission (Blue spectra always HBeta)
            Hbeta_line_f        = lineslog_frame.loc['H1_4861A']['line_f']
            Hbeta_line_Emis     = lineslog_frame.loc['H1_4861A']['line_Emissivity']            
                           
            #Declare normalizing emission (in red spectra is the strongest emission )
            N_line_idx          = lineslog_frame.loc[RedH_indx]['Flux_Int'].idxmax()  #We do not use line_flux because it is a ufloat and it does not work with idxmax        
            N_line_flux         = lineslog_frame.loc[N_line_idx]['line_Flux'] 
            N_line_Ion          = lineslog_frame.loc[N_line_idx]['Ion']            
            N_line_Emis         = lineslog_frame.loc[N_line_idx]['line_Emissivity']            
                        
            #Determine theoretical intensity line ratios          
            Desplacement_constant   = ufloat(N_line_flux.nominal_value * Hbeta_line_Emis / N_line_Emis, N_line_flux.std_dev * Hbeta_line_Emis / N_line_Emis)
            Theo_RecomRatio_Red     = lineslog_frame.loc[RedH_indx, 'line_TheoRecombRatio'].values  
            Obs_RecombRatio_Red     = lineslog_frame.loc[RedH_indx, 'line_Flux'].values / Desplacement_constant
                        
            #Generate x_true and y axis arrays for the plot
            x_Red               = lineslog_frame.loc[RedH_indx, 'line_f'].values - Hbeta_line_f
            y_Red               = unum_log10(Theo_RecomRatio_Red) - unum_log10(Obs_RecombRatio_Red)

            return x_Red, y_Red, list(Obs_Red_Ions), N_line_Ion
        
        #Case we only have one red emission line... observation (most likely Halpha)
        else:
            
            return None, None, None, None
    
    def derreddening_line(self, CodeName, FileFolder, EmissionLine_label, EmissionLine_Wave, LinesLog_suffix, cHbeta):
        
        EmLine_Flux             = self.GetParameter_LineLog(CodeName, FileFolder, EmissionLine_label, 'FluxGauss', LinesLog_suffix)
        EmLine_Flux_derred      = None
    
        if cHbeta > 0:
            f_wave              = self.Reddening_f(array([EmissionLine_Wave]), 3.2)
            f_Hbeta             = self.Reddening_f(array([4861.333]), 3.2)
            
            Power_Coeff         = cHbeta * (1 + f_wave - f_Hbeta)
            
            EmLine_Flux_derred  = EmLine_Flux * power(10, Power_Coeff)
        
        else:
            EmLine_Flux_derred  = EmLine_Flux
    
            
        return EmLine_Flux_derred
    
    def getLinesFlux_dered(self, Lines_List, cHbeta, Mode = 'Auto'):
        #WARNING THE DICT WILL NOT BE CORRECTED FOR REDDENING IF ONE OF THE LINES IS NONE... DOES THIS AFFECT ME?
        Lines_dict, Wavelength_Vector   = self.getEmLine_dict(Lines_List, Mode = Mode)
                
        if (None not in Lines_dict.values()):
            if (cHbeta > 0.0) and (self.Reddening_Force == True):
                Fluxes_lines        = array(Lines_dict.values())
                f_lines             = self.Reddening_f(Wavelength_Vector,   3.2,  'Cardelli1989')
                Flux_derred         = Fluxes_lines * unum_pow(10,  f_lines * cHbeta)
                Dered_Lines_Dict    = OrderedDict(zip(Lines_dict.keys(), Flux_derred))
            
                return Dered_Lines_Dict
                
        return Lines_dict

    def derreddening_continuum(self, Spectrum_WavelengthRange, Spectrum_Flux, cHbeta):
        
        if (cHbeta != None) and (cHbeta > 0):
            f_wave              = self.Reddening_f(Spectrum_WavelengthRange, 3.2)
            f_Hbeta             = self.Reddening_f(array([4862.683]), 3.2)
            
            Power_Coeff         = cHbeta * (1 + f_wave - f_Hbeta)
            
            Int_spectrum        = Spectrum_Flux * power(10, Power_Coeff)
        
        else:
            print '- WARNING: c(Hbeta) is less than zero'
            Int_spectrum  = Spectrum_Flux
                       
        return Int_spectrum

    def reddening_continuum(self, Spectrum_WavelengthRange, Spectrum_Int, cHbeta):
        
        if (cHbeta != None) and (cHbeta > 0):
            f_wave              = self.Reddening_f(Spectrum_WavelengthRange, 3.2)
            f_Hbeta             = self.Reddening_f(array([4862.683]), 3.2)
            
            Power_Coeff         = cHbeta * (1 + f_wave - f_Hbeta)
            
            Spectrum_flux       = Spectrum_Int * power(10, -Power_Coeff)
        
        else:
            print '- WARNING: c(Hbeta) is less than zero'
            Spectrum_flux        = Spectrum_Int
                       
        return Spectrum_flux
 
    def Reddening_f(self, wave, R_v = 3.2, curve_parametrization = 'Miller&Mathews1972'):
                
        if curve_parametrization == 'Miller&Mathews1972':

            if isinstance(wave, ndarray):
                y           = 1.0/(wave/10000.0) 
                y_beta      = 1.0/(4862.683/10000.0)
                
                ind_low     = where(y <= 2.29)[0]
                ind_high    = where(y >  2.29)[0]
                
                dm_lam_low  = 0.74 * y[ind_low]  - 0.34 + 0.341 * R_v - 1.014
                dm_lam_high = 0.43 * y[ind_high] + 0.37 + 0.341 * R_v - 1.014
                dm_beta     = 0.74 * y_beta      - 0.34 + 0.341 * R_v - 1.014
                
                dm_lam = concatenate((dm_lam_low, dm_lam_high))
                
                f = dm_lam/dm_beta - 1
                
            else:
                
                y           = 1.0/(wave/10000.0) 
                y_beta      = 1.0/(4862.683/10000.0)
                
                if y <= 2.29:
                    dm_lam  = 0.74 * y  - 0.34 + 0.341 * R_v - 1.014
                else:
                    dm_lam = 0.43 * y + 0.37 + 0.341 * R_v - 1.014
        
                dm_beta     = 0.74 * y_beta - 0.34 + 0.341 * R_v - 1.014
                                
                f = dm_lam/dm_beta - 1
                        
        elif curve_parametrization == 'Cardelli1989':

            x_true = 1.0 / (wave / 10000.0)
            y = x_true - 1.82
        
            y_coeffs = array([ones(len(y)), y, power(y, 2), power(y, 3), power(y, 4), power(y, 5), power(y, 6), power(y, 7)])
            a_coeffs = array([1, 0.17699,    -0.50447,   -0.02427,   0.72085,    0.01979,    -0.77530,   0.32999])
            b_coeffs = array([0, 1.41338,    2.28305,   1.07233,   -5.38434,    -0.62251,    5.30260,   -2.09002])
            
            a_x =  dot(a_coeffs,y_coeffs)
            b_x =  dot(b_coeffs,y_coeffs)
            
            X_x = a_x + b_x / R_v
            
            y_beta          = (1 / (4862.683 / 10000)) - 1.82
            y_beta_coeffs   = array([1, y_beta, power(y_beta, 2), power(y_beta, 3), power(y_beta, 4), power(y_beta, 5), power(y_beta, 6), power(y_beta, 7)])
            
            X_x_beta          = dot(a_coeffs,y_beta_coeffs) + dot(b_coeffs,y_beta_coeffs) / R_v
        
            f = X_x / X_x_beta - 1
        
        return f

    def Epm_ReddeningPoints(self):
        
        x_true           = arange(1.0, 2.8, 0.1) #in microns -1
        X_Angs      = 1 / x_true * 1e4
        
        Xx          = array([1.36, 1.44, 1.84, 2.04, 2.24, 2.44, 2.66, 2.88, 3.14, 3.36, 3.56, 3.77, 3.96, 4.15, 4.26, 4.40, 4.52, 4.64])
        f_lambda    = array([-0.63,-0.61,-0.5, -0.45, -0.39, -0.34, -0.28, -0.22, -0.15, -0.09, -0.03, 0.02, 0.08, 0.13, 0.16, 0.20, 0.23, 0.26])
        
        return x_true, X_Angs, Xx, f_lambda
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
示例#13
0
                x_range, y_range = ExtractSubRegion(Wave, Int, RightPoints[i][0], RightPoints[i][1])
                Pv.Axis1.fill_between(x_range, zeros(len(x_range)), y_range, label= "Red Continuum", facecolor=Pv.Color_Vector[2][1],alpha = 0.2)
            
            Label3 = "Blue continuum"
            x_Bluecontinuum = SubWave[where(SubWave<=BalmerJump_Wavelength)]
            y_BlueContinuum = m_blue * x_Bluecontinuum + n_blue
            Pv.DataPloter_One(x_Bluecontinuum, y_BlueContinuum, Label3, Pv.Color_Vector[2][2], LineStyle='--', LineWidth=2)
            
            Label4 = "Red continuum"
            x_Redcontinuum = SubWave[where(SubWave>=BalmerJump_Wavelength)]
            y_RedContinuum = m_red * x_Redcontinuum + n_red
            Pv.DataPloter_One(x_Redcontinuum, y_RedContinuum, Label4, Pv.Color_Vector[2][1], LineStyle='--', LineWidth=2)
            
            if CodeName == 'SHOC579':
              
                H1 = RecAtom('H', 1)
                Hbeta_Emis = H1.getEmissivity(tem = 10000, den = 100, label = '4_2')
                H11_Emis = H1.getEmissivity(tem = 10000, den = 100, label = '11_2')
                ratio11_beta = Hbeta_Emis / H11_Emis  
                
#                              
#                 y_I             = 0.1119
#                 y_II            = 0.0006
#                 H11_Flux        = 8.280005e-16 #2.174
#                 Hbalmer_flux    = 2.258348e-14 #100 
#                 H11_Trick       = Hbalmer_flux / ratio11_beta
#                  
#                 print 'Theo ratio', ratio11_beta   
#                 print 'Obs ratio', Hbalmer_flux/ H11_Flux                
#                  
                BJ = y_BlueContinuum[-1] - y_RedContinuum[0]
class He_Inference_Abundance(Dazer_Files):
    
    def __init__(self):
        
        #Import Dazer_Files Class to import data from lines_logs
        Dazer_Files.__init__(self)
                
        #Declare Hydrogen and Helium collisional lines for the analysis
        self.posHydrogen_Lines      = ['Hdelta_6_2',    'Hgamma_5_2',   'Hbeta_4_2',    'Halpha_3_2']
        self.Hydrogen_Wavelengths   = [4101.742,        4340.471,       4862.683,        6562.819]
        #self.Hydrogen_Labels       = ['6_2',           '5_2',          '4_2',          '3_2']

        self.posHelium_Lines        = ['He1_3889A',    'He1_4026A',    'He1_4387A',      'He1_4471A',    'He1_4686A',      'He1_4714A',    'He1_4922A',      'He1_5876A',    'He1_6678A',      'He1_7065A',    'He1_7281A',      'He1_10380A']     
        self.Helium_Wavelengths     = [3889.0,        4026.0,         4387.0,         4471.0,         4686.0,         4714.0,         4922.0,         5876.0,         6678.0,         7065.0,         7281.0,         10380.0]
        #self.Helium_Labels         = ['3889.0',     '4026.0',       '4471.0',       '5876.0',       '6678.0',       '7065.0']
   
        self.Cand_Hydrogen_Lines    = []
        self.Cand_Helium_Lines      = []
        
        self.nHydrogen              = None
        self.nHelium                = None
    
        #Define indexes and labels to speed up the code               
        self.HBeta_label            = 'Hbeta_4_2'
                
        #Declare pyneb Hydrogen and Helium atoms to calculate emissivities
        self.H1                     = RecAtom('H', 1)
        self.He1                    = RecAtom('He', 1)                
        
        #Import collisional coefficients table
        self.Coef_Kalpha_dict       = self.Import_Coll_Coeff_Table(self.posHydrogen_Lines, None)

        #Import Optical depth function
        self.Coef_ftau_dict         = self.Import_OpticalDepth_Coeff_Table(self.posHelium_Lines) 
            
        #Line dictionaries
        self.Flux_dict              = OrderedDict()
        self.Error_dict             = OrderedDict()
        self.Wave_dict              = OrderedDict()
        self.PynebCode_dict         = OrderedDict()
        self.flambda_dict           = self.get_flambda_dict(self.posHydrogen_Lines + self.posHelium_Lines, self.Hydrogen_Wavelengths + self.Helium_Wavelengths) #WARNING: In this analysis flambda is mantained constant
        self.EqW_dict               = OrderedDict()
        self.EqWerror_dict          = OrderedDict()
        self.hlambda_dict           = OrderedDict()
    
        #Extra
        self.EmptyRowFormat         = 'nan'
        
    def Import_TableData(self, Address, Columns):
        
        Imported_Array  = genfromtxt(Address, dtype=float, usecols = Columns, skiprows = 2).T
        Datarray = Imported_Array[:,~isnan(Imported_Array).all(0)]
                
        return Datarray
     
    def Import_Coll_Coeff_Table(self, HydrogenLines, HeliumLines):
        
        data_dict = OrderedDict()
                
        for i in range(len(HydrogenLines)):
            
            Line            = HydrogenLines[i]
            Data_Columns    = [0 + 3*i, 1 + 3*i, 2 + 3*i]
            data_dict[Line] = self.Import_TableData(self.Hydrogen_CollCoeff_TableAddress, Data_Columns)
        
        #We ignore since the emissivities from PFM already have the collisional contribution accounted
#         for j in range(len(HeliumLines)):
#             
#             Line            = HeliumLines[i]
#             Data_Columns    = [0 + 3*j, 1 + 3*j, 2 + 3*j]
#             data_dict[Line] = self.Import_TableData(self.Helium_CollCoeff_TableAddress, Data_Columns)
            
        return data_dict
     
    def Import_OpticalDepth_Coeff_Table(self, HeliumLines):
        
        data_dict = OrderedDict()

        for i in range(len(HeliumLines)):
            
            Line            = HeliumLines[i]
            data_dict[Line] = loadtxt(self.Helium_OpticalDepth_TableAddress, dtype = float, skiprows = 2, usecols = (i,))
            
        return data_dict
    
    def Import_Synthetic_Fluxes(self, case = 'case1'):
 
#         if case == 'case1':
#         
# #             H_Flux_Obs  = array([ 0.24585991,  0.45343263,  2.95803687])
# #             He_Flux_Obs = array([ 0.0891384,   0.01283333,  0.03187135,  0.09890274,  0.02582588,  0.02366021])   
# #             H_Labels_0  =       ['Hdelta_6_2',    'Hgamma_5_2',   'Halpha_3_2']
# #             H_waves_0   = array([4101.742,        4340.471,       6562.819])   
# #             He_Labels_0 =       ['He1_3889A',   'He1_4026A',   'He1_4471A',     'He1_5876A',   'He1_6678A',     'He1_7065A']
# #             He_waves_0  = array([3889.0,        4026.0,         4471.0,         5876.0,         6678.0,         7065.0])             
# #         
# #             return H_Flux_Obs, He_Flux_Obs, H_Labels_0, H_waves_0, He_Labels_0, He_waves_0
#         
        if case == 'case2':
            
            H_Flux_Obs  = array([ 0.24625485,  0.454443,    2.98352834])
            He_Flux_Obs = array([0.10100783,  0.01691781,  0.03924855,  0.12725256,  0.03553524,  0.04162797])
            H_Labels_0  =       ['Hdelta_6_2',    'Hgamma_5_2',   'Halpha_3_2']
            H_waves_0   = array([4101.742,        4340.471,       6562.819])   
            He_Labels_0 =       ['He1_3889A',   'He1_4026A',   'He1_4471A',     'He1_5876A',   'He1_6678A',     'He1_7065A']
            He_waves_0  = array([3889.0,        4026.0,         4471.0,         5876.0,         6678.0,         7065.0])   
            
            return H_Flux_Obs, He_Flux_Obs, H_Labels_0, H_waves_0, He_Labels_0, He_waves_0
        
    def Calculate_synthetic_fluxes(self, mycase="case2"):

        y_plus, n_e, a_He, tau, Te_0, cHbeta, a_H, xi, EW_Hbeta, err_Flux_H, err_Flux_He = self.Example_SyntheticParameters2()
                
        #Import observed data:
        H_Flux_Obs, He_Flux_Obs, H_Labels_0, H_waves_0, He_Labels_0, He_waves_0     = self.Import_Synthetic_Fluxes(case = mycase)
        H_Flux_Obs_err, He_Flux_Obs_er                                              = H_Flux_Obs*0.01, He_Flux_Obs*0.02

        self.Cand_Hydrogen_Lines        = H_Labels_0
        self.Cand_Helium_Lines          = He_Labels_0

        self.nHydrogen                  = len(H_Flux_Obs) 
        self.nHelium                    = len(He_Flux_Obs)
        
        self.H_He_Obs_Flux              = concatenate([H_Flux_Obs, He_Flux_Obs])
        self.H_He_Obs_Error             = concatenate([H_Flux_Obs_err, He_Flux_Obs_er])
                        
        self.Hbeta_EW                   = 250
        self.Hbeta_EWerror              = self.Hbeta_EW* 0.05  
        self.hbeta_hlambda              = 1.0
        self.hlambda_H_vector           = ones(self.nHydrogen)
        
        self.Emissivity_H_vector        = zeros(self.nHydrogen)
        self.Kalpha_vector              = zeros(self.nHydrogen)
        self.flambda_H_vector           = zeros(self.nHydrogen)
        
        self.Emissivity_He_vector       = zeros(self.nHelium)
        self.ftau_He_vector             = zeros(self.nHelium)
        self.flambda_He_vector          = zeros(self.nHelium)
        self.hlambda_He_vector          = ones(self.nHelium)

        #Calculating the hydrogen lines fluxes    
        for i in range(self.nHydrogen):
            Label = self.Cand_Hydrogen_Lines[i]
            self.PynebCode_dict[Label]              = Label[Label.find('_')+1:len(Label)]
            self.flambda_H_vector[i]                = self.flambda_dict[Label]
    
        #Calculating the helium lines fluxes 
        for i in range(self.nHelium):
            Label = self.Cand_Helium_Lines[i]
            self.PynebCode_dict[Label]              = Label[Label.find('_')+1:-1]+'.0'
            self.flambda_He_vector[i]               = self.flambda_dict[Label]            
            
        #Adding Hbeta line
        self.PynebCode_dict[self.HBeta_label]       = '4_2'        
        
        #Calculating values+
        self.Calculate_Theoretical_Parameters(Te_0, n_e, tau)
        
        #Calculating synthetic hydrogen lines
        H_Flux  = self.H_Flux_theo(xi, cHbeta, a_H)
        
        #Calculating synthetic helium lines
        He_Flux = self.He_Flux_theo_nof(xi, cHbeta, a_H, a_He, y_plus)
        
        
        
        
        return H_Flux, He_Flux

    def Import_Object_Data(self, FileAddress):

        Labels, Ions                                                    = self.get_ColumnData([self.Labels_ColumnHeader, self.Ion_ColumnHeader], TableAddress = FileAddress, HeaderSize = 2, datatype = str) 
        Wavelengths, FluxGauss, ErrorEL_MCMC, EW, EW_error, h_lines     = self.get_ColumnData([self.Wavelength_ColumnHeader, self.GaussianFlux_ColumnHeader, self.GaussianError_ColumnHeader, self.EqW_ColumnHeader, self.EqW_error_ColumnHeader, self.Line_Continuum_ColumnHeader], TableAddress = FileAddress, HeaderSize = 2)
        
        #Empty the lists of candidate lines for Hydrogen and Helium
        del self.Cand_Hydrogen_Lines[:]
        del self.Cand_Helium_Lines[:]
        
        #Getting the indexes for the observed hydrogen lines
        #The structure is kind of inefficient
        #WARGNING helium and hydrogen lines are following a different structure
        for i in range(len(self.posHelium_Lines)):
            HeliumLine_i                                                = self.posHelium_Lines[i]
            index_i                                                     = where(Labels==HeliumLine_i)[0]
            if len(index_i) != 0:
                LabelLine                                               = Labels[index_i[0]]
                self.Flux_dict[LabelLine]                               = FluxGauss[index_i[0]]
                self.Error_dict[LabelLine]                              = ErrorEL_MCMC[index_i[0]]
                self.Wave_dict[LabelLine]                               = Wavelengths[index_i[0]]
                self.PynebCode_dict[LabelLine]                          = LabelLine[LabelLine.find('_')+1:-1]+'.0'
                self.EqW_dict[LabelLine]                                = EW[index_i[0]]
                self.EqWerror_dict[LabelLine]                           = EW_error[index_i[0]]
                self.hlambda_dict[LabelLine]                            = h_lines[index_i[0]]
                self.Cand_Helium_Lines.append(LabelLine)
                
        #Getting the indexes for the observed hydrogen lines
        #The structure is kind of inefficient
        #WARGNING helium and hydrogen lines are following a different structure
        for i in range(len(self.posHydrogen_Lines)):
            HydroLine_i = self.posHydrogen_Lines[i]
            index_i     = where(Ions == HydroLine_i)[0]
            if len(index_i) != 0:
                LabelLine                                               = self.posHydrogen_Lines[i]
                self.Flux_dict[LabelLine]                               = FluxGauss[index_i[0]]
                self.Error_dict[LabelLine]                              = ErrorEL_MCMC[index_i[0]]
                self.Wave_dict[LabelLine]                               = Wavelengths[index_i[0]]
                self.PynebCode_dict[LabelLine]                          = LabelLine[LabelLine.find('_')+1:len(LabelLine)]
                self.EqW_dict[LabelLine]                                = EW[index_i[0]]
                self.EqWerror_dict[LabelLine]                           = EW_error[index_i[0]]
                self.hlambda_dict[LabelLine]                            = h_lines[index_i[0]]
                self.Cand_Hydrogen_Lines.append(LabelLine)

        #Since we do not use the Hbeta line we remove it from the Hydrogen lines    
        self.Cand_Hydrogen_Lines.remove(self.HBeta_label)
      
        #Define in advance the numper of lines
        self.nHydrogen                                                  = len(self.Cand_Hydrogen_Lines) 
        self.nHelium                                                    = len(self.Cand_Helium_Lines)
        
        self.Flux_H_vector                                              = zeros(self.nHydrogen)
        self.Error_H_vector                                             = zeros(self.nHydrogen)
        self.Emissivity_H_vector                                        = zeros(self.nHydrogen)
        self.Kalpha_vector                                              = zeros(self.nHydrogen)
        self.flambda_H_vector                                           = zeros(self.nHydrogen)
        self.Eqw_H_vector                                               = zeros(self.nHydrogen)
        self.EqwError_H_vector                                          = zeros(self.nHydrogen)
        self.hlambda_H_vector                                           = zeros(self.nHydrogen)

        self.Flux_He_vector                                             = zeros(self.nHelium)
        self.Error_He_vector                                            = zeros(self.nHelium)
        self.Emissivity_He_vector                                       = zeros(self.nHelium)
        self.ftau_He_vector                                             = zeros(self.nHelium)
        self.flambda_He_vector                                          = zeros(self.nHelium)
        self.Eqw_He_vector                                              = zeros(self.nHelium)
        self.EqwError_He_vector                                         = zeros(self.nHelium)
        self.hlambda_He_vector                                          = zeros(self.nHelium)
        
        return

    def Preload_Synthetic_data(self, mycase):

        #Import observed data:
        H_Flux_Obs, He_Flux_Obs, H_Labels_0, H_waves_0, He_Labels_0, He_waves_0     = self.Import_Synthetic_Fluxes(case = mycase)
        H_Flux_Obs_err, He_Flux_Obs_er                                              = H_Flux_Obs*0.01, He_Flux_Obs*0.02

        self.Cand_Hydrogen_Lines        = H_Labels_0
        self.Cand_Helium_Lines          = He_Labels_0

        self.nHydrogen                  = len(H_Flux_Obs) 
        self.nHelium                    = len(He_Flux_Obs)
        
        self.H_He_Obs_Flux              = concatenate([H_Flux_Obs, He_Flux_Obs])
        self.H_He_Obs_Error             = concatenate([H_Flux_Obs_err, He_Flux_Obs_er])
                        
        self.Hbeta_EW                   = 250
        self.Hbeta_EWerror              = self.Hbeta_EW* 0.05  
        self.hbeta_hlambda              = 1.0
        
        self.Emissivity_H_vector        = zeros(self.nHydrogen)
        self.Kalpha_vector              = zeros(self.nHydrogen)
        self.flambda_H_vector           = zeros(self.nHydrogen)
        self.hlambda_H_vector           = ones(self.nHydrogen)

        self.Emissivity_He_vector       = zeros(self.nHelium)
        self.ftau_He_vector             = zeros(self.nHelium)
        self.flambda_He_vector          = zeros(self.nHelium)
        self.hlambda_He_vector          = ones(self.nHelium)

        #Calculating the hydrogen lines fluxes    
        for i in range(self.nHydrogen):
            Label = self.Cand_Hydrogen_Lines[i]
            self.PynebCode_dict[Label]              = Label[Label.find('_')+1:len(Label)]
            self.flambda_H_vector[i]                = self.flambda_dict[Label]
    
        #Calculating the helium lines fluxes 
        for i in range(self.nHelium):
            Label = self.Cand_Helium_Lines[i]
            self.PynebCode_dict[Label]              = Label[Label.find('_')+1:-1]+'.0'
            self.flambda_He_vector[i]               = self.flambda_dict[Label]

        #Adding Hbeta line
        self.PynebCode_dict[self.HBeta_label]       = '4_2'
        
        print 'Printing all the data:\n'
        
        print 'self.PynebCode_dict', self.PynebCode_dict
       
        print 'self.Cand_Hydrogen_Lines',self.Cand_Hydrogen_Lines
        print 'self.Cand_Helium_Lines',self.Cand_Helium_Lines

        print 'self.nHydrogen',self.nHydrogen                
        print 'self.nHelium',self.nHelium                 
        
        print 'self.H_He_Obs_Flux',self.H_He_Obs_Flux           
        print 'self.H_He_Obs_Error',  self.H_He_Obs_Error        
                        
        print 'self.Hbeta_EW',self.Hbeta_EW                
        print 'self.Hbeta_EWerror',self.Hbeta_EWerror            
        print 'self.hbeta_hlambda',self.hbeta_hlambda           
        
        print 'self.Emissivity_H_vector' ,self.Emissivity_H_vector       
        print 'self.Kalpha_vector',self.Kalpha_vector              
        print 'self.flambda_H_vector', self.flambda_H_vector          
        print 'self.hlambda_H_vector',self.hlambda_H_vector          

        print 'self.Emissivity_He_vector',self.Emissivity_He_vector      
        print 'self.ftau_He_vector',self.ftau_He_vector            
        print 'self.flambda_He_vector',self.flambda_He_vector         
        print 'self.hlambda_He_vector', self.hlambda_He_vector        
        
        return

    def Preload_Obs_data(self, Normalized = False):

        #Calculate in advance HBeta values
        self.Hbeta_Flux                             = self.Flux_dict[self.HBeta_label]
        self.Hbeta_error                            = self.Error_dict[self.HBeta_label]
        self.Hbeta_EW                               = self.EqW_dict[self.HBeta_label]
        self.Hbeta_EWerror                          = self.EqWerror_dict[self.HBeta_label]      
        self.hbeta_hlambda                          = self.hlambda_dict[self.HBeta_label]
        
        #Calculate in advance observed physical parameters vectors for Hydrogen lines
        for i in range(self.nHydrogen):
            Line_Label                              = self.Cand_Hydrogen_Lines[i]        
            self.Flux_H_vector[i]                   = self.Flux_dict[Line_Label]
            self.Error_H_vector[i]                  = self.Error_dict[Line_Label]
            self.Eqw_H_vector[i]                    = self.EqW_dict[Line_Label]
            self.EqwError_H_vector[i]               = self.EqWerror_dict[Line_Label]
            self.hlambda_H_vector[i]                = self.hlambda_dict[Line_Label]
            self.flambda_H_vector[i]                = self.flambda_dict[Line_Label]
                
        #Calculate in advance observed physical parameters vectors for the Helium lines
        for i in range(self.nHelium):
            Line_Label                              = self.Cand_Helium_Lines[i]
            self.Flux_He_vector[i]                  = self.Flux_dict[Line_Label]
            self.Error_He_vector[i]                 = self.Error_dict[Line_Label]
            self.Eqw_He_vector[i]                   = self.EqW_dict[Line_Label]
            self.EqwError_He_vector[i]              = self.EqWerror_dict[Line_Label]
            self.flambda_He_vector[i]               = self.flambda_dict[Line_Label]
            self.hlambda_He_vector[i]               = self.hlambda_dict[Line_Label]     

        #Combine Hydrogen and Helium values into a single vector
        if Normalized: 
            self.H_He_Obs_Flux                      = concatenate([self.Flux_H_vector, self.Flux_He_vector])
            self.H_He_Obs_Error                     = concatenate([self.Error_H_vector, self.Error_He_vector])

        else:
            self.H_He_Obs_Flux                      = concatenate([self.Flux_H_vector, self.Flux_He_vector])    / self.Hbeta_Flux
            self.H_He_Obs_Error                     = concatenate([self.Error_H_vector, self.Error_He_vector])  

    def Calculate_Theoretical_Parameters(self, T_e, n_e, tau):
        
        #Calculate in advance the T_4 parameter
        T_4 = T_e / 10000.0
        
        #Calculate the hbeta parameters
        self.Hbeta_Kalpha                           = self.Kalpha_Ratio_H(T_4 = T_4, H_label=self.HBeta_label)
        self.Hbeta_emis                             = self.H1.getEmissivity(T_e, n_e, label = self.PynebCode_dict[self.HBeta_label])

        #Calculate physical parameters for Hydrogen lines
        for i in range(self.nHydrogen):
            Line_Label                              = self.Cand_Hydrogen_Lines[i]
            self.Emissivity_H_vector[i]             = self.H1.getEmissivity(T_e, n_e, label = self.PynebCode_dict[Line_Label])
            self.Kalpha_vector[i]                   = self.Kalpha_Ratio_H(T_4 = T_4, H_label=Line_Label)
            
        #Calculate physical parameters for Helium lines
        for i in range(self.nHelium):
            Line_Label                              = self.Cand_Helium_Lines[i]
            self.Emissivity_He_vector[i]            = self.He1.getEmissivity(T_e, n_e, label = self.PynebCode_dict[Line_Label])
            self.ftau_He_vector[i]                  = self.OpticalDepth_He(tau = tau, T_4 = T_4, n_e = n_e, He_label = Line_Label)

        return

    def H_Flux_theo(self, xi, cHbeta, a_H):
        
        #Calculate the emissivities for each of the lines for the given temperature and density
        Emissivities_module = self.Emissivity_H_vector / self.Hbeta_emis
        
        #Calculate the Collisional excitation fraction
        CR_Module           = (1.0 + 0.0001* xi * self.Kalpha_vector) / (1.0 + 0.0001* xi * self.Hbeta_Kalpha)
        
        #Calculate the reddening component
        f_module            = power(10, -1 * self.flambda_H_vector * cHbeta)
        
        #Calculate the Hbeta normalization module
        EW_Hbeta_module     = (self.Hbeta_EW + a_H) / self.Hbeta_EW
        
        #Calculate stellar absorption module
        a_H_module          = ( a_H * self.hlambda_H_vector ) / (self.Hbeta_EW * self.hbeta_hlambda)
        
        #Calculate theoretical Hydrogen flux for each emission line
        H_Flux              = Emissivities_module * CR_Module * f_module * EW_Hbeta_module - a_H_module
        
        return H_Flux
        
    def He_Flux_theo_nof(self, xi, cHbeta, a_H, a_He, y_plus):
        
        #Calculate the emissivities for each of the lines for the given temperature and density
        Emissivities_module = self.Emissivity_He_vector / self.Hbeta_emis
        
        #Calculate the collisional excitation fraction
        CR_Module           = 1 / (1.0 + 0.0001* xi * self.Hbeta_Kalpha)

        #Calculate the reddening component
        f_module            = power(10, -1 * self.flambda_He_vector * cHbeta)

        #Calculate the Hbeta normalization module
        EW_Hbeta_module     = (self.Hbeta_EW + a_H) / self.Hbeta_EW
        
        #Calculate stellar absorption module
        a_He_module         = (a_He * self.hlambda_He_vector ) / (self.Hbeta_EW * self.hbeta_hlambda)
             
        #Calculate theoretical Hydrogen flux for each emission line
        He_Flux             = y_plus * Emissivities_module * self.ftau_He_vector * CR_Module * f_module * EW_Hbeta_module - a_He_module

        return He_Flux  
      
    def get_flambda_dict(self, lines_labels , lines_wavelengths, R_v=3.1):
    
        x_true          = 1.0 / (array(lines_wavelengths) / 10000.0)
        y               = x_true - 1.82
    
        y_coeffs        = array([ones(len(y)), y, power(y, 2), power(y, 3), power(y, 4), power(y, 5), power(y, 6), power(y, 7)])
        a_coeffs        = array([1, 0.17699,    -0.50447,   -0.02427,   0.72085,    0.01979,    -0.77530,   0.32999])
        b_coeffs        = array([0, 1.41338,    2.28305,   1.07233,   -5.38434,    -0.62251,    5.30260,   -2.09002])
        
        a_x             = dot(a_coeffs,y_coeffs)
        b_x             = dot(b_coeffs,y_coeffs)
        
        X_x             = a_x + b_x / R_v
        
        y_beta          = (1 / (4862.683 / 10000)) - 1.82
        y_beta_coeffs   = array([1, y_beta, power(y_beta, 2), power(y_beta, 3), power(y_beta, 4), power(y_beta, 5), power(y_beta, 6), power(y_beta, 7)])
        
        X_x_beta        = dot(a_coeffs,y_beta_coeffs) + dot(b_coeffs,y_beta_coeffs) / R_v
    
        f               = X_x / X_x_beta - 1
        
        return dict(zip(lines_labels , f))
         
    def Kalpha_Ratio_H(self, T_4, H_label):
                                          
        K_alpha_Ratio   = sum(self.Coef_Kalpha_dict[H_label][0] * exp(self.Coef_Kalpha_dict[H_label][1] / T_4) * power(T_4, self.Coef_Kalpha_dict[H_label][2]))
        
        return K_alpha_Ratio
    
    def OpticalDepth_He(self, tau, T_4, n_e, He_label):
                        
        f_tau   = 1 + (tau/2) * (self.Coef_ftau_dict[He_label][0] + (self.Coef_ftau_dict[He_label][1] + self.Coef_ftau_dict[He_label][2]*n_e + self.Coef_ftau_dict[He_label][3]*n_e*n_e) * T_4)

        return f_tau        
    
    def Example_SyntheticParameters(self):
        
        y_plus      = 0.08          #He+/H+
        n_e         = 100.0         #cm^-3 
        a_He        = 1.0           #Angstroms...
        tau         = 0.2         
        Te_0        = 18000.0       #K
        cHbeta      = 0.1           # 
        a_H         = 1.0           #Angstroms
        xi          = 1.0           #Angstroms
        EW_Hbeta    = 250           #Angstroms
        err_Flux_H  = 0.01          #Emission Line flux percentage
        err_Flux_He = 0.02          #Emission Line flux percentage
        
        return y_plus, n_e, a_He, tau, Te_0, cHbeta, a_H, xi, EW_Hbeta, err_Flux_H, err_Flux_He

    def Example_SyntheticParameters2(self):
        
        y_plus      = 0.085         #He+/H+
        n_e         = 500.0         #cm^-3 
        a_He        = 0.5           #Angstroms...
        tau         = 1.0         
        Te_0        = 16000.0       #K
        cHbeta      = 0.1           # 
        a_H         = 1.0           #Angstroms
        xi          = 1.0           #Angstroms
        EW_Hbeta    = 250           #Angstroms
        err_Flux_H  = 0.01          #Emission Line flux percentage
        err_Flux_He = 0.02          #Emission Line flux percentage
        
        return y_plus, n_e, a_He, tau, Te_0, cHbeta, a_H, xi, EW_Hbeta, err_Flux_H, err_Flux_He