Ejemplo n.º 1
0
    def __init__(self):
        
        #Variables included in the series
        self.fitting_parameters =   ['idx0', 'idx1', 'idx2', 'idx3', 'idx4', 'idx5'] 
        self.fitting_parameters +=  ['area_intg', 'area_intg_er', 'flux_gauss', 'flux_gauss_er', 'flux_intg', 'flux_intg_er'] #Additionally there is (A, mu, sigma, Eqw) + idx + _norm + _norm_er
        self.fitting_parameters +=  ['m_zerolev', 'n_zerolev', 'zerolev_mean', 'zerolev_std', 'zerolev_linear', 'zerolev_width', 'continuum_width']
        self.fitting_parameters +=  ['fit_routine', 'MC_iterations', 'blended_check', 'start_treatment', 'line_number', 'add_wide_component', 'wide_component']
        self.fitting_parameters +=  ['params_lmfit', 'params_lmfit_wide', 'parameters_list', 'fit_output']
        self.fitting_parameters +=  ['Wave1', 'Wave2', 'Wave3', 'Wave4', 'Wave5', 'Wave6']
        self.fitting_parameters +=  ['group_label', 'blended_lambdas', 'blended_labels', 'blended_ions']
        self.fitting_parameters +=  ['maxLambdas', 'maxPeaks', 'x_scaler', 'y_scaler', 'x_n', 'y_n', 'zerolev_n', 'sigZerolev_n']

        self.GHcoeffs = {}
        self.GHcoeffs['c0'] = sqrt(6.0) / 4.0
        self.GHcoeffs['c1'] = -sqrt(3.0)
        self.GHcoeffs['c2'] = -sqrt(6.0)
        self.GHcoeffs['c3'] = 2.0 * sqrt(3.0) / 3.0
        self.GHcoeffs['c4'] = sqrt(6.0) / 3.0
        
        self.skeness_limit = {'fixed':(False)}
        self.kutorsis_limit = {'fixed':(False)}
        
        self.skeness_Glimit = {'fixed':(True)}
        self.kutorsis_Glimit = {'fixed':(True)}        

        N2 = Atom('N', 2)
        N2_6548A = N2.getEmissivity(tem=10000, den=100, wave=6548)
        N2_6584A = N2.getEmissivity(tem=10000, den=100, wave=6584)
        
        self.N2_Ratio = N2_6584A / N2_6548A
        
        self.sqrt2pi = sqrt(2*pi)
Ejemplo n.º 2
0
def Load_lmfit_parameters_blended(N_comps, Initial_guesses_dic, wide_component = False, mu_precission = 1):
 
    N2 = Atom('N', 2)
    N2_6548A = N2.getEmissivity(tem=10000, den=100, wave=6548)
    N2_6584A = N2.getEmissivity(tem=10000, den=100, wave=6584)
     
    print 'Radio', N2_6584A / N2_6548A
     
    params = Parameters()
 
    for i in range(N_comps):
        index = str(i)
        params.add('A'      + index, value = Initial_guesses_dic['A'][i])
        params.add('mu'     + index, value = Initial_guesses_dic['mu'][i], min = Initial_guesses_dic['mu'][i] - mu_precission, max = Initial_guesses_dic['mu'][i] + mu_precission) #One angstrom tolerance for min and max value of mu
        params.add('sigma'  + index, value = Initial_guesses_dic['sigma'][i], min = Initial_guesses_dic['min_sigma'][i], max = 5.0)
        params.add('fwhm'   + index, expr = '2.354820045 * {sigma}'.format(sigma = 'sigma'  + index))
        params.add('FWHM'   + index, expr = '({fwhm}/{mu}) * 2.99792458e5'.format(fwhm = 'fwhm' + index, mu = 'mu' + index))
        params.add('Flux'   + index, expr = '({A}*{fwhm})/(2.35*0.3989)'.format(A = 'A'  + index, fwhm = 'fwhm' + index))
 
    #Set all sigmas to the same value
    for i in range(1, N_comps):
        index = str(i)
        params['sigma'      + index].expr='sigma0'
# 
    #Set flux in N2_6548A as 1/3 N2_6584A
    params.add('Flux0', expr = 'Flux2 / {ratio}'.format(ratio = N2_6584A / N2_6548A))
 
    if wide_component:
        index = str(N_comps)
        params.add('A'      + index, value = Initial_guesses_dic['A'][N_comps])
        params.add('mu'     + index, expr = 'mu1')
        params.add('sigma'  + index, value = Initial_guesses_dic['sigma'][N_comps], min = Initial_guesses_dic['min_sigma'][N_comps], max = 8.0)
        params.add('fwhm'   + index, expr = '2.354820045 * {sigma}'.format(sigma = 'sigma'  + index))
        params.add('FWHM'   + index, expr = '({fwhm}/{mu}) * 2.99792458e5'.format(fwhm = 'fwhm' + index, mu = 'mu' + index))
        params.add('Flux'   + index, expr = '({A}*{fwhm})/(2.35*0.3989)'.format(A = 'A'  + index, fwhm = 'fwhm' + index))
 
