예제 #1
0
def kurucz2moog(kurucz_path):
    # gfall08oct17.dat
    kurucz_all = pd.read_fwf('files/linelist/kurucz/gfall08oct17.dat',
                             colspecs=[(0, 11), (11, 18), (18, 24), (24, 36),
                                       (52, 64), (93, 98), (109, 116)],
                             names=[
                                 'wavelength', 'loggf_init', 'ele',
                                 'E(cm-1)_1', 'E(cm-1)_2', 'C6', 'hpf_frac'
                             ])
    kurucz_all['ele'] = kurucz_all['ele'] // 1 + kurucz_all['ele'] % 1 * 10
    kurucz_all['EP_1'] = kurucz_all['E(cm-1)_1'] / (
        1 / constants.h / constants.c).to(u.cm**-1 / u.eV).value
    kurucz_all['EP_2'] = kurucz_all['E(cm-1)_2'] / (
        1 / constants.h / constants.c).to(u.cm**-1 / u.eV).value
    kurucz_all['EP'] = np.where((kurucz_all['EP_1'] <= kurucz_all['EP_2']),
                                kurucz_all['EP_1'], kurucz_all['EP_2'])
    kurucz_all['loggf'] = kurucz_all['loggf_init'] + kurucz_all['hpf_frac']
    indices = (kurucz_all['ele'] % 1 <=
               0.2) & ~np.isnan(kurucz_all['loggf']) & (
                   kurucz_all['wavelength'] >= 200) & (kurucz_all['EP'] <= 50)
    kurucz_use = kurucz_all.loc[
        indices,
        ['wavelength', 'ele', 'EP', 'loggf', 'C6']].reset_index(drop=True)
    kurucz_use['wavelength'] = kurucz_use['wavelength'] * 10
    kurucz_use['D0'] = np.nan
    kurucz_use['EW'] = np.nan
    line_data.save_linelist(kurucz_use,
                            'files/linelist/kurucz/kurucz.list',
                            wav_start=2000,
                            wav_end=7e5)
    return kurucz_use
예제 #2
0
def mb992moog(mb99_path, save_path):
    mb99_j = pd.read_fwf(mb99_path,
                         colspecs=[(0, 7), (8, 16), (24, 29), (32, 37),
                                   (48, 56)],
                         names=['ele', 'wavelength', 'EP', 'loggf', 'C6'])
    mb99_j['ele'] = mb99_j['ele'].map(ele2ele_num)
    mb99_j['D0'] = np.nan
    mb99_j['EW'] = np.nan

    mb99_j_out = mb99_j[['wavelength', 'ele', 'EP', 'loggf', 'C6', 'D0', 'EW']]
    line_data.save_linelist(mb99_j_out, save_path, header='MB99 linelist')
예제 #3
0
def ges2moog(ges_path, save_path):
    GES = pd.read_csv(ges_path, sep='\t')
    GES['diss_energy'] = np.nan
    GES = GES[GES['moog_support'] == 'T']

    GES_moog = GES[[
        'wave_A', 'spectrum_moog_species', 'lower_state_eV', 'loggf', 'waals',
        'diss_energy', 'theoretical_ew'
    ]]
    GES_moog.columns = [
        'wavelength', 'element_index', 'EP', 'loggf', 'C6', 'D0',
        'theoretical_ew'
    ]

    line_data.save_linelist(GES_moog, save_path, header='MB99 linelist')
