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'
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
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
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
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
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
def load_atom(self): #atomicData.setDataFile('h_i_rec_SH95.hdf5', 'H1', 'rec') self.H1_atom = RecAtom('H', 1) return
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
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