#     if wide_component:
#         index = str(N_comps)
#         print 'Y la europea', 'A'      + index
#         params.add('A'      + index, value = Initial_guesses_dic['A'][N_comps], min=0.04748900 * 0.95, max = 0.04748900 * 1.05)
#         params.add('mu'     + index, value = Initial_guesses_dic['mu'][N_comps], min = Initial_guesses_dic['mu'][N_comps] - 2, max = Initial_guesses_dic['mu'][N_comps] + 2)
#         params.add('sigma'  + index, value = Initial_guesses_dic['sigma'][N_comps], min = Initial_guesses_dic['min_sigma'][N_comps], max = 8.0)
#         params.add('fwhm'   + index, expr = '2.354820045 * {sigma}'.format(sigma = 'sigma'  + index))
#         params.add('FWHM'   + index, expr = '({fwhm}/{mu}) * 2.99792458e5'.format(fwhm = 'fwhm' + index, mu = 'mu' + index))
#         params.add('Flux'   + index, expr = '({A}*{fwhm})/(2.35*0.3989)'.format(A = 'A'  + index, fwhm = 'fwhm' + index))
  
#     if wide_component:
#         index = str(N_comps + 1)
#         params.add('sigm_tol', value = 2.5, min = 2, max = 4)
#         params.add('A'      + index, value = Initial_guesses_dic['A'][N_comps])
#         params.add('mu'     + index, expr = 'mu2')
#         params.add('sigma'  + index, expr = 'sigm_tol*sigma2')
#         params.add('sigma'  + index, value = Initial_guesses_dic['sigma'][N_comps], min = Initial_guesses_dic['min_sigma'][N_comps], max = 8.0)
#         params.add('fwhm'   + index, expr = '2.354820045 * {sigma}'.format(sigma = 'sigma'  + index))
#         params.add('FWHM'   + index, expr = '({fwhm}/{mu}) * 2.99792458e5'.format(fwhm = 'fwhm' + index, mu = 'mu' + index))
#         params.add('Flux'   + index, expr = '({A}*{fwhm})/(2.35*0.3989)'.format(A = 'A'  + index, fwhm = 'fwhm' + index))
 
    return params
Ejemplo n.º 3
0
class Chemical_Analysis_pyneb():
    def __init__(self):

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

        self.Hbeta_label = 'H1_4861A'

    def load_elements(self):

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

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

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

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

        #Pyneb objects
        self.diags = Diagnostics()

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

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

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

        #Cloudy models for the SIV contribution

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

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

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

        print '-Elements loaded\n'

        return

    def declare_object(self, lines_log_frame):

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

        self.abunData = Series()

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

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

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

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

        #Generate
        for line in lines_log_frame.index.values:

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

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

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

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

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

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

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

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

        return

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

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

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

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

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

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

        return Te, ne

    def determine_electron_parameters(self, objectData):

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        return

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

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

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

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

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

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

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

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

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

        return

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

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

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

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

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

        return diagnos_eval, diagnos_mag

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        return

    def nitrogen_abundance_scheme(self, Tlow, ne):

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

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

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

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

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

        return

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

        print 'Metiendo esto', SIII_lines_to_use

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        return

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            print parameter, mean_value, std_value

        return

    def generate_nan_array(self):

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

        return nan_array

    def check_nan_entries(self, input_array):

        nan_count = np_sum(isnan(input_array))

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

        return new_distr
Ejemplo n.º 4
0
    def load_elements(self):

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

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

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

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

        #Pyneb objects
        self.diags = Diagnostics()

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

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

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

        #Cloudy models for the SIV contribution

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

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

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

        print '-Elements loaded\n'

        return