예제 #4
0
파일: blends.py 프로젝트: sselgueta/pymoog
    def prepare_file(self,
                     model_file=None,
                     model_type='moog',
                     loggf_cut=None,
                     abun_change=None,
                     molecules=None,
                     atmosphere=1,
                     lines=1):
        '''
        Prepare the model, linelist and control files for MOOG.
        Can either provide stellar parameters and wavelengths or provide file names.
        If fine name(s) provided, the files will be copied to working directory for calculation.  
        
        Parameters
        ----------
        model_file : str, optional
            The name of the model file. If not specified will use internal Kurucz model.
             
        model_type : str, optional
            The type of the model file. Default is "moog" (then no conversion of format will be done); can be "moog", "kurucz-atlas9" and "kurucz-atlas12". 
        
        logf_cut : float, optional
            The cut in loggf; if specified will only include the lines with loggf >= loggf_cut.
            
        abun_change : dict of pairs {int:float, ...}
            Abundance change, have to be a dict of pairs of atomic number and [X/Fe] values.
        '''
        private.subprocess.run(['rm', MOOG_run_path + 'batch.par'])
        private.subprocess.run(['rm', MOOG_run_path + 'model.mod'])
        private.subprocess.run(['rm', MOOG_run_path + 'line.list'])
        private.os.system('rm ' + MOOG_run_path + 'MOOG.out*')

        if model_file == None:
            # Model file is not specified, will download Kurucz model according to stellar parameters.
            model.interpolate_model(self.teff,
                                    self.logg,
                                    self.m_h,
                                    abun_change=abun_change,
                                    molecules=molecules)
            self.model_file = 'model.mod'
        else:
            # Model file is specified; record model file name and copy to working directory.
            if model_type == 'moog':
                private.subprocess.run(['cp', model_file, MOOG_run_path],
                                       encoding='UTF-8',
                                       stdout=private.subprocess.PIPE)
                self.model_file = model_file.split('/')[-1]
            elif model_type[:6] == 'kurucz':
                model.KURUCZ_convert(model_path=model_file,
                                     abun_change=abun_change,
                                     model_type=model_type[7:],
                                     molecules=molecules)
                self.model_file = 'model.mod'

        if self.line_list[-5:] != '.list':
            # Linelist file is not specified, use internal line list;
            line_list = line_data.read_linelist(self.line_list,
                                                loggf_cut=loggf_cut)

            # Input EW into the linelist
            line_list = line_list[
                (line_list['wavelength'] >= self.start_wav)
                & (line_list['wavelength'] <= self.end_wav)].reset_index(
                    drop=True)
            line_list.loc[1:, 'wavelength'] = -line_list.loc[1:, 'wavelength']
            line_list['EW'] = private.np.nan
            line_list.loc[0, 'EW'] = self.EW

            line_data.save_linelist(line_list,
                                    MOOG_run_path + 'line.list',
                                    negative=True)
            self.line_list = 'line.list'
        elif self.line_list[-5:] == '.list':
            # Linelist file is specified; record linelist file name and copy to working directory.
            private.subprocess.run(['cp', self.line_list, MOOG_run_path],
                                   encoding='UTF-8',
                                   stdout=private.subprocess.PIPE)
            self.line_list = self.line_list.split('/')[-1]
            # Input EW into the linelist
            line_list = line_data.read_linelist(MOOG_run_path + self.line_list)
            line_list.loc[1:, 'wavelength'] = -line_list.loc[1:, 'wavelength']
            line_list['EW'] = private.np.nan
            line_list.loc[0, 'EW'] = self.EW
            line_data.save_linelist(line_list,
                                    MOOG_run_path + 'line.list',
                                    negative=True)

        # Create parameter file.
        self.create_para_file(self.ele, atmosphere=atmosphere, lines=lines)