Ejemplo n.º 5
0
    def __init__(self):
            
        self.Combined                           = None
        self.MontecarloCheck                    = True
        self.MC_Iterations                      = 10
                
        self.NComps                             = 0
        self.GaussianSampling                   = 101
                
        self.Fitting_dict                       = OrderedDict()
        self.Fitting_dict['Deblend check']      = False    #This logic is true when a blended group is observed
        self.Fitting_dict['Fitting method']     = None
        self.Fitting_dict['start treatment']    = False    #This logic is true to force the deblending process
        self.Fitting_dict['line group']         = None     #This integer provides the index for the group of lines describes the blended lines
        self.Fitting_dict['line number']        = None     
        self.Fitting_dict['line label']         = None     #This string describes the label for the current blended line we are mesuring: H1_6563A
        self.Fitting_dict['blended label']      = None     #This string should be used for the blended label for the lines log
        self.Fitting_dict['blended number']     = None     #This integer describes the number of blended lines. Currently it must be equal to the number in the blended list elements.
        self.Fitting_dict['blended wavelengths']= None     #This list contains the wavelengths of the blended lines
        self.Fitting_dict['blended index']      = None     #This integer provides the index of the current line in a blended group
        self.Fitting_dict['kmpfit_dict']        = None     #This dictionaries containes the parameters for kmpfit

        self.Fitting_dict['Wide component']     = False    #This keyword informs if there is a wide component on the emission line
        
        self.Fitting_dict['line type']          = None     #Spectral feature type string: 'Absorption', 'Emission'
        self.Fitting_dict['peak_waves']         = None     #This list contains the wavelenghts of all the peaks  

        self.Fitting_dict['y_scaler']           = None     #This is the magnitude used to scale the y flux (normaly the line peak or line higher peak)
        self.Fitting_dict['x_scaler']           = None     #This is the magnitude used to scale the wavelength values (normaly the line middle wavelength)
        
        self.Fitting_dict['x_resample']         = None     #x Gaussian resampling of the line required for plotting
        self.Fitting_dict['y_resample']         = None     #y Gaussian resampling of the line required for plotting
        self.Fitting_dict['y_resample_total']   = None     #y Gaussian resampling of the blended group line required for plotting
        
        self.Fitting_dict['ContinuumFlux']      = None     #Continuum intensity across the whole plotting region 
        self.Fitting_dict['m_Continuum']        = None     #Assuming a line this is the gradient (m)
        self.Fitting_dict['n_Continuum']        = None     #Assuming a line this is the y axis interception point (n) 
        self.Fitting_dict['zerolev_resample']   = None     #Continuum level resampling at the line
        self.Fitting_dict['zerolev_median']     = None     #Mean level at the line center
        self.Fitting_dict['zerolev_sigma']      = None     #Continuum dispersion assuming linear shape 
        self.Fitting_dict['ContinuumWidth']     = None     #This is the number of pixels manually selected
        
        self.Fitting_dict['x_norm']             = None
        self.Fitting_dict['y_norm']             = None
        self.Fitting_dict['zerolev_norm']       = None
        self.Fitting_dict['sig_zerolev_norm']   = None
        
        self.Fitting_dict['lmfit_params']       = None     #lmfit parameters dict
        self.Fitting_dict['lmfit_params_wide']  = None     #lmfit parameters dict
        self.Fitting_dict['MC_iteration']       = None     #Number of iterations for calculation (1 for normal 1000 for MC)
        
        self.Fitting_dict['lmfit_output']       = None
        self.Fitting_dict['FluxI_N_vector']     = None     #This vectors holds all the fluxes calculated for the case of a gaussian fit
        self.Fitting_dict['parameters_list']    = None     #This list contains all the parameters which are fitted for a line: A1, mu1, sigma1, A2, mu2, sigma2 ...
        self.Fitting_dict['FluxI']              = None
        self.Fitting_dict['Add_wideComponent']  = None    #Extra step to procced to the wide component calculation 
        self.Fitting_dict['WC_theowavelength']  = None        #Gaussian_Coefficients coefficients
        
        self.Fitting_dict['wide mask']          = None
        
        self.GHcoeffs = {}
        self.GHcoeffs['c0'] = sqrt(6.0) / 4.0
        self.GHcoeffs['c1'] = -sqrt(3.0)
        self.GHcoeffs['c2'] = -sqrt(6.0)
        self.GHcoeffs['c3'] = 2.0 * sqrt(3.0) / 3.0
        self.GHcoeffs['c4'] = sqrt(6.0) / 3.0
        
        self.skeness_limit = {'fixed':(False)}
        self.kutorsis_limit = {'fixed':(False)}
        
        self.skeness_Glimit = {'fixed':(True)}
        self.kutorsis_Glimit = {'fixed':(True)}        

        N2 = Atom('N', 2)
        N2_6548A = N2.getEmissivity(tem=10000, den=100, wave=6548)
        N2_6584A = N2.getEmissivity(tem=10000, den=100, wave=6584)
        
        self.N2_Ratio = N2_6584A / N2_6548A
        print self.N2_Ratio
        
        self.s2pi = sqrt(2*pi)