예제 #5
0
def plot_contri_func(teff,
                     logg,
                     fe_h,
                     resolution,
                     line_list,
                     line_wav_input=None,
                     line_id=None,
                     target_line_df=None):

    if target_line_df is None and (line_wav_input is None or line_id is None):
        raise ValueError(
            'Please provide target_line_df or both line_wav_input and line_id.'
        )

    if target_line_df is not None:
        wav_start = private.np.min(target_line_df['wavelength']) - 7
        wav_end = private.np.max(target_line_df['wavelength']) + 7
        s = synth.synth(teff,
                        logg,
                        fe_h,
                        wav_start,
                        wav_end,
                        resolution,
                        line_list=line_list)
    else:
        s = synth.synth(teff,
                        logg,
                        fe_h,
                        line_wav_input - 7,
                        line_wav_input + 7,
                        resolution,
                        line_list=line_list)

    # Whole spectra
    s.prepare_file()
    s.run_moog()
    s.read_spectra()
    wav_all, flux_all = s.wav, s.flux

    # Target line excluded
    linelist_all = line_data.read_linelist(MOOG_run_path + 'line.list')
    if target_line_df is not None:
        line_index_all = line_data.find_lines(target_line_df, linelist_all)
    else:
        smooth_width = line_wav_input / resolution
        indices = (private.np.abs(linelist_all['wavelength'] - line_wav_input)
                   <= smooth_width) & (linelist_all['id'] == line_id)
        line_index_all = linelist_all[indices].index

    private.plt.figure(figsize=(14, 5 * len(line_index_all)))

    plot_index = 1
    for line_index in line_index_all:
        linelist_exclude = linelist_all.drop(line_index).reset_index(drop=True)
        line_data.save_linelist(linelist_exclude, MOOG_run_path + 'line.list')
        s.run_moog()
        s.read_spectra()
        wav_exclude, flux_exclude = s.wav, s.flux

        # Target line only
        linelist_target = linelist_all.loc[line_index:line_index].reset_index(
            drop=True)
        line_wavlength = linelist_target.loc[0, 'wavelength']
        line_loggf = linelist_target.loc[0, 'loggf']
        line_EP = linelist_target.loc[0, 'EP']
        s.prepare_file(atmosphere=2, lines=4)
        line_data.save_linelist(linelist_target, MOOG_run_path + 'line.list')
        s.run_moog()
        s.read_spectra()
        wav_target, flux_target = s.wav, s.flux

        # Calculate the EW and blending fraction
        EW = (private.np.sum(1 - flux_all) * 0.02 -
              private.np.sum(1 - flux_exclude) * 0.02) * 1000
        depth = 1 - private.np.min(
            flux_all[private.np.abs(wav_all - line_wavlength) <= 0.01])
        r_blend_depth = (1 - flux_exclude[private.np.argmin(
            private.np.abs(wav_exclude - line_wavlength))]) / (1 - flux_all[
                private.np.argmin(private.np.abs(wav_all - line_wavlength))])

        # Plot the line information
        CF_dict, atmosphere = cal_contri_func(MOOG_run_path + 'MOOG.out1',
                                              line_id=1)
        Ic_sum = private.np.sum(CF_dict['CF_Ic'])
        Dlp_sum = private.np.sum(CF_dict['CF_Dlp'])

        ax = private.plt.subplot(len(line_index_all), 2, plot_index)
        private.plt.plot(wav_all, flux_all, label='all lines included')
        private.plt.plot(wav_exclude,
                         flux_exclude,
                         label='target line excluded')
        private.plt.plot(wav_target, flux_target, label='target line only')
        private.plt.plot(line_wavlength,
                         1,
                         alpha=0,
                         label='EW={:.2f} m$\mathrm{{\AA}}$'.format(EW))
        private.plt.plot(line_wavlength,
                         1,
                         alpha=0,
                         label='$d$={:.2f}'.format(depth))
        private.plt.plot(
            line_wavlength,
            1,
            alpha=0,
            label='$f_\mathrm{{blend,depth}}$={:.2f}'.format(r_blend_depth))
        private.plt.axvline(wav_all[private.np.argmin(
            private.np.abs(wav_all - line_wavlength))],
                            zorder=0,
                            ls='--',
                            c='gray')
        private.plt.xlim(line_wavlength - 5, line_wavlength + 5)
        private.plt.legend()
        private.plt.xlabel(r'Wavelength ($\mathrm{\AA}$)')
        private.plt.ylabel('Normalized flux')
        if target_line_df is not None:
            line_id = linelist_all.loc[line_index, 'id']
        private.plt.title(
            'Teff={:.0f}, logg={:.2f}, [Fe/H]={:.2f}, line_id={:.1f}, EP={:.2f}, loggf={:.3f}'
            .format(teff, logg, fe_h, line_id, line_EP, line_loggf))
        plot_index += 1

        ax = private.plt.subplot(len(line_index_all), 2, plot_index)

        private.plt.plot(private.np.log10(CF_dict['tau_ref']),
                         CF_dict['CF_Dlp'] / max(CF_dict['CF_Ic']),
                         label='CF: $D_l^p$')
        private.plt.plot(private.np.log10(CF_dict['tau_ref']),
                         CF_dict['CF_Ilp'] / max(CF_dict['CF_Ic']),
                         label='CF: $I_l^p$')
        private.plt.plot(private.np.log10(CF_dict['tau_ref']),
                         CF_dict['CF_Dl'] / max(CF_dict['CF_Ic']),
                         label='CF: $D_l$')
        if Dlp_sum / Ic_sum < 0.1:
            private.plt.ylim(private.plt.ylim())
        private.plt.plot(private.np.log10(CF_dict['tau_ref']),
                         CF_dict['CF_Ic'] / max(CF_dict['CF_Ic']),
                         c='gray',
                         label='CF: $I_c$')
        private.plt.xlabel(r'$\log{\tau_\mathrm{ref}}$')
        private.plt.ylabel('CF: max($I_c$) normalized as 1')
        private.plt.title('Contribution function')

        ax2 = private.plt.twinx()
        private.plt.plot(private.np.log10(atmosphere['tauref']),
                         atmosphere['T'],
                         ls='--',
                         c='gray',
                         zorder=0,
                         label='T (K)')
        private.plt.ylabel('T (K)')
        lines, labels = ax.get_legend_handles_labels()
        lines2, labels2 = ax2.get_legend_handles_labels()
        ax2.legend(lines + lines2, labels + labels2)

        plot_index += 1
        private.plt.tight_layout()
예제 #6
0
def cal_blending_ratio(teff,
                       logg,
                       fe_h,
                       resolution,
                       line_list,
                       wav_range,
                       weedout=True):

    wav_start = wav_range[0] - 7
    wav_end = wav_range[1] + 7
    s = synth.synth(teff,
                    logg,
                    fe_h,
                    wav_start,
                    wav_end,
                    resolution,
                    line_list=line_list,
                    weedout=weedout)

    # Whole spectra
    s.prepare_file()
    s.run_moog()
    s.read_spectra(unlock=False)
    s.weedout = False
    wav_all, flux_all = s.wav, s.flux

    # Target line excluded
    linelist_all = line_data.read_linelist(s.rundir_path + line_list)
    indices = (linelist_all['wavelength'] >=
               wav_range[0]) & (linelist_all['wavelength'] <= wav_range[1])
    linelist_out = linelist_all[indices].reset_index(drop=True)
    line_index_all = linelist_all[indices].index

    r_blend_depth = []
    r_blend_EW = []
    depth = []
    for line_index in line_index_all:

        linelist_exclude = linelist_all.drop(line_index).reset_index(drop=True)
        line_data.save_linelist(linelist_exclude, s.rundir_path + line_list)
        s.run_moog()
        s.read_spectra()
        wav_exclude, flux_exclude = s.wav, s.flux

        # Calculate the EW and blending fraction
        linelist_target = linelist_all.loc[line_index:line_index].reset_index(
            drop=True)
        line_wavlength = linelist_target.loc[0, 'wavelength']
        EW = (private.np.sum(1 - flux_all) * 0.02 -
              private.np.sum(1 - flux_exclude) * 0.02) * 1000
        if flux_exclude[private.np.argmin(
                private.np.abs(wav_exclude - line_wavlength))] - flux_all[
                    private.np.argmin(
                        private.np.abs(wav_exclude - line_wavlength))] < 1e-5:
            r_blend_depth.append(1.0)
        else:
            r_blend_depth.append(
                (1 - flux_exclude[private.np.argmin(
                    private.np.abs(wav_exclude - line_wavlength))]) /
                (1 - flux_all[private.np.argmin(
                    private.np.abs(wav_all - line_wavlength))]))

        EW_indices = private.np.abs(
            wav_exclude - line_wavlength) < line_wavlength / resolution * 3
        r_blend_EW.append(
            private.np.sum(1 - flux_exclude[EW_indices]) /
            private.np.sum(1 - flux_all[EW_indices]))
        depth.append(1 - private.np.min(flux_all[
            private.np.abs(wav_all - line_wavlength) <= 0.03]))
    linelist_out['depth'] = depth
    linelist_out['r_blend_depth'] = r_blend_depth
    linelist_out['r_blend_EW'] = r_blend_EW

    return linelist_out
예제 #7
0
def vald2moog_format(init_linelist_name, out_linelist_name, loggf_cut=None):
    '''
    Transform VALD linelist download from VALD website into MOOG format.
    
    Parameters
    ----------
    init_linelist_name : str
        The VALD format line list.
    out_linelist_name : str
        Output line list name
    head : int, optional
        If specified then only save the first `head` number of lines.
    loggf_cut : float, optional
        Cut on loggf (only save for the lines with loggf > loggf_cut)
    '''
    # Find the footer index of VALD line pair
    with open(init_linelist_name) as file:
        contents = file.readlines()
        try:
            footer_index = len(contents) - contents.index(
                '* oscillator strengths were scaled by the solar isotopic ratios.\n'
            )
        except ValueError:
            footer_index = 0

    # Delete all the '.
    file = open(init_linelist_name)
    file_content = file.readlines()
    for i in range(len(file_content)):
        file_content[i] = file_content[i].replace("'", '')
    file.close()
    file = open(init_linelist_name, 'w')
    file.writelines(file_content)
    file.close()

    # subprocess.run(['sed', "s/'//g", init_linelist_name, '>', 'temp'])
    # subprocess.run(['mv', "temp", init_linelist_name])
    vald_init = pd.read_csv(init_linelist_name,
                            skiprows=2,
                            skipfooter=footer_index,
                            usecols=range(9),
                            engine='python',
                            names=[
                                'element', 'wavelength', 'EP', 'loggf',
                                'rad_damp', 'Stark_damp', 'Walls_damp',
                                'Lande_factor', 'Comment'
                            ])

    if loggf_cut != None:
        vald_init = vald_init[vald_init['loggf'] >= loggf_cut]
    vald_init['element_all'] = vald_init[['element', 'Comment'
                                          ]].apply(lambda x: ', '.join(x),
                                                   axis=1)
    vald_init['element_index'] = vald_init['element_all'].map(element2index)
    vald_init['diss_energy'] = vald_init['element_index'].map(get_diss_energy)

    vald_out = vald_init[[
        'wavelength', 'element_index', 'EP', 'loggf', 'Walls_damp',
        'diss_energy'
    ]]
    vald_out.columns = [
        'wavelength', 'element_index', 'EP', 'loggf', 'C6', 'diss_energy'
    ]
    vald_out = vald_out.astype(np.float64)

    # Remove triple or higher ionized lines; MOOG cannot do this.
    vald_out = vald_out[
        np.around(np.mod(vald_out['element_index'], 1), decimals=1) < 0.3]

    line_data.save_linelist(vald_out, out_linelist_name)